Require declared human control in factory credential delivery
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a07ff8-19d0-7820-b4d0-1353833cb7fc
This commit is contained in:
parent
d1c13b5dd6
commit
2b0d04e8e1
11 changed files with 451 additions and 27 deletions
|
|
@ -86,9 +86,50 @@ authority is approval-engine (checked as `issuer`); the decision's is flex-auth.
|
|||
|
||||
Every live privileged production handler passes `_require_lane_approval`,
|
||||
which calls `require_production_consume` before `OpenBaoClient.resolve`.
|
||||
Dry-run and `plan` do not consume. Build/test remain fail-open relative to
|
||||
approval-engine. The three-factor unsafe-demo exception is not a consume
|
||||
path.
|
||||
Dry-run and `plan` do not consume. For undeclared lanes, build/test and the
|
||||
three-factor unsafe-demo exception retain their existing behavior. An explicitly
|
||||
declared human control requires observation, PDP ALLOW and CAS consumption at
|
||||
every stage; no demo or lane-review fallback discharges it.
|
||||
|
||||
## Declared human-control workflow
|
||||
|
||||
The factory lane explicitly declares `approval.human_control: true`. This
|
||||
implements its existing human action-review requirement and GH-DEC-2026-016;
|
||||
it does not infer human control from a CCR model, stage, actor, or approver entry,
|
||||
and does not make a local authorization decision. Other catalog entries default
|
||||
to undeclared. The catalog value must be a boolean, and `bootstrap-only` cannot
|
||||
be combined with a declared human control.
|
||||
|
||||
The generated CheckRequest includes `context.human_control: true`. This changes
|
||||
its evaluator-bound identity. The separate request-creation caller must issue an
|
||||
unapproved Approval Engine object with **top-level `human_control: true`** and
|
||||
`pdp_path: true`, using the actual evaluator-origin digest of that exact claim-free
|
||||
request. A human subsequently supplies `/entries` through the admitted approver
|
||||
surface. Do not copy an old request digest or retrofit an existing approval.
|
||||
Approval Engine retains its unchanged five-field native act digest; the consumer
|
||||
joins through the distinct evaluator-origin PDP digest as before.
|
||||
|
||||
At observation, this engine requires **`claim.binding.human_control is true`**
|
||||
in addition to current validity, freshness and the PDP path. Missing, false,
|
||||
string or numeric declarations refuse before the PDP call. The declaration is
|
||||
checked again after PDP validation and carried in the internal consume binding
|
||||
and non-secret `approval_human_control` evidence. A declared lane cannot skip
|
||||
consumption through a build/test or unsafe-demo fallback. The consumer does not
|
||||
reconstruct approver identities or counts: Approval Engine owns that evidence.
|
||||
|
||||
The repeatable `tools/exercise_approval_identity.py --exec-owner --human-control`
|
||||
exercise creates a declared request through the actual engine API, proves a real
|
||||
KeyCape service JWT cannot bind it, proves an undeclared claim cannot reach the
|
||||
PDP/consume/backend path, and proves the real evaluator preserves the requirement.
|
||||
The positive human entry is **seeded in the disposable store**, while requester,
|
||||
claim and consume use real local service authentication. The backend and child
|
||||
payload are synthetic; this is not human JWT/PKCE or live custody evidence.
|
||||
See [the component receipt](evidence/2026-09-10-human-control-consumer-exercise.json).
|
||||
|
||||
Native narrow requester identity, browser human approval, admitted custody and
|
||||
current deployed services remain APPROVAL-WP-0002-T01/T03/T05,
|
||||
INFD-WP-0001-T07/T08 and SECRETS-WP-0009-T03. The factory catalog's exec owner
|
||||
remains pending; adding this requirement grants no runtime or credential access.
|
||||
|
||||
## Fail closed
|
||||
|
||||
|
|
@ -110,8 +151,9 @@ digest, idempotence, and consumed-at only. No token, secret, or accessor.
|
|||
|
||||
## Required configuration
|
||||
|
||||
The join is absent by default, so an unconfigured engine behaves exactly as it
|
||||
did before. Production additionally needs:
|
||||
The join is absent by default. Undeclared lanes retain their existing behavior;
|
||||
a lane declaring `approval.human_control: true` refuses an absent join.
|
||||
Production and declared human-control paths need:
|
||||
|
||||
| Variable | Meaning |
|
||||
| --- | --- |
|
||||
|
|
|
|||
|
|
@ -127,3 +127,16 @@ Before accepting an existing production lane:
|
|||
lanes. Set `false` when the consumer needs only the KV data GET; generated
|
||||
policy omits the metadata endpoint. Owner metadata verification then needs
|
||||
separate operator authority, not broader consumer access.
|
||||
|
||||
## Explicit human-control requirement
|
||||
|
||||
`approval.human_control` is an optional boolean, defaulting to undeclared. Set it
|
||||
to `true` only for a workflow whose existing contract requires human review. It
|
||||
is not inferred from `approval.model`, stage or principal type. A declared lane
|
||||
cannot use `bootstrap-only`; its live action requires an Approval Engine claim
|
||||
explicitly declared human-controlled, current PDP ALLOW and CAS consumption.
|
||||
Missing services cannot fall back to ordinary lane review or an unsafe demo.
|
||||
See [the requester and consumer contract](approval-consumption.md#declared-human-control-workflow).
|
||||
The HelixForge native-delivery catalog declares this requirement and remains
|
||||
pending owner admission. No OpenBao policy, role, credential or readiness state
|
||||
is activated by this source declaration.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,80 @@
|
|||
{
|
||||
"schema_version": 1,
|
||||
"target": "disposable local processes; synthetic credentials",
|
||||
"started_at": "2026-09-10T18:15:35.247006+00:00",
|
||||
"keycape_image": "forgejo.coulomb.social/coulomb/key-cape@sha256:7ff54c54e63ee172ae9e6e7fd2da96e427352f712343d74626ee6fe0f6f82611",
|
||||
"approval_engine_commit": "c8f85c6d7691f2319ad462791e6d385515d7e70d",
|
||||
"flex_auth_commit": "88b354377c8e26b162f1234e673072f1c06dcd89",
|
||||
"keycape_contract_commit": "f9812ab3b2bfe8f0817185f44071e612264ec3ee",
|
||||
"consumer_source_sha256": {
|
||||
"approval_auth.py": "6f3b033e7928e1c527bc19f5a1e01bf243540769a8646bd8cd47268da25637b5",
|
||||
"approval_consume.py": "4515c74dbe1cea030cdccebf17b27642ad4f67f2aaee4f3a87e4bb2b9cfad295",
|
||||
"approval_claim.py": "20b728d2d3e14ffc89fa21a137716015875f9a05c6af7ff48d07cf48d89503a9",
|
||||
"authorization.py": "c2b6679b4235611c4fd39dad8964a522378df42c0658f0a02dcc31f05141d6a0",
|
||||
"config.py": "2f2f1b60664d89bbb806aed0c768378923062077740e1f96e4c359238eb06955",
|
||||
"service_auth.py": "653723ef5babce2157771416d93cb15cdbb7caca3c45509c3730520c55e4515c",
|
||||
"cli.py": "1147d0e60850cfc38ee21e8564f51656d364ddc3cd8d6353a0c2dd6a0b78b8ec",
|
||||
"catalog.py": "247c29314bcf86b3439d756ed911df62fb43c3c498b18ce5403704986a501b18",
|
||||
"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",
|
||||
"positive human entry seeded in disposable store; no human JWT/PKCE proof"
|
||||
],
|
||||
"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,
|
||||
"declared_control_refuses_real_keycape_service_bind": true,
|
||||
"undeclared_control_refused_before_real_pdp_consume_backend": 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,
|
||||
"declared_human_intent_preserved_by_real_evaluator": true,
|
||||
"declared_human_fixture_consumed_before_owner_delivery": 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-10T18:15:47.092615+00:00",
|
||||
"consumer_base_commit": "d1c13b5dd667bcad453c94564f65bdf5f172ba3b",
|
||||
"source_suite": {
|
||||
"passed": 388,
|
||||
"new_cases": 27,
|
||||
"first_25_cases_failed_before": 25,
|
||||
"log_sha256": "e676747dc0f2547e42bf0f3d7f97a3e1a6da4d413428b44afe28d725abd7a4c7"
|
||||
},
|
||||
"factory_attempts": 0,
|
||||
"paid_model_calls": 0,
|
||||
"native_human_approval_proof": false,
|
||||
"remaining_records": [
|
||||
"SECRETS-WP-0009-T03",
|
||||
"APPROVAL-WP-0002-T01/T03/T05",
|
||||
"INFD-WP-0001-T07/T08",
|
||||
"RPF-WP-0035-T06 / CCR-2026-0019",
|
||||
"HFACT-WP-0001-T01/T03/T04/T05"
|
||||
],
|
||||
"command": "python tools/exercise_approval_identity.py --keycape-source PATH --approval-engine-source PATH --flex-auth-source PATH --exec-owner --human-control --receipt NEW_PATH"
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue