ConnectCond — Arquitetura RBAC Enterprise

ConnectCond — Arquitetura Oficial RBAC Enterprise


CampoValor
PlataformaConnectCond — Gestão de Condomínios, Cotações e Prestadores
DocumentoArquitetura Oficial RBAC Enterprise
Versão1.0.0
Data06 de Agosto de 2026
AmbienteProdução (Base44 BaaS)
ResponsávelEquipe de Engenharia ConnectCond
Status✅ Homologado

Sumário

  1. Objetivo da Arquitetura
  2. Visão Geral da Arquitetura
  3. Estrutura das Entidades
  4. Relacionamento entre Entidades
  5. Organização do Banco de Dados
  6. Matriz Oficial de Roles
  7. Matriz Mestre de Permissões
  8. Segmentação por Perfil
  9. Fluxo de Resolução das Permissões
  10. Fluxo de Convites
  11. Landing Page
  12. Tela "Convidar Colaborador"
  13. Regras de Governança
  14. Segurança
  15. Compatibilidade
  16. Fluxo Completo da Arquitetura
  17. Banco de Dados
  18. Exemplos Práticos
  19. Histórico da Arquitetura
  20. Conclusão

1. Objetivo da Arquitetura

Por que foi criada

A ConnectCond opera como uma plataforma SaaS multi-tenant onde Administradoras, Condomínios, Prestadores de Serviço e Fornecedores coexistem em um mesmo ambiente. Cada perfil de organização possui necessidades de acesso radicalmente diferentes, e dentro de cada organização, colaboradores precisam de níveis distintos de controle.

A arquitetura RBAC Enterprise foi criada para resolver três problemas fundamentais:

  1. Controle granular de acesso — Nem todo colaborador precisa de todas as permissões. Um síndico precisa aprovar cotações; um membro do conselho precisa apenas visualizar.
  2. Separação entre função profissional e perfil de acesso — Um "Síndico" (função profissional) pode ter perfil de acesso "Gestor" ou "Consulta" — são conceitos independentes.
  3. Governança centralizada — Apenas o Proprietário da organização pode personalizar permissões, garantindo que nenhum colaborador — mesmo com cargo de gestão — escalone privilégios além do autorizado.

Princípios de segurança adotados

PrincípioImplementação
Princípio do Menor PrivilégioTodo colaborador recebe o conjunto mínimo de permissões necessário para sua função. Overrides só adicionam permissões específicas, nunca concedem acesso irrestrito.
Segregação de FunçõesQuem convida colaboradores (team:invite) não é necessariamente quem pode alterar permissões (settings:edit). Apenas o Proprietário pode customizar permissões.
Auditoria CompletaToda alteração de permissão é registrada no AuditLog com usuário, ação, entidade, timestamp e metadados.
Resolução DeterminísticaAs permissões finais são sempre calculadas pela mesma fórmula: base_permissions + ADD - REMOVE. Não há ambiguidade.
Compatibilidade RLSA arquitetura opera em conjunto com o Row-Level Security nativo da Base44, sem conflito.

Benefícios para a ConnectCond

  • Onboarding seguro: Novos colaboradores recevem exatamente o acesso necessário, nem mais nem menos.
  • Flexibilidade: O Proprietário pode ajustar permissões individualmente sem criar novos Perfis de Acesso.
  • Conformidade: Auditoria completa para regulamentações e revisões internas.
  • Escalabilidade: A mesma arquitetura atende desde um condomínio com 2 colaboradores até uma administradora com centenas.

2. Visão Geral da Arquitetura

Diagrama de Fluxo de Resolução

┌─────────────────────────────────────────────────────────────────┐
│                    ORGANIZAÇÃO (Tenant)                          │
│                                                                  │
│  ┌──────────────────┐                                           │
│  │ Perfil da Org    │  administration | condominium |             │
│  │ (organization_   │  provider | supplier                        │
│  │  type)           │                                             │
│  └────────┬─────────┘                                            │
│           │                                                      │
│           ▼                                                      │
│  ┌──────────────────┐                                           │
│  │ Role              │  Proprietário | Gestor |                  │
│  │ (Perfil de        │  Colaborador | Consulta                   │
│  │  Acesso)          │                                             │
│  │                   │  base_permissions = [                       │
│  │                   │    "quotations:create",                    │
│  │                   │    "proposals:approve",                   │
│  │                   │    ...                                     │
│  │                   │  ]                                         │
│  └────────┬─────────┘                                            │
│           │                                                      │
│           ▼                                                      │
│  ┌──────────────────┐                                           │
│  │ Permissões Base  │  Conjunto de permissões atômicas           │
│  │ (base_perms)     │  definidas pelo Perfil de Acesso           │
│  └────────┬─────────┘                                            │
│           │                                                      │
│           ▼                                                      │
│  ┌──────────────────┐                                           │
│  │ MemberPermission │  Overrides personalizados pelo             │
│  │ (Overrides)      │  Proprietário:                             │
│  │                   │                                            │
│  │                   │  ADD    → adiciona permissão extra         │
│  │                   │  REMOVE → subtrai permissão da base        │
│  └────────┬─────────┘                                            │
│           │                                                      │
│           ▼                                                      │
│  ┌──────────────────┐                                           │
│  │ PERMISSÕES       │  FÓRMULA OFICIAL:                          │
│  │ FINAIS            │                                            │
│  │                   │  base_permissions                          │
│  │                   │    + ADD(MemberPermission)                 │
│  │                   │    - REMOVE(MemberPermission)              │
│  │                   │    = Permissões Finais                      │
│  └────────┬─────────┘                                            │
│           │                                                      │
│           ▼                                                      │
│  ┌──────────────────┐                                           │
│  │ APLICAÇÃO        │  Frontend (usePermissions.can())            │
│  │                   │  Backend (orgContextResolver.hasPermission)│
│  └──────────────────┘                                           │
└─────────────────────────────────────────────────────────────────┘

Explicação em linguagem simples

Imagine que cada organização na ConnectCond é como um prédio de escritórios:

  1. Perfil da Organização define que tipo de empresa é (Administradora, Condomínio, Prestador ou Fornecedor) — como o tipo de negócio do prédio.
  2. Perfil de Acesso (Role) é como o cargo do funcionário: Proprietário (dono do escritório), Gestor (gerente), Colaborador (funcionário ativo) ou Consulta (visitante com acesso só para leitura).
  3. Permissões Base são as chaves que cada cargo recebe por padrão — o Proprietário tem a chave-mestra, o Consulta só tem chaves de visualização.
  4. MemberPermission (Overrides) são chaves extras que o Proprietário entrega ou retirada individualmente — como dar uma chave específica para um Colaborador acessar a sala de reuniões, ou retirar a chave do cofre de um Gestor.
  5. Permissões Finais são todas as chaves que a pessoa realmente possui no final — o conjunto que de fato libera ou bloqueia cada porta do sistema.

3. Estrutura das Entidades

3.1 Role (Perfil de Acesso)

Finalidade: Define os 4 Perfis de Acesso oficiais da plataforma, cada um com um conjunto base de permissões atômicas. Existem 16 registros no total (4 Perfis × 4 tipos de organização).

Relacionamento: Cada Role pertence a um organization_type e é referenciada por OrganizationMember.role_id.

CampoTipoObrigatórioFinalidadeExemplo
namestringSimNome do Perfil de Acesso"Proprietário"
organization_typeenumSimTipo de organização ao qual pertence"condominium"
base_permissionsarray<string>NãoLista de chaves de permissão atômicas da Role base["quotations:create", "proposals:approve"]
descriptionstringNãoDescrição legível do Perfil e responsabilidades"Administrador de segurança..."
is_defaultbooleanNãoIndica se é o Perfil padrão para novos convitestrue (Gestor)
is_systembooleanNãoPerfis de sistema não podem ser excluídostrue (Proprietário)

Campo de compatibilidade: permissions (array) — mantido em sincronia com base_permissions para código legado que ainda referencia role.permissions. Ambos são atualizados juntos pelo seedPermissions.


3.2 Permission (Permissão Atômica)

Finalidade: Catálogo mestre de todas as permissões atômicas da plataforma, organizadas por módulo e segmentadas por tipo de organização.

Relacionamento: Referenciada por Role.base_permissions (por chave) e por MemberPermission.permission_key.

CampoTipoObrigatórioFinalidadeExemplo
keystringSimChave única no formato modulo:acao"quotations:create"
moduleenumSimMódulo da plataforma"quotations"
descriptionstringNãoDescrição legível"Criar cotações"
organization_typesarray<enum>NãoPerfis de organização que têm acesso["administration", "condominium"]

Módulos disponíveis: dashboard, team, solicitations, quotations, proposals, orders, contracts, documents, finance, chat, ai, subscription, settings, integrations, calendar, reports, erp, whatsapp, reviews, condominiums, suppliers, providers, notifications.


3.3 MemberPermission (Override Personalizado)

Finalidade: Armazena as personalizações individuais de permissão aplicadas pelo Proprietário a um colaborador específico, além (ou aquém) do que seu Perfil de Acesso define.

Relacionamento: Pertence a um OrganizationMember (via member_id) e a uma organization_id.

CampoTipoObrigatórioFinalidadeExemplo
member_idstringSimID do OrganizationMember ao qual se aplica"abc-123"
organization_idstringSimID da organização (para RLS multi-tenant)"cond-456"
permission_keystringSimChave da permissão"quotations:approve"
operationenumSimADD (adiciona) ou REMOVE (subtrai)"ADD"
granted_bystringNãoUUID do Proprietário que concedeu/removeu"user-789"
granted_atdate-timeNãoData/hora da alteração"2026-08-06T14:30:00Z"

3.4 OrganizationMember (Vínculo Colaborador ↔ Organização)

Finalidade: Entidade central que vincula um usuário autenticado a uma organização, definindo seu Perfil de Acesso e status dentro daquela organização.

Relacionamento: Referencia Role (via role_id e role), User (via user_id), e é pai de MemberPermission.

CampoTipoObrigatórioFinalidadeExemplo
user_idstringSimUUID do usuário (User.id)"usr-001"
user_emailstringNãoE-mail do usuário (identificação/visualização)"joao@email.com"
full_namestringNãoNome completo do colaborador"João Silva"
phonestringNãoTelefone do colaborador"+5511999999999"
positionstringNãoCargo/função descritivo"Comprador"
professional_functionstringNãoFunção profissional (informativa — sem efeito em autorização)"Síndico"
departmentenumNãoDepartamento (aplicável à equipe interna ConnectCond)"comercial"
organization_idstringSimID da organização"cond-456"
organization_typeenumSimTipo da organização vinculada"condominium"
rolestringNãoNome do Perfil de Acesso (compatibilidade RLS)"Proprietário"
role_idstringNãoUUID da Role (fonte oficial da verdade)"role-abc"
statusenumNãoStatus do vínculo"active"
invited_bystringNãoUUID de quem enviou o convite"usr-admin"
invited_by_namestringNãoNome de quem enviou o convite"Maria Souza"
invited_atdate-timeNãoData/hora do convite"2026-08-01T10:00:00Z"
accepted_atdate-timeNãoData/hora de aceitação"2026-08-02T14:00:00Z"
last_accessdate-timeNãoÚltimo acesso à organização"2026-08-06T09:00:00Z"

Estratégia Dual-Field: role (string) e role_id (UUID) são mantidos em sincronia automática. role_id é a fonte oficial da verdade; role (string) é mantido para compatibilidade com as regras RLS existentes que comparam por nome.

professional_function vs role: A função profissional (professional_function) é estritamente informativa — exibida na UI, nunca usada em autorização ou RLS. O Perfil de Acesso (role/role_id) é o que determina permissões.


3.5 AuditLog (Trilha de Auditoria)

Finalidade: Registra toda ação relevante executada no sistema, com foco em alterações de permissão, convites e mudanças de cargo.

Relacionamento: Referencia User (via user_id e user_email) e qualquer entidade afetada (via entity_name + entity_id).

CampoTipoObrigatórioFinalidadeExemplo
user_emailstringSimE-mail do usuário que executou a ação"maria@email.com"
user_idstringNãoID do usuário"usr-001"
actionenumSimTipo de ação executada"create"
entity_namestringNãoNome da entidade afetada"MemberPermission"
entity_idstringNãoID do registro afetado"mp-789"
descriptionstringNãoDescrição legível da ação"Permissão quotations:approve (ADD) definida para João Silva."
ip_addressstringNãoEndereço IP de origem"200.150.1.1"
metadataobjectNãoDados adicionais estruturados{ permission_key, operation, member_id }

Valores de action: create, update, delete, login, logout, export, view, approve, reject.

RLS do AuditLog: Apenas Super Admins (role: "admin") podem ler, atualizar ou excluir registros de auditoria. A criação é aberta para que funções de backend possam registrar eventos.


4. Relacionamento entre Entidades

Diagrama de Relacionamento (DER)

    ┌──────────────────┐
    │      Role        │
    │──────────────────│
    │ id               │
    │ name             │
    │ organization_type│
    │ base_permissions │
    │ is_system        │
    │ is_default       │
    └────────┬─────────┘
             │
             │ role_id (UUID)
             │ role (string, compatibilidade)
             ▼
    ┌──────────────────┐         ┌──────────────────────┐
    │ OrganizationMember│─────────│ MemberPermission     │
    │──────────────────│  1 : N  │──────────────────────│
    │ id               │────────▶│ id                   │
    │ user_id          │         │ member_id ───────────┘
    │ organization_id  │         │ organization_id
    │ organization_type│         │ permission_key
    │ role             │         │ operation (ADD/REMOVE)
    │ role_id          │         │ granted_by
    │ status           │         │ granted_at
    │ professional_    │         └──────────────────────┘
    │   function       │                  │
    │ invited_by       │                  │ permission_key
    │ accepted_at      │                  │ (referência por chave)
    └────────┬─────────┘                  ▼
             │                    ┌──────────────────────┐
             │ user_id            │ Permission           │
             │ (UUID)             │──────────────────────│
             ▼                    │ id                   │
    ┌──────────────────┐         │ key (único)         │
    │ User (Base44)    │         │ module              │
    │──────────────────│         │ description          │
    │ id               │         │ organization_types   │
    │ email             │         └──────────────────────┘
    │ role (platform)  │
    │ organization_ids │
    └──────────────────┘
             │
             │ Toda ação relevante
             ▼
    ┌──────────────────┐
    │ AuditLog         │
    │──────────────────│
    │ id               │
    │ user_id          │
    │ user_email       │
    │ action           │
    │ entity_name      │
    │ entity_id        │
    │ description      │
    │ metadata         │
    └──────────────────┘

Explicação dos Relacionamentos

RelacionamentoCardinalidadeDescrição
Role → OrganizationMember1 : NUma Role é referenciada por múltiplos OrganizationMembers. A referência é dupla: role_id (UUID, fonte oficial) + role (string, compatibilidade RLS).
OrganizationMember → MemberPermission1 : NUm colaborador pode ter múltiplos overrides de permissão. Cada override é uma operação atômica (uma chave + uma operação).
MemberPermission → PermissionN : 1 (por chave)MemberPermission referencia Permission por permission_key (não por ID). A validade da chave é garantida pelo catálogo.
User → OrganizationMember1 : NUm usuário pode pertencer a múltiplas organizações (multi-tenant). User.organization_ids é um cache sincronizado com OrganizationMember.
OrganizationMember → AuditLog1 : N (indireto)Toda alteração em OrganizationMember ou MemberPermission gera um registro no AuditLog.

5. Organização do Banco de Dados

Onde cada informação fica armazenada

┌─────────────────────────────────────────────────────────────────┐
│                    BANCO DE DADOS BASE44                         │
│                                                                  │
│  ┌─────────────────────┐                                        │
│  │ Tabela: Role        │  → Armazena os 16 Perfis de Acesso     │
│  │                      │    (4 roles × 4 org_types)             │
│  │  • base_permissions  │    e suas permissões base              │
│  └─────────────────────┘                                        │
│                                                                  │
│  ┌─────────────────────┐                                        │
│  │ Tabela: Permission  │  → Armazena o catálogo de 52           │
│  │                      │    permissões atômicas, segmentadas    │
│  │  • key (único)       │    por organization_types              │
│  │  • organization_types│                                       │
│  └─────────────────────┘                                        │
│                                                                  │
│  ┌─────────────────────┐                                        │
│  │ Tabela:             │  → Armazena os overrides               │
│  │  MemberPermission   │    personalizados (ADD/REMOVE)          │
│  │                      │    aplicados a cada colaborador        │
│  │  • member_id         │                                       │
│  │  • operation         │                                       │
│  └─────────────────────┘                                        │
│                                                                  │
│  ┌─────────────────────┐                                        │
│  │ Tabela:             │  → Armazena o VÍNCULO do usuário       │
│  │  OrganizationMember │    com cada organização, incluindo:    │
│  │                      │                                       │
│  │  • role (string)     │  → Compatibilidade RLS                 │
│  │  • role_id (UUID)    │  → Fonte oficial da verdade            │
│  │  • professional_     │  → Informativo (sem autorização)       │
│  │    function          │                                       │
│  │  • status            │  → pending | active | blocked          │
│  └─────────────────────┘                                        │
│                                                                  │
│  ┌─────────────────────┐                                        │
│  │ Tabela: AuditLog    │  → Armazena a trilha completa de       │
│  │                      │    auditoria de todas as ações         │
│  │  • action            │    relevantes (permissões, convites)   │
│  │  • entity_name       │                                       │
│  │  • metadata          │                                       │
│  └─────────────────────┘                                        │
│                                                                  │
│  ┌─────────────────────┐                                        │
│  │ Tabela: User        │  → Identidade autenticada (Base44)     │
│  │  (sistema)          │                                       │
│  │  • organization_ids  │  → Cache sincronizado (RLS support)   │
│  │  • role (platform)   │  → admin | condominio | prestador...  │
│  └─────────────────────┘                                        │
└─────────────────────────────────────────────────────────────────┘

Campos de Compatibilidade

Os seguintes campos existem apenas para compatibilidade e NÃO são a fonte da verdade:

CampoEntidadePor que existeFonte oficial
permissionsRoleCódigo legado referencia role.permissionsbase_permissions
role (string)OrganizationMemberRegras RLS comparam por nomerole_id (UUID)
user_emailOrganizationMemberExibição e fallbackuser_id (UUID)

Regra arquitetural: Toda nova implementação deve usar a fonte oficial. Os campos de compatibilidade são mantidos em sincronia automática e nunca devem ser editados diretamente.


6. Matriz Oficial de Roles

Os 4 Perfis de Acesso Oficiais

Perfil de AcessoResponsabilidadeQuem pode criarQuem pode alterar permissõesis_systemis_default
ProprietárioControle total da organização. Único que pode personalizar permissões de outros colaboradores. Acesso a configurações de segurança, assinatura e integrações.Super Admin (plataforma) ou auto-criado no registro da organização✅ Sim (único)truefalse
GestorAdministrador operacional. Gerencia equipe e operações do dia a dia. Sem acesso a configurações de segurança (assinatura, integrações, ERP, WhatsApp).Proprietário ou Super Admin❌ Nãofalsetrue
ColaboradorUsuário operacional. Acesso a criação e edição de registros operacionais (cotações, propostas, documentos). Sem permissões de aprovação, exclusão ou gestão.Proprietário ou Gestor❌ Nãofalsefalse
ConsultaSomente leitura. Visualiza informações sem permissão de alteração. Ideal para conselheiros, auditores e consultores.Proprietário ou Gestor❌ Nãofalsefalse

Permissões de Segurança Exclusivas do Proprietário

As seguintes permissões são sempre excluídas dos Perfis Gestor, Colaborador e Consulta (apenas Proprietário as possui por padrão):

PermissãoMóduloDescrição
subscription:manageAssinaturaGerenciar assinatura e faturamento
settings:editConfiguraçõesEditar configurações da organização
integrations:configureIntegraçõesConfigurar integrações
erp:syncERPSincronizar dados com ERP
whatsapp:configureWhatsAppConfigurar WhatsApp

Nota: O Proprietário pode conceder essas permissões individualmente via MemberPermission (ADD), mas por padrão apenas o Proprietário as possui.


7. Matriz Mestre de Permissões

Catálogo Completo (52 Permissões Atômicas)

Módulo: Dashboard

ChaveDescriçãoPerfis que possuem
dashboard:viewVisualizar painel da organizaçãoProprietário, Gestor, Colaborador, Consulta

Módulo: Equipe (Team)

ChaveDescriçãoPerfis que possuem
team:viewVisualizar membros da equipeProprietário, Gestor, Colaborador, Consulta
team:inviteConvidar novos colaboradoresProprietário, Gestor, Colaborador
team:manageGerenciar cargos e promover membrosProprietário, Gestor
team:removeRemover membros da organizaçãoProprietário, Gestor

Módulo: Solicitações (Solicitations)

ChaveDescriçãoPerfis que possuem
solicitations:viewVisualizar solicitaçõesProprietário, Gestor, Colaborador, Consulta
solicitations:createCriar solicitaçõesProprietário, Gestor, Colaborador
solicitations:editEditar solicitaçõesProprietário, Gestor, Colaborador
solicitations:cancelCancelar solicitaçõesProprietário, Gestor

Módulo: Cotações (Quotations)

ChaveDescriçãoPerfis que possuem
quotations:viewVisualizar cotaçõesProprietário, Gestor, Colaborador, Consulta
quotations:createCriar cotaçõesProprietário, Gestor, Colaborador
quotations:editEditar cotaçõesProprietário, Gestor, Colaborador
quotations:approveAprovar propostas de cotaçãoProprietário, Gestor
quotations:cancelCancelar cotaçõesProprietário, Gestor

Módulo: Propostas (Proposals)

ChaveDescriçãoPerfis que possuem
proposals:viewVisualizar propostasProprietário, Gestor, Colaborador, Consulta
proposals:createEnviar propostasProprietário, Gestor, Colaborador
proposals:approveAprovar/selecionar propostasProprietário, Gestor
proposals:rejectRejeitar propostasProprietário, Gestor

Módulo: Pedidos (Orders)

ChaveDescriçãoPerfis que possuem
orders:viewVisualizar pedidosProprietário, Gestor, Colaborador, Consulta
orders:createCriar pedidosProprietário, Gestor, Colaborador
orders:editEditar pedidosProprietário, Gestor, Colaborador
orders:approveAprovar pedidosProprietário, Gestor

Módulo: Contratos (Contracts)

ChaveDescriçãoPerfis que possuem
contracts:viewVisualizar contratosProprietário, Gestor, Colaborador, Consulta
contracts:signAssinar contratosProprietário, Gestor
contracts:manageEnviar e gerenciar contratosProprietário, Gestor, Colaborador

Módulo: Documentos (Documents)

ChaveDescriçãoPerfis que possuem
documents:viewVisualizar documentosProprietário, Gestor, Colaborador, Consulta
documents:uploadEnviar documentosProprietário, Gestor, Colaborador
documents:deleteExcluir documentosProprietário, Gestor

Módulo: Financeiro (Finance)

ChaveDescriçãoPerfis que possuem
finance:viewVisualizar pagamentos e faturamentoProprietário, Gestor, Colaborador, Consulta
finance:createRegistrar pagamentos e notas fiscaisProprietário, Gestor, Colaborador
finance:approveAprovar/confirmar pagamentosProprietário, Gestor

Módulo: Chat

ChaveDescriçãoPerfis que possuem
chat:viewVisualizar conversas e mensagensProprietário, Gestor, Colaborador, Consulta
chat:sendEnviar mensagens em conversasProprietário, Gestor, Colaborador

Módulo: IA

ChaveDescriçãoPerfis que possuem
ai:viewVisualizar agentes e assistentes de IAProprietário, Gestor, Colaborador, Consulta
ai:useInteragir com agentes e assistentes de IAProprietário, Gestor, Colaborador

Módulo: Assinatura (Subscription)

ChaveDescriçãoPerfis que possuem
subscription:viewVisualizar assinatura e planoProprietário, Gestor, Colaborador, Consulta
subscription:manageGerenciar assinatura e faturamentoProprietário (exclusivo)

Módulo: Configurações (Settings)

ChaveDescriçãoPerfis que possuem
settings:viewVisualizar configurações da organizaçãoProprietário, Gestor, Colaborador, Consulta
settings:editEditar configurações da organizaçãoProprietário (exclusivo)

Módulo: Integrações (Integrations)

ChaveDescriçãoPerfis que possuem
integrations:viewVisualizar integraçõesProprietário, Gestor, Colaborador, Consulta
integrations:configureConfigurar integraçõesProprietário (exclusivo)

Módulo: Agenda (Calendar)

ChaveDescriçãoPerfis que possuem
calendar:viewVisualizar agendaProprietário, Gestor, Colaborador, Consulta
calendar:manageGerenciar agendaProprietário, Gestor

Módulo: Relatórios (Reports)

ChaveDescriçãoPerfis que possuem
reports:viewVisualizar relatóriosProprietário, Gestor, Colaborador, Consulta
reports:exportExportar relatóriosProprietário, Gestor

Módulo: ERP

ChaveDescriçãoPerfis que possuem
erp:viewVisualizar integração ERPProprietário, Gestor, Colaborador, Consulta
erp:syncSincronizar dados com ERPProprietário (exclusivo)

Módulo: WhatsApp

ChaveDescriçãoPerfis que possuem
whatsapp:viewVisualizar configurações do WhatsAppProprietário, Gestor, Colaborador, Consulta
whatsapp:configureConfigurar WhatsAppProprietário (exclusivo)

Módulo: Avaliações (Reviews)

ChaveDescriçãoPerfis que possuem
reviews:createAvaliar prestadores/fornecedoresProprietário, Gestor, Colaborador

Módulo: Condomínios (Administration only)

ChaveDescriçãoPerfis que possuem
condominiums:viewVisualizar condomínios gerenciadosProprietário, Gestor, Colaborador, Consulta
condominiums:manageGerenciar condomíniosProprietário, Gestor

8. Segmentação por Perfil

Cada permissão do catálogo é segmentada por tipo de organização. Abaixo, os módulos disponíveis para cada Perfil da Organização:

Administradora

┌──────────────────────────────────────────┐
│           ADMINISTRADORA                  │
│                                           │
│  Módulos disponíveis:                     │
│  ├── dashboard        (view)              │
│  ├── team             (view, invite,      │
│  │                     manage, remove)     │
│  ├── solicitations    (view, create,      │
│  │                     edit, cancel)       │
│  ├── quotations       (view, create,      │
│  │                     edit, approve,      │
│  │                     cancel)             │
│  ├── proposals        (view, approve,      │
│  │                     reject)             │
│  ├── contracts        (view, sign)         │
│  ├── documents        (view, upload,       │
│  │                     delete)             │
│  ├── finance          (view, create,       │
│  │                     approve)            │
│  ├── chat             (view, send)         │
│  ├── ai               (view, use)          │
│  ├── subscription     (view, manage*)      │
│  ├── settings         (view, edit*)        │
│  ├── integrations     (view, configure*)   │
│  ├── calendar         (view, manage)       │
│  ├── reports          (view, export)       │
│  ├── erp              (view, sync*)        │
│  ├── whatsapp         (view, configure*)   │
│  ├── reviews          (create)             │
│  └── condominiums     (view, manage)       │
│                                           │
│  * Apenas Proprietário                    │
└──────────────────────────────────────────┘

Condomínio

┌──────────────────────────────────────────┐
│             CONDOMÍNIO                    │
│                                           │
│  Módulos disponíveis:                     │
│  ├── dashboard        (view)              │
│  ├── team             (view, invite,      │
│  │                     manage, remove)     │
│  ├── solicitations    (view, create,      │
│  │                     edit, cancel)       │
│  ├── quotations       (view, create,      │
│  │                     edit, approve,      │
│  │                     cancel)             │
│  ├── proposals        (view, approve,      │
│  │                     reject)             │
│  ├── contracts        (view, sign)         │
│  ├── documents        (view, upload,       │
│  │                     delete)             │
│  ├── finance          (view, create,       │
│  │                     approve)            │
│  ├── chat             (view, send)         │
│  ├── ai               (view, use)          │
│  ├── subscription     (view, manage*)      │
│  ├── settings         (view, edit*)        │
│  ├── integrations     (view, configure*)   │
│  ├── calendar         (view, manage)       │
│  ├── reports          (view, export)       │
│  ├── erp              (view, sync*)        │
│  ├── whatsapp         (view, configure*)   │
│  └── reviews          (create)             │
│                                           │
│  * Apenas Proprietário                    │
└──────────────────────────────────────────┘

Prestador

┌──────────────────────────────────────────┐
│             PRESTADOR                     │
│                                           │
│  Módulos disponíveis:                     │
│  ├── dashboard        (view)              │
│  ├── team             (view, invite,      │
│  │                     manage, remove)     │
│  ├── quotations       (view)              │
│  ├── proposals        (view, create)       │
│  ├── orders           (view, create,      │
│  │                     edit, approve)      │
│  ├── contracts        (view, manage)       │
│  ├── documents        (view, upload,       │
│  │                     delete)             │
│  ├── finance          (view, create,       │
│  │                     approve)            │
│  ├── chat             (view, send)         │
│  ├── ai               (view, use)          │
│  ├── subscription     (view, manage*)      │
│  ├── settings         (view, edit*)        │
│  ├── integrations     (view, configure*)   │
│  ├── calendar         (view, manage)       │
│  ├── reports          (view, export)       │
│  ├── erp              (view, sync*)        │
│  └── whatsapp         (view, configure*)   │
│                                           │
│  * Apenas Proprietário                    │
│                                           │
│  NOTA: Prestador NÃO tem acesso a:        │
│  - solicitations ( módulo de quem cria)    │
│  - quotations:create/edit/approve/cancel   │
│  - proposals:approve/reject               │
│  - reviews (módulo de quem avalia)         │
│  - condominiums (módulo da administradora) │
└──────────────────────────────────────────┘

Fornecedor

┌──────────────────────────────────────────┐
│             FORNECEDOR                    │
│                                           │
│  Módulos disponíveis:                     │
│  ├── dashboard        (view)              │
│  ├── team             (view, invite,      │
│  │                     manage, remove)     │
│  ├── quotations       (view)              │
│  ├── proposals        (view, create)       │
│  ├── orders           (view, create,      │
│  │                     edit, approve)      │
│  ├── contracts        (view, manage)       │
│  ├── documents        (view, upload,       │
│  │                     delete)             │
│  ├── finance          (view, create,       │
│  │                     approve)            │
│  ├── chat             (view, send)         │
│  ├── ai               (view, use)          │
│  ├── subscription     (view, manage*)      │
│  ├── settings         (view, edit*)        │
│  ├── integrations     (view, configure*)   │
│  ├── calendar         (view, manage)       │
│  ├── reports          (view, export)       │
│  ├── erp              (view, sync*)        │
│  └── whatsapp         (view, configure*)   │
│                                           │
│  * Apenas Proprietário                    │
│                                           │
│  NOTA: Fornecedor NÃO tem acesso a:        │
│  - solicitations                          │
│  - quotations:create/edit/approve/cancel  │
│  - proposals:approve/reject               │
│  - reviews                                │
│  - condominiums                           │
└──────────────────────────────────────────┘

9. Fluxo de Resolução das Permissões

Diagrama do Fluxo de Resolução

┌─────────────────────────────────────────────────────────────┐
│                  FLUXO DE RESOLUÇÃO                          │
│                                                              │
│  1. Requisição chega                                         │
│     ├── Frontend: usePermissions(user, orgType, org)        │
│     └── Backend: orgContextResolver.hasPermission(          │
│                  base44, userId, orgId, permissionKey)      │
│                                                              │
│  2. Verificar Super Admin?                                   │
│     ├── User.role === 'admin' → ✅ Todas as permissões     │
│     │                                                         │
│  3. Verificar Proprietário?                                  │
│     ├── OrganizationMember.role === 'Proprietário'           │
│     │   → ✅ Todas as permissões implícitas                  │
│     │                                                         │
│  4. Verificar Owner Legado? (apenas frontend)               │
│     ├── Sem OrganizationMember mas:                          │
│     │   org.manager_email === user.email                     │
│     │   org.created_by_id === user.id                        │
│     │   → ✅ Todas as permissões (compatibilidade)           │
│     │                                                         │
│  5. RESOLVER PERMISSÕES VIA FÓRMULA HÍBRIDA                 │
│     │                                                         │
│     │  5a. Buscar Role (por role_id ou name+org_type)       │
│     │       └── base_permissions = Role.base_permissions     │
│     │                                                          │
│     │  5b. Buscar MemberPermission overrides                │
│     │       └── WHERE member_id = X AND organization_id = Y  │
│     │                                                          │
│     │  5c. APLICAR FÓRMULA:                                  │
│     │       ┌──────────────────────────────┐                 │
│     │       │  Permissões Finais =         │                 │
│     │       │    base_permissions          │                 │
│     │       │      + ADD(overrides)        │                 │
│     │       │      - REMOVE(overrides)     │                 │
│     │       └──────────────────────────────┘                 │
│     │                                                          │
│     │  5d. Verificar se permissionKey ∈ Permissões Finais   │
│     │       ├── Sim → ✅ Permitido                           │
│     │       └── Não → ❌ Negado                              │
│     │                                                         │
│  6. Retornar resultado                                      │
│     ├── Frontend: can('quotations:create') → true/false     │
│     └── Backend: hasPermission(...) → true/false             │
└─────────────────────────────────────────────────────────────┘

Passo a Passo (Explicação Técnica)

No Frontend (src/hooks/usePermissions.js)

// 1. Carrega o vínculo OrganizationMember do usuário na organização
const membership = await base44.entities.OrganizationMember.filter({
  organization_id: orgId, user_id: user.id
});

// 2. Carrega a Role (por role_id primeiro, depois por name)
if (membership?.role_id) {
  const byId = await base44.entities.Role.filter({ id: membership.role_id });
  // ...
}

// 3. Carrega os overrides de MemberPermission
const overrides = await base44.entities.MemberPermission.filter({
  member_id: membership.id, organization_id: orgId
});

// 4. Aplica a fórmula híbrida
const finalSet = new Set(role.base_permissions);
for (const override of overrides) {
  if (override.operation === 'ADD') finalSet.add(override.permission_key);
  if (override.operation === 'REMOVE') finalSet.delete(override.permission_key);
}

// 5. can() verifica hierarquia + permissão resolvida
const can = (key) => {
  if (isSuperAdmin || isOwner || isLegacyOwner) return true;
  return finalSet.has(key);
};

No Backend (base44/shared/orgContextResolver.ts)

// resolvePermissions() implementa a fórmula oficial:
export async function resolvePermissions(base44, memberId, organizationId) {
  // 1. Buscar OrganizationMember
  const member = await base44.asServiceRole.entities.OrganizationMember.filter({ id: memberId });

  // 2. Buscar Role (por role_id ou name + organization_type)
  let role = null;
  if (member.role_id) {
    role = await base44.asServiceRole.entities.Role.filter({ id: member.role_id });
  }
  if (!role && member.role) {
    role = await base44.asServiceRole.entities.Role.filter({
      name: member.role, organization_type: member.organization_type
    });
  }

  // 3. Base permissions da Role
  const basePermissions = new Set(role?.base_permissions || role?.permissions || []);

  // 4. Buscar MemberPermission overrides
  const overrides = await base44.asServiceRole.entities.MemberPermission.filter({
    member_id: memberId, organization_id: organizationId
  });

  // 5. Aplicar fórmula: base + ADD - REMOVE
  const finalPermissions = new Set(basePermissions);
  for (const override of overrides) {
    if (override.operation === 'ADD') finalPermissions.add(override.permission_key);
    if (override.operation === 'REMOVE') finalPermissions.delete(override.permission_key);
  }

  return finalPermissions;
}

Hierarquia de Autorização

PrioridadeCondiçãoResultado
1User.role === 'admin'✅ Todas as permissões (Super Admin bypass)
2OrganizationMember.role === 'Proprietário'✅ Todas as permissões implícitas
3Owner legado (sem membership, mas é dono por e-mail/criador)✅ Todas (apenas frontend, compatibilidade)
4Demais PerfisPermissões resolvidas via fórmula híbrida

10. Fluxo de Convites

Fluxograma do Fluxo de Convites

┌─────────────────────────────────────────────────────────────────┐
│                    FLUXO DE CONVITES                              │
│                                                                  │
│  ┌──────────────┐                                               │
│  │ Página Equipe │  Usuário clica em "Convidar Colaborador"     │
│  │ (Frontend)    │                                               │
│  └──────┬───────┘                                                │
│         │                                                        │
│         ▼                                                        │
│  ┌──────────────────┐                                           │
│  │ InviteMemberDialog│  Formulário:                             │
│  │ (Frontend)        │  • Nome Completo                         │
│  │                   │  • E-mail                                 │
│  │                   │  • Perfil de Acesso (Role)               │
│  │                   │  • Cargo/Função (informativo)            │
│  │                   │  • [Opcional] Personalizar Permissões   │
│  └──────┬───────────┘                                           │
│         │                                                        │
│         ▼                                                        │
│  ┌──────────────────┐                                           │
│  │ notifyOrganization│  Backend:                                 │
│  │ Invitation       │  1. Valida permissão team:invite          │
│  │ (Backend)        │  2. Valida que a Role existe              │
│  │                   │  3. Verifica duplicidade (convite/membro)│
│  │                   │  4. Cria OrganizationInvitation         │
│  └──────┬───────────┘                                           │
│         │                                                        │
│         ├──────────────────────────────┐                        │
│         ▼                              ▼                        │
│  ┌──────────────┐              ┌──────────────┐                │
│  │ EmailService │              │ manageMember │                │
│  │ (Facade)     │              │ Permissions  │                │
│  └──────┬───────┘              │ (Backend)    │                │
│         │                      │               │                │
│         ▼                      │ Salva         │                │
│  ┌──────────────────┐          │ custom_perms  │                │
│  │ EmailProvider    │          │ no convite    │                │
│  │ Factory          │          └──────────────┘                │
│  │                   │                                           │
│  │ EMAIL_PROVIDER →  │                                           │
│  └──────┬───────────┘                                           │
│         │                                                        │
│         ▼                                                        │
│  ┌──────────────────┐                                           │
│  │ ResendProvider   │  POST https://api.resend.com/emails       │
│  │ (API Resend)     │  Authorization: Bearer RESEND_API_KEY     │
│  └──────┬───────────┘                                           │
│         │                                                        │
│         ▼                                                        │
│  ┌──────────────────┐                                           │
│  │ Resend (Cloud)  │  E-mail transacional enviado               │
│  └──────┬───────────┘                                           │
│         │                                                        │
│         ▼                                                        │
│  ┌──────────────────┐                                           │
│  │ Novo Colaborador│  Recebe e-mail com link do convite         │
│  │ (caixa de entrada)│  Link: /register/invite?token=XXX        │
│  └──────┬───────────┘                                           │
│         │                                                        │
│         ▼                                                        │
│  ┌──────────────────┐                                           │
│  │ RegisterInvite   │  Página de validação do convite           │
│  │ (Frontend)       │  (validate → Auth → complete)             │
│  └──────┬───────────┘                                           │
│         │                                                        │
│         ▼                                                        │
│  ┌──────────────────┐                                           │
│  │ completeInvitation│  Backend:                                 │
│  │ Registration     │  1. Valida token + e-mail autenticado     │
│  │ (Backend)        │  2. Cria OrganizationMember (active)      │
│  │                   │  3. Sincroniza role_id + role             │
│  │                   │  4. Aplica custom_permissions (se houver) │
│  │                   │  5. Marca convite como accepted           │
│  │                   │  6. Sincroniza organization_ids (User)   │
│  │                   │  7. Atualiza User.role (platform)       │
│  │                   │  8. Registra AuditLog                     │
│  │                   │  9. Retorna redirect_path do dashboard   │
│  └──────────────────┘                                           │
└─────────────────────────────────────────────────────────────────┘

Explicação de Cada Etapa

EtapaComponenteResponsabilidade
1InviteMemberDialog (Frontend)Coleta dados do convidado e Perfil de Acesso. Se o usuário logado for Proprietário, exibe a opção de personalizar permissões.
2notifyOrganizationInvitation (Backend)Valida permissão team:invite, verifica duplicidade, cria OrganizationInvitation com token, expiração e custom_permissions (se houver).
3manageMemberPermissions (Backend)Se o Proprietário personalizou permissões, salva os overrides no campo custom_permissions do convite.
4EmailService (Facade)Camada única de entrada para e-mails. Resolve o provider via EmailProviderFactory e delega o envio. Nunca lança exceções.
5EmailProviderFactoryLê a secret EMAIL_PROVIDER e instancia o provider correto. Atualmente: resend. Para trocar de provider, basta alterar a secret.
6ResendProviderComunica-se com a API do Resend via fetch nativo. POST para https://api.resend.com/emails com Authorization: Bearer RESEND_API_KEY.
7RegisterInvite (Frontend)Página pública que valida o token do convite. Se válido, direciona o usuário para autenticação na Base44.
8completeInvitationRegistration (Backend)Após autenticação, vincula o usuário à organização: cria OrganizationMember com role_id, aplica custom_permissions como MemberPermission, sincroniza organization_ids e role no User, e registra auditoria.

Secrets Utilizados no Fluxo de Convites

SecretDescrição
RESEND_API_KEYChave de API do Resend para envio de e-mails transacionais
EMAIL_FROMEndereço de e-mail remetente (ex: noreply@connectcond.com.br)
EMAIL_PROVIDERProvider ativo (resend)

11. Landing Page

Implementação

A Landing Page da ConnectCond (rota /) continua utilizando exclusivamente o fluxo nativo da Base44.

Características confirmadas:

  • ✅ A Landing Page NÃO utiliza o Resend ou qualquer infraestrutura de e-mail personalizada.
  • ✅ A Landing Page NÃO é afetada pela arquitetura RBAC Enterprise.
  • ✅ A Landing Page é uma rota pública, acessível sem autenticação.
  • ✅ Qualquer formulário de contato ou captura de leads na Landing Page utiliza os mecanismos nativos da plataforma Base44.

Diferença do Fluxo de Convites: O fluxo de convites de colaboradores (Seção 10) utiliza o Resend via EmailService. A Landing Page é completamente independente desse fluxo.


12. Tela "Convidar Colaborador"

Componente: InviteMemberDialog.jsx

A tela de convite de colaboradores é implementada como um diálogo modal (Dialog) acessível a partir da página Equipe de cada organização.

Campos da Interface

CampoTipoObrigatórioDescrição
Nome CompletoInput de textoNãoNome do convidado (para exibição e e-mail)
E-mailInput de e-mailSimE-mail que receberá o convite. Deve corresponder ao e-mail de autenticação.
Perfil de AcessoSelect dropdownSimUm dos 4 Perfis oficiais (Proprietário, Gestor, Colaborador, Consulta). Cada opção exibe o nome e a descrição do Perfil.
Cargo/FunçãoInput de textoNãoFunção profissional (Síndico, Comprador, Financeiro...). Informativo — não concede permissões. Ajudante de texto abaixo do campo: "Campo informativo — não concede permissões."
Personalizar PermissõesCheckbox + MatrizCondicionalDisponível apenas se o usuário logado for Proprietário ou Super Admin. Quando ativado, exibe a PermissionMatrix com todas as permissões do organization_type, agrupadas por módulo.

Fluxo Visual do Diálogo

┌─────────────────────────────────────────────────────┐
│  [👤] Convidar colaborador                          │
│                                                       │
│  O colaborador receberá um convite por e-mail com    │
│  um link para concluir o cadastro e acessar a        │
│  plataforma.                                         │
│                                                       │
│  ┌─────────────────┐  ┌─────────────────┐            │
│  │ Nome completo   │  │ E-mail *        │            │
│  │ [João Silva   ] │  │ [joao@...     ] │            │
│  └─────────────────┘  └─────────────────┘            │
│                                                       │
│  Perfil de Acesso *                                  │
│  ┌─────────────────────────────────────────┐        │
│  │ Gestor                                    │        │
│  │ Administrador operacional. Gerencia...    │        │
│  └─────────────────────────────────────────┘        │
│                                                       │
│  Cargo/Função                                        │
│  [Síndico, Comprador, Financeiro...]               │
│  Campo informativo — não concede permissões.        │
│                                                       │
│  ┌─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─┐    │
│  │ [☑] 🛡️ Personalizar permissões deste       │    │
│  │       colaborador                           │    │
│  │    Ajuste permissões individuais além do    │    │
│  │    Perfil de Acesso selecionado.            │    │
│  │                                              │    │
│  │  ┌─────────────────────────────────────┐   │    │
│  │  │  Permissões (scroll)                 │   │    │
│  │  │                                       │   │    │
│  │  │  📋 Equipe                           │   │    │
│  │  │  ☑ Visualizar membros da equipe      │   │    │
│  │  │  ☑ Convidar novos colaboradores [Extra]│  │    │
│  │  │  ☐ Gerenciar cargos  [Removida]      │   │    │
│  │  │                                       │   │    │
│  │  │  📄 Cotações                         │   │    │
│  │  │  ☑ Visualizar cotações               │   │    │
│  │  │  ☑ Criar cotações                    │   │    │
│  │  │  ...                                  │   │    │
│  │  └─────────────────────────────────────┘   │    │
│  └─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─┘    │
│                                                       │
│                    [Cancelar]  [Enviar convite]     │
└─────────────────────────────────────────────────────┘

PermissionMatrix (Matriz de Permissões)

Quando o Proprietário ativa "Personalizar permissões", a PermissionMatrix é exibida com as seguintes características:

Estado VisualSignificado
☑ Checkbox marcado, sem badgePermissão vem da Role base (base)
☑ Checkbox marcado, badge verde "Extra"Permissão adicionada via override (ADD)
☐ Checkbox desmarcado, badge vermelho "Removida"Permissão removida via override (REMOVE)
☐ Checkbox desmarcado, sem badgePermissão não pertence à Role base e não tem override

A matriz é segmentada por organization_type — apenas as permissões aplicáveis ao Perfil da Organização são exibidas.


13. Regras de Governança

Matriz Oficial de Governança

AçãoProprietárioGestorColaboradorConsultaSuper Admin
Convidar colaborador (team:invite)✅✅✅❌✅
Gerenciar cargos (team:manage)✅✅❌❌✅
Remover membro (team:remove)✅✅❌❌✅
Personalizar permissões (MemberPermission)✅❌❌❌✅
Criar cotação (quotations:create)✅✅✅❌✅
Aprovar proposta (proposals:approve)✅✅❌❌✅
Assinar contrato (contracts:sign)✅✅❌❌✅
Gerenciar assinatura (subscription:manage)✅❌❌❌✅
Editar configurações (settings:edit)✅❌❌❌✅
Configurar integrações (integrations:configure)✅❌❌❌✅
Sincronizar ERP (erp:sync)✅❌❌❌✅
Configurar WhatsApp (whatsapp:configure)✅❌❌❌✅
Excluir documento (documents:delete)✅✅❌❌✅
Exportar relatório (reports:export)✅✅❌❌✅
Visualizar (todos os módulos :view)✅✅✅✅✅

Regras de Governança Críticas

  1. Apenas o Proprietário pode personalizar permissões — Validado no backend manageMemberPermissions (função isProprietario). Retorna HTTP 403 se o solicitante não for Proprietário ou Super Admin.

  2. O Gestor pode gerenciar a equipe mas NUNCA pode alterar permissões — O Gestor tem team:manage (pode alterar cargos), mas a função manageMemberPermissions verifica especificamente role === 'Proprietário', não team:manage.

  3. Todas as alterações de permissão são auditadas — O manageMemberPermissions registra no AuditLog toda criação, atualização e remoção de MemberPermission, com descrição legível e metadados estruturados.

  4. O Super Admin (plataforma) bypassa todas as verificações — User.role === 'admin' tem acesso irrestrito a todas as operações.


14. Segurança

Princípio do Menor Privilégio

Toda implementação parte da premissa de que cada colaborador deve ter apenas as permissões mínimas necessárias para executar sua função:

  • O Perfil Consulta recebe apenas permissões :view (somente leitura).
  • O Perfil Colaborador recebe permissões operacionais (view, create, edit, send, use, upload), mas nunca manage, approve, delete, configure ou sync.
  • Permissões de segurança (subscription:manage, settings:edit, integrations:configure, erp:sync, whatsapp:configure) são exclusivas do Proprietário por padrão.

Segregação de Funções

A arquitetura garante que funções sensíveis sejam separadas:

FunçãoQuem pode executarQuem NÃO pode
Personalizar permissõesProprietárioGestor, Colaborador, Consulta
Convidar colaboradorProprietário, Gestor, ColaboradorConsulta
Aprovar pagamentosProprietário, GestorColaborador, Consulta
Gerenciar assinaturaProprietárioTodos os demais

Auditoria

Toda alteração de permissão gera um registro no AuditLog:

EventoAction no AuditLogEntity
Permissão concedida (ADD)createMemberPermission
Permissão removida (REMOVE)createMemberPermission
Override excluídodeleteMemberPermission
Colaborador vinculado via convitecreateOrganizationMember
Permissões salvas em conviteupdateOrganizationInvitation

Cada registro contém: user_email, user_id, action, entity_name, entity_id, description (legível), metadata (estruturado).

Compatibilidade com RLS (Row-Level Security)

A arquitetura RBAC Enterprise opera em conjunto com o RLS nativo da Base44:

  • RLS controla quais registros um usuário pode ver/editar (isolamento multi-tenant).
  • RBAC controla quais ações um usuário pode executar dentro dos registros que o RLS permite.

Exemplo: O RLS garante que um colaborador do Condomínio A não veja as cotações do Condomínio B. O RBAC garante que, dentro do Condomínio A, um Colaborador possa criar cotações mas não possa aprová-las.

Compatibilidade com Autenticação

A autenticação é exclusivamente gerenciada pela Base44:

  • Criação de identidade (conta, senha, verificação de e-mail) → Base44 Auth.
  • Sessões e tokens → Base44 Auth.
  • A arquitetura RBAC não cria identidades — apenas gerencia vínculos (OrganizationMember) e permissões (Role, MemberPermission) para identidades já autenticadas.

Governança

A governança é enforced no backend, não apenas no frontend:

CamadaMecanismo
FrontendusePermissions.can() esconde/bloqueia ações não autorizadas
BackendorgContextResolver.hasPermission() valida antes de executar
Backend (convites)notifyOrganizationInvitation valida team:invite
Backend (permissões)manageMemberPermissions valida role === 'Proprietário'
Backend (cargos)inviteMember valida team:manage para update_role

Princípio: O frontend é uma camada de UX; a segurança real é sempre validada no backend.


15. Compatibilidade

Esta arquitetura foi projetada para ser totalmente compatível com todos os módulos homologados da ConnectCond, sem quebrar funcionalidade existente:

MóduloCompatívelObservação
Landing Page✅Não utiliza RBAC; rota pública independente
Cadastro (Registration)✅Fluxo nativo de registro não foi alterado
Login (Auth)✅Base44 Auth gerencia autenticação; RBAC gerencia vínculos
Checkout✅Fluxo de pagamento não foi alterado
Assinaturas✅subscription:view disponível para todos; subscription:manage exclusivo do Proprietário
IA✅ai:view e ai:use disponíveis conforme Perfil
Chat✅chat:view e chat:send disponíveis conforme Perfil
WhatsApp✅whatsapp:configure exclusivo do Proprietário; infraestrutura inalterada
Stripe✅Integração de pagamento não foi alterada
ERP✅erp:sync exclusivo do Proprietário; conector inalterado
Fluxo de Convites✅Refatorado para usar role_id + custom_permissions; Resend inalterado
Organização✅Multi-tenant preservado; RLS não foi alterado
Todos os módulos homologados✅Nenhuma regra de negócio homologada foi quebrada

Campos de compatibilidade ativos: Role.permissions (sincronizado com base_permissions), OrganizationMember.role (sincronizado com role_id), OrganizationMember.user_email (mantido para exibição). Todos são atualizados automaticamente — nunca editados diretamente.


16. Fluxo Completo da Arquitetura

Diagrama Geral da Arquitetura RBAC Enterprise

┌─────────────────────────────────────────────────────────────────────┐
│                    ARQUITETURA RBAC ENTERPRISE                       │
│                    CONNECTCOND — VISÃO COMPLETA                     │
│                                                                      │
│  ┌─────────────────────────────────────────────────────────────┐   │
│  │                     CAMADA DE IDENTIDADE                      │   │
│  │                                                                │   │
│  │  ┌──────────────┐    ┌──────────────┐    ┌──────────────┐   │   │
│  │  │ Base44 Auth  │───▶│ User Entity  │───▶│ organization │   │   │
│  │  │ (Login/Senha)│    │ (id, email,  │    │ _ids (cache) │   │   │
│  │  │              │    │  role, ...)  │    │              │   │   │
│  │  └──────────────┘    └──────────────┘    └──────────────┘   │   │
│  └─────────────────────────────────────────────────────────────┘   │
│                              │                                       │
│                              │ user_id                              │
│                              ▼                                       │
│  ┌─────────────────────────────────────────────────────────────┐   │
│  │                   CAMADA DE VÍNCULO                           │   │
│  │                                                                │   │
│  │  ┌──────────────────────────────────────────┐               │   │
│  │  │ OrganizationMember                        │               │   │
│  │  │  • user_id ──────────────────────────────│───────────────│   │
│  │  │  • organization_id                        │               │   │
│  │  │  • organization_type (admin/cond/         │               │   │
│  │  │    provider/supplier)                     │               │   │
│  │  │  • role (string, compat RLS) ────────────│───────────────│   │
│  │  │  • role_id (UUID, fonte oficial) ────────│───────────────│   │
│  │  │  • professional_function (informativo)   │               │   │
│  │  │  • status (pending/active/blocked)       │               │   │
│  │  └──────────────┬───────────────────────────┘               │   │
│  │                 │                                               │   │
│  │         ┌───────┴────────┐                                    │   │
│  │         ▼                ▼                                     │   │
│  │  ┌──────────┐     ┌──────────────────┐                        │   │
│  │  │ Role     │     │ MemberPermission │                        │   │
│  │  │          │     │  (Overrides)     │                        │   │
│  │  │ base_    │     │                  │                        │   │
│  │  │ perms[]  │     │  ADD / REMOVE    │                        │   │
│  │  └────┬─────┘     └────────┬─────────┘                        │   │
│  │       │                    │                                    │   │
│  │       │     ┌──────────────┘                                    │   │
│  │       │     │ (referência por key)                              │   │
│  │       ▼     ▼                                                    │   │
│  │  ┌──────────────────┐                                          │   │
│  │  │ Permission       │  Catálogo de 52 permissões atômicas     │   │
│  │  │  (key, module,   │  segmentadas por organization_types      │   │
│  │  │   org_types)     │                                          │   │
│  │  └──────────────────┘                                          │   │
│  └─────────────────────────────────────────────────────────────┘   │
│                              │                                       │
│                              ▼                                       │
│  ┌─────────────────────────────────────────────────────────────┐   │
│  │                  CAMADA DE RESOLUÇÃO                          │   │
│  │                                                                │   │
│  │  orgContextResolver.ts (Backend)                              │   │
│  │  usePermissions.js (Frontend)                                 │   │
│  │                                                                │   │
│  │  FÓRMULA:                                                      │   │
│  │  Permissões Finais = base_permissions + ADD - REMOVE          │   │
│  │                                                                │   │
│  │  Hierarquia:                                                   │   │
│  │  1. Super Admin → tudo                                        │   │
│  │  2. Proprietário → tudo                                       │   │
│  │  3. Owner legado → tudo (compat)                              │   │
│  │  4. Demais → fórmula híbrida                                  │   │
│  └─────────────────────────────────────────────────────────────┘   │
│                              │                                       │
│                              ▼                                       │
│  ┌─────────────────────────────────────────────────────────────┐   │
│  │                    CAMADA DE APLICAÇÃO                        │   │
│  │                                                                │   │
│  │  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐       │   │
│  │  │ Frontend     │  │ Backend      │  │ RLS (Base44) │       │   │
│  │  │ can(key)     │  │ hasPermission│  │ Isolamento   │       │   │
│  │  │              │  │ (key)        │  │ multi-tenant │       │   │
│  │  └──────────────┘  └──────────────┘  └──────────────┘       │   │
│  └─────────────────────────────────────────────────────────────┘   │
│                              │                                       │
│                              ▼                                       │
│  ┌─────────────────────────────────────────────────────────────┐   │
│  │                    CAMADA DE AUDITORIA                        │   │
│  │                                                                │   │
│  │  ┌──────────────────┐                                        │   │
│  │  │ AuditLog         │  Toda alteração registrada             │   │
│  │  │  (action, user,  │  com descrição e metadados             │   │
│  │  │   entity, desc)  │                                        │   │
│  │  └──────────────────┘                                        │   │
│  └─────────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────────┘

17. Banco de Dados

Diagrama das Tabelas

┌─────────────────────────────────────────────────────────────────┐
│                        BANCO DE DADOS                            │
│                                                                  │
│  ┌──────────────────────┐        ┌──────────────────────┐       │
│  │     Role             │        │    Permission         │       │
│  │──────────────────────│        │──────────────────────│       │
│  │ id          (UUID)   │        │ id          (UUID)   │       │
│  │ name        (string) │        │ key         (string) │       │
│  │ organization_type     │        │ module      (enum)  │       │
│  │   (enum)             │        │ description (string)│       │
│  │ base_permissions      │        │ organization_types   │       │
│  │   (array<string>)    │        │   (array<enum>)     │       │
│  │ permissions* (compat) │        │                      │       │
│  │ description (string) │        │ RLS: read=public     │       │
│  │ is_system  (boolean) │        │      CUD=admin       │       │
│  │ is_default (boolean) │        └──────────────────────┘       │
│  │                      │                    ▲                  │
│  │ RLS: read=public     │                    │ (key ref)        │
│  │      CUD=admin       │                    │                  │
│  └──────────┬───────────┘                    │                  │
│             │ role_id                         │                  │
│             ▼                                 │                  │
│  ┌──────────────────────┐        ┌───────────┴──────────┐     │
│  │ OrganizationMember   │────────│  MemberPermission     │     │
│  │──────────────────────│  1:N   │──────────────────────│     │
│  │ id          (UUID)   │        │ id          (UUID)   │     │
│  │ user_id     (UUID)   │        │ member_id   (UUID)   │     │
│  │ user_email* (compat) │        │ organization_id(UUID)│     │
│  │ full_name   (string) │        │ permission_key(string)│     │
│  │ phone       (string) │        │ operation   (enum)   │     │
│  │ position    (string) │        │   ADD | REMOVE       │     │
│  │ professional_function│        │ granted_by  (UUID)   │     │
│  │   (string, informat.)│        │ granted_at  (datetime)│    │
│  │ department (enum)    │        │                      │     │
│  │ organization_id      │        │ RLS: read=org member │     │
│  │   (UUID)             │        │      CUD=admin       │     │
│  │ organization_type     │        └──────────────────────┘     │
│  │   (enum)             │                                      │
│  │ role        (string) │        ┌──────────────────────┐     │
│  │   (compat RLS)       │        │     AuditLog          │     │
│  │ role_id     (UUID)   │        │──────────────────────│     │
│  │   (oficial)         │        │ id          (UUID)   │     │
│  │ status      (enum)  │        │ user_email (string)  │     │
│  │   pending/active/   │        │ user_id     (UUID)   │     │
│  │   blocked/expired   │        │ action      (enum)   │     │
│  │ invited_by  (UUID)  │        │ entity_name(string) │     │
│  │ invited_by_name      │        │ entity_id   (UUID)  │     │
│  │ invited_at(datetime)│        │ description (string)│     │
│  │ accepted_at(datetime)│       │ ip_address (string) │     │
│  │ last_access(datetime)│       │ metadata    (object)│     │
│  │                      │        │                      │     │
│  │ RLS: read=self/org   │        │ RLS: read=admin      │     │
│  │      CUD=self/admin  │        │      CUD=admin       │     │
│  └──────────────────────┘        │      create=open     │     │
│                                   └──────────────────────┘     │
│                                                                  │
│  * Campo de compatibilidade (não é fonte da verdade)           │
└─────────────────────────────────────────────────────────────────┘

Tabela de Campos por Entidade

Role (16 registros: 4 Perfis × 4 org_types)

CampoTipoOrigemFonte da Verdade?
namestringDefinido no catálogo✅ Sim
organization_typeenumDefinido no catálogo✅ Sim
base_permissionsarray<string>Definido no catálogo✅ Sim
permissionsarray<string>Sincronizado com base_permissions❌ Compatibilidade
descriptionstringDefinido no catálogo✅ Sim
is_systembooleanDefinido no catálogo✅ Sim
is_defaultbooleanDefinido no catálogo✅ Sim

Permission (52 registros)

CampoTipoOrigemFonte da Verdade?
keystringDefinido no catálogo✅ Sim
moduleenumDefinido no catálogo✅ Sim
descriptionstringDefinido no catálogo✅ Sim
organization_typesarray<enum>Definido no catálogo✅ Sim

MemberPermission (dinâmico)

CampoTipoOrigemFonte da Verdade?
member_idstring (UUID)Referência a OrganizationMember✅ Sim
organization_idstring (UUID)Referência à organização✅ Sim
permission_keystringReferência a Permission.key✅ Sim
operationenum (ADD/REMOVE)Definido pelo Proprietário✅ Sim
granted_bystring (UUID)User.id do Proprietário✅ Sim
granted_atdate-timeTimestamp da alteração✅ Sim

OrganizationMember (dinâmico)

CampoTipoOrigemFonte da Verdade?
user_idstring (UUID)User.id✅ Sim
user_emailstringUser.email❌ Compatibilidade
full_namestringFormulário de convite✅ Sim
positionstringFormulário de convite✅ Sim
professional_functionstringFormulário de convite✅ Informativo
organization_idstring (UUID)ID da organização✅ Sim
organization_typeenumTipo da organização✅ Sim
rolestringSincronizado com role_id❌ Compatibilidade
role_idstring (UUID)Role.id✅ Sim
statusenumCiclo de vida do vínculo✅ Sim

AuditLog (dinâmico)

CampoTipoOrigemFonte da Verdade?
user_emailstringUser.email✅ Sim
user_idstring (UUID)User.id✅ Sim
actionenumTipo da ação✅ Sim
entity_namestringEntidade afetada✅ Sim
entity_idstring (UUID)ID do registro afetado✅ Sim
descriptionstringTexto legível✅ Sim
metadataobjectDados estruturados✅ Sim

18. Exemplos Práticos

Exemplo 1: Criando um Proprietário

Cenário: Maria Souza registra a Administradora "CondAdmin Ltda" na plataforma.

Registros criados:

1. Administration
   { id: "admin-001", name: "CondAdmin Ltda", ... }

2. User (via Base44 Auth)
   { id: "usr-maria", email: "maria@condadmin.com.br", role: "administradora" }

3. OrganizationMember
   {
     id: "member-001",
     user_id: "usr-maria",
     organization_id: "admin-001",
     organization_type: "administration",
     role: "Proprietário",
     role_id: "role-prop-admin",   ← Role "Proprietário" + org_type "administration"
     status: "active",
     professional_function: "Diretor"
   }

Permissões recebidas: Todas as permissões do organization_type: "administration" (implícitas — Proprietário tem tudo).

Resolução:

Hierarquia → Proprietário → ✅ Todas as permissões implícitas
(MembroPermission overrides não são consultados — Proprietário tem tudo)

Exemplo 2: Criando um Gestor

Cenário: Maria (Proprietária) convida João Silva como Gestor da Administradora.

Registros criados:

1. OrganizationInvitation
   {
     id: "inv-001",
     organization_id: "admin-001",
     email: "joao@condadmin.com.br",
     role: "Gestor",
     token: "abc-token-123",
     status: "pending",
     custom_permissions: []
   }

2. (E-mail enviado via Resend com link /register/invite?token=abc-token-123)

3. OrganizationMember (criado quando João aceita o convite)
   {
     id: "member-002",
     user_id: "usr-joao",
     organization_id: "admin-001",
     organization_type: "administration",
     role: "Gestor",
     role_id: "role-gestor-admin",  ← Role "Gestor" + org_type "administration"
     status: "active",
     professional_function: "Gerente"
   }

Permissões recebidas: base_permissions da Role "Gestor" + organization_type: "administration", exceto as 5 permissões de segurança exclusivas do Proprietário.

Resolução:

base_permissions (Gestor, administration) = [
  "dashboard:view", "team:view", "team:invite", "team:manage", "team:remove",
  "solicitations:view", "solicitations:create", "solicitations:edit", "solicitations:cancel",
  "quotations:view", "quotations:create", "quotations:edit", "quotations:approve", "quotations:cancel",
  "proposals:view", "proposals:approve", "proposals:reject",
  "contracts:view", "contracts:sign",
  "documents:view", "documents:upload", "documents:delete",
  "finance:view", "finance:create", "finance:approve",
  "chat:view", "chat:send",
  "ai:view", "ai:use",
  "subscription:view",
  "settings:view",
  "integrations:view",
  "calendar:view", "calendar:manage",
  "reports:view", "reports:export",
  "erp:view",
  "whatsapp:view",
  "reviews:create",
  "condominiums:view", "condominiums:manage"
]
+ ADD: (nenhum override)
- REMOVE: (nenhum override)
= Permissões Finais (sem subscription:manage, settings:edit, integrations:configure, erp:sync, whatsapp:configure)

Exemplo 3: Criando um Colaborador com Permissões Personalizadas

Cenário: Maria (Proprietária) convida Carlos como Colaborador, mas personaliza suas permissões para também poder aprovar propostas (proposals:approve), que normalmente o Colaborador não tem.

Registros criados:

1. OrganizationInvitation
   {
     id: "inv-002",
     organization_id: "admin-001",
     email: "carlos@condadmin.com.br",
     role: "Colaborador",
     token: "def-token-456",
     status: "pending",
     custom_permissions: [
       { permission_key: "proposals:approve", operation: "ADD" }
     ]
   }

2. (E-mail enviado via Resend)

3. OrganizationMember (criado quando Carlos aceita)
   {
     id: "member-003",
     user_id: "usr-carlos",
     organization_id: "admin-001",
     organization_type: "administration",
     role: "Colaborador",
     role_id: "role-colab-admin",
     status: "active",
     professional_function: "Assistente"
   }

4. MemberPermission (criado a partir do custom_permissions do convite)
   {
     id: "mp-001",
     member_id: "member-003",
     organization_id: "admin-001",
     permission_key: "proposals:approve",
     operation: "ADD",
     granted_by: "usr-maria",
     granted_at: "2026-08-06T14:30:00Z"
   }

Resolução:

base_permissions (Colaborador, administration) = [
  "dashboard:view", "team:view", "team:invite",
  "solicitations:view", "solicitations:create", "solicitations:edit",
  "quotations:view", "quotations:create", "quotations:edit",
  "proposals:view", "proposals:create",
  "contracts:view", "contracts:manage",
  "documents:view", "documents:upload",
  "finance:view", "finance:create",
  "chat:view", "chat:send",
  "ai:view", "ai:use",
  "subscription:view", "settings:view", "integrations:view",
  "calendar:view",
  "reports:view",
  "erp:view", "whatsapp:view",
  "reviews:create",
  "condominiums:view"
]
+ ADD: "proposals:approve"     ← do MemberPermission
- REMOVE: (nenhum)
= Permissões Finais:
  (...todas as base...) + "proposals:approve"

Carlos agora PODE aprovar propostas, mesmo sendo Colaborador.

Exemplo 4: Criando um Consulta com Permissão Removida

Cenário: Maria (Proprietária) convida Ana como Consulta (somente leitura), mas remove explicitamente a permissão finance:view (que o Consulta normalmente tem).

Registros criados:

1. OrganizationInvitation
   {
     custom_permissions: [
       { permission_key: "finance:view", operation: "REMOVE" }
     ]
   }

2. OrganizationMember
   { role: "Consulta", role_id: "role-cons-admin", ... }

3. MemberPermission
   {
     permission_key: "finance:view",
     operation: "REMOVE",
     ...
   }

Resolução:

base_permissions (Consulta, administration) = [
  "dashboard:view", "team:view",
  "solicitations:view", "quotations:view", "proposals:view",
  "contracts:view", "documents:view", "finance:view",    ← está na base
  "chat:view", "ai:view",
  "subscription:view", "settings:view", "integrations:view",
  "calendar:view", "reports:view",
  "erp:view", "whatsapp:view",
  "condominiums:view"
]
+ ADD: (nenhum)
- REMOVE: "finance:view"     ← do MemberPermission
= Permissões Finais:
  (...todas as base...) - "finance:view"

Ana NÃO pode visualizar o módulo Financeiro, mesmo sendo Consulta
(que normalmente teria finance:view).

19. Histórico da Arquitetura

VersãoDataPrincipais DecisõesJustificativa
1.0.006/08/2026Arquitetura RBAC Enterprise homologadaEvolução do modelo RBAC simples para um modelo híbrido com Perfil de Acesso + Overrides personalizados

Decisões Técnicas Registradas

IDDecisãoJustificativa
DA-001Desacoplar Role de Professional FunctionA função profissional (Síndico, Comprador) é informativa; o Perfil de Acesso (Proprietário, Gestor) determina permissões. São conceitos independentes.
DA-002Usar MemberPermission como entidade dedicadaOverrides personalizados em tabela dedicada são mais auditáveis, idempotentes e consultáveis do que arrays embutidos em OrganizationMember.
DA-003Dual-Field Strategy (role + role_id)role_id (UUID) é a fonte oficial; role (string) é mantido para compatibilidade com regras RLS existentes que comparam por nome. Sincronização automática.
DA-004Resolução centralizada em orgContextResolver.tsToda resolução de permissão no backend passa por um único módulo, garantindo consistência e facilitando manutenção.
DA-005Apenas Proprietário pode personalizar permissõesPrincípio do Menor Privilégio aplicado à própria governança — nem o Gestor pode escalonar privilégios.
DA-006Base44 Auth é única responsável por identidadeA RBAC Enterprise não cria identidades; apenas gerencia vínculos e permissões para identidades já autenticadas pela Base44.
DA-007Fórmula aditiva/subtrativabase_permissions + ADD - REMOVE é determinística, idempotente e fácil de auditar.
DA-008Segmentação por organization_typesCada permissão declara quais Perfis de Organização a utilizam, evitando que um Prestador veja permissões de Condomínio.
DA-00916 Roles (4 × 4) em vez de Roles genéricasRoles específicas por organization_type permitem que as base_permissions sejam precisamente calibradas para cada contexto.
DA-010EmailProviderFactory para e-mails transacionaisO fluxo de convites usa Resend via factory pattern, permitindo troca de provider sem alterar código de negócio.

Arquitetura Homologada

Esta versão (1.0.0) foi homologada em 06 de Agosto de 2026 após:

  • ✅ Implementação completa das 5 entidades (Role, Permission, MemberPermission, OrganizationMember, AuditLog)
  • ✅ Catálogo de 52 permissões atômicas + 16 Perfis de Acesso populado via seedPermissions
  • ✅ Resolvedor central (orgContextResolver.ts) implementado e testado
  • ✅ Hook frontend (usePermissions.js) evoluído com fórmula híbrida
  • ✅ Fluxo de convites refatorado com role_id + custom_permissions
  • ✅ Tela "Convidar Colaborador" com PermissionMatrix implementada
  • ✅ Governança de permissões (apenas Proprietário) validada no backend
  • ✅ Auditoria de todas as alterações de permissão

20. Conclusão

Esta passa a ser a Arquitetura Oficial Homologada da ConnectCond para controle de acesso baseado em papéis (RBAC Enterprise).

Pontos-Chave

  1. Modelo Híbrido: Perfil de Acesso (Role) define a base; MemberPermission permite personalizações individuais (ADD/REMOVE).
  2. Fórmula Determinística: Permissões Finais = base_permissions + ADD - REMOVE — sempre previsível e auditável.
  3. Governança Centralizada: Apenas o Proprietário pode personalizar permissões; o Gestor gerencia a equipe mas não pode escalonar privilégios.
  4. Auditoria Completa: Toda alteração de permissão é registrada no AuditLog com rastreabilidade total.
  5. Compatibilidade Total: Nenhum módulo homologado foi quebrado; campos de compatibilidade mantêm o funcionamento de código legado.
  6. Segurança em Camadas: Frontend (UX) + Backend (validação real) + RLS (isolamento multi-tenant) operam em conjunto.

Referência Oficial

Este documento serve como referência oficial para:

  • Novos desenvolvedores integrando à equipe
  • Futuras evoluções da plataforma
  • Auditorias de segurança e conformidade
  • Homologações de novos módulos
  • Documentação interna
  • Entendimento do negócio por stakeholders técnicos e não técnicos

Nota de Fidelidade: Este documento reflete a implementação real do ambiente de produção. Caso discrepâncias sejam identificadas entre este documento e o comportamento observado do sistema, o código-fonte em produção deve ser considerado a fonte definitiva, e este documento deve ser atualizado para refletir a realidade.


ConnectCond © 2026 — Arquitetura RBAC Enterprise v1.0.0 — Documento Oficial Homologado