[
  "Repository studied: private yeegz/WayClub at commit 65a18ff93c9ee39f52a9a42e67fa00cc7a4c49b5 (committed 2026-11-01 23:44 +0800), cloned to a scratch directory; the owner's working tree (uncommitted changes to 067_identity.sql, wayclub-db.test.mjs, SECURITY.md and others) was NOT used. Nothing was committed to the WayClub repo.",
  "Postgres: dedicated local cluster, PostgreSQL 17.10 (Homebrew) on aarch64-apple-darwin25.6.0, port 55499, fsync=on, synchronous_commit=on, shared_buffers=512MB, max_connections=200; created with initdb on 2026-11-01. No cloud resource touched.",
  "Machine: Apple M1 Pro, 8 cores (hw.ncpu=8), 16 GB (hw.memsize=17179869184), macOS 27.0.1 (26A434); Node v26.0.0, pg 8.22.0, pgbench 17.10, Python 3.14.2.",
  "Load: results/load.log (76 samples, 17:13Z-17:53Z), one-minute load average median 84.0, min 56.1, max 99.3 (results/load_summary.json); uptime at 17:13Z reported 15-min load 105.64 (covers Experiment 1, 16:44-16:55Z).",
  "Run times: results/run_all.log — exp1 16:44:18Z-16:55:01Z, exp4 to 17:11:41Z, exp2 query timing x0/x50 to ~17:21Z, x1000 restarted 17:22:45Z-17:26:22Z, pgbench to 17:38:42Z, minimal reproduction to 17:52:37Z; helper microbenchmark re-run after a fix at ~17:45Z (results/exp2_helper_overhead.jsonl).",
  "Table 1 documented values: docs/SECURITY.md lines 110-122 at 65a18ff ('Measured on 2026-08-03 ... 22 at the time of measurement'; 78 of 79; 126 policies across 47 tables; 48 reachable; 31 deny-all).",
  "Table 1 measured values: results/exp3_catalogue_counts.json via scripts/catalogue_history.py on wc_at_022 (scripts/build_db_at.sh at 940b2ae) and wc_head_clean (65a18ff, 68 migration files); schema_migrations ledger excluded. Raw: sql/catalogue_counts.sql output at 022 showed 80 public tables incl. schema_migrations.",
  "Head counts: 103 public tables excl. ledger, 102 RLS, only 'role' without RLS, 0 forced, 225 policies on 75 tables (212 request-role/PUBLIC, 13 wayclub_service), 75 tables reachable by wayclub_app, 27 deny-all; 249 SECURITY DEFINER functions in app/wayclub_auth/public/abuse/platform, all with proconfig (SET search_path); 210 of 225 public policies reference app.* (results/exp3_catalogue_counts.json).",
  "Scope history: results/exp3_scope_history.json via sql/old_vs_new_predicate.sql — 016: 57/57; 022: 72/78 blind spot 6 (account, account_entitlement, club_affiliation, club_migration, club_migration_mapping, institution_claim); HEAD: 85/95 blind spot 10; blind_spot_without_rls = 0 in all.",
  "Old predicate text: infra/postgres/tests/wayclub-db.test.mjs at 85475d7 lines 1238-1262 (relname = 'institution' or attname = 'institution_id'); new predicate introduced in 5096bcd (2026-08-03 05:40 +0800), git log -S.",
  "Continuity tables carry institution_id: information_schema on wc_at_021 shows handover and external_tool have both account_id and institution_id (contradicts docs/SECURITY.md line 146 'the whole continuity domain').",
  "Head suite red: results/exp3_vitest_full_db_file_head.log — wayclub-db.test.mjs at 65a18ff: 105 passed, 2 failed (A5 'every request-role policy is keyed on the ACCOUNT' listing legal_version.legal_version_public_read, reserved_handle.reserved_handle_read, person_handle.person_handle_select, person_avatar.person_avatar_select; and 'the auth schema guard' expecting no display_name_pending column). Uncommitted working-tree diff (git diff HEAD -- infra/postgres/tests/wayclub-db.test.mjs) adds an ALLOWED map for exactly these four; inspected read-only, not used.",
  "Full-directory vitest run in parallel failed for harness reasons (shared reset lock, hook timeouts): results/exp3_vitest_all_files_parallel_head.log; hence only the single file was run.",
  "Mutation analysis: results/exp3_mutations.txt via scripts/run_mutations.sh on seeded wayclub_test (65a18ff); baseline results/exp3_baseline_head.txt; table results/exp3_mutation_table.json. Vitest confirmation: results/exp3_vitest_summary.txt (baseline 1 failed/4 passed; M1 3 failed; M2 2 failed; M7 1 failed = baseline only).",
  "R1 rule source: infra/deploy/google/checks/database-checks.mjs lines 99-117 at 65a18ff (unprotectedGrants), ported in sql/catalogue_assertions.sql.",
  "Housekeeping: the vitest mutation runs left mut_m7 and a 999_mutation.sql ledger row in wayclub_test; they were dropped from wc_head, wc_bench_x0, wc_bench_x50, wc_bench_x1000 before experiments 1, 2 and 4 used those databases; catalogue counts use wc_head_clean built fresh.",
  "FORCE probe: results/force_rls_probe.txt (sql/force_rls_probe.sql on wc_bench_x0, rolled back): not forced is_member_of=t, owner count(membership)=16; forced is_member_of=f, owner count=0; app-visible events 7 in both states for persona 1.",
  "Experiment 1: results/exp1_lockscope_{before,after,head,head_immediate}.jsonl, 30 runs each, hold 5000 ms; summary.json exp1_lockscope (before same p50 4919.1 p95 4945.5 min 4905.5; other p50 21.8; after same p50 41.3 max 190.1, other p50 42.5; head 105.2/109.2; head_immediate same p50 4972.3, other 71.8). Prior measurement cited from docs/adr/0009-per-account-audit-chain.md (4780 ms, 4792 ms vs 43 ms).",
  "Speedup 119x = 4919.1 / 41.3 (before vs after same-tenant p50).",
  "Experiment 4: results/exp4_{interleave,stress,tamper}_{before,after,head}.jsonl; summary.json exp4_audit_chain: before interleave 200/200 fail, 0 forks, median 2 breaks; before stress 100/100 fail, 100/100 with shared predecessor; after and head 0/300 each (600 total), 0 forks, 0 writer errors.",
  "Tamper: results/exp4_tamper_head.jsonl and _after/_before: owner UPDATE blocked WC403; interior edit detected (1 break); interior delete detected (break + chain_index gap); tail delete not detected; edit+rehash suffix not detected.",
  "Minimal public reproduction: sql/minimal/*.sql (verbatim 006 lines 23-94 and 011 lines 58-168; 011 identical at 85475d7 and 65a18ff by diff; 006 chain section unchanged, later diffs only in audit trigger functions beyond line 122). Results results/min_*.jsonl, summary_minimal.json: before same p50 4967.9 vs other 51.7; after 150.4 vs 142.3; chain before interleave 200/200 fail, stress 100/100 fail with forks; after 0/300.",
  "Experiment 2 data: bench/setup_bench.sql; wc_bench_x0 (22 events), x50 (1,122), x1000 (22,022); 16 personas from active memberships. results/exp2_query_x0.jsonl and x50 (16 personas x 5 reps x 2 queries = 160 lines), x1000 (personas 1,7,9,14, 1 rep); aborted all-persona x1000 partial in exp2_query_x1000_aborted_partial.jsonl (2 lines, 144 s discovery under RLS). rows_equal_fraction = 1.0 at all scales.",
  "Exp2 medians/minima (summary.json exp2_query_timing): x0 club RLS p50 4.46 min 0.081 vs filter p50 0.035 min 0.021; x50 club RLS p50 1168.9 min 17.1 vs 0.93/0.077 (ratio median 856); x50 discovery 999.6/11.4 vs 0.92/0.092 (1656); x1000 club 10762.9/1940.9 vs 10.6/4.7 (524); x1000 discovery 5436.3/2691.5 vs 65.8/7.0 (372).",
  "pgbench: results/pgbench/*.txt, 5 runs x 3 modes x 2 scales, 20 s each, -c 8 -j 4 -M prepared; summary.json exp2_pgbench: x0 owner 358.3±99.6 tps, rls 65.5±18.7, rls+filter 58.0±20.8; x50 owner 190.0±64.3, rls 1.72±0.75, rls+filter 2.0±0.6; 0 failed transactions.",
  "Helper microbenchmark: results/exp2_helper_overhead.jsonl (5 reps, wc_bench_x1000, persona 1, account with 14,014 events): shipped p50 3369.1 min 2532.8; definer no SET 2766.2; invoker without SET 2191.5; set-based 126.9 min 40.2; floor 3.4; is_university_admin() inside OR per row 39727.8; hoisted 214.3. First attempt failed on a type error (uuid = uuid[]) and a bare row-independent qual became a one-time filter; both fixed before the reported run.",
  "Helper definitions: app.is_member_of, app.current_account_id, app.is_university_admin, app.has_institution_role read with pg_get_functiondef on wc_bench_x0 (all LANGUAGE sql STABLE SECURITY DEFINER SET search_path='').",
  "References verified 2026-11-02 via Crossref API (DOIs 10.1145/317087.317089, 10.1145/223784.223785, 10.1145/3035918.3064037, 10.1145/1071610.1071615, 10.1145/1376616.1376690, 10.14778/2367502.2367523, 10.1109/TSE.2010.62) and web search (Crosby & Wallach USENIX Security 2009 page; Chong et al. 2006 PDF; RFC 6962); PostgreSQL docs and wiki URLs returned HTTP 200.",
  "Documents read: docs/SECURITY.md, docs/TESTING.md (line 157 on the 017 gap), docs/adr/0002, 0008, 0009, infra/postgres/README.md, migrations 006, 011, 012, 019, tests wayclub-db.test.mjs, all at 65a18ff.",
  "Review revision v1.1 (2026-11-02): every number recomputed from the raw results/*.jsonl and results/pgbench/*.txt with an independent script; all matched summary.json and summary_minimal.json.",
  "Headline interval: scripts/bootstrap_ci.py -> results/exp1_bootstrap_ci.json (ratio of medians 119.0; percentile bootstrap 95% 80.9-152.3, 10,000 resamples, seed 1; min(before)/max(after) = 4905.52/190.12 = 25.8).",
  "Per-measurement RLS/filter ratio ranges: x1000 club 345-2,128 (median 524, n=4); x1000 discovery 56-593 (median 372, n=4); x50 minima ratios 17.072/0.077 = 222 and 11.375/0.092 = 124; x1000 minima ratios 411 and 383.",
  "Plan shapes: bench/explain_plans.sql run on wc_bench_x50 during review (EXPLAIN without ANALYZE, persona 1) -> results/exp2_plans_x50.txt: account test is an index condition; event_select's OR of app.oversees_club, is_committee_of, is_member_of, is_reviewer_for_club, is_university_admin, club_is_suspended is a per-row Filter; (select app.is_university_admin()) becomes InitPlan 2.",
  "Per-row cost arithmetic (Section 7.1): (3369.1-3.4)/14014 = 0.24 ms; 39727.8/14014 = 2.83 ms; (126.9-3.4)/14014 = 0.0088 ms; definer without SET saves (3369.1-2766.2)/3369.1 = 18%.",
  "Load coverage: load.log starts 17:13Z, after exp1 (16:44-16:55Z) and exp4 (to 17:11Z); uptime at 17:13Z 15-min load 105.64. Artifact README previously said 70-110; corrected to median 84, range 56-99. At review time (2026-11-02 02:05 +08) the 1-minute load average was 173.",
  "Rule of three: 3/300 = 1.0%, 3/600 = 0.5%.",
  "Privacy pass (v1.1): removed role passwords from the artifact README and scripts (local cluster uses trust authentication); no absolute local paths, credentials or private test source in the artifact; vitest logs contain only result lines.",
  "References added in v1.1: pgTAP documentation (policies_are, policy_roles_are, policy_cmd_is present) and Supabase database linter page (lints 0003 auth_rls_initplan, 0007, 0008, 0013 present), both fetched 2026-11-02. Warszawski & Bailis claim reworded to the paper's scope (22 attacks, 12 e-commerce applications)."
]