informed-decision/docs/keycape-sitting-requester-registration.md
tegwick 12311d196c Sitting requester: allow approval:read, keep approve/consume refused
key-cape 82b471f prepares approval:read on informed-decision-sitting-requester
for present_existing intake reads (INFD-WP-0010). The registration doc, JSON
and test no longer forbid read (applied state stays create-only; read is
recorded as preparedScopes), and create_sitting_approvals checks only
approve and consume, so it keeps working once read is live.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 5502@bnt-lap001
Assistant-Session: 68b3b02f-5d0f-4e71-8421-796f62e50196
2026-11-01 04:02:50 +01:00

85 lines
3.9 KiB
Markdown

# Sitting requester — create-only client (requested, not applied)
**Workplan task:** `INFD-WP-0002-T03`
**For:** `key-cape` (same registration shape as `secrets-engine-requester`)
**Copied to:** `approval-engine` (`docs/keycape-service-registrations.md` —
“no requester identity has been settled for `approval:create`”)
**Status:** **applied 2026-09-15** (CCR-2026-0026/0027, KeyCape row live,
create-only exchange proof verified). No secret is in this repository.
Sittings are still INFD-WP-0002; platform did not POST. Attended create:
`tools/create_sitting_approvals.py`.
This is the missing presenter for compact Decision Memo sittings whose
protected side effect is a **work-record update** (`INFD-WP-0002-T04`), not a
PEP consume.
## Why a second client
`informed-decision-approver` is the **human** browser client
(`approval:read` + `approval:approve`). Humans cannot `POST /v1/approvals`.
`secrets-engine-requester` is create-only with `sub=secrets-engine` and must
not draft WSL2 retirement, clock ownership, or mason plan accepts —
`binding.actor` has to match the authenticated subject.
This client names the presenter for *this* sitting.
## The strings
| Field | Value |
| --- | --- |
| `client_id` | `informed-decision-sitting-requester` |
| Grant | `client_credentials` |
| Client type | confidential |
| Audience | `approval-engine` (resource server, never the OAuth client id) |
| Scopes | `approval:create`, plus `approval:read` once key-cape `82b471f` is applied; never approve or consume |
| `serviceSubject` / token `sub` | `informed-decision` |
| `tenant` | `tenant:platform` (exact) |
| `principal_type` | `service` |
| Role | `informed-decision-sitting-requester` |
| Token lifetime | 15m |
| Redirect URI | **none** — this is not a browser client |
Machine-readable copy: `keycape-sitting-requester-registration.json`.
`secretRef` is a custody *name*. It is not a credential.
## Anti-requirements
- **No** `approval:approve`. That stays on the human PKCE client.
- **No** `approval:consume`. Consumption belongs to a PEP. This sitting's
T04 path is repo files + `fix-consistency`.
- `approval:read` is **allowed** (changed 2026-11-01). present_existing intake (INFD-WP-0010) GETs an
approval another actor created before presenting it. Prepared in key-cape `82b471f` (source only); the live
registry still holds `approval:create` alone until the founder-run change. `allowedScopes` in the JSON copy
records the applied state; `preparedScopes` records the pending one. Approve and consume stay refused, and
`tools/create_sitting_approvals.py` checks only those two.
- Do **not** reuse `approval-engine-operator` (cancelled bundle, too wide).
- Do **not** reuse `secrets-engine-requester` for unrelated acts.
- Do **not** register this client until `key-cape` owns the row and
`railiance-platform` owns attended secret custody. This document is not
admission.
## Binding rules at create time
`POST /v1/approvals` requires `binding.actor ==` the token `sub`, so actor is
always `informed-decision`.
| Binding field | Value for this sitting |
| --- | --- |
| `actor` | `informed-decision` |
| `principal` | owning system of the work record (not the human, not this client by default) |
| `action` / `purpose` / `target` | one memo, one act — see `docs/batches/2026-09-14/approval-create-intents.json` |
| `human_control` | `true` |
| `pdp_path` | `false` — no consume PEP on T04 |
| `required_count` | 1 |
`infd-20260914-c01` (SECRETS-WP-0010 native delivery) may belong on
`secrets-engine-requester` instead if a later consume is in-scope. It is
marked undecided in the intents file. Do not POST it on this client until
that is stated.
## What this does not do
It does not bind. It does not admit Flex Auth. It does not load the review
store. After KeyCape registers the row and platform materializes custody,
an attended create can mint the eight (or seven) objects; then
`tools/attach_compact_bindings.py` with the operator's live KeyCape `sub`.