Skip to content

docs(plans): environment profiles + host-to-host session teleport#365

Merged
physercoe merged 3 commits into
physercoe:mainfrom
agentfleets:docs/env-teleport-plan
Jul 23, 2026
Merged

docs(plans): environment profiles + host-to-host session teleport#365
physercoe merged 3 commits into
physercoe:mainfrom
agentfleets:docs/env-teleport-plan

Conversation

@agentfleets

Copy link
Copy Markdown
Collaborator

What

A third design plan: docs/plans/env-profiles-and-session-teleport.md — two control-plane primitives from the cloud-agent comparison (Claude Code on the web / Codex cloud), grounded in the current codebase first. Docs-only.

Part 1 — Environment profiles (first-class env_profiles)

The gap: Claude/Codex web attach setup script + env vars + secrets + network policy to tasks as a reusable entity. Grounding showed termipod has no env/setup fields anywhere (templates, families, spawn spec — schema grep is zero), nothing but the hub-minted MCP token is injected into spawns, the egress proxy does URL-masking only, and the docs flag the gap themselves (multi-agent-harness-landscape.md:627).

The design, built around the zero-knowledge vault (ADR-052) instead of against it:

  • Team-scoped env_profiles entity: setup_script (hub-visible) + plain env_vars (hub-visible) + secret_refs (references into the vault — never values) + declarative network_policy.
  • Secret delivery honors forbidden-pattern deps(hub): bump modernc.org/sqlite from 1.34.4 to 1.50.1 in /hub #15: host device keys (X25519 keypair at registration, public key rides capabilities_json — same shape as ADR-052's per-device wrapping); the client resolves vault refs and seals a per-spawn envelope to the target host's key; the hub carries ciphertext it cannot decrypt.
  • Snapshot semantics at spawn (profile id + rev), deterministic env merge order, setup script after workdir creation with fail-closed default.
  • Wedges: E1 entity+plain env+setup script → E2 attach points (project config, spawn sheet) + UI (the vault's unused env/script item types finally get a consumer) → E3 secret envelopes (own ADR) → E4 network-policy enforcement via egress-proxy rules.

Part 2 — Session teleport between hub-registered hosts

Grounding: the resume primitive (resumePausedSession) already does terminate + respawn + keep session row + splice engine cursor — but hard-pinned to the same host (handlers_sessions.go:691), and engine session stores (~/.claude/projects, ~/.kimi-code/sessions, …) are host-local disk files (ADR-014's single-host assumption), so naive cross-host resume would cold-start. Transcripts are hub-side, so conversation history is portable for free.

The design: POST /sessions/{id}/teleport {target_host_id}

  1. Validate target (online via checkSpawnHostReachable, capability supports the family, repo reachable for worktree sessions).
  2. Workdir handoff: branch push/pull for worktree sessions (hub/<handle>); tar-via-hub-blob relay for non-worktree (T2, size-capped).
  3. Engine-state bundles: families declare state_paths globs in agent_families.yaml; source tars the engine store → hub blob → target restores with workdir-path remapping, so sessions.engine_session_id resolves on the target exactly as on the source. Degraded fallback: cold-start + session digest context file, explicit in UI.
  4. Terminate-after-verify swap — source is only terminated after the target spawn reports ready; failure leaves the source untouched.
  5. UX: teleport action with capability-filtered host picker and progress phases, on desktop first (T1), mobile in T2.

Wedges: T1 worktree sessions + kimi/claude state bundles → T2 non-worktree + remaining families + mobile → T3 failover/drain/bare-repo relay.

Security / ADR notes called out

New ADR for E3 (extends ADR-052 to hosts); engine-state blobs flagged as transcript-equivalent sensitivity (seal-to-host via E3 keys recommended in T3); workdir tar caps + blob TTL; setup scripts fail-closed.

Open questions (§end)

Profile scoping vs per-project key overrides; mobile as secret-ref resolver; engine-state blob sensitivity gate for T1; teleport of active-but-idle vs paused-only; non-git tar size cap.

Verification

  • scripts/lint-docs.sh ✓ (cross-link to the now-merged transcript plan resolves)

agentfleet and others added 3 commits July 23, 2026 00:50
Two control-plane primitives grounded in the current codebase:
- env_profiles: first-class setup-script + env-vars + network-policy
  entity; secret values stay in the zero-knowledge vault as references,
  delivered per-spawn as envelopes sealed to host device keys
  (hub-blind, extends ADR-052's pattern; new ADR flagged for E3).
- session teleport: re-targets the existing resume machinery
  (terminate-after-verify) across hub hosts; engine-state bundles via
  per-family state_paths (tar -> hub blob -> target) so cross-host
  resume doesn't cold-start; branch handoff for worktree sessions,
  workdir tar relay for the rest.
…d transport, envelope re-seal, host-key trust, decisions

Maintainer review amendments before merge:
- Teleport reordered pause-first per ADR-014's single-appender
  invariant: terminate-after-verify cut the engine-state bundle while
  the source engine could still append (silent turn loss) and put two
  engines on one logical store during the verify window. Pause is now
  step 2; every later failure falls back to resume-on-source — the
  existing resumePausedSession path.
- Transport section added: /v1/blobs caps at 25 MiB and buffers
  uploads in memory, so single-blob tars (256 MB workdir cap, large
  engine stores) are impossible — teleport rides a chunked bundle
  manifest (<=25 MiB parts + manifest blob + whole-tar hash).
- E3 x Part 2 interaction stated: env_secret_envelope is sealed to the
  source host's key; the initiating client re-resolves and re-seals to
  the target host during teleport; headless teleport of secret-bearing
  sessions is impossible by design.
- E3 host-key enrollment gains ADR-052 D-4's explicit trust step
  (fingerprint short-code confirm, pinned thereafter, re-key =
  re-trust) — without it a hub could substitute keys and open every
  envelope.
- env_profile_rev dropped: the entity has no revision machinery;
  snapshot = materialize resolved env_vars + setup_script into the
  spawn spec, env_profile_id kept for provenance.
- Open questions closed as decisions; companion links updated (physercoe#363
  c97c522, physercoe#364 c797538; branch merged with main so both resolve).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
physercoe
physercoe previously approved these changes Jul 23, 2026
@physercoe
physercoe merged commit fb8e5f1 into physercoe:main Jul 23, 2026
3 checks passed
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.

2 participants