glas-harness/docs/local-profile-acceptance.md
tegwick 9fa17dd39b
All checks were successful
ci / validate (push) Successful in 2m34s
docs: record sandbox runtime implementation and remaining auth gates
Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a0726e-5232-73f2-aaca-2c05ceb62efb
2026-09-05 20:36:58 +02:00

183 lines
10 KiB
Markdown

# First local profile: runtime requirements and acceptance
Work record: [GLAS-WP-0012](../workplans/GLAS-WP-0012-first-local-profile-production-proof.md).
Live residual: `GLAS-IN-0002`. Owner dependency: `SAND-WP-0014-T05`.
Start from `harness.agent-dev-local@1.0.0`: rein-aharness / Claude Code /
`claude-sonnet-4-6` / `green-commit-only`. The future proof candidate is
`harness.agent-dev-local@1.1.0`; it is not yet in the catalog because its runtime,
sandbox profile, and credential route are not resolved.
## Reviewed baseline, 2026-09-05
Glas owner adapter: `63a7f9f`. Sand-boxer:
`b6655d88590e03820675719d6dd574e5f5a9f82e`. Rein-aharness source:
`1429db5ad4c83331b6375349ffde1eb13af9575b`.
Run `.venv/bin/python scripts/inspect-local-runtime.py` to inspect the current
`profile.bwrap-local` from inside owner-mediated execution. This is a
non-secret inventory, not a model call or a readiness bypass. It does not read
credentials or the interactive user's authentication files. Exit zero means
the inventory ran and cleaned up; it does not mean the profile is ready.
Recorded run: sandbox `236f3683`, consumer `agt` / `glas-runtime-baseline`,
run id `glas-wp-0012-baseline`. Inventory completed successfully; final state
was `destroyed` and the workspace was absent.
| Requirement | Current evidence | Required owner deliverable |
|---|---|---|
| Owner execution | Real gateway boundary proof passed in GLAS-WP-0005 | Retain exact identity, argv/stdin, timeout, and teardown semantics |
| Rein runtime | `rein-aharness`, `rein_aharness`, and `llm_connect` absent from sandbox discovery | Read-only, reproducible runtime with all required Python dependencies and working CLI entrypoint |
| Claude runtime | `claude` discoverable; startup/authentication not tested | Pin runtime version; prove startup, model selection, tools, and streaming options under the owner environment |
| Persona preparation | `kaizen-agentic` absent | Explicitly accept the rein's recorded `persona_source=none` for this fixture, or provide the optional runtime |
| Authentication | Selected Glas profile declares no credential route | Claude-compatible value-free route id, owner approval/implementation, delivery and revocation behavior |
| Network | `default: deny`, empty egress, only `lo` | Explicit enforced provider route, required DNS/TLS support, denied-destination proof |
| Writable runtime state | Owner sets `HOME` to the copied worktree | Define private auth/cache/state locations and ensure they cannot enter an agent commit |
The `SANDBOXER_CREDENTIAL_ROUTE_REFS` environment field only carries route
labels. In the reviewed broker it does not acquire or deliver credentials.
Glas must not invent a route id, borrow an interactive login, or use the
OpenRouter credential as a substitute for the selected Claude route.
The bwrap implementation unconditionally creates an isolated network namespace
and does not create an outbound interface. Declaring an egress hostname in YAML
alone cannot make the current runtime reach it. Sand-boxer owns the enforcement
implementation and its negative tests.
The rein uses `llm_connect.claude_code.ClaudeCodeAdapter` and launches Claude
with cwd pinned to the sandbox and a named tool allow-list. Host environment
overrides do not survive the owner's sanitized child environment. The runtime
must work under that actual environment, including Git author configuration,
private writable state, and the applicable tool/streaming CLI options.
## Owner return contract
Record exact non-secret artifact/revision references for:
1. The installed sandbox owner path and host. Glas currently calls the local
creating `SandboxManager`; if the intended deployment requires authenticated
HTTP instead, supply that contract and adapt/prove the client before claiming
equivalence with the local manager proof.
2. The sandbox profile and read-only rein/Claude runtime artifact, Python
dependencies, trust store, executable paths, and writable state placement.
3. The Claude-compatible credential route, delivering component, consumer scope,
and cleanup/revocation behavior. Evidence contains route ids and outcomes,
never values, auth files, or provider responses.
4. The enforced egress destinations and ports, DNS/TLS requirements, and proof
that an undeclared destination remains denied. Provider connectivity does
not grant the agent additional network tools.
5. Non-secret startup checks (`rein-aharness --help`, `claude --version` or
owner-equivalent checks), exact actor/project/run identity, absent source
checkout, and destroyed/absent workspace under the deployed path.
The current SAND-WP-0014-T05 text mentions an OpenRouter AppRole read. That is
a separate route from the chosen first Claude profile. Resolve this distinction
in owner work before selecting credentials or treating T02 as complete.
## Real acceptance fixture
After owner dependencies pass, review the exact versioned candidate as
`unverified` and run it on a disposable repository with no push remote. Use a
local test Git identity and a small non-secret task: create only `PROOF.md`
with a fixed expected line and make exactly one local commit. Bound the run
within the reviewed profile's token/time limits.
Use the actual Glas gateway, concrete `ReinAharness` adapter, installed
`rein-aharness` CLI, and selected Claude model. The GLAS-WP-0005 deterministic
dispatch cannot substitute for this test.
Before teardown, validate through owner execution:
- The expected file content, exactly one new commit, expected changed paths,
and a clean working tree.
- Host source path absent from the sandbox; the source sentinel and Git HEAD
remain unchanged when independently checked on the host.
- Exact actor/project/request id as `consumer.run_id` at create and exec;
declared credential route and network policy match the reviewed candidate.
- No task/auth/cache artifacts in the accepted commit; generated task removed
before destroy, followed by destroyed state and absent workspace.
Retain actual commit/content-validation results before gateway teardown
destroys the workspace. A returned commit SHA alone is insufficient artifact
verification. Keep the proof observer in the acceptance fixture unless a
separate product requirement justifies a general artifact API.
Also retain failed-run cleanup evidence for an unavailable runtime, refused
credential route, denied required egress, and timeout. Use owner-controlled
negative fixtures; do not disable host networking or mutate real credentials.
The current Glas adapter supplies `--no-metrics` and has no repository-grant
field. Rein-aharness explicitly refuses repository-grant runs with
`--no-metrics`. This proof therefore validates its disposable output
independently; it must not claim that the repository-grant contract was exercised.
Production grant propagation, if required by the owner return contract, needs
an explicit adapter/state-storage design before the proof candidate can pass.
## Readiness and rollback
Only the proven candidate becomes `ready`, with evidence recording the exact
host/runtime scope and revisions. A ready catalog entry is not a live health
probe for every host. Preserve the blocked `1.0.0` version as the rollback pin;
returning to it must refuse, never invoke another runtime. Do not silently
retarget existing consumers or enable production schedules.
The open-weight profile remains blocked until its own route and real-rein
proof pass. Keep that portion of `GLAS-IN-0002` live after this workplan closes.
## Prepared acceptance runner
After the owner requirements and candidate review pass, run:
```bash
.venv/bin/python scripts/prove-local-profile.py \
--harness-profile harness.agent-dev-local@1.1.0
```
Use `--profile-dir <reviewed-directory>` if the versioned candidate is staged
outside the packaged catalog. The runner requires an explicit version, the
local Claude route, nonempty credential route references, and bounded token/time
limits. It preserves catalog readiness and refuses blocked profiles before
creating even the disposable fixture. There is no force or readiness override.
The fixture wraps the catalog-built `ReinAharness` to observe its result and
cleanup, while delegating actual session setup and agent dispatch. It checks
the committed and working-tree file contents, direct parent commit, changed
paths, clean tree (including ignored files), source absence, exact child
identity, and task mode inside owner execution. Task removal is checked before
destroy; host source integrity and workspace absence are checked afterward.
Output includes configuration references, requested model, commit id, and
boolean checks. It excludes raw model/provider output, task text, and exception
messages. Exit zero means this real-run artifact/lifecycle acceptance passed;
`readiness_review_required` remains true. The owner runtime/deployment pins,
credential-delivery proof, enforced egress and negative-route checks remain
separate prerequisites for T02/T05. The runner does not update the catalog or
publish artifacts.
Validation of the runner itself: its focused tests use local disposable Git
repositories and mocked adapter boundaries, covering extra commits, extra
paths, bad content, untracked/ignored artifacts, source visibility, file mode,
strict boolean inspection results, redacted failures, and profile refusal.
These tests do not count as the pending real-rein acceptance run.
## Owner runtime return, 2026-09-05
Sand-boxer commit `d69827a` (`SAND-WP-0015`) implemented owner-configured, digest-pinned Python
runtime mounts and mode-0700 private HOME/XDG/TMP state outside the worktree.
Its runtime smoke `d4de9531` ran the actual rein CLI and imported the Claude
adapter, proved read-only runtime/source absence/clean Git state, preserved
private state across two exec calls, and removed the workspace. Sand-boxer
validation passed lint and 132 tests; authenticated owner API smoke `223db65b`
passed. Details: `../sand-boxer/docs/bwrap-runtime.md` from the Glas repo root.
The candidate artifact digest is
`4c316737ec2715936a12c4f49621a5e4be3d1f4fe4739130393f28cdda66fbd9`.
This is a temporary standalone Python bundle, not a deployed production
profile or pinned Claude executable. The default profile inventory `ce15f4cb`
now reports HOME outside the worktree but still has no selected rein bundle.
T02 remains waiting on a concrete Claude workload authentication lane,
credential delivery/revocation, the matching enforced provider egress, a pinned
Claude executable, and deployment/profile review. Both credential searches
(`anthropic`, `claude-code`) returned no catalog match. Runtime-startup proof
does not authorize promotion of the local Glas profile.