feat(w4): 10-scenario adversarial suite + 4 benchmark tables (0/10 vs 9/10)#24
Merged
Conversation
Closes #15, #16, #17. Delivers the W4 acceptance signal: Warden: leaks = 0/10 Naive baseline: leaks = 9/10 All 4 benchmark tables reproduce via `make bench` and land in docs/bench/*.md. evals/corpus.py Parameterized synthetic corpus generator. Deterministic under seed. Power-law org distribution (top 20% of orgs hold ~80% of docs) plus configurable selectivity, barrier density, and scale (smoke/small/ 10k/100k/1M presets). Not from a real IR corpus — the recall numbers we care about are relative (strategy A vs B), not absolute. evals/scenarios/_shared.py Two deliberately-broken naive baselines: - naive_authz_check: any grant path, ignores deny + expiry - naive_rag_retrieve: top-K by similarity, no auth filter Both exist to be beaten. evals/scenarios/scenario_0{1,2,3,5,6,7,8,9}_*.py 8 new scenarios. Combined with the 2 from W3 (in-flight revocation, prompt injection) this completes the design-doc's 10-scenario suite: 01 semantic_neighbor Gate 1+2 vs unfiltered top-K 02 ethical_wall deny dominance vs naive union grants 03 stale_revocation Gate 2 vs stale label filter 04 in_flight_revocation (W3) — Gate 3 evicts mid-run 05 citation_leak Gate 3 strips revoked citations 06 cross_tenant_space wall wins over space grant 07 expired_guest expiry enforcement 08 transitive_nesting fidelity + safety at 5 hops 09 deleted_embedded stale index cannot leak past Gate 2 10 prompt_injection (W3) — principal binding beats injection evals/scenarios/run_all.py Suite runner. Prints Harvey-blog-style table with leak counts per side. Exit code 0 iff Warden's leak count is 0. tests/test_scenarios.py Parametrized across all 10 scenarios plus two aggregate assertions: Warden must be 0/10, naive must be > 0. evals/bench/{_common,table1_overhead,table2_recall,table3_scaling, table4_revocation,run}.py Four benchmark tables and an orchestrator. Numbers are real, measured, and honest — every table caption disclaims "synthetic single-node laptop" scale. docs/bench/*.md Generated tables checked in. Highlights from the current run: Table 1: Gate 2 = ~52µs at 1k docs, ~640µs at 50k docs (p50) Table 2: post-filter recall = 0.06 at 1% selectivity; label pushdown = 1.00. The recall cliff, visualized. Table 3: ID-list = 9,663 ints at 50k docs; label pushdown = 6. The O(1) vs O(n) claim, in numbers. Table 4: revoke → deny = 3µs; revoke → evict = 17µs. Sync. Makefile New: scenarios-report (prints leak table), bench (writes docs/bench/). .github/workflows/ci.yml Fast job now also runs `bench` (smoke) and `scenarios-report` on every push. README.md Adds a "Headline numbers" section linking to the four tables and showing the 0/10 vs 9/10 result. Deps: numpy>=1.26 (used by the corpus generator). Test state: 100 unit tests + 4 differential properties (5000 examples in CI) + 21 integration tests. All green. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Milestone W4 — the product. 10 adversarial scenarios (Warden 0/10, naive baseline 9/10), 4 benchmark tables reproducible by
make bench. Closes #15, #16, #17.The W4 acceptance signal:
The four tables land in
docs/bench/. Highlights:What ships
evals/corpus.py— parameterized synthetic corpus (deterministic under seed; scales fromsmoketo1m).evals/scenarios/_shared.py— two deliberately-broken naive baselines (naive_authz_check,naive_rag_retrieve).evals/scenarios/scenario_0{1,2,3,5,6,7,8,9}_*.py— 8 new scenarios completing the 10 from the design doc.evals/scenarios/run_all.py— suite runner with the Harvey-blog table + leak counts. Exit code 0 iff Warden = 0.evals/bench/— 4 tables + orchestrator.make benchwrites todocs/bench/*.md.docs/bench/*.md— generated tables checked in as the current reference.README.md— Headline numbers section linking to the tables.The 10 scenarios
Test plan
make oracle— 15 greenmake rebac— 18 greenmake labels— 19 greenmake gates— 22 greenmake api— 5 greenmake scenarios— 12 tests green (10 individual + 2 aggregate) — the W4 acceptance gatemake bench— writes all 4 tables in ~30s; regenerated files committedmake test— 100 green, 21 integration skipped w/o env varsmake differential-gate— 4 properties × 5000 examples still greenInvariant checklist
make oraclegreen.make testgreen.core/oracle.pyand any engine module.Security-sensitive?
Does not touch
core/algebra.py,core/oracle.py,core/rebac.py,core/barriers.py,core/labels.py, or the gate wiring. Pure measurement + adversarial-suite additions.Read invariants section of the README.
Not fixing an undisclosed vulnerability.
Notes for reviewers
authorized_setas ground truth, not a live pgvector benchmark. The shape of the recall cliff is what matters. A live pgvector Recall@K benchmark is a follow-up (needs ~1M docs on real hardware to be meaningful); the harness inretrieval/strategies.pyfrom W2 is ready to plug in._common.measure()usestime.perf_counterwith 5-iteration warmup and 500-iteration samples. Median-based percentiles. Numbers vary ~10% run-to-run on the same laptop.