nexus-core-v3 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (232) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +134 -0
  3. package/agents/README.md +133 -0
  4. package/agents/_protocol.md +107 -0
  5. package/agents/analyst.md +138 -0
  6. package/agents/architect.md +146 -0
  7. package/agents/data-engineer.md +170 -0
  8. package/agents/dev.md +134 -0
  9. package/agents/devops.md +141 -0
  10. package/agents/nexus-master.md +147 -0
  11. package/agents/pm.md +133 -0
  12. package/agents/po.md +138 -0
  13. package/agents/qa.md +192 -0
  14. package/agents/sm.md +122 -0
  15. package/agents/squad-creator.md +121 -0
  16. package/agents/ux-design-expert.md +165 -0
  17. package/artifact-manifest.json +903 -0
  18. package/bin/nexus.mjs +37 -0
  19. package/checklists/README.md +49 -0
  20. package/checklists/architect-checklist.md +47 -0
  21. package/checklists/change-checklist.md +61 -0
  22. package/checklists/db-predeploy-checklist.md +57 -0
  23. package/checklists/design-quality-checklist.md +57 -0
  24. package/checklists/discovery-checklist.md +36 -0
  25. package/checklists/foundation-checklist.md +39 -0
  26. package/checklists/launch-checklist.md +39 -0
  27. package/checklists/pm-checklist.md +48 -0
  28. package/checklists/po-master-checklist.md +64 -0
  29. package/checklists/reality-check-checklist.md +49 -0
  30. package/checklists/story-dod-checklist.md +52 -0
  31. package/checklists/story-draft-checklist.md +36 -0
  32. package/dist/bin/dashboard.html +279 -0
  33. package/dist/bin/nexus.mjs +20008 -0
  34. package/dist/constitution.yaml +76 -0
  35. package/knowledge/README.md +57 -0
  36. package/knowledge/architecture/architectural-styles-map.md +182 -0
  37. package/knowledge/architecture/design-patterns-gof.md +192 -0
  38. package/knowledge/architecture/distributed-patterns-cheatsheet.md +201 -0
  39. package/knowledge/architecture/saas-subscription-blueprint.md +355 -0
  40. package/knowledge/architecture/system-design-tradeoffs.md +231 -0
  41. package/knowledge/architecture/t3-fullstack-typesafe-stack.md +273 -0
  42. package/knowledge/copy/landing-copy-that-converts.md +168 -0
  43. package/knowledge/data/postgres-indexing-and-tuning.md +263 -0
  44. package/knowledge/data/schema-modeling-decisions.md +273 -0
  45. package/knowledge/data/supabase-rls-patterns.md +316 -0
  46. package/knowledge/data/zero-downtime-migrations.md +308 -0
  47. package/knowledge/devops/cicd-pipeline-best-practices.md +318 -0
  48. package/knowledge/devops/production-dockerfile.md +283 -0
  49. package/knowledge/devops/twelve-factor-app.md +398 -0
  50. package/knowledge/engineering/clean-code-principles.md +429 -0
  51. package/knowledge/engineering/effective-code-review.md +204 -0
  52. package/knowledge/engineering/testing-strategy-beyond-unit.md +307 -0
  53. package/knowledge/governance/risk-matrix.md +56 -0
  54. package/knowledge/integration/mcp-server-selection-matrix.md +235 -0
  55. package/knowledge/marketing/copy-que-converte.md +43 -0
  56. package/knowledge/marketing/funil-e-jornada.md +36 -0
  57. package/knowledge/negocios/proposta-vencedora.md +38 -0
  58. package/knowledge/negocios/roi-e-unit-economics.md +46 -0
  59. package/knowledge/pipeline/1-descobrir.md +26 -0
  60. package/knowledge/pipeline/2-estrategizar.md +26 -0
  61. package/knowledge/pipeline/3-estruturar.md +27 -0
  62. package/knowledge/pipeline/4-construir.md +27 -0
  63. package/knowledge/pipeline/5-endurecer.md +28 -0
  64. package/knowledge/pipeline/6-lancar.md +27 -0
  65. package/knowledge/pipeline/7-operar.md +27 -0
  66. package/knowledge/security/lgpd-conformidade-basica.md +35 -0
  67. package/knowledge/security/owasp-secure-coding-gates.md +220 -0
  68. package/knowledge/security/owasp-top10-threat-assessment.md +287 -0
  69. package/knowledge/security/threat-modeling-stride.md +34 -0
  70. package/knowledge/web-craft/a11y-audit-checklist.md +251 -0
  71. package/knowledge/web-craft/accessible-component-patterns.md +383 -0
  72. package/knowledge/web-craft/anti-ai-look.md +114 -0
  73. package/knowledge/web-craft/design-system-from-code.md +195 -0
  74. package/knowledge/web-craft/intrinsic-css-layout.md +420 -0
  75. package/knowledge/web-craft/style-cloning.md +185 -0
  76. package/knowledge/web-craft/visual-polish-review.md +183 -0
  77. package/package.json +55 -0
  78. package/runbooks/campanha-de-conteudo.md +36 -0
  79. package/runbooks/feature-em-projeto-existente.md +37 -0
  80. package/runbooks/mvp-startup.md +38 -0
  81. package/runbooks/resposta-a-incidente.md +37 -0
  82. package/squads/exemplo-conteudo/agents/editor-chefe.md +48 -0
  83. package/squads/exemplo-conteudo/agents/pesquisador.md +44 -0
  84. package/squads/exemplo-conteudo/agents/redator.md +45 -0
  85. package/squads/exemplo-conteudo/knowledge/estilo-editorial.md +21 -0
  86. package/squads/exemplo-conteudo/squad.yaml +19 -0
  87. package/squads/exemplo-conteudo/tasks/pesquisar-fontes.md +26 -0
  88. package/squads/exemplo-conteudo/tasks/planejar-pauta.md +27 -0
  89. package/squads/exemplo-conteudo/tasks/redigir-artigo.md +26 -0
  90. package/squads/exemplo-conteudo/tasks/revisar-artigo.md +27 -0
  91. package/squads/marketing/agents/analista.md +56 -0
  92. package/squads/marketing/agents/chefe-marketing.md +65 -0
  93. package/squads/marketing/agents/conteudo.md +55 -0
  94. package/squads/marketing/agents/copy.md +55 -0
  95. package/squads/marketing/agents/growth.md +56 -0
  96. package/squads/marketing/agents/social.md +55 -0
  97. package/squads/marketing/squad.yaml +17 -0
  98. package/squads/marketing/tasks/aprovar-campanha.md +43 -0
  99. package/squads/negocios/agents/chefe-negocios.md +65 -0
  100. package/squads/negocios/agents/financas-roi.md +55 -0
  101. package/squads/negocios/agents/suporte.md +55 -0
  102. package/squads/negocios/agents/vendas-proposta.md +56 -0
  103. package/squads/negocios/squad.yaml +17 -0
  104. package/squads/negocios/tasks/aprovar-proposta.md +40 -0
  105. package/squads/security/agents/appsec-reviewer.md +59 -0
  106. package/squads/security/agents/chefe-seguranca.md +65 -0
  107. package/squads/security/agents/compliance-auditor.md +60 -0
  108. package/squads/security/agents/threat-modeler.md +60 -0
  109. package/squads/security/squad.yaml +20 -0
  110. package/squads/security/tasks/aprovar-gate-seguranca.md +42 -0
  111. package/squads/security/tasks/emitir-parecer-conformidade.md +42 -0
  112. package/tasks/README.md +72 -0
  113. package/tasks/accessibility-wcag-checklist.md +69 -0
  114. package/tasks/advanced-elicitation.md +42 -0
  115. package/tasks/analyze-performance.md +54 -0
  116. package/tasks/analyze-project-structure.md +59 -0
  117. package/tasks/apply-qa-fixes.md +57 -0
  118. package/tasks/architect-analyze-impact.md +62 -0
  119. package/tasks/archive-squad.md +52 -0
  120. package/tasks/audit-codebase.md +53 -0
  121. package/tasks/build-component.md +61 -0
  122. package/tasks/calculate-roi.md +63 -0
  123. package/tasks/ci-cd-configuration.md +51 -0
  124. package/tasks/collect-visual-evidence.md +62 -0
  125. package/tasks/compose-molecule.md +57 -0
  126. package/tasks/consolidate-patterns.md +54 -0
  127. package/tasks/create-brownfield-prd.md +54 -0
  128. package/tasks/create-competitor-analysis.md +42 -0
  129. package/tasks/create-deep-research-prompt.md +62 -0
  130. package/tasks/create-doc.md +62 -0
  131. package/tasks/create-epic.md +49 -0
  132. package/tasks/create-front-end-spec.md +56 -0
  133. package/tasks/create-migration-plan.md +57 -0
  134. package/tasks/create-next-story.md +66 -0
  135. package/tasks/create-prd.md +53 -0
  136. package/tasks/create-project-brief.md +47 -0
  137. package/tasks/create-rls-policies.md +59 -0
  138. package/tasks/create-schema.md +57 -0
  139. package/tasks/create-service.md +55 -0
  140. package/tasks/create-squad.md +100 -0
  141. package/tasks/create-suite.md +62 -0
  142. package/tasks/db-apply-migration.md +56 -0
  143. package/tasks/db-domain-modeling.md +57 -0
  144. package/tasks/db-dry-run.md +50 -0
  145. package/tasks/db-env-check.md +57 -0
  146. package/tasks/db-load-csv.md +54 -0
  147. package/tasks/db-policy-apply.md +58 -0
  148. package/tasks/db-rollback.md +51 -0
  149. package/tasks/db-run-sql.md +61 -0
  150. package/tasks/db-seed.md +52 -0
  151. package/tasks/db-smoke-test.md +51 -0
  152. package/tasks/db-snapshot.md +48 -0
  153. package/tasks/db-verify-order.md +49 -0
  154. package/tasks/deliberate.md +46 -0
  155. package/tasks/design-indexes.md +59 -0
  156. package/tasks/dev-develop-story.md +61 -0
  157. package/tasks/document-project.md +59 -0
  158. package/tasks/execute-checklist.md +57 -0
  159. package/tasks/execute-epic-plan.md +52 -0
  160. package/tasks/execute-subtask.md +51 -0
  161. package/tasks/extend-pattern.md +63 -0
  162. package/tasks/extend-squad.md +60 -0
  163. package/tasks/extract-patterns.md +64 -0
  164. package/tasks/extract-tokens.md +59 -0
  165. package/tasks/facilitate-brainstorming-session.md +42 -0
  166. package/tasks/generate-ai-frontend-prompt.md +57 -0
  167. package/tasks/generate-documentation.md +60 -0
  168. package/tasks/generate-migration-strategy.md +57 -0
  169. package/tasks/generate-shock-report.md +56 -0
  170. package/tasks/mcp-management.md +66 -0
  171. package/tasks/orchestrate.md +50 -0
  172. package/tasks/perform-market-research.md +42 -0
  173. package/tasks/plan-create-context.md +57 -0
  174. package/tasks/plan-create-implementation.md +58 -0
  175. package/tasks/po-close-story.md +60 -0
  176. package/tasks/po-manage-story-backlog.md +59 -0
  177. package/tasks/po-pull-story.md +60 -0
  178. package/tasks/po-sync-story.md +59 -0
  179. package/tasks/pr-automation.md +50 -0
  180. package/tasks/pre-push-quality-gate.md +54 -0
  181. package/tasks/push.md +53 -0
  182. package/tasks/qa-browser-console-check.md +52 -0
  183. package/tasks/qa-create-fix-request.md +58 -0
  184. package/tasks/qa-evidence-requirements.md +55 -0
  185. package/tasks/qa-false-positive-detection.md +55 -0
  186. package/tasks/qa-fix-issues.md +55 -0
  187. package/tasks/qa-gate.md +53 -0
  188. package/tasks/qa-migration-validation.md +58 -0
  189. package/tasks/qa-nfr-assess.md +45 -0
  190. package/tasks/qa-review-story.md +56 -0
  191. package/tasks/qa-risk-profile.md +45 -0
  192. package/tasks/qa-security-checklist.md +64 -0
  193. package/tasks/qa-test-design.md +47 -0
  194. package/tasks/qa-trace-requirements.md +48 -0
  195. package/tasks/release-management.md +53 -0
  196. package/tasks/repository-cleanup.md +61 -0
  197. package/tasks/route.md +44 -0
  198. package/tasks/run-tests.md +50 -0
  199. package/tasks/security-audit.md +54 -0
  200. package/tasks/setup-database.md +60 -0
  201. package/tasks/setup-design-system.md +60 -0
  202. package/tasks/shard-doc.md +60 -0
  203. package/tasks/spec-assess-complexity.md +55 -0
  204. package/tasks/spec-critique.md +64 -0
  205. package/tasks/spec-gather-requirements.md +48 -0
  206. package/tasks/spec-research-dependencies.md +42 -0
  207. package/tasks/spec-write-spec.md +50 -0
  208. package/tasks/test-as-user.md +52 -0
  209. package/tasks/ux-create-wireframe.md +54 -0
  210. package/tasks/ux-user-research.md +55 -0
  211. package/tasks/validate-next-story.md +61 -0
  212. package/tasks/validate-squad.md +55 -0
  213. package/tasks/verify-subtask.md +52 -0
  214. package/tasks/version-management.md +45 -0
  215. package/templates/README.md +47 -0
  216. package/templates/architecture-tmpl.md +115 -0
  217. package/templates/competitor-analysis-tmpl.md +87 -0
  218. package/templates/epic-tmpl.md +83 -0
  219. package/templates/front-end-spec-tmpl.md +110 -0
  220. package/templates/market-research-tmpl.md +98 -0
  221. package/templates/migration-plan-tmpl.md +92 -0
  222. package/templates/prd-tmpl.md +95 -0
  223. package/templates/project-brief-tmpl.md +100 -0
  224. package/templates/qa-verdict-tmpl.md +73 -0
  225. package/templates/rls-policies-tmpl.md +93 -0
  226. package/templates/schema-design-tmpl.md +107 -0
  227. package/templates/spec-tmpl.md +88 -0
  228. package/templates/squad/agent-dna-tmpl.md +72 -0
  229. package/templates/squad/chief-dna-tmpl.md +98 -0
  230. package/templates/squad/squad-task-tmpl.md +50 -0
  231. package/templates/squad/squad-yaml-tmpl.md +47 -0
  232. package/templates/story-tmpl.md +63 -0
@@ -0,0 +1,287 @@
1
+ ---
2
+ id: owasp-top10-threat-assessment
3
+ domain: security
4
+ agents: [qa]
5
+ when: "ao fazer uma avaliação de risco de segurança de uma aplicação"
6
+ ---
7
+
8
+ # OWASP Top 10 (2021) — threat assessment acionável
9
+
10
+ Fonte: OWASP Top 10:2021 (owasp.org/Top10). Cada categoria abaixo traz o **risco em uma linha**,
11
+ **como detectar** (e onde no pipeline), um **cenário de ataque concreto** e a **prevenção** — extraídos
12
+ do material oficial, não inventados.
13
+
14
+ ## O problema
15
+
16
+ Uma avaliação de risco genérica produz um relatório que ninguém usa: "valide entradas", "use HTTPS",
17
+ "mantenha dependências atualizadas". Isso é prosa. Um threat assessment **útil** amarra cada risco a:
18
+
19
+ 1. **Um CWE** concreto (rastreável, não opinião).
20
+ 2. **Uma técnica de detecção** com a ferramenta certa (SAST/DAST/IAST/SCA) e o **ponto do pipeline**
21
+ onde ela roda — porque SAST acha SQLi mas não acha broken access control; DAST acha o oposto.
22
+ 3. **Um cenário de ataque** que o time consegue reproduzir.
23
+ 4. **Um controle de prevenção** verificável por teste.
24
+
25
+ Os tells de um assessment ruim: lista as 10 categorias sem dizer **como achar cada uma**; mistura
26
+ SAST e DAST como se fossem intercambiáveis; recomenda "input validation" para A01 (Broken Access
27
+ Control), onde validação de input não resolve nada — o problema é autorização, não sanitização.
28
+
29
+ ### A regra que mais se erra: qual ferramenta acha o quê
30
+
31
+ | Técnica | Quando roda | Acha bem | NÃO acha |
32
+ |---|---|---|---|
33
+ | **SAST** (estático, lê código) | Pre-commit / PR / CI build | A03 Injection, A02 cripto fraca, hardcoded secrets, A08 deserialização | A01 access control (precisa de contexto de runtime/autorização), A05 config de ambiente, A09 logging gaps |
34
+ | **DAST** (dinâmico, ataca app rodando) | Staging / nightly / pre-release | A01 (force browsing, IDOR), A05 (headers, error pages), A10 SSRF, A07 (sem rate-limit em login) | Bugs em caminhos não exercitados; lógica de negócio (A04) sem casos de abuso modelados |
35
+ | **IAST** (instrumenta app durante testes) | Durante testes E2E/integração em CI | A03 com baixo falso-positivo (vê o dado fluir até o sink), A02 em runtime | Cobertura limitada ao que os testes exercitam |
36
+ | **SCA** (software composition analysis) | Pre-commit / CI / monitoramento contínuo | A06 componentes vulneráveis (CVE/NVD), A08 supply chain | Vulnerabilidades no SEU código |
37
+ | **Threat modeling** (manual, design-time) | Antes de codar; em mudança de fluxo crítico | A04 Insecure Design, A01 a nível de regra de negócio | Bugs de implementação |
38
+ | **Secret scanning** | Pre-commit (hook) + CI | A02 (CWE-259 hardcoded), A07 default creds | — |
39
+
40
+ Regra prática: **SAST + SCA + secret scanning no PR (rápido), DAST + IAST em staging (lento), threat
41
+ modeling no design.** Nenhuma das três sozinha cobre o Top 10.
42
+
43
+ ## O conhecimento / os princípios
44
+
45
+ ### A01:2021 — Broken Access Control
46
+
47
+ - **Risco (1 linha):** usuário age fora das permissões pretendidas → leitura/escrita/destruição de
48
+ dados de outros ou execução de função de negócio fora do seu limite. (CWE-200, CWE-201, CWE-352)
49
+ - **Como detectar:** **DAST** + teste manual de autorização em staging (SAST é cego aqui). Force
50
+ browsing a páginas privilegiadas; trocar IDs em IDOR; chamar API com método não autorizado
51
+ (POST/PUT/DELETE). Em CI, **testes de integração de autorização** rodando como user A tentando
52
+ acessar recurso de user B.
53
+ - **Cenário de ataque (oficial):** atacante troca o parâmetro do browser para acessar conta alheia —
54
+ `https://example.com/app/accountInfo?acct=notmyacct` — ou faz force browsing a
55
+ `https://example.com/app/admin_getappInfo` sem ser admin.
56
+ - **Prevenção:** *deny by default* para todo recurso não-público; impor **ownership de registro** (não
57
+ assumir que o user pode acessar qualquer registro); um único mecanismo de access control reusado em
58
+ todo o app; invalidar sessão server-side no logout; **testes unit e de integração de access control**;
59
+ rate-limit; logar falhas de access control e alertar.
60
+
61
+ ```sql
62
+ -- VULNERÁVEL: confia no acct vindo do cliente, sem checar ownership
63
+ SELECT * FROM accounts WHERE acct_id = :acct; -- :acct = "notmyacct"
64
+
65
+ -- CORRETO: ownership forçado no WHERE — o user só vê o que é dele
66
+ SELECT * FROM accounts WHERE acct_id = :acct AND owner_user_id = :session_user_id;
67
+ ```
68
+
69
+ ### A02:2021 — Cryptographic Failures
70
+
71
+ - **Risco (1 linha):** falha (ou ausência) de criptografia expõe dado sensível. (CWE-259 senha
72
+ hardcoded, CWE-327 algoritmo quebrado/arriscado, CWE-331 entropia insuficiente)
73
+ - **Como detectar:** **SAST** para MD5/SHA1/algoritmos depreciados e padding PKCS#1 v1.5; **secret
74
+ scanning** no pre-commit para chaves/senhas hardcoded; **DAST**/análise de TLS em staging para falta
75
+ de HSTS, downgrade HTTP, ciphers fracos.
76
+ - **Cenário de ataque (oficial):** app armazena cartão com criptografia automática do banco, que
77
+ **descriptografa ao ler** — uma falha de SQL injection retorna os números em texto claro. Outro:
78
+ banco de senhas usa hash **sem salt ou hash simples**; um upload flaw permite roubar o arquivo.
79
+ - **Prevenção:** classificar o dado; **não armazenar dado sensível desnecessário**; criptografar em
80
+ repouso e em trânsito (TLS com FS, HSTS); **senhas com Argon2/scrypt/bcrypt/PBKDF2** com work factor;
81
+ IV via CSPRNG e **nunca reutilizado com a mesma chave**; usar **authenticated encryption**; evitar
82
+ MD5, SHA1, PKCS#1 v1.5.
83
+
84
+ ```python
85
+ # VULNERÁVEL — CWE-327 / CWE-916: hash rápido e sem salt
86
+ import hashlib
87
+ pwd_hash = hashlib.sha256(password.encode()).hexdigest()
88
+
89
+ # CORRETO — adaptive + salted com work factor (Argon2)
90
+ from argon2 import PasswordHasher
91
+ ph = PasswordHasher() # gera salt e parametriza custo
92
+ pwd_hash = ph.hash(password)
93
+ ph.verify(pwd_hash, password)
94
+ ```
95
+
96
+ ### A03:2021 — Injection
97
+
98
+ - **Risco (1 linha):** dado não-confiável não validado/sanitizado vira parte de query ou comando.
99
+ (CWE-89 SQLi, CWE-79 XSS, CWE-73 path)
100
+ - **Como detectar:** **SAST** (taint analysis: source → sink) no PR; **IAST** durante testes E2E para
101
+ baixo falso-positivo; **DAST** em staging para XSS refletido e SQLi cego.
102
+ - **Cenário de ataque (oficial):** construção de SQL por concatenação em Java —
103
+ `String query = "SELECT * FROM accounts WHERE custID='" + request.getParameter("id") + "'";` — e o
104
+ atacante envia `id` = `' UNION SELECT SLEEP(10);--`, via
105
+ `http://example.com/app/accountView?id=' UNION SELECT SLEEP(10);--`, mudando o sentido da query.
106
+ - **Prevenção:** **API segura/parametrizada ou ORM** (evita o interpretador); validação positiva
107
+ server-side (não é defesa completa); para query dinâmica residual, **escape com a sintaxe específica
108
+ do interpretador**.
109
+
110
+ ```java
111
+ // VULNERÁVEL (oficial) — concatenação
112
+ String query = "SELECT * FROM accounts WHERE custID='" + request.getParameter("id") + "'";
113
+
114
+ // CORRETO — query parametrizada (PreparedStatement)
115
+ PreparedStatement ps = conn.prepareStatement(
116
+ "SELECT * FROM accounts WHERE custID = ?");
117
+ ps.setString(1, request.getParameter("id")); // o input nunca vira código SQL
118
+ ResultSet rs = ps.executeQuery();
119
+ ```
120
+
121
+ ### A04:2021 — Insecure Design
122
+
123
+ - **Risco (1 linha):** controle ausente ou ineficaz **por design** (falha de arquitetura, não de
124
+ implementação). (CWE-209 erro com info sensível, CWE-256/522 credenciais, CWE-501 trust boundary)
125
+ - **Como detectar:** **threat modeling no design** (SAST/DAST não acham — não há bug, há ausência de
126
+ controle); revisão de arquitetura; **casos de abuso** escritos como testes de integração.
127
+ - **Cenário de ataque (oficial):** rede de cinema dá desconto de grupo com máximo de 15 lugares antes
128
+ de exigir depósito; o atacante modela o fluxo e reserva **600 lugares em todos os cinemas** em poucos
129
+ requests, causando perda massiva. Outro: e-commerce sem proteção contra bots de scalpers comprando
130
+ placas de vídeo.
131
+ - **Prevenção:** SDLC seguro com AppSec; **biblioteca de design patterns seguros**; threat modeling
132
+ para auth/access control/lógica de negócio; **plausibility checks em cada camada**; unit/integration
133
+ tests que validam os fluxos críticos contra o threat model (use-cases **e** misuse-cases); limitar
134
+ consumo de recurso por usuário/serviço.
135
+
136
+ ### A05:2021 — Security Misconfiguration
137
+
138
+ - **Risco (1 linha):** hardening ausente, features desnecessárias ligadas, credenciais default,
139
+ erros vazando info. (CWE-16 Configuration, CWE-611 XXE, CWE-614 cookie sem Secure)
140
+ - **Como detectar:** **DAST** em staging (security headers ausentes, directory listing, stack traces
141
+ em erro, XXE); scanners de config/IaC no CI; checagem de buckets de cloud com permissão default.
142
+ - **Cenário de ataque (oficial):** app de exemplo com falha conhecida fica em produção e
143
+ **credencial admin default não foi trocada**; directory listing ligado deixa baixar classes
144
+ compiladas e descompilar; erro detalhado (stack trace) **revela versões de componentes**; storage de
145
+ cloud com sharing default aberto à Internet.
146
+ - **Prevenção:** **processo de hardening repetível**; plataforma mínima (sem features/samples
147
+ desnecessários); review de config no patch management; arquitetura segmentada; **security headers**
148
+ enviados ao cliente; **processo automatizado** que verifica a efetividade das configs em todos os
149
+ ambientes.
150
+
151
+ ```http
152
+ # CORRETO — diretivas de segurança enviadas ao cliente (mitiga A05/A02)
153
+ Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
154
+ Content-Security-Policy: default-src 'self'
155
+ X-Content-Type-Options: nosniff
156
+ Set-Cookie: session=...; Secure; HttpOnly; SameSite=Strict
157
+ ```
158
+
159
+ ### A06:2021 — Vulnerable and Outdated Components
160
+
161
+ - **Risco (1 linha):** uso de componentes com vulnerabilidade conhecida; componentes rodam com o
162
+ mesmo privilégio do app. (CWE-937, CWE-1035, CWE-1104 componente não mantido)
163
+ - **Como detectar:** **SCA** no PR e **monitoramento contínuo** (OWASP Dependency-Check, retire.js),
164
+ acompanhando CVE/NVD com assinatura de alertas — não é evento único, é processo de lifetime.
165
+ - **Cenário de ataque (oficial):** **CVE-2017-5638**, RCE no Struts 2, permite executar código
166
+ arbitrário no servidor e foi responsabilizado por grandes vazamentos. IoT é caso difícil de patch
167
+ com alto risco (biomédico, crítico).
168
+ - **Prevenção:** eliminar dependências/features não usadas; **rastrear versões cliente e servidor**
169
+ continuamente; obter componentes **só de fontes oficiais por links seguros**, preferir **pacotes
170
+ assinados**; virtual patching quando não dá para corrigir; **plano contínuo** de monitorar/triar/
171
+ aplicar updates pela vida da aplicação.
172
+
173
+ ### A07:2021 — Identification and Authentication Failures
174
+
175
+ - **Risco (1 linha):** confirmação de identidade, autenticação e gestão de sessão fracas abrem
176
+ credential stuffing, brute force e reuso de credencial roubada. (CWE-287, CWE-297, CWE-384 session
177
+ fixation)
178
+ - **Como detectar:** **DAST**/teste de auth em staging (login sem rate-limit, mensagens que permitem
179
+ enumeração de conta, timeout de sessão incorreto); **secret scanning** para credenciais default;
180
+ testes que verificam rotação de session ID após login.
181
+ - **Cenário de ataque (oficial):** **credential stuffing** — atacante usa listas de senhas conhecidas
182
+ contra um app que funciona como validador de senha sem proteção; reuso de sessão em computador
183
+ público quando o user não faz logout (timeout impróprio).
184
+ - **Prevenção:** **MFA** contra stuffing/brute force; **não shipar credenciais default** (sobretudo
185
+ admin); testar senha nova contra a lista das **10.000 piores senhas**; alinhar política ao **NIST
186
+ 800-63b**; **mesma mensagem para todos os desfechos** (evita enumeração); atrasar/limitar logins
187
+ falhos; **session manager server-side que gera novo session ID de alta entropia após login**.
188
+
189
+ ### A08:2021 — Software and Data Integrity Failures
190
+
191
+ - **Risco (1 linha):** código e infra que não protegem contra violação de integridade (updates,
192
+ deserialização, pipeline CI/CD). (CWE-829, CWE-494 download sem checagem, CWE-502 deserialização)
193
+ - **Como detectar:** **SCA**/supply-chain tool (OWASP Dependency-Check, CycloneDX) no CI; **SAST**
194
+ para deserialização insegura; revisão de **segregação e access control do pipeline CI/CD**.
195
+ - **Cenário de ataque (oficial):** **SolarWinds Orion** — nation-state ataca o mecanismo de update e
196
+ distribui update malicioso a **18.000+ organizações**. **Deserialização insegura**: atacante nota a
197
+ assinatura `rO0` (objeto Java em base64) e usa o **Java Serial Killer** para RCE no servidor.
198
+ - **Prevenção:** **assinaturas digitais** para verificar origem e integridade; libs/deps de
199
+ **repositórios confiáveis** (considerar repo interno vetado); supply-chain tool checando CVE; review
200
+ de mudanças de código e config; **CI/CD com segregação e access control**; **não enviar dado
201
+ serializado sem assinatura/integridade** a clientes não-confiáveis.
202
+
203
+ ### A09:2021 — Security Logging and Monitoring Failures
204
+
205
+ - **Risco (1 linha):** sem logging/monitoramento suficiente, breaches ativos não são detectados,
206
+ escalados nem respondidos. (CWE-117 log injection, CWE-223 omissão, CWE-532 dado sensível em log,
207
+ CWE-778 logging insuficiente)
208
+ - **Como detectar:** revisão de cobertura de logs (login/access control/validação falham e são
209
+ logados?); teste se **transações de alto valor** têm trilha íntegra (append-only); verificar tempo
210
+ de detecção em exercício de resposta a incidente.
211
+ - **Cenário de ataque (oficial):** provedor de plano de saúde infantil **não detectou** o breach por
212
+ falta de logging/monitoramento; um terceiro avisou que um atacante acessou e modificou registros de
213
+ **3,5 milhões de crianças** — o breach pode ter durado **mais de sete anos** (desde 2013). Companhia
214
+ aérea europeia foi multada em **£20 milhões** após 400.000 registros de pagamento colhidos.
215
+ - **Prevenção:** logar login/access control/validação com **contexto de usuário** e retenção para
216
+ forense; logs em **formato consumível** por SIEM; **encodar log** para evitar injeção; trilha de
217
+ auditoria **append-only com controle de integridade** para transações de alto valor; alerting do
218
+ DevSecOps; **plano de resposta a incidente** (NIST 800-61r2).
219
+
220
+ ### A10:2021 — Server-Side Request Forgery (SSRF)
221
+
222
+ - **Risco (1 linha):** o app busca um recurso remoto **sem validar a URL fornecida pelo usuário**.
223
+ (CWE-918)
224
+ - **Como detectar:** **DAST** em staging com payloads SSRF; **SAST** para sinks de fetch HTTP que
225
+ recebem URL de input do usuário; revisar se há **allow-list** de schema/porta/destino.
226
+ - **Cenário de ataque (oficial):** **port scanning** da rede interna via timing/respostas; leitura de
227
+ arquivo/serviço local — `file:///etc/passwd` e `http://localhost:28017/`; **metadata de cloud** via
228
+ `http://169.254.169.254/`; abuso de serviço interno para **RCE ou DoS**.
229
+ - **Prevenção (rede):** segmentar acesso a recurso remoto; firewall **deny by default** bloqueando
230
+ todo tráfego intranet não-essencial; logar fluxos aceitos/bloqueados. **(app):** validar todo input
231
+ do cliente; impor **schema, porta e destino por allow-list positiva**; **não devolver resposta crua**
232
+ ao cliente; **desabilitar redirects HTTP**; cuidar de **DNS rebinding** e **TOCTOU**.
233
+
234
+ ```python
235
+ # VULNERÁVEL — busca a URL que o usuário mandou (acesso a 169.254.169.254, file://, localhost)
236
+ url = request.args["url"]
237
+ return requests.get(url).text # devolve resposta crua = SSRF
238
+
239
+ # CORRETO — allow-list de schema + host; sem redirect; sem devolver resposta crua
240
+ from urllib.parse import urlparse
241
+ ALLOWED_HOSTS = {"api.parceiro.com"}
242
+ p = urlparse(request.args["url"])
243
+ if p.scheme != "https" or p.hostname not in ALLOWED_HOSTS:
244
+ abort(400)
245
+ r = requests.get(p.geturl(), allow_redirects=False, timeout=5)
246
+ return {"ok": r.status_code == 200} # nunca o corpo cru
247
+ ```
248
+
249
+ ## Checklist de threat-assessment (acionável por risco)
250
+
251
+ Marque por categoria; qualquer "não" é um achado a registrar com o CWE correspondente.
252
+
253
+ - [ ] **A01** Testes de integração provam que user A **não** acessa recurso de user B (IDOR/force
254
+ browsing); APIs têm controle em POST/PUT/DELETE; *deny by default*; ownership no `WHERE`.
255
+ - [ ] **A02** SAST não acusa MD5/SHA1/PKCS#1 v1.5; senhas em Argon2/bcrypt/scrypt/PBKDF2 com salt;
256
+ secret scanning verde (nada hardcoded); TLS + HSTS em todas as páginas.
257
+ - [ ] **A03** Zero concatenação de input em SQL/HQL/comando — tudo parametrizado/ORM; SAST/IAST verde
258
+ para taint source→sink; DAST não acha XSS/SQLi cego.
259
+ - [ ] **A04** Fluxos críticos têm threat model com **misuse-cases** virados em teste; limites de
260
+ negócio (qtd, valor) impostos por domínio; rate/resource limit por usuário.
261
+ - [ ] **A05** Hardening repetível + processo automatizado de verificação; sem credencial default; sem
262
+ directory listing; erro **não** vaza stack trace; security headers presentes; buckets fechados.
263
+ - [ ] **A06** SCA no PR + monitoramento contínuo de CVE/NVD; sem dependência não-mantida; componentes
264
+ de fonte oficial/assinados; plano de patch de lifetime.
265
+ - [ ] **A07** MFA disponível; sem credencial default; rate-limit/atraso em login falho; mensagem
266
+ uniforme (anti-enumeração); novo session ID de alta entropia após login; senha checada vs piores 10k.
267
+ - [ ] **A08** Updates/artefatos com assinatura digital; deps de repo confiável + supply-chain tool;
268
+ CI/CD segregado com access control; nada serializado sem integridade enviado a cliente não-confiável.
269
+ - [ ] **A09** Login/access control/validação falham **e são logados** com contexto; logs em formato de
270
+ SIEM e encodados; trilha append-only para alto valor; alerting e plano de IR (NIST 800-61r2).
271
+ - [ ] **A10** Toda URL de fetch passa por allow-list de schema/porta/host; redirects desabilitados;
272
+ resposta crua nunca devolvida; firewall deny-by-default no egress; proteção a DNS rebinding/TOCTOU.
273
+
274
+ ## Tabela de decisão "use X quando Y"
275
+
276
+ | Quando (Y) | Use (X) | Por quê |
277
+ |---|---|---|
278
+ | Achar **A03 Injection / A02 cripto fraca / hardcoded secret** antes do merge | **SAST + secret scanning no PR** | Lê o código sem rodar; pega taint source→sink e algoritmos depreciados rápido |
279
+ | Achar **A01 access control / A05 misconfig / A10 SSRF / A07 sem rate-limit** | **DAST em staging** | Só ataque ao app rodando revela autorização, headers, error pages e SSRF reais |
280
+ | Reduzir **falso-positivo de injection** com cobertura de teste | **IAST durante E2E em CI** | Instrumenta e vê o dado chegar ao sink — confirma exploitabilidade |
281
+ | Achar **A06 componente vulnerável / A08 supply chain** | **SCA no PR + monitoramento contínuo (CVE/NVD)** | Vulnerabilidade está na dependência, não no seu código; é processo de lifetime |
282
+ | Achar **A04 Insecure Design** (limite de negócio, fluxo abusável) | **Threat modeling no design + misuse-cases como teste** | Não há bug para scanner achar — é ausência de controle por design |
283
+ | Detectar **A09** (breach passando despercebido) | **Revisão de cobertura de log + alerting + exercício de IR** | Nenhum scanner mede "você perceberia um ataque agora?" |
284
+ | Decidir **prevenção de A01** | **Ownership no WHERE + deny-by-default**, não input validation | A01 é autorização; sanitizar input não corrige acesso indevido |
285
+ | Decidir **prevenção de A03** | **Query parametrizada/ORM**, não só escaping | Escaping é defesa residual; parametrização tira o input do plano de código |
286
+ | Decidir **prevenção de A07 contra stuffing** | **MFA + rate-limit + mensagem uniforme** | Senha forte sozinha não para reuso de credencial roubada |
287
+ | Priorizar achados | **Por impacto do CWE + exploitabilidade do cenário**, não por categoria | A06 com RCE conhecido (ex. CVE-2017-5638) > A05 cosmético |
@@ -0,0 +1,34 @@
1
+ # Modelagem de ameaças com STRIDE
2
+
3
+ Modelagem de ameaças é o exercício de olhar o sistema pelos olhos do atacante ANTES de ele olhar. O
4
+ método STRIDE dá seis lentes para não esquecer nenhuma classe de ameaça em cada fronteira de confiança.
5
+
6
+ ## Fronteira de confiança
7
+
8
+ O conceito central: todo lugar onde o dado cruza de um domínio controlado para um não-controlado (ou
9
+ com nível de confiança diferente) é uma fronteira. Ex.: browser → API, API → banco, serviço → serviço
10
+ externo, código → arquivo do usuário. As ameaças moram nas fronteiras, não no interior.
11
+
12
+ ## As seis lentes STRIDE
13
+
14
+ | Letra | Ameaça | Pergunta | Mitigação típica |
15
+ |---|---|---|---|
16
+ | **S** | Spoofing (falsificação de identidade) | Dá para se passar por outro? | autenticação forte, tokens assinados |
17
+ | **T** | Tampering (adulteração) | Dá para alterar dado em trânsito/repouso? | integridade (HMAC), TLS, validação |
18
+ | **R** | Repudiation (repúdio) | Dá para negar que fez? | logs de auditoria assináveis, trilha |
19
+ | **I** | Information disclosure (vazamento) | Dá para ler o que não devia? | criptografia, authz por recurso, minimização |
20
+ | **D** | Denial of service | Dá para derrubar/exaurir? | rate limit, quotas, timeouts, back-pressure |
21
+ | **E** | Elevation of privilege | Dá para virar admin? | authz por operação, princípio do menor privilégio |
22
+
23
+ ## Como aplicar
24
+
25
+ 1. Desenhe os componentes e os fluxos de dado — e MARQUE as fronteiras de confiança.
26
+ 2. Marque onde vivem os ativos sensíveis (credenciais, PII, dinheiro).
27
+ 3. Para cada fronteira, passe as seis lentes: a ameaça é possível? Há mitigação? Se não, é achado.
28
+ 4. Priorize por impacto × alcance (a ameaça que atinge todos vence a que atinge um).
29
+
30
+ ## Anti-padrões
31
+
32
+ - Modelar só o caminho feliz — o modelo tem de incluir o fluxo do atacante.
33
+ - Diagrama sem fronteiras de confiança — vira decoração, não análise.
34
+ - Tratar mitigação documentada como mitigação existente — verifique que ela roda.
@@ -0,0 +1,251 @@
1
+ ---
2
+ id: a11y-audit-checklist
3
+ domain: web-craft
4
+ agents: [ux-design-expert]
5
+ when: "ao auditar a acessibilidade de uma página/app"
6
+ ---
7
+
8
+ # A11y Audit Checklist — como AUDITAR acessibilidade (WCAG 2.2)
9
+
10
+ > **Este pack é o avesso do APG.** O APG (ARIA Authoring Practices) ensina **como CONSTRUIR** um
11
+ > combobox, um menu, um dialog. Este pack ensina **como AUDITAR** — pegar uma página pronta e provar,
12
+ > categoria por categoria, se ela passa ou falha, com o critério WCAG e o teste exato. APG = receita;
13
+ > isto = inspeção.
14
+
15
+ ## O problema
16
+
17
+ Acessibilidade "auditada" mal vira teatro: rodar o axe DevTools, ver "0 violations", declarar
18
+ acessível e seguir. Isso é falso. O **axe-core encontra ~30–57% dos problemas WCAG** (Deque mede ~57%
19
+ no melhor caso; estudos independentes ficam em 30–40%). Um scan limpo significa que você resolveu **a
20
+ parte automatizável** — sobram 40–70% que só aparecem com teclado, leitor de tela e olho humano.
21
+
22
+ Os tells de uma auditoria fake:
23
+ - **"Passou no axe" como veredito final.** O axe não sabe se o `alt` é significativo, se a ordem de
24
+ leitura faz sentido, se o anúncio do leitor de tela é compreensível. Ele valida sintaxe, não semântica.
25
+ - **Nunca se navegou pela página só com Tab.** Foco invisível, ordem ilógica e armadilhas de teclado
26
+ (keyboard trap) não aparecem em scan estático.
27
+ - **Nunca se ligou um leitor de tela.** Botão de ícone sem nome acessível, ordem de leitura quebrada,
28
+ `aria-label` que mente — tudo passa batido.
29
+ - **Contraste "no olho".** Sem medir, ninguém vê que `#999` sobre branco dá 2.85:1 e **falha**.
30
+ - **Auditou o estado feliz.** Não testou foco visível, erro de formulário, estado `:invalid`, modal aberto.
31
+
32
+ A régua deste pack: **toda afirmação de conformidade aponta para um critério WCAG 2.2 numerado + um
33
+ teste reproduzível.** "Parece acessível" não é veredito.
34
+
35
+ ## O conhecimento
36
+
37
+ ### Os números WCAG 2.2 que você precisa de cor (fonte: w3.org)
38
+
39
+ | Critério | Nível | Número exato | Não confunda |
40
+ |---|---|---|---|
41
+ | **1.4.3** Contraste (Mínimo) | AA | Texto normal **4.5:1**; texto grande **3:1** | "Grande" = **≥18pt (~24px)** OU **≥14pt bold (~18.5px)**. `4.499:1` **falha** — não arredonde. |
42
+ | **1.4.11** Contraste de não-texto | AA | **3:1** | Bordas de input, ícones de UI, foco, estado checked, partes de gráfico que carregam significado. Hover NÃO precisa contrastar com o default. |
43
+ | **2.4.7** Foco visível | AA | Indicador de foco visível | Default do browser conta, mas se você matou o outline tem que repor. |
44
+ | **2.4.11** Foco não obscurecido (Mín.) | AA | Foco ao menos **parcialmente** visível | **F110**: header/footer sticky que cobre 100% o elemento focado = falha. Resolva com `scroll-padding`. |
45
+ | **2.4.13** Aparência do foco | AAA | Foco com área ≥ perímetro de 2px e **3:1** entre focado/não-focado | AAA — meta, não obrigação AA. |
46
+ | **2.5.7** Movimentos de arrastar | AA | Toda ação de drag precisa de **alternativa de clique único** | Slider, kanban, reorder por drag. |
47
+ | **2.5.8** Tamanho do alvo (Mín.) | AA | Alvo de ponteiro **≥24×24 CSS px** | Exceções: spacing (círculo de 24px não intersecta), equivalente na mesma página, inline no texto, controle do UA, essencial (pin de mapa). |
48
+ | **3.3.7** Entrada redundante | A | Não pedir de novo o que já foi informado | Auto-preencher ou deixar selecionar. |
49
+ | **3.3.8** Autenticação acessível (Mín.) | AA | Sem teste de função cognitiva (decorar, transcrever) sem alternativa | Deixe colar senha; permita gerenciador de senha. |
50
+
51
+ ### Landmarks e ordem de headings — o esqueleto navegável
52
+
53
+ O leitor de tela navega por landmarks (`D` no NVDA) e por headings (`H`). Se o esqueleto está quebrado,
54
+ a página é inutilizável às cegas, mesmo com axe limpo.
55
+
56
+ ```html
57
+ <!-- Estrutura de landmark correta: cada região de conteúdo tem seu elemento -->
58
+ <header>…</header> <!-- role=banner implícito (1 por página) -->
59
+ <nav aria-label="Principal">…</nav>
60
+ <main>…</main> <!-- role=main implícito (EXATAMENTE 1) -->
61
+ <aside aria-label="Relacionados">…</aside>
62
+ <footer>…</footer> <!-- role=contentinfo implícito (1 por página) -->
63
+ ```
64
+
65
+ Regras de auditoria de headings (SC 1.3.1):
66
+ - **Exatamente um `<h1>`** por página, descrevendo o conteúdo principal.
67
+ - **Hierarquia sem pulos**: `h1 → h2 → h3`. Nunca `h2 → h4`. Pular nível confunde a navegação.
68
+ - Heading é para **estrutura**, não tamanho. "Quero texto grande" não justifica um `<h2>`.
69
+ - Dois `<nav>` no DOM? Cada um precisa de `aria-label` distinto pra serem distinguíveis.
70
+
71
+ ### Foco visível — o CSS que separa acessível de hostil
72
+
73
+ `outline: none` sem reposição é o pecado capital. O moderno:
74
+
75
+ ```css
76
+ /* Foco SÓ por teclado — não polui o clique de mouse, mas garante teclado */
77
+ :focus-visible {
78
+ outline: 2px solid var(--focus); /* 2px é o mínimo de 2.4.13 */
79
+ outline-offset: 2px; /* respira; não some na borda */
80
+ }
81
+ /* Nunca remova o foco sem repor algo perceptível */
82
+ :focus:not(:focus-visible) { outline: none; } /* ok: tira só do mouse */
83
+
84
+ /* Sticky header NÃO pode comer o foco (2.4.11 / F110) */
85
+ html { scroll-padding-top: 5rem; } /* altura do header sticky */
86
+
87
+ /* O indicador de foco precisa de 3:1 contra o fundo (1.4.11) */
88
+ ```
89
+
90
+ Teste: o contraste do anel de foco contra o fundo adjacente tem que bater **3:1**. Um foco azul claro
91
+ sobre fundo claro falha.
92
+
93
+ ### Formulários — o trio label / describedby / invalid
94
+
95
+ A maioria das falhas de form é o leitor de tela não saber o que é o campo, qual a dica, ou que deu erro.
96
+
97
+ ```html
98
+ <label for="email">E-mail</label>
99
+ <input
100
+ id="email"
101
+ type="email"
102
+ autocomplete="email"
103
+ aria-describedby="email-hint email-err"
104
+ aria-invalid="true"
105
+ />
106
+ <p id="email-hint">Usaremos só para o recibo.</p>
107
+ <p id="email-err" role="alert">E-mail inválido — falta o @.</p>
108
+ ```
109
+
110
+ Régua de auditoria:
111
+ - **Todo input tem `<label>` associado** (`for`/`id`), não placeholder fazendo de label. Placeholder
112
+ some ao digitar e costuma falhar contraste.
113
+ - **Dica e erro ligados via `aria-describedby`** — o leitor anuncia junto com o campo.
114
+ - **`aria-invalid="true"`** só no campo em erro, e a mensagem é texto (não só borda vermelha — cor
115
+ sozinha viola 1.4.1).
116
+ - **Grupos** (radios, checkboxes relacionados) em `<fieldset>` + `<legend>`.
117
+ - **`autocomplete`** correto (`email`, `name`, `tel`) — atende 1.3.5 e 3.3.7 (entrada redundante).
118
+ - Erros resumidos **em lista no topo do form**, cada item linkando ao campo.
119
+
120
+ ### Alt text e SVG acessível — a árvore de decisão
121
+
122
+ `alt` não é "descreva a imagem", é "qual o **propósito** dela aqui". A mesma foto tem alt diferente em
123
+ contextos diferentes.
124
+
125
+ | Imagem | Decisão |
126
+ |---|---|
127
+ | Informativa (gráfico, foto que carrega conteúdo) | `alt` descreve a informação, não a aparência |
128
+ | Decorativa (textura, divisor, blob) | `alt=""` (vazio, presente) — remove da árvore de acessibilidade |
129
+ | Dentro de link/botão sem texto | O alt/label carrega o **destino**: `alt="Página inicial"`, não `alt="logo"` |
130
+ | Complexa (gráfico de dados) | Alt curto + descrição longa adjacente (texto ou `<figcaption>`) |
131
+
132
+ SVG (fonte: CSS-Tricks, MDN) — três padrões, escolha um:
133
+
134
+ ```html
135
+ <!-- 1. SVG DECORATIVO (ícone ao lado de texto que já diz tudo) -->
136
+ <svg aria-hidden="true" focusable="false">…</svg>
137
+
138
+ <!-- 2. SVG SIGNIFICATIVO standalone (carrega sentido sozinho) -->
139
+ <svg role="img" aria-label="Aviso de erro">…</svg>
140
+
141
+ <!-- 3. BOTÃO/LINK SÓ DE ÍCONE: nome no controle, ícone escondido -->
142
+ <button aria-label="Fechar">
143
+ <svg aria-hidden="true" focusable="false">…</svg>
144
+ </button>
145
+ ```
146
+
147
+ Tell de auditoria: botão de ícone sem texto visível **e** sem `aria-label` → o leitor anuncia "botão"
148
+ sem nome. Falha 4.1.2. `focusable="false"` em SVG dentro de link é cinto-e-suspensório (legado do IE),
149
+ mas mantém previsível.
150
+
151
+ ### Reduced motion — respeite quem pede menos
152
+
153
+ ```css
154
+ @media (prefers-reduced-motion: reduce) {
155
+ *, *::before, *::after {
156
+ animation-duration: .01ms !important;
157
+ animation-iteration-count: 1 !important;
158
+ transition-duration: .01ms !important;
159
+ scroll-behavior: auto !important;
160
+ }
161
+ }
162
+ ```
163
+
164
+ Auditoria: ative "Reduzir movimento" no SO e recarregue. Parallax, auto-carousel, fade-up em scroll —
165
+ tudo deve cessar ou virar instantâneo. Animação que pisca >3×/s é gatilho de convulsão (2.3.1) e é
166
+ **bloqueante**, não negociável.
167
+
168
+ ### O teste que o axe NÃO faz — o protocolo manual
169
+
170
+ Auditoria de verdade tem 3 camadas. Pular qualquer uma é auditoria fake.
171
+
172
+ 1. **axe-core** (DevTools ou `@axe-core/playwright`): pega o automatizável (~30–57%). É o piso, não o teto.
173
+ 2. **Só teclado**: desconecte o mouse. `Tab` por toda a página.
174
+ - Chega em todo controle? A ordem segue o visual? O foco é sempre visível? Dá pra **sair** de
175
+ todo widget (sem keyboard trap)? `Esc` fecha modal? `Enter`/`Espaço` acionam?
176
+ 3. **Leitor de tela** (NVDA no Windows, VoiceOver no Mac — `Cmd+F5`): 10 minutos pegam o que nenhum
177
+ scanner pega.
178
+ - Navegue por headings (`H`) e landmarks. Faz sentido a estrutura?
179
+ - Todo botão/link tem **nome** anunciado? Imagens informativas têm alt útil? O erro de form é
180
+ **anunciado** ao ocorrer (`role="alert"`)? A ordem de leitura bate com a visual?
181
+
182
+ ## Checklist
183
+
184
+ Audite por categoria. Qualquer item marcado é uma **falha com critério WCAG** a corrigir.
185
+
186
+ **Estrutura (landmarks + headings)**
187
+ - [ ] Existe exatamente **um `<main>`** e exatamente **um `<h1>`**?
188
+ - [ ] Headings sem pulo de nível (sem `h2 → h4`)? (1.3.1)
189
+ - [ ] `<header>/<nav>/<main>/<footer>` usados como landmarks; `<nav>` repetidos têm `aria-label` distinto?
190
+ - [ ] `<html lang="pt-BR">` presente? `<title>` único e descritivo por página?
191
+
192
+ **Foco e teclado**
193
+ - [ ] Todo controle é alcançável por `Tab` e o **foco é sempre visível** (2.4.7)?
194
+ - [ ] Ordem de tabulação segue o layout visual; sem `tabindex` positivo?
195
+ - [ ] Nenhuma **armadilha de teclado**; `Esc` fecha modais/overlays?
196
+ - [ ] Header/footer sticky **não cobre 100%** o elemento focado (2.4.11 / F110)?
197
+ - [ ] Anel de foco tem **≥3:1** contra o fundo (1.4.11)?
198
+
199
+ **Formulários**
200
+ - [ ] Todo input tem `<label>` associado (não só placeholder)?
201
+ - [ ] Dica e erro ligados via `aria-describedby`; erro também é **texto**, não só cor (1.4.1)?
202
+ - [ ] Campo em erro tem `aria-invalid="true"` e a mensagem usa `role="alert"`?
203
+ - [ ] Grupos em `<fieldset>`/`<legend>`; `autocomplete` correto (3.3.7)?
204
+
205
+ **Imagens e SVG**
206
+ - [ ] Toda `<img>` informativa tem `alt` que descreve o **propósito**?
207
+ - [ ] Imagens decorativas têm `alt=""` (presente e vazio)?
208
+ - [ ] SVG decorativo: `aria-hidden="true"`; SVG significativo: `role="img"` + `aria-label`?
209
+ - [ ] Botão/link só de ícone tem `aria-label` no **controle** (4.1.2)?
210
+
211
+ **Contraste (medido, não no olho)**
212
+ - [ ] Texto normal **≥4.5:1**; texto grande (≥18pt / ≥14pt bold) **≥3:1** (1.4.3)?
213
+ - [ ] Bordas de input, ícones de UI e indicador de foco **≥3:1** (1.4.11)?
214
+ - [ ] Texto sobre imagem/gradiente medido no ponto de pior contraste?
215
+ - [ ] `::selection` customizado ainda tem contraste suficiente?
216
+ - [ ] Nenhuma informação transmitida **só por cor** (1.4.1)?
217
+
218
+ **Movimento e toque**
219
+ - [ ] `prefers-reduced-motion: reduce` desliga/instantaneíza animações?
220
+ - [ ] Nenhum flash >3×/s (2.3.1, bloqueante)?
221
+ - [ ] Alvos de ponteiro **≥24×24 CSS px** ou com spacing equivalente (2.5.8)?
222
+ - [ ] Ação de drag tem alternativa de clique único (2.5.7)?
223
+
224
+ **Protocolo de teste (as 3 camadas)**
225
+ - [ ] axe-core rodado e zerado (piso, ~30–57%)?
226
+ - [ ] Página percorrida **só com teclado**?
227
+ - [ ] Página ouvida em **leitor de tela** (NVDA/VoiceOver), estrutura e nomes conferidos?
228
+
229
+ ## Tabela de decisão
230
+
231
+ | Sintoma observado | Critério WCAG | Veredito | Correção |
232
+ |---|---|---|---|
233
+ | `outline: none` sem reposição | 2.4.7 AA | **FAIL** | `:focus-visible { outline: 2px solid }` |
234
+ | Texto cinza `#999` sobre branco (2.85:1) | 1.4.3 AA | **FAIL** | Escurecer até **≥4.5:1** |
235
+ | Borda de input quase invisível (1.8:1) | 1.4.11 AA | **FAIL** | Borda **≥3:1** contra o fundo |
236
+ | Header sticky cobre 100% o item focado | 2.4.11 AA | **FAIL** | `scroll-padding-top` = altura do header |
237
+ | Botão de ícone sem texto nem `aria-label` | 4.1.2 A | **FAIL** | `aria-label` no botão; SVG `aria-hidden` |
238
+ | Placeholder no lugar de `<label>` | 1.3.1 / 4.1.2 | **FAIL** | `<label for>` real associado |
239
+ | Erro de form só em vermelho, sem texto | 1.4.1 AA | **FAIL** | Mensagem em texto + `role="alert"` |
240
+ | Pulo de heading `h2 → h4` | 1.3.1 A | **FAIL** | Hierarquia sequencial sem pulo |
241
+ | Dois `<main>` na página | 1.3.1 A | **FAIL** | Apenas um `<main>` |
242
+ | Alvo de toque 18×18 px, sem spacing | 2.5.8 AA | **FAIL** | Aumentar para **≥24×24** ou afastar |
243
+ | Carrossel auto-play ignora reduced-motion | 2.3.3 AAA / boa prática | **CONCERNS** | Honrar `prefers-reduced-motion` |
244
+ | Animação pisca 4×/s | 2.3.1 A | **FAIL (bloqueante)** | Remover/reduzir para <3×/s |
245
+ | axe limpo, mas nunca testado por teclado/leitor | — | **CONCERNS** | Rodar as 3 camadas antes de aprovar |
246
+ | Drag-and-drop sem alternativa de clique | 2.5.7 AA | **FAIL** | Adicionar ação de clique equivalente |
247
+ | Imagem decorativa com `alt="imagem decorativa"` | 1.1.1 A | **CONCERNS** | Trocar por `alt=""` |
248
+
249
+ ---
250
+
251
+ **Fontes:** [WCAG 2.2 (W3C/TR)](https://www.w3.org/TR/WCAG22/) · [What's New in WCAG 2.2](https://www.w3.org/WAI/standards-guidelines/wcag/new-in-22/) · [SC 1.4.3 Contrast Minimum](https://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum.html) · [SC 1.4.11 Non-text Contrast](https://www.w3.org/WAI/WCAG22/Understanding/non-text-contrast.html) · [SC 2.4.11 Focus Not Obscured](https://www.w3.org/WAI/WCAG22/Understanding/focus-not-obscured-minimum) · [F110](https://www.w3.org/WAI/WCAG22/Techniques/failures/F110.html) · [SC 2.5.8 Target Size](https://www.w3.org/WAI/WCAG22/Understanding/target-size-minimum.html) · [The A11Y Project Checklist](https://www.a11yproject.com/checklist/) · [Accessible SVG Icons — CSS-Tricks](https://css-tricks.com/accessible-svg-icons/) · [axe-core (Deque)](https://github.com/dequelabs/axe-core)