feat: finish ZONE-WP-0003 Engine/PIP freeze and claim mapping
Declare the layer in layer.yaml, check it against INTENT.md, and fail make check on a new Tooling client or HTTP decision surface. Record the six statute §10 artifacts for the 2026-08-23 cut, name access-engine on the README, and offer a non-schema PIP field mapping to Taxonomy. Assistant: grok Assistant-Session: 01a04ceb-0745-7ae1-9e26-0d10e5d52b8b
This commit is contained in:
parent
e9d0fecede
commit
acfd93fc86
11 changed files with 682 additions and 35 deletions
|
|
@ -34,7 +34,8 @@ companion: net-kingdom/SECURITY-COMPANION.md
|
||||||
> surface, or stance compiled into membership would each be a layer change,
|
> surface, or stance compiled into membership would each be a layer change,
|
||||||
> and a layer change needs the six artifacts in statute §10, including a
|
> and a layer change needs the six artifacts in statute §10, including a
|
||||||
> permission freeze. The 2026-08-23 cut already happened; it does not reopen
|
> permission freeze. The 2026-08-23 cut already happened; it does not reopen
|
||||||
> by practice.
|
> by practice. The six statute §10 artifacts are gathered in
|
||||||
|
> `history/2026-08-29-layer-change-artifacts.md`.
|
||||||
>
|
>
|
||||||
> **`access-engine` is the only PDP.** It is the ruled name for the repository
|
> **`access-engine` is the only PDP.** It is the ruled name for the repository
|
||||||
> currently called `flex-auth`. This file's original §5 — *"flex-auth is the
|
> currently called `flex-auth`. This file's original §5 — *"flex-auth is the
|
||||||
|
|
|
||||||
7
Makefile
7
Makefile
|
|
@ -1,10 +1,13 @@
|
||||||
.PHONY: canon-lineage check exception-fixtures reference-fixtures test
|
.PHONY: canon-lineage check exception-fixtures layer-conformance reference-fixtures test
|
||||||
|
|
||||||
check: test reference-fixtures exception-fixtures
|
check: test reference-fixtures exception-fixtures layer-conformance
|
||||||
|
|
||||||
test:
|
test:
|
||||||
PYTHONDONTWRITEBYTECODE=1 python3 -m unittest discover -s tests -v
|
PYTHONDONTWRITEBYTECODE=1 python3 -m unittest discover -s tests -v
|
||||||
|
|
||||||
|
layer-conformance:
|
||||||
|
PYTHONDONTWRITEBYTECODE=1 python3 tools/check_layer_conformance.py
|
||||||
|
|
||||||
reference-fixtures:
|
reference-fixtures:
|
||||||
PYTHONDONTWRITEBYTECODE=1 python3 tools/resolve_zones.py --manifest fixtures/manifests/reference.yaml --control-profile profiles/netkingdom-build-v0.1.yaml >/dev/null
|
PYTHONDONTWRITEBYTECODE=1 python3 tools/resolve_zones.py --manifest fixtures/manifests/reference.yaml --control-profile profiles/netkingdom-build-v0.1.yaml >/dev/null
|
||||||
|
|
||||||
|
|
|
||||||
16
README.md
16
README.md
|
|
@ -1,13 +1,15 @@
|
||||||
# zone-engine
|
# zone-engine
|
||||||
|
|
||||||
Offline reference conformance for NetKingdom **security zones**. This repository
|
Engine-layer **PIP** for NetKingdom **security-zone** identity and membership,
|
||||||
validates workload membership and admission, projects only explicit
|
retained as offline reference conformance. This repository validates workload
|
||||||
owner-versioned control profiles, checks time-boxed exception fixtures, and
|
membership and admission, projects only explicit owner-versioned control
|
||||||
verifies the lineage of the canonical standard.
|
profiles, checks time-boxed exception fixtures, and verifies the lineage of
|
||||||
|
the canonical standard.
|
||||||
|
|
||||||
It is not a service or policy decision point. Canon is published by
|
It is not a live engine, not a PEP, and not a policy decision point. Canon is
|
||||||
`net-kingdom`; flex-auth and each enforcement-point owner retain live policy
|
published by `net-kingdom`. `access-engine` (currently `flex-auth`) is the
|
||||||
authority.
|
only PDP; each enforcement-point owner retains live policy and failure-mode
|
||||||
|
authority. Layer declaration: `INTENT.md` frontmatter and `layer.yaml`.
|
||||||
|
|
||||||
## Checks
|
## Checks
|
||||||
|
|
||||||
|
|
|
||||||
22
SCOPE.md
22
SCOPE.md
|
|
@ -28,10 +28,11 @@ Declared in `INTENT.md` frontmatter, in this repository's own voice:
|
||||||
| Tooling contacts | none |
|
| Tooling contacts | none |
|
||||||
| Conformance | conforming for Tooling contact; the live Engine API is not a missing capability this repository currently owes |
|
| Conformance | conforming for Tooling contact; the live Engine API is not a missing capability this repository currently owes |
|
||||||
|
|
||||||
The machine-readable `layer.yaml` form and a conformance check that fails a
|
The machine-readable declaration is `layer.yaml`. `tools/check_layer_conformance.py`
|
||||||
new Tooling client or a new decision surface are not yet evidenced here.
|
fails if that file disagrees with `INTENT.md` frontmatter, if a Tooling-layer
|
||||||
Until they are, the declaration is the `INTENT.md` frontmatter and the prose
|
client appears under `tools/`, or if an HTTP authorization decision surface
|
||||||
in that file.
|
appears. The six statute §10 artifacts for the already-completed layer cut
|
||||||
|
are `history/2026-08-29-layer-change-artifacts.md`.
|
||||||
|
|
||||||
`access-engine` (currently `flex-auth`) is the only PDP. Zone stance and
|
`access-engine` (currently `flex-auth`) is the only PDP. Zone stance and
|
||||||
failure mode remain owner policy and PEP configuration. This repository
|
failure mode remain owner policy and PEP configuration. This repository
|
||||||
|
|
@ -82,8 +83,8 @@ This repository provides:
|
||||||
- an offline exception checker with an explicit evaluation instant, covering
|
- an offline exception checker with an explicit evaluation instant, covering
|
||||||
grant authority, maximum duration, exclusive expiry, overlap, renewal,
|
grant authority, maximum duration, exclusive expiry, overlap, renewal,
|
||||||
wildcard rejection, and durable-authority bounds; and
|
wildcard rejection, and durable-authority bounds; and
|
||||||
- reusable manifests, profiles, exception fixtures, evidence, and 29 unit
|
- reusable manifests, profiles, exception fixtures, evidence, and unit
|
||||||
tests.
|
tests covering resolver, exceptions, lineage, and layer conformance.
|
||||||
|
|
||||||
The resolver consumes already-located declarations and already-resolved
|
The resolver consumes already-located declarations and already-resolved
|
||||||
workload-reference projections. It does not discover a fleet, repair an
|
workload-reference projections. It does not discover a fleet, repair an
|
||||||
|
|
@ -91,9 +92,10 @@ ambiguous join, read a live clock, or publish a consumer registry. Its profile
|
||||||
fixture records owner-approved v0.1 behavior; only the referenced owner policy
|
fixture records owner-approved v0.1 behavior; only the referenced owner policy
|
||||||
and PEP configuration can change a live effect.
|
and PEP configuration can change a live effect.
|
||||||
|
|
||||||
The resolver output is a reference membership/admission record. It is not yet
|
The resolver output is a reference membership/admission record. It is not a
|
||||||
a statute §17 request-claim. Taxonomy owns that schema and has not published
|
statute §17 request-claim. Taxonomy owns that schema and has not published
|
||||||
it. This repository must not ship a competing dialect.
|
it. The field mapping offered to Taxonomy is `docs/pip-claim-boundary.md`.
|
||||||
|
This repository must not ship a competing dialect.
|
||||||
|
|
||||||
## Authority boundary
|
## Authority boundary
|
||||||
|
|
||||||
|
|
@ -140,6 +142,8 @@ decision point.
|
||||||
|
|
||||||
- Reproducing or extending v0.1 conformance fixtures.
|
- Reproducing or extending v0.1 conformance fixtures.
|
||||||
- Checking direct declarations or explicit Repo Manager projections offline.
|
- Checking direct declarations or explicit Repo Manager projections offline.
|
||||||
|
- Mapping those membership facts onto a future request-claim
|
||||||
|
(`docs/pip-claim-boundary.md`) without shipping a schema.
|
||||||
- Verifying a versioned owner profile is total and fully attributed.
|
- Verifying a versioned owner profile is total and fully attributed.
|
||||||
- Testing an owner exception implementation against the lifecycle boundaries.
|
- Testing an owner exception implementation against the lifecycle boundaries.
|
||||||
- Reviewing a net-kingdom canon lifecycle/content change, including the
|
- Reviewing a net-kingdom canon lifecycle/content change, including the
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
| --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- |
|
||||||
| workplan | ZONE-WP-0001 | finished | — | workplans/ZONE-WP-0001-security-zone-model.md |
|
| workplan | ZONE-WP-0001 | finished | — | workplans/ZONE-WP-0001-security-zone-model.md |
|
||||||
| workplan | ZONE-WP-0002 | finished | — | workplans/ZONE-WP-0002-reference-contract-hardening-and-retirement.md |
|
| workplan | ZONE-WP-0002 | finished | — | workplans/ZONE-WP-0002-reference-contract-hardening-and-retirement.md |
|
||||||
| workplan | ZONE-WP-0003 | ready | — | workplans/ZONE-WP-0003-security-layer-model-alignment.md |
|
| workplan | ZONE-WP-0003 | finished | — | workplans/ZONE-WP-0003-security-layer-model-alignment.md |
|
||||||
| task | ZONE-WP-0001-T01 | done | — | workplans/ZONE-WP-0001-security-zone-model.md |
|
| task | ZONE-WP-0001-T01 | done | — | workplans/ZONE-WP-0001-security-zone-model.md |
|
||||||
| task | ZONE-WP-0001-T02 | done | — | workplans/ZONE-WP-0001-security-zone-model.md |
|
| task | ZONE-WP-0001-T02 | done | — | workplans/ZONE-WP-0001-security-zone-model.md |
|
||||||
| task | ZONE-WP-0001-T03 | done | — | workplans/ZONE-WP-0001-security-zone-model.md |
|
| task | ZONE-WP-0001-T03 | done | — | workplans/ZONE-WP-0001-security-zone-model.md |
|
||||||
|
|
@ -25,9 +25,9 @@
|
||||||
| task | ZONE-WP-0002-T05 | done | — | workplans/ZONE-WP-0002-reference-contract-hardening-and-retirement.md |
|
| task | ZONE-WP-0002-T05 | done | — | workplans/ZONE-WP-0002-reference-contract-hardening-and-retirement.md |
|
||||||
| task | ZONE-WP-0002-T06 | done | — | workplans/ZONE-WP-0002-reference-contract-hardening-and-retirement.md |
|
| task | ZONE-WP-0002-T06 | done | — | workplans/ZONE-WP-0002-reference-contract-hardening-and-retirement.md |
|
||||||
| task | ZONE-WP-0002-T07 | done | — | workplans/ZONE-WP-0002-reference-contract-hardening-and-retirement.md |
|
| task | ZONE-WP-0002-T07 | done | — | workplans/ZONE-WP-0002-reference-contract-hardening-and-retirement.md |
|
||||||
| task | ZONE-WP-0003-T01 | todo | — | workplans/ZONE-WP-0003-security-layer-model-alignment.md |
|
| task | ZONE-WP-0003-T01 | done | — | workplans/ZONE-WP-0003-security-layer-model-alignment.md |
|
||||||
| task | ZONE-WP-0003-T02 | done | — | workplans/ZONE-WP-0003-security-layer-model-alignment.md |
|
| task | ZONE-WP-0003-T02 | done | — | workplans/ZONE-WP-0003-security-layer-model-alignment.md |
|
||||||
| task | ZONE-WP-0003-T03 | todo | — | workplans/ZONE-WP-0003-security-layer-model-alignment.md |
|
| task | ZONE-WP-0003-T03 | done | — | workplans/ZONE-WP-0003-security-layer-model-alignment.md |
|
||||||
| task | ZONE-WP-0003-T04 | todo | — | workplans/ZONE-WP-0003-security-layer-model-alignment.md |
|
| task | ZONE-WP-0003-T04 | done | — | workplans/ZONE-WP-0003-security-layer-model-alignment.md |
|
||||||
| task | ZONE-WP-0003-T05 | todo | — | workplans/ZONE-WP-0003-security-layer-model-alignment.md |
|
| task | ZONE-WP-0003-T05 | done | — | workplans/ZONE-WP-0003-security-layer-model-alignment.md |
|
||||||
| intake | ZONE-IN-0001 | closed | — | intakes/intakes.md |
|
| intake | ZONE-IN-0001 | closed | — | intakes/intakes.md |
|
||||||
|
|
|
||||||
72
docs/pip-claim-boundary.md
Normal file
72
docs/pip-claim-boundary.md
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
# PIP claim boundary — zone identity and membership
|
||||||
|
|
||||||
|
This note maps the facts this Engine/PIP already emits onto the facts a
|
||||||
|
future request-claim must carry. It is **not** a schema, not a wire format,
|
||||||
|
and not estate canon.
|
||||||
|
|
||||||
|
Statute §17 assigns the request-claim schema to Taxonomy and records that
|
||||||
|
ownership as proposed, not assigned. Statute §18 says zone stance enters a
|
||||||
|
decision as a **claim on the request or a rule in a versioned
|
||||||
|
`access-engine` policy package**, never as compiled registry content.
|
||||||
|
Inventing a competing dialect here is the drift §17 exists to prevent.
|
||||||
|
|
||||||
|
Offered to `gate-house` / `net-kingdom` (Taxonomy publication) and to
|
||||||
|
`access-engine` (currently `flex-auth`, the consumer of the claim). Assent
|
||||||
|
is not required to keep the 2026-08-23 freeze.
|
||||||
|
|
||||||
|
## Facts this PIP owns today
|
||||||
|
|
||||||
|
Emitted by `tools/resolve_zones.py` as a reference membership/admission
|
||||||
|
record, given already-located declarations and already-resolved Repo
|
||||||
|
Manager projections:
|
||||||
|
|
||||||
|
| Field | Meaning |
|
||||||
|
| --- | --- |
|
||||||
|
| `identity_bindings` | Authoritative workload identity bindings |
|
||||||
|
| `workload_ref` | Explicit workload reference (`rapp_id`, name, deployable, applicability) |
|
||||||
|
| `declared_zone` | Responsible party's declared membership |
|
||||||
|
| `effective_zone` | Admitted zone, or `unknown` / none |
|
||||||
|
| `admission` | `satisfied`, `unsatisfied`, `unknown`, or `not-applicable` |
|
||||||
|
| `admission_reason` | Why that result, without inference |
|
||||||
|
| `membership_revision` | Digest bound to identity, membership, workload ref, and source revision |
|
||||||
|
| `source` | Declaration path or projection source |
|
||||||
|
| `source_revision` | Caller-supplied source revision; absence yields no source-bound digest |
|
||||||
|
| `guarantees` | What the record actually promises (non-inference, source binding, …) |
|
||||||
|
|
||||||
|
Optional control-profile projection (`policy_owner`, `pep_owner`,
|
||||||
|
`policy_ref`, stance, failure mode) is **not** a PIP fact. It is owner data
|
||||||
|
copied through for evidence, and only the referenced owner policy or PEP
|
||||||
|
configuration may change a live effect.
|
||||||
|
|
||||||
|
Input `zones.reviewed` / `zones.review_due` are validated and are not
|
||||||
|
currently copied onto the output record. Freshness the resolver *does*
|
||||||
|
bind is `source_revision` via `membership_revision`.
|
||||||
|
|
||||||
|
## Mapping onto a future request-claim
|
||||||
|
|
||||||
|
Until Taxonomy publishes the schema, this is the contribution, not a type:
|
||||||
|
|
||||||
|
| Claim slot (statute §17) | This PIP's field | Must not carry |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| Issuer | this repository, plus `source` / `source_revision` | a second PDP identity |
|
||||||
|
| Subject | `identity_bindings` and `workload_ref` | path, repo, reef, actor, or lane as a substitute subject |
|
||||||
|
| Zone membership | `declared_zone`, `effective_zone`, `admission`, `admission_reason` | stance, failure mode, allow/deny |
|
||||||
|
| Freshness | `source_revision` and `membership_revision` | an implicit "current" with no revision |
|
||||||
|
| Effect of the zone | — | **not a PIP field**; `access-engine` policy package or a versioned rule (statute §18) |
|
||||||
|
|
||||||
|
A decision that turned on a zone must name the policy-package version that
|
||||||
|
read it. Membership may be compiled into the registry `access-engine`
|
||||||
|
already loads only as a **fact**. Compiled data that determines an outcome
|
||||||
|
is still deciding (statute §6.1).
|
||||||
|
|
||||||
|
## Forbidden
|
||||||
|
|
||||||
|
- Shipping a zone-engine claim JSON Schema, protobuf, or `/claims` endpoint.
|
||||||
|
- Encoding stance or failure mode as if they were membership.
|
||||||
|
- Compiling these facts into registry content that changes allow/deny
|
||||||
|
without a policy-package revision.
|
||||||
|
- Treating a missing claim as permission. `unknown` and `not-applicable`
|
||||||
|
stay distinct; absence is not `z0`.
|
||||||
|
|
||||||
|
The freeze in `history/2026-08-29-layer-change-artifacts.md` holds while
|
||||||
|
this mapping waits on Taxonomy.
|
||||||
97
history/2026-08-29-layer-change-artifacts.md
Normal file
97
history/2026-08-29-layer-change-artifacts.md
Normal file
|
|
@ -0,0 +1,97 @@
|
||||||
|
---
|
||||||
|
id: ZONE-LAYER-CHANGE-2026-08-23
|
||||||
|
type: layer-change-record
|
||||||
|
title: "Statute §10 artifacts for the 2026-08-23 zone-engine layer cut"
|
||||||
|
status: accepted
|
||||||
|
recorded: "2026-08-29"
|
||||||
|
standard: net-kingdom/canon/standards/security-layer-model_v0.7.md
|
||||||
|
---
|
||||||
|
|
||||||
|
# Statute §10 artifacts — the 2026-08-23 layer cut
|
||||||
|
|
||||||
|
Statute §10 writes the layer-change procedure from this repository's case:
|
||||||
|
the runtime hypothesis was falsified, and the Engine remained as offline
|
||||||
|
reference conformance. The six artifacts are gathered here so a reviewer
|
||||||
|
does not have to reconstruct them from workplan history.
|
||||||
|
|
||||||
|
A later live API, decision surface, or compiled stance would be a **new**
|
||||||
|
cut and would need its own six artifacts plus assent from every repository
|
||||||
|
whose boundary moves. This record does not authorize that.
|
||||||
|
|
||||||
|
## 1. Before / after `INTENT.md`
|
||||||
|
|
||||||
|
| | Before (through 2026-08-23) | After (2026-08-29) |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| Desired sentence | Not yet sayable | Sayable; standard adopted |
|
||||||
|
| Runtime | Hypothesis under test | Falsified; cheaper answer taken |
|
||||||
|
| Layer | Unstated in this repository's voice | Engine, role PIP |
|
||||||
|
| Surface | Assumed an engine might be needed | Offline reference conformance |
|
||||||
|
| PDP line | `flex-auth` is the only decision point | Same ruling; ruled name `access-engine` (currently `flex-auth`) |
|
||||||
|
|
||||||
|
Before-state: `history/2026-08-23-retain-reference-decision.md`,
|
||||||
|
`history/2026-08-23-scope-against-intent.md`, and the 2026-08-23 body of
|
||||||
|
`INTENT.md` retained as design history.
|
||||||
|
|
||||||
|
After-state: `INTENT.md` frontmatter (`layer: Engine`, `role: PIP`) and the
|
||||||
|
2026-08-29 declaration prose. Machine-readable twin: `layer.yaml`.
|
||||||
|
|
||||||
|
## 2. Client inventory
|
||||||
|
|
||||||
|
| Contact | Before | After |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| Tooling-layer clients (`OpenBao`, `key-cape`, datastore) | none | none |
|
||||||
|
| HTTP authorization decision surface | none | none |
|
||||||
|
| Live Engine API | none | none |
|
||||||
|
| Python tools | offline resolver, exception checker, lineage checker | same |
|
||||||
|
| Non-Tooling | State Hub work records via CLI / agent sessions | same; recorded in `layer.yaml` |
|
||||||
|
|
||||||
|
There was no Tooling client to retire and none to add. `tools/` imports the
|
||||||
|
standard library and PyYAML only.
|
||||||
|
|
||||||
|
## 3. Gap inventory
|
||||||
|
|
||||||
|
| Kind | Before | After |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| §5.3 declared Tooling contacts | none | none |
|
||||||
|
| Unowned capabilities this repository currently owes | none | none |
|
||||||
|
| Live Engine API | not owed; catalog records the offline form | still not owed |
|
||||||
|
|
||||||
|
A missing live API is not a §5.3 gap. Closing it in place would reverse the
|
||||||
|
cut this record describes.
|
||||||
|
|
||||||
|
## 4. Assent list
|
||||||
|
|
||||||
|
No new boundary moved on 2026-08-29. The cut of 2026-08-23 was already
|
||||||
|
assented in practice by the two consuming owners:
|
||||||
|
|
||||||
|
| Repository | Evidence | Boundary |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| flex-auth (`access-engine`) | `FLEX-WP-0016` adoption; profile owner in `profiles/netkingdom-build-v0.1.yaml`; review of ZONE-WP-0001 | remains the only PDP; stance stays in its policy package |
|
||||||
|
| ops-warden | retired `policy.enabled`; PEP failure modes; adoption evidence 2026-08-22/23 | consumes membership; owns unreachable-engine stance |
|
||||||
|
| net-kingdom | published `security-zones_v0.1` (still `proposed`) | canon publication |
|
||||||
|
| gate-house | §4 catalog row names the offline disposition; `ZONE-IN-0001` requested the own-voice declaration | layer model |
|
||||||
|
|
||||||
|
A future live surface would require fresh assent from at least
|
||||||
|
`access-engine` and `ops-warden`.
|
||||||
|
|
||||||
|
## 5. State-migration decision
|
||||||
|
|
||||||
|
`history/2026-08-23-retain-reference-decision.md`. There was no live state
|
||||||
|
to migrate: no API, no store, no consumer registry. Consumers already read
|
||||||
|
declarations in owning repos and policy in owner packages. Retention is of
|
||||||
|
fixtures, lineage, and offline tools.
|
||||||
|
|
||||||
|
## 6. Permission freeze
|
||||||
|
|
||||||
|
Until a later cut carries its own six artifacts:
|
||||||
|
|
||||||
|
- no live API, daemon, database, controller, scheduler, or reload path;
|
||||||
|
- no authorization decision surface and no cached verdict;
|
||||||
|
- no stance compiled into membership, and no local profile change that
|
||||||
|
alters a live effect;
|
||||||
|
- no PEP, and no unreachable-engine stance map published from this
|
||||||
|
repository;
|
||||||
|
- no Tooling-layer client.
|
||||||
|
|
||||||
|
`tools/check_layer_conformance.py` is the freeze's check: a new OpenBao
|
||||||
|
import or an `/authorize` helper fails `make check`.
|
||||||
65
layer.yaml
Normal file
65
layer.yaml
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
# zone-engine — NetKingdom security layer declaration
|
||||||
|
#
|
||||||
|
# Framework: net-kingdom/canon/standards/security-layer-model_v0.7.md
|
||||||
|
# Companion: net-kingdom/SECURITY-COMPANION.md v0.2
|
||||||
|
# Declaration: INTENT.md (this repository's own voice, §11)
|
||||||
|
# Validate: python3 tools/check_layer_conformance.py
|
||||||
|
#
|
||||||
|
# §11 requires a machine-readable form because prose cannot distinguish a
|
||||||
|
# declaration from a transcribed review. Shape adapted from kings-guard's
|
||||||
|
# no-contact declaration, offered estate-wide under §11.
|
||||||
|
#
|
||||||
|
# Catalogued as Engine / PIP for zone identity and membership, offline
|
||||||
|
# reference conformance per the 2026-08-23 disposition. There is no
|
||||||
|
# Tooling contact, no PEP, and no authorization decision surface.
|
||||||
|
|
||||||
|
schema_version: "0.1"
|
||||||
|
framework: netkingdom-security-layer-model
|
||||||
|
standard_version: "0.7"
|
||||||
|
repository: zone-engine
|
||||||
|
layer: engine
|
||||||
|
role: pip
|
||||||
|
declared_by: INTENT.md
|
||||||
|
declared_at: "2026-08-29"
|
||||||
|
|
||||||
|
# §4 catalog entry, transcribed so drift is visible. The standard is
|
||||||
|
# authoritative for the row; this records what we understand ourselves
|
||||||
|
# to have been assigned.
|
||||||
|
catalog_entry:
|
||||||
|
owns:
|
||||||
|
- zone identity and membership
|
||||||
|
form: offline reference conformance (2026-08-23 disposition)
|
||||||
|
pep_shaped: false
|
||||||
|
|
||||||
|
# §5 / §11: every direct contact with a Tooling-layer system (a §4 Tooling
|
||||||
|
# row), one entry each. Empty is a claim. tools/check_layer_conformance.py
|
||||||
|
# fails if a Tooling client or a decision surface appears under tools/.
|
||||||
|
tooling_contacts: []
|
||||||
|
|
||||||
|
# No pep_stance path. This repository causes no protected side effect.
|
||||||
|
|
||||||
|
# §11 requires non-Tooling clients to be recorded so the check is total.
|
||||||
|
# There is no library client in this repository. Work-record writes happen
|
||||||
|
# through the State Hub CLI / agent sessions, not through tools/.
|
||||||
|
non_tooling_clients:
|
||||||
|
- id: state-hub-work-records
|
||||||
|
target: state-hub
|
||||||
|
layer: not-catalogued
|
||||||
|
operation: "HTTP via statehub CLI / agent sessions for work records and progress events"
|
||||||
|
write: true
|
||||||
|
in_tree: false
|
||||||
|
note: >-
|
||||||
|
Outside §5 by the v0.5 scope rule: "Tooling-layer system" means a §4
|
||||||
|
Tooling row, and state-hub is not one. Recorded, not policed. Carries no
|
||||||
|
security authority and no secret payload. No import of a State Hub
|
||||||
|
client exists under tools/.
|
||||||
|
|
||||||
|
# A live Engine API is not an unowned capability this repository currently
|
||||||
|
# owes. The catalog records the offline form. Growing one would be a §10
|
||||||
|
# layer change, not a gap to close in place.
|
||||||
|
unowned_capabilities: []
|
||||||
|
|
||||||
|
declared_shapes:
|
||||||
|
"5.1": []
|
||||||
|
"5.2": []
|
||||||
|
"5.3": []
|
||||||
106
tests/test_layer_conformance.py
Normal file
106
tests/test_layer_conformance.py
Normal file
|
|
@ -0,0 +1,106 @@
|
||||||
|
from pathlib import Path
|
||||||
|
from tempfile import TemporaryDirectory
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
from tools import check_layer_conformance as layer
|
||||||
|
|
||||||
|
|
||||||
|
INTENT = """---
|
||||||
|
layer: Engine
|
||||||
|
role: PIP
|
||||||
|
standard: netkingdom-security-layer-model
|
||||||
|
standard_version: "0.7"
|
||||||
|
---
|
||||||
|
|
||||||
|
# INTENT
|
||||||
|
"""
|
||||||
|
|
||||||
|
DECL = {
|
||||||
|
"layer": "engine",
|
||||||
|
"role": "pip",
|
||||||
|
"repository": "zone-engine",
|
||||||
|
"standard_version": "0.7",
|
||||||
|
"tooling_contacts": [],
|
||||||
|
"unowned_capabilities": [],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _write_tree(root: Path, *, decl=None, intent=None, tools=None) -> None:
|
||||||
|
(root / "layer.yaml").write_text(yaml.safe_dump(decl if decl is not None else DECL))
|
||||||
|
(root / "INTENT.md").write_text(intent if intent is not None else INTENT)
|
||||||
|
tools_dir = root / "tools"
|
||||||
|
tools_dir.mkdir()
|
||||||
|
(tools_dir / "noop.py").write_text("import json\n")
|
||||||
|
if tools:
|
||||||
|
for name, body in tools.items():
|
||||||
|
(tools_dir / name).write_text(body)
|
||||||
|
|
||||||
|
|
||||||
|
class LayerDeclarationTest(unittest.TestCase):
|
||||||
|
def test_declaration_exists_and_matches_intent(self):
|
||||||
|
decl = yaml.safe_load(layer.DECL.read_text())
|
||||||
|
intent = layer.load_intent()
|
||||||
|
self.assertEqual(decl["repository"], "zone-engine")
|
||||||
|
self.assertEqual(decl["layer"], "engine")
|
||||||
|
self.assertEqual(decl["role"], "pip")
|
||||||
|
self.assertEqual(decl["standard_version"], "0.7")
|
||||||
|
self.assertEqual(decl["tooling_contacts"], [])
|
||||||
|
self.assertIsNone(decl.get("pep_stance"))
|
||||||
|
self.assertEqual(intent["layer"].lower(), "engine")
|
||||||
|
self.assertEqual(intent["role"].lower(), "pip")
|
||||||
|
self.assertEqual(layer.check_declaration_agrees(decl, intent), [])
|
||||||
|
|
||||||
|
def test_checker_passes_on_the_real_tree(self):
|
||||||
|
code, errors, _reports = layer.evaluate()
|
||||||
|
self.assertEqual(code, 0, errors)
|
||||||
|
self.assertEqual(errors, [])
|
||||||
|
|
||||||
|
|
||||||
|
class LayerCheckerFailureTest(unittest.TestCase):
|
||||||
|
def test_missing_declaration_is_exit_2(self):
|
||||||
|
with TemporaryDirectory() as directory:
|
||||||
|
root = Path(directory)
|
||||||
|
(root / "INTENT.md").write_text(INTENT)
|
||||||
|
(root / "tools").mkdir()
|
||||||
|
code, errors, _ = layer.evaluate(root=root)
|
||||||
|
self.assertEqual(code, 2)
|
||||||
|
self.assertTrue(any("no declaration" in item for item in errors))
|
||||||
|
|
||||||
|
def test_intent_disagreement_is_exit_2(self):
|
||||||
|
with TemporaryDirectory() as directory:
|
||||||
|
root = Path(directory)
|
||||||
|
_write_tree(root, intent=INTENT.replace("Engine", "Staff").replace("PIP", "null"))
|
||||||
|
code, errors, _ = layer.evaluate(root=root)
|
||||||
|
self.assertEqual(code, 2)
|
||||||
|
self.assertTrue(any("disagrees" in item for item in errors))
|
||||||
|
|
||||||
|
def test_undeclared_tooling_client_is_exit_1(self):
|
||||||
|
with TemporaryDirectory() as directory:
|
||||||
|
root = Path(directory)
|
||||||
|
_write_tree(root, tools={"vault.py": "import hvac\n\nclient = hvac.Client()\n"})
|
||||||
|
code, errors, _ = layer.evaluate(root=root)
|
||||||
|
self.assertEqual(code, 1)
|
||||||
|
self.assertTrue(any("hvac" in item for item in errors))
|
||||||
|
|
||||||
|
def test_http_decision_surface_is_exit_1(self):
|
||||||
|
with TemporaryDirectory() as directory:
|
||||||
|
root = Path(directory)
|
||||||
|
_write_tree(
|
||||||
|
root,
|
||||||
|
tools={
|
||||||
|
"api.py": (
|
||||||
|
"import fastapi\n\n"
|
||||||
|
"app = fastapi.FastAPI()\n\n"
|
||||||
|
"@app.post('/v1/check')\n"
|
||||||
|
"def check():\n"
|
||||||
|
" return {'allow': True}\n"
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
code, errors, _ = layer.evaluate(root=root)
|
||||||
|
self.assertEqual(code, 1)
|
||||||
|
joined = "\n".join(errors)
|
||||||
|
self.assertIn("fastapi", joined)
|
||||||
|
self.assertIn("/v1/check", joined)
|
||||||
293
tools/check_layer_conformance.py
Normal file
293
tools/check_layer_conformance.py
Normal file
|
|
@ -0,0 +1,293 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Check zone-engine against the NetKingdom security layer model (§5, §6, §11).
|
||||||
|
|
||||||
|
Read-only. This repository's position is:
|
||||||
|
|
||||||
|
Engine / PIP for zone identity and membership, offline reference
|
||||||
|
conformance, no Tooling-layer client, no HTTP authorization decision
|
||||||
|
surface, no PEP.
|
||||||
|
|
||||||
|
§11 requires a machine-readable declaration that agrees with INTENT.md
|
||||||
|
frontmatter. This script is what makes that claim checkable: it fails if
|
||||||
|
layer.yaml is missing, disagrees with INTENT.md, or if a Tooling client or
|
||||||
|
decision surface appears under tools/.
|
||||||
|
|
||||||
|
The failure it exists to catch is a *convenience* — a live lookup, an
|
||||||
|
OpenBao client, or an /authorize helper "just for this consumer". That is
|
||||||
|
this repository's original §7 falsifier, now statute §6.
|
||||||
|
|
||||||
|
Review dates are reported, never enforced: a date-triggered failure breaks
|
||||||
|
the build on a calendar day with no code change.
|
||||||
|
|
||||||
|
Exit 0 clean, 1 undeclared contact or decision surface, 2 declaration
|
||||||
|
malformed or in disagreement with INTENT.md.
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import ast
|
||||||
|
import sys
|
||||||
|
from datetime import date
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Any, Iterable, Mapping
|
||||||
|
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
|
TOOLS = ROOT / "tools"
|
||||||
|
DECL = ROOT / "layer.yaml"
|
||||||
|
INTENT = ROOT / "INTENT.md"
|
||||||
|
|
||||||
|
TOOLING_IMPORTS = {
|
||||||
|
"hvac": "OpenBao / Vault client",
|
||||||
|
"bao": "OpenBao client",
|
||||||
|
"kubernetes": "cluster client",
|
||||||
|
"kubernetes_asyncio": "cluster client",
|
||||||
|
"psycopg": "direct database connection",
|
||||||
|
"psycopg2": "direct database connection",
|
||||||
|
"asyncpg": "direct database connection",
|
||||||
|
"sqlalchemy": "direct database connection",
|
||||||
|
"pymysql": "direct database connection",
|
||||||
|
"redis": "direct datastore connection",
|
||||||
|
"ldap3": "direct LDAP client (key-cape tooling)",
|
||||||
|
"python_ldap": "direct LDAP client (key-cape tooling)",
|
||||||
|
"docker": "container runtime client",
|
||||||
|
}
|
||||||
|
|
||||||
|
HTTP_SURFACE_IMPORTS = {
|
||||||
|
"flask": "HTTP framework",
|
||||||
|
"fastapi": "HTTP framework",
|
||||||
|
"starlette": "HTTP framework",
|
||||||
|
"aiohttp": "HTTP framework",
|
||||||
|
"tornado": "HTTP framework",
|
||||||
|
"bottle": "HTTP framework",
|
||||||
|
"quart": "HTTP framework",
|
||||||
|
"sanic": "HTTP framework",
|
||||||
|
"django": "HTTP framework",
|
||||||
|
"gunicorn": "HTTP server",
|
||||||
|
"uvicorn": "HTTP server",
|
||||||
|
"hypercorn": "HTTP server",
|
||||||
|
"waitress": "HTTP server",
|
||||||
|
}
|
||||||
|
|
||||||
|
DECISION_PATHS = ("/authorize", "/v1/check", "/v1/authorize")
|
||||||
|
|
||||||
|
|
||||||
|
class ConformanceError(ValueError):
|
||||||
|
"""Declaration is missing, unparseable, or disagrees with INTENT.md."""
|
||||||
|
|
||||||
|
|
||||||
|
def _frontmatter(path: Path) -> dict[str, Any]:
|
||||||
|
text = path.read_text()
|
||||||
|
if not text.startswith("---\n") or "\n---\n" not in text[4:]:
|
||||||
|
raise ConformanceError(f"{path.name} requires YAML frontmatter")
|
||||||
|
raw = text.split("\n---\n", 1)[0][4:]
|
||||||
|
value = yaml.safe_load(raw) or {}
|
||||||
|
if not isinstance(value, Mapping):
|
||||||
|
raise ConformanceError(f"{path.name} frontmatter must be a mapping")
|
||||||
|
return dict(value)
|
||||||
|
|
||||||
|
|
||||||
|
def load_declaration(path: Path = DECL) -> dict[str, Any]:
|
||||||
|
if not path.exists():
|
||||||
|
raise ConformanceError(f"no declaration at {path.name} (§11)")
|
||||||
|
try:
|
||||||
|
data = yaml.safe_load(path.read_text())
|
||||||
|
except yaml.YAMLError as exc:
|
||||||
|
raise ConformanceError(f"{path.name} is not parseable: {exc}") from exc
|
||||||
|
if not isinstance(data, Mapping):
|
||||||
|
raise ConformanceError(f"{path.name} must be a mapping")
|
||||||
|
for key in ("layer", "role", "repository", "tooling_contacts", "standard_version"):
|
||||||
|
if key not in data:
|
||||||
|
raise ConformanceError(f"{path.name} missing required key '{key}' (§11)")
|
||||||
|
return dict(data)
|
||||||
|
|
||||||
|
|
||||||
|
def load_intent(path: Path = INTENT) -> dict[str, Any]:
|
||||||
|
if not path.exists():
|
||||||
|
raise ConformanceError(f"no INTENT.md at {path}")
|
||||||
|
return _frontmatter(path)
|
||||||
|
|
||||||
|
|
||||||
|
def _norm(value: Any) -> str:
|
||||||
|
return str(value or "").strip().lower()
|
||||||
|
|
||||||
|
|
||||||
|
def check_declaration_agrees(
|
||||||
|
decl: Mapping[str, Any], intent: Mapping[str, Any]
|
||||||
|
) -> list[str]:
|
||||||
|
errors: list[str] = []
|
||||||
|
if _norm(decl.get("layer")) != "engine":
|
||||||
|
errors.append(f"declared layer is '{decl.get('layer')}', expected 'engine'")
|
||||||
|
if _norm(decl.get("role")) != "pip":
|
||||||
|
errors.append(f"declared role is '{decl.get('role')}', expected 'pip'")
|
||||||
|
if _norm(intent.get("layer")) != _norm(decl.get("layer")):
|
||||||
|
errors.append(
|
||||||
|
f"INTENT.md layer '{intent.get('layer')}' disagrees with "
|
||||||
|
f"layer.yaml '{decl.get('layer')}'"
|
||||||
|
)
|
||||||
|
if _norm(intent.get("role")) != _norm(decl.get("role")):
|
||||||
|
errors.append(
|
||||||
|
f"INTENT.md role '{intent.get('role')}' disagrees with "
|
||||||
|
f"layer.yaml '{decl.get('role')}'"
|
||||||
|
)
|
||||||
|
if decl.get("repository") != "zone-engine":
|
||||||
|
errors.append(f"declared repository is '{decl.get('repository')}'")
|
||||||
|
if decl.get("pep_stance"):
|
||||||
|
errors.append("pep_stance is set; this repository is not PEP-shaped")
|
||||||
|
contacts = decl.get("tooling_contacts")
|
||||||
|
if contacts not in ([], None):
|
||||||
|
errors.append(
|
||||||
|
"tooling_contacts is not empty; a new contact needs a §10 cut, "
|
||||||
|
"not a quiet row"
|
||||||
|
)
|
||||||
|
return errors
|
||||||
|
|
||||||
|
|
||||||
|
def imported_modules(path: Path) -> set[str]:
|
||||||
|
try:
|
||||||
|
tree = ast.parse(path.read_text())
|
||||||
|
except SyntaxError:
|
||||||
|
return set()
|
||||||
|
found: set[str] = set()
|
||||||
|
for node in ast.walk(tree):
|
||||||
|
if isinstance(node, ast.Import):
|
||||||
|
found.update(alias.name.split(".")[0] for alias in node.names)
|
||||||
|
elif isinstance(node, ast.ImportFrom):
|
||||||
|
if node.level == 0 and node.module:
|
||||||
|
found.add(node.module.split(".")[0])
|
||||||
|
return found
|
||||||
|
|
||||||
|
|
||||||
|
def string_literals(path: Path) -> list[str]:
|
||||||
|
try:
|
||||||
|
tree = ast.parse(path.read_text())
|
||||||
|
except SyntaxError:
|
||||||
|
return []
|
||||||
|
found: list[str] = []
|
||||||
|
for node in ast.walk(tree):
|
||||||
|
if isinstance(node, ast.Constant) and isinstance(node.value, str):
|
||||||
|
found.append(node.value)
|
||||||
|
return found
|
||||||
|
|
||||||
|
|
||||||
|
def scan_tooling(directory: Path) -> list[tuple[Path, str, str]]:
|
||||||
|
hits: list[tuple[Path, str, str]] = []
|
||||||
|
for path in sorted(directory.rglob("*.py")):
|
||||||
|
for module in sorted(imported_modules(path)):
|
||||||
|
if module in TOOLING_IMPORTS:
|
||||||
|
hits.append((path, module, TOOLING_IMPORTS[module]))
|
||||||
|
return hits
|
||||||
|
|
||||||
|
|
||||||
|
def scan_decision_surfaces(directory: Path) -> list[tuple[Path, str, str]]:
|
||||||
|
hits: list[tuple[Path, str, str]] = []
|
||||||
|
for path in sorted(directory.rglob("*.py")):
|
||||||
|
if path.resolve() == Path(__file__).resolve():
|
||||||
|
continue
|
||||||
|
for module in sorted(imported_modules(path)):
|
||||||
|
if module in HTTP_SURFACE_IMPORTS:
|
||||||
|
hits.append((path, module, HTTP_SURFACE_IMPORTS[module]))
|
||||||
|
if module == "http":
|
||||||
|
# http.server is the stdlib decision-adjacent live surface.
|
||||||
|
text = path.read_text()
|
||||||
|
if "http.server" in text:
|
||||||
|
hits.append((path, "http.server", "stdlib HTTP server"))
|
||||||
|
for literal in string_literals(path):
|
||||||
|
for needle in DECISION_PATHS:
|
||||||
|
if needle in literal:
|
||||||
|
hits.append((path, literal, f"authorization path {needle}"))
|
||||||
|
return hits
|
||||||
|
|
||||||
|
|
||||||
|
def overdue_reviews(decl: Mapping[str, Any], today: date | None = None) -> list[str]:
|
||||||
|
today = today or date.today()
|
||||||
|
notes: list[str] = []
|
||||||
|
for cap in decl.get("unowned_capabilities") or []:
|
||||||
|
review = cap.get("review")
|
||||||
|
if not review:
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
due = date.fromisoformat(str(review))
|
||||||
|
except ValueError:
|
||||||
|
notes.append(f"{cap.get('id')}: unparseable review date {review!r}")
|
||||||
|
continue
|
||||||
|
if due < today:
|
||||||
|
notes.append(f"{cap.get('id')}: review overdue ({review})")
|
||||||
|
return notes
|
||||||
|
|
||||||
|
|
||||||
|
def evaluate(
|
||||||
|
*,
|
||||||
|
root: Path | None = None,
|
||||||
|
tools: Path | None = None,
|
||||||
|
decl_path: Path | None = None,
|
||||||
|
intent_path: Path | None = None,
|
||||||
|
) -> tuple[int, list[str], list[str]]:
|
||||||
|
"""Return (exit_code, errors, reports). Exit 2 for declaration, 1 for tree."""
|
||||||
|
root = root or ROOT
|
||||||
|
tools = tools or (root / "tools")
|
||||||
|
decl_path = decl_path or (root / "layer.yaml")
|
||||||
|
intent_path = intent_path or (root / "INTENT.md")
|
||||||
|
try:
|
||||||
|
decl = load_declaration(decl_path)
|
||||||
|
intent = load_intent(intent_path)
|
||||||
|
except ConformanceError as exc:
|
||||||
|
return 2, [str(exc)], []
|
||||||
|
errors = check_declaration_agrees(decl, intent)
|
||||||
|
if errors:
|
||||||
|
return 2, errors, []
|
||||||
|
reports = overdue_reviews(decl)
|
||||||
|
tree_errors: list[str] = []
|
||||||
|
for path, module, what in scan_tooling(tools):
|
||||||
|
rel = path.relative_to(root) if path.is_relative_to(root) else path
|
||||||
|
tree_errors.append(f"{rel}: imports '{module}' — {what}")
|
||||||
|
for path, token, what in scan_decision_surfaces(tools):
|
||||||
|
rel = path.relative_to(root) if path.is_relative_to(root) else path
|
||||||
|
tree_errors.append(f"{rel}: {what} ({token})")
|
||||||
|
if tree_errors:
|
||||||
|
return 1, tree_errors, reports
|
||||||
|
return 0, [], reports
|
||||||
|
|
||||||
|
|
||||||
|
def main(argv: Iterable[str] | None = None) -> int:
|
||||||
|
parser = argparse.ArgumentParser(description=__doc__)
|
||||||
|
parser.add_argument("--report", action="store_true", help="print the declaration summary")
|
||||||
|
args = parser.parse_args(list(argv) if argv is not None else None)
|
||||||
|
|
||||||
|
code, errors, reports = evaluate()
|
||||||
|
if args.report:
|
||||||
|
try:
|
||||||
|
decl = load_declaration()
|
||||||
|
except ConformanceError as exc:
|
||||||
|
print(f"FAIL: {exc}", file=sys.stderr)
|
||||||
|
return 2
|
||||||
|
print(
|
||||||
|
f"zone-engine — layer {decl['layer']}, role {decl['role']}, "
|
||||||
|
f"standard v{decl['standard_version']}"
|
||||||
|
)
|
||||||
|
print(f" tooling contacts declared: {len(decl.get('tooling_contacts') or [])}")
|
||||||
|
print(f" pep_stance: {decl.get('pep_stance')!r}")
|
||||||
|
for note in reports:
|
||||||
|
print(f" review: {note}")
|
||||||
|
|
||||||
|
if code == 2:
|
||||||
|
print("FAIL: layer declaration malformed or disagrees with INTENT.md (§11)", file=sys.stderr)
|
||||||
|
for item in errors:
|
||||||
|
print(f" {item}", file=sys.stderr)
|
||||||
|
return 2
|
||||||
|
if code == 1:
|
||||||
|
print("FAIL: undeclared Tooling client or HTTP decision surface (§6, §11)", file=sys.stderr)
|
||||||
|
for item in errors:
|
||||||
|
print(f" {item}", file=sys.stderr)
|
||||||
|
print("", file=sys.stderr)
|
||||||
|
print(" A live API, Tooling client, or /authorize helper is a layer change.", file=sys.stderr)
|
||||||
|
print(" Do not declare it to make the check pass.", file=sys.stderr)
|
||||||
|
return 1
|
||||||
|
if not args.report:
|
||||||
|
print(f"OK: Engine/PIP declaration agrees with INTENT.md; no Tooling client or decision surface in {TOOLS.relative_to(ROOT)}")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main())
|
||||||
|
|
@ -4,7 +4,7 @@ type: workplan
|
||||||
title: "Declare Engine/PIP and freeze the offline zone-membership surface"
|
title: "Declare Engine/PIP and freeze the offline zone-membership surface"
|
||||||
domain: infotech
|
domain: infotech
|
||||||
repo: zone-engine
|
repo: zone-engine
|
||||||
status: ready
|
status: finished
|
||||||
owner: zone-engine
|
owner: zone-engine
|
||||||
assignee: grok
|
assignee: grok
|
||||||
lane: yellow
|
lane: yellow
|
||||||
|
|
@ -12,6 +12,10 @@ topic_slug: netkingdom
|
||||||
planning_priority: P1
|
planning_priority: P1
|
||||||
created: "2026-08-29"
|
created: "2026-08-29"
|
||||||
updated: "2026-08-29"
|
updated: "2026-08-29"
|
||||||
|
quality_dod: DoD-Ok
|
||||||
|
quality_dod_at: "2026-08-29"
|
||||||
|
quality_dod_by: grok
|
||||||
|
quality_dod_note: "layer.yaml agrees with INTENT.md; make check covers the freeze (no Tooling client, no decision surface); §10 artifacts and PIP claim mapping are cited; README uses the ruled PDP name; no live API was added."
|
||||||
origin: "history/2026-08-29-security-layer-model-scope-against-intent.md"
|
origin: "history/2026-08-29-security-layer-model-scope-against-intent.md"
|
||||||
context_paths:
|
context_paths:
|
||||||
- "GOAL.md"
|
- "GOAL.md"
|
||||||
|
|
@ -91,7 +95,7 @@ and the `flex-auth` repository rename are intentionally excluded.
|
||||||
|
|
||||||
```task
|
```task
|
||||||
id: ZONE-WP-0003-T01
|
id: ZONE-WP-0003-T01
|
||||||
status: todo
|
status: done
|
||||||
priority: high
|
priority: high
|
||||||
state_hub_task_id: "ca687f30-2ad5-5243-8e48-efc34c78465c"
|
state_hub_task_id: "ca687f30-2ad5-5243-8e48-efc34c78465c"
|
||||||
```
|
```
|
||||||
|
|
@ -149,7 +153,7 @@ counting this repository among the undeclared nine.
|
||||||
|
|
||||||
```task
|
```task
|
||||||
id: ZONE-WP-0003-T03
|
id: ZONE-WP-0003-T03
|
||||||
status: todo
|
status: done
|
||||||
priority: medium
|
priority: medium
|
||||||
state_hub_task_id: "828a4c67-9644-5b27-ac97-d79563848dfc"
|
state_hub_task_id: "828a4c67-9644-5b27-ac97-d79563848dfc"
|
||||||
```
|
```
|
||||||
|
|
@ -174,7 +178,7 @@ them from workplan history, and `INTENT.md` or `SCOPE.md` cites the note.
|
||||||
|
|
||||||
```task
|
```task
|
||||||
id: ZONE-WP-0003-T04
|
id: ZONE-WP-0003-T04
|
||||||
status: todo
|
status: done
|
||||||
priority: medium
|
priority: medium
|
||||||
state_hub_task_id: "bd4955b6-dfb8-59e5-be20-f4f8ab93ae8e"
|
state_hub_task_id: "bd4955b6-dfb8-59e5-be20-f4f8ab93ae8e"
|
||||||
```
|
```
|
||||||
|
|
@ -194,7 +198,7 @@ SCOPE.md GOAL.md` is the consumer-facing surface.
|
||||||
|
|
||||||
```task
|
```task
|
||||||
id: ZONE-WP-0003-T05
|
id: ZONE-WP-0003-T05
|
||||||
status: todo
|
status: done
|
||||||
priority: medium
|
priority: medium
|
||||||
state_hub_task_id: "ee883d61-4d27-5223-826c-c37f66e3bcb4"
|
state_hub_task_id: "ee883d61-4d27-5223-826c-c37f66e3bcb4"
|
||||||
```
|
```
|
||||||
|
|
@ -221,14 +225,14 @@ and no new wire format has shipped.
|
||||||
|
|
||||||
## Acceptance criteria
|
## Acceptance criteria
|
||||||
|
|
||||||
- [ ] `layer.yaml` declares Engine / PIP, no Tooling contacts, no PEP map.
|
- [x] `layer.yaml` declares Engine / PIP, no Tooling contacts, no PEP map.
|
||||||
- [ ] `make check` fails a new undeclared Tooling client or decision surface.
|
- [x] `make check` fails a new undeclared Tooling client or decision surface.
|
||||||
- [x] `ZONE-IN-0001` is closed on the own-voice declaration.
|
- [x] `ZONE-IN-0001` is closed on the own-voice declaration.
|
||||||
- [x] `gate-house` has been notified.
|
- [x] `gate-house` has been notified.
|
||||||
- [ ] Statute §10 artifacts for the 2026-08-23 cut are gathered in one place.
|
- [x] Statute §10 artifacts for the 2026-08-23 cut are gathered in one place.
|
||||||
- [ ] Consumer-facing docs use `access-engine` as the ruled PDP name.
|
- [x] Consumer-facing docs use `access-engine` as the ruled PDP name.
|
||||||
- [ ] PIP facts are mapped for a future claim schema without shipping one.
|
- [x] PIP facts are mapped for a future claim schema without shipping one.
|
||||||
- [ ] No live API, daemon, decision surface, or compiled stance was added.
|
- [x] No live API, daemon, decision surface, or compiled stance was added.
|
||||||
|
|
||||||
## Out of scope
|
## Out of scope
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue