host/taint: pin the role-receiver mutation; doc fixes; document the unbounded-buffer limit (Codex round 5)

Round 5 convergence check. Codex confirmed F1(broad rule)/F2(doc)/
link-group fingerprint complete, and raised three more:

- P2 (fixed): a mutation deleting the *role-based* receiver insertion
  survived all 55 tests — every tested bridge source also had an inbound
  link. A pixelpass capture sink is a taint root before anything links
  into it, and its re-emitting sibling must bridge from it on role alone.
  Added `a_local_root_receiver_bridges_without_an_inbound_link`; mutation
  now killed.
- P3 (fixed): doc drift. The backstop's preamble still described the old
  "targets must be unbounded / apps never swept" rule; rewritten to the
  two-tier trigger/sweep. The `session_device` factory guidance now says
  explicit allowlist, not "and the like".
- P1 (dispositioned as a documented v1 limitation, not fixed): a buffered
  echo across a *full* teardown of an *unbounded* reader. Grounds, in the
  module docs: (1) it needs a stream exposing no PID/module-id/link-group,
  which is malformed/identity-hiding and outside v3.4 §2's non-adversarial
  threat model; (2) it contradicts the design's explicit "reappears after
  full teardown ⇒ new owner, starts clean" (§6.1.3), so closing it is a
  design change; (3) the only closed-form fix is a whole-share hammer
  (one keyless stream ⇒ desktop unshareable for the share). Reachable
  cases — a reader live now — are already covered by the backstop.
  Owed to the design doc as a round-8 note.

56 tests. Taking the P1 disposition to Codex for ratification, then to
the user as a design decision.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-21 18:06:45 -04:00
co-authored by Claude Opus 4.8
parent 2183084ec8
commit 65fde92628
3 changed files with 80 additions and 17 deletions
+24
View File
@@ -1721,3 +1721,27 @@ fn a_link_group_new_connection_of_a_still_tainted_owner_inherits_the_taint() {
],
);
}
#[test]
fn a_local_root_receiver_bridges_without_an_inbound_link() {
// Round 5 finding 2: a mutation deleting the *role-based* receiver
// insertion survived all 55 tests, because every tested bridge source
// also had an inbound Link that put it in `receivers` anyway. A
// pixelpass capture sink is a taint root the moment it exists — before
// anything links into it — and its owner's re-emitting leg must bridge
// from it on the strength of its role alone.
let mut graph = Graph::new();
// A capture sink (PixelpassOwned by name), sharing module id 55 with a
// re-emitting output leg, and NO inbound link yet.
let sink = graph.module_node("pixelpass_capture_4242", MediaRole::Sink, 55);
let leg = graph.module_node("capture-reemit", MediaRole::StreamOutput, 55);
let firefox = graph.app_node("firefox", MediaRole::StreamOutput, 11114);
let decisions = run(&graph, &ctx());
assert_partition(
&decisions,
&[("firefox", firefox)],
&[("leg", leg, "tainted-owner-bridge")],
);
assert_tainted(&decisions, sink, "pixelpass-owned");
}