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
|
|
@ -4,7 +4,7 @@ type: workplan
|
|||
title: "Security layer model conformance for Engine/PIP"
|
||||
domain: communication
|
||||
repo: user-engine
|
||||
status: active
|
||||
status: finished
|
||||
owner: grok
|
||||
topic_slug: netkingdom
|
||||
created: "2026-08-29"
|
||||
|
|
@ -52,7 +52,7 @@ by itself make the runtime conforming.
|
|||
|
||||
```task
|
||||
id: USER-WP-0024-T02
|
||||
status: todo
|
||||
status: done
|
||||
priority: high
|
||||
state_hub_task_id: "2874fd05-5b54-5812-9e89-2832408e488b"
|
||||
```
|
||||
|
|
@ -65,46 +65,33 @@ claim input), and the path of the PEP stance map. Adapt
|
|||
undeclared OpenBao, Vault, LDAP, or cluster client fails the commit that
|
||||
introduces it.
|
||||
|
||||
Do not add a Tooling client to have something to declare.
|
||||
|
||||
**Done when:** `layer.yaml` is the machine-readable declaration, the
|
||||
checker exits 0 on the current tree, and a test covers the empty
|
||||
Tooling-contact claim.
|
||||
Done 2026-08-29. `layer.yaml`, `scripts/check_layer_conformance.py`, and
|
||||
`tests/test_layer_conformance.py`. Checker exits 0; a synthetic `hvac`
|
||||
import fails the scan.
|
||||
|
||||
## T03 — PEP obligations on the production path
|
||||
|
||||
```task
|
||||
id: USER-WP-0024-T03
|
||||
status: todo
|
||||
status: done
|
||||
priority: high
|
||||
state_hub_task_id: "caf7ef66-d221-5548-947b-17b5ff1865ee"
|
||||
```
|
||||
|
||||
Ship the four §6.4 obligations for this PEP-shaped Engine:
|
||||
Ship the four §6.4 obligations for this PEP-shaped Engine.
|
||||
|
||||
1. Publish `pep-stance.yaml` (total, no implicit default). Production
|
||||
remains fail-closed, including unknown. A test asserts the file equals
|
||||
`FlexAuthHTTPAdapter` behaviour.
|
||||
2. On engine-unavailable DENY, record stance application (scope, failure
|
||||
mode, outcome). `decision_id` is present only when flex-auth rendered
|
||||
a decision. Stop minting a local id via `AuthorizationDecision`'s
|
||||
default factory on that path.
|
||||
3. Give `AuthorizationDecision` an explicit lifetime (TTL or
|
||||
session/obligation binding). Do not add a verdict cache.
|
||||
4. Confine `LocalAuthorizationCheckPort` to tests and standalone
|
||||
fixtures. Production `create_application()` must be unable to
|
||||
construct a default-allow adapter.
|
||||
|
||||
**Done when:** the published map matches shipped fail-closed behaviour,
|
||||
unavailable DENY audits carry no engine decision id, allows carry a
|
||||
lifetime, and the local port cannot enter the production runtime
|
||||
assembly.
|
||||
Done 2026-08-29. `pep-stance.yaml` is total fail-closed including unknown
|
||||
and equals `user_engine.pep_stance`. Unavailable DENY sets
|
||||
`stance_applied` and `decision_id=None`. Allows are request-bound with a
|
||||
30s lifetime. `LocalAuthorizationCheckPort` raises when
|
||||
`USER_ENGINE_FLEX_AUTH_TOKEN_FILE` is set; `runtime.py` does not import
|
||||
it.
|
||||
|
||||
## T04 — Evidence bound and cadence
|
||||
|
||||
```task
|
||||
id: USER-WP-0024-T04
|
||||
status: todo
|
||||
status: done
|
||||
priority: medium
|
||||
state_hub_task_id: "b4cebd66-21d0-5a6d-b718-971af70bebb6"
|
||||
```
|
||||
|
|
@ -113,30 +100,30 @@ Classify local audit and outbox events as load-bearing or attributive.
|
|||
Keep mutation+audit+outbox atomic in the store transaction (already
|
||||
true). For denials and membership/account revocations — low-volume
|
||||
load-bearing classes — declare a heartbeat or reconciliation, not a
|
||||
rate. Update `docs/evidence-gap-examples.md` and operability copy so the
|
||||
trail is never described as complete, and so absence of a record is not
|
||||
read as non-occurrence.
|
||||
rate.
|
||||
|
||||
**Done when:** the classification is in-repo, the heartbeat or
|
||||
reconciliation form is named, and docs use the sound evidence sentences.
|
||||
Done 2026-08-29. `src/user_engine/evidence.py`,
|
||||
`UserEngineService.record_evidence_heartbeat()`,
|
||||
`docs/evidence-classification.md`. Operability copy no longer says
|
||||
audit correlation completeness.
|
||||
|
||||
## T05 — Access-control facts remain claims
|
||||
|
||||
```task
|
||||
id: USER-WP-0024-T05
|
||||
status: todo
|
||||
status: done
|
||||
priority: medium
|
||||
state_hub_task_id: "f1ac9244-0639-5e97-8981-babdbe8991e5"
|
||||
```
|
||||
|
||||
Prove under statute §6.1 that hats, access profiles, and
|
||||
`AccessControlFact` exports cannot be mistaken for an authorization
|
||||
decision. Add a test that selection and export never return allow/deny.
|
||||
Document the consumer contract: compiling those facts into a local
|
||||
decision is an early decision and is forbidden.
|
||||
decision.
|
||||
|
||||
**Done when:** a test and the hats/boundary docs state the claim
|
||||
contract, and no user-engine API on that path exposes an effect.
|
||||
Done 2026-08-29. `tests/test_evidence.py` forbids effect fields on claim
|
||||
shapes and asserts hat selection and export never return allow/deny.
|
||||
`docs/hats-realms-services-assets-access-profiles.md` states the
|
||||
consumer contract.
|
||||
|
||||
## T06 — Close the intake and request the stance-map row
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue