Skip to content

fix(daemon): let an installed version stand as its whole code identity - #2569

Merged
thymikee merged 2 commits into
mainfrom
t3code/fix-2458-quality-refactor
Sep 14, 2026
Merged

thymikee merged 2 commits into
mainfrom
t3code/fix-2458-quality-refactor

Conversation

@thymikee

@thymikee thymikee commented Sep 13, 2026 •

Copy link
Copy Markdown
Member

Summary

Two installs of one published version signed their identical bytes differently: the fingerprint is size:mtime, and an installer stamps a fresh mtime on every file. The second client read code-signature mismatch, replaced a daemon already running exactly its code, and dropped the live session on it.

The bypass is pairwise, not one-sided. A running daemon now publishes codeOrigin: 'installed' | 'checkout' beside its signature, and a client declines the comparison only where both sides are installs of the version they report — the only pair whose shared version already fixes the bytes both run. Every other pair is judged: checkout against checkout by signature as before, and a pair whose trees cannot match at all restarts the daemon rather than run code it cannot identify. A daemon too old to carry the field is judged by its signature, so nothing is trusted by silence.

Users see Replacing daemon disappear between two installs of one version; security-trust.md states what remains undetected (an install hand-patched under its own version).

16 files, +498/-68 across two commits, one command family.

Validation

Commit edff9074af.

  • pnpm check:quick, check:layering, check:package, check:production-exports pass. The packaging assertion proves a clean install ships no src/daemon.ts.
  • pnpm gate vitest-related <changed files>: 4228 passed; the one failure is the known runner-client.test.ts subprocess contention timeout (50/50 in isolation).
  • Field evidence, two clean installs of one packed version sharing --state-dir: install B reuses A's daemon pid silently; a checkout client against the installed daemon prints code origin mismatch (daemon installed, client checkout); an installed client against a checkout daemon prints code origin mismatch (daemon checkout, client installed).
  • Regression proof: the one-sided bypass fails the two installed-client cases; a naive info.codeSignature !== await ... compare fails the Same published version installed twice replaces the daemon and drops the live session #2458 reuse case.

Unresolved: mutation-model fails at merge-base ab3d11e069 too (gestures.test.ts no longer reaches scroll-edge-state) — advisory-only per #1457, and its workflow is path-filtered away from this diff.

Two installs of one published version signed their identical bytes
differently, because the fingerprint is size:mtime and an installer stamps a
fresh mtime on every file. The second client therefore read "code-signature
mismatch" and replaced a daemon that already ran exactly its code, dropping
the live session on it (#2458).

An installed tree's version already fixes its bytes, so it now answers with
no fingerprint and the version alone decides reuse. A source checkout, where
code does move under an unchanged version, keeps the check. The predicate
that tells the two trees apart moves beside the project-root walk it shares,
and the takeover ladder moves beside the answer it consumes so the order
lives in one place.

The packaging gate proves the premise against a clean install: the published
tree ships no src/daemon.ts.

Closes #2458
@github-actions

github-actions Bot commented Sep 13, 2026 •

Copy link
Copy Markdown
Contributor
PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-09-14 12:41 UTC

@github-actions

github-actions Bot commented Sep 13, 2026 •

Copy link
Copy Markdown
Contributor

Size Report

Metric Base Current Diff
Installed (including dependencies) 4.52 MB 4.52 MB +699 B
Package (unpacked) 4.52 MB 4.52 MB +699 B
Package (download) 1.33 MB 1.33 MB +197 B

Startup median (7 runs, lower is better):

Scenario Base Current Diff
CLI --version 28.3 ms 29.8 ms +1.5 ms
CLI --help 78.3 ms 79.2 ms +0.9 ms

@thymikee

Copy link
Copy Markdown
Member Author

The signature bypass at daemon-launch-spec.ts:113 only checks the client. With an explicit shared --state-dir, a modified source checkout can start a daemon under the published version, and an installed client now reuses that modified code. #2458 scopes the bypass to both sides being installed. Record the daemon’s code origin or equivalent package identity and bypass fingerprints only for two matching installed versions; add the source-daemon → installed-client case. Checks are green, but this remains a code blocker at 5fef822.

An installed client declined the code comparison on the strength of its own tree
alone, which left whatever is already running unverified: a source checkout that
shares an explicit --state-dir can publish any code it likes under a published
version string, and the installed client would have run it (#2458 review).

A daemon now records which tree it started from beside its signature, and the
bypass is pairwise — it holds only where both sides say they are installs of that
version. A checkout still judges a checkout by signature; a pair whose trees
cannot match at all restarts the daemon rather than run code it cannot identify,
which is also the rule a daemon too old to report an origin is judged by.

Closes #2458
@thymikee

Copy link
Copy Markdown
Member Author

Fixed in edff9074af. The bypass is pairwise now, and the daemon says what it is.

A running daemon publishes codeOrigin: 'installed' | 'checkout' beside its signature (server-lifecycle.ts, from resolveDaemonCodeOrigin() in @agent-device/host-kit/code-signature), and resolveCodeIdentityMismatch in daemon-launch-spec.ts:150 holds the bypass only where both sides report installed. A checkout still judges a checkout by signature; a pair whose trees cannot match at all restarts the daemon instead of running code it cannot identify — which is also the rule a daemon too old to carry the field is judged by, so no published daemon is trusted by silence.

Proof against two clean installs of one packed version, one shared --state-dir:

installed A -> installed B (dist mtimes shifted)   reuses pid 38232, stderr empty
checkout client -> installed daemon               code origin mismatch (daemon installed, client checkout)
installed B -> checkout daemon                    code origin mismatch (daemon checkout, client installed)

The third line is the case you flagged. Two tests pin it (daemon-launch-spec.test.ts), and restoring the one-sided bypass fails exactly those two. daemon-client-metadata.test.ts is the new mirror for the round trip through daemon.json, including a value no writer produces.

Local: check:quick, check:layering, check:package, check:production-exports green; gate vitest-related 4228 passed with the known runner-client.test.ts contention timeout (50/50 in isolation).

@thymikee

Copy link
Copy Markdown
Member Author

The previous blocker is fixed at edff907: fingerprint bypass now requires both client and daemon to be installed copies of the same version. The origin round trip, cross-origin rejection tests, and reported two-install field checks cover the failure case. Review is clean, all checks pass, and there are no merge conflicts.

@thymikee thymikee added the ready-for-human Valid work that needs human implementation, judgment, or maintainer merge label Sep 14, 2026
@thymikee
thymikee merged commit 0a47c4e into main Sep 14, 2026
20 checks passed
@thymikee
thymikee deleted the t3code/fix-2458-quality-refactor branch September 14, 2026 12:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-human Valid work that needs human implementation, judgment, or maintainer merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant