Revisar com evidências: Well-Architected, ameaças, dados e IAM
Quatro ferramentas de revisão do Orders, uma regra que muda tudo (controle sem prova vira unknown) e a anatomia de um achado que vale alguma coisa.
12 min de leitura
Escolha como aprender
combine como quiserDica: o vídeo é um resumo visual rápido; o áudio e o texto trazem a aula completa. Terminar o áudio ou o vídeo, ou passar no quiz, já conta a aula como concluída.
Revisar arquitetura é a parte do trabalho em que mais se mente sem querer: alguém marca "least privilege: ok" no checklist e ninguém pergunta onde está a prova. Nesta aula você usa quatro ferramentas do Moretes Architect MCP para revisar o Orders por evidência: well_architected_review, threat_model, data_classification e iam_policy_review. No fim você sabe o que um achado precisa ter para valer e o que o servidor se recusa a fazer: dar nota.
Revisar é organizar evidência, não dar nota
Esta aula assume o que o módulo 1 deixou pronto: o servidor conectado no seu agente e o brief do Orders (300 pedidos por minuto no pico, pagamento com cartão, clientes brasileiros, equipe de 4 pessoas, US$ 1.500 por mês, SLO de 99,9%). O que ela acrescenta é o fluxo de revisão.
O servidor publica esse fluxo como a skill architecture-review (recurso moretes://skills/architecture-review) e como o prompt architecture_review, cujo texto é curto: coletar a arquitetura proposta e a evidência, montar a figura comum com c4_model, depois threat_model, well_architected_review, data_classification e as revisões de IaC quando couber. E a frase que eu considero a mais importante do prompt: "Heuristic findings are not certifications". O resultado esperado é uma lista priorizada de lacunas com dono, teste e perguntas em aberto.
Lembre o que o servidor é: determinístico. Ele nunca chama um modelo. Quem raciocina é o modelo do seu cliente (Claude, Codex, Kiro); as ferramentas devolvem estrutura, cálculo, fonte e lacuna explícita. Toda resposta das quatro ferramentas desta aula vem com kind: "heuristic-design-aid", validated: false e uma limitation dizendo que não é revisão oficial da AWS, nem auditoria de segurança. Eu não escrevo isso por modéstia: em 12 anos operando sistemas, nenhuma revisão que eu assinei saiu de um checklist. Saiu de alguém perguntando "me mostra".
{
"arguments": {
"workload": "Orders API",
"controls": [
{ "id": "backup-restore-tested", "pillar": "reliability", "status": "met",
"evidence": "Restore drill 2026-09-14, 38 minutes, ticket OPS-412" },
{ "id": "least-privilege-iam", "pillar": "security", "status": "met", "evidence": "" },
{ "id": "cost-alerts", "pillar": "cost", "status": "gap", "owner": "platform-team" },
{ "id": "runbooks", "pillar": "operational-excellence", "status": "unknown" }
]
},
"result": {
"kind": "heuristic-design-aid",
"validated": false,
"controls": [
{ "id": "backup-restore-tested", "status": "met" },
{ "id": "least-privilege-iam", "status": "unknown", "evidence": "" },
{ "id": "cost-alerts", "status": "gap", "evidence": "", "owner": "platform-team" },
{ "id": "runbooks", "status": "unknown", "evidence": "" }
],
"summary": { "met": 1, "gaps": 1, "unknown": 2 },
"missingPillars": ["performance", "sustainability"],
"next": "Assign owners and evidence for each gap. No compliance score is issued."
}
}A regra: met sem evidência vira unknown, nunca certificado
A ferramenta well_architected_review recebe workload e uma lista de 1 a 80 controls. Cada controle tem id, pillar (um dos seis: operational-excellence, security, reliability, performance, cost, sustainability), status (met, gap ou unknown), evidence (texto, pode ser vazio) e owner opcional. A lógica inteira cabe numa linha de src/architecture.ts: se status é met e evidence está em branco, o status vira unknown. Nada mais.
Olhe o que aconteceu no exemplo. backup-restore-tested entrou como met com a evidência "Restore drill 2026-09-14, 38 minutes, ticket OPS-412" e continuou met: tem data, duração e ticket, dá para conferir. least-privilege-iam entrou como met com evidence: "" e saiu como unknown. Alguém achava que estava tudo bem, mas não trouxe nada. cost-alerts entrou como gap com dono platform-team e ficou assim: lacuna conhecida, com responsável. runbooks já era unknown.
O summary conta: met 1, gaps 1, unknown 2. E missingPillars lista performance e sustainability: ninguém sequer escreveu um controle para esses dois pilares. Isso não é lacuna, é ponto cego, e a ferramenta separa as duas coisas de propósito.
A diferença entre gap e unknown é a diferença que mais importa numa revisão. gap significa "sabemos que não temos"; unknown significa "ninguém olhou". O primeiro vai para o backlog com dono. O segundo exige que alguém vá verificar antes de qualquer promessa. O campo next repete a postura: "Assign owners and evidence for each gap. No compliance score is issued". Se você quer um exercício, o docs/workshop.md do repositório pede exatamente isto: submeta um controle met sem evidência e veja ele voltar unknown.
threat_model: 18 perguntas STRIDE, zero respostas prontas
threat_model recebe assets (de 1 a 15), boundaries (as fronteiras de confiança, em linhas) e dataClassification (texto curto). No Orders os ativos foram Orders API, Orders DB e Payment webhook endpoint; as fronteiras, Internet to API Gateway, API to payment provider e Webhook from provider to API; a classificação, personal + financial-card (tokenized).
O retorno é previsível por construção: para cada ativo, as seis categorias STRIDE (Spoofing, Tampering, Repudiation, Information disclosure, Denial of service, Elevation of privilege), cada uma com uma mitigation genérica e status: "to-assess". Três ativos vezes seis categorias dá 18 linhas, todas to-assess. A ferramenta não leu código, não varreu rede, não olhou um security group. Ela é um auxílio de revisão, não um scanner, e a descrição dela diz isso com todas as letras.
Então para que serve? Para que a reunião de revisão não pule nada. O trabalho humano é pegar cada uma das 18 linhas e decidir entre três destinos: mitigado, com a evidência (o teste, o log, a configuração); aberto, com dono; ou não se aplica, com a justificativa escrita. Exemplo concreto: Payment webhook endpoint + Spoofing, mitigação sugerida "Verify issuer, audience and caller identity". A pergunta real é: o endpoint valida a assinatura do provedor e rejeita replay? Se a resposta for "acho que sim", a linha fica aberta. As boundaries voltam no resultado sem alteração justamente para isso: Webhook from provider to API é a fronteira em que spoofing mais dói neste sistema, e cabe a você cruzar ativo com fronteira.
Se o seu agente te devolver "a ferramenta encontrou 18 ameaças", corrija ele. Encontrou 18 perguntas.
data_classification: CPF, PAN e histórico, com LGPD e PCI como ponteiros
data_classification recebe system, uma lista de elements e jurisdictions (BR, EU, US, other; padrão BR). Cada elemento tem name, category (uma de oito: public, internal, personal, sensitive-personal, financial-card, health, credential, children), purpose, retentionDays, residency e sharedWith. No Orders entraram três: customer CPF (personal, finalidade invoice issuance, retenção 1825 dias, residência BR (sa-east-1), compartilhado com tax authority), card PAN (financial-card, finalidade payment, compartilhado com payment provider, sem retenção e sem residência) e order history (personal, finalidade customer service, nada mais).
O resultado abre com highestSensitivity: "financial-card", porque PAN de cartão pesa mais que dado pessoal na ordem interna da ferramenta. Para cada item vêm controls (7 para personal), regulationHints por jurisdição e questions. Para o CPF a dica é "LGPD art. 5 I (dado pessoal), art. 7 (bases legais), art. 18 (direitos do titular)" e a única pergunta é confirmar o acordo com tax authority. Para o PAN, a dica é "PCI DSS v4.0.1 (contractual) and BCB regulation for payment institutions", o primeiro controle é "Do not store PAN unless in PCI DSS scope; prefer tokenization by the payment provider", e saem três perguntas: retenção indefinida, residência indefinida e acordo com payment provider. O histórico de pedidos herda as duas primeiras perguntas.
Repare que as perguntas são derivadas do que você não informou. Preencha retentionDays e residency e elas somem. A ferramenta não sabe a resposta certa; ela sabe que você ainda não decidiu.
A limitation deste resultado é diferente das outras e eu peço que você a leia: "Regulation references are pointers for a legal or privacy review, not legal advice. Article numbers may change; verify the current text". Eu não sou advogado, o servidor menos ainda. O que ele faz é garantir que o CPF e o PAN cheguem à mesa do jurídico com finalidade, retenção, residência e terceiros já escritos.
{
"kind": "data-classification-review",
"validated": false,
"limitation": "Regulation references are pointers for a legal or privacy review, not legal advice. Article numbers may change; verify the current text.",
"system": "Orders platform",
"jurisdictions": ["BR"],
"highestSensitivity": "financial-card",
"items": [
{
"name": "card PAN",
"category": "financial-card",
"purpose": "payment",
"sharedWith": ["payment provider"],
"controls": [
"Do not store PAN unless in PCI DSS scope; prefer tokenization by the payment provider",
"Never store CVV after authorization",
"Segmented network and scope documentation",
"Key management with rotation"
],
"regulationHints": { "BR": "PCI DSS v4.0.1 (contractual) and BCB regulation for payment institutions" },
"questions": [
"Retention period and deletion trigger are undefined",
"Storage residency and cross-border transfer path are undefined",
"Confirm processor or controller agreements with: payment provider"
]
}
],
"summary": { "personal": 2, "financial-card": 1, "sensitive-personal": 0, "credential": 0 },
"nextTools": ["threat_model", "well_architected_review", "decision_record"]
}iam_policy_review: s3: e Resource em três achados, e o que ele não prova
iam_policy_review recebe um único argumento, policy: o documento JSON da política IAM. A do exemplo tem dois statements. O Statement[0] permite s3: em Resource: "", sem condição. O Statement[1] permite dynamodb:GetItem e dynamodb:PutItem num ARN de tabela específico, com Condition em aws:RequestedRegion.
O resultado traz três findings, todos em Statement[0]: high, "Broad allowed action; enumerate operations and justify scope" (a ação termina em :); medium, "Wildcard resource; verify whether each action supports resource-level restrictions" (o Resource é ); e info, "No conditions; evaluate source account, source ARN, region and organization boundaries where supported". O Statement[1] não aparece. As regras são seis e estão em src/review.ts: ação ou serviço:, NotAction, NotResource, Resource com , Principal com e ausência de Condition. Só statements com Effect: Allow são olhados.
Agora o que importa: o Statement[1] ter saído limpo não quer dizer que ele esteja correto. Quer dizer que nenhum dos seis padrões casou. A ferramenta declara as limitations: "No effective permission or condition evaluation", "Cannot prove policy safety", "No account calls or policy changes". Para validação autoritativa, a fonte citada no próprio resultado é a validação de políticas do IAM Access Analyzer. Eu uso o iam_policy_review como triagem: em menos de um segundo ele separa a política que precisa de conversa da que precisa de leitura atenta.
Essa ferramenta também roda no CLI com o documento bruto: node dist/cli.js call iam_policy_review --input politica.json embrulha o arquivo no argumento policy sozinho. Com --format sarif --fail-on high o processo sai com código 1 se existir achado high, o que é tudo que um pipeline precisa para barrar um merge e esperar um humano. Na próxima aula isso vira rotina para Terraform, CloudFormation e Kubernetes.
# o arquivo é a própria política; o CLI a embrulha no argumento "policy"
# the file is the policy itself; the CLI wraps it in the "policy" argument
node dist/cli.js call iam_policy_review --input iam-worker.json --format markdown
# para o pipeline: SARIF + falha em high (exit 0 ok, 1 achado >= threshold, 2 erro de entrada)
node dist/cli.js call iam_policy_review --input iam-worker.json --format sarif --fail-on high > iam.sarif
echo "exit=$?"Ordem de trabalho da skill architecture-review
- 1
requirements_check
Expõe as lacunas do brief. Se SLO ou orçamento estiverem faltando, pare e pergunte; não preencha com valores típicos.
- 2
c4_model
Contexto e depois contêiner, para que todo revisor olhe a mesma figura antes de opinar.
- 3
threat_model + data_classification
STRIDE por fronteira de confiança e classificação para cada repositório de dados. Saem perguntas, não vereditos.
- 4
well_architected_review (+ iam_policy_review)
Um controle é met só com evidência; o resto é unknown. Políticas IAM passam pela triagem heurística aqui.
- 5
Números e recuperação
capacity_plan, latency_budget e queue_sizing para as contas; cost_model com fontes datadas; dr_strategy e failure_rehearsal para o que acontece quando quebra.
- 6
decision_record + implementation_plan
Um ADR para cada coisa que mudou e um plano com portões de validação. O prompt architecture_review encadeia tudo isso numa conversa.
O que um achado precisa ter (e o que não é achado)
platform-team no controle cost-alerts.Glossário: os seis pilares e as seis letras de STRIDE
Toque num cartão para virar.