Declare layer.yaml, add a Python engine over a local SQLite store, and cover deterministic assessment, the §13 gap register, stance-map inventory, claim guardrails, and the gate-house review path with tests. Assistant: grok Assistant-Session: 01a04ceb-150e-7e80-a542-ec8b1372e164
56 lines
1.9 KiB
Markdown
56 lines
1.9 KiB
Markdown
# Maturity level claim contract
|
|
|
|
`maturity-engine` is a PIP. A computed level leaves this engine only as a
|
|
**request claim** (or as a versioned policy rule authored elsewhere). It is
|
|
not an authorization decision.
|
|
|
|
Statute: `security-layer-model` v0.7 §6.2, §9.5.
|
|
|
|
## Claim shape
|
|
|
|
```json
|
|
{
|
|
"kind": "maturity-level",
|
|
"issuer": "maturity-engine",
|
|
"subject": "ops-warden",
|
|
"model_id": "asm",
|
|
"model_version": "0.3",
|
|
"level": 1,
|
|
"level_id": "ASM-1",
|
|
"assessed_at": "2026-08-29T12:00:00Z",
|
|
"assessment_id": "<uuid5 of canonical inputs>",
|
|
"freshness_rule": "assessment evaluated_at plus limiting evidence valid_until",
|
|
"digest": "<sha-256 of the claim without this field>"
|
|
}
|
|
```
|
|
|
|
`access-engine` consumes this object as an input claim. Reconstructability
|
|
is from the decision record that names the claim digest, not from a registry
|
|
row.
|
|
|
|
## Forbidden
|
|
|
|
- Compiling a level into registry content. Until `access-engine` decision
|
|
provenance carries a registry-snapshot digest, a level that reached a
|
|
decision through the registry is not reconstructable. The engine raises
|
|
`GuardrailError` on `compile_into_registry`.
|
|
- A consumer branching on a fetched level (`if level >= 3: allow`). That is
|
|
a second decision point. The engine raises `GuardrailError` on
|
|
`gate_on_level`.
|
|
- Any `authorize` / `decide` / `may` surface on this engine.
|
|
|
|
## Evidence bound
|
|
|
|
Assessment records are **load-bearing** once consumed as claims: emission is
|
|
queued in this engine's local SQLite outbox in the same transaction as the
|
|
state change. No synchronous `audit-core` call sits inside that transaction.
|
|
|
|
The archive proves records were not altered or truncated after arrival. It
|
|
does not prove an event never sent. Absence of a record is not evidence of
|
|
non-occurrence.
|
|
|
|
Rare load-bearing classes use a **heartbeat** (`maturity-engine heartbeat`
|
|
via `Engine.heartbeat`), not a rate.
|
|
|
|
Gap-register mutations are **attributive** unless a control's soundness
|
|
depends on their presence.
|