feat(brief): optional threat model in the brief (decision 164, 218)

A brief may carry an optional `## Threat Model` with one line per bullet,
`- Inside: <text>` or `- Outside: <text>`. Present and malformed (no such
bullet, another label or form, empty text, two sections) is
BRIEF_THREAT_MODEL_MALFORMED; absent is today's rule. No brief_version bump
(the ceremony / artifact_store precedent). Sections are found fence- and
comment-aware through intent-approval's new sectionTexts, so the validator
and the hash count the same sections; brief-validator exports
parseThreatModel for the reader.

The intent hash covers `## Threat Model` when present (two sections -> null
hash, as Intent and Goal), so an edited, added or removed threat model
makes the approval stale; a brief without one hashes exactly as before. The
stale message and the /trekplan halt table name the section.

/trekbrief offers the section in its question round when the task touches
a guard, a gate, untrusted input, secrets or publishing, writes it only
when given, shows it verbatim at the Phase 4h approval, and --approve reads
it out. The template documents it; brief-gate-coverage pairs the new code.

Part 2, step 2.1 of the E plan.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-11-08 08:47:51 +01:00
commit 74f75dcb7d
Signed by: ktg
SSH key fingerprint: SHA256:JakMjO6FTBBzN0Bhfj9saOoEjaFxlSdYuZQQpM/lF9Q
7 changed files with 350 additions and 23 deletions

View file

@ -88,6 +88,20 @@ Quantified where possible.*
- {NFR 1 — e.g., "p95 response time < 200ms"}
- {NFR 2 — e.g., "Zero new npm dependencies"}
## Threat Model
*Optional: write it only when the task touches a guard, a gate, untrusted input,
secrets or publishing, and leave the whole section out otherwise (absent = every
security finding counts). One line per bullet, each `- Inside: <text>` (what the
work must defend against) or `- Outside: <text>` (what it deliberately does not);
any other bullet makes the brief invalid (`BRIEF_THREAT_MODEL_MALFORMED`).
Voyage's own security findings block inside it; one that quotes an `Outside:`
line's text exactly becomes a listed known issue. The intent approval covers
this section: editing it afterwards makes the approval stale.*
- Inside: {e.g., "a crafted file name in a pull request reaches the shell"}
- Outside: {e.g., "a local user who can already edit the repo's hooks"}
## Success Criteria
*Falsifiable, command-checkable conditions that define "done". Each must be