Skip to content

Isolate caller-owned session recovery environment and cleanup #33

Description

@rynfar

Problem

A Pylon server can host multiple Prime provider instances, but public SDK recovery currently derives an owned session's launchEnv from ambient process.env during attach. Initial workers inherit the caller-scoped daemon environment; recovered workers can instead receive the Pylon host process environment. Two instances in one Node process can therefore recover with the same or wrong Prime home, PATH, API keys, or credential overrides.

The current SDK also lets DaemonAgentConnection.dispose() swallow complete_owned_session failure, so a caller cannot prove that its owned worker was completed before tearing down or replacing an instance.

Required public SDK contract

  • Add an opt-in, caller-supplied, defensively cloned ownedSessionLaunchEnv snapshot. Capture it once for stock client-owned connections and use that exact snapshot for initial attach, direct-connect fallback, reattach, worker recovery, and daemon/supervisor replacement instead of later ambient process.env.
  • In opted-in mode, launch workers with that exact snapshot plus only documented Prime-owned bootstrap keys. Keep the environment transient. Do not persist, fingerprint, log, or expose it in descriptors, owner registries, snapshots, events, proofs, results, or errors.
  • Freeze the public SDK feature token as caller_owned_session_environment_cleanup_v1. Callers must require this root token, the server's negotiated offer, and a current successful post-attach proof before relying on the contract.
  • Expose getOwnedSessionContractProof() as a safe current-attach proof. It may contain protocol/schema/app/build and supervisor/local-transport generations, but never raw hello data, owner/session tokens, PIDs, sockets, paths, environment values, or secrets. Invalidate it on disconnect or replacement and republish it only after a new successful owned attach.
  • Preserve owner scoping. A caller must never complete or recover another owner's worker.
  • Add single-flight disposeOwnedSession() with bounded, fixed, secret-free outcomes for completed, already completed, owner mismatch, active/stopping timeout with uncertain cleanup, transport failure, unsupported peers, and replacement-settled only when settlement is tied to this connection's prior successful owned-attach proof and opaque session identity. Proving historical ownership from an arbitrary replacement client would require a durable owner-scoped receipt and is out of scope.
  • Keep existing dispose(): Promise<void> as legacy best-effort compatibility. Do not advertise the frozen token when the caller did not opt in or the complete proof cannot be made.

The existing daemon wire already carries launchEnv; this should remain a focused public-client contract rather than a daemon redesign.

Acceptance coverage

  • Create two connections in one Node process with disjoint environment sentinels A/B.
  • Prove exact isolation on initial attach, worker crash/recovery, daemon reconnect, and daemon replacement.
  • Change ambient process.env to a third sentinel and prove it reaches neither recovered worker.
  • Prove launch values never appear in descriptors, owner state, snapshots, logs, events, or error text.
  • Prove wrong owners cannot complete or recover a worker.
  • Prove strict cleanup outcomes across success, already-complete, timeout/uncertain transport, replacement, and owner mismatch.
  • Preserve compatibility for callers that do not opt into the new contract, but do not advertise the frozen capability in that mode.

Scope

This issue owns the Prime public SDK isolation/cleanup primitive only. Pylon home resolution, provider cache fencing, UI, resource budgets, and multi-instance enablement belong in a separate Pylon issue. It is independent of Prime #20 and Comet.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions