Appearance
Multi-tenancy
Isolamento de dados por empresa.
Modelo
User ◄───► BorrowerCompany ◄───► Company
◄───► ProviderCompany ◄───►
◄───► UserCompany ◄───►
│
│ (role)
│
▼
Todos recursos
filtrados por
companyIdRoles de Empresa
| Role | Descrição |
|---|---|
borrower | Tomador de serviços |
provider | Prestador de serviços |
user | Funcionário da empresa |
Implementação
Header x-company-id
Todas as requisições que precisam de contexto de empresa devem enviar:
x-company-id: <uuid-da-empresa>Decorator CurrentCompany
typescript
@CurrentCompany() company: CurrentCompanyData
interface CurrentCompanyData {
id: string;
name: string;
document?: string;
role: string;
}Repository Pattern
Sempre filtrar por companyId:
typescript
async findAll(companyId: string) {
return this.prisma.contract.findMany({
where: { companyId, deletedAt: null }
});
}Regras
- Todo recurso pertence a uma empresa
- Usuário só acessa recursos de empresas que ele pertence
- Queries sempre filtram por
companyId - O guard
CompanyGuardvalida acesso automaticamente
TenantUrlService (links de e-mail)
src/common/services/tenant-url.service.ts centraliza a montagem do endereço base de um link (subdomínio do tenant ou aplicação principal). Nenhum e-mail deve concatenar CLIENT_URL à mão: sempre resolver por este serviço.
| Método | Como resolve |
|---|---|
resolveByCompanyId(companyId) | Do slug provisionado no domínio da empresa (companyDomain) monta <slug>.contrasync.com. Forma preferida nos e-mails transacionais. |
resolveByOrigin(origin) | Usa o subdomínio do header Origin da requisição para manter a pessoa no mesmo ambiente. |
resolveBySlug(slug) | Monta a URL quando o slug já é conhecido. |
Fallback: sem tenant provisionado, retorna a aplicação principal (CLIENT_URL), garantindo link válido.
Usam o subdomínio do tenant: recuperação de senha, convite/primeiro acesso, desbloqueio de conta e o link de portfólio do import legado.
Ficam no domínio da aplicação (decisão): os portais públicos de contraparte (assinatura /public/signing, revisão /public/review, negociação /public/negotiation, onboarding e publicação de contrato). São autenticados por token, sem marca de subdomínio, para preservar a fronteira entre a sessão pública e a sessão do tenant (SSO). Ver business/emails-tenant-links.md.
Documento atualizado em Julho 2026