Updated by fix-consistency on 2026-09-21:
- update .custodian-brief.md for flex-auth
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 28468@bnt-lap001
Assistant-Session: c76569b2-6056-4dad-aea4-49cd7a018f5d
Eleven messages sent. Every finding is open until its owner answers; T04 stays
in progress rather than done, because a finding is not closed by silence.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 28468@bnt-lap001
Assistant-Session: c76569b2-6056-4dad-aea4-49cd7a018f5d
INTENT.md pinned standard_version: "0.7" in the frontmatter §11 requires. That
conflated two things the standard separates itself: assent "records assent to a
BOUNDARY, given at the version named. It is not assent to the current text."
flex-auth is Engine/PDP at v0.6, v0.7, v0.8 and after; the role does not change
when the text is amended. The field was also decorative — parsed into
Declaration.StandardVersion and never validated — so the version was load-bearing
only via a test asserting it equalled 0.7.
That test is inverted rather than deleted: internal/layer now rejects a version
pin in the declaration and requires conformance_record to name a file that
exists. Version-scoped state moves to docs/conformance/security-layer-conformance.md,
a derived artifact carrying what it derives from and the version derived at, as
§11 requires of derived artifacts.
SCOPE.md: gap assessment replaces "conforming with one declared gap" with three
gaps, each with an owner and a route. G2 is new — flex-auth declares no emission
guarantee where §11 requires one of every §4 source of evidence. It is recorded
as a gap rather than as conformance because the flattering reading, that
audit-core is the source and flex-auth merely produces, has been asserted by
nobody but flex-auth. Also corrects the stance register from two rows to five.
Fixing one line meant reading what the declaration asserts, and a boundary is
only half held here. docs/conformance/boundaries-review.md checks the other
halves across twelve counterparts and finds four security-relevant repositories
with no layer declaration at all — including key-cape, the identity source whose
claims flex-auth consumes as normative input. That boundary is asserted from one
side only. Recorded as unstated, never as agreed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 28468@bnt-lap001
Assistant-Session: c76569b2-6056-4dad-aea4-49cd7a018f5d
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 28468@bnt-lap001
Assistant-Session: c76569b2-6056-4dad-aea4-49cd7a018f5d
Updated by fix-consistency on 2026-09-20:
- update .custodian-brief.md for flex-auth
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 28468@bnt-lap001
Assistant-Session: c76569b2-6056-4dad-aea4-49cd7a018f5d
docs/stance-register-review.md is published, dated 2026-09-06, and titled "the
register has a second row". Three things moved under it: §13.1 now carries five
rows rather than two, v0.8 §6.4 obligation 3 ruled that unknown is not a zone and
must resolve to fail_closed, and two rows are now marked non-conformant.
The review's closing line warned that the cost of two incommensurable axes is
small and the cost of five is not. Five arrived in fourteen days.
The plan supersedes rather than amends: a published review silently rewritten to
match the world is FLEX-DEC-2026-008's defect, and flex-auth does not exempt its
own artifacts from a rule it holds others to.
Recorded accurately rather than flatteringly — the divergence was resolved by
gate-house doctrine in secrets-engine's direction, not by flex-auth's review, and
ops-warden's marked-non-conformant row is right to stay unconverted until
WARDEN-WP-0040 raises zone coverage. Conformance and correctness have come apart
on that cell.
INTENT.md stays at standard_version 0.7: v0.8 is still proposed, and the trigger
for the bump is stated in T04 so it is not "fixed" early.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 28468@bnt-lap001
Assistant-Session: c76569b2-6056-4dad-aea4-49cd7a018f5d
Updated by fix-consistency on 2026-09-20:
- update .custodian-brief.md for flex-auth
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 28468@bnt-lap001
Assistant-Session: c76569b2-6056-4dad-aea4-49cd7a018f5d
FLEX-WP-0020-T04: reuse-surface is the first owner to return a live work-record
(REUSE-WP-0023, two tasks, both deliberately in wait). Recorded in the handoff
evidence and verified rather than taken on report — the hub record is active,
access-engine raw returns 404, flex-auth returns 303, so the rename has not
landed and their refusal to pre-rewrite the federation source URL is correct.
That refusal changed the plan rather than only their side: flipping an enabled,
publish-passing source before the rename drops a live capability from the
composed federated index, so the source rewrite is ordered after T06, and
flex-auth owes them a ping when access-engine serves the capabilities index.
Nine owners remain pending; T05 stays blocked.
FLEX-WP-0022-T01: re-asked tenant-engine what CheckRequest.tenant denotes on the
write API, stating that "none" is a complete answer. Their code copies tenant_id
onto both tenant and resource.id, but that is observation, not admission, and
encoding a rule from it would make flex-auth the author of their tenancy model.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 28468@bnt-lap001
Assistant-Session: c76569b2-6056-4dad-aea4-49cd7a018f5d
Updated by fix-consistency on 2026-09-15:
- update .custodian-brief.md for flex-auth
Assistant: grok
Assistant-Session: 01a0a6cb-0334-72c0-83b0-2df57474a0f6
FLEX-WP-0020 T01-T03: fresh preflight is zero-blocker, repository-only
scope is FLEX-DEC-2026-013, concurrent work is FLEX-DEC-2026-014.
T04 handoff requests are posted; owner work-records are still required.
T06 stays behind the exact human confirm string and a post-commit preflight.
Assistant: grok
Assistant-Session: 01a0a6cb-0334-72c0-83b0-2df57474a0f6
FLEX-WP-0022-T03: the rules already refused a foreign tenant; the fixture
suites never varied the field. No policy or version change. Asked
tenant-engine to name the CheckRequest tenant relation for T01/T02.
Assistant: grok
Assistant-Session: 01a0a6cb-0334-72c0-83b0-2df57474a0f6
Updated by fix-consistency on 2026-09-15:
- update .custodian-brief.md for flex-auth
Assistant: grok
Assistant-Session: 01a0a6cb-0334-72c0-83b0-2df57474a0f6
CI image 8007ede@sha256:6da9543d02ff556d5d5e33624599eb26b73ef365ed0e1ee2fac2ad7703b7dcba
now serves examples/informed-decision-sitting. T03 deployment is unchanged.
Native caller checks pass with synthetic identities; human bind stays with
INFD-WP-0002.
Assistant: grok
Assistant-Session: 01a0a6cb-0334-72c0-83b0-2df57474a0f6
Updated by fix-consistency on 2026-09-15:
- update .custodian-brief.md for flex-auth
Assistant: grok
Assistant-Session: 01a0a6cb-0334-72c0-83b0-2df57474a0f6
Seven exact-record pins from the 2026-09-15 sitting-create receipt.
c01 is omitted. Identity bar matches T03. 147 local evaluator checks
pass. Deploy waits on a CI image that contains the new package.
Assistant: grok
Assistant-Session: 01a0a6cb-0334-72c0-83b0-2df57474a0f6
Set flavor on open workplans from origin/prose/status. Copy existing
depends_on aliases only. Do not promote residuals.
Assistant: grok
Assistant-Session: 01a09dc1-b21e-77e1-919e-fcad2f82b267
Updated by fix-consistency on 2026-09-14:
- update .custodian-brief.md for flex-auth
Assistant: grok
Assistant-Session: 01a09dc1-b21e-77e1-919e-fcad2f82b267
Detached Ed25519 over the canonical envelope with signature omitted.
Unsigned is stated, not implied. Testdata fixtures prove verify and
tamper failure without minting a production key. FLEX-WP-0025 is
finished with the validate check from the previous commit.
Assistant: grok
Assistant-Session: 01a09dc1-b21e-77e1-919e-fcad2f82b267
FLEX-WP-0025-T03: flex-auth validate flags input.*.attributes keys that
no sibling registry or manifest supplies. A broken testdata package
proves tests can pass while the ceiling remains caller-only.
Assistant: grok
Assistant-Session: 01a09dc1-b21e-77e1-919e-fcad2f82b267
Updated by fix-consistency on 2026-09-14:
- update .custodian-brief.md for flex-auth
Assistant: grok
Assistant-Session: 01a09dc1-b21e-77e1-919e-fcad2f82b267
FLEX-WP-0025-T01/T02: keep merged attributes, add registry/asserted
namespaces later, and declare the remaining ceiling keys so no
published allowlist is unbacked. T03 stays waiting on validate.
Assistant: grok
Assistant-Session: 01a09dc1-b21e-77e1-919e-fcad2f82b267
Updated by fix-consistency on 2026-09-14:
- update .custodian-brief.md for flex-auth
Assistant: grok
Assistant-Session: 01a09dc1-b21e-77e1-919e-fcad2f82b267
FLEX-WP-0023-T04: provenance.caller is additive (mode required;
principal/audience/not_after when a token was reviewed). TokenReview
keeps the JWT exp. request_digest is unchanged because the caller is
not binding material.
Assistant: grok
Assistant-Session: 01a09dc1-b21e-77e1-919e-fcad2f82b267
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
Updated by fix-consistency on 2026-09-07:
- update .custodian-brief.md for flex-auth
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 715613@bnt-lap001
Assistant-Session: fabd95c1-4c9e-4080-8849-8707ae025f80
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
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
Updated by fix-consistency on 2026-09-07:
- update .custodian-brief.md for flex-auth
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 715613@bnt-lap001
Assistant-Session: fabd95c1-4c9e-4080-8849-8707ae025f80
gate-house circulated security-layer-model v0.8 for assent. Assent given
with four findings; F1 is fail-open and blocking for calling the section
6.4 PEP obligations complete, though not for anyone's adoption — the
condition already exists under v0.7 and is not created by this version.
F1. "A decision from access-engine" is not a checkable predicate. 6.4
obligation 1 requires a PEP to hold one; obligation 2 supplies a test it
is emphatic is mechanical and not a judgement call. That test establishes
which request a decision is for and nothing about who issued it, because
every input to every digest a PEP can check is either sent by the caller
or published. A responder knowing the package id and version reproduces
all three exactly.
What makes it sharp is internal: 9.4 requires the approval object to
carry authenticated entries, and 6.4 obligation 5 then requires each
artifact be validated against its owning layer, naming the approval-claim
and DecisionEnvelope pair as the live instance. So the obligation is
unsatisfiable for half the pair it was written about — a PEP can validate
the approval's authenticity and cannot validate the decision's. The
asymmetry is argued nowhere.
Section 16 already carries this observation one layer up, about the
standard's own publication path having no digest or freeze discipline.
Applied to the artifact the standard regulates, it is F1. The gap was
visible from inside and got recorded against the wrong artifact.
F2 answers the absent-vs-unknown question gate-house flagged as ours.
Runtime behaviour must be identical — absent fails closed too, and for a
stronger reason, since it is the branch reached by discovering your model
of your own scope axis was wrong. But omitting the distinction makes
totality unfalsifiable: a map with an unknown catch-all satisfies 6.4
obligation 3 vacuously, and its drift test passes by exercising the
catch-all rather than the axis. Same defect we published as
FLEX-DEC-2026-008 — coverage counted rather than executed, in a stance
map instead of a fixture suite.
F3. "The published map MUST equal the shipped behaviour, and that
equality SHOULD be asserted by a test", in a paragraph arguing drift is
worse than no publication. The strongest obligation in 6.4 has the
weakest verification, and 13.1 shows four of five rows already test it.
F4. 13.1 marks ops-warden's unknown cell non-conformant and states
ops-mason's map as simply not published, which is a plainer violation of
the same obligation, unmarked in the same table.
Also answered their direct question: no, they did not over-read our
divergence report. Added that the ruling costs us nothing, since we are
not PEP-shaped, so our concurrence is weak evidence and ops-warden's
assent is worth more here.
FLEX-WP-0023-T05 and FLEX-WP-0024-T04 close. Notes T01-T03 landed from
Glas meanwhile with real receipts including an actually-expired token,
and that enforce authenticates the caller while leaving F1 untouched —
as their own note says.
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
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
Updated by fix-consistency on 2026-09-06:
- update .custodian-brief.md for flex-auth
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 715613@bnt-lap001
Assistant-Session: fabd95c1-4c9e-4080-8849-8707ae025f80
Updated by fix-consistency on 2026-09-06:
- workplan status: ready → active
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 715613@bnt-lap001
Assistant-Session: fabd95c1-4c9e-4080-8849-8707ae025f80
secrets-engine probed the Service DNS name handed over in FLEX-WP-0021-T05
and found it resolves, from the workstation, to an unrelated public host.
Reproduced here: search ad.binect.de answers wildcard, so
flex-auth-secrets-engine.flex-auth.svc.cluster.local and
this-service-does-not-exist.flex-auth.svc.cluster.local both resolve to
80.158.43.29, while the trailing-dot FQDN correctly fails. A bare Service
name in a handover is not merely unreachable from there, it is a live
misdirection, and the handover was ours.
Had a deployment pointed at it, the CheckRequest body would have gone to
that host: subject, tenant, lane and resource ids, stage, field names,
purpose, plus the caller's bearer token.
Trailing-dot FQDN and "in-cluster only" now replace the bare name in the
example README, SCOPE.md, and the T05 note.
Their real question was how the response channel is authenticated, and
they declined to answer it locally because choosing a transport control
for our service is not a consumer's call. Right boundary, so the answer
is recorded here as FLEX-DEC-2026-010: it is not authenticated. Pins
serve plain HTTP, the envelope carries no signature, and a responder that
knows the package id and version can return a well-formed allow that
passes every check a consumer performs.
The part worth stating in the contract is that the digests do not help
and look like they do. Every input to request_digest,
policy_package_digest and registry_snapshot_digest is either sent by the
caller or published in this repo, so a forger reproduces all three
exactly. They establish integrity of the binding, never authenticity of
the source — and publishing more digests makes a forged envelope look
more authenticated, not less.
For secrets-engine specifically: fail-closed protects against a PDP that
is absent, not against one that lies. An unreachable PDP denies; a lying
PDP allows.
Third instance of one seam in three decisions. 008: a tenant carried
into the digest and never compared — visible, not enforced. 009: a caller
authenticated and never recorded — enforced, not visible. 010: a record
verifiable and unauthentic — checkable, but not evidence.
One nuance that changes the operator recommendation: kubectl port-forward
does authenticate the responder, transitively — no DNS name, one named
pod, API-server TLS. That is the exact reverse of the caller direction,
where it bypasses the NetworkPolicy. Independent properties pointing
opposite ways, so neither can be summarised as "the network protects it".
FLEX-WP-0024 carries signing; key custody routes through warden/OpenBao
rather than minting a key here.
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
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
Updated by fix-consistency on 2026-09-06:
- update .custodian-brief.md for flex-auth
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 715613@bnt-lap001
Assistant-Session: fabd95c1-4c9e-4080-8849-8707ae025f80