# Review: Security layer model v0.7 vs INTENT, SCOPE, and implementation Date: 2026-08-29 Author: grok Standard: `net-kingdom/canon/standards/security-layer-model_v0.7.md` (accepted) Companion: `net-kingdom/SECURITY-COMPANION.md` v0.2 Compared: adapted `INTENT.md`, updated `SCOPE.md`, current CLI implementation Intake closed by this session: `SECRETS-IN-0001` ## Executive assessment The accepted layer model confirms what this repository already was in practice and had not yet declared in its own voice: **Engine, role Lifecycle** — a deterministic API over OpenBao for cataloged credential lanes. The gate-house review note at the top of `INTENT.md` was not a declaration. That note is now replaced by frontmatter, prose, `layer.yaml`, and a published PEP stance map. The intent remains directionally sound. The layer model does not move the system boundary (OpenBao stays Tooling; `access-engine` stays the only PDP; ops-warden stays the SSH Staff PEP). It **tightens the contract** this engine owes at every protected side effect, and it **names two proposed surfaces** this repository had not answered: an SSH-CA signing API, and secret-use evidence for kings-guard. `SCOPE.md` and the implementation already describe a guarded OpenBao CLI MVP with one proven native workload pilot. Against the new intent they are **aligned on layer and ownership, behind on PEP, decision, and evidence obligations**. Several of those obligations overlap active work in `SECRETS-WP-0007`; the new work is the layer-model remainder, not a restart of CLI hardening. A finding is raised against the §4 catalog cell, not against the proposed layer: the catalog says this repository owns "custody". Custody is OpenBao's. This engine owns the lifecycle API over that custody. ## What was declared | Artifact | Content | | --- | --- | | `INTENT.md` frontmatter | `layer: Engine`, `role: Lifecycle` | | `INTENT.md` body | Own-voice declaration, PEP shape, evidence bound, proposed surfaces | | `layer.yaml` | Machine-readable declaration; owned OpenBao contact; no decision surface | | `pep-stance.yaml` | Unreachable-engine stance by catalog stage; prod fail-closed | | `scripts/check_layer_conformance.py` | Mechanical check of the above | | `tests/test_layer_conformance.py` | Declaration + published map equals shipped prod fail-closed | Contest of the proposed **layer** (Engine): none. The determinism test holds. Contest of **catalog wording**: yes — "custody" should not appear as this engine's owned property. Answers to proposed ownerships: | Proposed surface | Answer | | --- | --- | | SSH-CA signing write (`ops-warden` §5.3 gap) | **Accept** as a Lifecycle engine API. **Decline** operational SSH-lane stewardship. ops-warden remains the Staff PEP. | | Secret-use evidence (`kings-guard`) | **Accept** as a proposed Lifecycle engine surface, bounded by §9.6. Not shipped. | ## INTENT vs SCOPE No contradiction on layer, owners, or forbidden claims. Drift is maturity: | Intent claim | SCOPE today | Gap kind | | --- | --- | --- | | Engine / Lifecycle declaration | Declared | Closed this session | | Consume an access-engine decision before every protected side effect | Consumer validator exists; production live fail-closed because the durable object is not served | Implementation (WP-0007-T04 + WP-0008-T02) | | Published PEP stance equals shipped behaviour, stance application recorded | Map published; prod fail-closed matches; records are `DecisionError`, not named stance fields | Implementation (WP-0008-T01) | | Evidence to `audit-core` under §9.6 | Local JSONL + best-effort State Hub; attributive; completeness not claimed | Implementation (WP-0008-T03) | | SSH-CA engine API | Not implemented; ops-warden still writes OpenBao | Proposed surface (WP-0008-T04) | | Secret-use evidence API | `route` / `audit` summarize local JSONL | Proposed surface (WP-0008-T05) | | No standing agent credential | Bootstrap token file still accepted; KeyCape scaffold unwired to OpenBao | Hardening (WP-0007-T05 / WP-0008-T06) | | Service API | CLI only | Deferred until WP-0007 exit criteria | | Every allow has a lifetime | Delivery sessions self-revoke; decision TTL waits on durable authorization | Partial | | Doctrine as claims | Catalog/policies are local YAML | Later; do not compile outcomes here | `SCOPE.md` remains the implemented-capability ledger. Volatile workplan status stays out of it. The new durable additions are the layer table, the updated system boundary, and the explicit not-implemented layer-model surfaces. ## INTENT vs implementation The strongest implemented slice is unchanged: ```text catalog -> approval-status or fail-closed prod gate -> guarded plan -> policy/AppRole apply -> bounded presence/capability verification -> CLI-local exec/handoff -> non-secret route/evidence pointer ``` That slice is a Lifecycle engine **shape**. It is not yet a conforming PEP. ### Scorecard against the accepted model | Rule | Assessment | Evidence | Material gap | | --- | --- | --- | --- | | §3.3 Lifecycle | Aligned in shape | OpenBao isolated in `openbao.py`; catalog/plan/delivery/lifecycle are the API | Service API absent; CLI is the only surface | | §6 one decision point | Partial, fail-closed | `authorization.py` validates a supplied object and does not evaluate policy. Production live commands refuse without a durable ActionAuthorization. Build/test still accept State Hub status or a local fixture | Local/hub status is not an access-engine decision record. Risk of compiled early decision if fixtures return for production | | §6.1 compiled data | Watch | Catalog admission and publication-scope policy clamp lanes; they must not become the allow | Keep catalog descriptive; effects stay in the decision | | §6.4 PEP obligation 1 | Partial | Privileged handlers record attempt/terminal evidence; production refusal is a `DecisionError` | Stance application is not recorded as named fields (stage, failure mode, decision id present only where rendered) | | §6.4 PEP obligation 2 | Aligned as declared | No verdict cache; `verdict_caching: none` | Must remain none when ActionAuthorization is live | | §6.4 PEP obligation 3 | Published, not yet loaded | `pep-stance.yaml` is total over build/test/prod/unknown; tests pin prod fail-closed to `_require_lane_approval` | Code still hardcodes the gate rather than loading the map. Build/test fail-open is relative to access-engine, not a manufactured allow — that residue is itself a gap | | §6.4 PEP obligation 4 | Attributive | Local JSONL + hub receipts; OpenBao remains backend audit | Completeness not claimed (correct). No `audit-core` emit | | §9.6 load-bearing vs attributive | Undeclared in code | `layer.yaml` classifies today's trail as attributive | Destroy, revoke, and dual-control provision will become load-bearing once they are production-live. They need atomic local outbox + cadence/heartbeat **before** any control branches on them | | §9.7 lifetime | Partial | AppRole sessions self-revoke; ActionAuthorization has `expires_at` in the consumer schema | Production never reaches the lifetime because live prod is disabled. Bootstrap tokens remain standing credentials | | §20.2 credentials after a decision | Principle aligned; production blocked | Fail-closed is the honest residue while the PDP object is unserved | Do not reopen production on hub status | | Staff must not touch OpenBao | External | ops-warden still has the SSH-CA write gap with intended owner here | Engine surface not shipped; do not take the Staff lane | | Agent rule 1 (no standing credential) | Not met | `--bootstrap-token-file` and `BAO_TOKEN` are the live auth path | KeyCape scaffold exists and is deliberately unwired | | Observation / actuation | Correctly not claimed | Companion §10: nothing is observed in production; nothing can be contained automatically | Do not plan as if either existed | ### Overlap with active workplans `SECRETS-WP-0007` already owns CLI hardening that the 2026-08-23 assessment called P0/P1: merge-safe provision (done), lifecycle split (in progress), exact-action authorization (in progress), session self-revocation (in progress), verification/evidence (in progress). Those tasks stay there. What the layer model **adds**, and what `SECRETS-WP-0008` is for: 1. Bind the published PEP stance to shipped behaviour and record stance application by name. 2. Treat the durable ActionAuthorization as an **access-engine decision record** under §6.4, not as a State Hub status check, once WP-0007-T04's endpoint exists. 3. Classify evidence and emit it to `audit-core`. 4. Answer the two proposed surfaces (SSH-CA API, secret-use evidence) in this repository's own contract. 5. Retire standing engine credentials as a layer obligation, not only as bootstrap hygiene. Do not start service mode, runtime tenancy, or a second custody backend from this review. Companion §10 still holds: nothing is observed in production, and nothing can be contained automatically. ## Recommended sequence 1. Keep `SECRETS-WP-0007` as the CLI-hardening track. Do not reopen live production on coarse hub status. 2. Land `SECRETS-WP-0008-T01` — load `pep-stance.yaml` as the source of the fail-closed gate and record stance application fields. 3. When the durable authorization object is served, consume it as a decision record (`WP-0008-T02` / `WP-0007-T04`) with digest+lifetime replay rules. 4. Classify evidence; emit load-bearing classes to `audit-core` with a local outbox; declare cadence or heartbeat. 5. Publish the SSH-CA engine contract with ops-warden before writing a client replacement. Keep their Staff PEP. 6. Publish the secret-use evidence contract with kings-guard. `audit` is not that contract. 7. Wire service identity only after the platform-owned OpenBao JWT role exists. Bootstrap remains break-glass. ## Conclusion `INTENT.md` now declares Engine / Lifecycle in this repository's own voice and accepts the two proposed surfaces without taking Staff work. `SCOPE.md` is honest about the CLI MVP and the new not-implemented obligations. The implementation is a Lifecycle engine in shape and a partial PEP in behaviour: production fail-closed is the correct residue, build/test still run on a pre-decision-record approval path, and evidence is attributive local notes rather than `audit-core`. The repository should not advertise itself as a service API, a second PDP, a custody backend, an SSH issuer, or an observation system. Follow-on work is `SECRETS-WP-0008`.