# Managed client adoption and containment matrix This document defines how an operator-installed agent client becomes launchable inside Glove and which evidence is required before the multi-agent matrix in [`future-work.md`](future-work.md) is complete. Follow the operational sequence in [managed-client-setup.md](managed-client-setup.md) without broadening these authority boundaries. ## Host configuration is discovery input, not authority Installing or configuring a client as the Glove service user is not sufficient for managed launch. Glove deliberately does not inherit the service user's `PATH`, home, authentication, sessions, provider/model selection, package-manager credentials, or arbitrary client settings. The operator must separately authorize four closures: 1. **Executable closure** — detect the client in an explicit search directory, then pin a canonical executable and any immutable dependencies in a runtime template. Package-manager trees that are not safe launch authority must first be copied with `glove policy stage` into a protected snapshot. 2. **Managed home closure** — Glove creates a fresh `/home/agent` and projects only adapter-owned configuration and verified Sage skills into the client's native locations. 3. **Credential closure** — an owner-protected source file is named only by an opaque secret handle in the controller plan. Linux copies it into a content-versioned lease and mounts the lease at an exact path below the managed home. The original host file and broader host home are never mounted. 4. **Egress closure** — a separate local policy names the exact allowed network targets. A credential does not imply network access, and network access does not imply a credential. A client configured under user `bm` therefore becomes usable only after its executable closure, private-home adapter, credential lease (when needed), and egress policy have each been reviewed and bound into the Glove policy. This is intentional: "works on the host" must never mean "inherits host authority." ## Supported adapter inventory All built-in adapters use `/home/agent`, receive verified Agent Skills bundles, and are bound to the same Linux managed-session filesystem and resource lifecycle. | Runtime | Executable | Native skill root | Adapter-owned environment | Managed configuration | Host-state adoption | |---|---|---|---|---|---| | `codex` | `codex` | `.codex/skills` | `CODEX_HOME=/home/agent/.codex` | Glove writes a minimal trusted-project `config.toml`; Glove remains the sandbox authority | None; credentials require an explicit secret mount | | `claude-code` | `claude` | `.claude/skills` | None | None | None; credentials require an explicit secret mount | | `pi` | `pi` | `.pi/agent/skills` | None | Glove generates `settings.json` from the adopted package snapshot | Explicit package-closure adoption only; auth, sessions, host settings, model state, and package credentials are excluded | | `copilot` | `copilot` | `.copilot/skills` | `COPILOT_HOME=/home/agent/.copilot` | None | None; credentials require an explicit secret mount | | `opencode` | `opencode` | `.config/opencode/skills` | `XDG_CONFIG_HOME=/home/agent/.config` | None | None; credentials require an explicit secret mount | Pi is intentionally different. `glove policy adopt-pi` reads an explicitly named host settings file only to select package closure members from an explicitly named package store. It emits immutable payload snapshots and a generated managed setting containing relative extension paths plus `enableSkillCommands=true`. It does not copy the host settings document. ## Operator workflow For every client: ```sh glove policy detect --search-path /absolute/reviewed/bin --json glove policy stage \ --runtime \ --source /absolute/reviewed/bin/ \ --directory /absolute/protected/runtime-root \ --dry-run # Review, then repeat with --yes. glove policy generate \ --runtime \ --executable /absolute/protected/runtime-root/ \ --template-id -safe ``` Pi additionally requires a separate adoption preview and confirmed snapshot: ```sh glove policy adopt-pi \ --settings /absolute/reviewed/pi/settings.json \ --package-store /absolute/reviewed/pi/package-store \ --directory /absolute/protected/pi-adoption \ --dry-run # Review, then repeat with --yes. ``` Credential source files and egress targets are added only through a separately reviewed policy generation step. Client homes or authentication directories are never valid runtime dependency roots. ## Containment evidence matrix `Required` means the repository must provide executable evidence for every supported adapter. Shared lifecycle evidence may be parameterized by runtime ID when the enforcement code is client-independent. An installed-client probe is still required to prove the pinned distribution starts through the same path. | Invariant | Current evidence | Required completion evidence | Status | |---|---|---|---| | Explicit executable authority | Runtime-template validation rejects inherited `PATH`; detection and staging tests cover canonical protected paths | Keep one shared denial suite and one successful staged closure per distribution shape | Partial | | Fresh private home | Synthetic Linux managed-session cases cover all five native roots | Parameterized assertion for every adapter that host homes and unrelated client state are absent | Partial | | Native skill projection | Synthetic Linux cases cover all five skill roots and receipt-bound bundle digests | Retain shared projection assertions for every adapter | Covered | | Managed environment | Synthetic cases cover Codex, Copilot, and OpenCode variables | Assert exact environment allowlist and absence of representative inherited variables for all five | Partial | | Managed client configuration | Codex and Pi generated files have focused tests | Assert no unmanaged configuration appears for Claude Code, Copilot, or OpenCode | Partial | | Pi package adoption | Dedicated snapshot, mutation, ownership, link-count, auth/session exclusion, and generated-settings tests | Keep Pi-specific adoption evidence; do not generalize it into host-home copying | Covered | | Credential isolation | Generic secret-lease and launch-binding tests cover owner files, private-home targets, and runtime binding | Add a table of reviewed client credential target paths and a no-secret startup probe; real credentials remain outside CI | Partial | | Egress isolation | Linux no-network lifecycle tests are client-independent | Run the same deny-network probe under every adapter identity; online provider access requires a separate opt-in lane | Partial | | Tool-policy binding | Session-plan validation binds an allowed tool-policy identifier into the canonical plan | Prove the identifier reaches the Sage/controller authorization boundary; do not claim harness-native tool enforcement that does not exist | Gap | | Terminal limits | PTY, transcript, input, output, resize, signal, and stop tests cover the shared lifecycle | Parameterize adapter identity in terminal receipt assertions or document the shared binding proof | Partial | | Cancellation and cleanup | Shared Linux process-tree, cgroup, materialization, and cleanup tests exist | Parameterize each adapter identity and require empty materialization roots after exit/stop | Partial | | Crash recovery | Session/process identity and journal recovery tests cover the shared lifecycle | Demonstrate that every adapter launch uses the same recoverable session identity and profile digest | Partial | | Installed client startup | Dedicated `container_linux_native_harness_matrix` runs `--version` for Codex, Claude Code, Pi, Copilot, and OpenCode through managed PTYs; a missing harness root is an explicit CTest skip | Run this lane against a protected root containing every reviewed distribution and retain its receipts/output as deployment evidence | Partial | | Model-backed smoke | No credentialed provider call is claimed | Optional operator-run lane with dedicated credentials, exact egress, bounded prompt, receipts, rotation, and cleanup; never a required public CI secret | Gap | ## Required test lanes ### Repository lane The ordinary test suite remains credential-free. It must cover all five adapter identities with synthetic executables while exercising real Glove enforcement: filesystem projection, private home, environment scrubbing, no-network policy, resource limits, terminal behavior, cancellation, receipts, and cleanup. ### Installed-client lane A dedicated Linux CTest lane receives a protected, prebuilt harness root through `GLOVE_TEST_NATIVE_HARNESS_ROOT`. It runs the real installed executables only through the normal adapter and managed-session path: ```sh GLOVE_TEST_NATIVE_HARNESS_ROOT=/absolute/protected/harness-root \ ctest --test-dir build/dev --output-on-failure \ -R '^container_linux_native_harness_matrix$' ``` It must: - include Codex, Claude Code, Pi, Copilot, and OpenCode; - verify immutable executable/dependency mounts; - invoke a credential-free command such as `--version`; - bind a verified skill projection and private home; - produce a terminal receipt tied to the launch profile and projection digest; - enforce resource and output ceilings; - leave no materialization behind; and - emit an explicit skip when a client distribution is unavailable. This lane proves distribution compatibility, not model-provider access. ### Operator model-access lane A model-backed smoke is private deployment evidence. Each client gets a dedicated least-privilege credential, an exact credential target beneath its private home, and an explicit provider egress allowlist. The test uses a bounded prompt, no wallet, no host auth, and no retained host write. Rotate by installing a new owner-protected source, updating the policy to a new handle or content lease, verifying one session, then revoking the old credential. ## Completion rule The `future-work.md` multi-agent item is complete only when: 1. every repository-lane row above is `Covered`; 2. the installed-client lane is a separately visible test and includes all five adapters without silently substituting synthetic clients; 3. skipped kernel or missing-distribution probes are reported as skips, not passes; 4. a review confirms that client-specific code cannot bypass the shared Linux filesystem, resource, terminal, receipt, and recovery lifecycle; and 5. documentation preserves the separation between executable, managed-home, credential, and egress authority.