Repository navigation
refactor(runtime): paired sockets authenticate to a device principal - #27480
Conversation
|
Important Review skippedReview was skipped as selected files did not have any reviewable changes. ⚙️ Run configuration
📥 Commits
You can disable this status message by setting the Use the checkbox below for a quick retry:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
📝 Walkthrough
Priority: ➖ Normal Merge Risk: ⚪ Minimal · up to This PR changes paired-socket identity, and the reviewed mobile test fixture now supplies the corresponding principal and token. No concrete user-impacting failure is established, so the remaining merge risk is minimal. Pre-merge checks |
|
2af1165 to
0e73592
Compare
|
Review (P0/P1 only): codex reviewer was unavailable (orchestration consumer_fenced, retried) so an Opus reviewer ran instead — No P0/P1 findings (14-item coverage log: disconnect cleanup keys, revoke targeting across ws/relay transports, delegated children, per-request re-resolution, registry downgrade). Own review: no P0/P1; two nits fixed (formatting, stale comment). One CI failure (mobile launch-authority test fixture lacked the principal) fixed in-PR. |
ELI5
Inside the desktop, a connected phone or paired computer is now tracked by its device ID, not by its secret pairing code. Nothing changes for users. This is the groundwork that later lets a device sign in with a key instead of a reusable code.
What Changed
Before: the host used one string, the device's pairing token, as its identity everywhere:
validateToken(token)on every request);sha256(token)).After: an authenticated socket carries a
DevicePrincipal:{ deviceId, scope, clientId, callerFingerprint, credentialRevision }, built once from the registry row at auth time.terminateDeviceConnections, the other-live-sockets check on close) is keyed bydeviceId. Revoke paths pass the device id.(deviceId, credentialRevision)(plus the token for token rows). A revoke, or any later credential change that bumps the revision, refuses the socket's next request.DeviceEntrygains two optional top-level fields,credentialRevisionandcallerFingerprint. Rows written today never set them, the loader validates them, and an older build's loader keeps them (it spreads unknown fields).fingerprintAuthenticatedPairingCredentialmoved intodevice-principal.ts; the formula is unchanged.Deliberately unchanged for token rows:
clientId, the key for per-client runtime state such as terminal drivers, dictation and file grants, is still the token. The caller fingerprint is stillsha256(token). Shipped phones stamp their token into terminalclient.id,mobileClient.idand subscription ids, so keeping it avoids rewriting request params for old phones. Rows without a token (device keys, in a later PR) will use their id.Why
The pairing token currently does four jobs at once: secret, credential, identity and authority. Device-key sign-in cannot ship while identity is the secret. Splitting identity first, with no wire change, keeps the later credential PR small. Binding sockets to a revision gives that PR a way to fence sockets authenticated under an old credential.
Alternative considered: rewrite
params.client.idto the device id for every paired caller. Rejected for now. Desktop runtime clients use distinct per-paneclient.ids that must not be merged, and old phones embed the token in several params besidesclient.id. Keeping the token as the client id for token rows is behavior-identical.Linked Issue
Part of #17394 / #17398 (groundwork; no issue closes here)
Visual Proof
N/A: no UI or wire change.
Testing
New
src/main/runtime/device-principal.test.ts:resolveAuthenticatedPrincipalrefuses a removed row, a revision mismatch and a token mismatch;clientIdand an unchanged fingerprint, and is refused once the row's revision changes.mobile-socket-wiring.test.ts: the transport client id is now the device id; new case for two live sockets of one device (hasOtherConnections).Fixtures building
E2EEAuthenticatedDeviceupdated for the new required principal fields.pnpm tc,pnpm test src/main/runtime, oxlint,check:code-quality:changed.I manually tested these changes locally
Automated tests added/updated, or explained why not below
Review
Agent skill upstream boundary
Notes
Checklist
N/Awith reasonpnpm lint,pnpm typecheck,pnpm test, andpnpm buildpass (or CI will cover; local preferred)