# Mapas de arquitetura

- `continuidade-primeiro-pagamento.architecture.json`: cadastro com intenção assinada → Auth → primeiro pagamento → checkout nativo → confirmação financeira → onboarding; ajuda e LGPD preservadas.

## Regra única deste diretório: o JSON é a FONTE; o HTML é DERIVADO

Cada mapa tem um `*.json` (fonte) e pode ter um `*.html` (render).

> **Se os dois divergirem, o HTML é que está errado.** Nunca edite o HTML à mão: regenere-o a partir do
> JSON.

O motivo está aqui e não num handoff porque é aqui que a decisão errada seria tomada. O HTML é o
formato mais fácil de abrir e editar — e **o formato mais fácil de editar é o que envelhece mentindo**:
uma correção feita nele parece funcionar, some na próxima geração, e nesse intervalo a fonte deixou de
ser fonte sem ninguém decidir isso.

## Mapas

| arquivo | escopo |
|---|---|
| `atendimento-alerta-humano-nome-informado.architecture.json` | aviso interno por episódio, reserva sem reenvio incerto, nome selecionado pela ferramenta com escopo inbound e ficha vazia; limites da timeline declarados |
| `apresentacao-do-catalogo.architecture.json` | apresentação de produto pela IA, opcional por empresa: chave, seção, ferramenta no turno, snapshot, retomada e envio em ordem |
| `catalogo-de-modelos.architecture.json` | descoberta diária de modelos nativos OpenAI/Anthropic via Models.dev, conciliação OpenRouter, seletores e auditoria |
| `lista-de-espera.architecture.json` | módulo opcional da agenda: vaga que abre, oferta atômica, aviso pelo caminho proativo, aceite pela agenda, recusa e vencimento chamam o próximo |
| `etiquetas-paginadas.architecture.json` | vocabulário paginado, busca e sugestões nos editores do Inbox |
| `nomes-internos-das-conexoes.architecture.json` | renomeação interna dos canais — cartões de WhatsApp, parceiro e redes sociais → rota tenant-aware → `channel_sessions.display_name` → cartões e seletores, com auditoria e sem alterar o nome público no provedor |
| `conversoes-de-anuncios.architecture.json` | Purchase, etapas e LeadSubmitted por clique CTWA; entrega, livro de cliques e reprocessamento |
| `prospeccao-nativa.architecture.json` | busca comercial, fila gradual, configuração conversacional persistente, sandbox e assistente de voz opcional |
| `pre-go-live-whatsapp.architecture.json` | modo de teste por canal (issue #573): configuração administrativa, gate compartilhado, releitura no envio e validação pelo Inbox |
| `app-da-meta-da-instalacao.architecture.json` | App da Meta da instalação (issue #850, migration 0257) — 10 peças, 12 arestas; a tela `/admin/meta` que grava a chave e mostra o token uma vez, o resolvedor que serve o par inteiro de UMA fonte (banco, com o `.env` de reserva) e por que Conexões só mostra o token quando ele veio do `.env` |
| `agenda-camada-datas-dos-negocios.architecture.json` | camada de leitura das datas do funil na Agenda: 10 peças, 13 arestas; desligada de fábrica, a data no `where` com ordem e teto, e as **não-ligações declaradas** (não vira compromisso, não grava a escolha, não escreve no negócio) |
| `agenda-google-sync.architecture.json` | fontes/destino por dono, tupla estável, três vias, claim/CAS e cobertura de calendário; presença e LGPD integradas |
| `encerramento-atendimento.architecture.json` | conversa/demanda independentes, mutex no inbound, origem imutável dos jobs, memória vigente e guardas antes dos efeitos |
| `agent-turn.workflow.json` | Conversador e Operador, entregas determinísticas de Meet e respostas aprovadas; revisão humana ligada ao mesmo core e à cadeia de envio. O JSON é a fonte atual; o HTML é um render anterior |
| `crm-vivo.architecture.json` | subsistema **CRM Vivo** — 24 peças, 44 arestas, 6 faixas |
| `atualizacao-self-service.architecture.json` | botão de atualizar pela UI — `agent.sh`/`update.sh` (host) ↔ rota do agente ↔ tabelas de instância ↔ rodapé/tela |
| `gestao-funis.architecture.json` | gestão de funis pela tela do Kanban — 18 peças, 30 arestas; as três dependências do funil e por que só uma o banco defende |
| `ia-360-organizar.architecture.json` | IA 360 W4 — o agente organiza a operação: 18 peças, 24 arestas; uma regra por operação servindo REST e MCP, a autoria da configuração ao lado do estado, e **quatro não-ligações declaradas** (autoria não aponta para `ai_agents`; o agente não escreve regra automática, nem resposta pronta, nem o vocabulário canônico de marcadores) |
| `ia-360-retencao.architecture.json` | pacote **Não perder o cliente** (IA 360 · wave 2) — 26 peças, 36 arestas; a regra única do retorno para o motor e para a capacidade configurável, e por que cancelado precisou deixar de ser igual a disparado |
| `escalacao-ciclo-humano.architecture.json` | o ciclo agente ↔ pessoa — 30 peças, 38 arestas; as **três** travas da passagem (só uma era solta) e por onde a decisão da pessoa volta ao contexto do turno |
| `central-avisos.architecture.json` | projeção em lote sob RLS, contexto real e resolver/reabrir independentes |
| `followup-dossie.architecture.json` | dossiê do follow-up e intervenção humana — 20 peças, 30 arestas; as **duas metades** da corrida contra o motor (o tick reclamado e o turno em voo) e quatro não-ligações declaradas |
| `followup-duplicar.architecture.json` | duplicar e renomear um fluxo — cópia sempre rascunho, nome único na org, o mesmo PATCH de nome agora com superfície na lista e no construtor |
| `rodizio-de-atendentes.architecture.json` | rodízio de atendentes na ação Atribuir das Automações (#2041) — 8 peças, 8 arestas; a fila mora na regra, e uma função SQL trava por regra, escolhe, registra a vez e grava o dono numa transação só, para dois leads simultâneos não irem para a mesma pessoa |
| `designer-de-automacoes.architecture.json` | designer de automações (fase 1) — 8 peças, 9 arestas; a mesma regra da aba Automações montada em caixas ligadas, validada pelo mesmo schema e gravada pela mesma rota, e por que o desenho em si não vai para o banco |
| `followup-retorno.architecture.json` | gatilho Cliente voltou — inbound depois do silêncio, envio inline, turno do agente cede |
| `indice-de-atrito.architecture.json` | índice de atrito — 24 peças, 31 arestas; a régua do atrito, o rádio que a lê e as demandas que entram nela |
| `marca-propria.architecture.json` | marca própria (white-label) — 37 peças, 54 arestas, 6 faixas; a pilha org → instalação → `.env` → padrão, as saídas SEM DOM (`marcaDaSaida`) e a **não-ligação declarada** do PDF de LGPD, que imprime o CONTROLADOR e nunca a marca de quem revende |
| `retencao-de-historico.architecture.json` | poda do histórico (issue #261) — 16 peças, 18 arestas, 6 faixas; o que sai (`done`/`failed`/`dead` velho), o que tem dono e **não** sai (`pending`/`running`, e `dead` com aviso ainda aberto), e por que o expurgo do audit é uma `security definer` sem seletor de linha em vez de uma porta |
| `extensoes-declarativas.architecture.json` | perfil declarativo: catálogo de ensaio, admissão, recibos, arquivo local, ativação por organização, guia no CRM, as trocas de versão (atualizar e desfazer a última troca), a remoção da instalação e a auditoria da organização; o estado das provas fica no `contracts.status` do próprio mapa |
| `banco-de-dados-externo.architecture.json` | banco externo (migration 0372, recorte do PR #1130 de @vgamkt) — 27 peças, 48 arestas, 5 faixas; o cadastro por admin e a leitura por todos, a view `_safe` como única superfície da tela, a guarda de rede revalidada a CADA abertura de pool, e a **não-ligação declarada**: as tools do agente ficaram no PR de origem e entram num segundo recorte |
| `captacao-por-webhook.architecture.json` | captação por webhook — 17 peças, 26 arestas, 5 faixas; o adaptador por ferramenta (Respondi, RD Station, Elementor, genérico), o cadastro do campo que mora no funil e o laço em que a definição volta como rótulo no painel, no card do lead, nos botões da automação e na entrada da IA; **não-ligação declarada**: o rótulo que o Elementor manda não é guardado |
| `suspensao-de-organizacao.architecture.json` | suspensão que suspende (PR 1 da cobrança do revendedor): 17 peças, 24 arestas; a régua única de "opera", a escrita do estado só por duas funções definer (e o gatilho que fecha o PostgREST), o hub `/account-suspended` e o laço de retorno pela Central até a Fila; as **não-ligações declaradas** (entrada de mensagens, landings, escrita pela RLS) estão no card do próprio mapa |
| `cobranca-do-revendedor.architecture.json` | cobrança do revendedor, PR 2 (planos e limites): a chave da instalação acima de uma régua única de limite (`fn_limite_do_plano`), as travas no banco para pessoas e números, o teto de IA numa consulta separada do orçamento da org, o teste grátis na criação e a liberação ao desligar a chave. Cada nó que espelha outro mapa declara `espelho`, e o teste reprova quando a peça espelhada some; a PR 3a acrescenta o caminho do dinheiro (conexão, adaptador, aviso assinado, releitura, régua, cron, hub do suspenso) e o card lista o que ainda não liga; a PR 3b liga o Asaas (Pix e boleto recorrentes) no mesmo encaixe, com o dialeto /v3 no mesmo dublê |
| `numero-oficial-do-provedor.architecture.json` | o número oficial pelo provedor parceiro de pé sozinho — 16 peças, 14 arestas; a saúde que vê o número que não recebe ou está com envio restrito (motivo no cartão de Conexões e aviso na Central), a nova tentativa na mesma linha quando o provedor pede calma, o pino lido do próprio webhook e os eventos de etapa que saem pela conversa |
| `entrada-que-responde-antes.architecture.json` | a entrada do número oficial pelo provedor parceiro responde antes de processar — 11 peças, 14 arestas; o arquivo como caixa durável (sem a marca de aceita, 503), a ingestão no `after()` e no cron `webhook-replay` pela mesma função, e por que só mensagem nova entra por aqui |
| `molde-de-ia.architecture.json` | molde de IA das empresas novas (migration 9096) — 17 peças, 23 arestas; a escolha em Recursos opcionais, a cópia por gatilho de `organizations` (o único ponto comum aos quatro caminhos de criação), o padrão decidido num lugar só (`fn_seed_org_llm_defaults`) e o laço de retorno: a auditoria da empresa nova aparece na página dela |

> **Esta tabela já apodreceu uma vez:** ela listava 8 mapas quando o disco tinha 9 — faltava
> `indice-de-atrito`. Nenhum teste lê este README (o gate lê os `.json`), então mapa novo que
> não ganhe linha aqui nasce invisível para quem lê antes de codar. Confira com
> `ls docs/architecture/*.json` antes de confiar na lista.


### Aviso: só o `agent-turn.workflow.json` é renderizável hoje

Medido com archify 2.11.0: os `*.architecture.json` deste diretório **não validam em nenhum
dos dois modos**. Como `workflow` param no `diagram_type`; como `architecture` param na forma —
aquele schema pede `components`, não `lanes`/`nodes`/`edges`. Trocar o `diagram_type` não
resolve: os `node.type` que usamos (`api`, `service`, `table`, `lib`, `route`, `tool`,
`config`) estão fora do enum do archify
(`frontend|backend|database|cloud|security|messagebus|external`), vários `col` passam de 5, e
os `dot` `sky`/`red`/`blue`/`green` não existem no enum de cards.

A prova de que ninguém tentou renderizar está no próprio diretório: existe **um** `.html`, e é
o do único arquivo que valida.

Isto não invalida os outros mapas — eles seguem sendo a fonte da verdade em JSON, lida por
gente e pelo `tests/unit/mapas-de-arquitetura.test.ts`. Mas o README dizia "re-renderize" como
se fosse possível para todos, e não é: quem seguisse a instrução em qualquer um dos outros
receberia um erro de schema e concluiria que estragou algo.

### `crm-vivo.architecture.json` é PLANTA, não fotografia

Ele descreve o desenho **contratado** das oito waves do épico. As waves 6, 7 e 8 **ainda não existem em
código** — quem procurar essas peças no repositório não vai achar, e **o mapa não está errado: está
adiantado**.

Invariantes que a forma não mostra vivem nos `cards` do próprio JSON — inclusive as **não-ligações
deliberadas** (ex.: o score fica **fora** da publicação de realtime, de propósito). *Ausência de aresta
é indistinguível de aresta esquecida; por isso a não-ligação se **declara**, não se desenha.*

## O pedágio do eixo CONTATO × NEGÓCIO

Três peças diferentes pagaram o mesmo custo, e a quarta pagaria igual se isto
não estivesse escrito:

| onde | o que custou |
|---|---|
| **dossiê** (wave 6) | a timeline era indexada por `contact_id`; negócio sem contato ficava mudo — 25% dos leads, 64% das atividades |
| **reativação** (wave 7) | `cron_jobs` é por contato; negócio sem contato não pode receber proposta de retomada — 26 de 68 abertos |
| **funil do agente** (wave 8) | `lead_state.stage` é por contato e o card é por negócio; um contato com dois negócios exige decidir qual se move |

**A aresta:** `contacts` ─(1:N)─ `crm_leads`, e quase todo mecanismo do agente
vive do lado do CONTATO enquanto quase toda superfície do produto vive do lado
do NEGÓCIO.

**A regra que sai daí:** toda peça nova que ligue um mecanismo do agente a uma
superfície do CRM atravessa essa aresta, e precisa responder três perguntas
**antes** de ser escrita:

1. e se o contato tiver **dois** negócios abertos? — reuse
   `resolveActiveLeadForContact`, nunca escreva um segundo resolvedor;
2. e se o negócio **não tiver** contato? — é 25% dos casos, não é canto;
3. o que a peça faz quando não dá para decidir? — não agir e deixar rastro é
   resposta; agir no negócio errado não é.

As três vezes o custo foi o mesmo: descobrir a aresta **durante** a
implementação, com a peça já meio pronta.

- `carteiras-transferencia.architecture.json`: atribuição respeita o escopo da carteira sob lock.
- `atendimento-comercial.architecture.json`: entrada, veto, briefing e configuração de atendimento comercial exclusivamente humano.

`cadencias.architecture.json`: módulo oficial opcional do PR#1738; vitrine, decisão da empresa, fila, transporte, consentimento, descadastro e LGPD. Contrato em `docs/modulos/cadencias.md`.
