← Commit history

docs: 0.6.5–0.6.7 — lineage window, re-attribution root cause (first-match walk) and equality binding to the COM-attached process; 20 adversary passes

Drew Owens ·3f3064ebc5 ·1mo ago ·parent 0eade07
1 file changed +43−1
README.md+43−1
@@ -347,7 +347,49 @@ not.  ## Roadmap -- v0.6.4 (this): **the same mistake one route further down, and a window around+- v0.6.7 (this): **ordering is not equality — a consent-affecting bug I shipped+  in 0.6.6.** That release fixed the walk to try every `sldworks.exe`, and used+  the COM-attached pid only to ORDER the candidates, taking the first that+  descended. With two SOLIDWORKS running it could therefore prove lineage for our+  launcher's child while COM was attached to a DIFFERENT process, and then label+  the session `attributed:true`. Everything downstream reads that label — the quit+  gate's bridge-launched proof, and a quit ladder that builds its Identity from the+  COM pid — so the bridge would have been willing to END a session nothing had+  proved was ours. Re-attribution now succeeds ONLY when the process that descends+  IS the attached one (pid and creation time), refusing `attached_pid_not_ours`+  otherwise; the evidence names the proved pid, its creation time, the parent it+  came from and that it equals the attached pid; the ledger lists every candidate+  with its own clause instead of "the last one stands"; and the verbs that END a+  session now refuse `identity_mismatch` if the launch's recorded claim is about a+  different process than the one COM answers for. 296 tests.+- v0.6.6: **the lineage walk took the first SOLIDWORKS in the census, and+  it had no parent.** Re-attribution had been unreachable since 0.6.0 and three+  passes failed to find out why from outside, because it refused silently. So the+  diagnostic came first: every `return None` on that path now names its clause,+  reported as `reattributionRefusedBecause` and ledgered. The positive case then+  answered in one word — `no_parent_recorded`. `census.iter().find(is SLDWORKS)`+  took whichever process the census listed first; that one had no `ppid`, the walk+  ended there, and a second sldworks.exe further down the list — descended from our+  own launcher — was never examined. It is the same defect `host_app_health` was+  rewritten for in 0.4.x ("EVERY sldworks.exe, not just the first"), reappearing in+  a walk written two years later. Now every sldworks.exe is tried, the one COM is+  attached to first. Also: the mock's `status` consults the simulator the way a+  real `GetActiveObject` consults the machine, so a session that comes up while+  nobody is calling `swx_start` — a user finishing a sign-in, which is the entire+  case this feature exists for — is visible to `swx_status` alone. 292 tests.+- v0.6.5: **a real child is created while its parent runs.** The lineage+  window was a flat 30 seconds — three census intervals of invented slack, and+  slack in an identity rule is the space a recycled pid lives in. It is now the+  census interval itself, which is the only reason the window is not zero: our+  knowledge of "while it ran" is a poll, so a child born in the gap between two+  censuses was still born while the parent ran. The simulator can finally express+  PID REUSE (`census-overrides.json` retires a pid and reissues it with a new+  creation time), which nothing before it could pose. And re-attribution being+  possible only for an ATTRIBUTED route is now written down as a rule and pinned:+  `explorer` and `cmdStart` cannot say what they started, so there is no identity+  to walk a parent back to, and a session that came up after one of them is not+  claimed however plausible it looks. 290 tests.+- v0.6.4: **the same mistake one route further down, and a window around   lineage.** 0.6.3 stopped the bridge calling its ATTRIBUTED launcher foreign;   pass 16 found it still doing so for the routes that cannot name what they   started. `explorer` and `cmdStart` have no attribution root, so their root and