feat(service): the Mac's commands are sealed for following over Neon Realtime, claimed by id
Merged
CH
10d ago+551+551+012345678901234567890123456789-13-13-01234567890123456789
Stack 4 · Mac commands, on #4228 (luke/live-same-user). The service side of following the Mac's commands through the live layer: Neon Realtime where LUKE_REALTIME=on, and the held poll (#4272) everywhere else. It replaces the always-on held read of GET /api/mac-commands.
The held read does three jobs: it marks the Mac as listening, waits for commands, and claims them. A live read writes nothing, so each job gets its own procedure, on #4273's kinds:
live.macCommands(GET /api/live/mac-commands?kinds=): the commands of the named kinds that no Mac of the account has claimed, as one statement (macCommandsLiveStatement:user_id = $1 AND kind IN (…) AND claimed_at IS NULL, no clock window). It goes throughsealedPartsand is checked bysameUserlike every live read. The reader sorts the rows (macCommandsOfLiveRows, earliest queued first, a shell row's text or a browser row'sparams).macCommands.claim(POST /api/mac-commands/claim {id}): claims one command by id. TheCLAIM_WINDOWis enforced here, on the service's clock. It answers with the command ornot-found. Bearer only.macCommands.listening(POST /api/mac-commands/listening {kinds}):markMacListeningfor the named kinds. Bearer only.
The held GET /api/mac-commands and the result routes are unchanged for released desktops.
Tests:
mac-command-store.test.ts: the live statement delivers only the account's own commands of the named kinds, and a claim by id takes a command once, for its own account, inside the window.mac-commands-procedures.test.ts: claim and listening, byte for byte. A cookie is refused.live-procedures.test.ts: the read is sealed for the bearer and the named kinds, and a read naming another account gets 401.live-statements.test.ts:mac.commandscalls only immutable functions, and Neon's drizzleAdapter seals it.mac-command-client.test.ts:livenames the kinds and the user (a 401 means signed out), andclaim.
Checked piece by piece: tsc for features, service and database; vitest over features, service live, mac-commands and the store; knip; oxlint.