fix(daemon): scope a transient device claim to the session that holds it

Merged
TH
1d ago
+985-103

Summary

Closes #3345. Another session’s install or reinstall refuses while a session owns the device. Acquisition requires the recorded claim kind to match the acquirer, including its transient command. Legacy kindless records remain fences and cannot donate ownership tokens. Owning-session operations remain valid.

Example: open Lab --session a; install app.apk --session b returns DEVICE_IN_USE, reason DEVICE_CLAIM_LIVE_OWNER, owner a; reinstall Lab app.apk --session a succeeds. The common acquisition boundary, admission, records, tests, help and docs span 18 files.

Validation

Head 00e495278e, base a61556b8: direct pnpm check:affected --run --head 00e495278ec3b3d2b1af932902b8edba115078f1 passed with exactCommit: true, unchanged clean fingerprints, 10 executed checks, seven documented skips and 2,333 passing related tests. Receipt: .tmp/validation/run-v6Vzc8/receipt.json.

Raw daemon/CLI proof covers foreign refusals, owner reinstall, close and no remaining claim. Author audit corrects provenance and the initial wrong test expectation; final settlement tests pass 15/15. Independent review found no blocking issues, with bound-checkout mutation limitations; both checkouts are restored clean.

Maintainer accepts the fix; readiness label is present. Current-head iOS CI failed public-CLI preflight with a 15-second daemon startup timeout and empty daemon log. Cause and branch participation remain unproven. Other checks passed. The requested retry has not run: campaign policy requires proven infrastructure failure. #3782 tracks the startup class.