Repository navigation
feat(managed-runtime): soul home mounts — resolve in-home {file:} config references - #844
Merged
Merged
Conversation
… (rootless-native group-read design)
…path, rig lifecycle, allow-list sites, DAC test views, cargo filters, ratified mechanism block
…rkspace==home drop, real UI signals, POSIX DAC classes
…t-guard for env path, owned prep script, send-then-assert, placeholder locator, mask canaries
…ript behavioral test, rotation re-run rule, canary rejection semantics, flag-based red fallback, precise residuals
…ersal in prep, compose canonical-path bind, clone fix, sync-throw canary assertion, ratified boundary stated precisely
…+ positive control, prep mkdirs mask destinations with invariant-pair guarantee, time-invariant persisted-mask verification contract
…ation mask filter
…me-invariant verification
…ferences
Adds the local-only regression that proves the operator-home soul mounts fix the {file:} API-key-reference incident class through the real fresh-agent launch path on the real rootless Docker daemon, plus the rig/broker plumbing that admits the new mounts: the operatorHome rig option (passed to the supervisor as --operator-home and used as the web home), the broker's allowedOperatorHomeRoots policy with the same-path read-only bind arm and the three secret-mask tmpfs arms (with unit tests), and the LOCAL_ONLY_SPECS registration.
Scratch-red evidence: with the rig's operatorHome flag forwarding removed (startSupervisor operatorHome: undefined), the spec fails with the production incident's 'Configuration is invalid ... bad file reference ... does not exist' in the soul's terminal spool and no native session ever materializes; with the flag wired the spec passes.
… wiring, and posture docs
… parse - backend: the three fail-closed arms of inspected_operator_home now have unit tests through verify_inspect_config — a marker env without its persisted label, a malformed label record, and an env home that diverges from the persisted record each fail with OwnershipMismatch (each test pins its arm's message and passes against the pre-change code, proving the arms were correct but untested). - session-host: factor provider_run_as_identity's pure parse into provider_run_as_identity_from(lookup) and cover the set-and-parseable path without a process-wide env race; the emission's observable behavior is unchanged and the default path keeps its existing test.
…ompose image contract - create_stopped no longer refuses a launch when the operator-home record cannot serialize (a non-UTF8 home path): the new persisted_operator_home_record drops the mount whole — no home bind, no marker env, no label, exactly the pre-feature launch shape — and logs supervisor.operator_home_mount_dropped. A unit test builds a real non-UTF8 path via OsStringExt to pin the drop and the surviving-record path. - compose: the supervisor command block's comment now states the deployment-provided image contract (no supervisor ENTRYPOINT, binary on PATH) and both contract-violation signatures — an executable-not-found restart loop vs the CLI's usage-line supervisor.fatal loop — instead of claiming an unverifiable mirror of the systemd launch. No pinned supervisor image exists in the repo, docs, or local daemon to inspect, so the contract is documented rather than verified.
…uns; compose web stages operator config; sound mask canaries
Delta-review round 1 remediation: the prep's group-read pass is pruned away
from ~/.amplifier/onecli and actively revokes group bits there (a soul created
before onecli existed keeps that mask filtered for its lifetime, so a re-run
must never make onecli content readable to it); mask destinations the script
creates are owner-only (0700) regardless of umask; the compose web service
binds the operator home and points HOME at it so managed_provider_bootstrap
stages the operator's global config (the file containing the {file:}
references); the e2e canaries get explicit chmods (Node applies the process
umask to writeFileSync mode, leaving requested 0640 at 0600 where a canary cat
would throw for the wrong reason); rootful-degradation doc wording now states
the observable is the mount's absence; README fixes the uid/passwd claim.
…HELL_HOME; e2e launches in the nested production layout Delta-review round 2 remediation: the web service keeps HOME at the operator home (managed_provider_bootstrap stages the global provider config from it) while FRESHELL_HOME — which the server's resolve_home prefers for ALL state (settings, projections, instance id) — points at a new writable web-state named volume, so state no longer lands under the read-only home bind. The e2e regression now launches its freshopencode pane with a cwd nested INSIDE the fixture operator home (group-writable, like production repos), exercising the RO-home + deeper RW-workspace bind shadowing the production layout depends on.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Fresh-agent souls died at launch whenever a projected provider config referenced an absolute path under the operator's home — e.g. opencode
"apiKey": "{file:/home/dan/.amplifier/ms-runpod.key}"— because the65534:0provider child could not read the file ("Configuration is invalid ... bad file reference"). Souls now mount the operator's home read-only at its own canonical path, and provider children keep their identity: under the rootless production daemon the child's gid 0 is the operator's group, so group-readable reference targets resolve with no identity change, no migration, and no digest churn.Changes
freshell-supervisor):OperatorHomeMountderivation — owner-guarded--operator-homeflag;HOMEenv fallback that declines for root/containerized supervisors; masks fixed to.freshell/.amplifier/onecli/.config/gcloud, filtered to destinations existing at creation. Wiring: RO home bind + tmpfs masks in container creation, additive marker env (FRESHELL_OPERATOR_HOME_MOUNT=1+FRESHELL_OPERATOR_HOME), the resolved mount persisted as a Docker container label, and marker-gated time-invariantverify_inspect_config(compares live topology against the persisted creation-time mask list; pre-upgrade souls keep passing). A mount that cannot be serialized is dropped, never a launch refusal.freshell-session-host): POSIX first-matchchild_can_traverse+ oneoperator_home_readinessJSONL event (home-root scope,home_root_traversable_by_child), stat-failure tolerant, never affects launch.{file:}-referencing config boots on the real rootless daemon — RED reproduced the production incident error verbatim; GREEN proves a positive control (child reads the unmasked 0640 key) plus three mask canaries, launching in the nested production layout (<home>/code/...inside the RO home). RigoperatorHomeoption + broker allow-list arms with unit tests.scripts/prepare-operator-home.sh(idempotent; creates mask destinations owner-only; group traversal for home root + config roots; group read for the~/.amplifiertree exceptonecli, which is pruned and actively kept owner-only so a re-run can never expose a running soul) with a behavioral vitest harness; compose wiring for both controller services (supervisor flag + bind; web stages config viaHOMEwhileFRESHELL_HOMEholds writable state on a named volume); posture docs (managed-runtime.md contract + residuals + invariant pair, launch runbook prep step, runtime README).Testing
4bbbb93e2(2026-10-12 15:10–17:20 PDT: workspacecargo test --workspace --locked, client, Rust, and Electron phases all green; Electron 395/395).net_bind::tests::rebind_serves_a_connection_queued_on_the_retiring_listener(unrelated to this branch — it passes in isolation and passed in the full-suite gate at this commit); pushed with the documented--no-verifybypass.rust-gateis the backstop.Review trail
Executed subagent-driven (fresh implementer + fresh reviewer per task, whole-branch review with one fix wave), then an independent delta review (the-usual stage 5): rounds 1–2 found and fixed a real exposure sequence (prep re-run vs. filtered masks), incomplete compose web staging/state, and unsound mask canaries; round 3 PASSED. Plan + run record:
docs/plans/2026-10-11-soul-home-mounts.mdand its superseded provenance plan.Deployment notes
scripts/prepare-operator-home.shafter any Amplifier key rotation.