Document exact native signer and CLI admission requirements
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a140c4-354a-7823-8f0d-8f717397f786
This commit is contained in:
parent
ff1a13dabd
commit
5a2099f400
6 changed files with 351 additions and 36 deletions
|
|
@ -23,20 +23,20 @@ $ getent hosts this-service-does-not-exist.flex-auth.svc.cluster.local
|
|||
`*.svc.cluster.local` name answers with one unrelated public address. Sending
|
||||
there ships the CheckRequest body and our bearer token to a third party.
|
||||
|
||||
`flex-auth.decision-record.v1` supports a detached Ed25519 signature on the
|
||||
producer side (FLEX-WP-0024), but this consumer does not yet verify it against
|
||||
independently admitted keys. Without that verification, every binding digest
|
||||
is either sent by us or published in flex-auth's repo, so a forger can
|
||||
reproduce those digests. Digests establish integrity of the binding, never
|
||||
authenticity of the source. As flex-auth put it in `FLEX-DEC-2026-010`:
|
||||
As of source `ff1a13d` (2026-10-16), this consumer requires the producer's
|
||||
detached Ed25519 signature using independently admitted local keys and exact
|
||||
signed evaluator/mode/policy pin. The complete CLI wheel-plus-helper bundle and
|
||||
strict task handoff are implemented in source. Native signer custody, key/pin
|
||||
admission, installed placement and actual consumer receipts remain unaccepted;
|
||||
source enforcement does not establish those facts. See
|
||||
[the scoped native preparation](proposals/native-cli-admission/README.md).
|
||||
|
||||
> Fail-closed protects against a PDP that is ABSENT, not against one that LIES.
|
||||
|
||||
The literal loopback address restriction limits the destination; it does not
|
||||
prove responder identity. The operator must verify the cluster and named pod
|
||||
behind the port-forward. Signed consumer enforcement, independently admitted
|
||||
verification keys, rotation and downgrade tests remain open in SECRETS-WP-0014
|
||||
and Custodian G13. Producer support alone does not close that gap.
|
||||
Historical 2026-10-12 finding: prior consumer source did not verify producer
|
||||
signatures, so a forger could reproduce public request digests. The literal
|
||||
loopback address restriction limited the destination and did not prove responder
|
||||
identity. That source defect is repaired; FLEX-DEC-2026-010's historical warning that an absent
|
||||
PDP and a lying responder require different controls remains relevant. The
|
||||
independently admitted native trust and rollout obligations in SECRETS-WP-0014 T02/T03 remain open.
|
||||
|
||||
The Check client disables automatic redirects, environment/system proxies and
|
||||
the process-global urllib opener. A 3xx response fails closed without contacting
|
||||
|
|
@ -51,9 +51,12 @@ apply when the approval flow invokes the PDP client.
|
|||
Regression tests use disposable local HTTP servers and synthetic credentials;
|
||||
they do not demonstrate identity or signature verification on the native pin.
|
||||
|
||||
## The supported path
|
||||
## Historical transport procedure and current admission gate
|
||||
|
||||
Use literal loopback `kubectl port-forward` to the admitted named pod after
|
||||
The following transport example records the earlier supported access shape; it
|
||||
is incomplete for current native use without independently admitted signing trust,
|
||||
the reviewed CLI bundle and exact owner configuration. It grants no token mint,
|
||||
installation or live action. Use literal loopback `kubectl port-forward` to the admitted named pod after
|
||||
verifying the cluster identity and pod identity. That path rides the Kubernetes
|
||||
API server's TLS with the operator's cluster credentials; the client cannot infer
|
||||
that binding from its local URL. Note this
|
||||
|
|
@ -92,8 +95,10 @@ false` and no role bindings — it exists to be a caller identity and nothing el
|
|||
|
||||
v1 shipped and was deployed with no `input.tenant` rule at all; a `rotate` under
|
||||
`tenant:coulomb` returned **allow**. v2 supersedes rather than amends it so the
|
||||
change is visible in the version string, and this engine refuses a v1 decision
|
||||
outright. See `docs/tenant-alignment.md`.
|
||||
change is visible in the version string. Current consumer configuration and signed
|
||||
trust must explicitly pin the admitted v2 artifact; the validator does not impose
|
||||
a universal hard-coded package/version default. A v1 configuration is not admitted
|
||||
by this proposal. See `docs/tenant-alignment.md`.
|
||||
|
||||
## The digest join, and why it is not a digest comparison
|
||||
|
||||
|
|
@ -114,19 +119,18 @@ and the fix follows it rather than inventing one:
|
|||
> statement of what it hashed. To recompute independently, hash the same
|
||||
> normalized tuple the binding carries.
|
||||
|
||||
`validate_decision_envelope` now does exactly that:
|
||||
The bullets in earlier revisions described the September structured-enrichment
|
||||
check. Current source has since moved to the producer's submitted-request replay
|
||||
contract: `validate_decision_envelope` validates the exact submitted digest,
|
||||
opaque enriched digest shape, approval-free correspondence, policy pin and
|
||||
lifetime on an authenticated envelope. It does not independently reconstruct the
|
||||
full enriched tuple or native five-field claim in the generic CLI path.
|
||||
|
||||
- **Structured correspondence.** Everything we proposed — tenant, action,
|
||||
context, `subject.id`/`type`, `resource.id`/`type`/`system` and every
|
||||
attribute we sent — must survive unchanged in the binding.
|
||||
- **Enrichment only where the contract permits it.** A ref may gain `type`,
|
||||
`tenant` and `attributes`; any other added field is refused. An enriched
|
||||
`tenant` must be the request's tenant, so a cross-tenant binding cannot arrive
|
||||
wearing our request's clothes.
|
||||
- **Digest self-consistency.** `request_digest` is recomputed over the
|
||||
normalized tuple the binding carries, per the contract's own instruction. It
|
||||
is still checked — just for coherence of the binding rather than against
|
||||
material we never sent.
|
||||
The separate strict `task_execution_handoff` additionally recomputes the evaluated
|
||||
and approval-free digests, verifies exact descriptor/context/native claim joins
|
||||
(including the served native digest), and binds signed enforced caller provenance.
|
||||
That source seam is not an `execute-ccr` CLI command and does not admit the proposed
|
||||
service caller mapping or enable either task policy's runtime false gate.
|
||||
|
||||
The lesson worth keeping: the replay fixtures could not catch this, because
|
||||
`_request_from()` rebuilds the request from the binding, so the tests hashed the
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue