Pular para o conteúdo principal
Modular Development Style · Roadmap de Implementacao

ModularReports

Companheiro do DRS

Publicado em 24 de julho de 2026 Modulareasy · modulareasy.com/mds
Progresso da implementação ...
Planejamento 0%
Construção 0%
Testes 0%
Progresso geral: 0%
Clique no quadradinho para marcar como feito. O progresso é salvo automaticamente e compartilhado.

ModularReports: Roadmap de Implementação

CampoValor
ProdutoModularReports
DocumentoRoadmap de Implementação (companheiro do DRS)
Data de revisão2026-08-09

Documentos da família

Este é o roteiro de construção do sistema, em ordem, com verificação primeiro: para cada tarefa, o observável que prova que ela está pronta é declarado antes do como construir. A ordem vem das ondas de entrega do DRS (bloco 9, J.1 e J.2) e de suas dependências. Cada tarefa cobre um ou mais requisitos funcionais (RF) do DRS.

Como usar

Cada tarefa é um cartão com um código curto e estável (ex.: F1-03), o RF que cobre, o que implementar, como verificar (o teste, declarado primeiro) e o critério de aceite H1. Marque a tarefa como feita quando o teste passar. As fases são sequenciais; dentro de uma fase, siga a ordem dos cartões. Ao fim de cada fase há uma Definição de Pronto: a fase só fecha quando todos os seus critérios estão verdes.

Mapa de cobertura

FaseOnda do DRSMódulo do DRSRFs cobertos
PlanejamentoPreparaçãoElicitação, especificação, companheiros, validação, aprovaçãoPré-concluída na aprovação do DRS
M, Mockup NavegávelPreparaçãoReferência visual do sistema completo (bloco 6, F.3)Concluída: mockup de 17 telas publicado e aprovado
F1, Protótipo do pipeline IAFatia 1reports-compose (CMP), reports-boundary (BND), reports-ingest (ING)RF-BND-001, RF-CMP-005/006/008 a 016, RF-ING-003, RNF-SEG-002/003/004, RN-012, RF-CMP-018 (mecanismo determinístico)
F1b, Schema de dadosFatia 1bModelo de dados (E.1, E.2)Cria as tabelas do schema reports (as 7 do E.2 mais report_goal), antes das fatias que as consomem; RN-009 (trigger report.company_id = company_id do Account)
F2, Contrato de bloco e snapshotFatia 2reports-render (REN), reports-publish (PUB), reports-ingest (ING)RF-REN-001/002/003, RF-PUB-001, RF-ING-005, RN-001 a RN-006
F3, Package renderizadorFatia 3reports-render (REN)RF-REN-004/005/007, RNF-MANUT-001, RNF-A11Y-001
F4, Ingestão, quota e storageFatia 4reports-ingest (ING), reports-boundary (BND)RF-ING-001/002/003/004/006, RF-BND-002, RNF-LGPD-001
F5, Leitor públicoFatia 5reports-render (REN)RF-REN-006/010, RNF-SEG-001 (caminho do leitor: role reports_reader, GRANT das 3 tabelas e policy PERMISSIVE publicado+não-expirado), RNF-SEG-005, RNF-PERF-001, RNF-DISP-001, RN-011
F6, Role, entitlement e RBAC no HubFatia 6reports-admin (ADM)RF-ADM-001/002/012, RNF-SEG-001 (caminho do operador: RESTRICTIVE por company_id), RN-007 (log append-only)
F7, Chrome e shell do operadorFatia 7reports-admin (ADM)RF-ADM-003/004/014, RNF-MANUT-002
F8, Wizard e compositorFatia 8reports-compose (CMP), reports-curate (CUR)RF-CMP-001 a 004, RF-CUR-001 a 008, RNF-PERF-002, RF-CMP-017, RF-CMP-019, RF-CMP-020
F9, Publicação e linkFatia 9reports-publish (PUB), reports-compose (CMP), reports-comment (COM)RF-CMP-007, RF-PUB-002 a 010, RF-COM-004, RN-010 (imutabilidade do snapshot imposta pela função SECURITY DEFINER de publish), RF-CMP-018
F10, TemplatesFatia 10reports-admin (ADM)RF-ADM-009/010/016/017, RN-013 (escopo Global e individual)
F11, Importação de metasFatia 11reports-ingest (ING), reports-boundary (BND)RF-BND-003, RF-ING-007, RN-008 (snapshot congela as metas vigentes no publish)
F12, ComentáriosFatia 12reports-comment (COM)RF-COM-001 a 006
F13, AnalyticsFatia 13reports-analytics (ANL), reports-admin (ADM)RF-ANL-001 a 006, RF-ADM-015, RNF-LGPD-003
F14, Domínio custom e white-labelFatia 14reports-render (REN)RNF-SEG-006
F15, PDF condicionalFatia 15reports-render (REN)RF-REN-008/009
F16, Painel do clienteFatia 16reports-admin (ADM), reports-render (REN)RF-ADM-005/006/007/008/011/013, RF-REN-011 (portal logado do cliente)
F17, Blocos reais, cadência e biblioteca de modelosFatia 17reports-render (REN), reports-compose (CMP), reports-admin (ADM)RF-REN-012 (cobertura nominal dos 16 tipos do Ap.3), RF-REN-013, RF-CMP-001 (cadência no passo 1), RF-CMP-021, RF-CMP-022, RF-CMP-023, RF-ADM-017, RN-014, RN-013 item 4, ADR-016, ADR-017. Vem na fila antes de F13 a F16, ver a nota de prioridade da fase
F12, ComentáriosFatia 12reports-comment (COM)RF-COM-001 a RF-COM-006, mais RNF-SEG-007 (guarda de script inline, {F12-07}), nascida da verificação real desta fatia
F19, Geração agendadaFatia 19reports-admin (ADM), reports-compose (CMP)RF-ADM-019 a RF-ADM-022, RF-CMP-027, RF-CMP-028, RF-CMP-029, RN-017, ADR-021, E.2 (report_schedule, schedule_cycle, report_job). Nasceu da resposta do dono a {Q4b}. Depende de {F17-05} (cadência) e de {F18-05} (anti-fadiga por quadrantes)
F20, Modelo de venda e camada de resultadoFatia 20reports-admin (ADM), reports-render (REN), reports-compose (CMP), reports-ingest (ING)RF-ADM-023, RF-REN-016, RF-REN-017, RF-CMP-030, RF-CMP-031, RF-ING-008, RN-018, ADR-022, ADR-023, Ap.10. Nasceu da planilha de gestão apontada pelo dono e fecha o item de investigação do Ap.9. Depende de {F11-01} e {F11-02} (importação)
F18, Honestidade do número e calibração da réguaFatia 18reports-compose (CMP), reports-render (REN), reports-admin (ADM), reports-curate (CUR)RF-CMP-016 (reescrito), RF-CMP-024, RF-CMP-025, RF-CMP-026, RF-REN-014, RF-REN-015, RF-ADM-018, RF-CUR-009, RNF-MANUT-003, RNF-MANUT-004 (rota provada pelo HTTP servido, {F18-18}), RNF-SEG-008 (varredura de topologia no publish), RNF-PERF-002 (teto escalado), RNF-MANUT-005 (número que vem de cima também se mede), RN-015, RN-016, ADR-018, ADR-019, ADR-020, Ap.4 (segundo critério de coerência, E1 a E3). Depende de F17

Estado global

Recontagem em 2026-08-18, após o fechamento do {F8-58} e o nascimento do {F8-62}, e ela é a base vigente: qualquer número mais antigo neste documento está morto. Mesmo método das recontagens anteriores, expressão regular sobre toda linha de cartão de checklist do documento, aceitando letra minúscula no fim do código, conferido sem duplicidade (269 linhas de cartão para 269 códigos únicos). Placar: 269 cartões no documento, sendo 29 de Planejamento (100%) e 2 de Mockup (100%), e 238 de Construção, dos quais 226 fechados e 12 abertos. Contando a Fase M dentro da barra de Construção, como o renderizador faz: 228 de 240 = 95,0%. Os 12 abertos: {DEF-01}, {DEF-02}, {F8-20}, {F8-37}, {F8-38}, {F8-41}, {F12-07}, {F18-11}, {F18-16}, {F18-19}, {F20-10} e {F8-62} (nascido nesta rodada). O Plano de Testes não foi remedido nesta rodada (carregado o último valor conferido no próprio documento: 165 itens, 90 fechados, 136 Alfa e 29 Beta, todos os fechamentos na seção Alfa = 54,5%). Pelos pesos 40/40/20 das três seções, o geral fica em 88,9%.

O que mudou nesta rodada, em uma frase: o {F8-58} fechou e nasceu o {F8-62} no lugar dele, denominador líquido +1, sem nenhum outro cartão mudando de estado. A guarda de endereço de aviso que o {F8-58} media saiu do módulo de relatórios e passou a valer para o Hub inteiro (publishNotification, apps/api/src/lib/notifications.ts, 20 importadores, fail closed), com 7 isenções nomeadas por prefixo só para o módulo control e 3 destinos mortos corrigidos com o destino medido no front. A medição de fechamento (feita por conta própria, antes de declarar pronto) DIVERGE da tabela que o próprio cartão trazia desde a rodada de 2026-08-18 anterior: a tabela contava 584 casam/8.395 não casam, a remedição achou 395 casam/8.584 não casam, e as duas ficam escritas no cartão, sem ajustar uma pela outra. O achado que sustenta o {F8-62}: no control o campo link é ao mesmo tempo chave de deduplicação e destino de navegação, e a segunda função nunca foi honrada, cerca de 8,2 mil avisos levam ao painel inicial em silêncio; mexer nesses avisos vivos é decisão do dono, não de quem implementa, e por isso virou cartão em vez de conserto em massa.

Recontagem em 2026-08-09, feita depois da reconciliação de documento da fatia {F8-08} A, e ela é a base vigente: qualquer número mais antigo neste documento está morto. Universo e critério, declarados porque número sem critério não se audita: o universo é toda linha de cartão de checklist DESTE documento, e o critério é a marca no próprio texto (a declaração de quem produz, não o clique de quem lê), conferida contra o estado efetivo que o sistema serve, que devolveu exatamente os mesmos 218 itens com 201 fechados. Placar: 218 cartões no documento, sendo 29 de Planejamento e 2 de Mockup, todos fechados desde a aprovação, e 187 de Construção com 170 fechados e 17 abertos. Contando a Fase M dentro da barra de Construção, como o renderizador faz, são 189 com 172. O Plano de Testes foi recontado no próprio documento na mesma data: 165 itens com 90 fechados, sendo 136 Alfa e 29 Beta. Pelos pesos 40/40/20 das três seções, o geral é 87,3%.

O denominador subiu de 183 para 187 e o percentual de Construção caiu de 92,9% para 90,9%, e isso é o processo funcionando. Nenhum cartão fechado reabriu. Os quatro que nasceram vieram todos de defeito medido durante a obra desta fatia: {F8-21} (a barra de marca da agência na página pública nunca foi construída, e é ela que bloqueia a metade do logo), {F8-22} (as páginas de link revogado e expirado resolvem identidade por uma segunda precedência), {F8-23} (a varredura de número reprova casos que o próprio requisito isenta nominalmente) e {F8-24} (a procedência da identidade é gravada e nenhuma tela a lê). O Plano de Testes subiu de 163 para 165 pelos dois requisitos novos do DRS.

A ORDEM FOI INVERTIDA na fatia {F8-08} A, e o registro fica aqui porque a lição é de processo, não de cartão. Neste projeto o DRS é lei e mudança de escopo se reconcilia no documento ANTES de codar; o plano da fatia declarava isso como passo 1, com todas as letras. A construção foi despachada sem o passo 1: o código ficou pronto e em gates, e o DRS e o Inventário publicados eram anteriores aos commits e não mencionavam nada da sobreposição de identidade por relatório. Quem mediu e apontou a divergência foi a revisão de código, não o processo. A reconciliação veio depois, em 2026-08-09 (RF-CUR-004 endurecido, RF-CUR-012, RF-CUR-013, RN-020, a coluna nova no Inventário, o artefato {ART-SCR-03}, os quatro cartões filhos e a cobertura Alfa dos requisitos novos), e nada foi revertido. O que muda daqui para frente: despachar construção sem despachar o passo zero deixa o bloqueio (aqui, {F8-21}) existindo só na cabeça de quem planejou, e bloqueio que não virou cartão não bloqueia ninguém.

Um achado desta reconciliação vale por si, porque é um número herdado que estava errado. O plano da fatia registrou que o perímetro da disciplina de número derivava de uma segunda lista curada, deixando a abertura do relatório de fora da varredura. Medido no código vivo em 2026-08-09, por controle negativo comportamental e não por busca textual: a premissa é FALSA, já tinha sido corrigida por {F18-20}, e a abertura reprova corretamente um número digitado à mão. A mesma medição, porém, encontrou o defeito oposto e ele é real, e virou {F8-23}. Evidência anterior a um conserto não prova defeito vivo, e por isso número que vem pronto se remede antes de virar cartão.

NOTA DE PRODUÇÃO, 2026-08-05: as Fatias 11 a 20 saíram da branch e foram para produção. Os números abaixo, medidos em 2026-08-03, descreviam código construído e testado numa linha de trabalho separada da que serve o produto; não descreviam o que estava no ar. Nesta data as dez fatias foram mergeadas na linha principal e colocadas em produção, com QA e revisão de código independentes rodadas pela primeira vez sobre o pacote acumulado (a suíte completa, banco real: mais de mil testes verdes; revisão de código: zero achado crítico, zero regressão fora do escopo). Um defeito de infraestrutura foi achado e corrigido no mesmo movimento: o servidor que atende o link público não encaminhava as rotas novas de comentário (sessão, comentário, pedido de acesso, asset por identificador) para o leitor, então quem clicasse em "Comentar" no relatório publicado caía em erro; corrigido e provado com o fluxo completo (convite por link mágico até o comentário persistido). Os cartões marcados fechados abaixo agora descrevem produto no ar, não apenas branch testada, e é essa distinção que esta nota registra.

Um cartão foi reaberto e re-fechado no mesmo dia, e a volta fica registrada porque a lição vale. Uma medição contra a infraestrutura em produção achou o {F15-02} (assets do leitor e do PDF) afirmando um mecanismo de armazenamento que parecia não existir, e o cartão foi reaberto. A medição tinha consultado o serviço de armazenamento errado: a plataforma-mãe nunca usou aquele serviço, de nenhum módulo, então a consulta sempre daria zero. O mecanismo real é armazenamento em sistema de arquivos sobre volume dedicado, já usado por outras áreas do Hub, com arquivo real do próprio ModularReports gravado nele; medido de novo no mecanismo certo, o cartão fechou de volta. Nenhum outro cartão fechado precisou reabrir: a verificação direta em produção (tabelas do banco, rotas da API, containers ativos, disparadores) confirmou o que os demais cartões já diziam. O {ART-INFRA-01} do Inventário teve a mesma volta, com a ficha reescrita para descrever o mecanismo real.

Recontagem em 2026-08-08, pelo endpoint de estado do roadmap sobre o documento publicado. Esta é a base única; qualquer número mais antigo neste documento está morto, incluindo o "159 de 174" que outra frente publicou nesta mesma data. Aquele número e os anteriores vinham de uma contagem que perdia três cartões cujo código termina em letra minúscula ({F1b-01}, {F8-02b}, {F8-02c}), fechados desde as fases iniciais; o endpoint os enxerga porque não filtra por formato de código. Contagem exaustiva por código, sem duplicidade (cada código aparece como cartão de checklist exatamente uma vez, conferido): 209 cartões no total, sendo 29 de Planejamento (100% fechados), 2 de Mockup (100% fechados) e 178 de Construção, dos quais 164 fechados e 14 abertos. Os 14 abertos, cada um com o motivo no próprio cartão: {F8-07}, {F8-08}, {F8-11}, {F8-12}, {F8-15}, {F8-16}, {F8-17}, {F8-18}, {F12-07}, {F13-03}, {F18-11}, {F18-16}, {F18-19} e {F20-10}. {F4-07} e {F5-06}, que apareciam abertos na última recontagem, fecharam entre uma medição e outra e saem da lista.

Recontagem de 2026-08-08 ao fim do dia, e ela SOBE o denominador de propósito. Universo e critério, declarados porque número sem critério não se audita: o universo é toda linha de cartão de checklist DESTE documento e o critério é a marca no próprio texto (- [x] contra - [ ]), ou seja, a declaração de quem produz, não o clique de quem lê. Placar: 211 cartões no total, sendo 29 de Planejamento (fechados), 2 de Mockup (fechados) e 180 de Construção, dos quais 165 fechados e 15 abertos; 165 mais 15 fecham em 180, e 29 mais 2 mais 180 fecham em 211. Os 15 abertos: {F8-07}, {F8-08}, {F8-12}, {F8-15}, {F8-16}, {F8-17}, {F8-18}, {F8-19}, {F8-20}, {F12-07}, {F13-03}, {F18-11}, {F18-16}, {F18-19} e {F20-10}. O que mudou em relação ao parágrafo acima, item a item: {F8-11} fechou e sai da lista de abertos; {F8-19} e {F8-20} são cartões novos, nascidos do planejamento do {F8-07} (imagem vetorial servida embutida na página pública, e a eliminação de dados pessoais que não alcança arquivo nenhum). Denominador de 178 para 180 sem nenhum cartão fechado reabrir: os dois novos vieram de defeito medido durante a obra, que é o processo funcionando e não o escopo escorrendo.

Duas bases circulam e as duas são verdadeiras; ao comparar números, diga qual está usando. Excluindo Planejamento e Mockup, a Construção tem 178 cartões com 164 fechados. Contando a Fase M dentro da barra de Construção, como o renderizador faz, são 180 com 166. A diferença é exatamente os 2 cartões de Mockup, que nasceram fechados.

O denominador subiu com o nascimento de {F12-08} em 2026-08-08, e é o mesmo desenho de sempre: a obra encontrou defeito olhando o produto. {F12-08} (o botão de comentar sobrepondo o título do bloco em tela de celular) nasceu e fechou no mesmo dia, visto na verificação real de {F5-06}, mergeado e deployado, provado em produção por geometria real. Nenhum cartão fechado reabriu. Bases que não valem mais: qualquer contagem de Construção que não inclua {F1b-01}, {F8-02b} e {F8-02c}, e o "159 de 174" publicado por outra frente nesta mesma data.

Recontagem em 2026-08-08, à noite, publicando o que fechou depois da recontagem do fim de tarde: dois cartões fecharam. {F8-12} fechou por verificação (composição síncrona provada em produção, sem código novo). {F13-03} fechou mergeado e deployado (fonte única de contagem de visualização, prova real: o mesmo relatório passou a mostrar 147 nos dois lugares que exibem visualização). {F8-11}, já fechado no parágrafo anterior, permanece sem mudança. Nenhum outro cartão mudou de estado; {F8-07} e {F8-08} ganharam achados novos no planejamento (os dois cartões que nasceram deles, {F8-19} e {F8-20}, já estão contados acima), mas os dois seguem abertos, por falta de construção e não de exercício. Placar: 211 cartões no total, 29 de Planejamento (fechados), 2 de Mockup (fechados) e 180 de Construção, dos quais 167 fechados e 13 abertos. Os 13 abertos: {F8-07}, {F8-08}, {F8-15}, {F8-16}, {F8-17}, {F8-18}, {F8-19}, {F8-20}, {F12-07}, {F18-11}, {F18-16}, {F18-19} e {F20-10}. Contando a Fase M dentro da barra de Construção, como o renderizador faz: 169 de 182 = 92,9%. Testes não foram remedidos nesta rodada (carregado o último valor publicado, 91 de 161 = 56,5%). Pelo peso 40/40/20 do progresso geral, o geral fica em 88,4%.

Recontagem em 2026-08-09, do zero, pelo mesmo método declarado acima, sem herdar nenhum número anterior por adoção. Método: expressão regular sobre toda linha de cartão de checklist do documento (- [ ] {CODIGO} ou - [x] {CODIGO}), aceitando letra minúscula no fim do código, o mesmo formato que a contagem de 2026-08-08 tinha perdido em três cartões ({F1b-01}, {F8-02b}, {F8-02c}); conferido que cada código aparece exatamente uma vez, sem duplicidade, 213 linhas de cartão para 213 códigos únicos. Placar: 213 cartões no total, sendo 29 de Planejamento (fechados), 2 de Mockup (fechados) e 182 de Construção, dos quais 169 fechados e 13 abertos. Os 13 abertos: {F8-08}, {F8-15}, {F8-16}, {F8-17}, {F8-18}, {F8-19}, {F8-20}, {F12-07}, {F18-11}, {F18-16}, {F18-19}, {F18-21} e {F20-10}. O que mudou em relação ao parágrafo acima, item a item: {F18-20} é cartão novo e já nasce fechado (mergeado e deployado em 2026-08-09, a disciplina de número passou a cobrir os 16 tipos de bloco por exceção nomeada em vez de lista curada declarada tipo a tipo); {F18-21} é cartão novo e nasce aberto (o limite que sobrou da correção acima, sigla de custo seguida de quatro dígitos inteiros ainda escapa da guarda); e {F8-07} sai da lista de abertos por correção de prosa, não por trabalho novo desta rodada, o cartão já estava [x] desde 2026-08-08 (fechado, mergeado e deployado, ver o próprio card) e o parágrafo anterior não tinha acompanhado o texto. Contando a Fase M dentro da barra de Construção, como o renderizador faz: 171 de 184 = 92,9%. Testes não foram remedidos nesta rodada (carregado o último valor publicado, 91 de 161 = 56,5%). Pelo peso 40/40/20 do progresso geral, o geral fica em 88,5%.

Reconciliação em 2026-08-09, mesmo dia, dois cartões mudam de estado. {F8-15} fechou: mergeado e deployado, provado em produção (o próprio cartão descreve a prova). No mesmo commit nasceu {F8-25}, aberto, achado fora do diff da verificação de {F8-15}: a terceira ocorrência do padrão ler, chamar a rede e gravar cego, ainda sem conserto em duas rotas da pesquisa de mercado, por isso pede varredura do padrão e não conserto caso a caso. Recontagem pelo mesmo método do parágrafo anterior (expressão regular sobre toda linha de cartão, aceitando letra minúscula no fim do código, sem herdar nenhum número por adoção): conferido que cada código aparece exatamente uma vez, sem duplicidade, 214 linhas de cartão para 214 códigos únicos. Placar: 214 cartões no total, sendo 29 de Planejamento (fechados), 2 de Mockup (fechados) e 183 de Construção, dos quais 170 fechados e 13 abertos. Os 13 abertos: {F8-08}, {F8-16}, {F8-17}, {F8-18}, {F8-19}, {F8-20}, {F8-25}, {F12-07}, {F18-11}, {F18-16}, {F18-19}, {F18-21} e {F20-10}. O que mudou em relação ao parágrafo anterior, item a item: {F8-15} sai da lista de abertos (fechou); {F8-25} entra (nasceu aberto); nenhum outro cartão mudou de estado. {F8-08} segue aberto sem alteração nesta reconciliação, mesmo com outra frente de trabalho em curso nele: ele só fecha quando o próprio cartão declarar a prova. Contando a Fase M dentro da barra de Construção, como o renderizador faz: 172 de 185 = 93,0%. Testes não foram remedidos nesta rodada (carregado o último valor publicado, 91 de 161 = 56,5%). Pelo peso 40/40/20 do progresso geral, o geral fica em 88,5%.

O total de Construção SOBE quando a obra encontra defeito, e isso é o desenho funcionando, não o placar piorando. Entre 04/08 e 05/08 ele foi de 167 para 171: fecharam {F4-05}, {F7-04} e {F10-07}, e nasceram cinco cartões, todos de defeito MEDIDO durante a construção, nenhum de escopo novo inventado. {F4-07} (o Inventário afirma vinte parâmetros editáveis por painel e a lista de fontes é constante congelada em código), {F5-06} (a página pública não declara viewport, então todo o desenho de tela estreita fica adormecido em celular real), {F8-15} (salvar uma parte do briefing apaga as outras), {F18-19} (andaime interno da IA vazando no texto que o cliente lê) e o próprio {F4-07} vieram de olhar, não de planejar. Bases antigas que circularam aqui e não valem mais: "167 de Construção com 12 abertos", "191 cartões com 134 fechados" e "16 cartões abertos".

O ModularReports está com o DRS aprovado e o mockup navegável (17 telas) publicado e aprovado: Planejamento 29 de 29 cartões = 100%, Fase M 2 de 2 = 100%, Construção 170 de 187 cartões = 90,9%, Testes 90 de 165 itens = 54,5% (as duas contagens foram remedidas em 2026-08-09, cada uma no seu próprio documento, e conferidas contra o estado efetivo que o sistema serve; {F5-09} não tem TA associado no Plano de Testes). Pelo peso 40/40/20 do progresso geral, e contando a Fase M dentro da barra de Construção como o renderizador faz (172 de 189 = 91,0%), o geral fica em 87,3%. Este parágrafo é o estado presente e foi reescrito junto da recontagem do topo; os parágrafos datados acima são história e descrevem o momento deles, não o de agora.

O percentual CAIU de 92,4 para 90,8 e isso é o processo funcionando. Nenhum cartão fechado reabriu: três nasceram, todos de defeito medido durante a obra. Enquanto a construção continuar olhando o produto de verdade, o denominador vai crescer, e um placar que só sobe seria sinal de que ninguém está olhando.

O denominador caiu de percentual porque subiu de tamanho, e isso é o esperado. O geral recuou de 72,9% para 69,6% sem que uma linha de código fosse desfeita: 16 cartões novos entraram na fila e 18 itens novos entraram no Plano de Testes. Progresso que sobe quando o escopo cresce seria o sinal errado.

A família "peça pronta que ninguém aciona" fechou INTEIRA em 2026-08-04, com {F10-05}, {F10-06}, {F11-03} e {F20-08}. Metade dela era trabalho já feito e inalcançável, não trabalho pendente. O {F20-08} foi destravado por decisão de MECANISMO e não de produto: reusar a localização de dado em artefato que já existe, apontada para as chaves canônicas do funil, sem inventar um terceiro caminho. Essa decisão não subiu ao dono porque as chaves já tinham sido decididas por ele na planilha de referência, e o que restava era mecanismo. Três propriedades ficaram provadas ao vivo: a camada de resultado não ramifica por modelo de venda, etapa não encontrada sai como ausente e nunca como zero, e a distinção dos dois nulos vale no caminho real (sem modelo declarado a composição fica idêntica à anterior, e artefato ilegível recusa com motivo em vez de fabricar bloco).

Fatia entregue em 2026-08-03: dois cartões fechados e um defeito real de publicação corrigido. O {F20-09} fechou com o aviso de conflito de eixo nomeando as séries em texto, na mesma caixa vermelha dos demais erros, e o achado é o de sempre: a detecção já existia no backend e a API já devolvia o aviso, faltava o painel consumir. O {F18-06} fechou com identidade persistente da recomendação, critério declarado (dono e horizonte como portas, similaridade dentro delas) e cinco controles negativos de isolamento, com o limite escrito em código: o limiar é calibrado por sonda sintética, não por dado real, e calibrá-lo virou o {F20-10}. Junto vieram dois defeitos que ninguém tinha pedido para procurar: o gate de proveniência não enxergava o plano de ação (número cru publicava sem verificação, provado ANTES de corrigir e agora ligado ao caminho real, {F20-11}), e o validador de tamanho e horizonte do item existia, era testado e nenhum gate o chamava ({F20-12}), sétima ocorrência da mesma classe nesta sessão.

A interface do operador ganhou suíte de teste de componente em 2026-08-03, e ela fechou 4 itens Alfa e deixou 3 explicitamente parciais. A tela não tinha nenhum teste, então toda cláusula que dependia do comportamento dela só era verificável a olho. Estado medido: 2 arquivos de teste de componente com 11 casos, cada um nascido com controle negativo provado individualmente. Fecharam por cobertura INTEIRA do critério: {TA-28}, {TA-46}, {TA-54} e {TA-82}. Seguem abertos por cobertura PARCIAL, com a cláusula que falta nomeada em cada um: {TA-26} (falta o vínculo com o template), {TA-42} (falta esconder bloco) e {TA-15} (o teste prova a EXIBIÇÃO do histórico, e o critério é sobre a GRAVAÇÃO do log). Nasceu também o {F20-09}, achado de produto: o aviso de conflito de eixo existe, funciona e é apenas um contorno tracejado, sendo a exceção silenciosa num produto que avisa todo o resto em caixa vermelha com texto.

A auditoria do Plano de Testes fechou 28 itens Alfa em 2026-08-03, e REABRIU um. O reaberto é o mais importante: o {TA-66} estava aprovado validando a geração de PDF, e a fase que a implementa vive numa branch órfã, medida como não ancestral da linha principal nem de nenhuma das cinco outras em curso. Era um cartão de teste aprovado sobre funcionalidade que não existiria no produto entregue. A auditoria também levantou uma divergência entre documento e código no custo de julgar, que a medição reconciliou a favor do documento: o padrão é três passadas por critério, e o que mudou foi a concorrência delas, não a contagem.

A Fase F18 chegou a 15 de 18 em 2026-08-03, com as seis guardas centrais LIGADAS no publish real. Elas estavam escritas e testadas por unidade, e o publish não as chamava. Cada ligação foi provada individualmente, comentando a própria linha e conferindo que só o teste dela caía, uma a uma nas seis, e as sete suítes irmãs que também publicam seguiram verdes, o que prova a outra metade: nenhum relatório legítimo passou a reprovar. O achado mais fino da fase veio junto: a saída legal do {F18-07} era ela própria sempre reprovada pelo gate de proveniência estrutural, ou seja, a escotilha existia no texto e era inalcançável no código, que é o defeito exato contra o qual a regra do {F18-10} foi escrita. Sobram três cartões, cada um por motivo nomeado: o {F18-06} é lacuna de MODELO DE DADOS e não de ligação (escalar recomendação repetida exige persistir a identidade da recomendação entre edições, e não há onde guardar), e o {F18-11} e o {F18-16} têm evidência de entrega medida no repositório mas sem confirmação do H1.

A Fase F20 FECHOU em 2026-08-03, e a F18 avançou sem fechar. A F20 (modelo de venda e camada de resultado) fechou com a prova que sustenta a camada inteira: as 11 métricas com fórmula pendente foram exercitadas com todos os operandos presentes, e nenhuma emitiu, o que prova que a trava é a regra e não a falta de insumo; o prazo de retorno do CAC segue bloqueado mesmo com fórmula literal, porque um operando dele não existe no catálogo. As contagens do catálogo são função calculada e não constante escrita à mão, que é o que impede o placar de mentir depois. O funil canônico ignora o rótulo digitado (provado corrompendo o rótulo e conferindo que ele não chega ao HTML) e o funil livre roda inalterado, com regressão zero. A F18 avançou 6 cartões (chegando a 8 de 18, com 10 ainda abertos: {F18-01} a {F18-08}, {F18-11} e {F18-16}), e o {F18-15} derrubou uma premissa do próprio documento: a composição encadeia dois passos e não de cinco a sete, e as três passadas da régua eram independentes e agora rodam em paralelo. Nasceu um cartão aberto, o {F20-08}: os construtores do funil e do resultado existem e nada os aciona, porque falta neste documento o mapeamento entre o dado do artefato e as chaves canônicas de operando, e inventá-lo seria repetir o erro que as fórmulas pendentes evitam.

A Fase F19 (geração agendada) FECHOU em 2026-08-03, entregue e provada nos dois repositórios, com a tela passando por smoke real. A trava que o dono impôs como condição está provada por dois meios independentes: nenhuma referência a publicação no disparador nem no módulo de agenda, e o publish seguindo como endpoint único sem parâmetro de origem. A guarda não é uma condição dentro do publish, é a ausência do caminho. Três decisões de escopo do dono ficaram escritas como escopo declarado e não como pendência: a agenda automatiza a composição e não a coleta (ela adota um relatório já preparado, e sem ele o ciclo fecha com desfecho nomeado); o gate de honestidade roda no publish e não dentro da composição automática, com a condição registrada de que isso muda se a publicação virar automática; e o próximo vencimento aparece por extenso na tela para não duplicar a matemática de calendário em duas linguagens.

A Fase F17 FECHOU em 2026-08-03, com dois cartões acrescentados durante a entrega. Os dez originais ({F17-01} a {F17-10}) entregaram os cinco tipos de bloco novos, a cadência na instância, a guarda de largura de janela, a métrica não somável e a biblioteca semeada. O {F17-11} nasceu porque quatro dessas peças estavam construídas, testadas e NÃO ligadas ao caminho real, e cada ligação nasceu com um teste que prova que falha sem ela (procedimento executado, não presumido: comentar a chamada, rodar, ver vermelho, restaurar). O {F17-12} nasceu da causa por trás disso, que é o achado mais estrutural do dia: as peças nunca estiveram no índice público do pacote, e por isso eram indefinidas para o consumidor externo, enquanto os testes de unidade passavam por importarem o módulo de origem direto. A varredura mediu 63 nomes fora do índice, 62 internos de propósito e 1 defeito vivo, e a causa foi fechada com um teste de contrato por máquina (RNF-MANUT-006). O smoke visual da fase achou três defeitos que 32 testes verdes não pegaram, todos invisíveis para asserção e óbvios para o olho.

Mais três cartões fecharam no mesmo dia, e o mais velho deles com conclusão e não com "resolvido". {F1-17} era o cartão mais antigo em aberto do projeto: fechou com a régua recalibrada contra um relatório real de 25 seções e a conclusão medida de que comprimento não explica a reprovação dos dois documentos legados, ou seja, régua exigente contra prática antiga e não régua descalibrada. {F18-12} fechou entregando esse documento ao conjunto de referência. {F18-13} fechou REESCRITO: a premissa dele (rubrica julga bloco a bloco) foi medida no código e é falsa, o que também matou o risco de custo de 75 chamadas por relatório, que era 3 o tempo todo. Nasceu daí a RNF-MANUT-005: número que vem de cima também se mede.

Quatro números escritos estavam divergentes do que a medição mostra, e os quatro foram acertados contra a fonte, nunca um contra o outro. (1) O parágrafo abaixo dizia que a fila tinha ido a 143 cartões, quando o conjunto medido tinha 146 fora do Planejamento antes desta sessão. (2) O Inventário declarava 31 artefatos enquanto a própria tabela de tipos dele já somava 33. (3) O placar das fórmulas do Ap.10 chegou como oito pendentes e a recontagem por classe deu onze. (4) O DRS registrava um risco de custo de 75 chamadas de modelo por relatório para julgar qualidade, e a leitura do código mostrou 3, porque a rubrica nunca julgou bloco a bloco. Nenhum dos quatro mudou o trabalho feito: os dois primeiros eram aritmética acumulada na prosa, e os dois últimos eram afirmação recebida pronta que ninguém tinha medido. É deste dia que nasce a RNF-MANUT-005.

De 115 para 123 (primeiro movimento). A auditoria dos relatórios que a operação já entregou abriu a Fase F17 com 8 cartões. Três achados a sustentam. O primeiro é um gap de bloco medido: o registro do renderizador tem 11 tipos, e os que faltam estão em uso em 4 dos 6 relatórios reais no formato v2, o que significa que hoje o produto não reproduz o relatório que a operação entrega, e isso torna o critério de adoção (A.7) inalcançável por construção. O segundo é a decisão de cadência: periodicidade é atributo da instância e não tipo de modelo, o type fica fechado em três propósitos, e a cadência escolhe contra o que o relatório compara (RN-014, ADR-016, {F17-05}). O terceiro é a guarda de comparação, que fecha um defeito com caso real registrado, comparar janela parcial com janela cheia, mais a regra de métrica não somável entre janelas ({F17-06}, {F17-07}).

De 123 para 143 (segundo movimento). O council de 2026-08-02 sobre essa mesma auditoria acrescentou 2 cartões à F17 e abriu a Fase F18 com 16; somam-se a eles o {F12-07}, nascido da verificação real da Fatia 12, e o {F18-17}, nascido da varredura de topologia da própria documentação. Na F17, o tipo de abertura herdado do sistema irmão foi DECOMPOSTO em dois neste contrato: o divisor puro section_intro ({F17-01}, reescrito) e a régua de confiabilidade reliability ({F17-09}, novo), que é DERIVADA por código e não escrita à mão, mais o hero singular ({F17-10}, novo). Com isso o catálogo do Ap.3 vai a dezesseis tipos. O {F17-08} passou a semear dois modelos Globais confirmados mais um terceiro individual da agência de origem, porque uma amostra só, em formato antigo, não sustenta apresentar uma hipótese a todas as agências como se fosse o jeito certo de fazer. A F18 tem 17 cartões e fecha classes de mentira que ainda passam (base da comparação declarada dentro da frase, tupla de identidade completa do número exibido, causalidade degradada para coocorrência sem evidência, anti-fadiga medindo variação do dado contra variação do texto, histórico mínimo por seção, vocabulário único de não medido, sazonalidade no cadastro do cliente) e conserta a régua de qualidade que travava o {F1-17} (conjunto de referência recalibrado para o tamanho real do produto, segundo critério de coerência de documento, teto de tempo por bloco que escala). Ela também escreve o limite de usabilidade das travas ({F18-10}, recusa entrega a saída legal e existe escotilha registrada) e a regra de que toda trava nasce com fixture de controle negativo ({F18-11}).

De 146 para 162 (terceiro movimento). O dono respondeu em 2026-08-03 as duas perguntas que travavam o formato do produto, e cada resposta virou uma fase. {Q4b} trouxe a geração agendada para dentro do escopo, com as quatro palavras da resposta (configurável, editável, ativável e pausável) tratadas como requisitos e não como adjetivos: nasceu a Fase F19 com 9 cartões, e a tabela de estado da composição deixou de estar escrita como evolução futura e passou a ser parte do produto (ADR-021). Junto vieram as duas consequências que já se sabia onde doem: a geração automática não publica sozinha e não ganha atalho pelas guardas de honestidade ({F19-07}), e a correção do anti-fadiga ({F18-05}) virou PRÉ-REQUISITO da agenda, porque cadência curta e automática pressiona muito mais uma guarda que hoje mede texto contra texto. {Q5b} fechou a convivência com o outro sistema de páginas de resultados: não substitui nada por enquanto, e conviver não é espelhar (RN-019, ADR-024). E a fonte que o dono apontou para o modelo de venda (a planilha de gestão que a operação usa de verdade) abriu a Fase F20 com 7 cartões e fechou o item de investigação que o Ap.9 mantinha aberto, contra a parte cara da hipótese: o corte entre geração de leads e comércio eletrônico é estrutural, mas produz UMA estrutura com vocabulário trocável e não duas, então nenhum tipo de relatório novo nasce por vertical de negócio (ADR-022) e nenhum tipo de bloco novo nasce por causa disso (ADR-023). O primeiro cartão da F20 é a conferência das fórmulas contra a planilha, porque o que se transcreveu com certeza foi a lista das métricas e a estrutura do funil, não as fórmulas campo a campo, e uma fórmula errada aqui não quebra nada: produz um número verdadeiro na forma e falso no valor. Parte dessa conferência já foi feita em 2026-08-03: a exportação da planilha não expõe fórmula de célula, mas traz notas do autor, e delas saíram quatro formas transcritas (Lucro Bruto, ROMI, CPR e CAC Payback) mais a definição de unidade do LTV. As notas também revelaram uma métrica que não estava na lista inicial, o CAC Payback, então o catálogo do Ap.10 foi de 19 para 20 entradas, e restam 11 fórmulas a conferir.

A Fatia 12 (comentários) fechou quase inteira, e a lição dela vale para o projeto. A verificação de ponta a ponta REPROVOU o que os testes aprovavam: a política de segurança de conteúdo do leitor bloqueava os três scripts inline da fatia, então o magic link nunca criava sessão e dois botões eram código morto, com a tela parecendo correta porque tudo vinha do servidor renderizado. Corrigido por autorização de hash, sem afrouxar segurança e com unsafe-inline recusado nominalmente. Um segundo defeito da mesma verificação: todo comentário assinava como "Cliente" genérico porque a consulta do leitor não selecionava a coluna de nome do autor. Fechados por prova real com lado negativo: {F12-01}, {F12-03}, {F12-04}, {F12-05} e {F12-06}. {F12-02} segue ABERTO de propósito, e não por falta de construção: a primeira metade do H1 está provada (escrita por endpoint separado autenticado, anônimo recebe 401), e a segunda metade não foi exercida (falta assumir a role do leitor público contra o banco e confirmar que INSERT, UPDATE e DELETE em comentário são recusados). Fechar sem esse controle negativo seria arredondamento: isolamento de leitura não é ausência de permissão de escrita. Nasceu {F12-07}, aberto, com a guarda genérica que impede a repetição do defeito (RNF-SEG-007): o teste que existe hoje enumera os três scripts conhecidos e por isso não reprova o quarto.

Plano de Testes, recontado em 2026-08-08 no próprio documento, e o parágrafo abaixo estava errado em quase tudo. Universo e critério: toda linha de cartão de checklist do documento de testes, pelo código entre chaves, e a marca no texto do documento (não o clique de quem lê). Placar: 163 cartões, sendo 134 Alfa (124 por requisito, numerados sem buraco de {TA-01} a {TA-124}, mais 10 gerais nomeados: visual, KPI, segurança, performance, domínio, mobile, regressão, e o trio de sanity de uso, navegação e autonomia) e 29 Beta (26 por jornada, sem buraco de {TB-01} a {TB-26}, mais 3 nomeados: navegação, feedback e ajuda); 134 mais 29 fecham em 163. Feitos: 90, todos na seção Alfa; a seção Beta está em zero, o que é o esperado, porque Beta só começa depois de Alfa fechar. Os 2 cartões Alfa novos desta rodada são {TA-123} e {TA-124}, um para cada regra nova do DRS (RF-CUR-010 e RF-CUR-011); e {TA-23} voltou de feito para aberto, porque estava fechado sobre um gesto que não existe no sistema (o motivo está no próprio cartão). O parágrafo seguinte é o texto anterior, preservado por honestidade e MORTO como fonte de número: ele afirmava 136 itens e ao mesmo tempo 113 mais 24 fechando em 137, ou seja, não fechava nem consigo mesmo, e é exatamente o tipo de número que envelhece sem ninguém perceber porque ninguém recontava.

Plano de Testes: 136 itens, contados no próprio documento. Universo e critério: cartões de checklist do documento de testes, contados pelo código entre chaves na linha do cartão, não por estimativa. Placar: 113 Alfa (103 por requisito, numerados sem buraco de {TA-01} a {TA-103}, mais 10 gerais: visual, KPI, segurança, performance, domínio, mobile, regressão, e o trio de sanity de uso, navegação e autonomia) mais 24 Beta, e 113 mais 24 fecham em 137. Eram 123 antes desta rodada e 120 na versão publicada. Os 12 cartões Alfa novos são {TA-92} a {TA-103} (um por requisito novo, mais um pela regra de fixture de controle negativo, um pela guarda de script inline e um pela varredura de topologia do publish) e os 2 Beta novos são {TB-20} e {TB-21}, um por jornada nova. Feitos: 29. Cinco são os testes Alfa de comentário provados na verificação real da Fatia 12 ({TA-69}, {TA-71}, {TA-72}, {TA-73}, {TA-74}); o {TA-70} fechou junto com {F12-02} pela conferência de privilégio da Fatia 13; seis vêm da Fatia 13 ({TA-75}, que cobre o pipeline e a conferência de privilégio do ingestor, mais {TA-76}, {TA-78}, {TA-79}, {TA-80} e {TA-18}); o {TA-DOM} fechou com a Fatia 14; {TA-66} e {TA-67} fecharam com a Fatia 15, os dois por inspeção visual do arquivo; e sete vêm da Fatia 16 ({TA-08}, {TA-09}, {TA-10}, {TA-11}, {TA-14}, {TA-16} e {TA-81}), com a nota de procedência de segunda mão registrada no topo da seção Alfa. Segue aberto o {TA-77}, pelo mesmo motivo nomeado de {F13-03}.

Fatias 1, 1b, 2, 3, 4, 5, 6, 7, 8, 9 e a maior parte da 10 fechadas; a Fatia 11 fechou o backend ({F11-01}, {F11-02}) com prova real (testes de integração 9/9 verdes e publish real), o que também move os itens de teste Alfa {TA-03} e {TA-25} para feito, e um achado de segurança corrigido no mesmo commit (a RLS de report_goal só conferia company_id, nunca que account_id pertencia àquela company; fechado estendendo a RN-009 via trigger trg_report_goal_rn009_company_matches_account, com reteste confirmando a escrita cruzada recusada). Falta a interface: nenhuma tela do painel permite ao operador importar ou ver as metas hoje, então o cartão {F11-03} segue aberto. Na Fatia 10, {F10-00} a {F10-04} estão fechados e verificados; {F10-05}, {F10-06} e {F10-07} seguem abertos, cada um com o motivo no próprio card. Seguem abertos, cada um por motivo registrado no próprio card: {F1-17} (gate D, a régua reprova 2 documentos legados do conjunto de referência, e a causa medida está endereçada por {F18-12} e {F18-13}), {F4-05} (pesquisa de mercado, falta buscador externo), {F7-04} (marca no link público, metade), {F8-07} (criativos; o bloqueio de storage CAIU com a {F15-02}, e o motivo real, medido em 2026-08-08, é que não existe onde clicar: nenhuma rota cria bloco e nenhum controle da tela envia imagem para o rascunho, ou seja, é falta de construção e não de exercício), {F8-08} (cor por relatório, falta coluna), {F8-11}, {F8-12} e {F11-03}. A Fase 9 (publicação e link) fechou inteira, mais o card {F9-13}, cuja guarda de coerência de rótulo o {F18-03} agora generaliza para a tupla de identidade completa. Da Fatia 12 segue aberto o {F12-07}. As Fatias 9, 12 (menos um cartão), 13 (menos um cartão), 14, 15 e 16 estão fechadas.

Onde o projeto está, em uma frase: as 16 fatias do plano original do bloco 9 do DRS estão entregues, e os 41 cartões abertos são de outra natureza: 13 são pontas com motivo nomeado dentro das fatias fechadas, e 28 são as Fases F17 e F18, que não existiam no plano e nasceram da auditoria dos relatórios que a operação já entrega e do council de 2026-08-02. Ou seja, o que falta não é o que foi planejado e não saiu; é o que a realidade acrescentou depois.

A Fatia 15 (PDF) fechou, e a lição dela é sobre o que a verificação de estrutura NÃO vê. O arquivo foi conferido com os olhos, página a página, convertendo as páginas em imagem: documento real de 22 blocos e 11 tipos, tema claro, cor da agência aplicada em rótulo, valor e barras do funil, e ausência de marca da agência desenvolvedora confirmada NO VISUAL e não só por busca de texto (busca de texto não pega marca em imagem, que é o modo de vazamento que importa no white-label). Nenhum bloco cortado, nenhuma página começando por número solto, sem token cru, sem objeto cru, sem NaN.

A paginação passou por três estados, e os dois primeiros eram defeito: sem regra nenhuma, o gerador cortava bloco no meio e a página começava por um número sem rótulo (defeito de rótulo produzido pela diagramação); com a regra aplicada de forma uniforme, todo bloco inteiro era empurrado para a página seguinte, a primeira página ficava com cerca de 60 por cento em branco e o documento inchava para 11 páginas. O segundo defeito só apareceu porque alguém ABRIU o arquivo, não estava em relatório nenhum de execução. A regra final é seletiva por natureza do bloco (pequeno e indivisível não quebra; longo e divisível quebra entre linhas com o cabeçalho repetindo) e o resultado medido é 8 páginas densas. Virou RNF-REN-001 no DRS e {TA-105} no Plano de Testes, escrito com o histórico das duas tentativas, porque regra por natureza é o tipo de coisa que alguém "simplifica" para uniforme sem saber que o uniforme já falhou nas duas pontas.

Duas notas de método que a fatia rendeu. A {F15-02} foi construída seguindo a Especificação do bucket que já existia no Inventário ({ART-INFRA-01}), sem invenção de escopo na hora, que é exatamente o que a REGRA-INV-1 existe para garantir. E o defeito da moldura de mídia foi corrigido nas DUAS superfícies, leitor e PDF, porque era o mesmo CSS compartilhado: não era defeito do PDF, era defeito do renderizador aparecendo em dois lugares, e corrigir de um lado só criaria a divergência entre saídas que RF-REN-005 existe para impedir.

A Fatia 16 (painel do cliente) fechou, e com ela as 16 fatias do plano original do bloco 9 do DRS estão entregues. Provado com navegador real, login real e troca de empresa pelo switcher de verdade, desktop e 390 pixels: lista de clientes; ficha vazia visualmente distinta de ficha com erro de carregamento (a com erro traz aviso e ação de tentar de novo, e nunca se confunde com "nenhum relatório", que é a RN-015 aplicada à listagem e exatamente a confusão que deixou o defeito de rota sombreada passar duas vezes); ficha com dois relatórios reais, um publicado e um revogado, com selos distintos; e o portal do cliente mostrando o publicado com link e escondendo o revogado com a mensagem certa no MESMO request. Mais 22 asserções de integração real, incluindo os negativos de isolamento que mais importam: um contato não vê relatório de outra conta da MESMA agência, e a leitura direta por identificador sob a regra de acesso de outra agência devolve nada.

NOTA DE PROCEDÊNCIA, escrita porque a diferença importa: ao contrário das Fatias 13 e 15, os screenshots desta fatia não passaram pelo crivo visual do dono do projeto. A prova é de primeira mão de quem construiu, com método correto e detalhes que indicam observação real, mas é de segunda mão do ponto de vista da aprovação. O motivo está registrado: a sessão chegou perto do limite de contexto e a escolha foi declarar isso em vez de fingir uma verificação que não houve. Se aparecer defeito visual nesta fatia, é este parágrafo que explica, e não vale ler o cartão fechado como "foi visto e aprovado".

Mudança de comportamento do produto, decidida como rollout: o gate de publicação passou a EXIGIR tom de voz. Como a tabela de configuração de identidade da agência é nova, nenhuma agência tinha tom declarado e o gate travaria todas no primeiro dia. A saída não foi afrouxar o requisito: foi semear um tom neutro por agência, editável na tela, e apagar o default volta a travar, que é a prova de que a exigência continua viva. A semente não é exceção ao H1 do RF-ADM-006, é a segunda alternativa que ele já previa, e o relatório registra que a origem do tom foi o padrão da AGÊNCIA e não a ficha do CLIENTE, distinção que é a razão de o estado de identidade existir.

Bug real corrigido de passagem, e pré-existente: a cor da agência era lida no formato errado, então NENHUM relatório com ficha preenchida mostrava a cor certa. Não foi introduzido nesta fatia, foi descoberto nela, e seguiria invisível porque cor errada não quebra nada, apenas mente sobre a marca do cliente.

A Fatia 13 (analytics) fechou 6 de 8, e o critério para fechar foi o lado negativo exercitado, nunca o positivo observado. Fechados: {F13-01} (com o ingestor LENTO a resposta continua rápida, com ele FORA DO AR a página não cai, que são dois modos de falha distintos e os dois foram provocados de propósito), {F13-02} (3 acessos reais gerados no link público, refletidos no painel, sem semear linha no banco), {F13-05} (sem referrer sai "Origem desconhecida" e nenhum canal é fabricado, visto na tela), {F13-06} (prova visual em pixel, desktop e 390 pixels, com o isolamento ATACADO de propósito: relatório de outra agência responde como inexistente e não como permissão negada, que é a resposta certa porque negar permissão já confirma que o recurso existe), {F13-07} (o negativo prova que republicar não altera a duração já registrada, sem o que a métrica viraria ruído no critério de adoção que ela alimenta) e {F13-08} (privilégio conferido NO BANCO: a role do ingestor tem zero permissão de tabela e só execução da função). O {F13-06} também provou zero distinguível de não medido na superfície de analytics, que é a RN-015 aplicada, e que papel sem a capability é recusado na URL direta e não apenas escondido do menu.

O {F13-04} fechou: a segunda cláusula foi exercitada como o cartão exigia, com varredura do HTML BRUTO de 2 relatórios publicados reais, buscados anonimamente, e zero email de verdade (o único casamento foi um campo de formulário vazio). As duas cláusulas eram fatos diferentes e foram provadas separadamente, que era exatamente o motivo de o cartão ter ficado aberto uma rodada.

O {F13-03} segue aberto, e por decisão, não por esquecimento. Veio uma ANÁLISE DE CÓDIGO argumentando que o modo apresentar é renderização no próprio navegador do que já estava carregado, e portanto nunca chama a rota pública nem qualquer contagem. O argumento é estrutural e provavelmente certo. Mesmo assim não fecha: quem analisou registrou, honestamente, que não conseguiu completar o clique real porque um guard de contexto de empresa barrou. O critério desta fase é que caminho distinto que falharia CALADO fecha por exercício e não por leitura de código, e aplicá-lo só quando é confortável seria não ter critério nenhum.

A Fatia 14 (domínio custom e white-label) fechou inteira. O teste central não foi o caminho feliz, foi o negativo do isolamento, em HTTP real: uma requisição chegando pelo domínio ativo da agência A carregando token de relatório da agência B é recusada como inexistente. Domínio custom sem isolamento é vazamento entre agências com a marca do cliente por cima, então esse é o caso que precisava ser exercitado. A verificação de posse roda contra registro DNS REAL, sem simulação, e a tela foi provada ao vivo por navegador (criar, verificar, remover). Limitação DECLARADA (ADR-020), registrada como tal e não como pendência esquecida: ativar o domínio com certificado exige hoje um passo manual no servidor, porque a infra não tem emissão sob demanda; está documentado no código e num script de provisionamento, e escrito no card, no DRS e no topo da fase para que quem for ativar saiba de antemão.

Padrão que virou requisito, porque aconteceu DUAS vezes no mesmo dia: uma rota de caminho fixo registrada depois de uma rota dinâmica do mesmo prefixo é engolida por ela e passa a responder erro para todo chamador, com a interface mascarando como "não tem nada" (o front trata erro como lista vazia). Ocorreu no painel de analytics e no domínio custom, por caminhos diferentes. A suíte não pega porque chama o handler importado direto, pulando o roteador, ou seja, o caminho testado nunca é o caminho servido, que é a mesma família do bloqueio de scripts inline do leitor ({F12-07}). Virou RNF-MANUT-004 no DRS e o cartão {F18-18}, que exige a conferência de ordem de registro, o teste batendo no HTTP real, e a varredura retroativa das rotas existentes, já que as duas ocorrências conhecidas foram achadas por acaso e não por busca.

O {F12-02} fechou de carona. Ele estava aberto exatamente por faltar o controle negativo sobre a role do leitor público, e a conferência de privilégios feita em {F13-08} confirmou que essa role segue sem permissão de escrita. É o valor de ter deixado aberto em vez de arredondar: o cartão foi fechado por um fato, e não por uma suposição que ninguém teria revisitado.

Comportamento que parecia defeito e está documentado agora: o Super Admin precisa de contexto de empresa ATIVO para ver o painel de analytics de uma agência; em modo global ele vem vazio. Isso é correto, porque a regra de acesso ao relatório é por agência e não abre exceção para o papel que enxerga todas as empresas, e uma exceção assim seria uma segunda regra de acesso ao mesmo dado (é assim que isolamento entre agências morre). Registrado no DRS (RF-ANL-006, Notas), no topo da Fase F13 e na jornada "Auditar uso" do Super Admin, porque custou tempo de investigação e voltaria a custar.

As decisões técnicas de construção foram resolvidas no DRS (bloco 9, J.4) e a descoberta de integração da plataforma-mãe já fixou os internos que o Reports reusa (Fase 0, {P0-29}). As duas decisões que travavam o formato do produto foram RESPONDIDAS em 2026-08-03 e viraram fase. {Q4b}: a geração agendada entra no escopo, configurável, editável, ativável e pausável, e por isso nasceu a Fase F19 e a report_job deixou de ser evolução (ADR-021). {Q5b}: o ModularReports não substitui nada por enquanto, os dois sistemas convivem, e a convivência não é espelhamento (RN-019, ADR-024). {Q4} ficou respondida por consequência de {Q4b}: o relatório compara períodos, e a edição agendada compara com a anterior automaticamente. Junto veio a resposta sobre o modelo de venda, que fechou o item de investigação do Ap.9 e abriu a Fase F20. Quatro decisões de produto seguem em aberto no Questionário, e são do dono: {Q1} (como uma agência parceira nova começa), {Q2} (quem libera o acesso do cliente para comentar), {Q5c} (já que os dois sistemas convivem, por qual critério cada relatório vai para um ou para o outro, e quem decide na hora) e {Q8} (as métricas comerciais da agência aparecem na página do cliente, ou são só de gestão interna). Nenhuma das quatro impede os cartões da fila atual: {Q8} tem default seguro escrito no Ap.10 e imposto por RF-REN-017. {Q3}, {Q4}, {Q4b}, {Q5}, {Q5b}, {Q6} e {Q7} já foram respondidas.


Planejamento

Concluída na aprovação do DRS. Vale 40% do projeto (seção Planejamento). Estas etapas cobrem tudo que aconteceu antes de começar a construir o sistema.

0.1 Entendimento e Elicitação

0.2 Especificação (o DRS)

0.3 Documentos companheiros

0.4 Validação e Qualidade

0.5 Publicação e Aprovação


Fase M, Mockup Navegável (pós-Planejamento, gate de aprovação)

Dependência: DRS aprovado (Planejamento fechado). A construção (F1 em diante) não começa com esta fase aberta. Concluída: mockup completo publicado em modulareasy.com/mockups/modulareasy/modularreports e aprovado.
Definição de Pronto M: mockup completo no ar, aprovado, e vinculado no DRS como guia do desenvolvimento. CUMPRIDA.

Fase F1, Protótipo do pipeline IA (Fatia 1, gates HARD de I.1)

Dependência: nenhuma além do mockup aprovado (Fase M). Fatia cravada como risco número 1 do produto (I.1): entrega o package e as interfaces identity, storage e render, o sandbox de parse isolado e a composição in-process, agnóstico à decisão de módulo, mais os gates de qualidade e segurança que reprovam o protótipo se falharem.
Definição de Pronto F1: os 4 gates HARD de I.1 verdes (zero alucinação numérica, tríade de segurança, isolamento cross-tenant, qualidade da narrativa pela rubrica 5D); package com as interfaces identity, storage e render, o sandbox de parse isolado e a composição in-process prontos para as fatias seguintes.

Fase F1b, Schema de dados (Fatia 1b)

Dependência: nenhuma (a migration não depende do chrome do Hub). Cria as tabelas do schema reports ANTES das fatias que as consomem: F2 mexe em snapshot e report_draft, F4 grava artifact, F5 lê snapshot. A migration de RLS, entitlement, RBAC e auditoria (que dependem do catálogo do Hub) fica em F6.
Definição de Pronto F1b: as tabelas de dados do schema reports existem e as fatias F2 a F5 têm onde ler e escrever, sem esperar o chrome do Hub (F6/F7).

Fase F2, Contrato de bloco e snapshot (Fatia 2)

Dependência: {F1b-01} (tabelas do schema) e {F1-15} (a composição in-process, que produz o formato de blocos e pontos de dado). Esta fatia entrega o coração de dados que serve IA, curadoria, leitor e analytics.
Definição de Pronto F2: contrato de bloco v3 estável, snapshot imutável provado, e as 6 regras de negócio de dados verdes. Serve de base para F3 (renderizador), F8 (compositor) e F13 (analytics).

Fase F3, Package renderizador (Fatia 3)

Dependência: {F2-01} (contrato de bloco). Package de funções puras que serve leitor, preview e PDF a partir do mesmo contrato.
Definição de Pronto F3: os três consumidores (leitor, preview, PDF) renderizam do mesmo package, sanitizados, com tokens por cliente e contraste AA.

Fase F4, Ingestão, quota e storage (Fatia 4)

Dependência: {F1-02} (sandbox de parse isolado), {F1-16} (interface de storage), {F1b-01} (tabela artifact). Entrada de dados do sistema.
Definição de Pronto F4: upload, quota, parse isolado e TTL funcionando ponta a ponta com um conjunto de artefatos real; nenhuma tela de acervo de artefatos.

Fase F5, Leitor público (Fatia 5)

Dependência: {F2-04} (snapshot imutável), {F3-02} (package renderizador). Serviço isolado somente leitura que serve o snapshot ao cliente final.
Definição de Pronto F5: leitor público no ar, isolado, rápido, com estados brandados e deploy próprio.

Fase F6, Role, entitlement e RBAC no Hub (Fatia 6)

Dependência: {F1b-01} (tabelas de dados já criadas). Provisiona o registro do módulo, o entitlement, o RBAC, a RLS e a auditoria que as fatias de chrome (F7, F8) e publicação (F9) vão usar. As tabelas de dados nasceram em F1b; aqui entram as camadas que dependem do catálogo do Hub.
Definição de Pronto F6: schema provisionado, entitlement desligado por default, RBAC sem papel novo, RLS provado com dois tenants, auditoria por ponto único.

Fase F7, Chrome e shell do operador (Fatia 7)

Dependência: {F6-02} (entitlement), {F6-03} (RBAC). Grupo de rotas isolado que o operador usa.
Definição de Pronto F7: chrome isolado no ar, lazy, com self-service de agência e identidade da agência aplicada.

Fase F8, Wizard e compositor (Fatia 8)

Dependência: {F1} (pipeline IA), {F2} (contrato de bloco), {F3} (package renderizador, o preview do compositor usa as mesmas funções puras), {F6}/{F7} (chrome, RBAC). Onde o operador compõe e cura.

E este cartão consertou o {F8-56}, que eu tinha fechado sem prova. Ao exercitar o caminho real descobri que aquele merge chamava criar_banco_de_teste - uma função que nunca foi gravada no arquivo (o patch que a inseria falhou numa asserção e não escreveu; o seguinte inseriu só o chamador). O script caía sempre no ramo de contenção: por acaso o comportamento era o seguro (a suíte não rodava contra produção), mas a feature não existia. Por que passou: a imagem mhub-api-test-runner:f8-33 não existia neste host, então o caminho docker - o único onde o banco isolado entra - nunca tinha sido percorrido. Imagem construída pelo Dockerfile do test-all.README.md, e agora provado ponta a ponta: banco próprio criado (mhub_test_1042565_1787057915), 52 arquivos de teste rodando contra ele, a guarda confirmando de dentro do container que não é produção, e zero bancos deixados para trás. É a mesma lição que a onda OP escreveu dois dias antes, e desta vez fui eu: card só fecha depois de exercitar o caminho real, não o que o código diz que faz. Cartão novo, achado pela obra do {F8-18} em 2026-08-13. Aquela fatia consertou uma guarda de tamanho de corpo que falhava aberta: cabeçalho ausente virava zero e aprovava; cabeçalho ilegível virava valor não-numérico e pulava a condição inteira, então a guarda simplesmente não rodava. Fail-open silencioso, a assinatura que este projeto já nomeou. O que foi medido: a mesma condição, copiada, vive em outras duas rotas do Hub, fora do módulo de relatórios. Elas não foram tocadas porque estavam fora do escopo, e a decisão de não consertar por fora está certa. Por que vira cartão em vez de nota: cobrança sem dono some na próxima leitura. Foi exatamente assim que o {F8-50} nasceu. O conserto do módulo de relatórios extraiu a guarda para um lugar único; o trabalho aqui é as outras duas passarem a usar esse mesmo lugar, não ganharem cada uma a sua cópia corrigida. Copiar o conserto reproduz o problema com a idade zerada. Cuidado, e é o que decide o tamanho do cartão: essas rotas não são do módulo de relatórios. Meça o que elas aceitam hoje antes de apertar. Uma guarda que passa a recusar o que sempre passou é regressão, mesmo sendo mais correta. Entre com o par: o caso que prova que ela pega, e o que prova que ela não ficou severa demais. Como verificar (teste primeiro): cabeçalho ausente e cabeçalho ilegível são recusados nas duas rotas; o envio legítimo que passa hoje continua passando. Aceite (H1): Dada uma rota do Hub que limita tamanho de corpo, Quando o cabeçalho de tamanho vem ausente ou ilegível, Então a requisição é recusada, E nenhuma dessas rotas mantém cópia própria da guarda.

---

### MEDIÇÃO REFEITA POR CONTA PRÓPRIA (2026-08-18) - o número se confirma, a leitura muda

Contado direto no banco, com a régua remontada do zero a partir dos path="/…" do App.tsx (não reaproveitei a tabela do {F8-53}, que é o que o cartão manda evitar):

MóduloAvisos com linkCasam com rotaNão casam
control8.181578.124
reports31042268
social303
drx2572570
chat1351350
tasks84840
opadmin880
financeiro110
Total8.9795848.395

A suspeita do cartão - "outros módulos usam convenção diferente e a régua está errada" - NÃO se confirmou. Cinco módulos estão 100% corretos pela mesma régua. O problema está concentrado em dois prefixos: /controle (8.124) e /reports (268, o resíduo do próprio módulo, cuja rota real é /relatorios). Confirmado por busca no front inteiro: /controle não existe em lugar nenhum - nem no router, nem em qualquer arquivo.

O ACHADO QUE MUDA O DESENHO DO CONSERTO, e não estava no cartão: no módulo control o campo link não é um endereço de navegação - é a chave de deduplicação. O próprio código diz ("Link canônico de dedup: /controle/alertas/task_overdue:<task_id>. Usado como discriminador único") e a dedup consulta por LIKE '/controle/alertas/task_overdue:%', em 15 pontos. E o mesmo campo é o destino do clique: NotificationBell.tsx:114 faz navigate(n.link) para qualquer valor que comece com /. Como rota desconhecida cai no path="*" → <Navigate to="/">, clicar em qualquer um dos 8.124 leva ao painel inicial, em silêncio. Não é endereço errado por descuido: é um campo com duas responsabilidades, e a segunda nunca foi honrada.

Consequência para o conserto: levar o funil do {F8-53} para o control como está o faria reprovar as 15 chamadas de dedup - que não são erro de endereço. O caminho que resolve os dois sem DDL é o control passar a discriminar por um link que existe (/alertas?..., e /alertas é rota real), mantendo a dedup pela mesma técnica com a string nova; a transição precisa cobrir os dois formatos por uma janela, senão os 8.124 antigos deixam de casar e republicam. Fica explicitamente fora do que executo sozinho: mexer na dedup de 8 mil avisos vivos do produto do dono, e a alternativa mais limpa (coluna própria de chave de dedup) é DDL em messages, fora do schema reports. Medido, relatado, nada apagado - como o cartão pede. Como verificar (teste primeiro): um aviso criado com endereço que não casa com rota declarada é recusado, em qualquer módulo; e um aviso legítimo (inclusive com trecho variável, parâmetro de busca ou fragmento) continua sendo criado. Aceite (H1): Dado qualquer produtor de aviso do Hub, Quando ele publica um aviso com link, Então o endereço é conferido contra as rotas declaradas na criação, E nenhum produtor consegue publicar endereço que não existe.

---

### FECHADO em 2026-08-18, guarda Hub inteiro ligada, e SEGUNDA MEDIÇÃO diverge da tabela acima

A guarda saiu do módulo de relatórios e passou a valer para o Hub inteiro, em publishNotification (apps/api/src/lib/notifications.ts): 20 importadores, zero insert direto em produção, fail closed. O espelho de rotas mudou de casa para apps/api/src/lib/web-routes.ts (sem re-export); o casador matchesDeclaredRoute continua único, em notif-link-scan.ts. 7 isenções NOMEADAS por prefixo, só para o módulo control, nunca por módulo inteiro, cada uma com motivo escrito, dono e cartão de saída {F8-62}; publicar sob isenção emite [notif-link][isento]; isenção MORTA reprova na guarda estática. 3 destinos mortos corrigidos com o destino medido no front: /canais-email/threads?conv=<id> (a página passou a ler ?conv), /empresas?company=<id>&suspension=<t> (com o LIKE do dedup cobrindo os DOIS formatos por uma janela) e /agencia.

A remedição de fechamento (por conta própria, antes de fechar o cartão) DIVERGE da tabela acima, e as duas ficam registradas, sem ajustar nenhuma: a tabela publicada nesta MEDIÇÃO REFEITA (2026-08-18) contava 584 casam / 8.395 não casam; a segunda contagem, feita para fechar o cartão, mediu 395 casam / 8.584 não casam. As duas linhas que a tabela dava como 100% corretas e não são: chat (135, rota real /canais-email/threads/<id> tem 2 segmentos, o link tinha 3) e control (+54, formato /admin/companies/<id>?suspension=, que não existe nem como rota de API). O cartão fecha com AS DUAS contagens escritas, não com uma corrigindo a outra.

Provas da guarda ligada: dry-run com o balde "lançaria" VAZIO antes de ligar a guarda; guarda estática 90/0; par de casos em execução 26/0 (6 endereços mortos lançam SEM gravar; 27 legítimos seguem publicando); reprovação de isenção morta provada por QUEBRA. Duas reprovas custaram a fatia inteira e as duas eram do INSTRUMENTO de teste, não da guarda: o plantio em disco usava nome fixo dentro do repo e, como sessão concorrente é requisito deste workspace, uma rodada lia o resíduo de outra como produtor real (o teto da isenção acusava "2ª publicação" num arquivo que tem uma). Isolar a escrita por PID não bastou, a varredura lê a árvore inteira; corrigido ignorando plantio alheio na varredura e limpando só o de processo morto. Provado com 3, 5 e 8 processos simultâneos.

NADA foi apagado no banco: os avisos com endereço morto seguem medidos e relatados, como o cartão sempre pediu. Sucessor nomeado: {F8-62}, o achado de produto que a medição revelou (no control o campo link tem duas responsabilidades, chave de dedup e destino de navegação, e a segunda nunca foi honrada) fica fora do que se corrige em massa aqui, por ser decisão do dono sobre dado vivo.

PERGUNTA REGISTRADA PARA O DONO, e o loop seguiu (2026-09-21). O proprio cartao diz que a escolha e decisao do dono, nao de quem implementa, entao ela nao foi tomada aqui. O que foi feito foi MEDIR, para a decisao nao sair no escuro:

  • A divida quase dobrou: sao 15.210 avisos com link em /controle/%, nao os cerca de

8,2 mil que o cartao anotou. Mais 540 em /admin/%, que caem em rotas reais.

  • O silencio esta confirmado nos dois lados: /alertas existe como rota declarada;

nenhuma rota comeca com /controle; e App.tsx:701 tem path="*" levando a <Navigate to="/" replace />. Ou seja, os 15.210 cliques vao para o painel inicial sem erro.

  • Formato real gravado: /controle/alertas/<tipo>:<uuid>, em que o sufixo depois dos dois

pontos e justamente a chave de dedup. E por isso que o campo acumula as duas responsabilidades.

Cenario 1, coluna propria de dedup. Nasce dedup_key em messages.notifications; o link passa a ser so endereco. Ganha: a dedup deixa de depender do formato de uma URL, entao mudanca de rota nunca mais reabre este defeito, e os 6 construtores passam a dizer o que fazem. Perde: exige DDL numa tabela quente e que pertence ao Hub (messages), fora do schema reports; e preciso backfill dos 15.210 antes de trocar as consultas, senao a dedup para de casar e o sistema republica tudo. Cenario 2, migrar o formato do link. O link passa a ser /alertas?..., que e rota real, e a dedup continua por LIKE com a string nova, com janela dupla de 7 dias cobrindo os dois formatos. Ganha: conserta os 15.210 cliques sem DDL e sem tocar tabela de outro schema; e o caminho mais curto ate o usuario parar de cair no painel. Perde: o campo continua com duas responsabilidades, entao a proxima mudanca de rota reabre exatamente este defeito, e a janela dupla vira divida com prazo (quem esquecer de remove-la depois deixa LIKE duplicado vivo).

Recomendacao de quem mediu, para o dono confirmar ou descartar: Cenario 2 agora, porque o dano e de navegacao e esta acontecendo em 15.210 avisos, e Cenario 1 como cartao proprio logo em seguida, porque e ele que impede a reincidencia. Fazer so o 2 conserta a tela e mantem a armadilha; fazer so o 1 demora mais para o usuario sentir.

O enunciado original do cartão, preservado abaixo: Cartão novo, achado em 2026-08-13 pela obra do {F8-47}, que foi construir o aviso vizinho e esbarrou neste. O que foi medido: a notificação de "comentário resolvido" (viva desde a Fatia 12, ou seja há quase duas semanas em produção) carrega um link para um endereço que não existe no front. Quem clica cai no painel inicial, sem nenhum aviso de que o destino não existe, porque a regra de rota desconhecida redireciona em silêncio. Por que ninguém viu: o mecanismo funciona. O aviso é criado, entregue, contado e some quando lido. Todo o caminho que alguém verificaria está correto. O que ninguém exercitou foi o clique, que é a única parte que o destinatário usa. É a família que este projeto já nomeou: peça pronta e inalcançável, com o agravante de ter passado por gate verde. Redirecionamento silencioso é o que torna isto invisível: um destino inexistente que respondesse "não encontrado" teria aparecido no primeiro clique. Cair no painel inicial parece navegação normal. O que implementar: apontar o aviso para um endereço que existe e que leva a ver o comentário, não a uma tela genérica. A fatia irmã já usa o endereço do compositor, onde o acesso ao comentário está sempre visível. Use o mesmo, não invente um terceiro. ESTE NÃO É RISCO HIPOTÉTICO: está acontecendo agora. Medido durante o deploy de 2026-08-13: o aviso do disparador de agendas está sendo publicado em produção a cada poucos minutos, para o dono, com link para endereço que não existe. Não é "alguém pode clicar um dia": é aviso morto acumulando no sino de quem usa o sistema todo dia. Comece por esse, não pelo do comentário resolvido. Já medido, e é pior do que um: a validação foi olhar os outros e achou mais um apontando para endereço inexistente, no disparador de ciclo das agendas. Dois dos três avisos do módulo levam para o vazio. O único que funciona é o que nasceu ontem, com este defeito já conhecido. Não é descuido isolado: é o que acontece quando o endereço do aviso é escrito à mão e nada confere. Por isso a guarda importa mais que os dois consertos: trocar as duas cadeias resolve hoje e o terceiro aviso nasce errado amanhã. Como verificar (teste primeiro): o endereço que o aviso carrega casa com uma rota declarada, e um endereço que não casa reprova. Guarda por conferência de tabela, não por leitura humana, senão o próximo aviso nasce com o mesmo furo. Aceite (H1): Dado um aviso do módulo entregue a alguém, Quando essa pessoa clica nele, Então ela chega à tela que trata do assunto do aviso, E nenhum aviso pode ser criado apontando para endereço que não existe.

O enunciado original do cartão, preservado abaixo: Cartão novo, escrito em 2026-08-12 a partir de uma admissão do próprio QA do {F8-46}, e a lição é de método, não de código. O que aconteceu: o QA exercitou o fluxo inteiro como super administrador, o perfil que tem todas as permissões e, por definição, nunca é recusado. Passou em tudo. O review então achou um defeito que vivia exatamente naquele buraco: uma tela oferecia ação a quem o servidor recusaria, e só aparece para quem não tem a permissão. A regra da casa que se aplica, já registrada em outro contexto: caminho negativo verde mascara o positivo morto. Aqui é o inverso e igualmente cego: o sujeito que sempre passa não prova nada sobre quem não passa. Por que vai repetir: a conta de serviço é a mais cômoda de usar, está documentada, e faz o smoke andar rápido. Ninguém erra por preguiça: erra porque o caminho fácil é o caminho errado, e nada no processo avisa. Um agravante medido na mesma fatia: naquela tela, captura de imagem não distingue o botão clicável do texto informativo: mesma cor, mesmo peso, mesmo tamanho. Ou seja, mesmo quem tentasse validar o caso negativo por imagem obteria uma prova vazia. Tem que ser pela estrutura da página ou pela resposta real do servidor. O que implementar: toda verificação de tela que dependa de permissão passa a exercitar os dois sujeitos, um com e um sem, e a prova do caso negativo não pode ser imagem. Onde isso vive é decisão da fatia: um teste em formato de matriz por permissão é o caminho mais barato e já existe precedente no produto. Cuidado ao construir: criar ator sem permissão exige registro explícito de revogação: um papel que já tem a permissão por padrão continua tendo se ninguém a revogar de fato. Foi assim que uma prova anterior se desfez ao ser medida: o usuário de teste nunca esteve sem a permissão. Como verificar (teste primeiro): um ator sem a permissão não vê a ação e recebe recusa do servidor; um ator com ela vê e usa. Os dois no mesmo teste, e o primeiro precisa falhar se a guarda for removida. Aceite (H1): Dada uma tela cuja ação depende de permissão, Quando a verificação roda, Então ela exercita um sujeito com e um sem a permissão, E a prova do caso negativo vem da estrutura ou da resposta do servidor, nunca de imagem.

O enunciado original do cartão, preservado abaixo: Cartão novo, do julgamento do QA no {F8-46} (2026-08-12), e ele é a metade que aquela fatia deliberadamente não cobriu. O que ficou resolvido: no compositor, o acesso aos comentários está sempre visível: quem abre o relatório para trabalhar encontra, sem depender de notar número nenhum. O que sobrou: nas outras duas telas, o número deixou de ser mudo e passou a levar a algum lugar, mas descobrir que existe comentário novo ainda depende de o operador visitar aquela tela e reparar. É o risco que o cartão anterior nomeou com todas as letras: contador que ninguém olha é o mesmo problema com outra roupa. Por que a fatia anterior parou aí, e a decisão foi correta: nenhum requisito do documento pede aviso ao operador: o único que trata de notificação manda avisar o autor quando o comentário é resolvido, e isso já existia. Construir canal novo teria sido escopo inventado. Então este cartão é decisão de produto antes de ser trabalho de código, e ela tem dois desfechos legítimos: Cenário 1, o operador vai atrás. Fica como está. O comentário espera na tela até alguém abrir o relatório. Serve quando a agência tem ritmo de revisão previsível: todo relatório é reaberto de qualquer jeito. O preço: um comentário urgente pode dormir dias, e quem escreveu não tem como saber disso. Cenário 2, o sistema avisa. O operador recebe sinal quando chega comentário novo. Elimina a espera invisível. O preço: mais um canal para manter, e a pergunta imediata de onde avisar (dentro do produto, por e-mail, ou num resumo periódico), porque aviso que vira ruído é ignorado, e aí volta ao Cenário 1 com custo extra. Recomendação: Cenário 2, dentro do produto, sem canal externo. O cliente escreveu esperando resposta; a assimetria de ele não saber se foi lido é o que o {F8-46} começou a corrigir. Aviso dentro do produto não cria canal novo de infraestrutura e some quando lido. Como verificar (teste primeiro): um comentário deixado por um cliente chega ao operador sem que ele precise abrir aquele relatório; e um comentário já lido não continua sinalizando. Aceite (H1): Dado um comentário novo deixado por um cliente, Quando o operador usa o produto, Então ele fica sabendo sem depender de abrir o relatório específico, E o sinal desaparece depois de lido.

FECHADO em 2026-08-18, e no ar. A recusa do tipo vetorial saiu das rotas e virou propriedade do armazenamento: image/svg+xml nao existe mais na tabela que define o que se aceita (lib/reports-asset-storage.ts), entao isAllowedAssetMime ja o recusa e todo caminho de escrita futuro herda a recusa sem que seu autor precise saber que ela existe, que era exatamente o furo do item 2 acima. A constante por chamador nomeado (ASSET_REJECTED_MIME) foi removida junto com os tres comentarios que ainda a descreviam; as duas rotas seguem respondendo o mesmo 415 REPORT_ASSET_MIME_NOT_ALLOWED (regressao provada: 40 PASS / 0 FAIL no teste do {F8-08b}). O tipo saiu tambem do mapa de extensoes, entao nem a leitura reconstroi o tipo ativo a partir de um arquivo herdado: arquivo com aquela extensao sairia como application/octet-stream, que com nosniff nao executa. Medido antes de remover: zero arquivo vetorial no volume de producao, entao nada existente deixou de ser servido. A ponta do compositor, o item 3 que o cartao dizia nao ter sido medido, foi medida, e ela desmente a suposicao confortavel: o painel nao manda politica de seguranca de conteudo nenhuma (hub.modulareasy.com responde so nosniff), ao contrario do leitor publico. A defesa que salvava a pagina do cliente nunca existiu do lado do operador, que e justamente a origem que carrega a sessao dele. Por isso as duas rotas que servem o byte (a do painel e a interna) passaram a manda-lo inerte por si: default-src 'none'; sandbox mais nosniff. E defesa em profundidade: o armazenamento ja nao aceita tipo ativo, e isto cobre o dia em que alguem aceitar um de novo. O caso que reprova sem o fix nao passa por nenhuma das duas rotas: e um chamador que grava direto no armazenamento, o formato exato do terceiro caminho que nascia furado. Verificado devolvendo o tipo a tabela: 3 casos reprovam, e o (3) grava de verdade o documento com script. Com a guarda, 5 PASS / 0 FAIL. Ha controle positivo (os 4 tipos raster seguem aceitos) e controle negativo (o mesmo chamador direto grava um PNG), entao verde nao pode significar "recusa tudo" nem "o ambiente nao deixou gravar". Provado em producao, nao no teste: imagem reconstruida, mhub-api recriado (62 conteineres antes e depois), e uma requisicao real a rota interna devolveu 200 com content-security-policy: default-src 'none'; sandbox e x-content-type-options: nosniff. Fixture nominal criada so para essa medicao e removida na sequencia (zero arquivo restante). Merge 657d8d0.

FECHADO em 2026-08-18, e no ar. O cartao mandava medir a causa antes de consertar, e a medicao derrubou a hipotese que ele mesmo carregava. Ele supunha "o expurgo falha e mesmo assim carimba". Nao e isso: purgeExpiredArtifacts empurrava para a lista de purgados tudo que nao lancasse, inclusive o {deleted:false} com que o proprio adaptador diz "nao havia byte nenhum aqui". Um desfecho que significa nao fiz nada era contado igual a um que significa removi. Nao havia falha para relatar: havia uma ausencia sendo lida como sucesso. O conserto: tres desfechos, contados separados. removed (o byte saiu do armazenamento nesta passagem, o unico que significa trabalho), absent (nao havia byte: id ja purgado antes, ou artefato cujo parse falhou e por isso nunca chegou a ser escrito) e failed (a tentativa lancou, e a linha nao sai, para a proxima passagem tentar de novo). A linha do absent continua saindo de proposito: reter faria a varredura tentar para sempre sobre um byte que nao existe. O que o cartao exige nao e reter a linha, e o relato parar de mentir. A auditoria por agencia passou a nomear os dois desfechos (removed_artifact_ids e absent_artifact_ids), mantendo artifact_ids para nao quebrar leitor antigo. Era exatamente essa indistinguibilidade que deixou 8 arquivos orfaos com a auditoria afirmando trabalho feito. Provado em producao, com a varredura real: fixture nominal de dois artefatos vencidos, um com byte no disco e um sem. O relato saiu 2 candidato(s), 1 removido(s) do disco, 1 sem byte no disco, 0 falha(s), com o identificador do ausente nomeado no aviso. Antes, essa mesma passagem teria dito "2 purgados". O byte do primeiro saiu do disco, as duas linhas sairam da tabela, e o registro de auditoria gravou removed_count: 1 e absent_count: 1 com os identificadores. Fixture removida por completo (zero arquivo, zero linha restante). 6 casos no pacote, e o que reprova sem o fix e o par assimetrico. Ha os dois controles espelhados (todos com byte, nenhum com byte), entao verde nao pode significar "classifica tudo como ausente" nem "classifica tudo como removido". Verificado devolvendo o arquivo ao estado anterior: 0 PASS / 6 FAIL. Regressao medida contra main com a suite inteira: 5 falhas identicas nos dois lados (pre-existentes, de ambiente) e uma instavel sob carga que, isolada, passa nos dois lados em 3 rodadas. Zero regressao introduzida. ACHADO NOVO, e o cartao nao o previa: ha um SEGUNDO caminho que produz orfao. A chave estrangeira de reports.artifact e ON DELETE CASCADE sobre reports.report. Apagar um relatorio leva as linhas de artefato sem tocar em byte nenhum, e nenhuma correcao na rotina de expiracao alcanca isso, porque a rotina nunca chega a ver essas linhas. Medido por identificador nos 8 orfaos: 6 vieram do expurgo (relatorio vivo, linha apagada, que e o defeito corrigido aqui) e 2 vieram do cascade (relatorio ja apagado). E a razao de o {F8-20} ter nascido varrendo diretorio e nao tabela. DECISAO DO DONO, como o cartao determina: os 8 arquivos seguem no disco, somando 52 KB, todos de 05 a 09/08. Apagar arquivo de producao nao e decisao de quem implementa. Lista nominal: 5ed3f61e 8 KB, 614eeda4 8 KB, c3b763fb 8 KB, c9d92a51 8 KB, c68b3f9a 4 KB, fe92b019 4 KB (expurgo); 2695d227 8 KB, 1f16cabf 4 KB (cascade). Aritmetica que fecha: 24 arquivos no disco menos 16 linhas vivas igual a 8 orfaos. Merges ad22a52 (pacote) e 2e24f86 (Hub).

FECHADO em 2026-08-18, e no ar. O cartao dava duas saidas, e a implementada e a segunda: o caminho que CRIA o compartilhamento ganhou guarda propria, com o motivo escrito. E ela que nao depende da fatia de eliminacao (que segue em branch de outra frente, nao mergeada): fecha a porta antes que o dano tenha por onde acontecer, que e o que "bloqueante da fatia" significa. Dois achados de medicao mudaram a implementacao. Primeiro: media nem esta em BLOCK_TYPES, entao barrar "o bloco de midia" nao protegeria nada. O vetor real e props, um mapa livre em qualquer tipo de bloco, e um hero com props.asset_id cria exatamente o mesmo compartilhamento. Por isso a guarda e por forma, nao por tipo de bloco. Segundo: dois modelos em producao ja carregam referencia a arquivo hoje, ou seja, o caminho nunca foi teorico. A guarda vive no funil unico (toTemplateEnvelope), nao em cada rota. Os quatro caminhos de escrita de modelo passam por ele (criar, editar, duplicar, criar-a-partir-de-relatorio), e dois deles nao passam pelo schema de entrada, porque copiam blocos que ja estao no banco. Uma guarda no schema teria deixado duplicar e criar-a-partir-de furados em silencio, que e o mesmo modo de falha que o {F8-19} corrigiu noutro lugar no mesmo dia. Provado por medicao e nao por leitura: os tres TEMPLATE__FAILED que seguem devolvendo 500 (apagar, promover, despromover) foram conferidos um a um e nenhum grava default_blocks. O criterio e nominal por sufixo (asset_id, sha256) e desce a arvore inteira, para que campo novo de referencia (cover_asset_id, logo_asset_id) ja nasca barrado sem ninguem lembrar de atualizar a guarda, e para que referencia aninhada em props.items[0].foto.asset_id seja pega igual a uma no topo. Campo vazio (asset_id: null) nao acusa: e campo vazio, nao referencia, e barra-lo faria a guarda reprovar o caso normal. A recusa e relatada, como o cartao exige: 422 TEMPLATE_BLOCK_ASSET_REF, com o campo exato que a causou e o motivo em linguagem humana. Se um caminho futuro esquecer de traduzir, o pior caso e um 500 no lugar de um 422: a gravacao continua barrada, porque quem barra e o funil. A guarda falha fechada. 12 casos, 0 falhas. O que reprova sem a guarda inclui duplicar um modelo legado, o caminho que nao passa por schema. Verificado removendo a guarda do funil: os tres caminhos gravam de verdade, e o duplicar cria uma segunda copia com a mesma referencia, que e o dano do cartao acontecendo na medicao. Ha controles negativos (modelo normal, campo vazio, palavra "asset" solta) para que verde nao possa significar "acusa tudo". Typecheck limpo, regressao 40/40 em reports-identity, e a guarda conferida dentro da imagem que serve producao apos o deploy (62 conteineres antes e depois, hub 200). DECISAO DO DONO: os 2 modelos legados com referencia a arquivo seguem no banco, ambos com 0 relatorios usando: bb2f87e5 "F820 Modelo da Agencia" (na agencia V4 Percus, cliente real) e 88574064 "F820 Modelo GLOBAL" (sem agencia). Sao fixtures da frente do {F8-20}, e entram na mesma decisao de limpeza do {F8-41}. A guarda nova impede que nascam novos e impede que estes sejam duplicados, mas nao apaga o que ja existe: apagar dado de producao nao e decisao de quem implementa. Merge 3807379.

DIAGNOSTICO de 2026-09-22, e ele MUDA o que este cartao e. O resumo semanal nao quebrou: ele nao rodou porque o agendador inteiro estava fora do ar em TODAS as tres segundas.

  • O job esta ATIVO e sempre esteve (control.cron_jobs, weekly_digest, is_active=t,

schedule 23 8 1), e o ultimo run consta como success em 31/08. Nao ha UMA execucao com falha registrada. O defeito nao deixou rastro porque nao houve tentativa.

  • As execucoes eram perfeitamente semanais ate parar: 27/07, 03/08, 10/08, 17/08, 24/08,

31/08. As tres segundas seguintes (07/09, 14/09 e 21/09) nao tem registro nenhum.

  • **Varrendo cron_job_executions desde 25/06 (sem expurgo na tabela, 2.312 execucoes), ha

TRES buracos em que NENHUM job rodou, de nenhum tipo: 01 a 10/07 (10 dias), 07 e 08/09 (2 dias) e 14 a 20/09 (7 dias). Sao 19 dias sem agendador em tres meses. CORRECAO de 2026-09-22: a primeira leitura deste cartao disse 6 dias e 18 no total; 14/09 tambem tem zero execucoes, entao o terceiro buraco comeca nele. E a volta foi as 11:07 de 21/09, depois do horario do digest (08:23): a quarta semana se perdeu por 2h44**, e uma recuperacao com 3h de folga a teria salvado.

  • So o terceiro buraco era conhecido (a parada da API de 14 a 21/09, achada pelo fiscal em

21/09). Os outros dois ninguem sabia, e o de julho durou dez dias.

  • Nos dias dos buracos faltam ate os jobs de hora em hora (auto_escalation, 24 execucoes

por dia), o que descarta "tick perdido" e prova parada do processo.

O que isso ensina sobre o mecanismo, e vale para os 6 jobs, nao so para o digest: o agendamento e setInterval de 60s dentro do processo da API, com matcher de minuto exato e sem recuperacao. Job de hora em hora perde um tique e o proximo cobre; job semanal perde o tique e perde SETE DIAS. Somando a isso que o processo pode simplesmente nao existir naquele minuto, o resumo semanal virou o unico sintoma visivel de uma queda, e um sintoma que so aparece uma vez por semana.

O cartao passa a exigir DUAS coisas, e a primeira nao e o digest:

  1. Recuperacao (catch-up): ao subir, o agendador compara o que deveria ter rodado com o que

rodou e executa o que ficou para tras, em vez de esperar a proxima janela. Sem isso, toda reinicializacao em cima de um horario agendado custa um ciclo inteiro daquele job.

  1. Detector de AUSENCIA, que e o que o cartao ja pedia: reprova quando um job nao roda ha

mais de um periodo dele. Os 19 dias existiram porque ninguem monitora o que nao aconteceu. CORRECAO de 2026-09-22 sobre o last_run_status, e ela piora o quadro: ele nao guarda o ultimo sucesso, como este cartao afirmou antes. Ele grava o resultado da ultima tentativa (running -> success/error, control-jobs.ts:1512 e :1547). O problema nao e a semantica do campo: e que nao existe campo nenhum para a tentativa que DEVERIA ter havido. Por isso o par (last_run_at, last_run_status) nunca consegue dizer "atrasado", nem se alguem corrigir o sentido dele. Fonte de verdade para ausencia e a ocorrencia esperada e nao ocorrida, calculada da propria cron, nunca o ultimo registro bom. E o detector NAO pode morar dentro do processo da API: seria cego exatamente quando o agendador morre, que e o unico momento em que ele importa. Reprova fechar so religando o digest, ou so olhando o digest: o defeito e do agendador.

A CAUSA das tres quedas, medida pela sessao fiscal em 2026-09-22, e nao e infra: fomos nos. No host nao houve reinicio do daemon do Docker desde 25/06, ha zero eventos de falta de memoria, e a maquina esta de pe sem reiniciar desde 30/04. Nada externo derrubou o container. Somado ao fato de que o mhub-api era o unico container mhub-* com politica de reinicio no, o que sobra e o simples: alguma sessao parou o container (deploy, rebuild, teste) e nao o subiu de volta, e a politica no transformou cada parada pontual em parada indefinida. Indicio, declarado como indicio e nao como fato: o buraco de 01 a 10/07 contem a data de um wipe de ambiente (ha um _BACKUP-PRE-WIPE-2026-07-05 no repositorio). Os logs daquele container nao existem mais para fechar a prova. Consequencia para a fila: esta porta ja foi fechada pelo {P0-A2}, que criou o caminho unico de recriacao com a politica junto e o verificador que reprova container sem ela. As tres paradas so foram possiveis porque qualquer mao podia parar e esquecer, e nada perguntava depois. Este cartao trata do que acontece quando uma parada ocorre, nao de evita-la.

FECHADO em 2026-08-18, e no ar. GET /:id/preview ja CHAMAVA fn_resolve_identity, a mesma funcao que o publish usa, e jogava a marcacao fora: o campo era resolvido e descartado uma requisicao antes de chegar em quem compoe. O trecho quebrado era o entre a funcao e a tela, nao a funcao (essa tem cobertura desde {F8-08a}). No servidor, a correcao e um campo. Na tela, o compositor passou a dizer de onde veio a cor, em linguagem humana, na secao Identidade que ja existe, sem canal novo. Os quatro estados sao ditos de forma diferente: report_override como escolha ("Cor escolhida neste relatorio" - chamar isto de heranca seria dizer o contrario do que aconteceu), declared como cor da ficha do cliente, e agency_default e gap em tom de aviso, com o que fazer para sair do estado. 4 casos, 0 falhas, exercitando a rota real com os tres cenarios do aceite. O quarto exige que os tres sejam distinguiveis entre si - sem ele, os tres primeiros passariam com a rota devolvendo sempre o mesmo valor. Achado ao montar a fixture: a ficha de identidade visual do cliente nao e coluna de hub.accounts, e tabela propria (hub.account_identidade_visual), medido no schema depois de a primeira versao do teste falhar assumindo o contrario. O SMOKE VISUAL ACHOU TRES DEFEITOS QUE O TESTE VERDE NAO PEGAVA, e e a licao do cartao: (1) o aviso nascia dentro da secao Identidade, que e colapsavel e comeca fechada - o aviso que RF-ADM-006 exige "em palavras" so aparecia para quem ja tivesse ido procurar. Aparecer sob clique nao e aparecer. Os dois casos de advertencia passaram a ficar sempre visiveis, fora do acordeao; os informativos seguem dentro, onde sao contexto de quem vai mexer na cor. (2) no tema escuro o corpo do aviso saiu em rgb(28,19,3), quase preto, sobre fundo escuro: usei text-warning-foreground (cor para fundo solido) sobre fundo translucido. A varredura mostrou que esse token tinha uma unica ocorrencia no repo inteiro, a minha. A correcao nao foi trocar a classe: foi parar de montar a caixa a mao e usar o primitivo Callout ({DS-01}), criado justamente para fechar essa familia - deixar uma caixa artesanal ali seria abrir a 42a variacao do que aquele cartao fechou. (3) Callout nao repassa props extras, entao os marcadores de teste passados a ele seriam descartados em silencio, e o typecheck nao acusa. Sem o wrapper, o proprio smoke que achou os dois primeiros defeitos deixaria de encontrar o elemento, e eu leria "sumiu" como "corrigi". Medido na producao, na tela, com a secao ainda fechada (aria-expanded=false): aviso visivel com altura real, procedencia agency_default, texto completo, icone presente, e contraste do corpo de 9,75:1 no tema escuro e 4,81:1 no claro (WCAG AA pede 4,5). Captura de imagem nao foi possivel nesta sessao porque o painel do navegador nao compoe quadros; a verificacao foi por medicao do renderizado (posicao, cor computada, contraste, visibilidade), e isso esta dito aqui em vez de declarado como se eu tivesse olhado a imagem. Merges 90b8923 (funcionalidade) mais os dois de correcao vindos do smoke. RF-ADM-006, RF-CUR-012, RN-020 item 1.

INVENTARIO NOMINAL (passo 1) FEITO em 2026-09-21, e ele MUDA o cartao.

  • O acervo nao e 23, sao 262, medidos em reports.report: 167 rascunhos e 95 revogados,

zero publicados. O cartao foi escrito em 10/08 e o numero cresceu mais de dez vezes desde entao, o que confirma a tese dele: a torneira segue aberta e ninguem e dono do conjunto.

  • Por agencia: F4-05 Market Research Smoke B 164 (141 com link vivo sem expiracao),

Agencia Teste 59, Modulareasy 32, ADS 4 PROS [ADOS] 6, F14 WL Agencia A 1. As quatro primeiras sao contas nossas; a exposicao real e a quinta.

  • Os 6 da parceira, nominalmente: cinco estao sob um cliente chamado *Cliente Smoke

ModularReports verificacao branding* (fixture nossa, 05 a 10/08, um deles com a propria instrucao "temp, revogar apos smoke" no titulo) e um esta sob AutoWorx [AURX], que e CLIENTE REAL da parceira (conta criada em 01/07), com titulo "Teste", criado em 14/08.

  • PASSO 2 EXECUTADO, e so nele: o unico rascunho com link vivo sob o Cliente Smoke

(2a0c84b6) foi revogado, com retrato antes e depois. Revogar e reversivel e tira a exposicao imediata, que e o que o proprio cartao manda fazer antes de apagar.

  • PERGUNTA REGISTRADA, e o loop seguiu: o relatorio "Teste" sob AutoWorx **nao foi

tocado. Ele e posterior a medicao original do cartao, esta dentro de um cliente real, e nao ha trilha que diga quem o criou (nao ha registro de autoria na tabela). Pode ser fixture nossa colocada no lugar errado ou pode ser o proprio parceiro experimentando a plataforma. Revogar trabalho do parceiro por deducao seria pior que a exposicao que se quer remover.** Quem pode responder em um minuto e o dono, perguntando a ADS 4 PROS.

  • O que este inventario ensina sobre o escopo: o passo 3 (fechar a torneira) deixou de ser o

menos urgente. Enquanto ele nao existir, cada obra nova soma fixture, e o proximo inventario achara um numero maior que 262. A ordem util passou a ser 3, depois 1 e 2 de novo, porque inventariar um acervo que cresce e enxugar gelo.

PASSO 2 CONCLUIDO em 2026-09-21, com GO do dono para os da parceira. Palavras dele sobre o relatorio que eu havia segurado: "A conta de cliente e real mas as acoes na ferramenta foram testes. Os relatorios nao sao reais ainda." Com isso:

  • ADS 4 PROS: 6 de 6 revogados, incluindo o que estava sob o cliente real AutoWorx.

Links vivos sem expiracao na parceira: 0. Retrato tirado antes e depois.

  • F4-05 Market Research Smoke B: 141 revogados de uma vez. E conta de smoke pelo proprio

nome, e os titulos confirmam (Wire A a Wire G, da fatia F4-05). Reversivel.

  • Sobraram 24 links vivos, todos em contas NOSSAS e nenhum em parceira: Modulareasy 22,

F14 WL Agencia A 1, Agencia Teste 1.

  • Os 22 da Modulareasy NAO foram tocados de proposito, e e triagem nominal pendente: ali

fixture e trabalho real convivem. QA sem logo agencia branding real, teste e Smoke direct fetch sao nossos de teste, mas Fechamento Julho 2026, Diagnostico do semestre e Lancamento Inverno tem cara de relatorio real de dogfooding. Revogar em bloco aqui seria o mesmo erro que segurar o AutoWorx evitou, so que na nossa casa. PASSO 3 EXECUTADO em 2026-09-22, com GO do dono e conferencia cruzada do fiscal a cada lote. O acervo foi de 262 relatorios para 2, e as duas primeiras pernas do H1 fecham: zero contas de teste visiveis para a parceira e zero links vivos sem expiracao.

iniciofim
empresas934
contas18289
relatorios2622
pessoas7575
projetos DR-X99

O que protegeu a execucao, e vale mais que o resultado:

  • Identificar por NOME apagaria 57 empresas de uma vez. As 93 empresas tinham apenas **11

nomes distintos** (uma fixture repetida 57 vezes, outra 24). Toda exclusao foi por id.

  • 155 de 159 chaves estrangeiras para hub.companies sao CASCADE, alcancando 163 tabelas:

errar a identificacao nao erraria uma linha, erraria um banco.

  • Trava por lote exigindo o numero exato, com DR-X e users_profile conferidos **dentro da

mesma transacao**; se qualquer um mexesse, abortava. Nenhum dos dois mudou em momento algum.

  • Backup aberto antes de usar (pg_restore --list, 230 tabelas com dados), nao so criado.

A "Agencia Teste" foi preservada e a medicao provou que estava certo: e a maior base do ambiente (44.899 linhas em 67 tabelas) e guarda os 9 projetos DR-X. Sairam dela apenas as 60 contas de smoke criadas em lote, nunca a empresa. A TERCEIRA PERNA CONTINUA ABERTA, e e a que importa para nao repetir: a torneira. Acervo zerado hoje nao impede o proximo smoke de plantar 57 empresas amanha, e foi exatamente esse padrao que produziu o acervo. Enquanto obra de verificacao puder criar fixture fora de uma conta isolada e sem expiracao por construcao, este cartao volta.

ATUALIZADO em 2026-08-18: passos 2 e 3 FEITOS e no ar. So o passo 1 (apagar) segue aberto, porque e irreversivel. O PLACAR MULTIPLICOU POR 11 EM 8 DIAS, e recontar mudou a natureza do problema: o cartao registrou 23 relatorios em 10/08. Hoje sao 262, com 84 PUBLICADOS (o cartao dizia 2), todos sem expiracao e todos sem senha. Numero velho de cartao subestima; a diferenca entre "sujeira acumulada" e "84 URLs publicas abertas" estava em medir de novo antes de agir. Passo 2 (revogar) FEITO. Os 84 foram revogados sob uma guarda que aborta se algum publicado estiver sob conta que nao case o padrao de teste; a consulta de controle devolveu zero, entao nenhum dado de cliente foi tocado. Provado ao vivo: um token que respondia 200 agora responde 410. Restam 0 publicados. Isso e reversivel e era o que tirava a exposicao imediata. Passo 3 (torneira) FEITO. A causa nunca foi descuido: cada obra limpou o que ela mesma criou e estava dizendo a verdade. Faltava escopo. O padrao da casa manda derivar o ator do banco em vez de escreve-lo a mao, e isso esta certo, mas a derivacao pega a primeira agencia que casa o criterio, e essa pode ser a de um cliente real. Foi assim que a conta "Cliente Smoke" foi parar na agencia parceira: ninguem decidiu, o teste perguntou "me da um team_manager" e o banco respondeu com um de verdade. fixtures/escopo-de-fixture.ts troca "a primeira que aparecer" por "a de fixtures, ou falha" (fail-closed), e a guarda e por excecao nomeada: os 31 legados ficam declarados e congelados, e arquivo novo ja nasce coberto. A guarda me pegou enquanto eu a escrevia: montei a lista de legados a mao a partir de um head -20 truncado, e ela acusou os 11 que faltavam. Regenerei a lista pela varredura. E a tese do proprio cartao acontecendo com quem o estava fechando. Tambem limpo nesta sessao: os 8 arquivos de artefato orfaos do {F8-59} (todos sob conta de smoke da casa; o disco agora tem 16 arquivos para 16 linhas, aritmetica fechada) e uma conta de fixture que eu deixei na V4 Percus nesta mesma sessao, por ordem errada no meu proprio codigo de teste (registro de limpeza depois do passo que podia falhar, corrigido em 1bc977a). O QUE FALTA, E E A UNICA COISA QUE DEPENDE DO DONO: apagar as contas e relatorios de fixture. Nada disso e dado de cliente (medido: nenhum publicado estava fora de conta de teste). A exposicao ja esta neutralizada pela revogacao, entao nao ha urgencia; o que resta e higiene. Distribuicao das contas de teste por agencia: Agencia Teste 67, F4-05 Market Research Smoke B 24, Modulareasy 3, F8-25 Race Smoke Artifacts B 2, F4-07a Smoke B 1, e V4 Percus 1 (esta ultima e a que aparece para uma agencia parceira: 3ef6481f, "Cliente Smoke ModularReports verificacao branding", com 5 relatorios, todos ja revogados). Tres agencias inteiras (F4-05 Market Research Smoke B, F8-25 Race Smoke Artifacts B, F4-07a Smoke B) sao fixture e podem ir junto. Merge d690a4e.

Definição de Pronto F8: wizard completo dos 4 passos e compositor com curadoria, regenerar, criativos, whitelist e apresentar, todos com proveniência preservada.

Dependência: {F2-04} (snapshot), {F8} (compositor). Onde o link nasce.
Definição de Pronto F9: publicar, revogar, republicar e o modal completo (senha, expiração, QR, card) funcionando ponta a ponta, com a republicação setando orphaned nos comentários dos blocos removidos; este é o marco que o critério de adoção (A.7) mede.

Fase F10, Templates (Fatia 10)

Dependência: {F1b-01} (tabela template), {F6} (RBAC e hub.is_super_admin()), {F8} (wizard usa o template no passo 1). Regra que rege a fase inteira: RN-013. Todo template nasce individual (da agência de quem criou) e só o Super Admin o marca como Global. A ordem dos cartões é a da dependência: primeiro o escopo existe no schema ({F10-00}), depois o CRUD ({F10-01}, {F10-02}), depois os dois gestos que o escopo habilita ({F10-03}, {F10-04}).
Definição de Pronto F10: escopo Global e individual valendo no schema e na tela, biblioteca com CRUD completo, "salvar como template" funcionando, promoção e despromoção exclusivas do Super Admin com auditoria, duplicação de um Global gerando cópia individual desatrelada, mais os três achados do fechamento (contagem de uso, leitura do log de auditoria na tela e o texto do estado vazio do Super Admin) resolvidos.

Fase F11, Importação de metas (Fatia 11)

Dependência: {F2-04} (snapshot copia metas), {F9} (publish). A Fatia 9 já nasce com o recorte mínimo de leitura de metas para o bloco planejado versus realizado; esta fatia é a importação estruturada completa (DRS J.4).
Definição de Pronto F11: importar metas e ver a comparação planejado vs realizado num relatório publicado, sem qualquer tracking contínuo criado, e o operador consegue concluir a importação e ver as metas listadas pelo próprio painel, sem chamar a API por fora.

Fase F12, Comentários (Fatia 12)

Dependência: {F5} (leitor público), {F2-01} (id estável do bloco), {F9-11} (quem seta orphaned na republicação é o fluxo de F9). Comentário logado ancorado. Lição desta fatia, registrada porque vale para o projeto inteiro: a verificação de ponta a ponta reprovou o que os testes aprovavam. A própria política de segurança de conteúdo do leitor (sem script-src declarado, caindo no default-src 'self') bloqueava os três scripts inline que a fatia introduziu. Efeito: o magic link nunca criava sessão, e os botões "Comentar" e "Ver trecho no relatório" eram código morto. A tela PARECIA certa porque tudo vinha renderizado do servidor, e a suíte passou porque teste não roda navegador com política aplicada. Corrigido sem afrouxar segurança, por autorização de hash, com os hashes computados a partir das MESMAS constantes que montam as tags, então tag e hash não têm como divergir; unsafe-inline foi recusado nominalmente, porque o leitor é internet-facing e renderiza narrativa de inteligência artificial e texto de Contact (verificado: zero unsafe-inline em script-src). Segundo defeito da mesma verificação: todo comentário aparecia assinado como "Cliente" genérico, porque a coluna de nome do autor existia no banco desde a migração de 2026-07-31 e a consulta do leitor simplesmente não a selecionava. A guarda genérica que impede a repetição disso nasceu como {F12-07}.
Definição de Pronto F12: comentário logado, ancorado, sobrevivente a republicação e com resolução notificando o autor, funcionando ponta a ponta, PROVADO em navegador real com a política de segurança aplicada (e não só em suíte de teste), com a guarda genérica de script inline no lugar. Estado em 2026-08-02: {F12-01}, {F12-03}, {F12-04}, {F12-05} e {F12-06} fechados por verificação real; {F12-02} aberto por metade de H1 sem prova (falta o controle negativo sobre a role do leitor); {F12-07} aberto.

Fase F13, Analytics (Fatia 13)

Dependência: {F5} (leitor público emite os acessos), {F9} (link publicado). Medição de audiência. Contexto de empresa ativo é obrigatório para o Super Admin ver este painel, e isso NÃO é defeito. Em modo global (sem empresa ativa) o painel vem vazio, porque a regra de acesso ao relatório é por agência e não abre exceção para quem enxerga todas as empresas. O comportamento é coerente com o resto do produto (Relatórios é módulo por agência, RF-ADM-001) e é o correto: uma exceção para o papel global significaria uma segunda regra de acesso ao mesmo dado, e regra de acesso duplicada é como isolamento entre agências morre. Está escrito aqui e no DRS (RF-ANL-006) porque custou tempo de investigação para quem chegou sem saber, e vai custar de novo.
Definição de Pronto F13: painel de analytics por agência com visualizações, último acesso, referrer, exclusão de sessão interna e duração de produção, isolado por tenant, alimentado por um ingestor de eventos separado do leitor. Estado em 2026-08-02: {F13-01}, {F13-02}, {F13-05}, {F13-06}, {F13-07} e {F13-08} fechados com lado negativo exercitado; {F13-03} aberto (falta exercitar o modo apresentar, que é o segundo caminho de entrada nomeado pelo H1) e {F13-04} aberto (falta varrer o HTML público em busca de email cru). Os dois eram verificações baratas e nenhum dos dois era falta de construção. Atualização de 2026-08-08: os dois fecharam. {F13-04} fechou em 2026-08-02 (varredura do HTML público confirmou zero email cru, ver o cartão). {F13-03} fechou em 2026-08-08, mergeado e deployado (fonte única de contagem de visualização, ver o cartão). Fase F13 FECHADA, 8 de 8.

Fase F14, Domínio custom e white-label (Fatia 14)

Dependência: {F7} (chrome), {F9} (link). Última camada de branding por agência. Limitação DECLARADA desta fase (ADR-020), não pendência esquecida: ativar o domínio com certificado exige hoje um passo MANUAL no servidor, porque a infra não tem emissão de certificado sob demanda. O ciclo do domínio e a validação de posse funcionam sozinhos; só a emissão do certificado tem esse passo, documentado no código e num script de provisionamento. Está escrito aqui para que quem for ativar um domínio saiba de antemão, em vez de descobrir na hora e tratar como defeito.
Definição de Pronto F14: domínio custom por agência funcionando com validação de posse obrigatória, entidade agency_domain e tela de gestão; a tela nova entra numa iteração do mockup. Estado em 2026-08-02: FASE FECHADA, com o isolamento white-label provado pelo negativo em HTTP real e a emissão de certificado registrada como limitação declarada (ADR-020), não como pendência.

Fase F15, PDF condicional (Fatia 15)

Dependência: {F3-02} (package renderizador). Reuso do gerador da plataforma-mãe. Lição desta fase, e o motivo de a regra de paginação estar no DRS (RNF-REN-001): o uniforme já foi tentado e falhou nas DUAS pontas. A primeira versão não tinha regra nenhuma e cortava bloco no meio da página, deixando a página começar por um número solto sem rótulo, que é defeito de rótulo produzido pela diagramação. A primeira correção resolveu o corte, mas aplicou a regra de forma CEGA, empurrando cada bloco inteiro para a página seguinte: a primeira página ficou com cerca de 60 por cento em branco e o documento inchou para 11 páginas. Esse segundo defeito só apareceu porque alguém ABRIU o arquivo; não estava em nenhum relatório de execução. A correção final é seletiva por natureza do bloco (pequeno e indivisível não quebra; longo e divisível quebra entre linhas com o cabeçalho repetindo), e o resultado é 8 páginas densas, sem corte e sem vazio. Quem for simplificar isso depois precisa saber que o simples já foi tentado.
ALERTA de 2026-08-03 RESOLVIDO em 2026-08-05: a reintegração terminou e o código chegou à linha principal e à produção. A fase do PDF (junto das Fatias 11 a 20 inteiras) foi mergeada na linha principal e colocada em produção em 2026-08-05, com QA e revisão de código independentes rodadas pela primeira vez sobre o pacote acumulado (zero bug bloqueante, zero regressão fora do escopo). A rota de PDF está confirmada respondendo em produção. A prova antiga (visual, página a página) segue válida porque foi feita sobre o MESMO código que chegou à produção, sem alteração no caminho. Lição de processo preservada, porque continua valendo para qualquer fase futura: encadear branch por fase cria dependência invisível, e uma fase que nasce da branch errada desaparece sem aviso, sem que teste, gate ou suíte apontem, porque todos rodam dentro da branch onde o código obviamente existe.
Definição de Pronto F15: PDF gerado pelo mesmo package do leitor, condicional à disponibilidade do gerador, sem fetch de rede na geração, com paginação por natureza do bloco (RNF-REN-001) e verificação visual do arquivo página a página, porque as duas falhas conhecidas de paginação não aparecem em teste de estrutura. Estado em 2026-08-02: FASE FECHADA.

Fase F16, Painel do cliente (Fatia 16, última fatia)

Dependência: {F1b-01} (as tabelas de dados já nascem no schema do dia 1, incluindo o modelo de identidade do cliente). Fecha o ciclo de administração do cliente final. NOTA DE PROCEDÊNCIA DA PROVA, e ela vale para os 7 cartões desta fase. Diferente das Fatias 13 e 15, cujas evidências visuais foram abertas e conferidas pelo dono do projeto, os screenshots desta fatia NÃO passaram pelo crivo visual dele. A prova é de primeira mão de quem construiu, com método correto (navegador real, login real, troca de empresa pelo switcher de verdade, desktop e 390 pixels) e com detalhes específicos que indicam observação real, mas é verificação de SEGUNDA mão do ponto de vista da aprovação. O motivo está registrado e é honesto: a sessão chegou perto do limite de contexto e a escolha foi fechar declarando isso, em vez de fingir uma verificação que não houve. Se aparecer defeito visual nesta fatia, este parágrafo é a explicação: não é caso de "foi visto e aprovado", é caso de "foi provado por quem construiu e aceito assim, com a diferença escrita". Comportamento de plataforma que vale referenciar aqui (documentado em RF-ANL-006 do DRS e no topo da Fase F13): o Super Admin em modo global, sem contexto de empresa ativo, sempre vê a pasta de relatórios VAZIA, porque a regra de acesso ao relatório não abre exceção para quem enxerga todas as empresas. É coerente com o produto (Reports é módulo por agência) e não foi introduzido nesta fatia. Está repetido aqui porque quem chegar pelo painel do cliente tropeça na mesma coisa e conclui que é defeito.
Definição de Pronto F16: painel do cliente completo (identidade, criação, ativação de acesso, offboarding LGPD, pasta por ano) e o portal logado de leitura do cliente final. Estado em 2026-08-02: FASE FECHADA, com as 16 fatias do bloco 9 do DRS entregues. A prova desta fase é de segunda mão do ponto de vista da aprovação (ver a nota de procedência no topo). O que segue depois daqui não é o plano original: são as Fases F17 e F18, nascidas da auditoria dos relatórios reais e do council de 2026-08-02, mais os cartões abertos por motivo nomeado nas fatias anteriores.

Fase F17, Blocos reais, cadência e biblioteca Global (Fatia 17)

Prioridade: esta fase nasceu em 2026-08-02 da auditoria dos relatórios que a operação já entregou, e vem na fila antes das fases F13 a F16, embora a numeração a coloque depois delas. O motivo é o critério de adoção (DRS A.7): enquanto os quatro tipos de bloco abaixo faltarem no registro, o sistema não reproduz o relatório que a operação entrega hoje, e um sistema que não reproduz o próprio trabalho da casa não é adotado. A posição no documento é de numeração, não de fila. Contagem que sustenta a fase inteira (medida em 2026-08-02, critério comportamental). Universo: as 8 linhas da tabela de relatórios do acervo. Critério: o valor de type efetivamente presente na lista de seções de cada relatório publicado, lido do conteúdo do próprio relatório, nunca busca textual em código. Placar: 6 relatórios estão no formato v2 com lista de seções e 2 estão em formato anterior sem lista de seções (um fechamento periódico multi-vertical e uma auditoria de marca, que não é relatório de mídia), e 6 mais 2 fecham em 8. Dos 6 v2: 4 diagnósticos de herança mais 2 fechamentos de campanha, e 4 mais 2 fecham em 6. O universo cobre 5 clientes distintos de uma mesma operação, não é um cliente só, e também não é "todos os relatórios já feitos": é o acervo dessa base. O lado negativo foi lido por inteiro, não amostrado: os 2 fechamentos de campanha têm a sequência completa funnel_simple, stat_cards, video_retention, rankings, data_table, insights, gap, e nenhum dos dois contém bloco de abertura em prosa, régua de confiabilidade, line_chart, donut ou action_plan. Dependência: {F2} (contrato de bloco v3) e {F3} (package renderizador) para os cartões de bloco; {F1b-01} e {F10-00} para a coluna de cadência e para os modelos semeados.
Definição de Pronto F17: ATENDIDA, fase FECHADA em 2026-08-03. Os dezesseis tipos do Ap.3 no registro, com os cinco novos provados por documento que os percorre; a régua de confiabilidade nascendo derivada e não editável; o hero singular imposto nas três superfícies; cadência declarada na instância com valor fechado imposto pelo schema e mapa de base de comparação valendo; a guarda de largura de janela recusando ou marcando toda comparação entre janelas diferentes, com a marca sobrevivendo ao publish; alcance e as demais métricas não somáveis usando o pico entre janelas; a biblioteca semeada com os dois modelos Globais confirmados mais o terceiro como individual da agência de origem; e, acrescentados durante a entrega, as quatro peças LIGADAS ao caminho real ({F17-11}) e o contrato público do pacote verificado por máquina ({F17-12}).
O smoke visual achou três defeitos que 32 testes verdes não pegaram, e é esta a evidência de por que a regra de olhar existe. Todos os três eram invisíveis para asserção e óbvios para o olho: no gráfico de linha, uma escala única esmagava a série menor até a linha reta; no donut, o texto do centro ficava sobreposto; e o bloco de confiabilidade repetia o mesmo fato três vezes. Nenhum quebrava build, nenhum derrubava teste, e os três teriam chegado ao cliente. A suíte prova que o dado está certo, não que a página está legível, e essas são duas perguntas diferentes.

Fase F18, Honestidade do número e calibração da régua

Onda nascida do council de 2026-08-02 sobre a auditoria dos relatórios reais. Ela não acrescenta funcionalidade nova de produto: fecha classes de mentira que o sistema ainda deixa passar, e consertou a régua de qualidade que travava o cartão {F1-17}, hoje fechado. Depende de {F17} (os tipos de bloco e a cadência precisam existir antes de as guardas os cobrirem). Princípio de dono desta fase (ADR-019): quando uma regra de comparação nasce, pergunte se o NÚMERO é falso, ou se o número é verdadeiro e a FRASE é falsa. Número falso, o dono é o extrator, que se recusa a produzi-lo. Número verdadeiro e frase falsa, o dono é o selo mais o compositor, proibido de emitir a afirmação quando o selo diz não comparável. Regra de nascença de toda guarda desta fase (RNF-MANUT-003): cada cartão entrega, junto com a trava, a fixture de controle negativo que ela DEVE reprovar, na suíte da integração contínua. Cartão sem fixture não fecha.
As seis guardas de {F18-01} a {F18-04}, {F18-07} e {F18-08} foram LIGADAS no publish real em 2026-08-03, e é isso que as tira de decorativas. Estavam escritas e testadas por unidade, e o publish não as chamava.
O método da prova, e é ele que deve se repetir. Cada guarda foi verificada INDIVIDUALMENTE: comentar a própria linha de ligação, rodar, e conferir que só o teste dela caía. Uma a uma, nas seis. Não é controle negativo genérico que derruba tudo e prova pouco (esse passa mesmo quando cinco das seis estão mortas); é a prova de que cada ligação específica está viva no caminho real. E as sete suítes irmãs que também publicam seguiram verdes, ou seja, nenhum relatório legítimo passou a reprovar, que é a outra metade da prova: uma guarda que reprova tudo também "funciona" e é inútil.
Achado extra, e é a lição mais fina desta fase: a saída legal que o {F18-07} documenta era ela própria sempre reprovada pelo gate de proveniência estrutural. A escotilha existia no texto e era inalcançável no código. É exatamente o defeito contra o qual a regra "toda recusa entrega uma saída legal" ({F18-10}) foi escrita, encontrado dentro da nossa própria implementação dela. Uma saída legal que o sistema recusa não é saída, é a mesma parede com outro nome. Corrigido isentando o histórico mínimo do gate estrutural.
Estado da F18 em 2026-08-03: 15 cartões de 18 fechados, 3 ABERTOS. Fechados: {F18-01} a {F18-05}, {F18-07} a {F18-10} e {F18-12} a {F18-18}. Abertos: {F18-06} (lacuna de modelo de dados, não de ligação), {F18-11} e {F18-16} (com evidência de entrega medida no repositório, mas sem confirmação do H1, e por isso não fechados). 15 mais 3 fecham em 18.
Duas correções de contagem nesta fase, e as duas foram pegas contando em vez de adotando. A primeira foi minha: cheguei a escrever que a fase estava fechada tratando um conjunto de seis cartões como "os seis restantes" sem contar a fase inteira, quando dez estavam abertos. A segunda veio na rodada seguinte: a lista de fechamento recebida previa quatro cartões restantes e nomeava apenas três, e a recontagem revelou que o quarto era o {F18-05}, que a medição mostrou já entregue. Nos dois casos o erro era de aritmética sobre um conjunto que ninguém tinha percorrido inteiro, e nos dois casos a recontagem pelo estado efetivo o desfez. É o que a RNF-MANUT-005 exige, e vale inclusive quando o número é meu.
Definição de Pronto F18 (ainda NÃO atendida): toda comparação da página declara a sua base dentro da frase; a tupla de identidade completa cobre todo número exibido e o gate nomeia o campo divergente; conectivo causal sem evidência sai como coocorrência; o anti-fadiga classifica pelos quatro quadrantes de dado contra texto e a recomendação repetida escala em vez de ser reescrita; seção sem histórico se oculta e vira lacuna; não medido tem uma representação única e nunca é zero; sazonalidade vive no cadastro do cliente; toda guarda não estrutural oferece saída legal e escotilha registrada; cada guarda tem a sua fixture de controle negativo na integração contínua; a régua de qualidade foi recalibrada contra um documento do tamanho do produto e ganhou o nível de documento; o teto de tempo escala com o tamanho; e os três campos excluídos são barrados por schema.

Fase F19, Geração agendada (Fatia 19)

Origem: resposta do dono a {Q4b} em 2026-08-03. A geração agendada deixou de ser evolução e virou escopo, e com ela a report_job (ADR-021, DRS E.2). As quatro palavras da resposta são requisitos e não adjetivos: configurável ({F19-02}), editável ({F19-03}), ativável e pausável ({F19-04} e {F19-05}).
FASE FECHADA em 2026-08-03, entregue e provada nos dois repositórios, incluindo a tela com smoke real (criar, listar, pausar, retomar, editar com prefill e histórico de ciclos).
A trava principal está PROVADA, e era a condição imposta pelo dono: não existe caminho que publique sozinho. Provado por dois meios independentes. Busca dirigida: nenhuma referência a publicação no disparador de ciclo nem no módulo de agenda, nos dois repositórios, medida arquivo a arquivo. E por teste: o publish segue sendo o único endpoint, sem parâmetro de origem, de modo que não existe nem sequer a forma de dizer a ele "esta edição veio da agenda". A guarda não é uma condição escrita dentro do publish, que alguém poderia inverter; é a ausência do caminho, que ninguém pode chamar.
ESCOPO DECLARADO, e não pendência: a agenda automatiza a COMPOSIÇÃO, não a COLETA (decisão do dono, 2026-08-03, RN-017 item 7). Este documento não define upload automático de artefato e não existe conector de ingestão. O disparador adota um relatório que o operador já deixou preparado (criado, com artefato subido e direção confirmada, sem ter clicado em compor) cuja conta, propósito e período batem com a janela do ciclo. Sem ele, o ciclo fecha com o desfecho no_artifact. O que a cadência tira do operador é montar e escrever, não juntar os dados, e dizer "geração automática" sem essa frase seria prometer mais do que se entrega.
ESCOPO DECLARADO: o gate de honestidade não roda dentro da composição automática, e está certo assim (RN-017 item 8). Ele roda no publish, que continua manual e obrigatório. O rascunho automático é matéria-prima, e a honestidade se verifica quando alguém decide publicar; o desfecho de falha da composição automática cobre falha estrutural e exceção, nunca honestidade. Condição registrada: se um dia a publicação virar automática, esse gate precisa entrar ANTES, dentro do caminho automático, como pré-requisito e não como consequência.
Dependências, e uma delas é dura. {F17-05} (cadência declarada na instância e mapa de base de comparação) precisa existir antes, porque a agenda carrega a cadência. E {F18-05} (anti-fadiga comparando variação do DADO contra variação do TEXTO) é PRÉ-REQUISITO, não melhoria paralela (RN-017 item 6): a cadência curta e automática faz as edições nascerem no ritmo do calendário e não no ritmo do operador, e punir repetição de texto num acervo denso, com o anti-fadiga ainda medindo texto contra texto, empurra a composição a inventar variação onde o dado não variou. Construir a agenda antes disso é ligar o volume numa guarda que mede a coisa errada.
Definição de Pronto F19: ATENDIDA, fase FECHADA em 2026-08-03. A agenda existe por cliente e por propósito, única no par e imposta pelo banco; ela é editável sem perder identidade nem o vínculo com as edições geradas; pausar interrompe apenas o nascimento de edições futuras, com os cinco negativos exercitados um a um; retomar segue do ciclo à frente e nunca repõe o atraso em lote; a edição agendada nasce em rascunho já comparada com a anterior e sob a guarda de largura de janela; nenhuma edição agendada publica sem gesto humano e nenhum gate olha a origem; todo ciclo vencido fecha com um dos seis desfechos e avisa o responsável; e o operador faz tudo isso por uma tela sem beco sem saída.

Fase F20, Modelo de venda e camada de resultado (Fatia 20)

Origem: a planilha de gestão que a operação usa de verdade, apontada pelo dono em 2026-08-03 como a base a seguir. Ela FECHA o item de investigação que o Ap.9 mantinha aberto (o corte entre geração de leads e comércio eletrônico) e o fecha contra a parte cara da hipótese: o corte é estrutural, mas produz UMA estrutura com vocabulário trocável, e não duas. Ver Ap.10, RN-018, ADR-022 e ADR-023.
Nenhum tipo de bloco novo nasce nesta fase (ADR-023). O funil canônico é o funnel_simple com o perfil canônico aplicado e a camada de resultado é stat_cards alimentada pelo catálogo do Ap.10. A lista nominal de dezesseis tipos de RF-REN-012 continua fechada e inalterada, e conferir isso é parte do aceite de {F20-03}.
FASE FECHADA em 2026-08-03, com os sete critérios provados.
A prova que sustenta a camada inteira, e ela é do tipo que quase nunca se faz. As 11 métricas com fórmula a conferir foram exercitadas com todos os operandos plausíveis PRESENTES no contexto, e nenhuma emitiu. A distinção é o ponto: não é "não emitiu porque faltou dado", que seria um teste fraco e passaria por acidente; é não emite mesmo com o dado na mão, porque a fórmula não foi conferida. E o prazo de retorno do CAC continua bloqueado mesmo tendo fórmula literal transcrita da planilha, porque um operando dele não existe no catálogo, testado inclusive com o custo real de aquisição hipoteticamente resolvido. É a prova de que a trava é a regra e não a ausência de insumo.
As contagens do catálogo são função CALCULADA, não constante escrita à mão. Os placares (2 mais 3 mais 15 igual a 20; 4 conferidas mais 11 a conferir igual a 15) são derivados do próprio catálogo em tempo de execução. É isto que impede o placar de mentir depois: uma entrada nova muda o número sozinha, e ninguém precisa lembrar de atualizar um total escrito à mão, que é exatamente como as quatro divergências de contagem desta sessão nasceram.
O funil canônico IGNORA o rótulo digitado. O vocabulário vem sempre do modelo de venda do cliente, e o teste prova pelo negativo: corrompe o rótulo de propósito no bloco e confirma que o texto digitado não chega ao HTML servido. E o funil livre, sem modelo declarado, roda inalterado contra o conjunto de calibração real: regressão zero, que era a condição para esta fase ser aditiva e não uma troca.
Dependência: {F11-01} e {F11-02} (importação pelo sandbox de parse), porque três entradas do Ap.10 são fatos do negócio do cliente (margem de contribuição, fee da agência e o multiplicador de LTV) e toda derivada cuja cadeia de operandos passe por elas fica indisponível sem a importação.
A família fechou INTEIRA em 2026-08-04, e a classificação dos quatro é o achado. Dois dos quatro já existiam prontos e só não estavam ligados: o log de auditoria já era rota genérica funcionando e faltava a tela chamar, e a tela de metas tinha o backend completo desde uma fatia anterior. Os outros dois foram construídos de fato. Ou seja, metade do que parecia trabalho pendente era trabalho já feito e inalcançável, que é exatamente a assinatura desta família e o motivo de ela merecer desenho e não cartão avulso. Nota de divergência registrada: a mensagem de commit da entrega agrupa TRÊS peças como já construídas, e a classificação recebida diz duas; a diferença não muda o fechamento de nenhum cartão e fica anotada em vez de arbitrada, porque nenhuma das duas contagens foi medida contra o código peça a peça.
A família "peça pronta que o operador não consegue acionar" teve QUATRO membros, e quatro casos é desenho, não cartão avulso. São eles: {F10-05} (contagem de uso na biblioteca de modelos), {F10-06} (leitura do log de auditoria de promoção exposta na tela), {F11-03} (metas importáveis sem tela que as importe ou liste) e este {F20-08} (funil e camada de resultado construídos sem gatilho que os acione). O padrão comum não é preguiça nem esquecimento: em cada caso a capacidade foi construída e provada por baixo, e a superfície que a torna alcançável ficou para depois, porque a prova de que funciona não exige a superfície. A consequência é que o sistema tem mais capacidade do que o operador consegue usar, e a diferença não aparece em teste nenhum, porque os testes exercitam a capacidade e não o alcance dela. Quatro ocorrências pedem uma decisão de desenho sobre quando a superfície entra, e não mais um cartão por caso.
Definição de Pronto F20: ATENDIDA, fase FECHADA em 2026-08-03. O catálogo do Ap.10 conferido campo a campo contra a planilha de gestão, com as 20 entradas classificadas e as 15 derivadas em estado conferida, e a leitura do Ap.10.3 (retorno sobre anúncios positivo pode conviver com prejuízo, LTV mínimo de 3 vezes o CAC, sinal do ROMI, unidade do CAC Payback em ciclos, LTV multiplicador distinto do valor em dinheiro) refletida nos rótulos; o modelo de venda vivendo no perfil do cliente com dois valores fechados e nulo permitido; o funil canônico de quatro etapas rendendo os dois vocabulários sobre a MESMA estrutura, com o funil livre preservado para cliente sem modelo declarado; a tripla por etapa completa, com a primeira etapa sem taxa por construção e sem entrar em lacuna; os parâmetros de negócio entrando pelo mesmo caminho de importação das metas e separados delas por conceito; toda métrica de resultado exibida com origem declarada e nenhuma saindo como zero por operando faltante; e as métricas comerciais da agência fora do snapshot publicado por default.

Onda DEF, Defeitos achados fora da obra (2026-08-11, fora da fila padrão)

Origem: varredura de erros de produção conduzida por outra frente em 2026-08-11, que estava investigando o registro de ocorrências e esbarrou nestes dois defeitos do módulo de relatórios. Nada aqui foi corrigido por quem achou: o arquivo é território da frente que constrói este módulo, e mexer nele em paralelo criaria colisão. O registro É a entrega, e a fila decide quando pegar. Prioridade: NENHUMA declarada. Os dois entram depois da fila vigente, salvo decisão em contrário de quem toca o módulo. O {DEF-01} tem mecanismo comprovado e nenhuma manifestação medida em produção; o {DEF-02} não quebra tela nenhuma, corrompe contagem. Medido em main f4037d8. Este HEAD é mais novo que o 5eb7575 de outras notas deste dia, porque a frente que constrói o módulo avançou entre uma medição e outra.

Correção: um helper único para efeito pós-commit, que registra a linha JSON efeito_pos_compromisso_falhou.

  • Publicar. Responde 200 com side_effect_warnings. O modal mostra "Publicado. O QR não pode ser

gerado." e o botão "Gerar QR de novo", que chama GET /:id/share-qr. Esse endpoint devolve 409 em rascunho, 403 sem a permissão de publicar e 404 para outra agência.

  • LGPD. Devolve LGPD_ARQUIVOS_PARCIAL; a nova tentativa conclui e respeita a posse.

Controle negativo: falha dentro da transação continua 500 e não grava nada. Baseline em 3cd18a3: a rota dava 500 com o relatório já publicado. O que perde: REPORT_PUBLISH_FAILED só cobre falha dentro da transação (o texto mudou para "nada foi publicado"). RF-PUB-011 (NOVO, publicado no DRS em 2026-08-11, módulo reports-publish). Card PAR: nenhum requisito vigente reprovava o desfecho, então ele nasce junto do que passa a reprovar, nunca como "exige RF novo" solto. O defeito em uma frase: a publicação confirma a transação e só DEPOIS gera a imagem do código de acesso; se essa geração falhar, o operador recebe erro de uma operação que aconteceu. O mecanismo, lido por inteiro no código: o handler de publicação abre o bloco protegido em apps/api/src/routes/reports.ts:3624; a confirmação da transação acontece no RETORNO do callback (apps/api/src/lib/db.ts:47 confirma assim que o callback devolve, e o callback devolve em reports.ts:4307), de modo que quando a linha reports.ts:4367 gera a imagem do código de acesso o relatório JÁ está publicado, o instantâneo JÁ está gravado e o evento de auditoria JÁ foi registrado. O tratamento de falha em reports.ts:4376-4377 devolve o erro genérico da publicação, situação 500. O resultado é um falso negativo: a resposta afirma o contrário do que o sistema fez. CORREÇÃO DE PREMISSA, e ela ameniza o defeito (o card não pode exagerar o próprio caso): a suposição de que a segunda tentativa seria recusada com "não está mais em rascunho" é FALSA. Lida por inteiro a função de publicação no banco, ela é IDEMPOTENTE por desenho: com o relatório fora de rascunho ela audita como republicação e refaz o instantâneo e a situação, então uma segunda tentativa CONCLUI e desta vez devolve a imagem normalmente. A única guarda dura do handler é a do relatório revogado (reports.ts:3631, situação 409). Ou seja, o dano é transitório e se cura sozinho no retentar, e isso é consequência direta do RF-PUB-009 (republicar reusa o mesmo link). O que sobra, e continua sendo defeito, é a mentira da primeira resposta: o operador que acredita nela e NÃO tenta de novo fica achando que não publicou um relatório que está no ar. Contagem (o conjunto FECHA, com limite declarado):

  • Universo: T = 46 handlers mutantes (não de leitura) do arquivo de rotas do módulo que abrem transação pelo padrão direto, levantados listando os handlers com transação (meio diferente do critério, que classifica lendo onde cada efeito colateral roda).
  • Critério (COMPORTAMENTAL, nunca busca textual como prova final): o handler executa algum efeito colateral DEPOIS da confirmação da transação e ainda dentro do bloco cujo tratamento devolve erro 5xx da operação?
  • Placar: seguros N = 45 / com efeito colateral pós-confirmação dentro do bloco M = 1 / N + M = T = 46. Fecha.
  • Lado negativo, lido por inteiro: o lado M tem UM item só, e o card diz isso em vez de fingir um segundo. É reports.ts:4367, a geração da imagem do código de acesso na publicação. Como controle, foi aberto por inteiro um handler do lado N que parecia arriscado, a regeneração de bloco por inteligência artificial (reports.ts:3272-3369): nele a chamada externa acontece ANTES da transação que grava, com releitura travada depois, e o comentário do próprio código declara esse desenho. Os demais candidatos de risco (envio de arquivo e mídia de bloco) também executam o efeito externo antes de abrir a transação de escrita, conferido lendo os dois.
  • LIMITE DECLARADO da contagem: o universo cobre os handlers que usam o padrão direto de transação. O handler de composição usa mecanismo próprio, numa biblioteca separada, e não foi contado nem classificado: se alguém quiser T incluindo ele, é uma passada própria naquela biblioteca. Além disso, dos 46 não foram abertos todos um a um: foram abertos os que a varredura sinalizou com chamada assíncrona fora da transação e os que os comentários do código já apontavam como historicamente arriscados. O placar é honesto sobre o método, e é por isso que ele está escrito aqui.
  • Universo é 1 agência?: não se aplica, é código.
  • Evidência de: 2026-08-11, main f4037d8.
  • Ocorrências em produção: ZERO comprovadas, e este card NÃO reivindica a que existe. Há exatamente 1 ocorrência do código de falha de publicação no registro, em 2026-08-08 às 22:13:42. Ela foi investigada e NÃO é este defeito: a busca por evento de publicação ou republicação na trilha de auditoria entre 22:10 e 22:20 daquele dia, para qualquer agência, devolveu 0 linhas, o que significa que a transação daquele caso NÃO foi confirmada e a falha aconteceu ANTES ou DENTRO dela, não depois. A única publicação daquela agência naquele dia foi às 22:21:18, oito minutos depois e sem falha associada. Portanto: mecanismo comprovado por leitura de código, manifestação medida em produção igual a zero. A causa daquela ocorrência de 2026-08-08 segue desconhecida e é assunto separado. Não foi possível medir "publicado sem imagem de código de acesso" por outro caminho porque a imagem nunca é persistida (não existe coluna para ela, ela só vai na resposta), e a checagem pela trilha de auditoria é o substituto válido.
  • Reprova por: nenhum RF vigente reprova. O RF-PUB-005 exige que a imagem do código de acesso seja exibida ao abrir o modal de publicação; ele nada diz sobre o que acontece quando a geração falha, então o falso negativo passa nele sem arranhão. Não há requisito não funcional de atomicidade que alcance o caso. A partir da publicação, reprova o RF-PUB-011, H1 "Então a resposta ao operador declara o estado VERDADEIRO do sistema e nomeia em separado o que não pôde ser feito, E nenhum operador recebe falha de uma operação cujo compromisso foi confirmado".

Direção da correção (sem prescrever implementação, a decisão é de quem toca o módulo): há duas saídas legítimas e o requisito aceita as duas. Ou o efeito colateral entra no MESMO compromisso da publicação, e aí uma falha dele derruba tudo junto e a resposta de erro volta a ser verdadeira; ou a falha dele deixa de ser erro da operação e vira aviso que declara o estado verdadeiro, algo como "publicado, mas o código de acesso não pôde ser gerado", com o caminho para tentar gerar de novo. A segunda saída depende de julgar a imagem do código de acesso ACESSÓRIA à publicação, e o H1 proíbe explicitamente rebaixar a aviso um efeito colateral que seja indispensável, justamente para que a correção não vire "engolir a falha em silêncio". Essa classificação é decisão de produto de quem toca o módulo, não deste card. Como verificar (teste primeiro): forçar a falha do efeito colateral posterior (por exemplo tornando inválida a entrada da geração da imagem) e publicar: a resposta ao operador NÃO pode ser o erro genérico da publicação, e o que a tela afirma tem que bater com o que ficou gravado no banco (relatório publicado, instantâneo gravado, evento auditado); repetir com uma falha DENTRO da transação e conferir que aí sim a resposta é de erro e nada ficou gravado (este é o controle negativo, e sem ele a correção poderia ter engolido também as falhas reais); e conferir que o caminho normal de publicação continua devolvendo a imagem do código de acesso, que é o RF-PUB-005. Aceite (H1): Dado uma operação cuja transação já foi confirmada, Quando um efeito colateral executado depois dela falha, Então a resposta declara o estado verdadeiro do sistema e nomeia em separado o que não pôde ser feito, E a resposta nunca é o erro genérico da operação inteira, E nenhum operador recebe falha de uma operação cujo compromisso foi confirmado, E o efeito colateral indispensável ao sucesso passa a ser executado dentro do compromisso.

Definição de pronto da onda: os 2 cards [x] com gates verdes por fatia; o falso negativo reproduzido e provado corrigido, com o controle negativo da falha dentro da transação também provado; a contagem do compositor recontada e o par diário desaparecido; e DRS, roadmap e Plano de Testes republicados sem divergência.

Onda OP, Defeitos que só aparecem USANDO o produto (2026-08-17/18)

Origem, e ela é o ponto: o dono do produto abriu a ferramenta e ela não funcionava. "vc implementou, implementou e a ferramenta não funciona. Faça um teste de uso dela e vai ver que trava em várias etapas e simplesmente não tem como nem testar." Os cartões abaixo nasceram de percorrer o wizard como operador em produção, nas visões de account manager e de gestor de tráfego, com tipos e períodos variados - não de leitura de código, não de gate. Por que a obra inteira estava verde com o produto travado: todos os gates mediam o que se mandou medir. planner planeja o objetivo, qa testa os critérios de aceite (= o objetivo), code-reviewer lê o diff (= o que mudou, não o que falta ligar) e o smoke olha a tela nova. Ninguém percorria o fluxo inteiro de ponta a ponta com dado de verdade. Onze cartões, e nenhum deles exigiu feature nova - todos eram peça pronta que não se ligava, guarda boa demais que reprovava o caso normal, ou constante espelhando um valor que mudou do outro lado. Todos [x]: corrigidos, com teste que impede a volta, mergeados em main nos dois repos e deployados. O denominador subir aqui é o processo funcionando: nenhum cartão fechado reabriu.
O que a onda deixou como dívida nomeada, e é de VERACIDADE, não de usabilidade: o gate de período compara a GRANULARIDADE, não QUAL período. Publiquei de propósito "a taxa de conversão de junho de 2026 ficou em {{dp:dp3}}" com um dp de janeiro e o publish passou - os dois são granularity: "mes". É precisamente o defeito que este gate existe para pegar (número verdadeiro na frase errada) e ele não vê. O link foi revogado (410 confirmado) para não deixar relatório enganoso no ar. Comparar o rótulo direto não serve ("junho de 2026" vs "jun/2026" vs "último mês"): precisa de normalização de rótulo de período antes da comparação. Próximo card da fila - ver {OP-12} abaixo.

Encerramento

Com as vinte fatias fechadas, a seção Construção chega a 100% e resta a seção Testes (Plano de Testes, Alfa e Beta) para o projeto chegar a 100% geral. Os ciclos reais de adoção (J.3 do DRS) começam assim que a Fatia 9 (publicação) estiver no ar, em paralelo às fatias seguintes. A ordem da fila não é a ordem da numeração: as Fases F17 e F18 vêm antes de F13 a F16, e F19 depende de {F17-05} e de {F18-05}, o que coloca F19 e F20 depois delas e não no fim por causa do número.

Documento ModularReports: Roadmap de Implementação
Metodologia MDS · Modular Development Style · 15 blocos / 86 campos
Publicado por Modulareasy
Site modulareasy.com/metodologias/mds