rein-aharness/docs/owner-bootstrap.md
tegwick b48c715e9a
Some checks failed
Governed runtime contract / contract (push) Failing after 12s
Add one-command owner envelope renewal (REINAH-WP-0008-T03)
owner renew validates a settled ledger, builds the new spend policy from an
envelope file of changed fields only, retires the old ledger by rename,
initializes a fresh one at the same path and rewrites the policy and
owner.json pins. Dry run by default; prints the Secrets Engine file pins.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 269692@bnt-lap001
Assistant-Session: 8077e68a-0985-4b41-898c-2dc602b0d6be
2026-10-13 23:24:24 +02:00

134 lines
7.6 KiB
Markdown

# One-cycle owner bootstrap
`rein-aharness metered-once --owner-config /absolute/private/owner.json` is the
explicit exec-env child entry point. It prepares the exact admitted pins, consumes
only the deliberately delivered `ANTHROPIC_API_KEY`, removes provider authentication
and base-URL variables before other child processes, and runs at most one claim
cycle. The provider key is held by MessagesOwner outside the sandbox. Missing/mixed
credentials, invalid pins, missing ledgers, blocked profiles, failed readiness and
unclaimed refusals return nonzero. Receipt output excludes raw errors and prompts.
There is no key fetch, alternate provider, key file, OAuth/HOME or daemon fallback.
`--check` validates local pins without a key, queue access or workload dispatch;
it can advance the ledger's clock watermark but never initializes/reset its schema.
**Rehearse before every paid attempt.** `--rehearse` (implies `--check`) also
runs the admitted runtime's `rein-aharness` and `glas-harness` launchers, and
`claude --version` when the build declares Claude, inside bwrap. The runtime is
read-only at the sandbox mount path; there is no network, a cleared
environment, no credentials, no provider route and no queue access. It writes
nothing beyond what `--check` writes. The receipt lists each exit code and
returns nonzero if any is not 0. The launcher check in `--check` reads only the
first line of each launcher; the rehearsal executes them. Run 6efa9436
(2026-09-27) failed with exit 127 on exactly such a launcher.
python -I -B -m rein_aharness.cli metered-once --owner-config /abs/owner.json --rehearse
**Renew an envelope with one command.** After the old envelope is
reconciled (no `held` reservation, no open request route), write a small
JSON file with only the fields that change: `envelope_id` (required and new),
plus any of `authority_ref`, `valid_from`, `expires_at`, `eur_per_usd`,
`per_run_eur`, `daily_eur`, `total_eur`, `max_budget_usd` and
`max_liability_usd`. Then:
python -I -B -m rein_aharness.cli owner renew --owner-config /abs/owner.json \
--policy /abs/spend-policy.json --ledger /abs/spend.sqlite3 \
--runtime-path /abs/runtimes/<digest> --envelope envelope.json
Without `--apply` this only prints the summary: envelope, policy and runtime
digests from old to new, the limits, and where the old ledger goes. With
`--apply` it:
- backs up `owner.json` and the policy as `<name>.<old envelope>.bak`;
- renames the old ledger to `<ledger>.retired-<old envelope>`;
- initializes a fresh ledger at the same path;
- writes the new policy and `owner.json` privately and atomically.
No digest is typed by hand. Paths do not change, so the Secrets Engine
`exec_owner` catalog needs only the new file hashes, which are printed as
`catalog_file_pins`. Update those pins, then run `--rehearse`.
Use the standalone candidate interpreter as `python -I -B -m rein_aharness.cli`.
`-I` excludes editable PYTHONPATH/user-site fallbacks; `-B` prevents bytecode writes
from changing the complete artifact digest. The source and namespace rein commands
continue to use their existing entry points. The owner config selects the pinned
runtime through the trusted, ephemeral sandbox binding; it cannot add egress or
provider credentials to the child. Normal `claim-loop` behavior is unchanged.
The mode-0600, regular, owner-owned config has exactly these fields:
```json
{
"version": "1",
"authority_ref": "REPLACE_WITH_ACCEPTED_SPEND_AUTHORITY",
"spend_policy_sha256": "REPLACE_WITH_ACCEPTED_SPEND_POLICY_DIGEST",
"messages_policy": {
"tariff_ref": "REPLACE_WITH_ACCEPTED_PROVIDER_BOUNDS_AND_RATES",
"model": "claude-sonnet-4-6",
"context_tokens": 0,
"max_output_tokens": 0,
"input_microusd_per_token": 0,
"output_microusd_per_token": 0,
"allowed_betas": []
},
"runtime": {
"path": "/absolute/accepted/runtime",
"sha256": "REPLACE_WITH_ACCEPTED_COMPLETE_ARTIFACT_DIGEST"
}
}
```
The placeholders and zero bounds deliberately refuse. The authority reference and
spend digest must match the private existing SpendPolicy. Worker/project, exact
profile/descriptor digests, operational readiness, model, empty-egress bwrap profile
and runtime digest are checked before claim. Runtime, owner state and target checkout
must not overlap. Provision parent and request ledgers as separate reviewed actions.
The normal ACTIVITY_CORE/AGENT_HARNESS worker and state configuration still applies.
The governed Python console launchers must be executable regular files naming
`/opt/sandboxer/runtime/bin/python3`, rather than a build-host interpreter.
The installed bwrap proof also runs their `--help` commands before any model request.
This config is not an authorization decision or a custody provenance proof. The
invoking credential engine must already have passed its exact action approval,
consume, scoped backend/readiness and admitted consumer checks. Its reviewed command
must be the fixed one-cycle owner entry point, with the accepted immutable config.
The current `glas-claude-agent-dev-anthropic` catalog describes delivery through the
sandbox helper and does not yet admit this owner holder. SECRETS-WP-0009-T03 and
HFACT-WP-0001-T03/T04 retain that review, existing client/audit/service dependencies,
Railiance placement and live negative tests. No real key is read by local validation.
This initial bootstrap obtains delivery before one claim cycle; an empty queue still
uses that delivery attempt. It intentionally exits after that cycle. Native scheduled
activation must not wrap a persistent claim loop with one reusable provider credential.
Later per-run acquisition for a continuous worker belongs to REINAH-WP-0003-T05/T06
and the same credential owner; it must retain exact action/lease/budget semantics.
`scripts/prove-metered-runtime.py` runs with a built candidate's `python -I -B`.
It verifies all four packages and definitions come from the artifact, exercises this
CLI once against an empty fake HTTP queue with a synthetic exec-env key, and runs the
pinned actual Claude CLI through the protected bwrap mount and metered owner. The
positive fake stream and pre-forward insufficient-capacity refusal are separate
cases. It checks unchanged artifact digest and teardown. Queue/provider/key/profile
are disposable fixtures, never evidence of live admission. The project records the
candidate result in `prj-helixforge-factory/evidence/2026-09-09-owner-bootstrap.json`.
## Current metered admission review — 2026-09-27
The credential catalog now configures the metered owner and companion, so the
older pending-holder paragraph above is historical. The corrected owner policy and Secrets Engine 11cc0d5 are installed after
explicit user approval; native spend/delivery approval remains open. Use
`../secrets-engine/docs/proposals/glas-metered-20260927/README.md` for exact inputs.
The proof script requires `--profile-ref` and `--expected-model`; for the current
b6e4e8a4 artifact use `--profile-ref harness.agent-dev-local@1.1.1
--expected-model claude-sonnet-5 --context-tokens 1000000
--max-output-tokens 64000 --input-rate 4 --output-rate 10
--extra-beta mid-conversation-system-2026-04-07` in addition to runtime/hash.
The fixture price input is explicit and still grants no paid authority. A passing
first-response proof does not prove a tool loop or native provider compatibility.
Add `--tool-cycle` for a synthetic EUR 10 parent envelope and two provider
requests with an actual Bash git-status tool result. This passed on Railiance;
receipt: `docs/evidence/2026-09-27-sonnet5-tool-session-proof.json`. The fixture
uses native USD 1/max-turns 4 and total EUR 30, not the live owner spend policy.
The requested inactive EUR 10 proposal is in the factory operations directory.