agent-engineering-skills 1.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.
- package/AGENTS.md +249 -0
- package/LICENSE +21 -0
- package/README.md +113 -0
- package/bin/cli.js +223 -0
- package/docs/agent-integration.md +200 -0
- package/docs/philosophy.md +131 -0
- package/docs/reference-authoring.md +117 -0
- package/docs/skill-authoring.md +126 -0
- package/examples/authorization-bypass.md +191 -0
- package/examples/frontend-review.md +244 -0
- package/examples/race-condition.md +128 -0
- package/examples/xp-reward-loop.md +123 -0
- package/package.json +45 -0
- package/references/engineering.yaml +88 -0
- package/references/frontend.yaml +139 -0
- package/references/product.yaml +54 -0
- package/references/research.yaml +88 -0
- package/references/security.yaml +85 -0
- package/references/ux.yaml +37 -0
- package/scripts/validate.py +454 -0
- package/skills/audit/adversarial-review/SKILL.md +190 -0
- package/skills/audit/business-logic-audit/SKILL.md +182 -0
- package/skills/audit/edge-case-hunter/SKILL.md +159 -0
- package/skills/audit/error-flow-audit/SKILL.md +184 -0
- package/skills/audit/state-consistency-audit/SKILL.md +174 -0
- package/skills/audit/user-flow-audit/SKILL.md +161 -0
- package/skills/frontend/accessibility-review/SKILL.md +186 -0
- package/skills/frontend/animation-review/SKILL.md +171 -0
- package/skills/frontend/interaction-design/SKILL.md +162 -0
- package/skills/frontend/ux-review/SKILL.md +172 -0
- package/skills/frontend/visual-quality-review/SKILL.md +160 -0
- package/skills/meta/research-router/SKILL.md +184 -0
- package/skills/meta/skill-router/SKILL.md +206 -0
- package/skills/product/gamification-audit/SKILL.md +213 -0
- package/skills/reliability/data-integrity-audit/SKILL.md +187 -0
- package/skills/reliability/idempotency-audit/SKILL.md +191 -0
- package/skills/reliability/race-condition-hunter/SKILL.md +181 -0
- package/skills/research/github-reference-research/SKILL.md +197 -0
- package/skills/research/implementation-research/SKILL.md +181 -0
- package/skills/research/market-research/SKILL.md +202 -0
- package/skills/research/reference-research/SKILL.md +186 -0
- package/skills/security/api-abuse-audit/SKILL.md +178 -0
- package/skills/security/authorization-audit/SKILL.md +176 -0
- package/skills/security/input-trust-audit/SKILL.md +178 -0
- package/templates/audit-report.md +89 -0
- package/templates/bug-report.md +107 -0
- package/templates/design-review.md +122 -0
- package/templates/research-report.md +96 -0
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: business-logic-audit
|
|
3
|
+
description: Identifies business rules, invariants, limits, ownership, transitions, and rewards and for each asks where it is enforced, whether it can be bypassed, repeated, reversed, or raced.
|
|
4
|
+
category: audit
|
|
5
|
+
triggers:
|
|
6
|
+
- "audit business rules"
|
|
7
|
+
- "review invariants and limits"
|
|
8
|
+
- "check ownership and permissions logic"
|
|
9
|
+
- "audit a reward or scoring system"
|
|
10
|
+
- "verify rule enforcement server-side"
|
|
11
|
+
priority: high
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Business Logic Audit
|
|
15
|
+
|
|
16
|
+
## Objective
|
|
17
|
+
|
|
18
|
+
Ensinar o agente a extrair as **regras de negócio** implícitas em um sistema e, para
|
|
19
|
+
cada uma, aplicar um protocolo de cinco perguntas que expõe onde a regra é frágil:
|
|
20
|
+
|
|
21
|
+
```text
|
|
22
|
+
Where is it enforced?
|
|
23
|
+
Can it be bypassed?
|
|
24
|
+
Can it be repeated?
|
|
25
|
+
Can it be reversed?
|
|
26
|
+
Can it race?
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
A diferença entre "o código faz X" e "o negócio exige X e o código garante X" é onde
|
|
30
|
+
moram os bugs de lógica.
|
|
31
|
+
|
|
32
|
+
## When to Use
|
|
33
|
+
|
|
34
|
+
* Quando o sistema tem regras: limites, cotas, ownership, permissões, transições de
|
|
35
|
+
estado, economia interna (XP, pontos, moedas, estoque).
|
|
36
|
+
* Antes de lançar features que envolvem valor transferível ou contável.
|
|
37
|
+
* Quando o pedido menciona "rules", "limits", "quotas", "ownership", "rewards",
|
|
38
|
+
"permissions", "state transitions".
|
|
39
|
+
* **Composição:** núcleo de quase toda auditoria de lógica. Pareia com
|
|
40
|
+
`gamification-audit` (regras de recompensa), `idempotency-audit` (repetições de
|
|
41
|
+
regra), `race-condition-hunter` (regras que dependem de read-then-write),
|
|
42
|
+
`authorization-audit` (ownership = autorização), `data-integrity-audit` (regras que
|
|
43
|
+
o banco deve impor), `input-trust-audit` (valores de regra confiados ao cliente).
|
|
44
|
+
|
|
45
|
+
## Mental Model
|
|
46
|
+
|
|
47
|
+
Toda regra de negócio é, no fundo, um **invariant** — uma asserção que deve ser sempre
|
|
48
|
+
verdadeira. "Um usuário não pode dar XP a si mesmo." "O saldo nunca fica negativo."
|
|
49
|
+
"Um item deletado não pode ser editado." "Limite de 5 por dia."
|
|
50
|
+
|
|
51
|
+
O bug de lógica acontece quando o sistema *acredita* no invariant sem *garanti-lo*. O
|
|
52
|
+
modelo é:
|
|
53
|
+
|
|
54
|
+
```text
|
|
55
|
+
regra (invariant) → onde é enforcement? → bypass? repeat? reverse? race?
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Se o enforcement está só no frontend, ou só em uma camada, ou em read-then-write sem
|
|
59
|
+
lock, o invariant é uma *crença*, não uma *garantia*. A skill transforma crenças em
|
|
60
|
+
perguntas e perguntas em evidência.
|
|
61
|
+
|
|
62
|
+
Classes de regra a procurar:
|
|
63
|
+
|
|
64
|
+
```text
|
|
65
|
+
rules — o que deve/não deve acontecer
|
|
66
|
+
invariants — o que deve ser sempre verdadeiro
|
|
67
|
+
limits — cotas, máximos, mínimos, por-tempo
|
|
68
|
+
ownership — de quem é o recurso; quem pode agir
|
|
69
|
+
transitions — estados permitidos e proibidos
|
|
70
|
+
rewards — o que concede valor e sob quais condições
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Investigation Procedure
|
|
74
|
+
|
|
75
|
+
1. **Inventariar regras.** Leia o fluxo e liste todas as regras implícitas. Para cada,
|
|
76
|
+
rotule a classe (rule/invariant/limit/ownership/transition/reward).
|
|
77
|
+
2. **Para cada regra, responder às 5 perguntas:**
|
|
78
|
+
* **Where is it enforced?** — frontend? API? server handler? DB constraint? nenhuma?
|
|
79
|
+
* **Can it be bypassed?** — existe um caminho alternativo (outro endpoint, campo
|
|
80
|
+
extra, manipulação de ID) que contorna o enforcement?
|
|
81
|
+
* **Can it be repeated?** — executar a ação N vezes viola a regra? (limite diário
|
|
82
|
+
resetável por retry? reward por repetição?)
|
|
83
|
+
* **Can it be reversed?** — desfazer + refazer viola a regra? (reward concedida de
|
|
84
|
+
novo ao refazer?)
|
|
85
|
+
* **Can it race?** — a regra depende de ler estado e depois escrever? Dois requests
|
|
86
|
+
concorrentes passam pela checagem?
|
|
87
|
+
3. **Triar por severidade** — regras sobre valor transferível (dinheiro, XP, estoque)
|
|
88
|
+
e ownership são mais graves que regras cosméticas.
|
|
89
|
+
4. **Confirmar com evidência** — para cada "yes" nas perguntas, reproduzir ou apontar o
|
|
90
|
+
mecanismo no código.
|
|
91
|
+
5. **Reportar** via `templates/audit-report.md`.
|
|
92
|
+
|
|
93
|
+
## Questions to Ask
|
|
94
|
+
|
|
95
|
+
* Quais são todas as regras de negócio deste fluxo? (liste explicitamente)
|
|
96
|
+
* Para cada regra: onde exatamente ela é enforcement? É a única camada?
|
|
97
|
+
* A regra confia em algum valor enviado pelo cliente (price, role, xp, ownerId)?
|
|
98
|
+
* Se eu repetir a ação, a regra ainda vale? Ou o contador/limite é inconsistente?
|
|
99
|
+
* Se eu desfazer e refazer, o efeito é concedido duas vezes?
|
|
100
|
+
* A checagem lê estado e depois escreve baseada no que leu? Há janela de race?
|
|
101
|
+
* A regra é imposta por constraint do banco (unique, FK, check)? Ou só em código?
|
|
102
|
+
* Quem é o owner do recurso? A checagem de ownership é no servidor?
|
|
103
|
+
* Existem transições de estado que deveriam ser proibidas mas não são validadas?
|
|
104
|
+
|
|
105
|
+
## Attack Patterns
|
|
106
|
+
|
|
107
|
+
```text
|
|
108
|
+
bypass — alternative endpoint
|
|
109
|
+
fluxo oficial: POST /reward {reactionId} (valida regra "não self-reward")
|
|
110
|
+
endpoint direto: POST /admin/grant {userId, xp} (valida? ou é interno confiável?)
|
|
111
|
+
|
|
112
|
+
bypass — extra field / mass assignment
|
|
113
|
+
POST /update {name: "x"}
|
|
114
|
+
POST /update {name: "x", role: "admin"} (campo extra aceito → regra de role violada)
|
|
115
|
+
|
|
116
|
+
repeat — daily limit reset
|
|
117
|
+
POST /claim → +1 (contador "hoje": 1/5)
|
|
118
|
+
retry rápido → o contador é por-calendário ou por-janela? manipular timestamp?
|
|
119
|
+
|
|
120
|
+
reverse — reward refund + regrant
|
|
121
|
+
react → +10 XP
|
|
122
|
+
unreact → -10 XP (ou não?)
|
|
123
|
+
react → +10 XP
|
|
124
|
+
→ se unreact não removeu XP, refazer = farming
|
|
125
|
+
|
|
126
|
+
race — check-then-act on a limit
|
|
127
|
+
request A: read "hoje: 4/5" → ok
|
|
128
|
+
request B: read "hoje: 4/5" → ok (mesma leitura)
|
|
129
|
+
request A: write "hoje: 5/5" + reward
|
|
130
|
+
request B: write "hoje: 5/5" + reward → 6/5, regra do limite violada
|
|
131
|
+
|
|
132
|
+
transition — illegal state reachable
|
|
133
|
+
DELETE /item → state: "deleted"
|
|
134
|
+
PUT /item {state: "active"} → permitido? transição proibida não checada?
|
|
135
|
+
|
|
136
|
+
ownership — authenticated ≠ authorized
|
|
137
|
+
GET /order/123 → 200 (é meu? ou só preciso estar logado?)
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Evidence Requirements
|
|
141
|
+
|
|
142
|
+
* **Nomear a regra e sua classe** (ex: "invariant: saldo não negativo").
|
|
143
|
+
* **Responder as 5 perguntas explicitamente** no finding — onde enforced, bypass,
|
|
144
|
+
repeat, reverse, race — mesmo que a resposta seja "não". Isto mostra que o protocolo
|
|
145
|
+
foi aplicado.
|
|
146
|
+
* **Mostrar o mecanismo da violação** — o endpoint/campo/sequência que contorna, ou o
|
|
147
|
+
read-then-write que abre race.
|
|
148
|
+
* **Escalar confiança:**
|
|
149
|
+
* `CONFIRMED` — reproduziu a violação da regra (ex: claim além do limite, reward
|
|
150
|
+
dupla).
|
|
151
|
+
* `HIGH CONFIDENCE` — código mostra enforcement faltando em um caminho claro.
|
|
152
|
+
* `POSSIBLE` — regra parece não enforced em um caminho plausível, não confirmado.
|
|
153
|
+
* `SPECULATIVE` — "deveria haver uma regra aqui" sem evidência de violação.
|
|
154
|
+
|
|
155
|
+
## False Positives
|
|
156
|
+
|
|
157
|
+
* **Enforcement em múltiplas camadas** — se a regra é checada no handler E no banco
|
|
158
|
+
(constraint), um bypass aparente no handler é defendido pelo banco. Confirmar ambas
|
|
159
|
+
antes de reportar.
|
|
160
|
+
* **Regra é de UI, não de negócio** — "campo obrigatório no form" pode ser só UX; se o
|
|
161
|
+
backend aceita vazio legitimamente, não é bug de lógica.
|
|
162
|
+
* **Limite é soft por design** — alguns limites são orientativos, não duros. Verificar
|
|
163
|
+
a intenção de produto antes de reportar como defeito (marcar `POSSIBLE`).
|
|
164
|
+
* **Self-reward prevenido por design diferente** — talvez o sistema permita "self-XP"
|
|
165
|
+
em um contexto (admin) e proíba em outro. Não reportar bypass sem entender o modelo
|
|
166
|
+
de papéis.
|
|
167
|
+
* **Regra não existe** — se você *assume* uma regra que o produto não definiu, qualquer
|
|
168
|
+
"violação" é falso positivo. Liste a regra como hipótese e marque `SPECULATIVE` se
|
|
169
|
+
não há evidência de que ela deveria existir.
|
|
170
|
+
|
|
171
|
+
## Output Format
|
|
172
|
+
|
|
173
|
+
Para cada regra com um "yes" em qualquer uma das 5 perguntas, um finding via
|
|
174
|
+
`templates/audit-report.md`. Em **Affected flow**, nomeie a regra violada. Em
|
|
175
|
+
**Reproduction**, mostre o caminho do bypass/repeat/reverse/race. Em **Root cause**,
|
|
176
|
+
diga *onde* o enforcement falta (camada, endpoint, ausência de constraint). Em
|
|
177
|
+
**Recommendation**, indique a camada que deve garantir o invariant (idealmente o banco,
|
|
178
|
+
ou lock/transaction no servidor).
|
|
179
|
+
|
|
180
|
+
Apresente o inventário de regras como tabela (regra | classe | onde enforced |
|
|
181
|
+
bypass? | repeat? | reverse? | race?), marcando as vulnerabilidades. Regras sobre valor
|
|
182
|
+
transferível e ownership primeiro.
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: edge-case-hunter
|
|
3
|
+
description: Generates edge cases around null, empty, zero, negative, huge values, duplicates, Unicode, stale data, deleted data, expired data, and repeated valid actions, then checks whether the system handles each.
|
|
4
|
+
category: audit
|
|
5
|
+
triggers:
|
|
6
|
+
- "find edge cases"
|
|
7
|
+
- "test boundary values"
|
|
8
|
+
- "what about null empty zero negative huge"
|
|
9
|
+
- "stress inputs with edge values"
|
|
10
|
+
- "unicode and duplicate handling"
|
|
11
|
+
priority: high
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Edge Case Hunter
|
|
15
|
+
|
|
16
|
+
## Objective
|
|
17
|
+
|
|
18
|
+
Ensinar o agente a **gerar sistematicamente** casos de fronteira e verificar se o
|
|
19
|
+
sistema trata cada um. Ao contrário de skills que atacam lógica ou fluxo, esta ataca
|
|
20
|
+
**valores** — as entradas nos limites onde suposições sobre formato, magnitude e
|
|
21
|
+
conteúdo quebram.
|
|
22
|
+
|
|
23
|
+
## When to Use
|
|
24
|
+
|
|
25
|
+
* Ao auditar qualquer função/campo que recebe input (formulários, APIs, imports,
|
|
26
|
+
parseadores, cálculos).
|
|
27
|
+
* Antes de confiar em um cálculo (saldo, XP, preço, contador, posição, índice).
|
|
28
|
+
* Quando o pedido menciona "edge cases", "boundary", "what about X values", "stress
|
|
29
|
+
inputs".
|
|
30
|
+
* **Composição:** complementar, não substitutiva. Rode junto com
|
|
31
|
+
`input-trust-audit` (esses valores viriam do cliente?), `business-logic-audit`
|
|
32
|
+
(limites que são regras), `error-flow-audit` (o que acontece quando o edge case
|
|
33
|
+
quebra), `data-integrity-audit` (o banco aceita esses valores?).
|
|
34
|
+
|
|
35
|
+
## Mental Model
|
|
36
|
+
|
|
37
|
+
A maioria do código é testada no happy path com valores "redondos" (1, 10, "hello").
|
|
38
|
+
Bugs vivem nas **fronteiras** — onde o input deixa de ser "normal" e expõe uma suposição
|
|
39
|
+
não escrita: "não será nulo", "não será vazio", "será positivo", "cabe em um int",
|
|
40
|
+
"é ASCII", "é único", "ainda existe".
|
|
41
|
+
|
|
42
|
+
A skill usa uma lista canônica de eixos de fronteira e, para cada campo/entrada
|
|
43
|
+
relevante, pergunta "o que acontece se este valor for `<eixo>`?". É exaustivo por
|
|
44
|
+
intenção, mas **triado por relevância**: nem todo eixo aplica a todo campo.
|
|
45
|
+
|
|
46
|
+
Eixos canônicos (do `plan.md` §6):
|
|
47
|
+
|
|
48
|
+
```text
|
|
49
|
+
null empty zero negative
|
|
50
|
+
huge values duplicates Unicode stale data
|
|
51
|
+
deleted data expired data repeated valid actions
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Investigation Procedure
|
|
55
|
+
|
|
56
|
+
1. **Listar entradas.** Identifique todos os campos/parâmetros/entradas que o
|
|
57
|
+
componente recebe (do cliente, de outra camada, de um job, de um import).
|
|
58
|
+
2. **Para cada entrada, mapear o tipo e as suposições** — número? string? referência a
|
|
59
|
+
entidade? data? Enumerar o que o código assume sobre ele.
|
|
60
|
+
3. **Gerar casos por eixo.** Para cada entrada × eixo aplicável, formule o caso.
|
|
61
|
+
Ex: `balance` × `negative` → "saldo -50"; `name` × `Unicode` → "nome com
|
|
62
|
+
zero-width/emoji/RTR"; `parentId` × `deleted data` → "referencia entidade deletada".
|
|
63
|
+
4. **Executar/verificar cada caso.** O que o sistema faz? Erro limpo? Silent fail?
|
|
64
|
+
Estado corrompido? Crash? Comportamento errado sem erro?
|
|
65
|
+
5. **Triar.** Descarte casos onde o eixo não aplica (ex: `negative` em um enum).
|
|
66
|
+
Priorize casos que corrompem estado ou causam comportamento errado silencioso.
|
|
67
|
+
6. **Confirmar com evidência** — reproduza o input e observe a saída/estado.
|
|
68
|
+
7. **Reportar** via `templates/audit-report.md`.
|
|
69
|
+
|
|
70
|
+
## Questions to Ask
|
|
71
|
+
|
|
72
|
+
* O que acontece se este campo for `null`? E vazio (`""`)? E só whitespace?
|
|
73
|
+
* E se for `0`? E `-1` / negativo?
|
|
74
|
+
* E se for enorme (overflow de int, string de 1MB, array de 10⁶ itens)?
|
|
75
|
+
* E se houver duplicata (dois iguais onde deveria ser único)?
|
|
76
|
+
* E se tiver Unicode exótico (zero-width joiner, RTL, emoji, combinando)?
|
|
77
|
+
* E se o dado referenciado foi deletado? (FK pendente, soft-deleted mas ainda usado)
|
|
78
|
+
* E se o dado está expirado? (token, sessão, oferta, cupom)
|
|
79
|
+
* E se for stale (cache desatualizado vs fonte)?
|
|
80
|
+
* E se a mesma ação válida for repetida N vezes? (limite, contador, reward)
|
|
81
|
+
* O erro (quando ocorre) é limpo e tratado, ou vaza crash/stack trace?
|
|
82
|
+
|
|
83
|
+
## Attack Patterns
|
|
84
|
+
|
|
85
|
+
```text
|
|
86
|
+
null
|
|
87
|
+
field: null → NullPointerException? 500? ou tratado como default?
|
|
88
|
+
|
|
89
|
+
empty
|
|
90
|
+
name: "" → validado? ou aceito e quebra display/sort?
|
|
91
|
+
|
|
92
|
+
zero
|
|
93
|
+
quantity: 0 → cálculo de total = 0 ok? ou divisão por zero downstream?
|
|
94
|
+
price: 0 → checkout grátis "válido"?
|
|
95
|
+
|
|
96
|
+
negative
|
|
97
|
+
amount: -50 → transfere -50 (inverte fluxo)? saldo fica negativo?
|
|
98
|
+
|
|
99
|
+
huge
|
|
100
|
+
count: 2147483648 → overflow int? loop eterno? OOM?
|
|
101
|
+
file: 10GB → limite de upload?
|
|
102
|
+
|
|
103
|
+
duplicate
|
|
104
|
+
POST /create {slug:"x"} twice → 409? ou cria dois?
|
|
105
|
+
|
|
106
|
+
Unicode
|
|
107
|
+
name: "ab" → zero-width; igual a "ab"? duplicata invisível?
|
|
108
|
+
name: "" → RTL override; rendering invertido
|
|
109
|
+
|
|
110
|
+
deleted data
|
|
111
|
+
POST /comment {postId: <deleted>} → cria comentário órfão?
|
|
112
|
+
|
|
113
|
+
expired data
|
|
114
|
+
redeem code expired → ainda resgata? ou checa expiração?
|
|
115
|
+
|
|
116
|
+
stale data
|
|
117
|
+
cache: balance=100, db: balance=50 → usa cache e permite gastar 100?
|
|
118
|
+
|
|
119
|
+
repeated valid action
|
|
120
|
+
claim reward 5× → limite por-janela respeitado? ou farming?
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Evidence Requirements
|
|
124
|
+
|
|
125
|
+
* **Nomear o eixo e o campo** testados.
|
|
126
|
+
* **Mostrar o input exato** usado (valor literal, não "um valor grande").
|
|
127
|
+
* **Mostrar a saída/estado resultante** — não só "quebra", mas *como* (erro 500,
|
|
128
|
+
silent success com estado errado, crash, comportamento correto).
|
|
129
|
+
* **Escalar confiança:**
|
|
130
|
+
* `CONFIRMED` — reproduziu com o input literal e observou o resultado.
|
|
131
|
+
* `HIGH CONFIDENCE` — código mostra caminho que não trata o eixo, sem reprodução.
|
|
132
|
+
* `POSSIBLE` — eixo plausível, caminho não confirmado.
|
|
133
|
+
* `SPECULATIVE` — "pode quebrar com X" sem rastrear.
|
|
134
|
+
* Priorize `silent success com estado errado` — é pior que crash, porque não alerta.
|
|
135
|
+
|
|
136
|
+
## False Positives
|
|
137
|
+
|
|
138
|
+
* **Validação de tipo no boundary do framework** — se o ORM/schema rejeita null/empty
|
|
139
|
+
antes do handler, o caso é tratado. Confirmar antes de reportar.
|
|
140
|
+
* **Default intencional** — alguns campos legitimamente defaultam null/0 e o código
|
|
141
|
+
trata downstream. Não reportar "aceita null" se o nulo é intencional e tratado.
|
|
142
|
+
* **Unicode normalizado por design** — se o sistema normaliza (NFC) e colapsa
|
|
143
|
+
zero-width de propósito, "duplicata invisível" é tratada, não bug.
|
|
144
|
+
* **Soft delete intencional** — referenciar entidade "deletada" (soft) pode ser
|
|
145
|
+
desejado (histórico). Verificar se é hard ou soft delete antes de reportar.
|
|
146
|
+
* **Limite enorme não é defeito** — se o sistema *deve* aceitar arquivos grandes,
|
|
147
|
+
"aceita 10GB" não é bug; "não limita e dá OOM" seria.
|
|
148
|
+
* **Caso não aplica** — `negative` em um boolean/enum não aplica; não force.
|
|
149
|
+
|
|
150
|
+
## Output Format
|
|
151
|
+
|
|
152
|
+
Para cada caso que produz comportamento errado (não só erro), um finding via
|
|
153
|
+
`templates/audit-report.md`. Em **Reproduction**, dê o input literal e o comando
|
|
154
|
+
request. Em **Actual behavior**, descreva exatamente o resultado observado. Em
|
|
155
|
+
**Recommendation**, indique validação (onde: schema vs handler vs sanitização).
|
|
156
|
+
|
|
157
|
+
Apresente a matriz de cobertura como tabela (entrada × eixos aplicáveis, marcando
|
|
158
|
+
✓ tratado / ✗ falha / — não aplica). Isto documenta quais eixos foram testados e
|
|
159
|
+
previne retrabalho. Silenciosos (estado errado sem erro) primeiro; crashes depois.
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: error-flow-audit
|
|
3
|
+
description: Investigates partial success, timeouts, lost responses, retries, crashes, and rollback failures to find states left inconsistent or operations left half-done when something fails mid-flight.
|
|
4
|
+
category: audit
|
|
5
|
+
triggers:
|
|
6
|
+
- "audit error handling"
|
|
7
|
+
- "what happens on failure mid-flow"
|
|
8
|
+
- "partial success and rollback"
|
|
9
|
+
- "retry and timeout behavior"
|
|
10
|
+
- "crash recovery and lost responses"
|
|
11
|
+
priority: high
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Error Flow Audit
|
|
15
|
+
|
|
16
|
+
## Objective
|
|
17
|
+
|
|
18
|
+
Ensinar o agente a parar de perguntar "isto funciona?" e perguntar **"o que acontece
|
|
19
|
+
quando isto falha no meio?"**. Toda operação multi-passo pode falhar entre os passos;
|
|
20
|
+
esta skill mapeia os pontos de falha e verifica se o sistema deixa o estado consistente
|
|
21
|
+
ou abandona o sistema em um estado parcial.
|
|
22
|
+
|
|
23
|
+
```text
|
|
24
|
+
partial success timeouts lost responses retries crashes rollback failures
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## When to Use
|
|
28
|
+
|
|
29
|
+
* Quando uma operação toca múltiplos recursos/serviços (DB + API externa + fila +
|
|
30
|
+
cache) e pode falhar entre eles.
|
|
31
|
+
* Quando há retries, timeouts, circuit breakers, ou webhooks.
|
|
32
|
+
* Quando uma falha pode deixar estado parcial (recurso criado mas notificação não
|
|
33
|
+
enviada; cobrança efetivada mas pedido não; metadados escritos mas arquivo não).
|
|
34
|
+
* Quando o pedido menciona "error handling", "rollback", "retry", "timeout", "what if
|
|
35
|
+
it fails", "partial", "idempotent on retry".
|
|
36
|
+
* **Composição:** pareia com `idempotency-audit` (retry de operação inteira),
|
|
37
|
+
`data-integrity-audit` (transação/rollback no banco), `state-consistency-audit`
|
|
38
|
+
(estado parcial = desync entre camadas), `user-flow-audit` (fluxo que falha num
|
|
39
|
+
passo intermediário), `race-condition-hunter` (falha concorrente com outra mutação).
|
|
40
|
+
|
|
41
|
+
## Mental Model
|
|
42
|
+
|
|
43
|
+
O happy path é fácil. O perigo é o **caminho parcial**: a operação completa passo 1,
|
|
44
|
+
falha no passo 2, e agora o sistema tem o efeito do passo 1 sem o do passo 2 — um estado
|
|
45
|
+
que o happy path nunca produziria e que ninguém projetou para existir.
|
|
46
|
+
|
|
47
|
+
As duas armadilhas simétricas:
|
|
48
|
+
|
|
49
|
+
1. **Sem rollback** — passo 1 efetivado, passo 2 falha, passo 1 não é desfeito. Estado
|
|
50
|
+
parcial persiste.
|
|
51
|
+
2. **Rollback sem idempotência** — retry reexecuta passo 1 (já feito) e cria efeito
|
|
52
|
+
duplicado. Ou rollback desfaz e reexecuta do zero, mas o "efeito externo" (email,
|
|
53
|
+
cobrança) já ocorreu e não é reversível.
|
|
54
|
+
|
|
55
|
+
O modelo: para cada operação multi-passo, pergunte *qual passo é idempotente*, *qual
|
|
56
|
+
é reversível*, *qual tem efeito externo irreversível*, e *o que acontece se falhar
|
|
57
|
+
após cada um*. Pontos de não-retorno (efeito externo já disparado) são os mais críticos.
|
|
58
|
+
|
|
59
|
+
Classes de falha a investigar (do `plan.md` §6):
|
|
60
|
+
|
|
61
|
+
```text
|
|
62
|
+
partial success — alguns passos efetivam, outros não
|
|
63
|
+
timeouts — chamada pendente; estado desconhecido (fez ou não fez?)
|
|
64
|
+
lost responses — servidor agiu mas o cliente não sabe; retry?
|
|
65
|
+
retries — reexecução; idempotente? ou duplica efeito?
|
|
66
|
+
crashes — processo morre mid-op; estado em disco consistente?
|
|
67
|
+
rollback failures — tentou desfazer e o rollback também falhou; agora o quê?
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Investigation Procedure
|
|
71
|
+
|
|
72
|
+
1. **Decompor a operação em passos.** Liste cada efeito (write DB, call API externa,
|
|
73
|
+
enqueue, send email, update cache, emit event).
|
|
74
|
+
2. **Rotular cada passo:** idempotente? reversível? efeito externo (irreversível)?
|
|
75
|
+
3. **Para cada ponto de falha (após passo k), perguntar:**
|
|
76
|
+
* O estado parcial é consistente ou corrompido?
|
|
77
|
+
* Há rollback? O rollback cobre todos os passos k?
|
|
78
|
+
* O rollback é idempotente (safe to retry)?
|
|
79
|
+
* Há efeito externo irreversível já disparado antes do ponto de falha?
|
|
80
|
+
4. **Testar timeout/lost-response:** se a chamada pendente, o sistema trata como
|
|
81
|
+
"feito", "não feito", ou "desconhecido"? O retry é seguro?
|
|
82
|
+
5. **Testar retry:** reexecutar a operação inteira após falha — duplica algum efeito?
|
|
83
|
+
6. **Testar crash mid-op:** se o processo morre entre passos, o estado em disco é
|
|
84
|
+
consistente ao reiniciar? Há recuperação/reconciliação?
|
|
85
|
+
7. **Testar rollback failure:** se o rollback também falha, o sistema fica em quê?
|
|
86
|
+
Há alerta/reconciliação, ou silencioso?
|
|
87
|
+
8. **Confirmar com evidência** — injete falha no passo k e observe o estado final.
|
|
88
|
+
9. **Reportar** via `templates/audit-report.md`.
|
|
89
|
+
|
|
90
|
+
## Questions to Ask
|
|
91
|
+
|
|
92
|
+
* Quais são os passos/efeitos desta operação? Qual ordem?
|
|
93
|
+
* Qual passo é o ponto de não-retorno (efeito externo irreversível)?
|
|
94
|
+
* Se falhar *após* o ponto de não-retorno, o que acontece?
|
|
95
|
+
* Há transação? Ela cobre todos os writes ou só alguns?
|
|
96
|
+
* Para chamada externa: timeout → estado desconhecido. Como o sistema resolve?
|
|
97
|
+
* Retry da operação inteira é idempotente? Ou duplica um efeito?
|
|
98
|
+
* Se o processo crashar entre passos, há reconciliação ao reiniciar?
|
|
99
|
+
* O rollback, se existe, é idempotente? E se o rollback falhar?
|
|
100
|
+
* Erros são tratados ou engolidos (empty catch)? Estado parcial é detectável?
|
|
101
|
+
|
|
102
|
+
## Attack Patterns
|
|
103
|
+
|
|
104
|
+
```text
|
|
105
|
+
partial success — no transaction
|
|
106
|
+
step 1: write db order "created" ✓ committed
|
|
107
|
+
step 2: charge payment ✗ fails
|
|
108
|
+
→ order exists, never paid, no rollback. Estado parcial.
|
|
109
|
+
|
|
110
|
+
partial success — external effect before commit
|
|
111
|
+
step 1: call payment gateway ✓ charged (irreversível)
|
|
112
|
+
step 2: write db order "paid" ✗ db error
|
|
113
|
+
→ cobrado, pedido não registrado. Ponto de não-retorno passado.
|
|
114
|
+
|
|
115
|
+
timeout → unknown state
|
|
116
|
+
call external API: 30s, no response
|
|
117
|
+
→ agiu ou não? retry agora duplica se agiu (não-idempotente).
|
|
118
|
+
|
|
119
|
+
lost response → blind retry
|
|
120
|
+
server processes request, response lost in network
|
|
121
|
+
client retries → reexecuta → efeito duplicado se não-idempotente.
|
|
122
|
+
|
|
123
|
+
retry that doubles
|
|
124
|
+
create + send welcome email
|
|
125
|
+
fails after create, before email
|
|
126
|
+
retry → create again (duplica) se create não-idempotente.
|
|
127
|
+
|
|
128
|
+
crash mid-op, no recovery
|
|
129
|
+
step 1: decrement stock
|
|
130
|
+
crash
|
|
131
|
+
restart → stock decremented, order never created. Sem reconciliação.
|
|
132
|
+
|
|
133
|
+
rollback failure, silent
|
|
134
|
+
try: step1, step2
|
|
135
|
+
catch: undo step1 ← undo also fails
|
|
136
|
+
→ step1 efetivado, sem log/alerta. Corrupção silenciosa.
|
|
137
|
+
|
|
138
|
+
empty catch / swallowed error
|
|
139
|
+
try { externalCall() } catch {}
|
|
140
|
+
→ falha virou sucesso aparente; estado parcial não detectado.
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Evidence Requirements
|
|
144
|
+
|
|
145
|
+
* **Nomear o ponto de falha** (após qual passo) e o **estado parcial resultante**.
|
|
146
|
+
* **Rotular cada passo** (idempotente / reversível / efeito externo) no finding.
|
|
147
|
+
* **Mostrar o mecanismo** — onde falta transação, onde retry não é idempotente, onde
|
|
148
|
+
rollback não cobre, onde catch engole. Ou reprodução com falha injetada.
|
|
149
|
+
* **Escalar confiança:**
|
|
150
|
+
* `CONFIRMED` — injetou falha e observou estado parcial/corrompido.
|
|
151
|
+
* `HIGH CONFIDENCE` — código mostra ausência de transação/rollback/idempotência em
|
|
152
|
+
caminho claro.
|
|
153
|
+
* `POSSIBLE` — plausível, caminho não confirmado.
|
|
154
|
+
* `SPECULATIVE` — "pode falhar" sem rastrear.
|
|
155
|
+
* Estados parciais **com efeito externo irreversível** (dinheiro cobrado, email
|
|
156
|
+
enviado) e **silenciosos** (empty catch) são os mais graves.
|
|
157
|
+
|
|
158
|
+
## False Positives
|
|
159
|
+
|
|
160
|
+
* **Transação cobre todos os writes** — se tudo está em uma DB transaction e nada de
|
|
161
|
+
externo ocorre antes do commit, "falha mid-op" é seguro (rollback automático).
|
|
162
|
+
Confirmar antes de reportar.
|
|
163
|
+
* **Operação é idempotente por design** — retry seguro significa "duplica" não é bug.
|
|
164
|
+
Relacionado a `idempotency-audit`; não duplique o finding.
|
|
165
|
+
* **Saga/outbox com reconciliação** — se há outbox + worker que reconcilia estado
|
|
166
|
+
parcial, a inconsistência é temporária e tratada. Reportar só se a reconciliação é
|
|
167
|
+
ausente/quebrada.
|
|
168
|
+
* **Timeout tratado como "unknown" com query+decide** — se após timeout o sistema
|
|
169
|
+
consulta o estado real antes de retry, é correto. Não reportar.
|
|
170
|
+
* **Empty catch é intencional e compensado** — raro, mas se há compensação downstream,
|
|
171
|
+
confirmar antes de reportar como defeito.
|
|
172
|
+
|
|
173
|
+
## Output Format
|
|
174
|
+
|
|
175
|
+
Para cada ponto de falha que deixa estado parcial/corrompido, um finding via
|
|
176
|
+
`templates/audit-report.md`. Em **Reproduction**, descreva a falha injetada (qual
|
|
177
|
+
passo falha, como) e o estado final observado. Em **Affected flow**, nomeie a operação.
|
|
178
|
+
Em **Root cause**, diga o que falta (transação, rollback, idempotência no retry,
|
|
179
|
+
reconciliação, detecção de erro). Em **Recommendation**, indique a estratégia (transação
|
|
180
|
+
atómica, outbox/saga, idempotency key, query-on-timeout, alerta em rollback failure).
|
|
181
|
+
|
|
182
|
+
Apresente a decomposição como tabela (passo | efeito | idempotente? | reversível? |
|
|
183
|
+
efeito externo? | estado se falhar após). Pontos de não-retorno e estados silenciosos
|
|
184
|
+
primeiro.
|