docs: record F11-1 closed — boundedness needs a resolved Client

Design v3.7 §6.1.1 gains the round-13 box (the rule, the ordering that is
load-bearing in both directions, and why bridging deliberately still uses the
full union); the phase-5 results file records the close with the measurement
the deferral was waiting for; the impl plan's phase-6 gate note drops F11-1.

pixelpass c78eb2d is the implementation.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-26 04:46:25 -04:00
co-authored by Claude Opus 5
parent bf908adbf0
commit 692ad677d2
3 changed files with 62 additions and 20 deletions
+25 -1
View File
@@ -581,6 +581,30 @@ Where an owner has a tainted input leg and an output leg with **no** resolvable
(§6.1.2), fail closed and exclude the output leg. This only ever engages for owners
actually reading a tainted monitor, so the blast radius is small.
> **⚠️ Round 13 (F11-1) — "bounded" is not "has a key". A self-claimed pid is not
> provenance.** Which legs this backstop sweeps depends on whether the tainted reader and
> the candidate outputs are *bounded* — i.e. whether we could enumerate their sibling legs
> and be right. Key 4 is a union of the node's `application.process.id` (client-controlled,
> optional) and its Client's `pipewire.sec.pid` (protected), so a node could bound itself
> with a value it invented and escape the sweep while its real sibling was unfindable.
>
> **Rule:** a strong key (`node.link-group`, `pulse.module.id`) bounds an owner on its own;
> key 4 bounds an owner **only when the node's Client resolves** — an unambiguous Client
> yielding `Some(pipewire.sec.pid)`, read *before* pipewire-pulse suppression. The
> ordering is load-bearing in both directions: read after suppression and every
> Pulse-emulated app on the box goes unbounded (§6.1.1 catastrophe, new door); accept "a
> unique Client object exists" instead of a `sec_pid` and a pid-less Client leaves the hole
> open.
>
> **Bridging is unchanged** — it still uses the full union, because a self-claimed pid is
> perfectly good *evidence that two legs are related*, which is the taint-increasing
> direction. Only the permission to declare a differently-keyed output "provably someone
> else" now demands a `pipewire.*` answer to "who is this".
>
> Measured cost on this host: **zero** — before/after binaries audited the same live graph
> simultaneously, same 14 decision states, no `unresolved-owner` on either side, eligible
> half non-empty. Implemented in pixelpass `c78eb2d`; five-case Client matrix in the tests.
### 6.1.3 ⚠️ Taint must be STICKY — current topology is not enough
**Conceded to Codex in round 6; my "conditional bridge" was correct about topology and
@@ -1198,7 +1222,7 @@ requirement to assert what must remain **eligible**: §6.1.2's pulse-PID derivat
| §5.1 matrix | **PASSED** — 13/13, incl. the full sticky lifecycle (row 10) and provable identifier recycling (row 11) |
| O5 | **closed on the real graph** — worst recompute 67 µs, churn mean 10 µs, busy fraction 0.0006 |
| Phase 5 | **machinery unchanged and correct** — three real defects caught on first contact with the live graph, none of them in the engine |
| Phase 6 | **still blocked** — by F11-1, phases 0b/0c/0d, and the "Stereo Mix" design call, *not* by this matrix |
| Phase 6 | **still blocked** — by F11-1, phases 0b/0c/0d, and the "Stereo Mix" design call, *not* by this matrix. (F11-1 was **closed later the same day** with this matrix's data — §6.1.2's round-13 box; the rest stand.) |
Three rows passed with recorded substitutions (8 EasyEffects, 9 Firefox's own mic/monitor
paths, 13 a real `Audio/Duplex` device) and the third-party samples stay owed.