Align to security layer model v0.7 and open the engine spine

The statute is accepted at v0.7; the operative form is
net-kingdom/SECURITY-COMPANION.md v0.2. INTENT now declares Engine / PIP
in its own voice, carries the §9.6 threat decomposition, the load-bearing
heartbeat obligation, issuer and freshness on the claim, consumption as a
mutation, and the custody question closed rather than held open.

SCOPE.md is the first-cut boundary (nothing shipped). layer.yaml is the
machine-readable declaration. The review under history/ scores intent vs
scope vs the empty implementation. APPROVAL-WP-0001 sequences contracts
before code and keeps consumption unimplemented until GH-WP-0002-T06.

Registered with State Hub as infotech / approval-engine.

Assistant: grok
Assistant-Session: 01a04ceb-2057-7e20-b0f9-c282964d5dd9
This commit is contained in:
tegwick 2026-08-29 11:58:28 +02:00
parent ab5d69e8f1
commit 2a5a47df89
9 changed files with 1069 additions and 35 deletions

169
INTENT.md
View file

@ -1,8 +1,25 @@
---
layer: Engine
role: PIP
standard: net-kingdom/canon/standards/security-layer-model_v0.7.md
companion: net-kingdom/SECURITY-COMPANION.md
---
# INTENT
> **Layer: Engine.** NetKingdom Security Layer Model §4 catalog — a deterministic
> API for a modeled concept, where the same authoritative input state yields the
> same result. Standard: `net-kingdom/canon/standards/security-layer-model_v0.5.md`.
> **Layer: Engine. Role: PIP.** NetKingdom Security Layer Model §3.3 / §4
> catalog — a deterministic API for a modeled concept, where the same
> authoritative input state yields the same result. This engine **supplies
> facts a decision consumes as claims**; it never renders one. A new engine is
> a PIP unless the statute is amended, and §6 means it can never be a second
> PDP.
>
> Statute (accepted 2026-08-29):
> `net-kingdom/canon/standards/security-layer-model_v0.7.md`.
> Operative form: `net-kingdom/SECURITY-COMPANION.md` v0.2. The statute governs
> on disagreement; a disagreement is a finding for `gate-house`.
>
> Machine-readable declaration: `layer.yaml`.
>
> This file captures why this repository exists and the kind of system it is
> meant to become. It is aspirational and stable, not a description of current
@ -21,7 +38,9 @@ It answers one question, totally and decidably:
Nothing else. It does not decide whether the action is permitted; that is
`access-engine`'s and it stays the only decision point. An approval is one
*input* to that decision.
*input* to that decision. An outage here is **input degradation**, which is this
engine's fallback to own (§9.3) — never a consumer-invented substitute for the
object.
## Why This Exists
@ -41,7 +60,8 @@ evaluates is self-dealing. It is not `audit-core`'s: an approval needs mutable,
in-path, current-state semantics, and an append-only audit fabric is built for
the opposite property.
So it is a concept, and concepts get engines.
So it is a concept, and concepts get engines. The catalog types it **PIP**
because "we need an engine for X" must not drift into "X now decides".
## The Concept
@ -63,6 +83,12 @@ requested → approved → valid → consumed
superseded / revoked / expired
```
An approval object is **not a Railiance workload** and never becomes one
(standard §20.1). Human commands, broker actions, and approvals that are not
themselves deployables sit outside the `railiance-*` / `rail-*` / `rapp-*` /
`reef-*` axes. This engine does not acquire an operational axis by being
consumed from one.
## Rigidity Is the Point
This engine is deliberately small, boring, and strict. Its state model is a
@ -74,6 +100,12 @@ that make Canon test `T-06 — Approval Replay` passable. An approval that is
partly valid, or whose validity must be inferred by replaying a log, is an
approval that can be replayed. Flexibility here is a defect.
**Consumption is a state change, never an inference** (standard §9.7.3). An
approval is consumed by a mutation in this engine. It MUST NOT be inferred from
the existence of a decision record — the decision precedes the action and the
action precedes consumption, so a decision record proves an intent to act, not
an act.
Progression modelling — graded, evidence-based, open-ended — belongs to
`maturity-engine`. The two engines are deliberate opposites and neither should
drift toward the other.
@ -86,11 +118,16 @@ drift toward the other.
- validity windows and expiry;
- binding to action, target, actor, principal, and purpose;
- revocation that does not require the holder's cooperation;
- an introspection API that `access-engine` consumes as an **input claim**;
- an introspection API that `access-engine` consumes as an **input claim**,
carrying issuer and freshness so the PDP can state a deadline for this input
class (§9.7.2);
- **emission atomicity** — every issuance, use, supersession, and revocation is
emitted to `audit-core` in the **same transaction** as the state change
(transactional outbox or equivalent). See below; this is a contract, not an
implementation detail.
queued in this engine's **local** transactional store in the **same
transaction** as the state change. See below; this is a contract, not an
implementation detail;
- **emission cadence** for load-bearing classes, in the form that actually
works for rare events: positive reconciliation or a heartbeat, not rate
monitoring.
## Emission Atomicity
@ -126,18 +163,62 @@ Consequence for design: emit-after-commit is a defect, not an optimization. A
best-effort publish, a fire-and-forget queue, or any path where the state change
can succeed while the event is lost is out of contract.
## Which threat atomicity closes — and which it does not
v0.6 read as though a local outbox closed §9.6's opening sentence. It does not.
The decomposition is now in the statute and is this engine's to carry, because
approval evidence is **load-bearing**:
| Threat | Covered by | When |
| --- | --- | --- |
| Accidental omission — crash between mutation and emit | local outbox (§9.4) | **prevented** |
| Adversarial omission — a compromised source declines to insert, deletes before drain, or drains to nowhere | cadence and reconciliation | **detected, after the fact** |
| Adversarial omission at a compromised source | — | **nothing in the model prevents it** |
The outbox sits inside this engine's blast radius. It makes emission atomic
against crash and partial failure, and nothing more. That residual is real.
Approval events are **low-volume load-bearing**. Rate monitoring cannot work:
a handful of revocations a month has no rate to drop below, and suppression is
indistinguishable from a quiet month. The required form is **positive
reconciliation or a heartbeat** — compare this engine's object-state transitions
against `audit-core`'s event count per class, or assert *nothing to report* as
a signed positive claim that can itself go missing. `GH-WP-0002-T04` is the
reference instance. A source of load-bearing evidence **MUST** declare this
(standard §9.6).
**Custody is not the residual's answer.** Whether approvals warrant archival
custody stronger than every other source is **decided: no** (standard §16).
Approval evidence carries the same bound as every other source. Archival
custody does not address omission at all. If a future requirement genuinely
needs WORM or a transparency log, that is a different store with a different
owner, raised then. This engine must not plan around a stronger archive.
## The Claim Shape
`access-engine` consumes approvals as input claims. The claim MUST carry the
approval identifier **and a digest over the same canonical binding the decision
point already computes**, so that *approved* and *approved for this exact
request* are distinguishable at decision time. Without it, wrong-action,
wrong-target, and wrong-scope proofs have nothing to compare against.
`access-engine` consumes approvals as input claims. The claim MUST carry:
- the approval identifier;
- a digest over the same canonical binding the decision point already computes,
so that *approved* and *approved for this exact request* are distinguishable
at decision time;
- **issuer** (this engine) and a **freshness** rule, so the PDP can state a
deadline for this input class rather than a single fiction covering every
source (§9.7.2, §17 request-claim schema).
Without the digest, wrong-action, wrong-target, and wrong-scope proofs have
nothing to compare against. Without issuer and freshness, a stated deadline
for the approval input class is unfalsifiable.
Until Taxonomy publishes the shared request-claim schema (§17; ownership
proposed, not assigned), this engine publishes the contract at its own
boundary and yields to the schema when it exists. Inventing a permanent local
shape is the drift §17 exists to prevent.
## Consumption Ordering — Unresolved
The decision precedes the action, and the action precedes consumption. Three
states follow that neither engine closes alone:
failure modes are named, and each needs an owner (standard §9.7.4, §16):
- an allow rendered against an approval that is then never consumed;
- an approval consumed twice by racing callers;
@ -146,8 +227,9 @@ states follow that neither engine closes alone:
`approval-engine` performs the mutation, because `access-engine` never mutates.
But *who signals consumption, at what point relative to the decision, and what
happens on each of the three states above* is a contract between the two engines
and is **not yet settled**. It is recorded in the standard's §16 and is required
before `FLEX-WP-0017` T05. Raised by `flex-auth`.
and is **not yet settled**. It is recorded in the standard's §16, in
`GH-WP-0002-T06`, and is required before `FLEX-WP-0017` T05. Raised by
`flex-auth`.
Nothing here may be implemented by guessing that contract.
@ -160,12 +242,18 @@ Nothing here may be implemented by guessing that contract.
versioned policy rules);
- **identity and authentication of approvers**`key-cape`, consumed as claims;
- **the evidence record**`audit-core` holds the archive; this engine holds
only the operative current state. Note the guarantee is bounded: `audit-core`
is not WORM or object-locked, and its tamper evidence is conditional on live
preconditions. Whether approvals warrant stronger custody is an open gap in
the standard's §13, and this engine must not assume it has been closed;
only the operative current state. The guarantee is bounded: `audit-core` is
not WORM or object-locked, and its tamper evidence is conditional on live
preconditions. Stronger custody is decided against (§16); this engine must
not assume it has been reopened;
- **credentials** materialized after a decision — `secrets-engine`;
- **maturity, readiness, or progression of anything**`maturity-engine`.
- **maturity, readiness, or progression of anything**`maturity-engine`;
- **an unreachable-engine stance map** — this engine is not PEP-shaped. It
does not cause a protected side effect on the far side of a decision. Callers
that do are PEP-shaped and owe companion §5 / statute §6.4;
- **Railiance operational axes** — an approval is not a workload (§20.1). How
those axes meet this model beyond §20's first statement is unwritten; do not
assume a mapping.
The repository's seed README described this as "an engine for modelling and
managing decisions". That wording is withdrawn: **decision** is `access-engine`'s
@ -173,7 +261,8 @@ word under standard §8, and this engine must never claim it.
## Design Principles
1. **Binary at the point of use.** Valid or not, consumed or not. No grades.
1. **PIP, never PDP.** Valid or not, consumed or not. No grades, and no
"may this actor do X".
2. **Atomic or it does not count.** Supersession and consumption are
compare-and-swap operations, never read-then-write.
3. **The evaluator is not the owner.** `access-engine` reads; it does not mutate.
@ -181,11 +270,16 @@ word under standard §8, and this engine must never claim it.
is one claim the decision point weighs.
5. **Revocation beats cooperation.** An approval can be killed without the
holder's participation.
6. **Every transition is evidence, atomically.** Issuance, use, supersession,
and revocation reach `audit-core` in the same transaction that made them
true. An event that can be lost is a state change that never happened, as far
as anyone auditing can tell.
7. **Small on purpose.** Scope growth here is a security regression.
6. **Every transition is evidence, atomically, and locally.** Issuance, use,
supersession, and revocation are queued in this engine's own store in the
same transaction that made them true. An event that can be lost is a state
change that never happened, as far as anyone auditing can tell.
7. **Atomicity prevents accidents; it does not prevent a compromised source.**
Cadence for load-bearing classes is a heartbeat or a reconciliation, and it
is a MUST.
8. **Consumption is a mutation.** Inferring it from a decision record is a
defect.
9. **Small on purpose.** Scope growth here is a security regression.
## Non-Goals
@ -194,6 +288,7 @@ word under standard §8, and this engine must never claim it.
- Not an approvals *inbox* or notification surface.
- Not an audit archive.
- Not a general state-machine service for other concepts.
- Not a Railiance axis, a PEP, or an actuation surface.
## What Would Make This Repository Wrong
@ -208,6 +303,15 @@ word under standard §8, and this engine must never claim it.
- **Emission is best-effort.** If a revocation can succeed while its event is
lost, the evidence half is silently incomplete and the most security-relevant
transition is the one most likely to vanish.
- **It claims the outbox closes omission.** Atomicity covers crash. Treating it
as covering a compromised source, or skipping the heartbeat, is the v0.6
overclaim this engine must not reintroduce.
- **It implements consumption by guessing.** The three races are named and
unowned. Code that picks a side is a contract with `access-engine` that
`access-engine` has not assented to.
- **It cites observation or containment that has not happened.** Nothing is
observed in production, and nothing can be contained automatically
(companion §10).
## Success Criteria
@ -221,6 +325,9 @@ word under standard §8, and this engine must never claim it.
5. no state change can be committed without its event — demonstrated by a test
that fails the transaction when emission fails, not by inspection, and with
the queue local so an `audit-core` outage never blocks a revocation;
6. the claim carries a binding digest, and a decision rendered against approval
A for request R cannot be replayed for request R';
7. `FLEX-WP-0017` T03 and T05 are unblocked.
6. the claim carries a binding digest, issuer, and freshness, and a decision
rendered against approval A for request R cannot be replayed for request R';
7. load-bearing classes declare a heartbeat or reconciliation, and divergence
from `audit-core`'s event count is a finding;
8. consumption is not implemented until `GH-WP-0002-T06` settles the contract;
9. `FLEX-WP-0017` T03 and T05 are unblocked.