Repository navigation
Closed
Labels
area/infraInfrastructure, deployment, and operationsInfrastructure, deployment, and operationseffort/mMedium: expected under 1 day of workMedium: expected under 1 day of workkind/enhancementmeta/enrichedIntake review done: acceptance criteria, links, and normalized labels addedIntake review done: acceptance criteria, links, and normalized labels addedpriority/normalOrdinary priority (the default)Ordinary priority (the default)status/needs-triageNot yet triaged; needs a first lookNot yet triaged; needs a first look
Description
Part of epic #5412. Design of record: #5425 (§6, §7 step 4 — "Dispatch (thin)"). Predecessor: step 3 (proxy domains). Gate: the thin verbs round-trip against the live pm-stack interfaces with pm-stack itself untouched.
Scope
fleet-dispatch: a thin client domain over pm-stack dispatch's existing interfaces (D6). "Dispatch" today is the pm-stack TypeScript/Bun service suite in this repo (its own systemd units, SOPS-rendered state) plus the hatch-personal steward cron gating it — it is not CLI-shaped, and wholesale absorption would be a rewrite. This step adds client verbs only.- pm-stack is not rewritten, rehomed, or re-platformed by this epic. Any interface gap found while building the verbs is filed as its own issue against pm-stack, not absorbed here.
- The steward cron's call sites move to the fleet verbs only if they want them — no cron is rewritten by this epic (§7 step 4).
- Dispatch appears in the registry /
--help/capabilitiessurface like every domain, and is absent where the §2 matrix says so (fleet-connect stubs it at 69; fleet-serve carries no dispatch client surface).
Gate
- The agreed verb set round-trips against the live dispatch interfaces from the full
fleetbuild, with evidence on this issue. - pm-stack diff attributable to this step: zero.
Acceptance criteria
- dispatch thin-client domain runs over pm-stack as described.
- No regression: existing tests/checks for the touched area remain green, and the change lands via PR referencing this issue.
- Evidence (PR link, test/CI output, or verification note) is posted on this issue before it is closed.
Metadata
Metadata
Assignees
Labels
area/infraInfrastructure, deployment, and operationsInfrastructure, deployment, and operationseffort/mMedium: expected under 1 day of workMedium: expected under 1 day of workkind/enhancementmeta/enrichedIntake review done: acceptance criteria, links, and normalized labels addedIntake review done: acceptance criteria, links, and normalized labels addedpriority/normalOrdinary priority (the default)Ordinary priority (the default)status/needs-triageNot yet triaged; needs a first lookNot yet triaged; needs a first look
Activity
dezren39 commentedon Nov 4, 2026
Intake review
🤖 Agent note · state: filed
Related: epic #5412 and steps #5429-#5433 form one set; #5413 is a sibling absorption task.
Notes: Newly filed this morning with no priority label and no acceptance-criteria section; both now supplied.
Risks: Sequencing: steps are gated in order (notably #5433 on the #5350 step 6 cutover); starting out of order risks rework.
Suggested approach: Triage through the queue in dependency order, one step per task, verifying each step's acceptance evidence before closing.
fleet step 4 (#5432): the dispatch thin client — status, launch, enqu…
fleet step 4 (#5432): the dispatch thin client — status, launch, enqu…
Merge pull request #5551 from developing-today/fleet-step4-dispatch
developing-today commentedon Nov 4, 2026
Step 4 complete. PR #5551 merged as
7648547062484404f5c8085b4b6cd0a808b76ed3(read-back verified: PR state MERGED,commits/mainreturned the same SHA). The dispatch thin client is live in the fullfleetbuild; pm-stack diff attributable to this step: zero.What shipped
New crate
crates/fleet-dispatch, wired into the bin's existingdispatchfeature and the registry entry (which gains theenqueueverb the live API carries):fleet dispatch status→GET /healthfleet dispatch launch …→POST /v1/sessionsfleet dispatch enqueue …→POST /v1/tasks(kind validated client-side against the service'sTASK_KINDS)The API surface was discovered from the code, not assumed:
pm-stack/dispatch/src/{server,auth,config,validate,packet,queue}.ts+ the dispatch README. Auth is the service's static bearer, resolved by name through fleet-secrets (pm-dispatch.api-token;[dispatch] token_nameoverrides) and sent as the oneAuthorizationheader — never printed, logged, or stored. Transports follow fleet-queue's two-shape pattern: directhttp://(FLEET_DISPATCH_URL/[dispatch] urlin the new fleet-config[dispatch]table, or the laptop seat's loopback probe), otherwise a CONNECT tunnel on the proxy egress via fleet-proxy's tunnel module. Exit codes: 0 ok · 2 usage · 3 transport/credentials · 4 service HTTP error · 69 stub machinery (fleet-serve and fleet-connect stub dispatch, asserted in smoke).Live round-trips (the shipped builds, against the running service, version
d94b895471024a21bf88358a4f451dc76df5aa7f)Laptop (full build, direct loopback):
dispatch status→{"ok": true, "status": "ok", "version": "d94b8954…", "transport": "direct http://127.0.0.1:4879"}, exit 0dispatch enqueue(dedupe keyfleet-step4-proof-5432) →201 {"task_id": 9645, "issue_number": null, "queue": "repo-health-code-pilot"}"pre_existing": trueand the service's dedupe warning (no error, no duplicate)dispatch launch --no-wait→202 {"task_id": 9647, "issue_number": 5548, "queue": "repo-health-code-pilot", "status": "launching"}; the task was claimed bydispatch-opencode, issue fleet step 4 thin-client proof (launch) #5548 gotqueue/claimed+work/assigned, and sessionses_e5e58dfa050ffexldsrSut6fjdreplied with the requested proof marker and made no changesSandbox (fleet-static build, tunnel transport):
dispatch status→ same health body,"transport": "tunnel via proxy egress to 100.99.113.103:4879"dispatch enqueue(dedupe keyfleet-step4-proof-5432-sandbox) →201 {"task_id": 9648, …}Cleanup verified in the queue store: 9645 cancelled, 9647 done (completed under its claim holder), 9648 cancelled. Proof issue #5548 commented and closed. Post-merge, the sandbox
~/tools/fleetconverged to the merged build (sha2561f515fbb93ea17c9e6c95159363106ddf1c361663403c4a80bff6cfc5b28616f);dispatch statusandrepo-queue healthre-proven through it.Gates
cargo test --workspace: 51 passed, 0 failed (fleet-dispatch +6, fleet-config +2 new);cargo fmt --checkclean; clippy clean (with the rustup 1.99.0 toolchain first in PATH — the laptop's mixed cargo/clippy provenance otherwise raises E0514 on pre-existing crates identically).bwson PATH): status round-trip + transport naming, launch and enqueue round-trips with the by-name bearer, a service 409 → exit 4 with its message, an unknown kind → exit 2, an unresolvable token name → exit 3 before any request. One build-system note: the workspace member list is explicit —crates/fleet-dispatchis registered there, and the new crate's files must be git-staged for flake builds to see them (untracked files are outside the flake source copy).Deltas: live API vs the design note's assumptions
~/.local/state/pm-dispatch/does not exist; pm-dispatch keeps no client-readable state files. Per-task status therefore rides the queue domain (fleet queue list), and the client is endpoints-only.POST /v1/tasks, so the shipped set is status / launch / enqueue.X-Agent-Token), which is why the sandbox route is a direct CONNECT tunnel on the same egress rather than a framed proxy request.DISPATCH_API_TOKENlived only in the laptop's~/secrets/dispatch.env; fleet-secrets had nothing to resolve. Filed in Bitwarden aspm-dispatch.api-token(same project as the other pm-stack secrets; value verified byte-identical to the service's by sha256, never printed). No pm-stack code or config changed.dedupe_keyreturns the pre-existing task withpre_existing: true+ a warning.Interface gaps filed against pm-stack as their own issue, per this step's scope rule: #5555 (no read/status endpoint for launched/enqueued work; the vault-home documentation point). The steward cron's call sites were not touched — they may adopt these verbs on their own schedule, as the design specifies.