arcadiasuite/docs/MAPA_TENANTS_ARCADIA.md

62 KiB

Arcádia Tenants — Mapa Completo da Gestão Multi-Tenant

Mapa da arquitetura multi-tenant da Arcádia Suite: hierarquia Master/Parceiro/Cliente, sistema de planos, ativação de módulos, empresas (Matriz/Filiais), comissões de parceiros, controle de acesso, e middleware de isolamento. Atualizado em: Março 2026


1. Visão Geral

A Arcádia Suite opera em modelo multi-tenant hierárquico com três níveis. Cada tenant possui um plano que define quais módulos da plataforma estão habilitados, e pode conter múltiplas empresas (CNPJ) para operações fiscais.

┌─────────────────────────────────────────────────────────────────────┐
│                      HIERARQUIA DE TENANTS                           │
│                                                                      │
│                    ┌──────────────┐                                  │
│                    │   MASTER     │  ← Operador da plataforma        │
│                    │              │  ← Vê tudo, controla tudo        │
│                    │  tenantType: │  ← Pode criar parceiros          │
│                    │  "master"    │  ← Pode excluir tenants          │
│                    └──────┬───────┘                                  │
│                           │                                          │
│              ┌────────────┼────────────┐                            │
│              ▼            ▼            ▼                            │
│     ┌──────────────┐ ┌──────────────┐ ┌──────────────┐             │
│     │  PARCEIRO A  │ │  PARCEIRO B  │ │  PARCEIRO C  │             │
│     │              │ │              │ │              │             │
│     │ tenantType:  │ │ Consultorias │ │ Integradores │             │
│     │ "partner"    │ │ Revendas     │ │ Franquias    │             │
│     │              │ │              │ │              │             │
│     │ partnerCode: │ │ comissão: %  │ │ plano:       │             │
│     │ "PARC-001"   │ │ sobre clientes│ │partner_pro  │             │
│     └──────┬───────┘ └──────┬───────┘ └──────┬───────┘             │
│            │                │                │                      │
│       ┌────┴────┐      ┌───┴───┐        ┌───┴───┐                 │
│       ▼         ▼      ▼       ▼        ▼       ▼                 │
│   ┌────────┐┌────────┐┌────────┐┌────────┐┌────────┐┌────────┐   │
│   │Cliente1││Cliente2││Cliente3││Cliente4││Cliente5││Cliente6│   │
│   │        ││        ││        ││        ││        ││        │   │
│   │tenant  ││tenant  ││tenant  ││tenant  ││tenant  ││tenant  │   │
│   │Type:   ││Type:   ││Type:   ││Type:   ││Type:   ││Type:   │   │
│   │"client"││"client"││"client"││"client"││"client"││"client"│   │
│   │        ││        ││        ││        ││        ││        │   │
│   │parent: ││parent: ││parent: ││parent: ││parent: ││parent: │   │
│   │Parc.A  ││Parc.A  ││Parc.B  ││Parc.B  ││Parc.C  ││Parc.C  │   │
│   │        ││        ││        ││        ││        ││        │   │
│   │Plano:  ││Plano:  ││Plano:  ││Plano:  ││Plano:  ││Plano:  │   │
│   │starter ││pro     ││free    ││enterpr.││starter ││pro     │   │
│   └────────┘└────────┘└────────┘└────────┘└────────┘└────────┘   │
└─────────────────────────────────────────────────────────────────────┘

Visibilidade por tipo:

Tipo Cria Exclui
Master Todos os tenants Parceiros e Clientes Qualquer (exceto master)
Partner Seu tenant + seus clientes Apenas clientes vinculados Nenhum
Client Apenas seu próprio tenant Nenhum Nenhum

2. Banco de Dados — Tabelas de Tenant

2.1 — tenants (Tabela Principal)

┌──────────────────────────────────────────────────────────────────┐
│  tenants                                                          │
│  Tabela: "tenants" — shared/schema.ts:849                        │
│                                                                   │
│  ┌─────────── Identificação ──────────────────┐                  │
│  │ id              serial PK                   │                  │
│  │ name            text NOT NULL                │                  │
│  │ slug            text UNIQUE                  │                  │
│  │ email           text                         │                  │
│  │ phone           text                         │                  │
│  │ logoUrl         text                         │                  │
│  └─────────────────────────────────────────────┘                  │
│                                                                   │
│  ┌─────────── Hierarquia ─────────────────────┐                  │
│  │ tenantType      "master" | "partner" |      │                  │
│  │                 "client"                     │                  │
│  │ parentTenantId  integer (self-ref FK)        │                  │
│  │ partnerCode     text (código único parceiro) │                  │
│  │ commissionRate  numeric(5,2) (% comissão)    │                  │
│  └─────────────────────────────────────────────┘                  │
│                                                                   │
│  ┌─────────── Plano e Limites ────────────────┐                  │
│  │ plan            "free" | "starter" | "pro"  │                  │
│  │                 | "enterprise" |            │                  │
│  │                 "partner_starter" |          │                  │
│  │                 "partner_pro"                │                  │
│  │ status          "active" | "trial" |        │                  │
│  │                 "suspended" | "cancelled"   │                  │
│  │ maxUsers        integer (default 5)          │                  │
│  │ maxStorageMb    integer (default 1000)        │                  │
│  │ features        JSONB → TenantFeatures       │  ← Módulos      │
│  └─────────────────────────────────────────────┘                  │
│                                                                   │
│  ┌─────────── Billing ────────────────────────┐                  │
│  │ billingEmail    text                         │                  │
│  │ trialEndsAt     timestamp                    │                  │
│  └─────────────────────────────────────────────┘                  │
│                                                                   │
│  ┌─────────── Dados Empresariais ─────────────┐                  │
│  │ cnpj            text                         │                  │
│  │ tradeName       text                         │                  │
│  │ address         text                         │                  │
│  │ city, state     text                         │                  │
│  │ segment         text                         │                  │
│  │ notes, source   text                         │                  │
│  │ commercialContact / commercialPhone          │                  │
│  └─────────────────────────────────────────────┘                  │
│                                                                   │
│  ┌─────────── Metadata ───────────────────────┐                  │
│  │ settings        text (JSON config)           │                  │
│  │ createdAt       timestamp                    │                  │
│  │ updatedAt       timestamp                    │                  │
│  └─────────────────────────────────────────────┘                  │
└──────────────────────────────────────────────────────────────────┘

2.2 — TenantFeatures (JSONB — Sistema de Módulos)

O campo features na tabela tenants é um JSONB que controla quais módulos da Arcádia estão habilitados para cada tenant. O tipo é definido em shared/schema.ts:821 e espelhado no frontend em client/src/hooks/use-tenant-features.ts:3.

┌──────────────────────────────────────────────────────────────────┐
│  TenantFeatures (JSONB)                                           │
│                                                                   │
│  ┌─────────── Módulos Booleanos ──────────────┐                  │
│  │                                             │                  │
│  │  ide           → IDE integrada              │                  │
│  │  whatsapp      → WhatsApp multi-sessão      │                  │
│  │  crm           → CRM completo               │                  │
│  │  erp           → SOE/ERP                     │                  │
│  │  bi            → Business Intelligence       │                  │
│  │  manus         → IA Manus (GPT-4o)          │                  │
│  │  centralApis   → APIs centrais              │                  │
│  │  centralApisManage → Gerenciar APIs          │                  │
│  │  comunidades   → Chat interno               │                  │
│  │  biblioteca    → Biblioteca de conhecimento  │                  │
│  │  bibliotecaPublish → Publicar na biblioteca  │                  │
│  │  suporteN3     → Suporte nível 3            │                  │
│  │  retail        → Módulo Varejo              │                  │
│  │  plus          → ERP Plus (Laravel)          │                  │
│  │  fisco         → Motor Fiscal               │                  │
│  │  cockpit       → Cockpit executivo          │                  │
│  │  compass       → Process Compass            │                  │
│  │  production    → Módulo Produção            │                  │
│  │  support       → Módulo Suporte             │                  │
│  │  xosCrm        → XOS CRM (Kanban)           │                  │
│  │                                             │                  │
│  └─────────────────────────────────────────────┘                  │
│                                                                   │
│  ┌─────────── Configurações Numéricas ────────┐                  │
│  │                                             │                  │
│  │  whatsappSessions  → Nº sessões WA (0-N)   │                  │
│  │  maxChannels       → Nº canais permitidos   │                  │
│  │                                             │                  │
│  └─────────────────────────────────────────────┘                  │
│                                                                   │
│  ┌─────────── Configurações de Texto ─────────┐                  │
│  │                                             │                  │
│  │  ideMode       → "none" | "no-code" |       │                  │
│  │                  "low-code" | "pro-code"    │                  │
│  │  manusTools[]  → Lista de tools habilitadas │                  │
│  │                                             │                  │
│  └─────────────────────────────────────────────┘                  │
└──────────────────────────────────────────────────────────────────┘

2.3 — tenant_empresas (Matriz/Filiais)

Cada tenant pode ter múltiplas empresas (CNPJs) cadastradas — essencial para operações fiscais (NF-e/NFC-e) por filial.

┌──────────────────────────────────────────────────────────────────┐
│  tenant_empresas                                                  │
│  Tabela: "tenant_empresas" — shared/schema.ts:889                │
│                                                                   │
│  ┌─────────── Identificação ──────────────────┐                  │
│  │ id              serial PK                   │                  │
│  │ tenantId        FK → tenants.id (CASCADE)   │                  │
│  │ razaoSocial     text NOT NULL                │                  │
│  │ nomeFantasia    text                         │                  │
│  │ cnpj            text NOT NULL                │                  │
│  │ ie              text (inscrição estadual)    │                  │
│  │ im              text (inscrição municipal)   │                  │
│  │ email, phone    text                         │                  │
│  │ tipo            "matriz" | "filial"          │                  │
│  │ status          "active" | "inactive"        │                  │
│  └─────────────────────────────────────────────┘                  │
│                                                                   │
│  ┌─────────── Endereço ───────────────────────┐                  │
│  │ cep, logradouro, numero, complemento,      │                  │
│  │ bairro, cidade, uf, codigoIbge             │                  │
│  └─────────────────────────────────────────────┘                  │
│                                                                   │
│  ┌─────────── Fiscal ─────────────────────────┐                  │
│  │ regimeTributario  "simples" | "presumido"   │                  │
│  │                   | "real"                  │                  │
│  │ certificadoDigitalId  FK certificado        │                  │
│  │ ambienteFiscal  "producao" | "homologacao"  │                  │
│  │ serieNfe        integer (default 1)          │                  │
│  │ serieNfce       integer (default 1)          │                  │
│  │ plusEmpresaId   integer (link ERP Plus)      │                  │
│  └─────────────────────────────────────────────┘                  │
│                                                                   │
│  ┌─────────── Metadata ───────────────────────┐                  │
│  │ createdAt, updatedAt  timestamp              │                  │
│  └─────────────────────────────────────────────┘                  │
└──────────────────────────────────────────────────────────────────┘

Uso típico:

Tenant "Empresa ABC" (id: 5)
├── Empresa Matriz: "ABC Comércio LTDA" (CNPJ: 12.345.678/0001-00)
│   regime: simples, ambiente: producao, série NF-e: 1
├── Filial SP: "ABC Comércio SP" (CNPJ: 12.345.678/0002-81)
│   regime: simples, ambiente: producao, série NF-e: 2
└── Filial RJ: "ABC Comércio RJ" (CNPJ: 12.345.678/0003-62)
    regime: simples, ambiente: homologacao, série NF-e: 1

2.4 — tenant_users (Membership)

┌──────────────────────────────────────────────────────────────────┐
│  tenant_users                                                     │
│  Tabela: "tenant_users" — shared/schema.ts:923                   │
│                                                                   │
│  id           serial PK                                           │
│  tenantId     FK → tenants.id (CASCADE)                           │
│  userId       FK → users.id (CASCADE)                             │
│  role         "owner" | "admin" | "member"                        │
│  isOwner      "true" | "false"                                    │
│  createdAt    timestamp                                           │
│                                                                   │
│  → Link N:N entre users e tenants                                 │
│  → Um usuário pode pertencer a múltiplos tenants                  │
│  → Cada tenant tem um owner + admins + members                    │
└──────────────────────────────────────────────────────────────────┘

2.5 — tenant_plans (Planos Disponíveis)

┌──────────────────────────────────────────────────────────────────┐
│  tenant_plans                                                     │
│  Tabela: "tenant_plans" — shared/schema.ts:933                   │
│                                                                   │
│  id            serial PK                                          │
│  code          text UNIQUE ("free", "starter", "pro",             │
│                "enterprise", "partner_starter", "partner_pro")    │
│  name          text NOT NULL                                      │
│  description   text                                               │
│  tenantType    "master" | "partner" | "client"                    │
│  maxUsers      integer (default 5)                                │
│  maxStorageMb  integer (default 1000)                             │
│  features      JSONB → TenantFeatures                             │
│  monthlyPrice  integer (centavos)                                 │
│  yearlyPrice   integer (centavos)                                 │
│  trialDays     integer (default 14)                               │
│  isActive      "true" | "false"                                   │
│  sortOrder     integer                                            │
│  createdAt     timestamp                                          │
└──────────────────────────────────────────────────────────────────┘

2.6 — partner_clients (Relacionamento Parceiro↔Cliente)

┌──────────────────────────────────────────────────────────────────┐
│  partner_clients                                                  │
│  Tabela: "partner_clients" — shared/schema.ts:951                │
│                                                                   │
│  id              serial PK                                        │
│  partnerId       FK → tenants.id (CASCADE)                        │
│  clientId        FK → tenants.id (CASCADE)                        │
│  commissionRate  numeric(5,2) — Override do rate do parceiro      │
│  status          "active" | "suspended" | "ended"                 │
│  notes           text                                             │
│  startedAt       timestamp                                        │
│  endedAt         timestamp                                        │
└──────────────────────────────────────────────────────────────────┘

2.7 — partner_commissions (Comissões dos Parceiros)

┌──────────────────────────────────────────────────────────────────┐
│  partner_commissions                                              │
│  Tabela: "partner_commissions" — shared/schema.ts:963            │
│                                                                   │
│  id               serial PK                                       │
│  partnerId        FK → tenants.id (CASCADE)                       │
│  clientId         FK → tenants.id (CASCADE)                       │
│  referenceMonth   text ("2026-01", "2026-02", ...)                │
│  clientPlanCode   text (código do plano do cliente)                │
│  clientPlanValue  integer (valor do plano em centavos)             │
│  commissionRate   numeric(5,2) NOT NULL                           │
│  commissionValue  integer NOT NULL (valor em centavos)             │
│  status           "pending" | "approved" | "paid" | "cancelled"   │
│  approvedAt       timestamp                                       │
│  paidAt           timestamp                                       │
│  paymentReference text                                            │
│  createdAt        timestamp                                       │
│                                                                   │
│  Fluxo: pending → approved → paid                                 │
│                                                                   │
│  Exemplo:                                                         │
│  Parceiro A tem Cliente X no plano "pro" (R$ 299/mês)            │
│  commissionRate: 20%                                              │
│  commissionValue: 5980 centavos (R$ 59,80)                        │
└──────────────────────────────────────────────────────────────────┘

3. Planos Pré-definidos (Seed)

A rota POST /api/admin/plans/seed cria os 6 planos padrão:

┌─────────────────────────────────────────────────────────────────────┐
│                        PLANOS PARA CLIENTES                          │
├────────────┬──────────┬──────────┬──────────────────────────────────┤
│ Plano      │ Preço/mês│ Usuários │ Módulos                          │
├────────────┼──────────┼──────────┼──────────────────────────────────┤
│ Gratuito   │ R$ 0     │ 2        │ erp, crm                         │
│ (free)     │          │          │                                  │
├────────────┼──────────┼──────────┼──────────────────────────────────┤
│ Starter    │ R$ 99    │ 5        │ erp, crm, bi, fisco,             │
│            │          │          │ whatsapp, compass                │
├────────────┼──────────┼──────────┼──────────────────────────────────┤
│ Pro        │ R$ 299   │ 15       │ erp, crm, bi, fisco, retail,     │
│            │          │          │ plus, whatsapp, manus, cockpit,  │
│            │          │          │ compass, support, biblioteca     │
├────────────┼──────────┼──────────┼──────────────────────────────────┤
│ Enterprise │ R$ 999   │ 100      │ TODOS os módulos                 │
│            │          │ 50GB     │ (erp, crm, bi, fisco, retail,    │
│            │          │          │ plus, whatsapp, manus, ide,      │
│            │          │          │ cockpit, compass, production,    │
│            │          │          │ support, xosCrm, centralApis,    │
│            │          │          │ comunidades, biblioteca)         │
└────────────┴──────────┴──────────┴──────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────┐
│                       PLANOS PARA PARCEIROS                          │
├──────────────────┬──────────┬──────────┬────────────────────────────┤
│ Plano            │ Preço/mês│ Usuários │ Módulos                    │
├──────────────────┼──────────┼──────────┼────────────────────────────┤
│ Parceiro Starter │ R$ 199   │ 10       │ erp, crm, bi, fisco,       │
│                  │          │          │ retail, whatsapp, compass,  │
│                  │          │          │ support                    │
├──────────────────┼──────────┼──────────┼────────────────────────────┤
│ Parceiro Pro     │ R$ 499   │ 50       │ TODOS os módulos           │
│                  │          │ 25GB     │ (igual Enterprise)         │
└──────────────────┴──────────┴──────────┴────────────────────────────┘

4. Sistema de Papéis (Roles)

A Arcádia opera com dois níveis de papéis que se complementam:

┌─────────────────────────────────────────────────────────────────────┐
│                    SISTEMA DUPLO DE ROLES                            │
│                                                                      │
│  ┌─────────── Papel do Sistema (users.role) ──────────────────┐    │
│  │                                                             │    │
│  │  "master"  → Superadmin, acesso total, bypass de tenant    │    │
│  │  "admin"   → Administrador, acessa /api/admin/*            │    │
│  │  "user"    → Usuário padrão, sem acesso admin              │    │
│  │                                                             │    │
│  │  Verificado no middleware global de admin:                  │    │
│  │  if (role !== "admin" && role !== "master") → 403           │    │
│  └─────────────────────────────────────────────────────────────┘    │
│                                                                      │
│  ┌─────────── Papel no Tenant (tenant_users.role) ────────────┐    │
│  │                                                             │    │
│  │  "owner"   → Dono do tenant, criador, full control         │    │
│  │  "admin"   → Administrador do tenant                       │    │
│  │  "member"  → Membro comum, acesso operacional              │    │
│  │                                                             │    │
│  │  Usado para scoping de dados e permissões intra-tenant     │    │
│  └─────────────────────────────────────────────────────────────┘    │
│                                                                      │
│  Combinação no login (getEnrichedUser):                              │
│  user.role + user.tenantId + user.tenantType + user.tenantRole       │
└─────────────────────────────────────────────────────────────────────┘

5. Controle de Acesso — Helpers

O backend implementa dois helpers essenciais em server/admin/routes.ts:

┌─────────────────────────────────────────────────────────────────────┐
│  getAllowedTenantIds(user)                                            │
│                                                                      │
│  Retorna os IDs de tenants que o usuário pode acessar:              │
│                                                                      │
│  • master      → null (acesso total, sem filtro)                    │
│  • partner     → [seu tenantId, ...clientIds vinculados]            │
│  • client      → [apenas seu tenantId]                              │
│                                                                      │
│  Usado em: GET /tenants, GET /partner-clients, GET /commissions,    │
│  GET /empresas, GET /tenants/hierarchy                               │
└─────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────┐
│  canAccessTenant(user, tenantId)                                     │
│                                                                      │
│  Verifica se o usuário pode operar sobre um tenant específico:      │
│                                                                      │
│  • master → true (sempre)                                            │
│  • partner → true se tenantId ∈ getAllowedTenantIds()               │
│  • client → true apenas se tenantId === user.tenantId               │
│                                                                      │
│  Usado em: PATCH /tenants/:id, DELETE /empresas/:id,                │
│  POST /empresas, etc.                                                │
└─────────────────────────────────────────────────────────────────────┘

6. Middleware de Módulos (requireModule)

O middleware requireModule em server/retail/routes.ts:25 bloqueia endpoints quando um módulo não está ativo para o tenant:

┌─────────────────────────────────────────────────────────────────────┐
│  requireModule(moduleKey: keyof TenantFeatures)                      │
│                                                                      │
│  Fluxo:                                                              │
│  1. Identifica tenantId do usuário logado                           │
│  2. Busca tenant no banco                                            │
│  3. Verifica features[moduleKey] === true                            │
│  4. Se false → 403 com mensagem:                                    │
│     {                                                                │
│       error: "Módulo 'X' não está ativo para este tenant",          │
│       moduleKey: "plus",                                             │
│       action: "Ative o módulo em Admin → Módulos"                   │
│     }                                                                │
│                                                                      │
│  Exemplo de uso:                                                     │
│  router.post("/plus/sync/customers",                                │
│    requireModule("plus"),     ← Bloqueia se Plus não está ativo     │
│    async (req, res) => { ... }                                      │
│  );                                                                  │
└─────────────────────────────────────────────────────────────────────┘

7. Hook Frontend (useTenantFeatures)

O hook useTenantFeatures() em client/src/hooks/use-tenant-features.ts fornece acesso às features do tenant no frontend:

┌─────────────────────────────────────────────────────────────────────┐
│  useTenantFeatures()                                                 │
│                                                                      │
│  Fonte: GET /api/soe/tenant/modules                                 │
│  Cache: 60 segundos (staleTime: 60000)                              │
│                                                                      │
│  Retorna:                                                            │
│  {                                                                   │
│    features: TenantFeatures,  ← Objeto completo de features         │
│    isLoading: boolean,                                               │
│    plan: string,              ← Código do plano atual                │
│    isEnabled: (key) => bool,  ← Verificação rápida                  │
│  }                                                                   │
│                                                                      │
│  Defaults (quando não logado / sem tenant):                         │
│  ide: true, crm: true, erp: true, manus: true, compass: true       │
│  Todos os demais: false                                              │
│                                                                      │
│  Uso no componente:                                                  │
│  const { isEnabled } = useTenantFeatures();                          │
│  if (isEnabled("bi")) { /* mostra menu BI */ }                      │
│  if (isEnabled("retail")) { /* mostra módulo varejo */ }            │
└─────────────────────────────────────────────────────────────────────┘

8. Interface de Administração

8.1 — Admin.tsx (Página Principal)

┌─────────────────────────────────────────────────────────────────────┐
│  Admin.tsx — client/src/pages/Admin.tsx (2.635 linhas)               │
│  Rota: /admin                                                        │
│                                                                      │
│  6 Abas:                                                             │
│  ┌─────────────┬──────────┬────────────┬───────────┬──────────────┐ │
│  │ Conexões    │ Tarefas  │ Knowledge  │ Bibliotecas│ Módulos     │ │
│  │             │          │            │            │             │ │
│  │ WhatsApp    │ Dev      │ Knowledge  │ Conteúdo   │ Ativação    │ │
│  │ ERPNext     │ Center   │ Graph      │ Docs       │ por tenant  │ │
│  │ APIs        │ Pipeline │ Q&A        │ Templates  │ Toggle on/  │ │
│  │             │          │            │            │ off módulos │ │
│  └─────────────┴──────────┴────────────┴───────────┴──────────────┘ │
│  ┌─────────────┐                                                     │
│  │Casa de      │                                                     │
│  │Máquinas     │                                                     │
│  │             │                                                     │
│  │ Status dos  │                                                     │
│  │ motores     │                                                     │
│  │ (:8002-8006)│                                                     │
│  └─────────────┘                                                     │
│                                                                      │
│  Aba "Módulos" renderiza: <MultiTenantSection />                    │
└─────────────────────────────────────────────────────────────────────┘

8.2 — MultiTenantSection (Gestão Completa)

┌─────────────────────────────────────────────────────────────────────┐
│  MultiTenantSection.tsx (1.486 linhas)                               │
│  client/src/components/MultiTenantSection.tsx                        │
│                                                                      │
│  4 Abas internas:                                                    │
│                                                                      │
│  ┌─ Tenants ──────────────────────────────────────────────────┐     │
│  │                                                             │     │
│  │  Lista de tenants com:                                      │     │
│  │  • Nome, tipo (Master/Parceiro/Cliente)                    │     │
│  │  • Plano atual e status                                     │     │
│  │  • Nº de filhos (childCount)                                │     │
│  │  • Tenant pai (parentTenant)                                │     │
│  │  • Ações: Editar, Ativar/Desativar módulos                 │     │
│  │                                                             │     │
│  │  Formulário de criação:                                     │     │
│  │  • Nome, email, phone                                       │     │
│  │  • Tipo (master/partner/client)                             │     │
│  │  • Plano (seleciona do tenant_plans)                        │     │
│  │  • Tenant pai (para hierarquia)                             │     │
│  │  • Features auto-preenchidas pelo plano selecionado        │     │
│  │  • Toggle individual de cada módulo                        │     │
│  │                                                             │     │
│  └─────────────────────────────────────────────────────────────┘     │
│                                                                      │
│  ┌─ Planos ───────────────────────────────────────────────────┐     │
│  │                                                             │     │
│  │  CRUD de planos com:                                        │     │
│  │  • Código, nome, descrição                                  │     │
│  │  • Tipo de tenant (client/partner)                          │     │
│  │  • Preço mensal e anual (centavos)                          │     │
│  │  • Max usuários e storage                                   │     │
│  │  • Features (toggle de cada módulo)                         │     │
│  │  • Botão "Seed" para criar planos padrão                   │     │
│  │  • Botão "Propagar" para aplicar features do plano          │     │
│  │    a todos os tenants que usam esse plano                   │     │
│  │                                                             │     │
│  └─────────────────────────────────────────────────────────────┘     │
│                                                                      │
│  ┌─ Comissões ────────────────────────────────────────────────┐     │
│  │                                                             │     │
│  │  Lista de comissões de parceiros:                           │     │
│  │  • Parceiro, Cliente, Mês referência                        │     │
│  │  • Valor do plano, taxa de comissão, valor da comissão     │     │
│  │  • Status (pending → approved → paid)                      │     │
│  │  • Ações: Aprovar, Marcar como paga                        │     │
│  │                                                             │     │
│  └─────────────────────────────────────────────────────────────┘     │
│                                                                      │
│  ┌─ Empresas ─────────────────────────────────────────────────┐     │
│  │                                                             │     │
│  │  EmpresasSubSection:                                        │     │
│  │  • Lista de empresas (Matriz/Filiais) por tenant            │     │
│  │  • CNPJ, Razão Social, Nome Fantasia                        │     │
│  │  • IE, IM, Regime Tributário                                │     │
│  │  • Endereço completo (CEP, logradouro, cidade, UF)         │     │
│  │  • Config Fiscal (ambiente, série NF-e, série NFC-e)       │     │
│  │  • Link com ERP Plus (plusEmpresaId)                        │     │
│  │  • Ações: Criar, Editar, Excluir                           │     │
│  │                                                             │     │
│  └─────────────────────────────────────────────────────────────┘     │
└─────────────────────────────────────────────────────────────────────┘

9. API REST Completa (/api/admin/*)

Tenants

Método Endpoint Função Acesso
GET /tenants Lista tenants (filtrado por acesso) master/partner/client
POST /tenants Cria tenant (resolve features do plano) master/admin
PATCH /tenants/:id Atualiza tenant (canAccessTenant) master/partner
DELETE /tenants/:id Exclui tenant (proteção master) somente master
GET /tenants/hierarchy Árvore hierárquica de tenants master/partner
GET /tenants/stats Estatísticas (total, por tipo, por status) master/admin

Planos

Método Endpoint Função
GET /plans Lista todos os planos
POST /plans Cria novo plano
PATCH /plans/:id Atualiza plano
DELETE /plans/:id Exclui plano
POST /plans/:id/propagate Propaga features do plano para todos os tenants que o usam
POST /plans/seed Cria 6 planos padrão

Parceiro-Cliente

Método Endpoint Função
GET /partner-clients Lista relacionamentos parceiro↔cliente
POST /partner-clients Cria vínculo parceiro↔cliente

Comissões de Parceiros

Método Endpoint Função
GET /commissions Lista comissões (filtro por partnerId, status)
PATCH /commissions/:id/approve Aprova comissão
PATCH /commissions/:id/pay Marca como paga

Empresas (Matriz/Filiais)

Método Endpoint Função
GET /empresas Lista empresas (filtro por tenantId + acesso)
GET /empresas/:id Detalhe da empresa
POST /empresas Cria empresa (verifica canAccessTenant)
PATCH /empresas/:id Atualiza empresa
DELETE /empresas/:id Exclui empresa

Outros Admin

Método Endpoint Função
GET /profiles Lista perfis de usuários
POST /profiles Cria perfil
PATCH /profiles/:id Atualiza perfil
DELETE /profiles/:id Exclui perfil
GET /users Lista usuários (com tenant info)
PATCH /users/:id Atualiza usuário
PATCH /users/:id/status Altera status do usuário
PATCH /partners/:id/status Altera status de parceiro
PATCH /clients/:id/status Altera status de cliente
GET /stats Estatísticas gerais (tenants, users, leads)
GET /libraries Lista bibliotecas de conteúdo

Total: 33 endpoints de administração


10. Fluxo Completo — Onboarding de Tenant

┌──────────┐    ┌────────────┐    ┌──────────────┐    ┌──────────────┐
│  1. CRIAR │───▶│ 2. PLANO   │───▶│ 3. FEATURES  │───▶│ 4. EMPRESAS  │
│  TENANT   │    │            │    │              │    │              │
│           │    │ Seleciona  │    │ Auto-resolve │    │ Cadastra     │
│ POST      │    │ plano      │    │ do plano ou  │    │ Matriz       │
│ /admin/   │    │ (free,     │    │ toggle       │    │ + Filiais    │
│ tenants   │    │ starter,   │    │ individual   │    │              │
│           │    │ pro, etc)  │    │ de módulos   │    │ CNPJ, IE,    │
│ name,     │    │            │    │              │    │ endereço,    │
│ email,    │    │ maxUsers   │    │ ide: true    │    │ regime       │
│ type      │    │ maxStorage │    │ crm: true    │    │ tributário,  │
│           │    │ preço      │    │ bi: false    │    │ certificado  │
│           │    │            │    │ ...          │    │ digital      │
└──────────┘    └────────────┘    └──────────────┘    └──────────────┘
                                                              │
                                                              ▼
┌──────────────┐    ┌──────────────┐    ┌──────────────────────────┐
│ 5. VINCULAR  │    │ 6. COMISSÕES │    │ 7. USUÁRIOS              │
│ PARCEIRO     │    │              │    │                          │
│ (se partner) │    │ Automáticas  │    │ Convida users            │
│              │    │ mensais      │    │ tenant_users             │
│ POST /admin/ │    │ baseadas no  │    │ roles: owner/admin/      │
│ partner-     │    │ plano do     │    │ member                   │
│ clients      │    │ cliente      │    │                          │
│              │    │              │    │ Scoping automático       │
│ partnerId    │    │ pending →    │    │ de todos os dados        │
│ clientId     │    │ approved →   │    │ por tenantId             │
│ commission%  │    │ paid         │    │                          │
└──────────────┘    └──────────────┘    └──────────────────────────┘

11. Propagação de Plano

Quando um plano é atualizado, a feature de propagação atualiza todos os tenants que usam esse plano:

┌─────────────────────────────────────────────────────────────────────┐
│  POST /api/admin/plans/:id/propagate                                 │
│                                                                      │
│  1. Busca o plano por ID                                            │
│  2. Pega features, maxUsers, maxStorageMb do plano                  │
│  3. Atualiza TODOS os tenants onde plan === plan.code:              │
│     UPDATE tenants SET                                               │
│       features = plan.features,                                      │
│       maxUsers = plan.maxUsers,                                      │
│       maxStorageMb = plan.maxStorageMb                               │
│     WHERE plan = 'pro'                                               │
│  4. Retorna: { propagated: 15, planCode: "pro" }                    │
│                                                                      │
│  Exemplo:                                                            │
│  Plano "pro" ganha módulo "production" →                            │
│  Propagar → 15 tenants "pro" recebem production: true               │
└─────────────────────────────────────────────────────────────────────┘

12. Isolamento de Dados

Toda query de dados respeita o escopo do tenant:

┌─────────────────────────────────────────────────────────────────────┐
│  ISOLAMENTO POR tenantId                                             │
│                                                                      │
│  Padrão em todas as queries:                                         │
│                                                                      │
│  const tenantId = (req.user as any).tenantId;                       │
│  const data = await db.select()                                      │
│    .from(tabela)                                                     │
│    .where(eq(tabela.tenantId, tenantId));                            │
│                                                                      │
│  Tabelas com tenantId:                                               │
│  • tenants (hierarquia)        • crm_channels                       │
│  • tenant_empresas             • crm_threads                        │
│  • crm_leads                   • crm_events                         │
│  • crm_clients                 • crm_campaigns                      │
│  • crm_opportunities           • crm_products                       │
│  • crm_partners                • crm_contracts                      │
│  • crm_pipeline_stages         • crm_commission_rules               │
│  • crm_proposals               • crm_quick_messages                 │
│  • retail_activity_feed        • valuation_*                         │
│                                                                      │
│  Resultado: Dados do Tenant A NUNCA são vistos pelo Tenant B        │
└─────────────────────────────────────────────────────────────────────┘

13. Arquivos-Chave

Arquivo Função Linhas
shared/schema.ts (L821-977) TenantFeatures type + 6 tabelas tenant ~160
server/admin/routes.ts API admin (33 endpoints) 876
client/src/pages/Admin.tsx Página admin (6 abas) 2.635
client/src/components/MultiTenantSection.tsx Gestão multi-tenant (4 sub-abas) 1.486
client/src/hooks/use-tenant-features.ts Hook de features no frontend 59
server/retail/routes.ts (L25) Middleware requireModule ~25
server/storage.ts (getEnrichedUser) Enriquece user com tenant info

14. Resumo Visual

┌─────────────────────────────────────────────────────────────────────┐
│                  ARCÁDIA MULTI-TENANT STACK                          │
│                                                                      │
│  ┌───── Autenticação ──────────────────────────────────────────┐   │
│  │  Login → getEnrichedUser → user + tenantId + tenantType     │   │
│  │                            + tenantRole + features           │   │
│  └─────────────────────────────────────────┬───────────────────┘   │
│                                             │                       │
│  ┌─────────────────────────────────────────▼───────────────────┐   │
│  │  Middleware                                                  │   │
│  │  ┌──────────┐  ┌─────────────┐  ┌────────────────────┐     │   │
│  │  │requireAuth│  │requireModule │  │getAllowedTenantIds │     │   │
│  │  │role check │  │feature check │  │canAccessTenant     │     │   │
│  │  └──────────┘  └─────────────┘  └────────────────────┘     │   │
│  └─────────────────────────────────────────┬───────────────────┘   │
│                                             │                       │
│  ┌─────────────────────────────────────────▼───────────────────┐   │
│  │  API /api/admin/*                                            │   │
│  │  33 endpoints: Tenants, Plans, Empresas, Comissões          │   │
│  └─────────────────────────────────────────┬───────────────────┘   │
│                                             │                       │
│  ┌─────────────────────────────────────────▼───────────────────┐   │
│  │  PostgreSQL                                                  │   │
│  │  6 tabelas: tenants, tenant_users, tenant_plans,            │   │
│  │  tenant_empresas, partner_clients, partner_commissions      │   │
│  └─────────────────────────────────────────────────────────────┘   │
│                                                                      │
│  ┌───── Frontend ──────────────────────────────────────────────┐   │
│  │  Admin.tsx (6 abas) → MultiTenantSection (4 sub-abas)       │   │
│  │  useTenantFeatures() hook → GET /api/soe/tenant/modules     │   │
│  └─────────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────────┘