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:
@@ -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");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user