--- id: USER-WP-0024 type: workplan title: "Security layer model conformance for Engine/PIP" domain: communication repo: user-engine status: active owner: grok topic_slug: netkingdom created: "2026-08-29" updated: "2026-08-29" depends_on: - USER-WP-0023 --- # USER-WP-0024 — security layer model conformance Adopt the accepted NetKingdom Security Layer Model (`net-kingdom/canon/standards/security-layer-model_v0.7.md`, companion `net-kingdom/SECURITY-COMPANION.md`) as this repository's own declaration and close the implementation gaps that leave a PEP-shaped Engine short of the standard. Assessment: `history/2026-08-29-security-layer-scope-intent-assessment.md`. Working references: `ops-warden/layer.yaml` and `kings-guard/layer.yaml` (no Tooling contacts). Credential and lane questions go to `ops-warden`, not this workplan. ## T01 — Declare Engine/PIP in own voice ```task id: USER-WP-0024-T01 status: done priority: high ``` Replace the gate-house review note in `INTENT.md` with this repository's own declaration: frontmatter `layer: Engine`, `role: PIP`, plus prose that subject context is a claim, never a decision, and that protected mutations are PEP-shaped without changing layer. Restate `SCOPE.md` from that INTENT. Record the scope-vs-intent-vs-implementation assessment under `history/`. Done 2026-08-29. Closes the declaration half of `USER-IN-0001`. Does not by itself make the runtime conforming. ## T02 — Machine-readable layer declaration and check ```task id: USER-WP-0024-T02 status: todo priority: high ``` Add `layer.yaml` (or equivalent) naming Engine/PIP, empty catalogued Tooling contacts, non-Tooling / own-store clients (PostgreSQL modeled concept, State Hub, env-injected secrets, flex-auth Engine API, OIDC claim input), and the path of the PEP stance map. Adapt `kings-guard/scripts/check_layer_conformance.py` and a unit test so an undeclared OpenBao, Vault, LDAP, or cluster client fails the commit that introduces it. Do not add a Tooling client to have something to declare. **Done when:** `layer.yaml` is the machine-readable declaration, the checker exits 0 on the current tree, and a test covers the empty Tooling-contact claim. ## T03 — PEP obligations on the production path ```task id: USER-WP-0024-T03 status: todo priority: high ``` Ship the four §6.4 obligations for this PEP-shaped Engine: 1. Publish `pep-stance.yaml` (total, no implicit default). Production remains fail-closed, including unknown. A test asserts the file equals `FlexAuthHTTPAdapter` behaviour. 2. On engine-unavailable DENY, record stance application (scope, failure mode, outcome). `decision_id` is present only when flex-auth rendered a decision. Stop minting a local id via `AuthorizationDecision`'s default factory on that path. 3. Give `AuthorizationDecision` an explicit lifetime (TTL or session/obligation binding). Do not add a verdict cache. 4. Confine `LocalAuthorizationCheckPort` to tests and standalone fixtures. Production `create_application()` must be unable to construct a default-allow adapter. **Done when:** the published map matches shipped fail-closed behaviour, unavailable DENY audits carry no engine decision id, allows carry a lifetime, and the local port cannot enter the production runtime assembly. ## T04 — Evidence bound and cadence ```task id: USER-WP-0024-T04 status: todo priority: medium ``` Classify local audit and outbox events as load-bearing or attributive. Keep mutation+audit+outbox atomic in the store transaction (already true). For denials and membership/account revocations — low-volume load-bearing classes — declare a heartbeat or reconciliation, not a rate. Update `docs/evidence-gap-examples.md` and operability copy so the trail is never described as complete, and so absence of a record is not read as non-occurrence. **Done when:** the classification is in-repo, the heartbeat or reconciliation form is named, and docs use the sound evidence sentences. ## T05 — Access-control facts remain claims ```task id: USER-WP-0024-T05 status: todo priority: medium ``` Prove under statute §6.1 that hats, access profiles, and `AccessControlFact` exports cannot be mistaken for an authorization decision. Add a test that selection and export never return allow/deny. Document the consumer contract: compiling those facts into a local decision is an early decision and is forbidden. **Done when:** a test and the hats/boundary docs state the claim contract, and no user-engine API on that path exposes an effect. ## T06 — Close the intake and request the stance-map row ```task id: USER-WP-0024-T06 status: done priority: medium ``` Mark `USER-IN-0001` answered: Engine/PIP, not contested. Message `gate-house` with the declaration path, the PEP-shaped finding for statute §13.1 (user-engine is a third PEP-shaped consumer; the register currently has one published row), and a pointer at this workplan for the runtime follow-through. Done 2026-08-29. Intake marked answered in `intakes/intakes.md`. Message `c014d12a-fe7a-4a90-ba73-03a5ac3e7f73` to `gate-house` carries the declaration, the non-contest, and the §13.1 request (row to be added when `pep-stance.yaml` ships in T03).