Tynnaretrato de 22/09, 21:52
voltar à Biblioteca

ADR-0081 — Tiers de conformidade por estágio de produto

15/08/2026 · aceita

docs/adr/ADR-0081-tiers-de-conformidade-por-estagio.md

ADR-0081 — Tiers de conformidade por estágio de produto

Status: aceita Data: 2026-08-15 Decisor(es): Marcelo Lermen (board) + Claude Code controller

Contexto

O board pediu revisão das boas práticas, padrões e quality gates, propondo uma lista de ~12 artefatos obrigatórios para todas as aplicações (PRD, UML, RBAC, multi-tenancy, RLS, secret management, catálogo de funcionalidades, botão de report de erro, testes, security audit, WAF/Bot Fight/rate-limiting, TLS full strict).

O pré-voo mediu o que já existe e o que a casa consegue sustentar. Três achados mudam a forma da decisão.

Achado 1 — metade da lista já existe, e o que existe é bom

itemondeestado
Testes (unit/integração/E2E)dev-standards §9 — ~150 linhasmaduro
RLS§10 + 12 ADRs + padrão #3 (FK no WITH CHECK)maduro
Secret management§10 + gitleaks (pre-commit + CI) + Keychainexiste
Multi-tenancy§10 "tenant isolation testado a cada release"existe
RBAC3 ADRs + 2 runbooksexiste, disperso
Rate limiting§10 + 4 ADRsdecidido, não aplicado
Rollback19 runbooks com seção própriaexiste
a11y (axe)gate bloqueante no ci.yml desde 19/06existe

Faltam de verdade: PRD, mapa de arquitetura, WAF/Bot Fight, TLS full strict, botão de report de erro, catálogo de funcionalidades, prova de restore.

Achado 2 — o gargalo não é falta de padrão, é padrão que ninguém verifica

Medido em um único dia (15/08), sem procurar por isso:

mecanismotempo morto em silêncio
snapshot de FinOps (com.tynna.token-snapshot)35 dias, 37 falhas
smoke-test-scripts~2 meses, 539 testes invisíveis
DRIFT-BAN5 acusações crônicas, 3 falso-positivo
Semgrep (fixture de JWT no mento)nunca detectada — scan incremental
teste em diretório fora do include do vitest2 ocorrências no mesmo dia

Adicionar obrigação a uma casa onde as existentes falham caladas piora a razão sinal/ruído. Cada item sem verificador é mais um lugar onde alguém escreve "✅ feito" e ninguém confere.

Achado 3 — a distribuição de esforço estava invertida

O apps/jep é o único produto com cliente pagante (ARMELS, publicado nas duas lojas) e era, até 15/08, o único sem error tracking. Os dois apps que tinham Sentry — web e mento — são justamente os sem receita.

Piso único não teria pego isso: teria distribuído exigência igualmente entre 7 apps, diluindo atenção em vez de concentrá-la onde há cliente.

Opções consideradas

(a) Piso único para todos os apps. Simples de enunciar. ⛔ Trava labs pré-receita com exigência de produção (WAF num app sem usuário é custo e falso-positivo), e dilui atenção — o oposto do que o Achado 3 pede.

(b) Três tiers (lab / usuário real / cliente pagante). Granularidade fiel à realidade. ⛔ Três checklists para manter numa casa cujo problema medido é não conseguir manter o que já tem. E o degrau do meio é o menos objetivo de definir.

(c) ⭐ Dois tiers, com promoção detectada por script. Piso enxuto para todo repo; Produção para o que tem usuário externo. A promoção não depende de alguém lembrar.

(d) Nada — manter como está. ⛔ Deixa o Achado 3 sem resposta.

Decisão

Adotamos (c): dois tiers, com detecção automatizada e a regra do verificador.

Os dois tiers

tierquemexige
Pisotodo repo/appTS strict · lint · testes de lógica pura · .env.example · secrets fora do código · error tracking
Produçãoapp com usuário externo (alguém que não somos nós)Piso + RLS testada + E2E happy-path + a11y (axe) + headers de segurança + rate-limit + TLS strict + LGPD + prova de restore

A regra que sustenta tudo

Item sem comando que prove seu estado não entra como gate — vira recomendação.

Isso não é preferência de estilo: é a conclusão do Achado 2. Regra escrita não muda gesto automático; ferramenta muda. Um item que só existe como frase em documento tem, nesta casa, histórico documentado de ficar meses sem cumprimento sem ninguém notar.

Promoção de tier é detectada, não lembrada

O registro (data/standards/conformance.yaml) declara o tier de cada app, e pnpm standards:check compara a declaração com os sinais da árvore. Um app declarado piso que já exibe sinais de produção (E2E configurado, testes de RLS, headers de segurança) é reportado como promoção pendente.

⚠️ Limitação declarada: a detecção é por proxy, não prova de que há usuário externo — nenhum sinal no repo prova isso. Ela existe para atacar o modo de falha real (app cresce, ninguém promove), não para decidir sozinha. A palavra final é do registro, que é editado por humano ou agente com justificativa.

O que fica de fora, e por quê

  • UML — recusado. Diagrama não gerado do código apodrece em meses, e a casa tem histórico disso. Substituído por C4 nível 1–2 em Mermaid versionado: renderiza no GitHub, entra no diff, e o revisor vê quando a arquitetura mudou sem o desenho mudar.
  • "Catálogo de funcionalidades" — recusado como item novo. Se é para humano, é o PRD; se é para a frota saber o que reusar, já existe docs/standards/reuso-catalogo.md. Criar um terceiro artefato para o mesmo fim contraria a regra de ouro do §7 (uma informação tem UM dono).
  • WAF/Bot Fight — só no tier Produção. Em app pré-lançamento é custo e risco de falso-positivo sem benefício.

Documentação continua no repo; o Paperclip aponta

A proposta de hospedar a documentação dos projetos no Paperclip foi avaliada e recusada na forma de cópia. O projeto no Paperclip tem um campo description; doze documentos ali viram monólito ou duplicata. O CLAUDE.md §8 (regra dura, 30/07) e o dev-standards §7 já decidem: "cópia apodrece em silêncio — o dono atualiza um lado só".

O que fazemos: doc técnica no repo; o description do projeto no Paperclip vira índice com links, não conteúdo.

Correção de contradição entre canônicos

O dev-standards §7 mandava estado de projeto, OKRs, tasks e dashboards para o EuGestor, enquanto o CLAUDE.md §6 e o ADR-0027 dizem Paperclip. Dois canônicos em conflito. Este ADR corrige o §7 para refletir o ADR-0027.

Consequências

Positivas

  • Atenção concentrada onde há cliente pagante, em vez de distribuída por 7 apps.
  • O registro torna o estado de conformidade medível — hoje ele não era.
  • Detecção de promoção ataca o modo de falha que já se repetiu 5× em um dia.
  • Menos artefatos novos que a proposta original: 3 recusados com justificativa.

Negativas / riscos

  • ⚠️ O registro pode apodrecer como qualquer artefato manual. Mitigação: standards:check compara declaração × árvore e falha quando diverge.
  • ⚠️ A detecção por proxy gera falso-positivo (um lab pode ter E2E por disciplina, sem usuário externo). Por isso ela reporta, não bloqueia.
  • ⚠️ Dois tiers são grosseiros para um portfólio que pode crescer. Se o degrau do meio voltar a doer, isso é motivo para um ADR novo — não para adicionar tier em silêncio.
  • O tier Produção tem itens ainda não implementados (WAF, TLS strict, prova de restore, LGPD). O registro os marca como pendentes em vez de fingir conformidade.

Estado inicial medido (2026-08-15)

app          tier        error-tr  testes  e2e  rls   headers
jep          producao    sim       127     sim  32    sim
mento        producao    sim        76     sim  24    sim
web          producao    sim        33     sim   0    NAO
publisher    piso        NAO        20     sim   0    sim
grana        piso        NAO        23      -    0    NAO
chat-bridge  piso        NAO         4      -    0    NAO
grana-bot    piso        NAO         3      -    0    NAO

Relacionado

  • TYN-3196 — gate incremental não vê o baseline (a classe do Achado 2)
  • TYN-964 / TYN-865 — error tracking do JeP (#1538)
  • TYN-3202 — botão de report de erro (fatia 2)
  • ADR-0027 — Paperclip como source of truth de coordenação
  • dev-standards §7, §9, §10, §15b

Só leitura. Toda mudança nestes documentos é pull request.