Skip to content

Multi-tenancy

Isolamento de dados por empresa.


Modelo

User ◄───► BorrowerCompany ◄───► Company
     ◄───► ProviderCompany ◄───►
     ◄───► UserCompany    ◄───►

              │ (role)


         Todos recursos
         filtrados por
           companyId

Roles de Empresa

RoleDescrição
borrowerTomador de serviços
providerPrestador de serviços
userFuncioná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

  1. Todo recurso pertence a uma empresa
  2. Usuário só acessa recursos de empresas que ele pertence
  3. Queries sempre filtram por companyId
  4. O guard CompanyGuard valida acesso automaticamente

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étodoComo 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