Skip to content

feat(fleet): native reservation adoption (register.sh honors signed Trackboard reservations) - #13

Merged
convenientlymike merged 2 commits into
mainfrom
feat/native-reservation-adopt
Sep 11, 2026
Merged

convenientlymike merged 2 commits into
mainfrom
feat/native-reservation-adopt

Conversation

@convenientlymike

Copy link
Copy Markdown
Owner

What

When a Claude session starts to fulfil a Trackboard reservation (a signed request to create/launch an agent with a chosen name/role/mission/model), the SessionStart hook now adopts it authoritatively on the real host — the on-host counterpart to Trackboard's server-side reconcile task, and what makes the mission seed reliable (it runs on the target host, keyed by the real session id).

New adopt.sh (sourced by register.sh after reap) does, on a clean match:

  • writes the identity overlay identities/<sid>.json (the same file Trackboard's roster reads — survives the heartbeat rewrite by construction),
  • seeds the mission host-locally + window-keyed: GOALSTACK_WINDOW=<sid> goalstack set <mission>,
  • records the device slug as host in the agent file (read_roster surfaces it; the reconcile host-qualifier trusts it),
  • flips the reservation to status=adopted (bound_sid/bound_host/adopted_via=native) and re-signs it.

Engineering

  • Authenticity (anti-forgery / indirect-prompt-injection). reservations/ is shared + on-default-unauthenticated, so a local writer could drop a forged reservation to seed a live agent's goalstack. adopt_reservation honors only reservations whose HMAC sig verifies with the per-host key Trackboard mints them with. Cross-language parity is byproduct-proven: bash jq -cS 'del(.sig)' reproduces Trackboard's canonical (sorted-key, compact) payload and openssl … -macopt hexkey: reproduces the exact signature. After mutating the record the hook re-signs it (it holds the key) so Trackboard's signed-only read path keeps surfacing it as adopted.
  • Multi-device correct. Host slug from $FLEET_HOST (a launcher/profile env) — never hostname; a named-device reservation is adopted only on that device. Exact rid via $FLEET_RESERVATION (unambiguous, preferred); the cwd fallback adopts NONE on ambiguity — never a silent guess.
  • Fail-OPEN + back-compat. Missing jq/openssl, no key (no Trackboard ran on this host), no/ambiguous match, or a bad signature → a silent no-op (the session registers exactly as before; Trackboard's reconcile task is the backstop). When nothing is adopted, the agent file is byte-identical to the pre-adoption baseline (the host field appears only on a clean adoption).

Verification

  • selftest-adopt.sh (hermetic, wired into CI) — 13 checks, each with a control that fires:
    • B1–B3 a signed reservation adopts: identity overlay + reservation flip + re-sign integrity + mission seed (mock goalstack records GOALSTACK_WINDOW=<sid> set <mission>).
    • B4 the authenticity gate bites: a post-sign-tampered (forged) reservation is ignored (control: an untampered twin adopts).
    • B5 ambiguity → adopt NONE. B6 $FLEET_RESERVATION disambiguates. B7 status gate (a reserved one isn't adopted). B8 host qualifier (a named-device reservation needs a matching $FLEET_HOST; control: matching slug adopts + records bound_host).
    • B9 back-compat: no-reservation register.sh writes the baseline agent file (no host, 9 fields); an adopted one gains exactly host (10 fields).
  • shellcheck --severity=warning clean; SSH-signed; branched off the latest main (post-attic feat(fleet): commit-attic — work-loss hardening (never lose a committed slice) #12).

Pairs with Trackboard D-v2 S4a (server-side reconcile). Composition: patched source → native adoption fires first on the target host (reliable mission); un-patched → the reconcile task adopts name/role/mission remotely. Both write the same overlay + status transition.

🤖 Generated with Claude Code

convenientlymike and others added 2 commits September 11, 2026 01:12
…rackboard reservations)

When a Claude session starts to fulfil a Trackboard "reservation" (a signed request to
create/launch an agent with a chosen name/role/mission/model), the SessionStart hook now
adopts it AUTHORITATIVELY on the real host — the on-host counterpart to Trackboard's
server-side reconcile task, and what makes the *mission* seed reliable.

New `adopt.sh` (sourced by `register.sh` after `reap`) does, on a clean match:
- writes the identity overlay `identities/<sid>.json` (the same file Trackboard's roster reads),
- seeds the mission host-locally + window-keyed: `GOALSTACK_WINDOW=<sid> goalstack set <mission>`,
- records the device slug as `host` in the agent file (read_roster surfaces it),
- flips the reservation to `status=adopted` (bound_sid/bound_host/adopted_via=native) and RE-SIGNS it.

Security + correctness:
- Authenticity: the shared, on-default-unauthenticated `reservations/` dir means a local writer
  could drop a forged reservation to seed a live agent's goalstack. adopt_reservation honors ONLY
  reservations whose HMAC `sig` verifies with the per-host key Trackboard mints them with. Cross-
  language parity is byproduct-proven: bash `jq -cS 'del(.sig)'` + `openssl … -macopt hexkey:`
  reproduce Trackboard's canonical payload + signature exactly; the hook re-signs after mutating so
  the signed-only read path keeps surfacing the record.
- Multi-device: host slug from `$FLEET_HOST` (never `hostname`); a named-device reservation is
  adopted only on that device. Exact rid via `$FLEET_RESERVATION` (preferred, unambiguous); the
  cwd fallback adopts NONE on ambiguity — never a silent guess.
- Fail-OPEN + back-compat: missing jq/openssl, no key, no/ambiguous match, or a bad signature → a
  silent no-op; the agent file is byte-identical to the pre-adoption baseline when nothing is adopted.

Forcing function: `selftest-adopt.sh` (hermetic, wired into CI) proves each guarantee BITES with a
control that fires — adoption (overlay + mission + flip + re-sign), forgery/ambiguity/wrong-status/
wrong-host all REFUSED, and byte-compatible registration when nothing is adopted.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…servation (adopt interop gate)

Folds the load-bearing cross-language proof into PR #13's own CI (this repo is pure bash, so the full
round-trip that re-verifies a bash re-signature in Python lives in the trackboard suite). New
selftest-adopt.sh check B10: a golden reservation minted by Python with Trackboard's exact signing —
json.dumps(record-minus-sig, sort_keys=True, separators=(",",":")) then HMAC-SHA256, under a key
DERIVED from a public string (sha256("trackboard-adopt-selftest-golden-v1"), not a real credential) —
must be accepted by adopt.sh's `jq -cS` + `openssl` verification. If it is, bash and Python agree on
canonicalization; a future jq/openssl drift is caught at CI time without needing Python here. The
control (a 1-field corruption, stale sig) must be rejected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@convenientlymike
convenientlymike merged commit 6666a3d into main Sep 11, 2026
4 checks passed
@convenientlymike
convenientlymike deleted the feat/native-reservation-adopt branch September 11, 2026 08:45
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