user-engine/docs/evidence-classification.md
tegwick 4349758608
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Build and Publish Container Image / build-and-push (push) Successful in 36s
Implement USER-WP-0024 security layer conformance
Declare Engine/PIP machine-readably, publish a total fail-closed PEP
stance map, stop minting local decision ids on engine-unavailable DENY,
bind allows to a 30s request lifetime, confine the local authorization
double, classify evidence and emit a denial/revocation heartbeat, and
prove access-control facts remain claims.

Assistant: grok
Assistant-Session: 01a04cea-f0d6-7ab3-9ffd-881eb6bea6cb
2026-08-29 12:53:16 +02:00

46 lines
1.9 KiB
Markdown

# Local evidence classification
Status: implemented
Updated: 2026-08-29
Standard: `net-kingdom/canon/standards/security-layer-model_v0.7.md` §9.6
Companion: `net-kingdom/SECURITY-COMPANION.md` §6
Local audit records and the durable outbox prove the records they hold
were **not altered or truncated after arrival**. They do not prove that
an event never sent did not happen.
Sound sentences:
- the archive proves the records it holds were not altered or truncated after arrival
- absence of a record is not evidence of non-occurrence
Unsound sentences, not used here:
- the audit record proves it happened
- there is no record, so it did not happen
- the trail is complete
## Classification
| Kind | Test | Local form |
| --- | --- | --- |
| **Load-bearing** | a control's soundness depends on the event being present | authorization denials; `account.status_changed`; `tenant_account.status_changed`; `prepared_account.revoked`; `family_invitation.revoked` |
| **Attributive** | forensic reconstruction; no control branches on presence | user/profile/membership-added/catalog/registration/hat events |
| **Heartbeat** | positive claim that can itself go missing | `user_engine.evidence.heartbeat` |
Successful mutations enqueue local audit and outbox in the same store
transaction. That prevents accidental omission (crash between save and
emit) of the *local* record. Drain to `audit-core` is after commit.
## Cadence
Rate monitoring cannot detect suppression of rare denials and
revocations. The required form is a **heartbeat**:
`UserEngineService.record_evidence_heartbeat()` emits a positive claim
with counts of load-bearing classes already on the local trail. The
payload sets `completeness_claimed: false`. Expected interval: one hour
when a drain loop is running. The heartbeat is the claim that can go
missing; it is not a completeness proof.
Adversarial omission at a compromised source is a known residual.
Nothing in this model prevents it.