Bind credential exec to exact owner inputs and approval digest
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a07ff8-19d0-7820-b4d0-1353833cb7fc
This commit is contained in:
parent
9eb07fd8fc
commit
42b48aa54f
13 changed files with 626 additions and 7 deletions
57
docs/evidence/2026-09-10-exec-owner-approval-exercise.json
Normal file
57
docs/evidence/2026-09-10-exec-owner-approval-exercise.json
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
{
|
||||
"schema_version": 1,
|
||||
"target": "disposable local processes; synthetic credentials",
|
||||
"started_at": "2026-09-10T07:15:53.047975+00:00",
|
||||
"keycape_image": "forgejo.coulomb.social/coulomb/key-cape@sha256:7ff54c54e63ee172ae9e6e7fd2da96e427352f712343d74626ee6fe0f6f82611",
|
||||
"approval_engine_commit": "62233c7c52447a6065055933a9c7cc1cfe3059eb",
|
||||
"flex_auth_commit": "88b354377c8e26b162f1234e673072f1c06dcd89",
|
||||
"keycape_contract_commit": "324b5e056dcfd5c6336750cd7a7b7f8c5ca2255f",
|
||||
"consumer_source_sha256": {
|
||||
"approval_auth.py": "6f3b033e7928e1c527bc19f5a1e01bf243540769a8646bd8cd47268da25637b5",
|
||||
"approval_consume.py": "9ccc6997fd4c1c82af8cf3dd440daf7b695d6272bb302eb083b73a2fe3674345",
|
||||
"approval_claim.py": "54dd469e4e3ac9472c4e21222d5a08f70723a63f01904a35922fcc0a07a41541",
|
||||
"authorization.py": "0656589832b7218cc1603890e93a3e09513af8b59694f279defa764a1edb30c9",
|
||||
"config.py": "2f2f1b60664d89bbb806aed0c768378923062077740e1f96e4c359238eb06955",
|
||||
"service_auth.py": "653723ef5babce2157771416d93cb15cdbb7caca3c45509c3730520c55e4515c",
|
||||
"cli.py": "1147d0e60850cfc38ee21e8564f51656d364ddc3cd8d6353a0c2dd6a0b78b8ec",
|
||||
"catalog.py": "7e77c89a2543e3759f1322aca9b9167b904bb30e1aec867c4415dfde4bddd5fa",
|
||||
"exec_owner.py": "10c21e7e37dd3d0aad41c4bb15df8f4a69c22d9046105a981a9613a91cd4c145",
|
||||
"exec_delivery.py": "b142b60d875acf3dea1ba3ae99182a7ed7328d955dee5be2d12c977fc5646e8e",
|
||||
"routing.py": "9d5050d7494a207394ce8251d8aac574ca0c08e3252639b5f05b373d6e35a076"
|
||||
},
|
||||
"limitations": [
|
||||
"standalone Flex Auth source, not deployed pin",
|
||||
"local Approval Engine source, not deployed image",
|
||||
"no live custody or client-side read grant",
|
||||
"no OpenBao effect or model execution"
|
||||
],
|
||||
"checks": {
|
||||
"operator_issued_and_approved_via_verified_jwt": true,
|
||||
"wrong_action_refused_before_consume": true,
|
||||
"producer_origin_join_with_carried_claim": true,
|
||||
"actual_consumer_claim_check_consume": true,
|
||||
"same_digest_retry_idempotent": true,
|
||||
"different_digest_refused": true,
|
||||
"spent_claim_refused": true,
|
||||
"operator_consume_scope_denied_by_issuer": true,
|
||||
"wrong_secret_refused": true,
|
||||
"no_access_token_file_created": true,
|
||||
"registry_override_accepts_exact_submission": true,
|
||||
"same_enriched_result_different_submission_refused": true,
|
||||
"real_dual_control_denial_then_claim_check_consume": true,
|
||||
"exec_owner_substitution_refused_before_consume_backend": true,
|
||||
"exec_owner_changed_environment_replay_refused_by_real_pdp_join": true,
|
||||
"exec_owner_real_cli_consumes_before_fixture_backend": true,
|
||||
"exec_owner_actual_child_excludes_parent_credentials": true,
|
||||
"exec_owner_digest_preserved_by_real_evaluator": true
|
||||
},
|
||||
"flex_auth_binary_sha256": "c7a1f35aa2cd7cf2733272923ace7fc4b4e55171db4ef8f3d0d6629183dcf1fa",
|
||||
"producer_input_sha256": {
|
||||
"policy_package.md": "657fa9312c9dcabee059ec31c89ee13396fe9aa54d852edc9e6559a74bbc139a",
|
||||
"registry_snapshot.json": "37fba44ec0e0fd9b1e17a05ad1b7e4f9bb6ec9e0fc0bb3133e8af2ac6f832d7c"
|
||||
},
|
||||
"exec_owner_scope": "Synthetic recipient/backend with real KeyCape, Approval Engine, Flex Auth and Secrets Engine CLI; not native custody or human approval proof",
|
||||
"status": "passed",
|
||||
"cleanup_complete": true,
|
||||
"finished_at": "2026-09-10T07:16:09.750288+00:00"
|
||||
}
|
||||
93
docs/exec-owner-binding.md
Normal file
93
docs/exec-owner-binding.md
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
# Bind native exec delivery to its reviewed recipient
|
||||
|
||||
SECRETS-WP-0009-T03. Implemented 2026-09-10. This constrains delivery; it is not
|
||||
an approval or proof of native credential access.
|
||||
|
||||
Previously `exec` consumed approval for a catalog/action/field, then accepted an
|
||||
arbitrary child command and copied the invoking engine's full environment. The
|
||||
factory recipient is now a pinned metered owner outside the sandbox. A different
|
||||
command or inherited engine credential would violate that boundary.
|
||||
|
||||
Catalog `delivery_config.exec_owner` is optional for existing lanes. The Claude
|
||||
factory lane explicitly requires it and currently declares `status: pending`,
|
||||
`owner` and `reason`. Pending means no exec: refusal precedes approval consumption,
|
||||
backend opening and secret retrieval. Routing stays unready even if custody exists.
|
||||
|
||||
A reviewed binding uses exactly these keys:
|
||||
|
||||
| Key | Required content |
|
||||
| --- | --- |
|
||||
| `status` | `configured`; this describes configuration, not authorization |
|
||||
| `owner` | Named trusted recipient |
|
||||
| `command` | Exact argv; absolute executable, no caller-selected additional arguments |
|
||||
| `cwd` | Exact private owner directory |
|
||||
| `environment` | Complete non-secret environment; no inheritance from the engine |
|
||||
| `files` | Absolute path → `{sha256: <64 lowercase hex>, private: <boolean>}` |
|
||||
|
||||
The executable and every absolute file argument require pins. Include the exact
|
||||
owner JSON and all immutable files it references, such as the spend-policy and
|
||||
accepted profile/descriptor configuration. Mutable ledgers are private state,
|
||||
not immutable file pins. The runtime owner retains whole-artifact and operational
|
||||
profile verification; hashing an interpreter alone does not verify its packages.
|
||||
|
||||
File checks refuse symlinks, nonregular inputs, untrusted owners, group/world
|
||||
writable paths and ancestors, changed bytes and exposed private inputs. Root-owned
|
||||
sticky temporary ancestors are allowed for contained proof. The working directory
|
||||
is private. The engine and configured owner UID remain trusted: this does not
|
||||
protect against that same trusted UID replacing files between checks and launch.
|
||||
Runtime and native service admission must preserve this trust boundary.
|
||||
|
||||
Only exec-env is allowed with this binding. The child receives the fixed environment
|
||||
plus the selected declared field; loader overrides and engine/provider auth
|
||||
variables cannot be supplied as fixed environment configuration. No values belong
|
||||
in the catalog. Queue/service credentials, if needed by the owner, require their
|
||||
separate admitted custody path. Child stdin is closed; stdout/stderr retain the
|
||||
existing value redactor. An arbitrary encoding by a malicious recipient is not
|
||||
made safe by redaction; the recipient itself must be trusted and admitted.
|
||||
|
||||
SHA-256 of the complete canonical binding is carried as
|
||||
`context.exec_owner_sha256` on the `exec` CheckRequest. The existing producer digest
|
||||
and approval join bind it without introducing another decision type. Changing
|
||||
command, file pins, environment, cwd or owner changes the request and requires new
|
||||
exact-action approval. Local checks run before approval/backend, again before
|
||||
retrieval, and after retrieval before launch; the admitted digest must still match.
|
||||
Configured bindings still pass existing approval, consume, lane-state and scoped
|
||||
backend checks. Other actions and lanes without this opt-in retain their contracts.
|
||||
|
||||
## Factory activation input
|
||||
|
||||
Use the installed artifact and paths in
|
||||
`prj-helixforge-factory/evidence/2026-09-10-runtime-placement.json`. The intended argv:
|
||||
|
||||
```text
|
||||
<protected-runtime>/bin/python3 -I -B -m rein_aharness.cli metered-once --owner-config <private-owner-config>
|
||||
```
|
||||
|
||||
Do not use the rolling CLI alias or a persistent claim loop. Complete and pin the
|
||||
private owner configuration, profile and spend inputs under HFACT-WP-0001-T01/T04;
|
||||
bind the required worker environment explicitly. Then review the MessagesOwner
|
||||
holder under this task and the existing native action/reader gates. The provider
|
||||
key stays in the metered owner; the workload receives the opaque local route token.
|
||||
The historical sandbox-helper child-key route is not this holder admission.
|
||||
|
||||
## Verification
|
||||
|
||||
The full suite passed 361 tests, including a real child with a synthetic key,
|
||||
fixed environment, closed stdin, redaction and substituted/config-changed refusal.
|
||||
The disposable integration exercise passed 18 checks using the pinned KeyCape
|
||||
image, actual Approval Engine and compiled Flex Auth, including five new owner
|
||||
checks: substituted argv refusal before consume/backend, changed-environment
|
||||
replay refusal, consume-before-backend, isolated child environment and preserved
|
||||
recipient digest. OpenBao and recipient are fixtures in this exercise. The
|
||||
historical combined operator identity is a synthetic test issuer fixture, not a
|
||||
request to restore CCR-2026-0020 or evidence of real human approval.
|
||||
|
||||
```bash
|
||||
uv run --extra dev --with 'PyJWT[crypto]>=2.7,<3' python tools/exercise_approval_identity.py \
|
||||
--keycape-source ../key-cape --approval-engine-source ../approval-engine \
|
||||
--flex-auth-source ../flex-auth --exec-owner --receipt /tmp/<new-receipt>.json
|
||||
```
|
||||
|
||||
Receipt: `docs/evidence/2026-09-10-exec-owner-approval-exercise.json`.
|
||||
Native custody, exact operator group/file delivery, real human/audit/service path,
|
||||
accepted factory configuration and paid execution remain open.
|
||||
|
|
@ -5,6 +5,13 @@ railiance-platform CCR-2026-0016; implementation/activation record SECRETS-WP-00
|
|||
KV custody is already confirmed at version 2. Do not provision or rotate it as
|
||||
part of native read-lane adoption.
|
||||
|
||||
2026-09-10: the factory continuation uses a metered MessagesOwner outside the
|
||||
sandbox. Its exact runtime is installed and synthetically proved on Railiance.
|
||||
The catalog now blocks exec with an explicit pending recipient binding until the
|
||||
native holder and immutable configuration are admitted. See
|
||||
[exec owner binding](exec-owner-binding.md). The older transport description
|
||||
below records the original child-key route; it cannot admit the metered holder.
|
||||
|
||||
The generated plan checks existing mount `platform`, creates policy and AppRole
|
||||
`se-prod-glas-claude-agent-dev-anthropic`, and grants read only on
|
||||
`platform/data/workloads/glas-harness/claude-agent-dev`. Field ANTHROPIC_API_KEY
|
||||
|
|
@ -37,7 +44,7 @@ catalog and service-jwt selection. No real value was requested.
|
|||
|
||||
Activation depends on SECRETS-WP-0007-T04 (exact production actions) and
|
||||
SECRETS-WP-0008-T02/T06 (decision consumption and service authority). Require
|
||||
canonical ActionAuthorization for each protected action, successful consume,
|
||||
canonical validated DecisionEnvelope for each protected action, successful consume,
|
||||
and exact scoped backend authority. This draft cannot authorize itself; an
|
||||
operator browser token or unsafe-demo flag is not a runtime substitute.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue