ADR-201: Identity — Organization & Collaborator
Status: Accepted
Contexto
middag-account é multi-tenant desde o início. Clientes são organizações (empresas/instituições), não usuários WordPress individuais. Cada organização precisa de: dados fiscais (CNPJ/EIN), hierarquia (holding→subsidiária), IDs duais de Stripe e HubSpot (BR + GLOBAL), verificação pelo admin, e controle granular de acesso para membros da equipe do cliente. O WooCommerce não oferece nada disso nativamente — trata todos como "customers" individuais.
Decisão
Organization como Raiz Multi-Tenant
Organization é o tenant de nível superior. Todo outro domínio referencia uma org — queries SEMPRE filtram por organization_id. Dados cross-organization NUNCA vazam sem permissão explícita.
Dados da Organization
| Campo | Tipo | Notas |
|---|---|---|
| Nome | string | Nome comercial |
| Razão social | string | Nome legal (para documentos fiscais) |
| Tax ID | string | CNPJ, EIN, VAT — label e formato configuráveis |
| Endereço | object | Rua, cidade, estado, CEP, país |
stripe_customer_id_br | string | Customer ID na conta Stripe BR |
stripe_customer_id_global | string | Customer ID na conta Stripe GLOBAL |
hubspot_company_id_br | string | Company ID no HubSpot BR |
hubspot_company_id_global | string | Company ID no HubSpot GLOBAL |
| Status de verificação | enum | pending → verified / rejected |
parent_organization_id | nullable | FK para org pai (hierarquia) |
| Company context | enum | middag_br / middag_global (roteamento default) |
Hierarquia de Organization
Até 3 níveis: holding → subsidiária → filial. Cada nível deve ser entidade faturável (CNPJ/EIN próprio). Configurável por admin. Não recursiva — profundidade máxima fixa.
Verificação (4 estados)
O ciclo de verificação segue 4 estados: pending → under_review → verified / rejected. O estado under_review é intermediário entre o envio de documentação pelo cliente e a decisão do admin. Organizações em estado rejected podem reenviar documentação, retornando a under_review.
Verificação automática por Tax ID (ex: CNPJ via API da Receita Federal) é suportada: se validação passa, transiciona diretamente para verified.
Hook middag_organization_verified dispara na verificação (sync HubSpot, email de boas-vindas). Funcionalidades comerciais (compras, aceite de quotes, emissão de NF) requerem status verified.
Detalhes completos do workflow, transições e restrições em REF-201-01 §12.
Collaborator RBAC
Collaborators são membros dentro de uma organização, com acesso controlado por papel (role) e escopos (scopes).
5 Roles (hierarquia estrita)
| Role | Nível | Descrição |
|---|---|---|
| owner | 1 | Criador/dono. Acesso implícito a todos os escopos. Imutável — não pode ser excluído nem rebaixado. |
| admin | 2 | Gerencia equipe: convida, remove, altera roles/scopes |
| member | 3 | Acesso conforme escopos atribuídos |
| guest | 4 | Acesso limitado — tipicamente apenas documents |
| pending | 5 | Convite enviado, aguardando aceitação |
11 Scopes
| Scope | Controla Acesso A |
|---|---|
organization | Detalhes da org, atualizar perfil |
finances | Faturas, notas fiscais |
orders | Histórico de pedidos |
licenses | Licenças, ativação, downloads |
tickets | Service requests (criar, visualizar) |
quotes | Propostas (visualizar, aceitar) |
contracts | Contratos, termos de SLA |
documents | Documentos compartilhados |
downloads | Downloads de produtos |
entitlements | Entitlements, environments, services |
admin | Operações administrativas (admin only) |
Extensível via filtro middag_collaborator_scopes.
Convite por Token
Fluxo: Admin envia convite → email com token → collaborator clica → define senha → login. Token tem TTL configurável. Role pending até aceitação.
Imutabilidade do Owner
- Owner não pode ser excluído
- Owner não pode ter role alterado
- Owner tem acesso implícito a todos os scopes (scopes ignorados)
- Transferência de ownership: operação administrativa especial
Limite de Collaborators com Scope tickets
Default: 5 collaborators com scope tickets por organization. Configurável via POLICY. Reflete termos de uso: "5 colaboradores por conta de suporte."
Responsabilidades do OrganizationService em REF-201-01.
Middleware Enforcement
Requisições à API REST são validadas em camadas: JWT → Organization → Role → Scope. Cada rota declara os scopes necessários; rotas sem declaração são bloqueadas (fail-closed). O header X-Middag-Company (middag_br / middag_global) funciona como filtro de dados, não como scope.
Detalhes completos em REF-201-01 §11.
Consequências
Positivas:
- Multi-tenancy real desde o início — não retrofit
- Clientes são organizações, não usuários WP — modelo B2B correto
- Dual Stripe/HubSpot IDs permitem operação dual-entity sem gambiarras
- RBAC granular (5 roles × 9 scopes) cobre cenários de equipe real
Negativas:
- Complexidade de manter isolamento multi-tenant em todas as queries
- Hierarquia de org até 3 níveis adiciona complexidade de consulta
- Owner imutável requer fluxo especial de transferência
Referências
- REF-201-01 — RBAC Roles & Scopes (matriz completa)
- ADR-101 — Product Vision (organization-first como diferencial)
- ADR-202 — Entitlement (pertence a Organization)
../reference/personas.md— Personas §2-4 (Admin, Cliente, Colaborador)