Files
DeskcommCRM/docs/prd/01-prd-platform-base.md
T
PessoaandClaude Opus 5 73857d4881 docs: a Vercel deixa de aparecer como onde o CRM roda e valida
O projeto do CRM na Vercel foi desvinculado do GitHub por decisao do dono: a
plataforma fica so com a landing page, em outro repositorio. Medido com a mesma
sonda nos dois lados — `gh api repos/.../commits/<sha>/status` devolve `Vercel`
no commit f65d04667 (antes) e vazio em a8c9e1ad3, 7168961ad e no head do #1081
(depois).

Com isso, dezenas de afirmacoes do repositorio publico viraram falsas. As que
falavam no presente sairam:

- mensagem automatica ao contribuinte, molde de PR, CONTRIBUTING e os espelhos
  na skill de contribuir prometiam um check "Vercel" vermelho que nao aparece
  mais. No lugar, a mensagem passa a dizer onde olhar o que trava o merge — os
  checks marcados Required no proprio PR, com a ressalva de que `--required` so
  lista os que ja reportaram;
- runbooks de operacao mandavam abrir o painel da plataforma e redeployar a
  main; passam a descrever o `.env` da instalacao e a recriacao dos conteineres;
- `lib/env.ts` mandava, no boot, ajustar variavel "na Vercel";
- specs e PRDs descreviam topologia, crons e guarda de segredo na plataforma;
- comentarios de codigo ancoravam decisoes vivas em premissa morta.

Registros datados (pesquisa, pitch, epicos, handoffs) nao foram reescritos:
ganharam uma linha dizendo que sao registro da fase hospedada.

O `vercel.ts` fica: ele serve quem hospeda um fork, e o gate
`tests/unit/cron-routes-scheduled.test.ts` continua reprovando divergencia de
rotas entre ele e o crontab do scheduler.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 15:00:03 -03:00

20 KiB
Raw Blame History

title, parent, version, status, date, owner, referencia_arquitetural
title parent version status date owner referencia_arquitetural
Sub-PRD 01 — Plataforma Base 00-prd-master.md 0.1 em revisão 2026-04-28 Rafael Melgaço docs/research/reference-synthesis.md

Sub-PRD 01 — Plataforma Base

Foundation do DeskcommCRM. Todo subsistema posterior (Customer 360, WhatsApp, Pipeline, IA, Nuvemshop) depende das capacidades aqui definidas. Profundidade técnica (schema, RLS policies, payloads de API) vai pra docs/specs/ na próxima fase.


1. Contexto & Posicionamento

A Plataforma Base resolve o problema fundacional: todo dado tocado pelo DeskcommCRM precisa estar autenticado, isolado por tenant, autorizado por role, auditado por mutação, e respeitar LGPD desde o primeiro request. Sem isso, qualquer feature em cima vira risco regulatório e operacional.

A Plataforma Base também sustenta a administração transversal da instalação. Quando uma pessoa administradora precisa acompanhar uma organização, o acesso operacional é uma sessão temporária com alvo, modo e prazo próprios; não é um bypass permanente nem uma membership implícita. O contrato vigente está em docs/support-sessions.md.

Esta camada é invisível pro cliente final mas governa todas as garantias de segurança, conformidade e operação multi-tenant do produto.


2. Escopo

Dentro do escopo deste sub-PRD

  1. Autenticação de usuários (humanos via UI, server-to-server via API)
  2. Modelo de tenancy (organizations, user_organizations, super-admin)
  3. RBAC com 4 roles canônicas + super-admin de plataforma
  4. Audit trail de toda mutação relevante
  5. Framework LGPD (consentimento, redact, data_request)
  6. Onboarding de tenant (mesmo que ainda não exposto publicamente)
  7. Convenções da API REST /api/v1/ (auth, idempotência, paginação, formato de erro, rate limit)

Fora do escopo deste sub-PRD (vão pra outros sub-PRDs)

  • Modelagem de cliente final / contatos / pedidos → Sub-PRD 02
  • Captura/envio de mensagens WhatsApp → Sub-PRD 03
  • Pipeline e tickets → Sub-PRD 04
  • IA, RAG, sentiment → Sub-PRD 05
  • Webhooks Nuvemshop → Sub-PRD 06

3. Capacidades Funcionais

3.1 Autenticação

O que provê. Login humano via Supabase Auth (email + senha + opcionalmente magic link); auth server-to-server via Bearer token (Authorization: Bearer tok_...); MFA TOTP forçado pra role admin e super-admin.

Princípios.

  • Sempre getUser() (valida JWT no backend), nunca getSession() (confia no cookie local)
  • API key NUNCA aceita em query string (vaza em logs de Vercel/CloudFlare)
  • Plaintext de Bearer token mostrado uma vez na criação; depois apenas hash SHA256 no DB
  • Session timeout de 1h com refresh rotation habilitado
  • Cookie SameSite=Strict, HttpOnly, Secure em produção

ACs principais.

  • Login com email/senha bem-sucedido devolve JWT com claim tenant_id
  • Tentativa de uso de token revogado retorna 401 com error.code='token_revoked'
  • Admin sem MFA é forçado a configurar TOTP no primeiro login
  • API key passada em query string retorna 400 com error.code='auth_in_query_forbidden'

3.2 Tenancy multi-tenant

O que provê. Isolamento de dados forte por tenant via Postgres Row-Level Security em toda tabela tenant-aware. Helper canônico fn_user_org_ids() retorna lista de orgs do usuário; policies usam essa função pra filtrar.

Princípios.

  • organization_id uuid not null references organizations(id) on delete cascade em toda tabela tenant-aware
  • Policy padrão tenant_isolation_<tabela>_all aplicada a todas
  • Service role bypassa RLS apenas em handlers de webhook e cron, e deve filtrar manualmente organization_id resolvido de fonte confiável (cookie, JWT, webhook secret, path token) — nunca do body
  • Roteamento de API pode usar header X-Tenant-ID ou subdomain (<tenant>.api.deskcomm.com); decisão final na Spec

ACs principais.

  • Cliente A não consegue ler nenhum recurso do cliente B em nenhum endpoint
  • Tentativa de inserir registro com organization_id diferente do JWT do usuário retorna 403
  • Teste automatizado de isolamento (cria 2 tenants + verifica não-vazamento) passa no CI antes de qualquer merge
  • Query do admin client com bypassed_rls=true é logada no audit trail

3.3 RBAC

O que provê. 4 roles canônicas hierarquicas dentro de cada tenant.

Role Hierarchy Permissões
viewer 1 GET em todos os recursos do tenant
agent 2 + POST/PATCH em leads e activities atribuídos a si; sem DELETE
manager 3 + DELETE leads; CRUD em pipelines e stages
admin 4 Tudo, incluindo gestão de api_tokens, webhooks e visualização de audit log

Princípios.

  • Roles vivem em user_organizations (junção user × org × role)
  • 1 usuário pode ter roles diferentes em orgs diferentes
  • Permissão por pipeline (user_pipeline_access) NÃO entra no MVP — adicionar quando cliente real pedir
  • Role mudança é evento auditado

ACs principais.

  • Viewer não consegue criar lead (403 forbidden_role)
  • Agent só consegue editar leads atribuídos a si (owner_user_id = self)
  • Audit trail registra mudança de role com who/from/to/when

3.4 Super-admin de plataforma

O que provê. Autoridade transversal para administrar a instalação e iniciar acompanhamento temporário de uma organização sem assumir a identidade de cliente.

Princípios.

  • A autoridade vive em platform_admins; scope limita o máximo efetivo e revogação encerra a continuidade.
  • Dados de uma organização são acompanhados por uma linha em platform_support_sessions, ligada ao ator e à auth.session_id, com modo full ou support_readonly e TTL máximo de uma hora.
  • A sessão projeta a organização e o papel efetivos sem criar user_organizations. Outra sessão do mesmo ator mantém seu próprio contexto, e direitos de plataforma preexistentes fora do alvo não são removidos.
  • support_readonly prevalece até sobre membership admin física no alvo; cercas de banco e guardas da aplicação bloqueiam efeitos sem paralisar workers ou outros usuários.
  • O início e cada uso reconfirmam autoridade, sessão, alvo, prazo e política de MFA. Expiração ou revogação exigem saída explícita; a saída restaura a organização anterior.
  • Operações pelas superfícies do aplicativo registram o ator real e support_session_id; não há promessa de auditoria de DML bruto fora dessas superfícies.

ACs principais.

  • A pessoa administradora escolhe edição ou somente leitura no detalhe da organização e vê banner com ação de saída durante todo o acompanhamento.
  • Outra sessão do mesmo ator não muda de organização. Expiração ou revogação retiram o snapshot até a saída; downgrade full → support_readonly retira escrita e estado de admin, mas mantém a leitura permitida na sessão ativa.
  • Somente leitura não marca inbox como lida, não executa mutações e continua restritiva mesmo se o ator for admin físico no alvo.
  • O acompanhamento termina pela posse da própria sessão, mesmo se a autoridade de plataforma tiver sido revogada.

Contrato completo e limites OAuth: docs/support-sessions.md.

3.5 Audit trail

O que provê. Log denso de toda mutação relevante (CRUD em leads, pipelines, contacts, mensagens, configurações, tokens, webhooks). Imutável após inserção. Visível pra admin do tenant e super-admin de plataforma.

Princípios.

  • Tabela api_audit_log registra: who (user_id, api_token_id, ip, user_agent), what (action canônica lead.created, token.revoked, etc.), which (resource_type, resource_id), when (created_at), metadata (diff, params relevantes)
  • Logging é fire-and-forget (nunca bloqueia request)
  • GET não-batch não é logado por padrão (volume); GET de export massivo SIM
  • Retenção 5 anos (boas práticas ANPD)
  • Audit log NÃO recebe RLS policy de UPDATE/DELETE — é append-only

ACs principais.

  • Toda mutação POST/PATCH/DELETE bem-sucedida gera 1 entrada de audit em ≤500ms p99
  • Audit log não pode ser editado nem deletado via API (só via DBA manual com double-confirmation)
  • Admin do tenant consulta audit log filtrável por actor, action, resource_type, date_range em endpoint dedicado
  • Falha em escrever audit log gera alerta operacional (Sentry/PagerDuty), mas não impede a mutação principal

3.6 LGPD framework

O que provê. Mecanismos pro tenant (e pra ANPD em última instância) exercerem direitos LGPD: consentimento granular, exportação de dados pessoais, anonimização ou exclusão.

Princípios.

  • Consentimento granular: contacts.consent jsonb com chaves marketing, transactional, profiling, cada uma com {granted_at, source, version}
  • Anonimização preferida sobre delete: vendas históricas precisam permanecer pro faturamento; nome/telefone/email do contato vira hash + token "Cliente Anonimizado #N"
  • Delete físico apenas quando solicitado e sem dependências (raro: pré-venda sem nenhum pedido)
  • Audit completo de toda operação em dados sensíveis (lgpd.data_request_received, lgpd.export_generated, lgpd.redact_executed, lgpd.consent_changed)
  • SLA: data_request entregue em D+7 dias úteis; redact executado em D+15
  • Imutabilidade: dados anonimizados não podem ser revertidos (decisão definitiva)

Endpoints (detalhe vai na Spec):

  • POST /api/v1/lgpd/data-request — recebe {contact_id | email | phone | cpf}, dispara job assíncrono que gera export estruturado (JSON + PDF assinado) e o entrega via email ou link assinado
  • POST /api/v1/lgpd/redact — recebe {contact_id, mode: 'anonymize' | 'delete'}, valida pré-condições, executa cascade
  • GET /api/v1/contacts/:id/consent — lê estado de consentimento
  • PATCH /api/v1/contacts/:id/consent — atualiza com audit

ACs principais.

  • Tenant admin solicita export de cliente X via UI → recebe PDF/JSON em D+7 com 100% dos dados pessoais armazenados
  • Anonimização cascade afeta: contact, conversations (preserva histórico), messages (mídia removida do storage), activities (mantém timestamps e tipos)
  • Tentativa de reverter anonimização retorna 403 lgpd_anonymization_irreversible
  • Audit do redact registra who, which contact, mode, cascaded_to=[conversations:N, messages:M, activities:K]

3.7 Criação e primeiro acesso de uma organização

O que provê. Em Administração → Gerenciar organizações, uma pessoa com autoridade de plataforma full cria a organização e define o responsável. A porta continua visível mesmo quando ela possui um único vínculo.

Princípios.

  • A criação valida UUID, payload, autoridade e MFA em dívida. Organização, vínculo admin aceito do ator criador e recibo idempotente confiável são gravados na mesma transação; falha intermediária reverte o conjunto.
  • A chave idempotente pertence ao ator e ao payload normalizado, vale por 24 horas e permite recuperar a mesma organização e o mesmo link após perda de resposta, sem repetir envio nem auditoria da criação. Recibo antigo ou editável não é autoridade.
  • Se o responsável é outra pessoa, o convite HMAC é emitido depois do commit. O link assinado de 24 horas é sempre exibido e pode ser copiado; ausência ou falha do Resend não desfaz a criação nem finge e-mail entregue.
  • O aceite serializa o vínculo. Replay de vínculo já ativo não altera papel ou interface; vínculo revogado só pode ser reativado por convite emitido depois da revogação.
  • O aceite ativa a organização convidada; troca normal continua sendo uma operação distinta, baseada em membership aceita e ativa.
  • OAuth, conexão WhatsApp e seed de pipeline são fluxos independentes; este contrato de criação não os declara concluídos.

ACs principais.

  • A criação devolve organização, validade, estado real do envio e link copiável mesmo sem Resend.
  • Repetir a mesma intenção dentro do TTL recupera o mesmo resultado; trocar o payload sob a mesma chave retorna conflito.
  • Responsável aceita o convite e entra na organização; replay não promove papel nem sobrescreve preferência alterada depois.
  • Falha da troca mantém cookie, contexto e dados da organização anterior e apresenta erro.

3.8 API base & convenções

O que provê. Convenções universais que toda rota /api/v1/ seguirá, em todo subsistema.

Aspecto Convenção
Versionamento Por path: /api/v1/, depois /api/v2/
Formato JSON snake_case em request e response
IDs UUID v4
Datas ISO-8601 UTC
Dinheiro _cents (bigint) + currency ISO-4217
Wrapper de sucesso { data: T, meta?: { cursor, has_more, total } }
Wrapper de erro { error: { code, message, details? } }
Paginação Cursor por default (cursor opaco base64 com HMAC)
Idempotência Header Idempotency-Key: <uuid> em POST de criação; TTL 24h
Rate limit Upstash Redis sliding window; headers X-RateLimit-* + Retry-After
Auth Cookie session (frontend) OU Authorization: Bearer tok_... (server-to-server)
Status codes 200 / 201 / 204 / 400 / 401 / 403 / 404 / 409 / 422 / 429 / 500
CORS Allowlist explícita por tenant; nunca *
Request ID Header X-Request-Id correlaciona com audit log

ACs principais.

  • Toda response de erro segue o wrapper { error: { code, message, ...} }
  • Idempotency-Key recebida 2x com mesmo body retorna mesma response sem duplicar efeito; com body diferente retorna 409 idempotency_conflict
  • Rate limit excedido retorna 429 com Retry-After e error.code='rate_limited'
  • Cliente recebe X-Request-Id em todo response e pode usá-lo pra suporte (audit log linka via esse ID)

4. Requisitos Não-Funcionais

4.1 Segurança

  • Toda comunicação HTTPS (TLS 1.3 mínimo)
  • Postgres com pgcrypto ativo pra encrypt at-rest de campos sensíveis quando aplicável
  • Sentry com beforeSend removendo headers/body sensíveis antes de enviar evento
  • Logs sanitizados: x-api-key, authorization, cookie, password, webhook_secret filtrados antes de gravar
  • INTERNAL_SECRET (cron) diferente do SUPABASE_SERVICE_ROLE_KEY
  • DNS rebinding protection ativa em endpoints sensíveis

4.2 Performance

  • p95 de auth check: <50ms
  • p95 de tenant resolution + RLS query simples: <100ms
  • p95 de mutação simples (POST/PATCH lead): <300ms
  • p95 de audit log write: <500ms (fire-and-forget)
  • Suporte concorrente: 100 RPS por tenant no MVP

4.3 Compliance

  • LGPD desde o dia 1 (vide §3.6)
  • Audit log retenção 5 anos
  • Backup diário do Postgres (Supabase) + retenção 30 dias
  • Documentação operacional (runbook LGPD) entregue antes do primeiro tenant em produção

4.4 Observabilidade

  • Sentry pra erros (com sanitização)
  • Métricas custom (latência, taxa de erro, audit log lag) em painel a definir na Spec
  • Health check endpoint público /api/v1/health (sem auth, retorna 200 + status de dependências)

5. Acceptance Criteria do sub-PRD

A Plataforma Base é considerada MVP-completa quando:

  1. ✅ 2 tenants podem ser criados pela porta administrativa com vínculo inicial e recibo idempotente atômicos; isolamento de dados é verificado por teste automatizado no CI
  2. ✅ MFA TOTP pode ser exigido pelas políticas independentes da plataforma e da organização; quem já possui fator verificado prova aal2 nas rotas protegidas
  3. ✅ Bearer token criado pelo admin permite chamada server-to-server, e tem audit log de criação/uso
  4. ✅ Endpoint LGPD data-request gera export JSON + PDF em ≤7 dias úteis pra um contato real
  5. ✅ Endpoint LGPD redact anonimiza um contato com cascade pra conversations/messages/activities, sem perda de histórico de pedidos
  6. ✅ Audit log captura todas as mutações listadas e não pode ser editado via API
  7. ✅ Super-admin inicia acompanhamento temporário em edição ou somente leitura, sai para o contexto anterior e mantém auditoria do ator real nas operações do aplicativo
  8. ✅ Rate limit funciona em endpoint crítico (login + criação de lead)
  9. ✅ Health check endpoint retorna 200 com status de Supabase, Redis e WAHA
  10. ✅ Documentação operacional (runbook LGPD + matriz RBAC + lista de eventos auditados) entregue

6. Dependências

Internas (outros sub-PRDs)

  • Nenhuma. Plataforma Base é foundation de todos os outros.

Externas

  • Supabase (Auth, Postgres, Storage) — projeto provisionado, plano Pro mínimo pra produção
  • Vercel AI Gateway — só o gateway de LLM, via AI_GATEWAY_API_KEY (pra Sub-PRDs futuros). Hospedagem não entra aqui: quem instala roda o CRM na própria infraestrutura
  • Upstash Redis — instância de produção pra rate limit
  • Sentry — projeto criado, com regras de sanitização aprovadas
  • Domínio + subdomínio admin.deskcomm.com (pra UI super-admin)

Decisões deferidas pra Spec

  • Tabela auxiliar platform_admins vs coluna is_platform_admin em auth.users
  • Roteamento por subdomain vs header X-Tenant-ID
  • Gerador de cursor (HMAC com qual chave?)
  • Política exata de retenção de mensagens por tenant (configurável dentro de bounds)

7. Riscos Específicos do sub-PRD

# Risco Mitigação
P1 RLS policy mal escrita vaza dados cross-tenant Templates de policy + linter SQL no CI + teste de isolamento obrigatório por tabela tenant-aware
P2 Service role key vaza em log/repo Variável de ambiente apenas; nunca em código; .gitleaks no pre-commit; rotação trimestral
P3 MFA TOTP perdido bloqueia admin Códigos de recuperação gerados na configuração; processo de reset via super-admin com audit duplo
P4 Audit log explode em volume e custa caro Retenção em hot storage 90 dias; rest em cold storage (S3) com lifecycle policy; sampling em GET-volume baixo
P5 Super-admin abusivo vê dados sem necessidade Toda ação loggeada com flag; revisão semanal pelo líder operacional; consideração futura de "modo restrito" exigindo justificativa por sessão
P6 LGPD data_request demora além de D+7 Job assíncrono com fila própria + alarme em D+5; runbook de escalação pra super-admin
P7 Onboarding manual erra config (webhook secret, role inicial) CLI script ou wizard guiado; validação automática pós-criação (ping em todos os endpoints essenciais)

8. Fora de Escopo (deste sub-PRD)

  • SSO empresarial (SAML, OIDC, Google Workspace) — entra em fase pós-MVP quando demanda enterprise surgir
  • 2FA por SMS — não recomendado (SIM swap); só TOTP/WebAuthn
  • Pentest formal externo — entra na Fase 1.5 (Hardening)
  • Certificações SOC 2, ISO 27001 — entram na Fase 2+ conforme demanda comercial
  • Multi-fator avançado (WebAuthn / passkey) — Fase 1.5 ou 2
  • Self-service de criação de tenant (signup público) — Fase SaaS
  • Permissão por pipeline (user_pipeline_access) — adicionar quando 1º cliente real pedir
  • Localização (multi-language) — produto começa só em PT-BR

9. Decisões deferidas pra Spec (Fase 3)

A serem decididas no spec correspondente (docs/specs/01-spec-platform-base.md):

  1. Schema SQL completo de organizations, user_organizations, auth.users extensions, api_tokens, api_audit_log, platform_admins (se virar tabela)
  2. Templates exatos de RLS policy por tabela
  3. Estrutura completa do payload de Bearer token (claims, escopos)
  4. Formato exato do cursor opaco (algoritmo HMAC, schema interno)
  5. Lista canônica de actions auditadas (ex: lead.created, token.revoked, consent.changed, redact.executed, etc.) — versão completa
  6. Esquema do export LGPD (estrutura JSON, layout do PDF)
  7. Fluxo de UI do super-admin (mockups na Spec)
  8. CLI ou wizard de onboarding de tenant
  9. Estratégia de cold storage de audit log (S3 + lifecycle policies)

Anexos

  • docs/research/reference-synthesis.md — pontos herdados (especialmente §4 Multi-tenancy, §6 API REST, §7 RBAC)
  • docs/prd/00-prd-master.md — visão geral
  • tasks/todo.md — fluxo de construção