Gates
A gate counts only after it proves it can fail: each one carries planted defects, and its proof is pinned to a hash of its definition. 20 gates guard the Advocate.
flowchart LR
tone_and_next_step["tone-and-next-step"]
student_sends["student-sends"]
safety_router["safety-router"]
freshness["freshness"]
sealed_facts["sealed-facts"]
evidence_pseudonymous["evidence-pseudonymous"]
no_status_question["no-status-question"]
snap_income_oracle["snap-income-oracle"]
journey_lock["journey-lock"]
community_moderation["community-moderation"]
no_dead_ends["no-dead-ends"]
docs_linked["docs-linked"]
no_hidden_egress["no-hidden-egress"]
pattern_coverage["pattern-coverage"]
findings_register["findings-register"]
zero_bypass["zero-bypass"]
authorship_tiers["authorship-tiers"]
held_out["held-out"]
sensitive_data["sensitive-data"]
block_library["block-library"]
change([A change]) --> tone_and_next_step & student_sends & safety_router & freshness & sealed_facts & evidence_pseudonymous & no_status_question & snap_income_oracle & journey_lock & community_moderation & no_dead_ends & docs_linked & no_hidden_egress & pattern_coverage & findings_register & zero_bypass & authorship_tiers & held_out & sensitive_data & block_library --> admit{All pass with valid proofs?}
admit -- yes --> ok([Admitted])
admit -- no or unknown --> no([Not admitted])| Gate | Protects | Proven against |
|---|---|---|
tone-and-next-step |
No message to a student scolds, reads above their level, or reports a problem without a next step (PRD P3, P4). | planted scolding message; planted message with no next step |
student-sends |
Nothing reaches an outside party without a single-use approval token for that exact content (PRD P9). | planted dispatcher that ignores tokens |
safety-router |
Crisis messages, including held-out phrasings, route to 988 before any model (PRD SAF-1). | planted router that only knows one phrase |
freshness |
A catalog entry past its freshness window is never offered as available (PRD P11). | planted finder that ignores freshness |
sealed-facts |
A sealed fact never appears in a message unless the student released it to a playbook that needs it (PRD P10). | planted message quoting the sealed fact |
evidence-pseudonymous |
The evidence store holds no student identifiers or content. | planted evidence row with a phone number |
no-status-question |
The team never asks about citizenship or immigration status (PRD NAV-7). | planted citizenship question |
snap-income-oracle |
SNAP income results match the published FY2027 table at and just over every limit (record-derived oracle, Pattern 17). | planted off-by-one limit |
journey-lock |
No change can edit or remove the journey cards it is judged by (Pattern 18). | planted lock missing a card |
community-moderation |
Harmful or risky posts never surface in the community (PRD COM-5). | planted community with no filters |
no-dead-ends |
Every button any agent offers works, in the app and by text (PRD P3, P8). | planted registry missing a handler; planted handler that answers with no next step |
docs-linked |
Every test file names the document it verifies, that document exists, and every document is verified by a test. | planted test file with no doc; planted link to a missing doc |
no-hidden-egress |
Only the model client and the egress block may reach the network; domain, agent and server code cannot (PRD P2). | planted fetch in a domain file |
pattern-coverage |
All 33 ZTHR patterns are implemented, each points at files that exist, and each is proven by a test (and a gate where it names one). | planted map missing a pattern; planted proof that does not exist |
findings-register |
Every finding we have not fixed is written down with a reason, an owner and an expiry, and none has expired (Pattern 13). | planted expired finding; planted finding with no owner |
zero-bypass |
Every required check runs in the live pipeline, none may fail and none can be skipped (Pattern 7). | planted pipeline without the gates step; planted step allowed to fail; planted step that swallows failure; planted script that skips its walk without carrying evidence |
authorship-tiers |
Every file belongs to an authorship tier and every tier names a guard that enforces it; the open tier comes last (Pattern 6). | planted tier with no guard; planted open tier first |
held-out |
No rule is written against its own evaluation set: a held-out line that appears in a rule is caught, to be retired (Pattern 32). | planted rule written against a held-out line |
sensitive-data |
Every field the app keeps is classified, and a planted marker in each personal, sensitive and secret field turns up only where its class may go. | planted field with no class; planted income marker in the evidence log; planted field the trace never exercised |
block-library |
Every block has its own tests, a page saying what to use it for and what not, at least one consumer, a mutation score at or above its floor, and no copy of its code inside an app. | planted block with no tests; planted block nothing uses; planted block under its mutation floor; planted block with no purpose page; planted app copy of a block function |
Verified by
- `packages/gates/test/hardening.test.ts` (6 test definitions)