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
156 lines
7.1 KiB
YAML
156 lines
7.1 KiB
YAML
# ops-warden — DERIVED form of the NetKingdom security layer declaration
|
|
#
|
|
# THIS FILE DOES NOT GOVERN. The declaration is the `layer:` key in INTENT.md's
|
|
# frontmatter; this file is a derived artifact under §11's derived-artifact rule
|
|
# and must agree with it (GH-DEC-2026-017 §1, amendment A11). A disagreement
|
|
# between the two forms is a finding in its own right and is reported, never
|
|
# resolved away by precedence.
|
|
#
|
|
# Framework: net-kingdom/canon/standards/security-layer-model
|
|
# Assent: docs/adr/ADR-0010 (ops-warden's own voice, per §11 "who must declare")
|
|
# Validate: python3 scripts/check_layer_conformance.py
|
|
#
|
|
# §11 makes one check mechanical: "every direct Tooling client in a Staff
|
|
# repository maps to a declared §5.1, §5.2, or §5.3 entry". This file is that
|
|
# map. It is machine-readable because §5.3 requires it to be — ops-warden
|
|
# proposed that shape and is implementing it rather than declaring in prose.
|
|
#
|
|
# Conformance rule inherited from tenancy.yaml: accuracy, not altitude. A
|
|
# declared gap is TRACKED NON-CONFORMANCE (§11), never a claim of conformance.
|
|
|
|
schema_version: "0.2"
|
|
framework: netkingdom-security-layer-model
|
|
|
|
# §11 derived-artifact marking (GH-DEC-2026-017 §1 / A11).
|
|
derived: true
|
|
derived_from: INTENT.md
|
|
|
|
# NO `standard_version` KEY, AND DO NOT ADD ONE BACK.
|
|
# GH-DEC-2026-017 §5 / amendment A12: a layer declaration MUST NOT carry a
|
|
# standard version. The declared layer is a standing property of the repository
|
|
# and does not change when the standard is revised; a version here makes every
|
|
# revision read as though it invalidated every declaration. Version-scoped state
|
|
# belongs in the derived conformance record, which already must carry the
|
|
# version or commit it was derived at. Keeping the field "for information" was
|
|
# declined explicitly: a field that is present will be branched on. Absence is
|
|
# enforced by tests/test_layer_conformance.py.
|
|
|
|
repository: ops-warden
|
|
|
|
# RULED, 2026-09-21 (GH-DEC-2026-017 §2): INTENT.md declares `Staff` and this
|
|
# file declares `staff`, and THAT IS NOT A DISAGREEMENT. §3's vocabulary is
|
|
# closed — {Taxonomy, Tooling, Engine, Staff} — and comparison is ASCII
|
|
# case-insensitive: a conformance run MUST fold case before comparing, and a
|
|
# lowercase declaration is conforming, not tolerated. No repository was asked to
|
|
# re-spell anything. Do not "fix" this line to match INTENT.md, or the reverse;
|
|
# folding case is the checker's job, and it does it.
|
|
layer: staff
|
|
declared_by: docs/adr/ADR-0010
|
|
declared_at: "2026-08-29"
|
|
|
|
# §6.4 — ops-warden is PEP-shaped (it causes a protected side effect: issuing a
|
|
# certificate). Its unreachable-engine stance map is published separately, and
|
|
# asserted equal to shipped behaviour by tests/test_layer_conformance.py.
|
|
pep_stance: pep-stance.yaml
|
|
|
|
# Every direct contact with a Tooling-layer system (§4), one entry each.
|
|
tooling_contacts:
|
|
|
|
- id: ssh-ca-signing-write
|
|
shape: "5.3" # declared engine gap
|
|
module: src/warden/vault.py
|
|
symbol: VaultCA.sign
|
|
tooling: OpenBao
|
|
operation: "HTTP POST <addr>/v1/<mount>/sign/<role> with X-Vault-Token"
|
|
write: true
|
|
capability: "Sign a short-lived SSH certificate for an adm/agt/atm actor"
|
|
intended_owner: secrets-engine
|
|
blocked_on: >-
|
|
No engine exposes an SSH certificate signing surface. secrets-engine owns
|
|
credential abstraction, custody and lifecycle, which is the layer this
|
|
belongs in, but fronts no SSH-CA API today.
|
|
review: "2026-11-28"
|
|
note: >-
|
|
Production-verified and in daily use. This is the one lane ops-warden owns
|
|
permanently (§4). Signing continues while the gap is open: refusing would
|
|
remove production host access to close a documentation gap.
|
|
|
|
- id: desk-paste-once-provision
|
|
shape: "5.3"
|
|
module: src/warden/desk.py
|
|
symbol: _provision_to_openbao
|
|
tooling: OpenBao
|
|
operation: "bao kv put <path> <field>=- (value on stdin, never argv)"
|
|
write: true
|
|
capability: "Founder paste-once provisioning of a secret straight into OpenBao"
|
|
intended_owner: secrets-engine
|
|
blocked_on: >-
|
|
No engine exposes an attended provisioning surface for a value the founder
|
|
holds and no automated path can produce.
|
|
review: "2026-11-28"
|
|
note: >-
|
|
Attended and founder-operated (WP-0029). The value reaches OpenBao without
|
|
passing through a terminal, an argv, or the audit log.
|
|
|
|
- id: taint-metadata-read
|
|
shape: "5.1" # read-only diagnostic observation
|
|
module: src/warden/taint.py
|
|
symbol: fetch_taint_status
|
|
tooling: OpenBao
|
|
operation: "bao kv metadata get -format=json <path>"
|
|
write: false
|
|
capability: "Report EXPOSED taint (custom_metadata) without reading secret data"
|
|
intended_owner: secrets-engine
|
|
blocked_on: >-
|
|
No engine exposes a disclosure-taint query. Metadata-only by construction —
|
|
reading the data would be the 2026-07-16 vector this exists to avoid.
|
|
review: "2026-11-28"
|
|
|
|
- id: access-proxy-conduit
|
|
shape: "5.2" # conduit
|
|
module: src/warden/proxy.py
|
|
symbol: proxy_fetch, proxy_attended_login_exec
|
|
tooling: OpenBao, key-cape
|
|
operation: "Runs the catalog-declared owner fetch_command as a child process"
|
|
write: false
|
|
capability: "warden access --fetch/--exec/--out/--wrap for exec_capable lanes"
|
|
supplied_authority: none
|
|
evidence:
|
|
no_own_credential: src/warden/proxy.py::_caller_env
|
|
test: tests/test_proxy.py::test_conduit_supplies_no_authority_of_its_own
|
|
audit: "audit.jsonl records the caller, the lane, and the outcome; never a value"
|
|
note: >-
|
|
The §5.2 test is the supplied-authority property: ops-warden presents no
|
|
credential of its own, cannot widen what the caller could already do, and
|
|
the action reconstructs as the caller's. Governed by ADR-0002.
|
|
|
|
- id: caller-identity-token
|
|
shape: "5.2"
|
|
module: src/warden/caller_identity.py
|
|
symbol: resolve_caller_token
|
|
tooling: OpenBao
|
|
operation: "Runs the operator-configured caller_auth command, or reads token env"
|
|
write: false
|
|
capability: "Establish the caller's own identity for the pre-sign policy gate"
|
|
supplied_authority: none
|
|
detection: voluntary # runs an operator-configured command, so no fixed
|
|
# argv shape to scan for; declared rather than omitted
|
|
note: >-
|
|
Obtains the CALLER's credential by the operator's configured means; adds no
|
|
authority. Never mints, and never persists what it resolves.
|
|
|
|
# Contacts that are deliberately NOT Tooling contacts, recorded so the check is
|
|
# total rather than silently selective.
|
|
non_tooling_clients:
|
|
|
|
- module: src/warden/policy.py
|
|
target: access-engine (flex-auth)
|
|
rationale: "Engine API — §5 permits it; this is the shape §5 prescribes."
|
|
|
|
- module: src/warden/worker.py
|
|
target: state-hub, llm-connect
|
|
rationale: >-
|
|
Not catalogued in §4. The layer catalog scopes the security estate, and
|
|
neither the State Hub nor llm-connect appears in it, so no §5 shape applies
|
|
on the standard's own terms. Raised with gate-house 2026-08-29 as a scope
|
|
question rather than resolved unilaterally — see the assessment note.
|