> ## Documentation Index
> Fetch the complete documentation index at: https://docs.switchbord.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Arquitetura da Plataforma

> Limites de serviço, topologia de runtime e modelo de deployment.

# Arquitetura da Plataforma

O Switchbord é implantado como uma aplicação Next.js multi-tenant na Vercel, com o Supabase como base para persistência, autenticação e realtime, e um worker hospedado na Railway para processamento em segundo plano. Não existe um serviço de control-plane separado — esse caminho arquitetural foi descontinuado e todas as responsabilidades de runtime foram consolidadas.

## Topologia

* **`apps/app`**: produto do operador — caixa de entrada, contatos, templates, campanhas, Margaret AI, configurações. Implantado na Vercel.
* **`apps/web`**: site de marketing, fluxos de QR/opt-in, landing pages restritas. Implantado na Vercel.
* **`apps/api`**: superfície de API Next.js para ingestão de webhook da Meta, API REST pública v1 (especificação OpenAPI em `/spec`), endpoints de compatibilidade e rotas de health/status. Implantado na Vercel.
* **`apps/docs`**: documentação baseada em Mintlify. Implantado no Mintlify.
* **`apps/worker`**: processamento de queue, retries, agendadores de campanha, despacho de mensagens, ferramentas de replay. Implantado na Railway.
* **Supabase**: Postgres, Auth, Storage, Realtime, Vault. Fonte única de verdade.

<Note>
  O serviço `apps/control-plane` foi removido. Todo o trabalho de control-plane orientado a webhook agora é executado dentro de `apps/api` e `apps/worker`. Quaisquer referências locais à porta 4000 ou a `apps/control-plane/.env.example` são artefatos legados.
</Note>

## Caminhos Principais de Runtime

1. **Webhook de entrada** — a Meta entrega um webhook para `apps/api` → assinatura verificada com `crypto.timingSafeEqual` → envelope bruto armazenado em `webhook_events` → o Supabase notifica o `apps/worker` → o worker roteia para o processador de mensagem, status, template ou jornada.
2. **Envio de saída** — o operador ou uma automação cria uma intenção de envio → o Supabase registra em `outbox_jobs` → `apps/worker` agenda considerando limites de throughput/pares → a resposta da Meta é registrada → webhooks de status atualizam o ledger.
3. **Disparos em massa** — um snapshot de audiência é criado → o worker distribui os jobs de outbox → o Supabase Realtime envia o progresso da campanha ao dashboard do operador.
4. **Margaret AI** — o operador aciona um rascunho de resposta de IA → `apps/app` chama `/api/ai-assistant` → o provider de LLM do workspace é resolvido a partir de `llm_provider_configs` → PII é pseudonimizado antes de qualquer prompt → a resposta é despseudonimizada → o rascunho aparece na caixa de entrada. A execução de agentes (BORD-140–143) adiciona uso de ferramentas (tool-use) sobre isso.

## Modelo de Workspace Multi-Tenant

Cada tenant é um **workspace** isolado. As garantias centrais de isolamento são:

* O contexto do workspace é resolvido no lado do servidor a partir de `workspace_members` — nunca a partir de variáveis de ambiente ou headers fornecidos pelo cliente.
* Todas as consultas de dados são delimitadas por `workspace_id`, derivado dessa resolução.
* O despacho de mensagens lê as credenciais da Meta a partir dos segredos do Vault pertencentes ao workspace proprietário — sem vazamento de credenciais entre workspaces.
* Quatro papéis de RBAC aplicados em toda rota: **owner**, **admin**, **developer**, **operator**.

Veja [Multi-Tenancy e Isolamento de Workspace](/pt-BR/security/multi-tenancy) para o modelo de segurança completo.

## Camada Margaret AI

A camada de IA introduz três novas preocupações de runtime:

* **Configurações de provider de LLM** — registros pertencentes ao workspace em `llm_provider_configs`, apontando para OpenAI, Anthropic, OpenRouter, Ollama ou vLLM. Chaves de API armazenadas no Supabase Vault via `workspace_secret_bindings`.
* **Agentes de IA** — a tabela `ai_agents` define persona, modelo, permissões de ferramentas e configurações de pseudonimização de PII por workspace.
* **Threads de IA** — `ai_threads` e `ai_thread_messages` mantêm o contexto de conversa para as respostas da Margaret. `ai_agent_executions` registra execuções de uso de ferramentas para fins de auditoria.

## Ledger de Consentimento

O ledger de consentimento (BORD-193) fornece um registro durável e auditável de todo evento de opt-in e opt-out por contato:

* **Tabela `consent_events`** — log somente de inserção (append-only) das transições de consentimento (opt-in / opt-out / revogado). Um trigger `AFTER INSERT` nessa tabela desnormaliza o estado mais recente em `contacts.consent_state` para leituras rápidas.
* **Detecção de palavras-chave STOP / START** — `packages/whatsapp` analisa mensagens de entrada em busca de palavras-chave localizadas de opt-out (`STOP`, `BLOQUEAR`, `FERMA`, `PARAR`) e opt-in (`START`, `INICIO`, `INIZIO`, `COMEÇAR`) em inglês, italiano, português e espanhol.
* **Gate de opt-out no despacho de campanhas** — o motor de disparos em massa verifica `contacts.consent_state` antes de enfileirar qualquer job de outbox. Contatos em estado `opted_out` ou `revoked` são ignorados silenciosamente.
* **Endpoints REST** — `GET /api/v1/contacts/:id/consent` retorna o estado atual e o histórico de eventos; `POST /api/v1/contacts/:id/consent` registra uma transição de consentimento manual (apenas owner/admin).

## Command Palette

O command palette (BORD-204) é uma superfície ⌘K para navegação, busca e ações em todo o produto do operador:

* **`command-palette.tsx`** — o shell da paleta, acionado por <kbd>⌘K</kbd> / <kbd>Ctrl+K</kbd>. Renderiza uma lista pesquisável de comandos agrupados por categoria.
* **`command-palette-provider.tsx`** — contexto React que agrega os comandos disponíveis de cada módulo (caixa de entrada, contatos, campanhas, templates, jornadas, configurações) e gerencia o estado aberto/fechado.
* **`command-palette-hint.tsx`** — badge de dica inline renderizado na barra lateral e nos cabeçalhos de página para ajudar a descobrir o atalho.

A paleta é extensível: qualquer módulo pode registrar comandos por meio do hook `registerCommands` do provider.

## Editor Gráfico de Jornadas

Um canvas React Flow em `/journeys/[id]` para construir automações multi-etapas visualmente:

* **9 tipos de node** — Trigger, Condition, Wait, Send Template, Update Attribute, Add/Remove Tag, Outbound Webhook, AI Agent Step e Exit.
* **Validação** — o editor valida campos obrigatórios, conectividade de edges e detecção de ciclos antes de publicar. Erros aparecem inline em cada node.
* **Pipeline de publicação** — os grafos validados são serializados na tabela `journeys` como JSON versionado. Uma mutation `publish` cria um snapshot imutável e ativa a jornada para execução em tempo real pelo `apps/worker`.

## Construtor Visual de Templates

Um construtor de 3 painéis em `/templates/new` para compor templates de mensagem do WhatsApp:

* **7 editores** — Header, Body, Footer, Buttons, Examples, Language e Category.
* **Coluna `parameter_format`** — armazenada em `message_templates` para declarar o tipo e a ordem esperados das variáveis do template.
* **Pipeline de submissão à Meta** — o construtor faz um POST do template composto para a Meta Business API e acompanha o status de aprovação por meio de webhooks de status de template.
* **Renderizador em phone-frame** — um componente de preview em tempo real renderiza o template como ele apareceria em um dispositivo, com substituição de placeholders pelas variáveis.

## Agente de Auto-Trigger

O agente de auto-trigger (BORD-192) estende a Margaret AI para redigir respostas automaticamente em mensagens de WhatsApp de entrada:

* **Gatilho de execução do agente** — quando uma mensagem de entrada chega e o workspace tem um agente de auto-trigger configurado, `agent.run` é invocado automaticamente pelo worker.
* **API de aceitar/rejeitar rascunho** — `POST /api/v1/contacts/:id/drafts/:draftId/accept` e `POST /api/v1/contacts/:id/drafts/:draftId/reject` permitem que operadores aprovem ou descartem rascunhos gerados por IA.
* **Banner de rascunho na caixa de entrada** — um banner visível na visualização da conversa avisa os operadores quando um rascunho está pendente, com ações de aceitar/rejeitar em um clique.

## Armazenamento de Assets

O armazenamento de assets (BORD-187) fornece uploads de arquivos delimitados por workspace para templates, jornadas e assets de conhecimento:

* **Tabela `asset_files`** — registra metadados do arquivo (nome, tipo MIME, tamanho, escopo de workspace) e aponta para o objeto armazenado.
* **Pipeline compatível com S3** — os uploads passam por um pipeline de URL pré-assinada para qualquer object store compatível com S3. O worker recupera os objetos no momento do despacho para envios de mídia.
* **Isolamento de workspace** — todo arquivo é delimitado por `workspace_id`; o acesso entre workspaces é rejeitado na camada de API.

## Alertas de Conta

Os alertas de conta (BORD-189) exibem para os operadores problemas em nível de conta da Meta:

* **Handler de webhook** — `apps/api` processa eventos de webhook `account_alerts` da Meta e os armazena em `account_alert_events`.
* **Painel de UI do operador** — um painel dedicado nas configurações exibe alertas ativos (por exemplo, violações de política, avisos de rate limit, expiração de credencial) com severidade e passos de resolução.

## Logs de Auditoria

Os logs de auditoria (BORD-158) registram ações do operador para conformidade e forense:

* **Tabela `audit_logs`** — log somente de inserção (append-only), delimitado por workspace, de ator, ação, recurso alvo e payload de diff.
* **`writeAuditLog()`** — um helper do lado do servidor que toda rota de mutation chama antes de fazer commit. Garante estrutura consistente e evita omissões acidentais.

## Retenção de Dados LGPD/GDPR

A retenção de dados LGPD/GDPR (BORD-165 / BORD-167) impõe limites de retenção por workspace:

* **`data_retention_days`** — uma configuração em nível de workspace (padrão 365). Controla por quanto tempo envelopes de webhook, conteúdo de mensagem e eventos de consentimento são retidos.
* **Job `retention_sweep`** — um job agendado do worker que exclui registros mais antigos que a janela de retenção do workspace. Executa diariamente; registra métricas de limpeza em `audit_logs`.

## Geração de Chave de API

A geração de chave de API (BORD-178) permite que owners de workspace provisionem chaves de API de longa duração:

* **Chaves com prefixo `swb_`** — geradas no servidor com um segredo criptograficamente aleatório de 32 bytes. O prefixo permite identificação visual rápida e detecção programática em logs.
* **Metadados de chave** — armazenados em `api_keys` com timestamp de criação, timestamp de último uso e descrição opcional. As chaves são armazenadas com hash em repouso; o segredo completo é exibido apenas uma vez, no momento da criação.

## Wizard Guiado

O wizard guiado (BORD-194) fornece um fluxo de onboarding do primeiro acesso até a primeira mensagem:

* **Sequência de etapas** — conectar número de WhatsApp → configurar provider de LLM → criar o primeiro template → enviar a primeira mensagem.
* **Rastreamento de progresso** — armazenado em `workspace_onboarding_state`. O wizard avança automaticamente e pode ser dispensado após a conclusão.
* **Ponto de entrada** — workspaces recém-criados são redirecionados para `/welcome` no primeiro login. O wizard também está acessível a partir de Configurações.

## Primitivas do Design System

Novas primitivas de design system lançadas em `packages/design-system`:

* **Tokens de design** — tokens semânticos de cor, espaçamento e tipografia em `tokens.css`, consumidos por todos os componentes shadcn/ui.
* **Motion** — utilitários consistentes de transição e animação em `motion.ts` (durações, easings, presets de entrada/saída).
* **Skeleton** — componente `Skeleton` com animação de pulso, usado como placeholder de carregamento em todo o produto do operador.

## Atualizações de Marca

* **Wordmark transparente** — o logo da barra lateral expandida agora usa um wordmark SVG com fundo transparente para renderização limpa em qualquer superfície.
* **Favicon com fundo preto** — `favicon.ico` atualizado para uma variante com fundo preto para maior visibilidade nas abas do navegador.

## Princípios de Dados e Segurança

* Todo envelope de webhook é imutável; corpo bruto + metadados são retidos com controles de retenção configuráveis.
* O histórico de entrega é somente de inserção (append-only) (`outbox_jobs`, `message_status_events`) — nunca sobrescrito.
* RBAC, feature flags e segredos de provider permanecem exclusivamente no lado do servidor.
* Tópicos privados de Supabase Realtime Broadcast alimentam os feeds em tempo real do operador; nenhum Postgres Changes broadcast é usado, para evitar problemas de escalabilidade.
* Log de auditoria em toda ação do operador e rotação de credencial.
* O ledger de consentimento impõe opt-out antes de qualquer despacho de campanha ou automação.
* As limpezas de retenção de dados impõem os prazos de exclusão da LGPD/GDPR por workspace.

Veja [Visão Geral de Segurança](/pt-BR/security/overview) para o status completo de implementação dos controles.

## UI do Operador — Barra Lateral e Navegação

A UI do operador (`apps/app`) usa uma barra lateral construída sobre as primitivas `Sidebar` do shadcn/ui.

### Componente

* **Arquivo**: `apps/app/components/operator-sidebar.tsx` (\~165 linhas)
* **Padrão**: `collapsible='icon'` — recolhe para um trilho somente com ícones; expande ao passar o mouse ou ao alternar. A interface de props é estável.
* **Layout**: cada página que precisa da barra lateral envolve seu conteúdo com `SidebarProvider`.

### Estrutura de navegação

* **Seção superior (nav plana)**: Caixa de entrada / Contatos / Disparos em massa / Templates / Operações
* **Seção inferior (rodapé)**: Configurações / Docs / Conta do usuário

### Tema

A barra lateral usa os valores padrão de variáveis CSS claras do shadcn — não há tema escuro customizado ou `className='dark'` aplicado ao elemento da barra lateral.

Variáveis relevantes (definidas em `:root` em `packages/design-system/styles/globals.css`):

* `--sidebar`: fundo quase branco
* `--sidebar-foreground`: texto quase preto

O tema escuro customizado quase preto da barra lateral, existente antes do PR #270, foi removido. A barra lateral agora herda os tokens padrão do design system claro do workspace.

### Logo

* **Expandida**: wordmark completo
* **Recolhida**: marca somente com ícone

## Monitoramento + Deployment

* Endpoints de health: `/health`, `/ready`, `/internal/runtime`.
* Endpoints operacionais: `/internal/webhooks`, `/internal/webhook-rejections`, `/internal/webhooks/:id/replay`.
* Especificação OpenAPI + explorador Scalar: `/spec`.
* Deploy de `apps/app`, `apps/web`, `apps/api` e `apps/docs` na Vercel/Mintlify. Deploy de `apps/worker` na Railway. Todas as superfícies compartilham o mesmo projeto Supabase.
* O CI valida builds, migrations, lint de docs e verificações de segredos. Veja [CI/CD](/pt-BR/operations/cicd).

## Leia a seguir

* [Visão Geral de Segurança](/pt-BR/security/overview)
* [Multi-Tenancy e Isolamento de Workspace](/pt-BR/security/multi-tenancy)
* [Modelo de Dados](/pt-BR/platform/data-model)
* [Matriz de Funcionalidades](/pt-BR/platform/feature-matrix)
* [Runbook de Operações](/pt-BR/operations/runbook)
