185 lines
9 KiB
Markdown
185 lines
9 KiB
Markdown
|
|
---
|
|||
|
|
title: "Scope vs Intent review against Security Layer Model v0.7"
|
|||
|
|
date: 2026-08-29
|
|||
|
|
repo: kings-guard
|
|||
|
|
author: kings-guard
|
|||
|
|
standard: net-kingdom/canon/standards/security-layer-model_v0.7.md
|
|||
|
|
companion: net-kingdom/SECURITY-COMPANION.md
|
|||
|
|
status: complete
|
|||
|
|
outcome: KG-WP-0003
|
|||
|
|
classification: Public
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# Scope vs Intent review against Security Layer Model v0.7
|
|||
|
|
|
|||
|
|
The NetKingdom Security Layer Model reached **v0.7, accepted**, with a working
|
|||
|
|
companion at `net-kingdom/SECURITY-COMPANION.md`. `INTENT.md` and `SCOPE.md`
|
|||
|
|
have been adapted to it. This review compares the adapted documents against the
|
|||
|
|
implementation and names what has to change.
|
|||
|
|
|
|||
|
|
The finding in one line: **the documents are now correct and the code has not
|
|||
|
|
caught up.** Every gap below is a place where `INTENT.md` or `SCOPE.md` now
|
|||
|
|
claims something `src/kings_guard/` does not do.
|
|||
|
|
|
|||
|
|
## 1. What the statute settled for this repository
|
|||
|
|
|
|||
|
|
Four of our review findings were adopted across v0.5–v0.7, and two of them
|
|||
|
|
changed what this repository is:
|
|||
|
|
|
|||
|
|
- **Containment left us entirely (§9.2).** Reduce authority, require step-up,
|
|||
|
|
isolate a workload are authority-changing operations, rendered by an Engine
|
|||
|
|
and enforced by a PEP. kings-guard proposes containment and never performs it.
|
|||
|
|
We had been carrying our inability to contain as our own gap; it was never
|
|||
|
|
ours. The actuation surface is unowned estate-wide and held at zero.
|
|||
|
|
- **The agent principal is now bound by four rules (§3.4).** v0.6 announced them
|
|||
|
|
and never wrote them; we found that and offered to assent sight-unseen, and
|
|||
|
|
v0.7 wrote them. They bind this repository harder than any other in the
|
|||
|
|
catalog.
|
|||
|
|
|
|||
|
|
Two obligations arrived with them:
|
|||
|
|
|
|||
|
|
- **kings-guard drafts the emission-cadence declaration (§17)** — as its only
|
|||
|
|
consumer. Ownership stays with Taxonomy; the draft is ours.
|
|||
|
|
- **Load-bearing evidence MUST declare an expected cadence (§9.6)**, and for
|
|||
|
|
low-volume classes — revocations, denials, containment — rate monitoring
|
|||
|
|
cannot work, so the required form is reconciliation or a heartbeat.
|
|||
|
|
|
|||
|
|
Our catalog entry is now: *adaptive defence and judgment; observation of
|
|||
|
|
Staff-reachable sources — identity and secret observation pending; proposes
|
|||
|
|
containment, which it does not own.*
|
|||
|
|
|
|||
|
|
## 2. Where the repository conforms
|
|||
|
|
|
|||
|
|
Worth stating, because the conformance position is unusual and is the thing most
|
|||
|
|
easily lost in a refactor:
|
|||
|
|
|
|||
|
|
- **No Tooling contact of any shape.** Not a §5.1 diagnostic read, not a §5.2
|
|||
|
|
conduit, not a §5.3 declared gap. `dependencies = []` in `pyproject.toml` is
|
|||
|
|
load-bearing for this and must stay empty.
|
|||
|
|
- **Blocked-clean (§11)**, which the statute rules MUST NOT rank below
|
|||
|
|
conforming. Three capabilities sit at zero rather than being taken locally.
|
|||
|
|
- **The claim is executable**, not asserted: `layer.yaml`,
|
|||
|
|
`scripts/check_layer_conformance.py`, `tests/test_layer_conformance.py`. The
|
|||
|
|
companion cites these estate-wide as the reference for a repository with no
|
|||
|
|
Tooling contacts at all.
|
|||
|
|
- **The asymmetry holds in code.** Every `EffectorRequest` carries an explicit
|
|||
|
|
`authority_boundary`; the values in use are `advisory_only` and
|
|||
|
|
`metadata_only`. No path widens authority.
|
|||
|
|
|
|||
|
|
## 3. Gaps — Intent and Scope against the implementation
|
|||
|
|
|
|||
|
|
### G1. Evidence is not classified load-bearing or attributive — §9.6
|
|||
|
|
|
|||
|
|
`ImmuneObservation` carries `source_system` and no evidence class. The statute
|
|||
|
|
attaches different obligations to each: a load-bearing source MUST declare a
|
|||
|
|
cadence, must emit atomically, and its absence is a finding; an attributive
|
|||
|
|
source SHOULD. Without the classification the evaluator cannot know which
|
|||
|
|
obligation applies to a stream, and `SCOPE.md` now claims we classify.
|
|||
|
|
|
|||
|
|
*Necessity:* an evidence class on the observation and on the genome's declared
|
|||
|
|
sources, with the obligation difference expressed in the contract document.
|
|||
|
|
|
|||
|
|
### G2. No emission-cadence declaration exists — §17, and it is ours to draft
|
|||
|
|
|
|||
|
|
`SecurityGenome` has no cadence field. We cannot implement silence-as-signal
|
|||
|
|
without a schema for declared cadence, and inventing a local shape is the exact
|
|||
|
|
drift §17 exists to prevent. The statute has accepted us as drafter.
|
|||
|
|
|
|||
|
|
*Necessity:* draft the declaration against `qonto-assistant` as the one real
|
|||
|
|
source, covering both forms — expected rate for volume classes, and
|
|||
|
|
reconciliation or heartbeat for low-volume load-bearing classes — and hand it to
|
|||
|
|
Taxonomy. It belongs alongside the security genome: a source already declares
|
|||
|
|
its intent there, and expected emission cadence is a claim of the same kind.
|
|||
|
|
|
|||
|
|
### G3. Silence is not a signal — §9.6
|
|||
|
|
|
|||
|
|
`PostureEvaluator.evaluate()` takes one observation and returns one assessment.
|
|||
|
|
It is stateless and has no view of a stream. An event that is never emitted is
|
|||
|
|
never evaluated: no finding, no signal, no posture change, and the last posture
|
|||
|
|
stands. Suppression therefore biases posture **optimistic**, silently. This is
|
|||
|
|
the failure the statute names, reproduced one layer up in the consumer.
|
|||
|
|
|
|||
|
|
*Necessity:* a stream-level evaluation path alongside the per-observation one —
|
|||
|
|
cadence comparison for volume classes, reconciliation or heartbeat absence for
|
|||
|
|
rare ones — emitting a finding when the stream itself goes quiet.
|
|||
|
|
|
|||
|
|
### G4. Confidence measures the record, not the stream — §9.6
|
|||
|
|
|
|||
|
|
`confidence_score` starts at 70 and rises with `policy_version`, `latency_ms`
|
|||
|
|
and `resource_scope`. It is a measure of field richness in the record we
|
|||
|
|
received. A perfectly-formed observation drawn from a 90%-suppressed stream
|
|||
|
|
scores 85. The score cannot express the doubt the statute now requires us to
|
|||
|
|
carry.
|
|||
|
|
|
|||
|
|
*Necessity:* separate completeness from richness. Posture output should carry a
|
|||
|
|
stream-completeness dimension that degrades when cadence is unmet or a heartbeat
|
|||
|
|
is missing, and `PostureAssessment` should be able to say *this judgment rests
|
|||
|
|
on a stream I cannot vouch for.*
|
|||
|
|
|
|||
|
|
### G5. Nothing prevents immune memory becoming a state plane — §3.4 rule 3
|
|||
|
|
|
|||
|
|
`ImmuneMemoryEntry` exists with `confidentiality: str = "non-secret"` and no
|
|||
|
|
rule about who may depend on it. `INTENT.md` stage 5 (federated memory) is
|
|||
|
|
exactly the shape that could drift into a state plane, and the statute forbids
|
|||
|
|
it unless catalogued as Tooling.
|
|||
|
|
|
|||
|
|
*Necessity:* state the constraint in `specs/ImmuneContracts.md` — immune memory
|
|||
|
|
informs kings-guard's judgment and may be published as evidence; no engine, PEP
|
|||
|
|
or workload may read it as a runtime input — and assert it in a test so the
|
|||
|
|
drift is caught rather than argued.
|
|||
|
|
|
|||
|
|
### G6. Proposals carry no reference to what they were rendered against — §9.2
|
|||
|
|
|
|||
|
|
`EffectorRequest` has `target_system`, `action`, `authority_boundary`, `reason`,
|
|||
|
|
`requires_human_approval`. §9.2 rules that a containment action is a decision
|
|||
|
|
record, not a side channel. Our proposals are the input to such a record and
|
|||
|
|
carry no request identity, so a proposal cannot be reconstructed against the
|
|||
|
|
observation that produced it once it leaves this repository.
|
|||
|
|
|
|||
|
|
*Necessity:* carry the originating observation and signal identity on the
|
|||
|
|
request, so the eventual decision record can name what it was rendered for.
|
|||
|
|
|
|||
|
|
### G7. The agent-principal rules are documented and unverified — §3.4
|
|||
|
|
|
|||
|
|
All four are now claimed in `INTENT.md`. None is checked. Rule 1 (no standing
|
|||
|
|
credential) is mechanically checkable in this repository the same way the
|
|||
|
|
no-Tooling-client claim is; rule 3 follows from G5.
|
|||
|
|
|
|||
|
|
*Necessity:* extend `scripts/check_layer_conformance.py` to cover what can be
|
|||
|
|
checked, and record honestly which rules are assertion rather than test.
|
|||
|
|
|
|||
|
|
### G8. §12's fourth step is unstaffed — the pilot is fixture-only
|
|||
|
|
|
|||
|
|
Every input is a hand-built fixture. Ten tests pass and none has met a real
|
|||
|
|
event. The statute records this as disclosed, and §19's verdict — the estate can
|
|||
|
|
propose and decide but cannot watch or act — names us as the watching half.
|
|||
|
|
|
|||
|
|
Nothing blocks it: `qonto-assistant` publishes its own genome and audit stream,
|
|||
|
|
needs no engine in the path, and its genome has not drifted since it was
|
|||
|
|
written. This is the one substantial lane no engine gap touches.
|
|||
|
|
|
|||
|
|
*Necessity:* ingest real emitted events from `qonto-assistant`, confirm or
|
|||
|
|
correct the observation mapping, keep the output advisory.
|
|||
|
|
|
|||
|
|
### G9. Residual vocabulary — KG-IN-0002
|
|||
|
|
|
|||
|
|
`specs/NetKingdomImmuneArchitecture.md` predates the model and still uses
|
|||
|
|
"control plane" across ~1900 lines. A scoping note heads the file; the body is
|
|||
|
|
unadapted. Now also carries the stale stage-3 framing that §9.2 corrected.
|
|||
|
|
|
|||
|
|
## 4. What is deliberately not being done
|
|||
|
|
|
|||
|
|
- **No engine gap is being worked around.** Identity and secret observation stay
|
|||
|
|
at zero. The blocked-clean position is the point, not an inconvenience.
|
|||
|
|
- **No actuation.** G6 makes proposals reconstructable; it does not make them
|
|||
|
|
actionable, and nothing here moves toward an effector that acts.
|
|||
|
|
- **No Tooling client**, including for live ingest in G8 — `qonto-assistant`
|
|||
|
|
is a governed domain assistant publishing its own stream, not a Tooling row.
|
|||
|
|
|
|||
|
|
## 5. Disposition
|
|||
|
|
|
|||
|
|
`KG-WP-0003` carries G1–G8. G9 remains `KG-IN-0002`. The ordering is forced:
|
|||
|
|
G2 unblocks G3, and G3 unblocks G4; G1 is a prerequisite for all three because
|
|||
|
|
the obligation differs by evidence class. G8 is independent and is what makes
|
|||
|
|
the rest testable against something real.
|