Commit graph

18 commits

Author SHA1 Message Date
a70f559d40 Apply GH-DEC-2026-017: INTENT.md governs, the sidecar is derived, no version
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 3s
Verified against gate-house's own committed files before editing, not the inbox
message: GH-DEC-2026-017 in decisions/decisions.md at gate-house@def0af2,
amendments A9-A13 in docs/amendments/v0.8-section-11-declaration-amendments.md,
and sections 3, 4 and 11 of net-kingdom's security-layer-model_v0.8.md. The
ruling and docs/layer-declaration-precedence.md's secondary account agreed.

INTENT.md's frontmatter is the declaration; layer.yaml is a derived artifact,
now marked derived: true / derived_from: INTENT.md, and it does not govern.

standard_version is removed from BOTH forms. The ruling's general form is that a
layer declaration must not carry a standard version, and INTENT.md is the
declaration, so removing it from the sidecar alone would have left the field in
the only file that actually declares. INTENT.md's version-pinned `standard:`
path is de-versioned for the same reason: a pinned path reads as a validity
condition. The version ops-warden assented at stays with the assent, ADR-0010.

NO LAYER VALUE IS CHANGED. INTENT.md still says Staff and layer.yaml still says
staff. Section 3's vocabulary is closed, four tokens, and case-insensitive: the
two forms were never in disagreement about a layer, and the ruling asked nobody
to re-spell anything. The comment marking the divergence is rewritten from
"unruled, do not touch" to "ruled, folding case is the checker's job".

check_layer_conformance.py would have rejected the conforming declaration this
ruling produces -- it listed standard_version as a required key. It now reads
INTENT.md as the governing form, ASCII-folds before comparing, validates both
values against the closed four-token vocabulary (Taxonomy included; omitting it
is the defect A9 records against the estate's other validator), requires the
derived marking, rejects a returning standard_version in either file, and
reports a post-fold disagreement between the forms as a finding rather than
resolving it away by precedence.

The test asserts the fold, not equality. An equality assertion here would be
this repository quietly performing the re-spelling the ruling declined to order;
the fold still fails on a real layer divergence.

pep-stance.yaml is untouched. A stance map is not a layer declaration, and the
sidecar schema beyond the derived marking and the version is explicitly not
ruled.

layer.yaml is the form seven repositories copied, so the adopter change set is
written out in wiki/playbooks/netkingdom-layer-declaration.md -- including the
trap that an adopter which also copied the checker turns a conforming
declaration into MALFORMED exit 2 by removing the field alone. No other
repository is edited here.

Still open: where the removed version lives. A12 says the derived conformance
record "already MUST" carry it; ops-warden has a re-runnable checker that emits
nothing durable. Asked of gate-house in message 4220413a, unanswered, and left
open rather than answered by choosing. Nothing above depends on it.

Carries WARDEN-WP-0034-T06 to done.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 63291@bnt-lap001
Assistant-Session: 8bd77868-ca68-4f49-bb1e-d539ecc0d703
2026-09-21 02:38:55 +02:00
c186a4e135 Record GH-DEC-2026-017 without applying it yet
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 3s
The precedence ruling landed mid-session: INTENT.md governs, the sidecar is
derived, section 3 folds case so nobody re-spells anything, and standard_version
comes out of the declaration. Two asks land on ops-warden because layer.yaml is
the form seven repositories copied.

Not applied here. Both asks edit this repository's security-layer declaration --
and the estate's reference shape -- on the strength of an instruction delivered
in an inbox message. The change set, and the condition that it be verified at
gate-house@def0af2 rather than from the message text, are written down so the
mandated session does not have to reconstruct them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 63291@bnt-lap001
Assistant-Session: 8bd77868-ca68-4f49-bb1e-d539ecc0d703
2026-09-21 02:26:33 +02:00
baf53602ca Revert the npm field, re-measure coverage, and hold the layer divergence
Five inbox items worked, none of which changed a credential value or moved a
secret.

whynot-design-npm-publish: field reverted npm_token -> NPM_AUTH_TOKEN and the
path confirmed, on railiance-platform's attended, read-only, no-value field
enumeration (their docs/evidence/2026-09-10-npm-lane-field-resolution.json).
Exactly one field is present at the governed path. The 2026-09-09 change was
adopted from a coordination message and would have failed at the WP-0037-T03
rotation. The ungoverned second location is recorded as an explicit non-lane,
not deleted and not tidied away.

pep-stance coverage: published figures were stale by eight lanes (unknown
18->20, not_applicable 12->15) while resolved stayed at 3 — the denominator
moved, the classification did not. Caught by the test that asserts the published
block equals what report_coverage.py measures. tests/test_workload_join.py held
the same stale counts; both now measure the same populations.

rapp-qonto-keycape-client: blocker character updated — authority exists and is
unexercised by owner decision ("not yet", offer open), which is not the same as
no authority existing. Reopen triggers are events, never elapsed time.

flex-auth -> access-engine rename (WARDEN-IN-0003): access-engine added to the
policy-check lane's keywords so routing resolves under both names from today.
owner_repo deliberately not flipped — policy.py sends it as resource.system on
every /v1/check, and FLEX-DEC-2026-013 keeps runtime names as flex-auth.

layer declaration: INTENT.md says Staff, layer.yaml says staff, section 11 does
not say which governs. Neither changed; gate-house holds the ruling. Position in
docs/layer-declaration-precedence.md, wait in WARDEN-WP-0034-T06, and a comment
in layer.yaml telling the next session not to "fix" it — the divergence is the
evidence the ruling is made against.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 63291@bnt-lap001
Assistant-Session: 8bd77868-ca68-4f49-bb1e-d539ecc0d703
2026-09-21 02:16:33 +02:00
00145d705e feat: complete local layer model v0.7 conformance work
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a06eaf-3425-7f92-a0c2-bb4aa4faebe4
2026-09-05 01:19:48 +02:00
70d8b503f0 Assent to the NetKingdom security layer model (WARDEN-IN-0001)
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
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
2026-08-28 21:47:44 +02:00
bc1966da82 docs: record attended login containment evidence
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a0290b-3241-74c3-b868-6049545af836
2026-08-23 01:32:59 +02:00
461f580813 docs: project remaining WP0027 owner gates
All checks were successful
CI Smoke / host-smoke (push) Successful in 1s
CI Smoke / container-smoke (push) Successful in 2s
Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a0290b-3241-74c3-b868-6049545af836
2026-08-22 23:50:46 +02:00
7fa6985f72 docs: record recovery preparation boundaries
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a0290b-3241-74c3-b868-6049545af836
2026-08-22 22:12:52 +02:00
5ac47520b1 docs: establish attended recovery drill scenario
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a0290b-3241-74c3-b868-6049545af836
2026-08-22 22:00:35 +02:00
e3b9b1620c fix: route OpenBao recovery ceremonies safely
Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a0290b-3241-74c3-b868-6049545af836
2026-08-22 20:54:45 +02:00
fff76ef089 docs: activate credential break-glass planning
All checks were successful
CI Smoke / host-smoke (push) Successful in 1s
CI Smoke / container-smoke (push) Successful in 1s
Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a0290b-3241-74c3-b868-6049545af836
2026-08-22 20:36:49 +02:00
e24d2d5bd0 docs: record live zone config migration
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a0291a-1e87-7151-9934-fcbfe3f65eb1
2026-08-22 15:50:42 +02:00
7ce58ae638 feat: adopt security zones and explicit workload refs
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a0291a-1e87-7151-9934-fcbfe3f65eb1
2026-08-22 15:36:37 +02:00
c357ce5908 WARDEN-WP-0033 T01/T02: two under-graded lanes, and ADR-0008
secrets-engine reviewed our catalog metadata while drafting their five entries
and graded issue-core-ingestion-api-key and reuse-surface-hub-write-token high.
We had both as standard, and had deliberately regraded them DOWN on 2026-08-19.

They are right. Both paths carry a second credential our grade never looked at --
GITEA_BACKEND_TOKEN (CCR-2026-0002, a deliberate field-set decision) and a
dual-consumer webhook HMAC (CCR-2026-0005). Neither is recovered by rotating the
credential the lane is named after.

The defect is structural: we graded the lane by its headline field, but a read
returns every field at the path. Worse, the evidence was already in the CCRs we
cite as authoritative -- not missing, unread -- and a test asserted the wrong
answer, so a correct first-pass grade got overruled by it.

ADR-0008 records the rule: a grade covers every field its path discloses.
ADR-0007 is unchanged and still governs; this says what the grade is of.

Six of the remaining standard lanes have no KV path. Two have paths and no field
evidence; per ADR-0008 they are stated as unknown rather than assumed, and left
for operator-sanctioned grading.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 08:36:42 +02:00
ac85259c20 Grade every catalog lane; record ADR-0007
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 2s
Closes the RISK-F-0003 exposure. All 14 ungraded lanes now carry an explicit
risk grade with its justification in the entry: 17 high, 10 standard, 0
ungraded. The agent read-boundary now fires (exit 7) on lanes that were silently
outside it.

Graded on merit rather than defensively. A first pass marked two ordinary
internal workload secrets high; test_high_risk_lanes_classified asserted the
opposite and was right, so both were regraded down. high means disclosure into a
logged context is damaging beyond what rotation recovers. inter-hub-bootstrap-ssh
is high conservatively, with the reason in the entry so it is regraded with
evidence rather than assumed down.

ADR-0007 records the rule the grading rests on: build-stage permissiveness
applies to controls that gate work, not to controls that prevent credential
disclosure. The test is friction, not severity — the read-boundary blocks nobody,
since --out/--exec/--wrap remain available, so relaxing it buys nothing. A
blocked operation is recovered by retrying; a credential in a logged transcript
is not recovered by rotation.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 23:44:58 +02:00
8c58f8bfa1 Hand the zone model to zone-engine; keep WP-0032 as the consumer side
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 2s
zone-engine is seeded and owns the security zone model as ZONE-WP-0001. Under
ADR-0005 ops-warden implements one lane narrowly and routes the rest, and an
estate-wide enforcement model is not a lane to absorb — it was ops-warden's
deferred flip that exposed the gap, not ops-warden's model to define.

WARDEN-WP-0032 is rewritten as the consumer side: hand the estate inputs to
ZONE-WP-0001-T02 (27 catalog lanes, the actor inventory, the three posture axes,
the three controls the model must express, and the compiled-registry path),
then replace policy.enabled with a zone-aware control and amend ADR-0006 to say
ops-warden follows the model rather than owning it.

ADR-0006 and SCOPE updated to point at zone-engine, which joins the related
repositories table.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 21:20:34 +02:00
cbf6828061 ADR-0006: enforcement is zone-scoped; defer the policy.enabled flip
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
flex-auth enforced its ops-warden pin (FLEX-WP-0016 T03) and the gate verified
clean against it: readiness exits 0, decision:f3f7c88f9585582a, anonymous
/v1/check now 401. Everything needed to set policy.enabled: true was in place.

It stays false, by decision. policy.enabled is a single repo-wide boolean, and
with fail_closed: true it makes flex-auth a hard dependency of every warden
sign — including the certs the ops-bridge tunnels depend on, one of which
carries the policy call itself. Uniform enforcement across an estate being
actively rebuilt hardens the access needed to perform the rebuild.

The repo already refuses one-dimensional posture: WP-0015 shipped environment
and maturity axes, WP-0029 added organization_posture. A global flag ignores all
three. ADR-0006 records that enforcement belongs to a zone, and binds future
work — a zone-blind enforcement flag is out of order, not merely unwise.

WARDEN-WP-0032 drafts the zone model, leading with the ownership question:
whether this is ops-warden's to own or NetKingdom canon to consume (ADR-0005).
WP-0031 is finished with T05 cancelled and resuming as WP-0032-T05.

Also replaces the hand-run kubectl port-forward with a managed ops-bridge
tunnel, flex-auth-ops-warden-railiance01 (-L 19090:10.43.1.165:8080).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 20:31:28 +02:00
35aff380a3 Lift ops-warden's binding rules into owned ADRs
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Five rules that governed this repo lived in wiki prose, a workplan, and a
comment at the top of catalog.yaml. All were followed; none was addressable.
A reader outside ops-warden could not cite one, could not tell whether it was
current, and — the point of this change — could not tell whether it was ours
to change or someone else's that we merely obey.

  ADR-0001  The routing catalog is a pointer layer, never a second copy
  ADR-0002  ops-warden is a transparent conduit, never a secret broker
  ADR-0003  Cover gaps, but never silently own them
  ADR-0004  High-risk lanes refuse raw value streaming to agent sessions
  ADR-0005  Implement one lane narrowly, route everything else

Each carries owner: ops-warden, which is the load-bearing field. It says we
follow the rule AND we are responsible for changing it — by superseding ADR,
never an in-place edit. The failure this prevents runs both ways: a rule we own
mistaken for inherited canon never gets fixed, because we wait for an owner who
does not exist; inherited canon mistaken for ours gets quietly bent, and the
drift is invisible until it breaks a repo that trusted the canonical version.

Rules we follow but do not own — NetKingdom canon, the IAM profile, the
credential-management standard, the-custodian's ADR-001 workplan convention —
are cited, never copied into docs/adr/. Copying them would recreate exactly the
second-source-of-truth failure ADR-0001 exists to prevent. architecture.md also
now flags the three-digit/four-digit ADR-001 vs ADR-0001 collision, which is
itself an ours-versus-inherited confusion waiting to happen.

Publication verified rather than assumed: all five render through policy-nexus
tools/render.py, and owner reaches the reader in three places — the page eyebrow
(render.py:346), the index Owner column (build_site.py:123,137), and the
publication manifest. build_site.py:179 makes title/status/owner required, so
ownership cannot be dropped on the way out. policy-nexus publishes and never
writes back; docs/adr/ stays the source of truth.

Documentation adapted: SCOPE.md gains a Governing rules section and an orientation
entry; .claude/rules/architecture.md replaced its stub with the ADR index, the
owned-versus-inherited rule, and ADR-over-wiki precedence; finding-routing.md's
ADR-gap section closed; catalog.yaml's no-double-source header now cites ADR-0001
rather than the originating workplan.

uv run pytest -q → 338 passed, 4 deselected.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 13:35:13 +02:00