Two real DecisionEnvelopes in examples/secrets-engine/replay/ for
secrets-engine to verify its digest join unchanged: a plain allow
(rotate, empty context) and the dual-control allow (destroy with a valid
approval-claim).
Both are included deliberately. input_claim_digests.context appears only
when the request carries a non-empty context, so a consumer asserting the
field is always present would pass on destroy and fail on rotate. One
fixture would have hidden that.
request_digest, policy_package_digest, registry_snapshot_digest and the
context claim digest are verified identical across two runs and are the
fields to pin. id, decision_time and the lifetime bounds move with the
clock; the README says so rather than leaving a consumer to discover it
by flake. lifetime.ttl is 15m from the package allow_ttl.
Emitted from flex-auth/local in standalone mode, not from a cluster pin.
T03 is progress, not done -- it closes when secrets-engine confirms their
validator accepts the records unchanged.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JTbVXpEiXA7mNJVpDnEPcB
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 412054@bnt-lap001
Assistant-Session: 3968fae1-8d59-4209-9bd6-c22594b8ab19
secrets-engine delivered the action vocabulary T01 asked for: twelve
actions read out of cli.py, not the example vocabulary. The gate earned
its keep -- four would have been inferred wrongly, and revoke, the
obvious thirteenth, does not exist as an action at all. It gates as
deactivate, which is also reached from lifecycle deactivate.
docs/secrets-engine-action-vocabulary.md records the list and the four
traps. examples/secrets-engine/ carries the package, both manifests, a
loadable registry snapshot, 26 fixtures, five check requests, and a
README. validate -kind policy is valid with 22/22 Rego tests and 26/26
fixtures.
allow_ttl is 15m, stated in the package rather than inherited from the
engine default: these decisions authorize live secret operations, so the
reliance window belongs where a reviewer sees it. Per FLEX-DEC-2026-004
it is authority to issue, not authority to keep using what the operation
produced.
destroy is the dual-control case, gated on a context.approval claim
marked approved with two distinct approvers, repeated entries counting
once. flex-auth checks what the claim says and deliberately does not
re-derive its temporal validity, signature, or supersession -- those are
approval-engine's to assert and the PEP's to verify against the live
claim, per the split accepted in FLEX-DEC-2026-006. It stays in the
package though its handler raises before the gate, so the rule is
reviewed and fixtured before SECRETS-WP-0007-T04 opens the path.
Following the FLEX-WP-0010-T02 precedent the denial ladder has no
action_not_granted branch: one subject holding all twelve actions could
never reach it, and a rule that cannot fail reads as control that is not
there. Registering a second calling identity is the revisit trigger.
Not deployed. No flex-auth-secrets-engine pin exists yet (T04), so their
policy pin stays unset and fail-closed until T05.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JTbVXpEiXA7mNJVpDnEPcB
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 412054@bnt-lap001
Assistant-Session: 3968fae1-8d59-4209-9bd6-c22594b8ab19
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JTbVXpEiXA7mNJVpDnEPcB
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 412054@bnt-lap001
Assistant-Session: 3968fae1-8d59-4209-9bd6-c22594b8ab19
Two cross-repo questions arrived in the flex-auth inbox and both are
answered as decision records rather than as prose in a message.
FLEX-DEC-2026-004 answers ops-warden WARDEN-WP-0034-T05. A decision
lifetime shorter than the SSH certificate TTL is meaningful, but only as
authority to issue, never as authority to use an already-issued
certificate. The pre-sign gate is the only consumer of the shorter
lifetime: no replay past expires_at, fresh Check per sign. The lever that
shortens effective access is the requested TTL as a policy input, which
is already deployed as the ttl_out_of_bounds deny. ops-warden's section
9.7.2 window through certificate TTL is correct as written and correctly
owned by the PEP; flex-auth does not want that residue moved to the PDP.
docs/decision-input-freshness.md gains the same boundary as published
contract text, so the ruling is not only in the decision log.
FLEX-DEC-2026-005 answers secrets-engine. A real policy package is
expected and flex-auth authors it here as it does for every consumer; the
reserved coordinate is secrets-engine.catalog-lane.lifecycle v1 and it
does not exist yet. Their choice not to default the pin was correct and
is endorsed explicitly. POST /v1/check is deployed but has no
estate-wide address by design -- per-consumer cluster-local pins with
default-deny ingress -- so their 2026-09-06 probe found the design
working, not an outage.
FLEX-WP-0021 carries that work: obtain the real action vocabulary from
secrets-engine, publish the package with fixtures, confirm the digest
join against a real decision record, then stand up a
flex-auth-secrets-engine pin in warn without moving the other two pins.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JTbVXpEiXA7mNJVpDnEPcB
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 412054@bnt-lap001
Assistant-Session: 3968fae1-8d59-4209-9bd6-c22594b8ab19
Close the remaining PDP obligations: mechanical layer declaration check,
registry-snapshot digest in provenance, explicit allow TTL, per-input-class
freshness deadlines, and the published decision-record contract. Document
the canonical request digest as the §6.4.2 replay test.
Assistant: grok
Assistant-Session: 01a06256-fb71-7102-b3a9-27e6734257d0
C-21 flagged the ready workplan as possibly stale: reviewed against 5753b47,
HEAD had moved. Checked rather than assumed — nothing since 5753b47 touches Go
or schemas. Every commit between is documentation or work-record only, and the
last implementation change is d402408 (2026-08-23).
reviewed_against_commit now names the implementation state reviewed rather than
the HEAD at review time, so it moves when the code moves, which is when the
review needs redoing. C-21 compares against HEAD and cannot distinguish a doc
commit from a code one, so it will keep warning softly on this plan; the record
is accurate and that is the trade taken deliberately.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012sgN4GH5ZYT8pJVkCR6dcP
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 4014348@bnt-lap001
Assistant-Session: a993abda-65a0-4ea8-8ccd-0fcd78c92ac0
C-34 flagged status=ready without a DoR assessment. The warning was right: the
plan claimed repo-state review with no review metadata, and work-item-dor.md
prefers DoR-Failed for a ready claim in that state.
Adds reviewed_at, reviewed_against_commit (5753b47 — the code state the
alignment review actually checked each obligation against), the origin pointer
to the review, and quality_dor: DoR-Ok with the criteria walked in the note.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012sgN4GH5ZYT8pJVkCR6dcP
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 4014348@bnt-lap001
Assistant-Session: a993abda-65a0-4ea8-8ccd-0fcd78c92ac0
The standard was accepted at v0.7 on 2026-08-29. Four of flex-auth's review
findings are in the accepted text: 9.3's two-owner split, 6.4.2 scoped to the
decision's own binding with our canonical request digest as its mechanical test,
9.7.2 split by role, and 17 moving the decision-record schema to access-engine.
INTENT.md
- Machine-readable layer declaration in frontmatter (layer: Engine, role: PDP),
which section 11 requires and we did not have. audit-core noted our
declaration was legible only by following the decision trail.
- PDP failure semantics stated: our outage is consumer residue, not input
degradation; fail-open is not expressible by a PDP at all.
- Four owned obligations added: the decision-record schema as our contract, the
request digest as the published replay test, a lifetime on every allow, and
visibility deadlines per input class.
- A Layer Conformance section stating the state honestly: conforming with one
declared gap, no Tooling client, not PEP-shaped.
- Vocabulary correction: earlier text dropped "control plane" as Staff
vocabulary. Section 8 binds it to the Engine layer, which is why kings-guard
was asked to release it. The term is ours; we prefer "decision engine" for
precision, not boundary.
SCOPE.md
- Layer and role in the one-liner; the four obligations In Scope; five
boundaries established in review but never written down Out of Scope.
- Three capability blocks marked planned for workplans completed in May are now
current; two blocks added.
- Superseded ADR-0006 citation corrected to ADR-0009, which retires the global
flag outright rather than deferring it.
history/2026-08-29-layer-model-v0.7-alignment-review.md checks each obligation
against the code and finds six gaps. FLEX-WP-0019 closes them, with T02 before
T04 because a visibility deadline for registry-borne facts is unfalsifiable
until provenance can identify the snapshot a decision read.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012sgN4GH5ZYT8pJVkCR6dcP
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 4014348@bnt-lap001
Assistant-Session: a993abda-65a0-4ea8-8ccd-0fcd78c92ac0
flex-auth answers gate-house's assent request on the three items ratified in
GH-DEC-2026-001, following the estate precedent that a boundary is drawn on
review by the other side.
Assent to all three, with one conformance debt flex-auth accepts as its own and
two conditions on the rename:
- Engine framing and sole decision point: assent. flex-auth cannot hold this
boundary against zone-engine and decline it as a general rule. But standard
section 6 also binds flex-auth: DecisionProvenance carries no registry
snapshot digest, so a decision that turned on registry content cannot be
replayed from its own provenance. Recorded as a known non-conformance rather
than claimed as conformance.
- access-engine rename: assent to the name, not to execution. Repository
identity and runtime identity must rename in separate revertible steps —
since FLEX-WP-0016 the enforcing ops-warden pin binds tokens to the
protected-system name, so a single-step rename 401s every warden sign,
including the certificate the ops-bridge tunnels depend on. FLEX-WP prefix
ownership stays with the repository.
- Authoring/evaluation split: assent, with the section 6 test applied
symmetrically — a gate-house authority ceiling that determines an outcome
reaches the decision as an input claim or as a rule in the versioned policy
package, so its application stays reconstructable from the decision record.
FLEX-WP-0017-T03 stays wait: the design half re-routes to gate-house, the
durable storage half remains unowned and is raised as an engine gap under
section 5.
Decision id follows the canon scheme {PREFIX}-DEC-YYYY-NNN.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012sgN4GH5ZYT8pJVkCR6dcP
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 4014348@bnt-lap001
Assistant-Session: a993abda-65a0-4ea8-8ccd-0fcd78c92ac0
These workplans exist only in the retired local hub. Their random pre-ADR-007
identifiers are refused by C-06 as stale references, so they cannot be
registered. Deriving from the canonical record id takes no identity from
anything: central does not hold them and the old ids die with the cache.
Records central already holds were deliberately left untouched.
Refs CUST-WP-0068-T06
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 2583210@bnt-lap001
Assistant-Session: f2bff2d5-e9b2-4338-92ca-10282a927006
FLEX-WP-0016 was titled 'so policy.enabled can flip' and the flip is not
coming. ops-warden's ADR-0006 defers it permanently in favour of
zone-scoped enforcement, so this closes rather than stalls: every task
it owned is delivered and enforce is independently verified by both
sides. The pin stays enforce and is not reverted to warn.
SCOPE's account of policy.enabled was stale - it read as a
build-stage timing choice. Replaced with the actual reason and with
flex-auth's boundary as the reviewing PDP: membership compiles to the
registry, stance stays in the policy package, fail-open is not
expressible by a PDP.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ops-warden WARDEN-WP-0031 T04 minted audience-flex-auth tokens as
system:serviceaccount:ops-warden:ops-warden and held the warn-log count.
Helm rev 2 is enforce. Live probe 200/401/403. policy.enabled is theirs.
policy.enabled cannot flip against the user-engine or tenant-engine
bindings. Helm release flex-auth-ops-warden rev 1 serves the production
registry in warn. Workstation warden sends no caller token; enforce and
the yaml flip stay ops-warden's.
flex-auth-tenant-engine Helm rev 2 is enforce on sha256:138aa347 after
tenant-engine 2063470 started sending a projected caller token
(sha256:7dc9d7bf). Probe 200/401/403. tenancy.current.A is 2. T04
cancelled: AuthZEN waits for a PEP we do not control.
Helm-adopted the kubectl-managed user-engine pin, promoted sha256:138aa347
warn then enforce. Reviewer volume needs fsGroup 65532; reviewer tokens
must use the API default audiences or TokenReview 401s on this k3s.
Live probe from user-engine-8569d7cb87-fp7px: 200 / 401 / 403. tenant-engine
is unchanged. tenancy.current.A stays 0 until that pin moves.
The sanctioned Helm chart could not promote ADR 0004 at all, and the
emergency manifests selected enforce. That made a FLEX-WP-0011 apply
either a no-op or a global 401. First production pin is now warn, per
consumer, on CI digest sha256:138aa347… . Enforce stays a later
per-consumer flip so USER-WP-0023-T03 can close without waiting on
tenant-engine.
Publishes tenancy.yaml (I1 A0 E2 P n/a R n/a, enables A3), the review
answering rapp-postgres's three asks, and FLEX-WP-0015 to close the gaps.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
CI digest sha256:1bf060e6 (main-f304688) is live. Seven pre-existing
actions still allow; guardrail.read/set match the FLEX-WP-0014 split.
user-engine pin unchanged. Rollback target is sha256:9320df39.
FLEX-WP-0014. Package tenant-engine.write-api.mutate v1 now carries
nine actions: tenant.guardrail.read and tenant.guardrail.set on
resource type guardrail, verbatim from tenant-engine's mapping.
The read/write split is used now: flex-auth may read ceilings and is
denied action_not_granted on set; tenant-engine may do both. 17/17
Rego tests and 23/23 fixtures pass. Live e2e against a real
tenant-engine FlexAuthWriteAuthorizer matches.
In source only; production still serves the seven-action 9320df39 pin.
FLEX-WP-0013. Production had been rolled back to sha256:c25fc34a
(four actions), so tenant.update / tenant.retire / tenant.reactivate
denied unknown_action. Re-pin and apply the previously-live
sha256:9320df39 image (e9911eb). Live probe after restore: all seven
actions allow; misspelled action and unknown subject still deny.
user-engine pin unchanged. TEN-WP-0006 guardrail actions not added.
T04 is done: nine fixtures including registration-applicant match the
deployed /v1/check, user-engine is on the fail-closed HTTP adapter, and
the deploy manifest now pins the live digest.
Opens the State Hub capability request 893ff109, unanswered since
2026-07-02. Drafted as proposed/P3 rather than as the blocker it was
filed as, because two of its premises no longer hold:
- It is not blocking anyone. railiance-platform re-scoped and closed
RAILIANCE-WP-0005-T07 the same day it filed the request; WP-0005 is
finished and their grant catalog already enforces TTL, actor-type,
purpose and delivery-mode bounds locally. This buys defence in depth
and central decision records, not unblocking.
- The stated technical blocker is wrong. The request says the CARING
/v1/check schema cannot express TTL, purpose or delivery mode; the
ops-warden package in this repo already denies ttl_out_of_bounds by
reading input.context.ttl_hours against resource.attributes. CARING
constrains descriptor vocabulary, not the request payload.
The real gap is narrower: no credential-grant policy package exists, and
the helper's flat payload/response shape differs from CheckRequest. Its
endpoint path is configurable, so no bespoke endpoint is strictly
required. T01 makes the adapter-vs-consumer-mapping call an explicit,
jointly-agreed decision rather than a default.
Flags two things worth knowing before anyone implements: the helper sends
requested_ttl as a duration string while the ops-warden precedent compares
numeric hours (mis-parsing it would fail open on the check that matters
most), and without --require-flex-auth the helper continues by local
preauthorization when flex-auth is unreachable -- a different posture from
the tenant-engine and ops-warden gates.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
CI-built image from e9911eb, digest
sha256:9320df394a642eff24da8af4a0ee8886a7bb78b0f14d8ee1deeb30ea8eeeaba7,
verified in a throwaway container before pinning and then probed again
against the live Service after rollout:
tenant.retire allow write_api_policy_matched decision:491bbef2db999c02
tenant.create allow write_api_policy_matched decision:fa3ba90e9cccb5aa
tenant.retired deny unknown_action decision:c5ee185de439ffe5
unknown subject deny unknown_subject decision:a98c59c6a34f84ad
tenant.retire has flipped from deny unknown_action to allow in
production, which is what TEN-WP-0005-T05 was waiting on.
Only flex-auth-tenant-engine was rolled. flex-auth-user-engine stays
pinned to a31961c4 -- its policy is unchanged and there is no reason to
move it. Previous tenant-engine digest kept in the runbook as the
rollback target.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
flex-auth had no image workflow, so its production images were hand-built
on a workstation and pushed with workstation credentials -- an artifact
whose provenance was someone's working tree rather than a forge revision.
Ports activity-core's canonical image.yaml: the container-build runner
fetches a tarball of the pushed commit, builds, and pushes :latest and
:main-<short-sha>, then reports the immutable digest for the rollout step.
examples/** is a build-trigger path on purpose -- policy packages are
COPYed into the image and there is no hot reload, so a policy change is
an image change.
Runbook updated to say plainly that images are not built on workstations.
FLEX-WP-0011 filed for the rest of the gap: flex-auth runs two production
Deployments on railiance01 but has never been brought under the
staged-promotion contract (RAIL-BS-WP-0006). No railiance/app.toml, no
stage commands, no canary or approval evidence; the deploy/ directory is
a rescue of specs that existed nowhere, not the sanctioned overlay shape.
Pre-existing debt found during the FLEX-WP-0010 rollout, not a regression
from it, and not a blocker for routine policy rollouts -- flex-auth fails
closed. T03 also flags that the coulombcore drain plan still lists
flex-auth on a host it no longer runs on.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
FLEX-WP-0010-T04: the deployed flex-auth-tenant-engine Deployment bakes
the policy package into its image, so production still serves the
four-action policy -- probed live, tenant.retire returns deny
unknown_action there while tenant.create allows. TEN-WP-0005-T05 is
unblocked in source but needs an image build from 8e127e5 and a rollout,
which this workplan does not scope. Stated in the workplan and in
examples/tenant-engine/README.md rather than left implied.
FLEX-WP-0009-T04: replayed all six user-engine fixtures against the
deployed flex-auth-user-engine service; all six matched expected effect
and reason, confirming the deployed failure matrix is still fail-closed.
T04 stays in progress -- the criterion also requires user-engine to
retire its local bridge, which is not flex-auth's to close.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Extend the tenant-engine write-API policy package with tenant.update,
tenant.retire, and tenant.reactivate, the three actions TEN-WP-0005
introduced. Until now every lifecycle mutation resolved to deny
unknown_action, blocking TEN-WP-0005-T05 production rollout.
- policy_package.md: three actions in valid_actions and frontmatter;
CARING capabilities extended with EditAny/Archive/Restore
- protected_system_manifest.yaml, subject_manifest.yaml, and the rebuilt
registry_snapshot.json carry all seven actions
- docs/tenant-engine-action-vocabulary.md documents the HTTP surfaces
- 8 new fixture pairs and 5 new Rego tests, including action-drift
guards (tenant.retired, tenant_update -> unknown_action)
T02 decision, recorded in policy_package.md: tenant.retire does NOT get
stricter authorization yet. With one service subject and no assurance
claim in the CheckRequest there is nothing stricter to check, and a
condition the sole caller always satisfies would falsely read as
separate control. Retirement is reversible and non-destructive. Revisit
on KEY-WP-0005 assurance claims or a second operator subject.
Verified: 11/11 Rego tests, 16/16 fixtures, go test ./... green, gofmt
and go vet clean. End-to-end against a live serve with a real
tenant-engine through the unmodified FlexAuthWriteAuthorizer: update
6176c39c2f4d7b15, retire 8a801b8ee8455080, reactivate c64cf3713cecd970
all allow; unregistered actor denied unknown_subject
(59d3e99c6416be89, 403 write_denied).
Handoff revision for TEN-WP-0005-T05: package
tenant-engine.write-api.mutate v1 (ready, caring-0.4.0-rc2).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
TEN-WP-0005 added tenant.update / tenant.retire / tenant.reactivate to
tenant-engine's write API. FLEX-WP-0008's policy package predates them, so
every lifecycle mutation resolves to deny unknown_action -- correct
fail-closed, but it blocks TEN-WP-0005-T05 rollout and USER-WP-0021.
Requested by tenant-engine; action strings taken verbatim from the live
_RESOURCE_TYPES mapping.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>