105 lines
5.1 KiB
Markdown
105 lines
5.1 KiB
Markdown
|
|
# Flex Auth review consumer contract
|
||
|
|
|
||
|
|
Source integration under `INFD-WP-0001-T08`; **production admission pending**.
|
||
|
|
This is the concrete consumer request for owner review. It does not grant a
|
||
|
|
role, register a caller or publish an allow policy. The checked Flex Auth source
|
||
|
|
at `88b354377c8e26b162f1234e673072f1c06dcd89` has no Informed Decision
|
||
|
|
production package in the examined examples, registry or docs.
|
||
|
|
|
||
|
|
## Caller and subject
|
||
|
|
|
||
|
|
`POST /v1/check` uses an independently provisioned workload credential, expected
|
||
|
|
to be a projected Kubernetes service-account token for audience `flex-auth`.
|
||
|
|
Flex Auth must admit the exact caller/system binding with TokenReview. The
|
||
|
|
fixture exercises `system:serviceaccount:informed-decision:review` bound to
|
||
|
|
system `informed-decision`; **that spelling is a proposal until the deployment
|
||
|
|
and policy owners admit it**. A human `approval-engine` token is never the
|
||
|
|
caller credential. Wrong service accounts and human-token substitution fail
|
||
|
|
before evaluation in the actual component test.
|
||
|
|
|
||
|
|
The subject comes from the verified KeyCape human session, including verified
|
||
|
|
roles and unchanged assurance facts. Membership tenant and act scope remain
|
||
|
|
distinct. The tenant provenance values are the consumer's typed
|
||
|
|
`directory-asserted` or `registration-supplied`; human provenance is
|
||
|
|
`authentication-derived`. Unknown routes refuse before a request is made.
|
||
|
|
The production package must deliberately interpret the admitted transitional
|
||
|
|
tenant route and action-specific MFA freshness; this surface does not infer a
|
||
|
|
mandate from membership, the named recipient match or a successful login.
|
||
|
|
|
||
|
|
## Closed request profile
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"id": "fresh-uuid-for-each-check",
|
||
|
|
"tenant": "tenant:platform",
|
||
|
|
"subject": {
|
||
|
|
"id": "VERIFIED-HUMAN-SUBJECT",
|
||
|
|
"type": "human",
|
||
|
|
"tenant": "tenant:platform",
|
||
|
|
"attributes": {
|
||
|
|
"tenant_source": "registration-supplied",
|
||
|
|
"principal_type_source": "authentication-derived",
|
||
|
|
"assurance": {"mfa": {"satisfied": true, "method": "totp", "at": "ISSUER-TIMESTAMP"}},
|
||
|
|
"roles": ["VERIFIED-ISSUER-ROLE"]
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"action": "read",
|
||
|
|
"resource": {
|
||
|
|
"id": "memo:EXACT-MEMO-ID",
|
||
|
|
"type": "decision-memo",
|
||
|
|
"system": "informed-decision",
|
||
|
|
"tenant": "tenant:platform"
|
||
|
|
},
|
||
|
|
"context": {
|
||
|
|
"memo_version": 1,
|
||
|
|
"approval_id": "EXACT-APPROVAL-ID",
|
||
|
|
"approval_binding_digest": "CARRIED-NATIVE-SHA256-DIGEST"
|
||
|
|
},
|
||
|
|
"policy_version": "OWNER-ADMITTED-VERSION"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
The assurance object above is illustrative; `build_request` carries the verified
|
||
|
|
issuer object without synthesizing stronger facts. Supported actions are
|
||
|
|
`read`, `acknowledge`, `accept`, `return`, `discuss`, `decline`. Read covers memo
|
||
|
|
rendering, original presentation retrieval and packet download. Other verbs
|
||
|
|
always get their own decision. Only accept can cause an Approval Engine POST.
|
||
|
|
No `consume`, wildcard action, `view_hash`, presentation id, acknowledgment
|
||
|
|
state or presentation claim is supplied. This prevents the renderer's evidence
|
||
|
|
from becoming an input to its own permission decision.
|
||
|
|
|
||
|
|
The owner must provide the exact package/version/digest, resource/subject
|
||
|
|
assignment source, admissible caller, scope and positive/negative fixtures.
|
||
|
|
The consumer does not guess an operator group or ship a local allow fallback.
|
||
|
|
The separately pending CCR-2026-0019 reader group does not automatically confer
|
||
|
|
permission to read or approve a memo.
|
||
|
|
|
||
|
|
## Required response and refusal behavior
|
||
|
|
|
||
|
|
The response is `flex-auth.decision-record.v1`, with matching request id,
|
||
|
|
submitted request digest, core actor/resource/action/context binding and exact
|
||
|
|
package/version/digest pins. The evaluated digest and registry snapshot digest
|
||
|
|
are observed from the owner; registry enrichment is not repeated locally.
|
||
|
|
`submitted_digest` implements this consumer's bounded Go JSON request profile,
|
||
|
|
not a second approval-act canonicalizer. Actual Go checks cover enrichment,
|
||
|
|
Unicode and HTML escaping; the native approval digest is always carried.
|
||
|
|
|
||
|
|
Only an allow with a current TTL and no obligations is supported. Maximum use
|
||
|
|
is 30 seconds from dispatch, bounded by the returned expiry and not-before;
|
||
|
|
there is no decision cache. A declared obligation needs explicit implementation
|
||
|
|
before it can be admitted. Deny, unsupported effects/obligations, stale or
|
||
|
|
mismatched responses and transport/caller failures all refuse. HTTP 401/403
|
||
|
|
remains `caller_refused` even when the native caller gate returns plain text.
|
||
|
|
|
||
|
|
Each obtained observation is append-only in the private evidence database,
|
||
|
|
before content exposure or an act. Diagnostic response text and bearer tokens
|
||
|
|
are not retained. Policy linkage is private content, not part of the emitted
|
||
|
|
presentation claim. The envelope remains unsigned, so
|
||
|
|
`decision_attributable=false`; native deployment cannot close `FLEX-WP-0024`.
|
||
|
|
|
||
|
|
`tests/fixtures/review-policy/` is deliberately a **fixture-only** package, with
|
||
|
|
one synthetic human/memo/approval and no production assignment. Its native
|
||
|
|
package pin proves the consumer seam and cannot be used as admission evidence.
|
||
|
|
Owner return must include admitted policy/caller pins and deployed allow/refusal
|
||
|
|
receipts for the exact native human/act before T08 can claim live binding.
|