flex-auth/workplans
tegwick 0bc624ba62
All checks were successful
CI Smoke / host-smoke (push) Successful in 1s
CI Smoke / container-smoke (push) Successful in 3s
Build and Publish Container Image / build-and-push (push) Successful in 57s
fix(decision): registry facts win over caller-supplied attributes
secrets-engine's first live request rejected our allow: binding.
request_digest is computed over material they never sent, because we
enrich subject and resource from the registry before hashing. Answering
that meant reading the enrichment path, which had a worse defect in it.

Enrichment was additive-if-absent — addAttribute wrote a registry value
only where the request had no value for that key. So where a caller
supplied a key, the caller's value won and the registry's never applied.
Every registry ceiling and allowlist was advisory. Verified against the
shipped ops-warden package, each one added key on an otherwise-denied
request:

  max_ttl_hours: 99      registry says 8    -> allowed a 12h certificate
  allowed_principals     registry allowlist -> disallowed_principal bypassed
  allowed_subjects       registry allowlist -> unknown_subject bypassed

The third is the one to read twice: a subject the registry does not know
authorized itself by naming itself in the allowlist it was being checked
against.

Not remotely reachable today — the PEP builds the CheckRequest,
ops-warden sends no resource.attributes, and enforce admits one identity.
It is a defence-in-depth failure: any path that lets attacker-influenced
data into a CheckRequest field became a full policy bypass rather than a
bounded input problem. Callers sending resource.attributes is not
hypothetical; secrets-engine does it on every request.

Registry facts now win, and diagnostics.registry_overrode names every
displaced key, because a registry that silently discards a contradicting
claim hides that a caller asserted authority it did not have.

subject.type is carved out, and the reason is a finding of its own.
Making the registry win there denied every secrets-engine allow: the
registry's type is CARING vocabulary (Human, Agent, Automation, Service)
and the request's is the protected system's actor vocabulary (service,
adm, agt, atm). Two fields sharing a name; substituting one for the other
is translation rather than identity, which GH-DEC-2026-008 ruled against.
Note what surfaced it — the registry's type had been dead data since the
field existed, because the caller's value always won.

Also publishes binding.submitted_request_digest, over the request exactly
as sent. request_digest was published as the consumer replay test and
cannot be one. Nothing is lost hashing the pre-enrichment form:
enrichment is a function of the request and the snapshot, and
registry_snapshot_digest already pins the snapshot.

Existing pins do not move. All three replay fixtures' request_digest and
approval_binding_digest values are byte-identical — those requests
contradict no registry fact. A field to add, not a value to correct.

Regression tests verified failing against the old behaviour before being
kept. FLEX-DEC-2026-012; FLEX-WP-0025 carries the residual, that a policy
still cannot tell a fact from an assertion.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014aQMM1dPXaPiXVn6DwwtLd

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 715613@bnt-lap001
Assistant-Session: fabd95c1-4c9e-4080-8849-8707ae025f80
2026-09-07 13:43:33 +02:00
..
FLEX-WP-0001-repo-intent-and-architecture-baseline.md Normalize agent instructions and workplan frontmatter (STATE-WP-0067) 2026-06-22 23:16:25 +02:00
FLEX-WP-0002-standalone-policy-as-code-core.md Normalize agent instructions and workplan frontmatter (STATE-WP-0067) 2026-06-22 23:16:25 +02:00
FLEX-WP-0003-markitect-consumer-integration.md Normalize agent instructions and workplan frontmatter (STATE-WP-0067) 2026-06-22 23:16:25 +02:00
FLEX-WP-0004-delegated-pdp-and-directory-adapters.md Normalize agent instructions and workplan frontmatter (STATE-WP-0067) 2026-06-22 23:16:25 +02:00
FLEX-WP-0005-foundations-and-topaz-alignment.md Normalize agent instructions and workplan frontmatter (STATE-WP-0067) 2026-06-22 23:16:25 +02:00
FLEX-WP-0006-ops-warden-ssh-signing-policy-gate.md FLEX-WP-0006: implement ops-warden signing gate policy 2026-06-23 21:17:42 +02:00
FLEX-WP-0007-ops-warden-policy-gate-production-deployment.md Close ops-warden policy gate deployment 2026-06-30 00:52:56 +02:00
FLEX-WP-0008-tenant-engine-consumer-integration.md fix(workplans): adopt ADR-007 derived identifiers for unregistered records 2026-08-25 20:10:35 +02:00
FLEX-WP-0009-user-engine-production-policy-service.md fix(workplans): adopt ADR-007 derived identifiers for unregistered records 2026-08-25 20:10:35 +02:00
FLEX-WP-0010-tenant-lifecycle-policy-actions.md fix(workplans): adopt ADR-007 derived identifiers for unregistered records 2026-08-25 20:10:35 +02:00
FLEX-WP-0011-railiance-staged-promotion-overlay.md fix(workplans): adopt ADR-007 derived identifiers for unregistered records 2026-08-25 20:10:35 +02:00
FLEX-WP-0012-credential-grant-authorization-surface.md fix(workplans): adopt ADR-007 derived identifiers for unregistered records 2026-08-25 20:10:35 +02:00
FLEX-WP-0013-restore-seven-action-tenant-engine-pin.md fix(workplans): adopt ADR-007 derived identifiers for unregistered records 2026-08-25 20:10:35 +02:00
FLEX-WP-0014-tenant-guardrail-policy-actions.md fix(workplans): adopt ADR-007 derived identifiers for unregistered records 2026-08-25 20:10:35 +02:00
FLEX-WP-0015-tenancy-posture-conformance.md fix(workplans): adopt ADR-007 derived identifiers for unregistered records 2026-08-25 20:10:35 +02:00
FLEX-WP-0016-ops-warden-incluster-policy-pin.md fix(workplans): adopt ADR-007 derived identifiers for unregistered records 2026-08-25 20:10:35 +02:00
FLEX-WP-0017-action-bound-authorization-contract.md Finish FLEX-WP-0017 2026-09-01 20:21:58 +02:00
FLEX-WP-0018-inbound-auth-corrections.md chore(registrar): assign State Hub identifiers 2026-08-23 13:21:43 +02:00
FLEX-WP-0019-layer-model-conformance.md Finish FLEX-WP-0019 layer-model v0.7 conformance 2026-09-03 23:48:45 +02:00
FLEX-WP-0020-repository-identity-migration.md chore(registrar): assign State Hub identifiers 2026-08-29 18:00:44 +02:00
FLEX-WP-0021-secrets-engine-consumer-policy-gate.md fix: the address we published was a misdirection, and the channel is unauthenticated 2026-09-06 22:44:45 +02:00
FLEX-WP-0022-tenant-scope-coverage.md chore(consistency): register FLEX-WP-0022 and refresh work records 2026-09-06 20:41:05 +02:00
FLEX-WP-0023-operator-caller-access-path.md docs: v0.8 assent review — four findings, one fail-open 2026-09-07 08:45:39 +02:00
FLEX-WP-0024-decision-envelope-authenticity.md docs: v0.8 assent review — four findings, one fail-open 2026-09-07 08:45:39 +02:00
FLEX-WP-0025-fact-versus-assertion.md fix(decision): registry facts win over caller-supplied attributes 2026-09-07 13:43:33 +02:00