Skip to content

fix(daemon): status.get shows an agent only its own leases and queue entries - #893

Draft
V3RON wants to merge 6 commits into
security/data-dir-modefrom
security/status-own-leases
Draft

V3RON wants to merge 6 commits into
security/data-dir-modefrom
security/status-own-leases

Conversation

@V3RON

@V3RON V3RON commented Oct 22, 2026

Copy link
Copy Markdown
Contributor

Summary

status.get is an agent operation, and it returned every lease and every waiting request to any agent token, with other principals' lease ids, device ids and requester ids. Now a non-admin session sees only the leases its principal owns and only the waiting requests it owns, the same rule lease.list already used. Admin sessions see everything, as before. That covers the local CLI (admin.token), operator tokens, the console, and the gateway's uplink to a worker, which the worker accepts as admin.

Changes

  • src/daemon/dispatcher.ts: lease.list and status.get share one owner filter (#leasesFor). status.get's waiting keeps only the requests whose recorded owner (queue.pendingRequestOwner) is the session principal.
  • src/gateway/dispatcher.ts: for a non-admin session, status.get's leases comes from #ownedFleetLeases (the lease-index lookup lease.list uses, so a worker's own local lease never matches), and waiting is filtered by coordinator.pendingRequestOwner. devices, capacity, workers, queueDepth and the other fields are unchanged.
  • src/http/route-declarations.ts: the GET /v1/status OpenAPI notes say an agent token sees only its own leases and waiting.
  • Website: remote-agents.mdx (new GET /v1/status row under "More calls"), reference/cli.mdx (simlock status), lease-lifecycle.mdx ("See what you hold"), gateway/access-control.mdx (the agent role row).
  • Manuals: src/daemon/AGENTS.md (dispatch step 4) and src/gateway/AGENTS.md ("Reads").
  • No contract shape change, so no protocol bump.

Tests

  • src/daemon/dispatcher.test.ts: a new table test. Admin sees both leases and both waiting requests. An agent with a lease and a waiting request sees only those. A proxy-style principal whose request waits under another requester id sees that request. An agent that owns nothing gets empty arrays, not an error. The existing "status.get waiting matches list.get requests" test now reads status as admin.
  • src/gateway/dispatcher.test.ts: the same table over gateway-issued leases, a worker's local lease, and fleet-queue requests.
  • Both new tests failed on their toEqual before the fix.
  • pnpm test:changed: 1781/1782 passed. The failing test was a different timing test on each of three runs (device.exec chunking against a real process, usage.get and a CLI startup timeout), at load average ~27; each passes when its file is run alone (src/daemon/dispatcher.test.ts 190/190, src/cli/index.test.ts 375/375).
  • Website build and check-openapi.mjs: ok (30 operations).
  • pnpm test:console --project=chromium: 208 passed; 1 failed, actions.spec.ts "a worker is drained from Fleet with no dialog, and Undo undrains it", which is the known flaky test Console e2e: a worker is drained from Fleet with no dialog, and Undo undrains it fails on the row's drained text #886.

Assumptions

  • Assumption: a gateway agent's waiting lists only fleet-queue requests it owns. That list already held only the gateway's own queue, not workers' queues.
  • Assumption: the GET /v1/status OpenAPI notes count as the HTTP API reference page, because that page is generated from the route declaration.

Written by an agent.

V3RON added 2 commits October 22, 2026 17:16
…entries

An agent token's status.get listed every lease and every waiting request,
with other principals' requester ids. Both dispatchers now filter leases
and waiting the way lease.list already does; admin sessions see all.
@V3RON

V3RON commented Oct 22, 2026

Copy link
Copy Markdown
Contributor Author

Review (maintainer's agent, round 1)

No blocking findings.

  • The worker dispatcher now has one owner filter for lease.list and status.get, so the two cannot drift apart again. Waiting entries are filtered through the queue's recorded owner of the requester, which is the right source since a waiting entry carries no owner field and requesterId is caller-supplied.
  • The gateway path reuses the lease-index lookup lease.list already used, so a worker-local lease whose owner happens to share the caller's name is never shown; the table test pins exactly that case.
  • Nothing in src/contract/ changed, so no protocol bump; the route notes line feeds the generated HTTP reference, and the four website pages that describe agent status output now say the same thing.
  • Switching the existing "waiting matches list.get" test to an admin session is correct: it was asserting fleet-wide content through a caller that owns none of it.

Note, no change needed: the three one-off unit failures across the test:changed runs were different timing tests each time under a load average of about 27 (seven agents building in parallel on this machine) and pass alone; CI on the PR is the arbiter.

@V3RON
V3RON changed the base branch from main to security/data-dir-mode October 23, 2026 06:19
@V3RON
V3RON added this pull request to stack #897 October 23, 2026 06:19

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant