--- title: Manager embedding authority description: Manager startup, signer custody, remote authority callbacks, and delegated user intent contracts. kind: Reference audience: integrators --- ## Interactive manager primary [#interactive-manager-primary] A trusted composition can pass `{ interactiveManagerSelection: "local-primary" }` as the third argument of `runAuthService(args, store, options)`. `AuthServiceRuntimeOptions` is exported by `@cotal-ai/auth`. The third argument still accepts the native daemon lifecycle hooks. No CLI flag or exchange field sets the policy, and unsupported runtime values refuse before startup effects. `openAuthAuthorityPlane` accepts the same option beside its fresh `localManager` reader; `OpenAuthAuthorityPlaneOptions` is exported too. The opt-in chooses the genuine local Manager up front for an unpinned human `manager-caller` exchange. It reads the persisted local identity and requires the existing open gate, serve principal, registration revision and status epoch checks. An absent, unreadable or noncandidate local Manager refuses without scanning or substituting remote Managers. Explicit selectors win, and managed-secret exchanges and launching or issued instance bindings keep their existing rules. The option adds no scopes, registry reads or inventory rows. This routes all unpinned interactive Manager control, not only `ps`: slot reads, stop, attach, input, spawn, models, hosted run verbs and generic Manager describe/invoke share the view. It chooses local even when the person has a live remote Manager. A host must decide whether that routing is appropriate; a local Manager without execution cannot forward a spawn or run to the person's remote Manager. The person selects that Manager explicitly for those operations. Absent the option, selection is unchanged. `startAuthService` still has no local Manager and keeps its remote-only composition. Supplying this programmatic option does not enable it in stock `up`, restart or recovery paths; a host must compose those paths separately after adopting the published API. `ps` still lists only the selected Manager's managed seats, not HTTP-hosted sessions. ## Supervisor signing authority [#supervisor-signing-authority] `@cotal-ai/manager` exports the `Manager` class; there is **no** `runSupervise(opts)` runner. The private CLI `runManager` also does broker-reachability checks, space/default resolution, roster/launch parsing and materialization, installed-extension resolution, signal handling, staged pre-spawn, and the forever wait. A host composes that lifecycle itself around `Manager`: ```ts import { Manager } from "@cotal-ai/manager"; const mgr = new Manager({ space, servers: brokerUrl, workspaceRoot }); await mgr.start(); // then wire your own SIGINT/SIGTERM -> mgr.stop() ``` `stop()` runs once. A later call joins the stop in progress and settles with it, and a call that asks for a different `withAgents` than the running stop is refused. `start()` refuses with the exported `ManagerInstanceLeaseHeld` when this instance's lease is held by another live process on this root, or by a holder on another root. Its `held` field is the lease row (runtime, pid, root, holder, since) and `sameRoot` says whether that root is this one. A restart whose predecessor on this root is dead, including this process's own earlier start, waits for the old key to expire instead. A lease that could not be read or written is a plain `Error`. ### Signer custody Unlike delivery, the manager is **not** a pre-minted-scoped-cred daemon (auth-service is also a signer: it holds fewer artifacts than the full trust bundle, but its data-account signing seed still grants complete data-account mint authority on compromise, so this is not least-privilege). On `start()` the manager reads its space's full trust chain **through its `secretStore`** (`getSpaceAuth(this.secrets, this.space)`, composed from `auth/broker.json` + `auth/account..json`; a container may instead mount a stripped signer bundle at the legacy `auth/auth.json` key) and **self-mints** its supervisor cred and renewals from the data-account signing seed. In static mode it also mints every per-agent cred from that seed; in user mode agents instead receive callout-minted bearers, but the manager still holds the signing seed for its own creds and renewal. So a hosted supervisor is a **trusted per-tenant account-signer process**, not a least-privilege connect client. It additionally requires a `~/.cotal/meshes/space..json` registry record and the workspace user-auth marker to start in user mode. `ManagerOptions.secretStore` injects the one `SecretStore` the manager uses for **the signer itself (the split trust records)**, daemon-credential renewal (`remintDaemonCreds`), and per-agent secrets, defaulting to the workspace filesystem store; pass the delivery daemon the *same* store for end-to-end hosted renewal. ### Daemon renewal ownership The store declares the same identity on both processes, or both set `COTAL_SECRET_STORE` to the same coordinate. The manager remints no daemon credential when the daemon names a different store, including a daemon that binds after start; it keeps running and serving its own agents, so one space can carry a manager on more than one workspace root. That manager also stays off the space's renewal lease, so a manager or a `cotal doctor auth --fix` on the daemon's store can still take it. Pointing several managers at one coordinate is safe: the store identity alone cannot pick an owner (it carries no holder and no tiebreak, so every manager sharing the store matches), so the manager that also holds the space's renewal lease is the one that remints and the rest skip it. Without that lease two owners would remint on independent timers with no ordering between them, and one write would land between the other's re-sign and its fingerprint-only `reloadCreds`. `cotal doctor auth --fix` takes the same lease before it re-signs, so a live manager and a local repair never race each other either. The signer IS now injectable: a hosted composition injects a KMS/Vault store and no signing seed lands on the hosted disk. What remains is signer **isolation**. The seed is decrypted in-process at the manager's uid. That issue needs an OS sandbox or remote signer; it is no longer a custody problem. The other knobs are `workspaceRoot` and the process-global `COTAL_HOME`. ### Rejection handling A store, runtime, extension or host callback the manager calls may reject with any value, including `null`. The manager logs or refuses with that value's `message`, or with the value itself as text when it has none, and keeps serving. A value it cannot read reports as `an unreadable rejection`. > Scope note: the **static-auth** operator paths (`cotal spawn`/`join`/`status`/`web`, via > `mesh-target` → `connect`/`preflight`) still read the signer from the local split records (sync > `loadSpaceAuth`). That is the single-machine composition, where the signer is on local disk by the > static-auth model; multi-tenant hosting runs **user mode**, which never mints from on-disk trust. The > store-injectable signer path is the hosted-server set: the manager, `remintDaemonCreds`, and delivery. ### Managed lifecycle retirement The typed remote-manager authority contract includes a one-shot terminal phase. A host implements `remoteAuthority.prepareAgentRetirement` to revoke the managed grant and finish its resumable release while preserving the UID, then `remoteAuthority.mintRetirementRequester` returns the host-signed JWT for a fresh participant-owned nkey. The credential is pinned to the authenticated owner, server-derived manager serve principal, current instance epoch, and exact target lifecycle. The manager then uses the existing auth `retireLifecycle` rail with the operation id derived by `managedRetirementOpId(target.lifecycleUid)`. This derivation is the reference remote-Manager composition's closed contract, not a rule for every retirement entry point; interactive retirement keeps its existing operation identity and remains compatible. The `retireLifecycle` rail independently recomputes the managed id from its broker-pinned target before any gate, head, intent, or barrier access, so mint-time validation is not the terminal boundary. A failure keeps the alias held. This does not expose the auth barrier or give the participant signer authority. Between prepare and the terminal request, the manager removes the agent's actor token, sentinel credential and health file from its own secret store and disk. The hosted enrollment wrote them there, so the host cannot remove them. Every removal is attempted, and a failed one keeps the alias held before the terminal request. If the participant disappears after prepare, the host finishes the retirement itself on the auth service's loopback face: `POST /managed-lifecycle/retire` (exported as `MANAGED_RETIRE_PATH` from `@cotal-ai/auth`) with the `Bearer ` from `auth-service.json` and only `{ owner, actor, lifecycleUid }`. It has the interactive door's guards (POST only, no `Origin`, JSON, capability, closed body) and is never served on the public face. The managed grant must already be revoked at that uid, or it answers 409. It runs the same `managedRetirementOpId(uid)` operation as the rail, and the rail and the door share one in-process flight, so a late participant request and the host call converge on one barrier. | lifecycle head | answer | | --- | --- | | absent, or `retired` at another uid | `200 { retired: false, lifecycleUid, notStarted: true }` | | `active`/`retiring` at another uid | `409` | | `retired` at this uid | `200 { retired: true, lifecycleUid, alreadyRetired: true }` | | `active`/`retiring` at this uid | the barrier runs, then `200 { retired: true, lifecycleUid }` | ### Durable cleanup results Deprovisioning durables stays with `deprovisionAgent` and a `deprovisioner` credential. Pass `memberChannels` to both to also purge the retired lifecycle's durable membership rows on those concrete channels and channel families. The manager fills that list from the launch's concrete read channels and the delivery daemon's read-only `lifecycleMemberships` admin verb. Before it reads that verb, it calls `fenceLifecycleAcl` under a deprovisioner credential for the same lifecycle with no member channels. That narrows the lifecycle's read-ACL row to no reads, and a durable join the inventory does not see then removes its own row. When that verb cannot answer, rows on other channels stay retained, the teardown logs the inventory as incomplete, and retirement remains held pending retry rather than releasing the alias. Each teardown examines two exact consumers, one ACL key and the named member keys. KV deletion uses a native revision condition; a lost condition with a live replacement refuses rather than claiming absence. Consumer INFO checks before and after DELETE distinguish verified prior absence from disappearance. `acknowledged` counts native DELETE success replies. `disappeared` counts observed live-to-absent consumers and live KV rows whose conditional purge lost to a competing deletion. These KV rows were present at the first read, so they never count as prior `absent` or as this caller's `deleted`. The ACL and membership subtotals preserve that distinction. Neither establishes which concurrent caller uniquely removed a consumer, so `consumers.deleted` and the total `deleted` are `null` when a consumer disappears without a winner token. A repeat after verified absence reports zero, not an invented deletion. `refused` counts slots whose cleanup or state remains uncertain. A partial failure raises `DeprovisionError` carrying these bounded observations. The Manager's static sweep preserves unknown uniqueness rather than adding acknowledged requests as physical removals; its slot totals remain exact. A separate host activates one exact managed lifecycle through the same full account auth service: `POST /managed-lifecycle/activate` (exported as `MANAGED_ACTIVATE_PATH`) with the `Bearer ` from that account's `auth-service.json` and the closed body `{ accountPublicKey, owner, actor, lifecycleUid }`. This route is present on an ordinary separately hosted full auth service. It does not require `platformControl`; that option adds the equivalent in-process handle for a composition sharing the process. A callout-only replica has no HTTP listener or authority plane and cannot serve it. The repeated account key prevents a host routing error from asking one account authority to act on another account's target. It must equal the service's assigned data account before lifecycle work. The route is POST-only, refuses `Origin`, requires JSON and the per-start capability, rejects unknown fields, and is absent from the public exchange face. Parser and authority-selection refusals state `outcome: "not-executed"`. After dispatch, the native activation code, details and outcome are returned. A non-native failure reports `outcome: "unknown"`, never activation success. The operation calls the authority plane's existing fence before `activateLifecycleAtUid`. Success returns `{ accountPublicKey, owner, actor, lifecycleUid, activated: true }` only after the head is active at that UID and its issuance gate is open. The native lifecycle contract remains unchanged: | lifecycle state | answer | | --- | --- | | absent, or `retired` at another UID | activate this UID | | `active` at this UID with an open gate | idempotent success | | `active` at another UID | `already-exists` refusal | | `retiring` | lifecycle-blocked `failed-precondition` | | this UID frozen by retirement, or terminally retired | lifecycle-blocked refusal | | authority fenced or unavailable | `unavailable`; no success result | ### Retained managed agents A host that resumes retained managed actors also implements `remoteAuthority.validateRetainedAgent`. The participant sends back the actor token and sentinel it already holds, plus the `nextRegistrationProof` returned by the activation response. That proof is host-issued after registration and binds the manager owner, actor, lifecycle, identity nkeys, current registration revision, and serving epoch. The host checks it against the current open manager gate, validates the retained secrets against its current managed row, and returns only the non-secret authority shape. The manager binds every result coordinate and the returned authority back to its inventory before use. Do not copy the provider's `issuer.json` or `callout.json` into the participant store. Both contain private signing or exchange authority. The same composition supplies `remoteAuthority.agentBearerExchangeUrl`, the pinned public auth-service base used by retained children. Remote adoption launches `agent-bearer --exchange-url `; it must not select the local `--dir` arm, which depends on a host-only auth-service process record. ### Fresh managed agents A host that lets a remote participant spawn FRESH managed agents implements `remoteAuthority.enrollManagedAgent`. The participant generates the standing actor token, writes it at mode 0600, and passes only its SHA-256 digest with the requested actor, label, role, capabilities, and channel lists, so the plaintext secret never leaves the participant machine. There is deliberately no `lifecycleUid` input: the host selects the UID, because only the host sees the retirement tombstones that make a UID permanently unusable, and a participant-chosen UID could aim a fresh grant at a dead incarnation. The host authors the ledger grant, pre-creates the lifecycle-keyed durables, clamps the requested lists to what the spawning owner already holds, and returns the owner, actor, chosen `lifecycleUid`, the space sentinel credentials, the effective lists, and `agentBearerExchangeUrl`. The manager binds every returned coordinate, re-keys the secret family onto the returned UID, and launches `agent-bearer --exchange-url `. When the hook is absent a signerless manager refuses the user-mode spawn rather than authoring a local grant the host knows nothing about. The hook also receives a stable `requestId` for an unlaunched enrollment. Forward it to `remoteManagedAgentEnrollmentRequest` after the optional `spawn` argument. The manager retains the request input and token in its secret store until bearer preflight succeeds. A later spawn with the same caller and persona authority keeps that request identity and token, but forwards its freshly served spawn request. The host can authorize an attempt that never committed even after the earlier observation expired or the auth service restarted. An existing grant still answers at its original lifecycle. Host registration proof and serve epoch come from the current manager registration. ### Managed-agent authority transport Both managed-agent operations ride the one verified `POST /manager-service-authority` transport as `kind: "manager-managed-agent-enrollment"` and `kind: "manager-managed-agent-prepare-retirement"`. Stock `cotal auth-service` answers both itself, because it owns the actor ledger and the space's provisioning authority. An enrollment writes the managed grant at a fresh UID with the supervising actor as its parent, or, when the request carries `spawn: { served, runId? }`, with the caller the host observed publishing that served `spawn` subject, or the run's starter for a run's spawn. It provisions that UID's durables, and returns the daemon's public exchange URL as `agentBearerExchangeUrl`; a daemon started without `--exchange-public-port` refuses enrollment. Before launching the child, the manager requires HTTPS or an HTTP loopback IP literal for this URL, using the same rule as `cotal agent-bearer`. A name such as `localhost` does not qualify for HTTP. A retry with the same token digest answers the same UID while its parent's current grant covers it, and a fresh enrollment's refusal otherwise. While the agent's grant stands, an enrollment with another digest is refused with `conflict` until that lifecycle's retirement is prepared. A prepare-retirement releases the target UID's broker footprint and then revokes its grant, so the manager's terminal rail finds the grant gone. The footprint includes every durable membership row of that UID, found as the manager's own teardown finds them: the grant's concrete channels, plus the delivery daemon's `lifecycleMemberships` inventory read after the ACL fence, which adds family rows and rows on channels a wildcard grants. When that inventory cannot be read, the prepare removes what the grant names, fails, and keeps the grant for a retry. A platform that keeps these writers in its own storage intercepts both kinds instead. It terminates its own public route, authenticates the human there, and asks the auth service for the decision at `POST /manager-service-authority/verify-enrollment` (exported as `VERIFY_ENROLLMENT_PATH` from `@cotal-ai/auth`) with the `Bearer ` from `auth-service.json` and only `{ owner, request }`. That door has the managed retirement door's guards, derives the caller's scope from the local ledger rather than the body, checks the manager gate and registration proof in-process, and answers `{ authorized: true, owner, actor, instanceId, serveEpoch, parent }`. `parent` is the ledger principal the helper is bounded by: the caller the auth service saw send the manager's `spawn` request, the run's starter for a run's spawn, or the manager. The door refuses a target wider than that parent's grant. It counts a list the target leaves out as empty, so the platform fills such a list from no more than the parent's grant and writes `parent` on the grant, so that narrowing or revoking the parent reaches the helper. A retry of the same enrollment gets the same answer. `authorizeRemoteManagedAgentEnrollment` and `authorizeRemoteManagedAgentPrepareRetirement` are exported too, for a host that composes the decision without the HTTP hop. Both require ledger scope `supervise`; `spawn` and `admin` do not imply it. Every door that checks a manager's current registration does it the same way, after its own space, scope and target checks. It refuses an absent or non-open gate with `failed-precondition`, then a gate held by any other principal with `permission-denied`, then a stale epoch with `conflict`. Last, it refuses a proof that does not match with `permission-denied`, compared in constant time. A manager-service `renew` carries no epoch, so a stale one fails the proof check. A manager-service `retire` runs the same gate checks with the same refusals but no current-registration proof, because its request carries the lifecycle registration proof instead. A host that runs managed agents on its own hosted runtime adds two more kinds on the same transport. `kind: "manager-managed-agent-runtime-create"` asks the host to create the runtime for one agent it already enrolled, and `kind: "manager-managed-agent-runtime-status"` reads that runtime's state. Both carry the manager envelope plus `target: { owner, actor, lifecycleUid }`, the coordinate the enrollment returned. Both schemas are closed. An unknown top-level or target field, including `providerRef`, `handle`, or `name`, is refused as `bad-request`, because the host alone issues and holds provider references. There is no stop, adopt, or probe kind: stop goes through prepare-retirement. Stock dispatch refuses both kinds with `unimplemented`, and the verify-enrollment door decides them. `authorizeRemoteManagedAgentRuntimeCreate` and `authorizeRemoteManagedAgentRuntimeStatus` apply the enrollment door's checks: host space, a target owner equal to the authenticated owner, the manager actor's own ledger row with `supervise`, the open gate, the current serve epoch, and the registration proof. Each returns only `{ owner, instanceId, actor, target }`. The door touches no provider and writes nothing. The host matches the decision to its own intent record and performs the create afterwards. The host answers with `state` (`reserved`, `creating`, `bound`, `create-unknown`, `closing`, or `closed`), `readiness` (`ready`, `bound-not-ready`, or `none`), and an optional `retirementPhase`. A manager builds requests with `remoteManagerClient.remoteManagedAgentRuntimeRequest` and binds the answer with `remoteManagedAgentRuntimeState`. ### Host runtime contracts An enrollment result may also carry `runtimeIntent: { state: "reserved" }` when the host reserved a hosted runtime for the agent. It is display-only. Older hosts omit it, the manager binds both shapes to the same material, and nothing reads it as authority. ### Delegated user intent decisions No stock door lets a platform control holder launch or retire an agent for a signed-in user. The managed-agent kinds above act only under the authenticated owner and refuse a caller that is not that user, so a platform could only run a user's agent by holding the user's login or by enrolling the agent under its own owner. Both are refused. The [delegated user launch intent](design/delegated-user-launch-intent.md) design and SPEC §13.16 define the smallest addition. The user admits one launch or one retirement on the host's authenticated route. The holder consumes that intent once, from its current registration, epoch and lifecycle. The host then enrolls the agent under the user's `u_` owner with the user's own actor as its ledger parent, so the envelope walk, membership and channel lists match what the user's own manager would produce. Retirement keeps the prepare, provider closure and terminal barrier order, and the host finishes it when the holder is gone. A launch the host had to undo keeps its agent name held until the host process that ran it confirms it has stopped, and while the name is held the host also refuses it to the user's own manager. `@cotal-ai/auth` ships the two decisions, `authorizeDelegatedUserIntentAdmission` and `authorizeDelegatedUserIntentExecution`, for a host that owns an intent store and those writers to compose on its own routes. Both read the holder's gate through the handle's `observeManagerGate`, present with `platformControl`, which reads over the context's own connection, so the host opens no second data-account connection. It is an observation for the decision: the consuming CAS and the writers still apply their own checks. The consuming CAS pins the incarnation of the host process that runs the flight as the executor, never the auth plane's, because the two can restart independently. ### Host registration artifacts `platformControl.host` names that process's reverse-DNS endpoint, the closure digest of its §13.7 cluster and the contract artifacts registration reads, and the auth plane self-authorizes that one name. Registration reads the closure manifest `{ v: 1, root, members }` at `clusterDigest`, then the cluster document at the manifest's `root`, and verifies each against its digest. `artifacts` therefore carries both, and `clusterDigest` is the digest of the manifest. `members` stays empty: SPEC §13.7 lists every reachable artifact there, but this implementation registers single-document clusters only and refuses a manifest that lists members. A manifest with any field beyond `v`, `root` and `members` is refused too, as the contract store refuses it. `singleDocumentClosure(document)` returns that manifest and its closure digest. The instance id is a lifecycle token, `[a-z0-9]{26,32}`. The minimal construction below has one command over the void schema. A host copies it, replaces `document` with its real cluster, and passes `host` as `platformControl: { observeAssignment, host }`. ```ts import { mintLifecycleUid, singleDocumentClosure, VOID_SCHEMA_DIGEST } from "@cotal-ai/core"; const document = { urn: "com.example.host", revision: 1, attributes: [], events: [], commands: [{ name: "ping", class: "ephemeral", targeted: false, capability: "host.ping", inputDigest: VOID_SCHEMA_DIGEST, outputDigest: VOID_SCHEMA_DIGEST, }], }; const { manifest, closureDigest } = singleDocumentClosure(document); const host = { endpoint: "com.example.host", clusterDigest: closureDigest, artifacts: [document, manifest] }; const instanceId = mintLifecycleUid(); // first start only; later starts reuse the persisted id ``` ### Host incarnation fencing `registerHostIncarnation(instanceId)` publishes the artifacts, registers that instance through the ceremony the plane runs for itself, and returns `{ instanceId, processEpoch }` with the epoch that registration committed. The host calls it at every start with its persisted instance id, before it admits or recovers any flight, so a restart fences its predecessor. The first registration of an instance commits epoch 0, which is open and serving like any later epoch, and each later start of that instance commits the previous epoch plus one. A consumer compares epochs for equality and never reads 0 as absent or not ready. A start whose confirming read of the gate finds that a later start of the same instance registered is refused with `conflict`. The returned epoch is a committed coordinate and stays current only until the next start registers, which can happen before the call returns. `observeHostGate(instanceId)` is a point-in-time read of an executor's gate, and answers null for an absent gate; a sweeper decides on it. `awaitHostFence(instanceId, processEpoch)` resolves with the gate once it is no longer open at that epoch, and with null once it is absent. It takes any non-negative safe integer epoch, 0 included, and refuses any other value with `bad-request`. The host arms it with its returned incarnation before it admits or recovers any flight, and stops serving when it resolves. It polls the gate, because no runtime credential may watch the auth bucket. ### Delegated intent execution The host's launch writer first activates the agent's lifecycle at the pinned UID through the handle's `activateManagedLifecycle`, before any ledger row or durable, and its compensation runs the same call before the terminal barrier, so a launch whose agent never exchanged its bearer still reaches the terminal barrier at that UID. The launched agent exchanges its bearer on the context's public face, so the host starts it with `publicFace`, and its retirement writer ends at `POST /managed-lifecycle/retire` with the handle's `cap`. Stock dispatch refuses both kinds as `unimplemented`. The holder's composition passes `remoteAuthority.executeDelegatedUserIntent`, which posts the execution request and binds the answer with `parseRemoteDelegatedUserIntentExecutionResult`. It then starts the agent with `startAgent({ ..., delegatedIntent: { intentId, owner, parent } })` and retires it with `retireDelegatedAgent(name, intentId)`, which stops the agent and removes its local secret family only after the host confirms `retired: true` for its exact target. A delegated agent's stop, exit or failed launch keeps its name held until that retirement confirms, and a secret file the retirement fails to remove keeps it held too. ### Remote administration authorization Remote user-mode managers must also supply `remoteAuthority.authorizeAdmin`. The manager builds each request only from the caller tuple parsed from the broker-authenticated endpoint subject, then relays that tuple over the current registered manager lifecycle. HTTPS does not separately authenticate the relayed caller. The host authenticates the manager operator, binds the request to the current open manager gate, registration proof, serving epoch, and identity nkeys, then reads the caller's unified authoritative row fresh. It returns only the manager owner and `authorized: boolean`, with every request coordinate echoed. Missing, revoked, narrowed, foreign-owner, and stale-lifecycle callers all return `false`; malformed coordinates or corrupt and unavailable authority state fail the operation. The participant never reads or mirrors the host ledger, and the remote branch has no local fallback. The same callback gates all `manager.admin` handlers, any-mode cross-owner control, and `ps` or `inspect` cross-owner visibility. Launch keeps its owner-equality policy. ### Maintenance limits Activation and standing renewal identify the manager contract by its closure manifest digest. The host keeps that registered digest in command authority and the serving descriptor; the inline cluster document retains its separate root artifact digest. The remote authority's instance executor remains the scoped maintenance credential for clean service deregistration and exact instance registration operations. It carries no records-stream consumer lifecycle authority. The manager's boot `goalidx` sweep uses the authenticated host operation, which returns parsed `goalidx.manager..>` entries for that owner only. The host keeps the sealed consumer connection and its create/delete rights. The five-minute executor already renews through `remoteAuthority.renewExecutor`. During participant registration, `registerRemoteManagerAuthority` accepts `refreshPrepareCreds` to request another prepare executor after broker-confirmed expiry. It must keep the same account and executor nkey and advance expiry. The stock supervise command supplies it through the authenticated host route; an embedding that omits it still refuses an expired registration. The frozen operation and durable progress survive each replacement connection. `remoteManagerClient.remoteStandingBundleRenewal` builds standing-bundle renewal requests, with adoption bound to the current serve epoch. `remoteRunHosting` supplies `renewRun` through the `renewRunDriver` authority operation. The host validates and adopts the driver and mediator pair before reconnecting, using the current holder and fencing coordinates. The [hosted runtime contract](design/hosted-runtime-contracts.md) records the bounded additions and their ownership; it is not a shipped pooled service. ### Agent isolation **Signer isolation needs an OS sandbox.** The default pty runtime runs agent children under the *same* OS uid and the *same* `workspaceRoot`, so mode-0600 on the trust records does not stop a hostile same-uid agent from reading their absolute paths. The reference [deploy](deploy.mdx) tree does not solve this: it mounts the signer into the agent's own container, so its phase-1 boundary isolates agents from each other, not the signer from the agent. A hosted composition must run the manager/minter that holds the signer in a different uid, container, or mount namespace from the agent children, which mount no signer at all; that split is future hosted-composition work, so until it (or a remote/injected minter) exists, do not run untrusted agents under this manager.