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
This commit is contained in:
parent
c7b6148a70
commit
4349758608
22 changed files with 1242 additions and 89 deletions
46
docs/evidence-classification.md
Normal file
46
docs/evidence-classification.md
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
# 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.
|
||||
Loading…
Add table
Add a link
Reference in a new issue