Document exact native signer and CLI admission requirements
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 2s

Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a140c4-354a-7823-8f0d-8f717397f786
This commit is contained in:
tegwick 2026-10-16 10:48:40 +02:00
parent ff1a13dabd
commit 5a2099f400
6 changed files with 351 additions and 36 deletions

View file

@ -0,0 +1,158 @@
# Native CLI signer and consumer admission preparation
This proposal covers the existing lifecycle CLI authentication path under
SECRETS-WP-0014. It grants no installation, key retrieval, caller mint, approval
consume, OpenBao effect or task-policy activation. All native acceptance counts
below are zero. Exact missing owner inputs are in `proposal.json`.
## Current consumer and initial scope
At source `ff1a13d`, the workstation has the repository's editable v0.1.0 CLI
entrypoint at `/home/worsch/secrets-engine/.venv/bin/secrets-engine`, importing
`secrets_engine.cli:main`. There is no global `~/.local/bin/secrets-engine` or uv
managed Secrets tool. Presence-only inspection of this session found none of the
PDP/trust/approval/policy/configuration variables set. This says nothing about
other sessions, private owner configuration or a remote installation. No credential
file, private configuration or process environment was inspected.
Use a separately reviewed immutable wheel-plus-verifier bundle for proposed
adoption. The canonical source for the candidate build is **ff1a13d**, containing
both CLI packaging and strict R2 handoff; earlier c80-based proof bundles are
intermediate source evidence. Custodian `decision-native-preparation/` retains the
exact canonical bundle manifest and hashes. Nothing was installed by this step.
Initial stage is signer-only existing lifecycle-pin admission plus offline
verification of captured native signed allow and deny records. Capturing those
records later needs its own admitted caller and exact source operation; this
proposal does not grant that capture. Use Access's one receipt verifier,
`tools/verify_native_signer_receipt.py`, with its reviewed admission file rather
than creating another consumer verifier or canonicalization implementation.
That tool is separate Access source preparation; its exact integrated revision
and reviewed admission file remain owner inputs, not part of this CLI install.
The producer-owned offline pin is `secrets-engine.catalog-lane.lifecycle` v2,
`sha256:bd11c5fe77ce6439c65fea225ad6b71d2110efc5e7b5bc9b499c59cd0a53b8b4`,
evaluator `flex-auth/local`, mode `standalone`. A source digest is not proof of the
live image's source or policy. Access's live metadata records the current pin has
no signer arguments/mounts; no production kid/public key/fingerprint/custody
receipt or candidate signed-runtime OCI digest is admitted. The proposed signer
custody route is draft/nonresolvable. Do not fill those gaps from fixture keys or
from the same responder's keys endpoint. The independent receipt must bind signer
purpose/custody to this exact consumer pin and declare any sharing. A shared key
plus the generic evaluator name cannot prove an individual pod's identity; the
owner-bound tunnel and rollout identity still require separate verification.
`lifecycle-trust.template.json` uses the existing runtime trust schema and the
producer-owned source pin, but deliberately has an empty key map. It **must
refuse** before caller credential access. It is not a deployable trust file. A
future owner-admitted copy must contain the independently authenticated actual
kid/key and exact pin, with its public-key fingerprint/custody provenance retained
outside this unadmitted template. The task-policy coordinate is not admitted here.
## Exact PEP denominator
The initial shared authentication implementation is one Check client reached
through `authorize_action` and `_require_lane_approval`. Native protected-effect
coverage remains **0 of 11 serving CLI call sites across 10 handlers**, not one
PEP per catalog row. The current lifecycle policy's action vocabulary has twelve
values; that is a separate count from handler/call-site coverage.
| CLI path | Handler / delegated authorization site | PDP action |
| --- | --- | --- |
| apply, live only | `cmd_apply` | apply |
| provision | `cmd_provision` | provision |
| rotate, live only | `cmd_rotate` | rotate |
| verify | `cmd_verify` | verify |
| handoff | `cmd_handoff` | handoff |
| wrap | `cmd_wrap` | wrap |
| exec primary | `cmd_exec`, primary gate | exec |
| exec companion | `cmd_exec`, delegated companion gate | exec for each companion; separate claim/CAS, same call site |
| revoke, live only | `cmd_revoke` | deactivate |
| lifecycle compromise/reactivate, live only | `_cmd_lifecycle_state` | selected compromise/reactivate; local state mutation |
| lifecycle suspend/deactivate/destroy, live only | `cmd_lifecycle` | selected operation |
`session revoke` is a separate stance/readiness-controlled backend path without
this served Check/CAS chain; it is excluded from this signer acceptance and still
refuses production under its stance. `service-auth probe-openbao` is an explicit
identity/login-self probe, not protected task adoption. `route` performs existing
backend readiness metadata probes through its ambient backend resolver; it is not
closed by this signer proposal. Dry-run/plan/catalog/audit/source evidence commands
are not protected-effect proof. These exclusions must remain visible in any claim
about the whole repository's PEP coverage.
The existing CLI handlers still use the generic `require_production_consume`
response contract. Strict R2 task consumption is a separate owner API, not a
retrofit of all eleven CLI sites. Native effect acceptance must review the actual
selected handler/consume contract and caller scope rather than borrow the task
fixture proof.
No production effect is authorized merely because a handler shares the signed
client. In particular, configured `service-jwt` still refuses protected CLI work
before approval/CAS/backend because CCR38 is identity-only. Do not select
bootstrap/env, alter the stance or enable unsafe-demo to manufacture acceptance.
## Owner-controlled placement and minimum configuration
The deploying owner must select the runtime UID, fresh release prefix, configuration
parent and exact runtime paths; none is agreed by this proposal. The future
admitted executable is `<prefix>/bin/secrets-engine`, whose wrapper fixes the
bundle helper and checks its digest before CLI import. The helper's source/binary
hash is artifact integrity, not independent package or key admission. Do not use
the editable checkout, a rolling alias, a synthetic test prefix or an internal
venv entrypoint as if it were that admission.
Explicit absolute owner-admitted catalog, policy, `SECRETS_ENGINE_PEP_STANCE`,
trust and evidence/outbox locations are needed. Installed-package defaults fall
back to working-directory metadata and are not an admitted native configuration.
The total existing stance remains prod fail_closed. Config needs the exact
producer policy/version, service subject, loopback owner-bound PDP tunnel and
separately admitted bounded audience `flex-auth` caller-file lifetime. Approval
endpoint and its existing separately scoped credential delivery must be admitted
independently. Both approval credential providers may not be configured together.
The bundle helper is not selected by an ambient override. Runtime credentials and
keys are not placed in this proposal or release bundle.
Acceptance order is: admit exact package/source/install/config; obtain independent
signer/key/pin custody return and exact signed producer rollout candidate; under
that separately reviewed rollout capture bounded native records; run Access's
single offline receipt verifier against the fixed installed helper and admitted
trust; prove forged/altered/unknown/unsigned/wrong-pin/expired refusal and exact
old/new-key overlap then removed-key refusal. Also close the producer's missing
native durable log/outbox/audit path under its owner. No install or rollout is
performed here, and shared-source tests do not fill native effect coverage.
Rollback retains the reviewed signed producer and admitted overlap or stops the
consumer. Rolling back to an unsigned image is an outage, not permission to turn
off verification. Removing keys, changing policy pins or restoring removed keys
needs exact owner review; no discovery/cached-key fallback or blind consume retry.
## Separate task-execution gap
Strict `task_execution_handoff` exists and Platform's independently confirmed
journal/native fixture path has actual source-server proof. Neither creates an
existing `execute-ccr` CLI command: the current parser has none. Proposed task
caller mapping/request join, policy admission, production source/Plan/grant and
installation/journal/cleanup placement remain separate owner decisions. Both
Access task-policy runtime false gates remain unchanged; lifecycle apply is not
a substitute for execute-ccr. Platform has selected no fresh approved real
CCR/catalogue/descriptor/grant. CCR42 is in_flight and lacks a matching Secrets
catalog; synthetic CCR2/issue-core fixture bytes and temporary paths are not native
inputs. Actual before/after bytes for the exact metadata targets and independent
readback/cleanup receipts must come from Platform's eventual owner-selected plan.
For future server-owned Approval facts, strict R2 deliberately requires the
returned binding context to equal the originally submitted context. B1 caller
join remains signed-DENY and must preserve that context. Replacing the carried
claim with a freshly observed blob would refuse because its freshness fields
change; no generic equality relaxation is proposed. Access's current review
preference is to validate fresh authoritative facts out of band while retaining
the submitted context, with reviewed producer-owned signed source/receipt evidence.
Exact stable fact/freshness and provenance correspondence requires Approval and
Access review before B2/B3; no new fields or behavior are implemented here.
The Approval owner's pending `approval-fact-contract/consumer-contract.md` and
`golden-vectors.json` in the Custodian target evidence name this correspondence.
They require both original/fresh windows and exact nonfreshness authority facts.
Their Python native numeric canonical vectors still need producer conformance;
no silent digest translation or new target numeric restriction is admitted.
The proposal pins those owner artifacts for review, not as B2 implementation.

View file

@ -0,0 +1,9 @@
{
"schema": "secrets-engine.pdp-trust.v1",
"evaluator": "flex-auth/local",
"mode": "standalone",
"policy_package": "secrets-engine.catalog-lane.lifecycle",
"policy_version": "v2",
"policy_package_digest": "sha256:bd11c5fe77ce6439c65fea225ad6b71d2110efc5e7b5bc9b499c59cd0a53b8b4",
"keys": {}
}

View file

@ -0,0 +1,133 @@
{
"proposal_id": "SECRETS-WP-0014-native-cli-20261016",
"status": "preparation only; not installable or executable authorization",
"source_base": "ff1a13dabd44ba02ddd6bc26ad75568f6d2e6225",
"workplans": [
"SECRETS-WP-0014-T02",
"SECRETS-WP-0014-T03",
"SECRETS-WP-0013-T01",
"SECRETS-WP-0013-T03"
],
"initial_scope": {
"producer": "existing flex-auth/flex-auth-secrets-engine lifecycle pin",
"consumer": "existing Secrets CLI serving authorization workflow, prospective reviewed release-bundle entrypoint only",
"stage1": "independent signer/package/trust admission and offline captured native allow+deny verification; zero protected effects",
"native_effects_admitted": 0,
"task_execution_enabled": false
},
"owner_returns": {
"access": "Custodian docs/changes/netkingdom-target-2026-10-16/access-native-preparation/native-admission-proposal-r1.json and source-policy-pins.json",
"platform": "No selected actual approved CCR/catalog/Plan/descriptor/grant/install placement; CCR-2026-0042 remains in_flight without matching catalog. Disposable source proofs are not production inputs."
},
"producer_pin": {
"evaluator": "flex-auth/local",
"mode": "standalone",
"policy_package": "secrets-engine.catalog-lane.lifecycle",
"policy_version": "v2",
"policy_package_digest": "sha256:bd11c5fe77ce6439c65fea225ad6b71d2110efc5e7b5bc9b499c59cd0a53b8b4"
},
"independent_admission": {
"production_kid": null,
"public_key": null,
"public_key_sha256": null,
"custody_receipt": null,
"candidate_producer_oci_digest": null,
"rule": "No responder keys endpoint, synthetic fixture key or deployment metadata substitutes for independent owner admission",
"receipt_verifier_integrated_revision": null,
"signer_purpose_pin_and_sharing_receipt": null
},
"placement": {
"owner": "Secrets consumer/deploying owner; exact runtime UID and paths not yet agreed",
"cli_release_prefix": null,
"cli_entrypoint": "<admitted-prefix>/bin/secrets-engine",
"fixed_verifier": "<admitted-prefix>/libexec/secrets-engine-pdp-verify",
"config_parent": null,
"trust_file": null,
"catalog_directory": null,
"policy_directory": null,
"pep_stance_file": null,
"evidence_directory": null,
"constraints": [
"new owner-controlled immutable release prefix; no overwrite or rolling source alias",
"absolute independently reviewed config/catalog/policy/stance/trust paths; no working-directory defaults for native use",
"trust regular non-symlink, not group/world writable; key admission not file-presence inference",
"owner retains manifest/admission/installation receipts and same-UID control boundary"
]
},
"configuration_contract": {
"SECRETS_ENGINE_PDP_URL": "literal loopback bare origin bound to independently verified cluster and named producer pod; exact native port awaiting owner placement",
"SECRETS_ENGINE_PDP_TOKEN_FILE": "admitted bounded Secrets ServiceAccount caller file outside Git; no mint/read here",
"SECRETS_ENGINE_PDP_TRUST_FILE": "absolute independently admitted lifecycle trust path; empty-key template deliberately refuses",
"SECRETS_ENGINE_PDP_VERIFIER": "bundle wrapper fixes installed helper; no ambient override or source-checkout helper",
"SECRETS_ENGINE_AUTHORIZATION_SUBJECT_ID": "secrets-engine",
"SECRETS_ENGINE_AUTHORIZATION_SUBJECT_TYPE": "service",
"SECRETS_ENGINE_AUTHORIZATION_POLICY_PACKAGE": "secrets-engine.catalog-lane.lifecycle",
"SECRETS_ENGINE_AUTHORIZATION_POLICY_VERSION": "v2",
"SECRETS_ENGINE_APPROVAL_URL": "independently admitted Approval endpoint/owner-bound tunnel; not yet supplied for this session",
"SECRETS_ENGINE_APPROVAL_CLIENT_SECRET_FILE": "separately admitted attended provider lifetime from existing custody contract; no read here",
"SECRETS_ENGINE_APPROVAL_TOKEN_FILE": "unset when client-secret provider selected; no simultaneous providers",
"SECRETS_ENGINE_CATALOG": "absolute owner-admitted metadata directory; initial actual lane unselected",
"SECRETS_ENGINE_POLICIES": "absolute owner-admitted metadata/policy directory",
"SECRETS_ENGINE_PEP_STANCE": "absolute hash-pinned existing total stance map; prod remains fail_closed",
"SECRETS_ENGINE_EVIDENCE": "absolute owner-private evidence/outbox path with declared custody/delivery",
"SECRETS_ENGINE_UNSAFE_DEMO": "unset; no native exception",
"backend_provider": "no new selection/entitlement; configured service-jwt protected handlers remain blocked; do not switch to bootstrap/env as workaround"
},
"rotation": {
"admit": "owner reviews independent new kid/public key/custody receipt and bounded overlap, preserving exact issuer/policy artifact pin",
"roll": "separate exact producer candidate digest/seed projection rollout with native signed receipts; never fetch discovery keys",
"remove": "after new-key native receipt/consumer acceptance, remove old kid and prove old-key refusal",
"rollback": "retain reviewed signed producer/key overlap or stop/refuse. An unsigned old deployment is an outage; never disable consumer verification, restore removed key without review, relax pin, widen backend grants or blind retry consumed operation"
},
"task_mapping_gap": {
"existing_cli_execute_ccr_command": false,
"source_handoff": "secrets_engine.task_execution_handoff authorize_task_execution/consume_task_execution",
"platform_source_mediator": "railiance-platform/scripts/task_execution_mediator.py run_native_fixture_task; source proof only",
"unadmitted_inputs": [
"real service caller-to-subject server mapping and request/service binding join",
"actual task policy candidate and independently reviewed source/runtime admission; both false gates unchanged",
"owner-selected fresh approved CCR/catalog/execution-grant, compiled Plan/whole descriptor and operation UUID",
"independent expected-before/after bytes for exact two metadata targets and actual estate/backend origin",
"actual source/Plan/install/journal/cleanup placement and trusted provider endpoints/credentials/custody",
"load-bearing audit/outbox cadence and durable receipt correlation",
"Approval/Access reviewed out-of-band fresh-fact versus original carried-claim correspondence and signed provenance; strict context equality remains unchanged"
],
"approval_fact_interface_review": {
"status": "review preference only; no implementation/admission",
"preserve": "strict binding.context equality and original submitted/approval-free/native joins",
"direction": "Access prefers out-of-band server-fetched authoritative fact checking while retaining original carried context, then reviewed producer-owned signed provenance/audit evidence",
"required_review": [
"Approval fact/freshness semantic correspondence",
"Access source receipt/provenance binding and exact request digests"
],
"b1": "signed-DENY caller join only; no context replacement",
"b2_b3": "not enabled or implemented here"
},
"approval_fact_contract": {
"artifact": "the-custodian/docs/changes/netkingdom-target-2026-10-16/approval-fact-contract/consumer-contract.md",
"sha256": "3dfb7987a4d9fe461b917cfa5bae7beef61bc4d9a4561fdded3e90128f5966de",
"vectors_artifact": "the-custodian/docs/changes/netkingdom-target-2026-10-16/approval-fact-contract/golden-vectors.json",
"vectors_sha256": "dfb0a8810cd91847d7af6a7af6a51607a67a66fad7b86fc57365308c36bd9323",
"status": "owner source contract pending integration; no Go conformance or B2 behavior admitted",
"required": "preserve original fact/context/freshness, independently validate fresh fact window and exact nonfreshness authority; do not translate native numeric digests or invent target restrictions"
}
},
"approval_state": "no owner assent, key admission, install, caller token, operation grant or live change requested/executed by this preparation",
"denominator": {
"shared_check_implementation": 1,
"serving_cli_call_sites": 11,
"serving_cli_handlers": 10,
"lifecycle_pdp_action_values": 12,
"native_effect_call_sites_accepted": 0,
"excluded": [
"session revoke stance-only backend path",
"service-auth explicit identity probes",
"route ambient-backend readiness probes",
"dry-run/non-effect reporting"
],
"task_cli_command_count": 0,
"platform_source_mediator_native_acceptance": false,
"generic_cli_consume_is_strict_task_handoff": false,
"effect_acceptance_required": "Review actual selected handler/generic consume response and caller scope separately; strict Platform fixture proof does not close existing CLI effects"
}
}