fleetd #721: gate fleet_status's pending-ask block by the delegation's creator terminal #723

Closed
agent wants to merge 0 commits from worker/721-70f9ea-5 into main
Member

Fixes fleetd #721.

fleet_status (MCP) and GET /sessions/{id}/status (REST) returned another session's pending fleet_ask question, its turnId and its ticket to any TASK_READ holder, with no check that the caller created that delegation.

  • MessageService.pendingAsk now takes callerTerminal and reuses the existing ownsTicket comparison (no new comparison, no convenience overload that forwards null).
  • FleetMcp.status and its statusHandler now thread the resolved callerTerminal(exchange) through.
  • FleetApp.sessionStatus now resolves ctx.attribute(CALLER) the same way taskStatus does and threads caller.terminal() through.
  • The base status line (and REST's ready field) is unchanged for every caller; only the pending-ask block (question/turnId/ticket) is gated.

Tests added (both surfaces, P1/P2/P3/P4 from the ticket, plus the #716-style "handler actually threads the terminal" scrape tests):

  • MessageServiceTest: pendingAskGatesTheQuestionByTheDelegationsCreatorTerminal, pendingAskDeniesATerminalBearingCallerWhenTheTaskRecordsNoCreator (plus the 5 pre-existing call sites updated for the new signature).
  • FleetMcpTest: statusGatesThePendingAskFieldsByTheDelegationsCreatorTerminal.
  • FleetMcpAuthzTest: theFleetStatusHandlerActuallyThreadsCallerTerminalIntoStatus.
  • FleetAppAuthTest: restStatusGatesThePendingAskFieldsByTheDelegationsCreatorTerminal, theSessionStatusRouteActuallyThreadsTheCallersTerminalIntoPendingAsk.

mvn clean install: 2026 tests, 0 failures, 0 errors, BUILD SUCCESS (main was at 2020; this adds 6).

Mutation proof (per surface, reverting the handler's threading of the caller terminal back to a literal null): mvn -o compile stayed green (confirming the mutation is a behavioral change, not a compile error), the corresponding new test(s) went red naming the right call site, and restoring produced a clean git diff on the touched production files.

Not in scope (per the ticket's honest-limit section): this closes only the read half of the hijack chain described in the ticket (an architect can no longer read another session's turnId via fleet_status). The write half (fleet_send{turnId} / answer() taking no caller identity) is fleetd #715 and is explicitly out of scope here.

Fixes fleetd #721. `fleet_status` (MCP) and `GET /sessions/{id}/status` (REST) returned another session's pending `fleet_ask` question, its `turnId` and its ticket to any `TASK_READ` holder, with no check that the caller created that delegation. - `MessageService.pendingAsk` now takes `callerTerminal` and reuses the existing `ownsTicket` comparison (no new comparison, no convenience overload that forwards `null`). - `FleetMcp.status` and its `statusHandler` now thread the resolved `callerTerminal(exchange)` through. - `FleetApp.sessionStatus` now resolves `ctx.attribute(CALLER)` the same way `taskStatus` does and threads `caller.terminal()` through. - The base status line (and REST's `ready` field) is unchanged for every caller; only the pending-ask block (question/turnId/ticket) is gated. Tests added (both surfaces, P1/P2/P3/P4 from the ticket, plus the #716-style "handler actually threads the terminal" scrape tests): - `MessageServiceTest`: `pendingAskGatesTheQuestionByTheDelegationsCreatorTerminal`, `pendingAskDeniesATerminalBearingCallerWhenTheTaskRecordsNoCreator` (plus the 5 pre-existing call sites updated for the new signature). - `FleetMcpTest`: `statusGatesThePendingAskFieldsByTheDelegationsCreatorTerminal`. - `FleetMcpAuthzTest`: `theFleetStatusHandlerActuallyThreadsCallerTerminalIntoStatus`. - `FleetAppAuthTest`: `restStatusGatesThePendingAskFieldsByTheDelegationsCreatorTerminal`, `theSessionStatusRouteActuallyThreadsTheCallersTerminalIntoPendingAsk`. `mvn clean install`: **2026** tests, 0 failures, 0 errors, BUILD SUCCESS (main was at 2020; this adds 6). Mutation proof (per surface, reverting the handler's threading of the caller terminal back to a literal `null`): `mvn -o compile` stayed green (confirming the mutation is a behavioral change, not a compile error), the corresponding new test(s) went red naming the right call site, and restoring produced a clean `git diff` on the touched production files. Not in scope (per the ticket's honest-limit section): this closes only the *read* half of the hijack chain described in the ticket (an architect can no longer read another session's `turnId` via `fleet_status`). The *write* half (`fleet_send{turnId}` / `answer()` taking no caller identity) is fleetd #715 and is explicitly out of scope here.
agent added 1 commit 2026-10-04 08:47:02 +02:00
fleetd #721: gate fleet_status's pending-ask block by the delegation's creator terminal
CI / shell-tests (pull_request) Failing after 9s
CI / contract (pull_request) Successful in 49s
CI / build (pull_request) Failing after 1m55s
0f5985b419
fleet_status (MCP) and GET /sessions/{id}/status (REST) handed any TASK_READ
holder another session's open fleet_ask question, its turnId and its ticket,
with no check that the caller created that delegation. MessageService.pendingAsk
now takes the caller's terminal and reuses the existing ownsTicket comparison;
FleetMcp.status and FleetApp.sessionStatus both thread the resolved caller
terminal through. The base status line and REST's ready field are unaffected.
ltms closed this pull request 2026-10-04 08:54:38 +02:00
Some checks are pending
CI / shell-tests (pull_request) Failing after 9s
CI / contract (pull_request) Successful in 49s
CI / build (pull_request) Failing after 1m55s

Pull request closed

Sign in to join this conversation.