Template
feat: add a dedicated Security Auditor agent with veto power
Security was one section among seven in the QA Engineer. That is structurally weak: the agent that wants to recommend "production ready: YES" also judged security, and as a subsection it competes for attention with acceptance criteria, regression and test authoring. The new agent: - has no Write/Edit tools, so "never fix what you find" is enforced by the tool list rather than by instruction — it cannot launder a finding into a patch - reports PASS / FAIL / UNVERIFIED, and UNVERIFIED must reach the spec; an audit that omits what it could not check reads as all-clear - audits against .claude/rules/security.md, the same standard the developer agents are held to, so every mandatory item gets a verdict - holds a veto: BLOCK stops /deploy regardless of functional test results /qa now runs both agents in parallel and keeps the verdicts separate. The QA Engineer is explicitly forbidden from speaking for security.
This commit is contained in:
@@ -18,6 +18,11 @@ on the host.
|
||||
|
||||
**No QA section:** → "Für PROJ-X gibt es noch kein QA-Ergebnis. Führe erst `/qa` aus." → Stop.
|
||||
**Critical or High bugs open:** → name them and stop. Those get fixed first.
|
||||
**Security verdict is BLOCK, or missing entirely:** → stop. A feature without a
|
||||
Security Auditor verdict has not been security-reviewed, no matter how green the
|
||||
functional tests are.
|
||||
**UNVERIFIED security items:** → list them and ask the user explicitly whether to
|
||||
ship with that surface unchecked. Do not decide this silently on their behalf.
|
||||
|
||||
## 2. Pre-flight
|
||||
|
||||
|
||||
+58
-19
@@ -23,14 +23,27 @@ user.
|
||||
Update `features/INDEX.md` and the spec header to **In Review**. Verify by
|
||||
re-reading.
|
||||
|
||||
## 3. Delegate testing
|
||||
## 3. Delegate — two agents, in parallel
|
||||
|
||||
Invoke the **QA Engineer** sub-agent with:
|
||||
Invoke both in the same turn so they run concurrently. They answer different
|
||||
questions and must not be merged into one agent.
|
||||
|
||||
**QA Engineer** — does the feature do what the spec promises?
|
||||
- the spec path
|
||||
- the list of deployed features to regression-check
|
||||
- any areas the developer flagged as risky
|
||||
|
||||
Wait for its report.
|
||||
**Security Auditor** — is it safe to expose to the internet?
|
||||
- the spec path
|
||||
- which routes, auth flows and compose services this feature touched
|
||||
- whether a deployment already exists (so it can check live headers)
|
||||
|
||||
Wait for both reports.
|
||||
|
||||
The Security Auditor has a **veto**. If it returns `BLOCK`, the feature is not
|
||||
Approved — regardless of how clean the functional test run was. Never average the
|
||||
two verdicts into an optimistic summary, and never let the QA Engineer's
|
||||
"production ready: YES" stand in for a security verdict it is not allowed to give.
|
||||
|
||||
## 4. Write results into the spec
|
||||
|
||||
@@ -42,7 +55,7 @@ Append this to the feature spec — not to a separate file:
|
||||
## QA Test Results
|
||||
|
||||
**Getestet:** YYYY-MM-DD
|
||||
**Tester:** QA Engineer (AI)
|
||||
**Geprüft von:** QA Engineer + Security Auditor (AI)
|
||||
|
||||
### Acceptance Criteria
|
||||
- [x] AC-1: [Kriterium]
|
||||
@@ -51,13 +64,32 @@ Append this to the feature spec — not to a separate file:
|
||||
### Edge Cases
|
||||
- [x] EC-1: [Randfall] — korrekt behandelt
|
||||
|
||||
### Security-Audit
|
||||
- [x] Ohne Session kein Zugriff
|
||||
- [x] Kein Zugriff auf fremde Datensätze
|
||||
- [x] Passkey ist der primäre Anmeldeweg
|
||||
- [x] Eingaben validiert, keine Injection
|
||||
### Security-Audit (Security Auditor)
|
||||
|
||||
### Gefundene Bugs
|
||||
**Verdikt: BLOCK | PASS-MIT-BEFUNDEN | PASS**
|
||||
|
||||
| Bereich | Ergebnis | Beleg |
|
||||
|---------|----------|-------|
|
||||
| Authentifizierung | PASS | Passkey primär, `src/lib/auth.ts:24` |
|
||||
| Autorisierung | FAIL | siehe SEC-1 |
|
||||
| Eingabevalidierung | PASS | Zod auf allen Write-Routen |
|
||||
| Secrets | PASS | nichts in der History, `.env.example` vollständig |
|
||||
| Container-Exposure | UNGEPRÜFT | Docker in dieser Umgebung nicht verfügbar |
|
||||
| Security-Header | PASS | `next.config.ts:8-20` |
|
||||
| Abhängigkeiten | PASS | 0 High/Critical in Prod-Deps |
|
||||
| Fehler- und Log-Hygiene | PASS | |
|
||||
|
||||
**UNGEPRÜFT ist kein Bestanden.** Jeder solche Punkt bleibt hier stehen, bis ihn
|
||||
jemand tatsächlich geprüft hat.
|
||||
|
||||
#### SEC-1: [Titel]
|
||||
- **Severity:** Critical | High | Medium | Low
|
||||
- **Ort:** `datei.ts:zeile`
|
||||
- **Angriff:** was ein Angreifer konkret tut
|
||||
- **Ursache:** warum es funktioniert
|
||||
- **Fix gehört zu:** /backend | /frontend
|
||||
|
||||
### Gefundene Bugs (QA Engineer)
|
||||
|
||||
#### BUG-1: [Titel]
|
||||
- **Severity:** Critical | High | Medium | Low
|
||||
@@ -68,33 +100,40 @@ Append this to the feature spec — not to a separate file:
|
||||
### Zusammenfassung
|
||||
- **Acceptance Criteria:** X von Y bestanden
|
||||
- **Bugs:** N gesamt (C critical, H high, M medium, L low)
|
||||
- **Produktionsreif:** JA / NEIN
|
||||
- **Security:** Verdikt + Anzahl Befunde + Anzahl UNGEPRÜFT
|
||||
- **Produktionsreif:** JA / NEIN — bei Security-Verdikt BLOCK immer NEIN
|
||||
```
|
||||
|
||||
Re-read the file afterwards to confirm it landed.
|
||||
|
||||
## 5. Review with the user
|
||||
|
||||
Present: criteria passed/failed, bugs by severity, security findings, verdict.
|
||||
Then ask:
|
||||
> "Welche Bugs sollen zuerst behoben werden?"
|
||||
Present both verdicts separately — functional and security. Name every UNVERIFIED
|
||||
security item out loud; those are the parts nobody has checked, and burying them in
|
||||
the table is how they get forgotten. Then ask:
|
||||
> "Welche Befunde sollen zuerst behoben werden?"
|
||||
|
||||
## 6. Wrap up
|
||||
|
||||
- [ ] Every acceptance criterion has an individual pass/fail
|
||||
- [ ] Documented and undocumented edge cases tested
|
||||
- [ ] Security audit done from a red-team angle
|
||||
- [ ] Security Auditor ran and returned a verdict
|
||||
- [ ] Every UNVERIFIED security item is listed in the spec, not silently dropped
|
||||
- [ ] Regression check against deployed features
|
||||
- [ ] Unit tests for non-trivial logic (`npm test` passes)
|
||||
- [ ] E2E test per passing criterion (`npm run test:e2e` passes)
|
||||
- [ ] QA section written into the spec and verified
|
||||
- [ ] `features/INDEX.md` → **Approved** if no Critical/High, otherwise stays **In Review**
|
||||
- [ ] `features/INDEX.md` → **Approved** only if there are no Critical/High bugs
|
||||
**and** the security verdict is not BLOCK; otherwise stays **In Review**
|
||||
|
||||
## Handoff
|
||||
|
||||
- Clean → "Alle Tests bestanden, Status **Approved**. Nächster Schritt: `/deploy`."
|
||||
- Bugs → "[N] Bugs gefunden ([Aufschlüsselung]). Status bleibt **In Review**.
|
||||
Erst `/frontend` bzw. `/backend` zum Beheben, danach nochmal `/qa`."
|
||||
- Both clean → "Tests bestanden, Security-Verdikt PASS. Status **Approved**.
|
||||
Nächster Schritt: `/deploy`."
|
||||
- Security BLOCK → "Security-Audit blockiert: [Befunde]. Status bleibt **In Review**,
|
||||
unabhängig von den Funktionstests. Erst `/backend` bzw. `/frontend` zum Beheben,
|
||||
danach nochmal `/qa`."
|
||||
- Nur Bugs → "[N] Bugs gefunden ([Aufschlüsselung]). Status bleibt **In Review**."
|
||||
|
||||
## Commit
|
||||
|
||||
|
||||
Reference in New Issue
Block a user