Updated by fix-consistency on 2026-09-09:
- update .custodian-brief.md for ops-warden
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 1276224@bnt-lap001
Assistant-Session: 426ec497-e1c4-4dd3-b417-dfce1ca1dbc3
Six inbound messages attended, three of them carrying real asks.
flex-auth FLEX-DEC-2026-004 answers WARDEN-WP-0034-T05's decision-lifetime
question: a decision lifetime shorter than the certificate TTL is meaningful,
but only as authority to ISSUE, never to USE an already-issued certificate.
The question had mistaken a decision lifetime for a credential lifetime. They
declined to move the §9.7.2 revocation residue to their side; that refusal is
right and the stance map is unchanged. T05 still waits on ops-mason and
railiance-infra.
WARDEN-WP-0039-T03 routed to flex-auth: is there an admitted contract for a
delegated credential read where caller and resource owner differ? Three
outcomes named as equally acceptable, including that there should be no such
contract and the interim proxy transport is itself the defect -- which would
shorten WP-0033 rather than block it. Two easy fixes ruled out in writing:
broadening the caller binding, and relabelling resource.system as ops-warden
so the binding matches. The second would make the audit trail assert we own
credentials we deliberately do not, by editing a field instead of making an
argument.
WARDEN-WP-0037: npm path routed to railiance-platform, catalog unchanged
pending their answer. secrets-engine refused to resolve it from a
coordination message and was right; asserting our own pointer is
authoritative because it is ours would route around that. The ask names a
location only, and flags that a `bao kv get` answer would be the 2026-07-16
disclosure vector on a risk: high lane.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013EPuTc18FjU5WFqoSEKH3C
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 1276224@bnt-lap001
Assistant-Session: 426ec497-e1c4-4dd3-b417-dfce1ca1dbc3
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013EPuTc18FjU5WFqoSEKH3C
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 1276224@bnt-lap001
Assistant-Session: 426ec497-e1c4-4dd3-b417-dfce1ca1dbc3
secrets-engine corrected our claim (msg 15f0c0ca): `npm_token` is the KV
field on the whynot-design publish lane; `NPM_AUTH_TOKEN` is the environment
variable their publication-scope policy injects. Their doc lists the two as
separate rows and we had copied the env var in as the field name, so our
`fetch_command` named a field that does not exist -- `bao kv get
-field=NPM_AUTH_TOKEN` could only ever have failed.
This is ADR-0001's failure mode, not a typo: a pointer layer restating an
owner's procedure and getting it wrong. Corrected from the owner's statement
rather than re-derived here, and the catalog now records the distinction
inline so the env var does not get copied back in.
The path is a separate and still-open question. secrets-engine declined to
resolve it unilaterally -- which location backs the lane for reads is
railiance-platform's custody state -- so the path is unchanged and routed to
them rather than moved on a coordination message.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013EPuTc18FjU5WFqoSEKH3C
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 1276224@bnt-lap001
Assistant-Session: 426ec497-e1c4-4dd3-b417-dfce1ca1dbc3
gate-house circulated security-layer-model v0.8, whose §6.4 obligation 3
makes our `unknown: fail_open` cell non-conformant, and asked to be argued
with rather than obeyed.
Finding 1 -- assent. They wrote the falsifier into GH-DEC-2026-009: a scope
genuinely unknown AND genuinely low-consequence, expected to be a §5.1
read-only diagnostic. We looked and do not have one. The stance map governs
`warden sign` -- a credential-issuing side effect -- so §5.1 does not reach
it and the argument stands. Being unclassifiable must not buy permissiveness.
Finding 2 -- adopting it today would be a global fail-closed flag in all but
name. Of four signing targets, zero resolve to a zone and three are
`unknown`, so the cell would fail closed on essentially every certificate
during a flex-auth outage -- including the SSH certificate needed to reach
the host and repair flex-auth. That is exactly ADR-0006's rejected
configuration reached by another route. Asked for a dated transition gated
on coverage, or failing that for §13.1 to record coverage alongside stance:
a row reading `unknown: fail_closed` while every target is unknown is
conformant and misleading.
Not flipping the cell. It is a proposed standard, 18 of our 18 unknown
lanes are unknown because another repo has not declared, and ADR-0009 rule 3
forbids closing that with inference -- a stricter stance is not a licence to
manufacture the membership that makes it survivable. WARDEN-WP-0040 records
the order: classify the continuity path, raise coverage by asking owners,
then supersede ADR-0009's unknown row.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013EPuTc18FjU5WFqoSEKH3C
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 1276224@bnt-lap001
Assistant-Session: 426ec497-e1c4-4dd3-b417-dfce1ca1dbc3
flex-auth fixed enrichment so registry facts beat caller-supplied ones
(FLEX-DEC-2026-012) and asked each consumer to confirm the ceiling and
allowlist keys are actually declared -- the fix wins only where the registry
HAS a value, and a manifest omitting max_ttl_hours hands that ceiling back
to the caller.
Confirmed, and made durable rather than read once.
scripts/check_flex_auth_manifest_coverage.py audits both ways a ceiling
gets handed back: an actor with no manifest resource at all (warden sign
names ssh-cert:actor/<name> whether or not the snapshot was rebuilt --
an honour-system step in SCOPE.md), and a resource missing one of the
seven keys. A null is treated as absent, because for enrichment it is.
Also asserts the property their exploitability assessment rested on and
nothing here held: ops-warden sends no resource.attributes. It was true
when they read it, secrets-engine sends them on every request, and it was
one refactor from silently stopping being true.
Current state: no gap. 4 actors, 4 resources, all seven keys declared.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013EPuTc18FjU5WFqoSEKH3C
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 1276224@bnt-lap001
Assistant-Session: 426ec497-e1c4-4dd3-b417-dfce1ca1dbc3
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013EPuTc18FjU5WFqoSEKH3C
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 1276224@bnt-lap001
Assistant-Session: 426ec497-e1c4-4dd3-b417-dfce1ca1dbc3
Updated by fix-consistency on 2026-09-08:
- update .custodian-brief.md for ops-warden
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 1276224@bnt-lap001
Assistant-Session: 426ec497-e1c4-4dd3-b417-dfce1ca1dbc3
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013EPuTc18FjU5WFqoSEKH3C
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 1276224@bnt-lap001
Assistant-Session: 426ec497-e1c4-4dd3-b417-dfce1ca1dbc3
key-cape corrected two blockers that had stopped being true after our
2026-08-28 source-read:
- rapp-qonto-keycape-client: `keycape service-token` (2026-09-05) is the
native exchange the blocker recorded as absent, and `keycape verify-client`
(2026-09-08) is rotation step 3 as one command. Narrowed to steps 1-2 --
successor generation and the CAS write -- rather than cleared, as they
asked. rotation.automatable -> false so a future executable driver is not
told a lane with no admitted custody transport is drivable; the per-step
truth moves into the steps.
- key-cape-oidc-login: ownership ACCEPTED by key-cape, so verified moves from
asked-and-waiting to owner-confirmed. Lane stays interim -- acceptance
covers the identity half, while the fetch_command yields an OpenBao token
whose mount, role mapping and enforcement are not key-cape's.
Two tests pinned `key-cape-oidc-login` to sitting `asked-and-waiting`, so
answering the question broke them -- they failed on good news. Both now
assert the property instead: an unverified blocker is stale regardless of
date, over whatever lanes are in that state.
Verifying the routing answer against our own front door turned up a defect:
`warden plan` returns `autonomous` for a custody *write* and answers it with
read transports, because it has no read-versus-mutate intent. Recorded as
WARDEN-WP-0038 (proposed) -- the WP-0033-T06 shape, as a class this time.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013EPuTc18FjU5WFqoSEKH3C
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 1276224@bnt-lap001
Assistant-Session: 426ec497-e1c4-4dd3-b417-dfce1ca1dbc3
Updated by fix-consistency on 2026-08-29:
- update .custodian-brief.md for ops-warden
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 4014535@bnt-lap001
Assistant-Session: d0036016-73e8-4da1-8e47-563e3ab39a3c
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YWBMovyFoy9RRrfL7zKvPJ
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 4014535@bnt-lap001
Assistant-Session: d0036016-73e8-4da1-8e47-563e3ab39a3c
The standard is accepted at v0.7, with SECURITY-COMPANION.md v0.2 as its
operative form. Four ops-warden findings were adopted between v0.4 and v0.7 —
§9.1's two marks, §5's Tooling scope rule, §6.4 obligation 1's second limb, and
§13.1's existence — and both ops-warden declaration artifacts are now cited in
the text as the estate's reference forms.
INTENT.md gains frontmatter (layer: Staff, pep_shaped: true) because §11 requires
a machine-readable declaration and prose cannot distinguish a declaration from a
transcribed review. The note now covers the agent principal (§3.4), the PEP
shape, the attributive evidence position, and the role the companion assigns:
the estate is told to ask ops-warden which lane, which credential, which route.
SCOPE.md records what is actually shipped against v0.7 and the honest conformance
state — declared gap, which is tracked non-conformance, not conformance.
The assessment checked every obligation against shipped code rather than intent.
Three gaps survive:
- §9.7.2 requires a PEP to state one revocation visibility deadline. Ours is
unstated, and the honest value is uncomfortable: the cert TTL, up to 48h. A
cert outlives revocation of the decision that authorized it — no CRL, no KRL
distribution. That is a design property never written down, which is exactly
what §9.7.2 exists to force into the open.
- §3.4 rule 1 forbids standing credentials and requires issued, attributable
authority. ADR-0004's boundary keys on WARDEN_AGENT_ID, which an agent sets
about itself. key-cape now issues a real coding-agent identity, so the
ops-warden half can stop being advisory.
- §9.6 cadence remains undeclared. Attributive, so SHOULD not MUST, but silence
through two reviews is the one outcome that is not defensible.
WARDEN-WP-0034 addresses all three, plus the discoverability gap the companion
creates and two items to route rather than absorb.
402 tests pass, ruff clean.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YWBMovyFoy9RRrfL7zKvPJ
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 4014535@bnt-lap001
Assistant-Session: d0036016-73e8-4da1-8e47-563e3ab39a3c
All three v0.4 findings were acted on — §9.1 split into pending/declared-gap and
§5's scope rule adopted as recommended and credited, and §9.6 ruled via the
load-bearing/attributive distinction with ops-warden's `# audit must not block
signing` named as the estate's live example.
Checked the favourable ruling rather than accepting it. §9.6's test is "no
control branches on its presence": the only consumer of audit.jsonl is `warden
activity`, which displays. Nothing gates on a signing record, so the lane is
genuinely attributive. AuditTrail.md now records the ruling instead of the open
question, and states that the trade must be revisited if a control ever gates on
the trail.
CONFORMANCE ACTION. §6.4 obligation 3 requires a stance map "published rather
than held in code", and requires every PEP-shaped consumer to publish one so the
maps can be inventoried — naming ADR-0009 as the reference shape. ops-warden was
not doing it: the map lived in PolicyConfig.failure_modes, a dataclass default.
Not a code comment, but not published either.
pep-stance.yaml publishes it, and the test asserts the published map EQUALS the
shipped default. A published map that may drift from the code is worse than no
map, because it invites reliance it cannot support.
Two findings sent to gate-house, in history/2026-08-29-layer-model-v06-review.md:
§6.4 obligation 1 (no side effect without a decision record) contradicts
obligation 3 and §9.3, with ops-warden's blessed fail-open stance as the
instance; and §6.4 mandates a stance-map inventory in §13 that §13 does not
implement — where ops-warden is currently the only PEP to have published one.
402 tests pass, ruff clean.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YWBMovyFoy9RRrfL7zKvPJ
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 4014535@bnt-lap001
Assistant-Session: d0036016-73e8-4da1-8e47-563e3ab39a3c
Assessment in history/2026-08-29-layer-model-v04-review.md. No objection to the
ruling; both ops-warden amendments were adopted (5.2 conduit, 5.3 declared gap).
Three findings, one against us.
The one against us is real. 9.6 requires emission atomic with the state change
for load-bearing evidence. ops-warden ca.py carries `pass # audit must not block
signing` and AuditTrail.md advertises that the trail never blocks the primary
action, so a failed append loses the event while the cert still issues -- a
suppressed event leaving the chain intact, which is exactly what 9.6 describes.
Whether to make it atomic is gate-house doctrine, not ops-wardens call: it would
give the estates operational access lane a new dependency on its own evidence
store. But one half of the fix is ours regardless -- the trail must not be read
as complete. AuditTrail.md now says absence of a record is not evidence of
absence, which it did not.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YWBMovyFoy9RRrfL7zKvPJ
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 4014535@bnt-lap001
Assistant-Session: d0036016-73e8-4da1-8e47-563e3ab39a3c
The security layer model moved v0.1 -> v0.4 (accepted) after ops-warden's
assent. Both §5 asks from ADR-0010 were adopted: §5.2 now sanctions the conduit
shape on the supplied-authority property, and §5.3 is the declared engine gap
amendment, carrying the four fields verbatim and crediting ops-warden's
delegation machinery as prior art.
Which creates an obligation. §5.3 requires those fields MACHINE-READABLY, and
§11 makes "every direct Tooling client maps to a declared §5.1/§5.2/§5.3 entry"
a mechanical check. ops-warden's declaration was prose in INTENT.md — the repo
that proposed the shape was not implementing it.
layer.yaml is the map: 5 contacts (2 declared gaps, 1 read-only observation,
2 conduits) plus the non-Tooling clients recorded explicitly so the check is
total rather than silently selective.
scripts/check_layer_conformance.py enforces it and found three undeclared
modules on its first run — all false positives (help text, a docstring, and the
doubles library that SIMULATES bao rather than calling it), which is why the
scan now matches invocation shapes instead of the word: an httpx call built
against the configured OpenBao address, or an argv whose first element is the
bao binary.
tests/test_layer_conformance.py adds the §5.2 test the standard says SHOULD
exist: _caller_env() returns the caller's environment unchanged, and proxy.py
is asserted not to reference X-Vault-Token, approle login, or token create — a
conduit that presents its own token is not a conduit.
No assertion on review dates, deliberately: a date-triggered failure breaks the
build on a calendar day with no code change, the same reasoning WP-0033-T05
recorded for blocker staleness.
398 tests pass, ruff clean.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YWBMovyFoy9RRrfL7zKvPJ
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 4014535@bnt-lap001
Assistant-Session: d0036016-73e8-4da1-8e47-563e3ab39a3c
Regenerated by fix-consistency; adds the inbound v0.3 review intake.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 2564823@bnt-lap001
Assistant-Session: 2a7ed827-4928-4b9f-8613-9135c9cadfe9
Updated by fix-consistency on 2026-08-28:
- update .custodian-brief.md for ops-warden
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 4014535@bnt-lap001
Assistant-Session: d0036016-73e8-4da1-8e47-563e3ab39a3c
railiance-platform accepted ops-warden revision 0fae0904 on 2026-08-23, in
RPF-WP-0017 (status: finished), together with railiance-infra approval at
186b030 and all five acceptance criteria met. T02 has been sitting `progress`
on a gate that was already open.
Verified rather than trusted: the receipt at bc1966da hashes to
d2ba444ed16989590325697e69d25283dc75a9432c29a72e627e80bf9fd987e4, matching
their record exactly.
One reason it went unnoticed is an identifier mismatch — T02 cites the
remediation interface as RAILIANCE-WP-0026-T01, but it is RPF-WP-0017-T01 in
the owner repo, and the cited id resolves to an unrelated workplan there.
Their acceptance is source acceptance only and authorizes no live drill, so
T02 stays progress: what unblocks is preparing a NEW scenario, which needs a
fresh human GO and is the platform owner s to execute. Surfaced, not taken.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YWBMovyFoy9RRrfL7zKvPJ
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 4014535@bnt-lap001
Assistant-Session: d0036016-73e8-4da1-8e47-563e3ab39a3c
T04 was the last open task, waiting on key-cape to accept or refuse ownership of
the coding-agent OpenBao issuance identity. They accepted, in KEY-WP-0009-T03,
on 2026-08-23: codex-railiance-platform is published in their
config/service-clients.example.yaml with subject service:codex:railiance-platform,
role coding-agent, scope openbao:login, 15m lifetime, and the service-auth
semantics in docs/openbao-service-auth-contract.md. The split is the one we
routed for — KeyCape issues, railiance-platform binds the OpenBao role, OpenBao
enforces, no secret value in either repo.
We found it by reading their repository. KEY-WP-0009-T04 records replying to
ops-warden; the inbox has zero messages from key-cape, read or unread. The task
sat `wait` on an answer that already existed.
That is T05's own lesson arriving on T04: a blocker is a claim about the world at
a date. So the same pass re-verified the two lanes pointing at key-cape against
their source instead of bumping dates:
- rapp-qonto-keycape-client -> verified: source-read. KEY-WP-0009-T02 did add
bounded service-auth, but that is client_credentials JWT issuance for OpenBao
machine login and does not front this client_secret_basic exchange or its
rotation. Blocker stands, now with evidence rather than memory.
- key-cape-oidc-login -> asked of key-cape today, which the entry had recorded
as still outstanding since 2026-08-21.
Also cleared the inbox that hid this: 9 stale unread, all superseded by shipped
work, with late closes sent to secrets-engine and llm-connect on the two threads
that had asked ops-warden something and never got an answer.
391 tests pass, ruff clean, boundary coverage 0 uncovered.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YWBMovyFoy9RRrfL7zKvPJ
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 4014535@bnt-lap001
Assistant-Session: d0036016-73e8-4da1-8e47-563e3ab39a3c
c374d41 added net-kingdom-lldap-bind-credential and
net-kingdom-privacyidea-admin-token as `risk: high` and did not re-run the
emitter, so registry/generated/high-risk-data-paths.yaml still described the
catalog at 0fae090. railiance-platform consumes that file instead of
hand-maintaining its deny list, and it has been reading a census two lanes short
since 2026-08-23.
This is precisely the drift WARDEN-WP-0033-T03 built the guard for — a lane
graded high after the last emit silently failing to reach the consumer. The
guard fired; nothing had acted on it.
The deny list itself does not move: both lanes are blocked on their OpenBao path
being published, so they land in `no_concrete_path` and concrete_path_count
stays 14. What changes is the count the consumer sees — 23 high-risk lanes, two
of which have no address yet. That is the honest signal and the reason the
bucket is listed rather than omitted.
check_agent_read_boundary.py still reports 0 uncovered.
The workload-join census moves 9 -> 11 not-applicable: both lanes are
provider/control-plane credentials rather than workload delivery lanes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YWBMovyFoy9RRrfL7zKvPJ
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 4014535@bnt-lap001
Assistant-Session: d0036016-73e8-4da1-8e47-563e3ab39a3c
gate-house asked ops-warden to assent to three boundary items ratified in
GH-DEC-2026-001. All three are assented in ADR-0010.
Staff: accepted. Grepping section 5 as it invites turned up a real
non-conformance — src/warden/vault.py is a direct OpenBao client performing a
write, and so is `warden desk`'s `bao kv put`. Section 5's only escape hatch is
read-only diagnostics, which does not cover a signing write, so both are
declared in INTENT.md as an engine gap with intended owner secrets-engine and
the blocker "no engine exposes an SSH-CA surface" — ADR-0003 turned inward
rather than an exemption argued for. taint.py is metadata-only and declared
under the read-only allowance; `warden access` proxies run under the caller's
identity and supply no authority of their own.
Doctrine versus runbook: accepted. NetKingdom Security Literacy becomes a lane
routing runbook that references gate-house doctrine instead of restating it. It
had also become a prose second source for registry/routing/catalog.yaml, which
ADR-0001 already rules against.
Lane versus rule: assented unconditionally, and the access-engine veto is not
exercised. One request on sequencing only — a window where both names resolve.
gate-house added to the routing tables in INTENT.md and SCOPE.md.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YWBMovyFoy9RRrfL7zKvPJ
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 4014535@bnt-lap001
Assistant-Session: d0036016-73e8-4da1-8e47-563e3ab39a3c
Regenerated by fix-consistency; adds the inbound assent intake.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 2564823@bnt-lap001
Assistant-Session: 2a7ed827-4928-4b9f-8613-9135c9cadfe9
The layer model is now published as
net-kingdom/canon/standards/security-layer-model_v0.1.md (proposed) and
ratified by gate-house GH-DEC-2026-001. The note previously said the
standard was not yet written.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 2564823@bnt-lap001
Assistant-Session: 2a7ed827-4928-4b9f-8613-9135c9cadfe9