#!/usr/bin/env python3 """Build a single, self-contained localhost HTML page for the sor-consent study. Reads the two paper drafts (lead + combined companion) and renders them into one offline HTML file with an executive summary and hand-authored SVG figures. Number fidelity is guaranteed because the paper bodies are converted straight from the committed markdown -- no figure is transcribed by hand except the SVG annotations, which are cross-checked against the sealed records. Sources (read-only): docs/stage-07-paper-draft.md -- lead paper (G4 + RQ1 + RQ2) docs/stage-07-companion-methods.md -- combined companion (RQ2-P3 mechanism + RQ3) Output: docs/paper-site/index.html """ from pathlib import Path import markdown HERE = Path(__file__).resolve().parent DOCS = HERE.parent LEAD_MD = DOCS / "stage-07-paper-draft.md" COMPANION_MD = DOCS / "stage-07-companion-methods.md" OUT = HERE / "index.html" MD_EXT = ["tables", "fenced_code", "sane_lists", "attr_list", "toc"] def render(md_path: Path) -> str: text = md_path.read_text(encoding="utf-8") return markdown.markdown(text, extensions=MD_EXT) lead_html = render(LEAD_MD) companion_html = render(COMPANION_MD) TEMPLATE = r""" Consent-Gated Federated Onion Routing — study site

Consent-Gated Federated Onion Routing:
Linkability, Anonymity-Set, and Churn-Resilience of an In-Band Accept/Reject Relay Model

A pre-registered, frozen-detector measurement study on a lab grid (2 phones + laptop, isolated-docker circuits). Two papers: a lead study (RQ1 linkability, RQ2 anonymity set) and a combined companion (RQ2-P3 mix mechanism, RQ3 churn-resilient agent selection). Reported honestly — nulls and negatives are results.

Pre-registered & hashed Detectors frozen before data 180 + 13,500 + 4,500 circuits BCa 95% CIs · Holm-7 Defensive-measurement instrument Containment: isolated-engine only

Executive summary

We built a consent-gated, federated, nested-SSH relay as a measurement instrument (not a service) and asked, on a lab grid, whether a shared bridge leaks entry↔exit linkability (RQ1), whether federation grows or shrinks the anonymity set (RQ2), whether shared-bridge concentration funnels or mixes (RQ2-P3), and whether a local open-weight agent selector survives churn without a rebuild fingerprint (RQ3). Every detector was calibrated on fixtures and frozen before any confirmatory cell ran.

RQ1 · Bridge linkability
AUC 0.466
CI [0.452, 0.480], below the 0.50 chance line. Calibration: linked 1.00 / unlinked 0.50.
No measurable leak
RQ2-P1 · Federation
ΔH −0.96 bits
CI [−1.06, −0.86]. Federation shrinks the per-circuit anonymity set (Holm-significant negative).
Honest negative
RQ2-P3 · Mix mechanism
ρ +0.62
CI [+0.59, +0.65]; slope β +0.71. Shared-pool concentration raises anonymity — corrects the lead "shrink" as a unique-bridge artifact.
Resolved: MIX
RQ3 · Agent selector
Null × 2
Retention margin −0.6pp (gate +10pp); rebuild AUC 0.587, CI upper 0.703 > 0.60. Neither beats baselines nor certifiably fingerprint-free (n=30).
H0 on both counts

The seven pre-registered tests (authoritative Holm-7)

TestEffect (point & 95% CI)Frozen gateHolm-7 adj pSurvives .05
RQ1-P1 leakAUC 0.466 [0.452, 0.480]CI excludes 0.5 (leak)0yes* (below chance → no leak)
RQ2-P1 federationΔH −0.96 [−1.06, −0.86] bitstwo-sided sign0yes — shrink
RQ2-P3 mechanismρ +0.62 [+0.59, +0.65]two-sided sign0yes — mix
RQ1-P2 paddingΔAUC +0.011 [−0.002, +0.023]CI > 00.365no
RQ3-P2 fingerprintAUC 0.587 [0.458, 0.703]CI upper ≤ 0.600.511no (not excluded)
RQ3-P1-perf−0.6pp [−1.58, +0.39]ppCI lower ≥ +10pp0.511no
RQ3-P1-latency−13.5ms [−52.1, +34.9]msCI upper ≤ 100ms0.511within budget

* RQ1-P1 rejects "AUC = 0.5" in the wrong direction (below chance), so it is not evidence of a leak. Survivors of the authoritative Holm-7: RQ1-P1, RQ2-P1 (shrink), RQ2-P3 (mix).

Visual abstract

Publication-ready SVG figures illustrating the instrument, the design, and each finding. All annotations are cross-checked against the sealed analysis records.

ISOLATED ENGINE (docker) — assert engine != local, or the run refuses · self-generated fixture traffic, lab-only Client seeds payload Hop 0 entry segment Hop 1 middle Hop 2 exit segment Fixture sink nested-SSH tunnels (R4) in-band consent (R5): Ed25519-signed request → verify before accept · X25519 per-hop credential sealed to host key 💾 pcap₀ 💾 pcap₁ 💾 pcap₂ Determinism & provenance (R1–R3): one --sor-seed → immutable manifest.json + SHA-256-sealed events.jsonl; every per-hop pcap written once and checksummed.
Figure 1. The instrument. A consent-gated, nested-SSH circuit: each hop must cryptographically accept a signed in-band request before it will carry the flow; per-hop credentials are X25519-sealed to the host key. Every forwarder runs in an isolated engine only. Entry (Hop 0) and exit (Hop 2) segments are the observable units RQ1 probes.
1-house-N House A all N nodes in one house bridge-federated House A House B Bridge shared observation point directory-federated A B C Dir- ectory no single shared hop
Figure 2. Federation topologies (RQ2), matched total node count N. The design isolates the topology effect, not a node-count artifact. RQ2-P1 compares the pooled federated arms against a single house of the same N.
0.40 0.50 0.60 0.80 1.00 chance 0.50 material 0.60 linked 1.00 measured 0.466 CI [0.452, 0.480] below chance → NO measurable entry↔exit leak; padding (RQ1-P2) has nothing to suppress
Figure 3. RQ1 — bridge linkability. The frozen correlator calibrates perfectly (linked 1.00 / unlinked 0.50) yet reads the bridge-on traffic at AUC 0.466 — distinguishable from chance but below it, which the pre-registered gate refuses to call a leak. An unexplained pooled-correlator artifact, explicitly not a padding effect (this is the no-pad arm).
ΔH = 0 0.0 −0.5 −1.0 ΔH = −0.96 bits CI [−1.06, −0.86] · Holm-significant Federation SHRINKS the anonymity set the opposite of RQ2's motivating hypothesis — reported with equal prominence, not re-framed as "federation helps". (Mechanism resolved in Fig 5.)
Figure 4. RQ2-P1 — anonymity-set effect of federation. Under the ratified adversary posterior, federating across houses reduces the per-circuit anonymity set by ~0.96 bits vs a matched-N single house — a genuine Holm-significant negative.
Lead as-instrumented: UNIQUE bridge / circuit Mechanism study: SHARED willing-bridge pool b1b2b3b4 every signature unique → set size 1 H ≈ 0 by construction B1B2 circuits SHARE a signature → sets grow H rises = MIX Dose-response (confirmatory, 13,500 circuits): H concentration → H1 Spearman ρ = +0.62 [+0.59, +0.65]  ·  H2 slope β = +0.71 [+0.62, +0.79] H3 joint → RESOLVED = MIX. Concentration ↑ ⇒ anonymity ↑, correcting the lead "shrink" as a unique-bridge artifact.
Figure 5. RQ2-P3 — the mix mechanism (headline correction). The lead topology assigned a fresh bridge per circuit, making every exit signature unique and driving H≈0 by injective construction — not by funnelling. Re-instrumented as a finite shared pool, concentration and entropy rise together (ρ +0.62): a shared bridge mixes. This qualifies the lead RQ2-P1 shrink without overwriting it. Disclosure: the frozen calibration dry-pass already previewed this direction (ρ 0→+0.838); the two-sided pre-commitment stands.
Throughput retention static random agent all ≈ 0.99 (ceiling) margin −0.6pp [−1.58,+0.39] · gate +10pp Added latency (agent) 0 0 ms budget 100 −13.5 ms [−52.1, +34.9] within budget (not slower) Rebuild fingerprint AUC 0.400.600.80 gate 0.60 AUC 0.587 [0.458, 0.703] CI crosses 0.60 → not excluded (n=30) Verdict: H0 on both counts — the local open-weight agent neither beats baselines nor is certifiably fingerprint-free on this grid.
Figure 6. RQ3 — churn-resilient agent selection (double null). At the pinned churn (kp30/steps20) every selector heals ~all drops, so there is no headroom for the +10pp gain; the agent is not slower (latency within budget) but the rebuild-timing classifier cannot be excluded at n=30. Both P1 and P2 are honest nulls.
Authoritative Holm-7 (frozen size-7 family) — adjusted p α=.05 00.300.60 RQ1-P1 leak survives · no leak RQ2-P1 federation survives · shrink RQ2-P3 mechanism survives · mix (corrects shrink) RQ1-P2 padding 0.365 RQ3-P2 fingerprint 0.511 RQ3-P1-perf 0.511 RQ3-P1-latency 0.511
Figure 7. Authoritative Holm-7. Over the frozen family of seven, three hypotheses survive at α=.05: RQ1-P1 (no leak), RQ2-P1 (shrink), and RQ2-P3 (mix). The RQ2-P3 slot carries the mechanism-corrected primary statistic, superseding the lead's degenerate as-instrumented test. This is the authoritative correction; the lead paper's conservative partial embedding remains valid and never under-corrects.
instrument / survives Holm mix / positive negative / gate null / does not survive client / house node

Lead paper — full text

Consent-Gated Federated Onion Routing: Linkability & Anonymity-Set Effects (G4 + RQ1 + RQ2) click to collapse
%%LEAD%%

Companion paper — full text

The Unique-Bridge / Mix Mechanism (RQ2-P3) and Churn-Resilient Agent Selection (RQ3) click to collapse
%%COMPANION%%

Provenance & integrity

Pre-registrations (frozen, hashed):
lead f22331a72e0d0ccf38b787e63acabbe9d666456ec76076787a6d545c3193425b
RQ2-P3 mechanism 8db4e8a7ac60f8b2861f2387249db68a3fd44822f6b3d9c7c6990ff65f261a3b

Sealed confirmatory records: lead 180 cells / 9,000 circuits (SHA256SUMS.txt); RQ2-P3 13,500 offline-deterministic bridged circuits (results 5fdcb379…); RQ3 4,500 live isolated-docker circuits (battery 5b61e461…, analysis e09c66ef…).

Discipline: detectors calibrated on fixtures and frozen before any confirmatory cell; effect size + BCa 95% CI for every test, p only orders the Holm step-down; Results filled once, post-seal; containment intact (isolated-engine only, self-generated fixtures, lab-only); worktree-only on feat/sor-consent-relay.

Note: this page is a presentation artifact generated from the committed paper drafts; the papers and sealed records are authoritative.

""" html = TEMPLATE.replace("%%LEAD%%", lead_html).replace("%%COMPANION%%", companion_html) OUT.write_text(html, encoding="utf-8") print(f"wrote {OUT} ({len(html):,} bytes)")