access-engine/workplans/FLEX-WP-0035-per-identity-application-readback.md
tegwick 9d9ca69b4c
All checks were successful
CI Smoke / host-smoke (push) Successful in 1s
CI Smoke / container-smoke (push) Successful in 2s
FLEX-WP-0035: activate; draft application access readback contract and FLEX-DEC-2026-019
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 609675@bnt-lap001
Assistant-Session: 4987a36e-eb38-4b10-803c-15a29cd78212
2026-10-09 19:11:55 +02:00

115 lines
4.5 KiB
Markdown

---
id: FLEX-WP-0035
type: workplan
title: "Per-identity application access readback and readable protected-system registry for user-engine"
domain: infotech
repo: access-engine
status: active
owner: claude
topic_slug: netkingdom
created: "2026-10-09"
updated: "2026-10-09"
related: [USER-WP-0026, USER-WP-0028]
state_hub_workstream_id: "cb9755fa-6824-5288-81c4-3aa2fbff1a9f"
---
user-engine (message `f1637c32`, 2026-10-09, routed by net-kingdom `19a0cbcd`)
needs to show a signed-in person which applications they can use. Its
`USER-WP-0026-T03` and `USER-WP-0028-T02` are `blocked_on` access-engine. The
PEP stance is already fail-closed: no decision renders `unavailable`, and allow
is never inferred from membership, platform role, registration, or a missing
record.
## What exists today (2026-10-09 review)
- `POST /v1/batch_check` takes several resources in one call and returns one
decision per resource, each with a `lifetime` (`expires_at`) per the decision
envelope. Shape-wise this is close to request (1).
- Caller auth authorizes the caller token against **every** `resource.system`
in the batch (`cmd/flex-auth/main.go`, `/v1/batch_check`). The
`flex-auth-user-engine` caller is bound to its own protected system, so a
readback across other systems is a 403 today. That is correct behaviour for
enforcement, and the reason this needs design rather than a config change.
- There is no generic "may use this application" action. Each package has its
own action vocabulary, so "access to system X" has no defined meaning yet.
- There is no registry read endpoint. The protected-system registry is loaded
from files and never served.
## Define the readback contract
```task
id: FLEX-WP-0035-T01
status: progress
priority: high
state_hub_task_id: "0585a684-d462-5caa-937f-b1730efddbd8"
```
Decide the action that a readback evaluates per system: a declared
`application.access` action each consumer package must opt into, versus a
per-system mapping held in the registry. A system that declares nothing is
returned as `not_applicable`, never allow. State per input class the
revocation-visibility deadline the readback carries (§9.7). Decide whether the
readback is a decision for audit purposes (decision record, emission) or an
explicitly non-enforcing advisory read. A displayed allow must not be usable as
a PEP decision by another system.
Gate: written contract in `docs/` plus an ADR or decision record; reviewed with
user-engine before code.
2026-10-09: activated by the founder. Draft contract
`docs/application-access-readback.md` and `FLEX-DEC-2026-019` (proposed). Key
finding: each pin loads one consumer's package, so no existing pin can answer
across applications. The draft proposes a dedicated readback pin with
multi-package mode, a `purpose: "readback"` binding that keeps decisions
non-transferable, and a new optional `client_binding` manifest field. Sent to
user-engine with four review questions. The gate closes on their reply.
## Caller authorization for cross-system readback
```task
id: FLEX-WP-0035-T02
status: todo
priority: high
depends_on: [FLEX-WP-0035-T01]
state_hub_task_id: "eb0b6a91-7750-553b-b87f-c4262eb9df07"
```
Add a distinct caller capability (readback scope) instead of widening the
`flex-auth-user-engine` binding to other systems' check rights. The readback
caller must not be able to obtain a decision that another system's PEP would
accept, and its decisions must say so in the binding.
Gate: tests prove a readback-scoped token gets 403 on `/v1/check` for a foreign
system and is admitted only on the readback route.
## Readable protected-system registry
```task
id: FLEX-WP-0035-T03
status: todo
priority: medium
depends_on: [FLEX-WP-0035-T01]
state_hub_task_id: "5dbb3280-8490-58a5-a0bb-f3883e568f58"
```
Serve a read-only projection: system id, display name, key-cape client binding.
Include the registry-snapshot digest so the catalogue is tied to the same
snapshot that decisions record (G1, `FLEX-WP-0019`). Grants and revocations stay
inside access-engine; user-domain admins get no grant surface from this work.
Gate: endpoint plus schema, admitted only for the readback caller, tests.
## Deploy to the user-engine pin
```task
id: FLEX-WP-0035-T04
status: wait
needs_human: true
depends_on: [FLEX-WP-0035-T02, FLEX-WP-0035-T03]
blocking_reason: "Live pin change on railiance01 needs founder go."
priority: medium
state_hub_task_id: "82a8a7e6-54e9-5262-a271-24ce2f161362"
```
Roll the readback route and its caller binding onto `flex-auth-user-engine`,
then hand user-engine the evidence that unblocks `USER-WP-0026-T03`.