Skip to content

rfc: persistent host processes — astrid:[email protected] (reattachable background processes)#31

Closed
joshuajbouw wants to merge 1 commit into
mainfrom
rfc/persistent-host-processes
Closed

rfc: persistent host processes — astrid:[email protected] (reattachable background processes)#31
joshuajbouw wants to merge 1 commit into
mainfrom
rfc/persistent-host-processes

Conversation

@joshuajbouw

Copy link
Copy Markdown
Contributor

Summary

Adds astrid:[email protected], an additive evolution of the host process interface introducing an opt-in persistent tier. spawn-persistent returns an opaque, unforgeable, principal-scoped process-id whose backing process lives in a host-owned registry (lifetime = the capsule, not the spawning instance) and is reattachable — read / signal / wait / write / stop — from any later invocation of the same (capsule, principal), including a different pooled instance. The frozen @1.0.0 ephemeral surface is re-exposed unchanged and composes via attach(id) -> process-handle.

Why

Under the dynamic instance pool, a spawn-background child is a wasmtime resource owned by the spawning instance, so it is reaped when that instance resets — before any later, separate tool call could read its logs or kill it. The shell capsule's spawn_background_process / read_process_logs / kill_process split-tool pattern is therefore impossible (it only works today via a carve-out that pins the capsule to one never-reset instance, forfeiting the pool). bash & doesn't help — Linux bwrap reaps orphans on namespace teardown; macOS would leak an untracked process. The fix is a host-owned, id-addressable, principal-scoped registry.

Per the design mandate this is built as a general primitive, not just shell's three tools — it also serves MCP-stdio subprocess hosts, dev-server / build-watch supervisors, and log tailers (read-since cursors, non-draining status/list-processes, event-driven watch).

How it was designed

Grounded in the real host code (ManagedProcess in the instance-owned resource table, ProcessTracker, the bwrap/seatbelt SandboxCommand::wrap path, the frozen-ABI discipline), then run through a multi-perspective design pass (identity/reattach, observability, lifecycle/limits, streams/interactivity, security/isolation, SDK/migration, prior-art) and an adversarial review. Review-found fixes are folded in:

  • macOS fail-closed by default — no PID-namespace reaper; persist-unsupported unless the operator opts in.
  • Spawn-boundary principal gatespawn-persistent refuses the capsule-owner fallback principal (else tenants share a default namespace).
  • Quota relocation is a precondition for retiring the single-instance carve-out, not an independent bugfix — must land atomically.
  • 256-bit CSPRNG id, principal-re-checked on every call (capability, not ambient name); stop (graceful) vs attach(id)?.kill() (immediate) split; bindgen type-identity From-mappings.

Key open questions (in the RFC)

  1. watch publish authority — does host-published astrid.process.v1.* need a manifest [publish], or is it a kernel-authored topic class? Ties to the topic-grammar work (#809). Fallback: drop watch, poll status + bounded wait.
  2. macOS reaper hardening; principal-eviction chokepoint; allow_persistent sub-grant; @1.0.0 concurrent-counter relocation.

Full WIT + reference semantics + security model + host-impl sketch + drawbacks/alternatives/prior-art are in text/0000-persistent-host-processes.md. Draft (unnumbered) per the RFC process.

Adds an additive astrid:[email protected] with an opt-in persistent tier:
spawn-persistent returns an opaque, principal-scoped process-id whose backing
process lives in a host-owned registry (lifetime = the capsule, not the
spawning instance) and is reattachable from any later invocation via attach(id)
+ id-keyed fns, status/list, read-since cursors, and event-driven watch.

Motivated by the pooled-instance reattach gap (a background process dies when
its spawning instance resets, so shell's spawn/read-logs/kill split-tool pattern
is impossible), generalized beyond shell to MCP-stdio hosts, dev-server
supervisors, and log tailers. Per-principal isolated, quota-bounded,
sandbox-contained, auditable, fail-secure; @1.0.0 stays byte-frozen.
@joshuajbouw

Copy link
Copy Markdown
Contributor Author

Closing — this belonged in the existing host-ABI RFC, not a standalone PR. Nothing has launched (everything is draft), so there is no frozen @1.0.0 to evolve from: the persistent-process tier is now folded directly into astrid:[email protected] in #22 (rfc/host-abi), alongside the ephemeral spawn/spawn-background.

@joshuajbouw joshuajbouw closed this Jun 6, 2026
@joshuajbouw joshuajbouw deleted the rfc/persistent-host-processes branch June 6, 2026 14:52
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