Cloud: read current chat-start grant without opening another VM link (W2-15)
W2-15 — backend prerequisite for delegated-chat revocation
Tracks HQ #5944 W2-15 and the source-backed finding on team-machine owner issue #5353. Classic backend owner prior art: merged #29217. Draft / no production deployment or merge requested.
Why
A teammate's NEXT Mac link keeps its attach-time vmKind: owner after the creator deletes their chat grant. App code needs a current authorization answer before attempting another delegated chat start. Reusing POST /api/vm/:id/attach-endpoint to check that permission is wrong: the attach path can wake a VM, provision an endpoint, write a lease and record an attach event.
Change
GET /api/vm/:id/chat-start-accesson the existing authenticated, billing/team-scoped classic VM route. Response:{"chatStart":"owner"|"granted"|"none"}for the requesting person only, withCache-Control: no-store.- Rechecks current team members via the bounded Stack directory read and the persisted grant via the existing repository method. Creator's personal VM: owner; creator's team VM: owner only while a member; granted teammate: granted only while still a member. Removed member or revoked grant: none. Missing or timed-out checks: retryable 503, never authorization.
- Does not call provider attach, pause/resume, mint a token, create a lease, or emit usage/billing mutations.
- Focused deterministic service tests for owner, current grant, revoke, departed member, admin without grant, unavailable team directory and unavailable grant store.
Review and deployment order
- Verify handler authentication, source team scope, strict no-store response and focused tests. Local full web test dependencies were unavailable in this chat; CI is the requested executable proof.
- Land/deploy this read-only endpoint before the dependent NEXT Mac change, so new clients never make a preflight request to a missing route.
- Verify two-person revoke during a still-connected link. This is client-side defense in depth, with a remaining short check-to-daemon-start race. Strong immediate revocation still needs a revocable capability verified by the remote daemon for every privileged start (separate authorization design/review). A machine shell grant remains broader than an app chat-start grant.
No cross-owner branches modified, no migrations, no permission expansion, no VM activity or production changes.
![View with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v3-3x.png)
![Autofix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark-3x.png)
Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
Adds a read-only GET /api/vm/:id/chat-start-access endpoint so the Cloud app can check current chat-start authority before delegating another chat start, instead of trusting the stale attach-time owner label on an existing link.
- Returns
owner,granted, ornonefor the requesting user only, withCache-Control: no-store. - Rechecks current team membership and the persisted grant; revoked grants and departed members resolve to
none. - Does not wake the VM, create an endpoint or lease, or emit usage or billing events.
- Unavailable team directory or grant store returns a retryable 503, never an authorization decision.
- Land and deploy before the dependent NEXT Mac change so new clients never preflight a missing route.
- Client-side defense in depth only; closing the remaining check-to-daemon race needs server-enforced revocable capabilities.