diff --git a/docs/flex-auth-request-list-action.md b/docs/flex-auth-request-list-action.md new file mode 100644 index 0000000..bae2000 --- /dev/null +++ b/docs/flex-auth-request-list-action.md @@ -0,0 +1,114 @@ +# Request to flex-auth: a `list` action for the decision overview + +**From:** informed-decision (`INFD-WP-0004`, intake `INFD-IN-0008`) +**To:** flex-auth, as the owner of the `informed-decision.*` policy packages +**Date:** 2026-09-21 +**Status:** draft, not yet sent + +## What we ask + +Please admit a policy for a new consumer action, **`list`**, on +`decision-memo` resources of system `informed-decision`. The identity bar for +`list` should allow comfortable browsing, and it should cover the memos of +**both** admitted packages (`informed-decision.t03-review` and +`informed-decision.compact-sitting`). This repository proposes the rule; +flex-auth decides it. Nothing here grants anything until you publish a +package, version and digest. + +## Why + +`INFD-WP-0003` put a decision overview on the signed-in home page. Each row +asks Flex Auth for `read`, the same action that gates rendering a memo for +binding. Since 2026-09-21 the review deployment points at +`informed-decision.compact-sitting` v2. In production this has two +consequences: + +1. **Every row is refused, even after the operator signs in again.** The + `read` rule requires `age <= 900` on `assurance.at`. KeyCape copies the + previous session's timestamp even after an actual MFA (`INFD-IN-0005`). + Authelia 4.38 cannot be made to force reauthentication (`cbea539`). So a + browsing session usually cannot meet a bar designed for binding. + Confirming this against the live policy observations is pending. +2. **The three `SECRETS-WP-0010-T03-*` memos are out of scope for good.** They + were admitted under `informed-decision.t03-review`. The served sitting + package does not name them, so their own reviewer cannot see their outcome. + +Looking back at your own decisions should not need to meet the bar for signing +a new one. Binding keeps its strict bar. Only the list gets a lighter one. + +## The consumer contract for `list` + +The request shape is unchanged (`docs/flex-auth-review-contract.md`): the same +closed profile, caller, subject object and memo resource, and the same +`context` (`memo_version`, `approval_id`, `approval_binding_digest`). Only +`action` is `"list"`. It is one request per memo row. There is no wildcard and +no collection resource. + +After an `allow` for `list`, the consumer shows **only** the following: + +- memo id and version, and the memo's question; +- the live Approval Engine status, read by the approval id the memo carries; +- the requesting person's own recorded responses on that memo: verb, memo + version, time and submission state. Notes are excluded. + +It does **not** show the brief, terms, justification, highlights, packet, +attachments or anyone else's responses. A `list` allow never enables +`acknowledge` or any disposition. Opening the memo for review still asks +`read`, and every act still asks its own action under the current strict rules. + +The consumer still requires `memo.binding.principal.id == subject` before it +asks. That structural match is not an entitlement. + +## Proposed rule + +Identity: the same as today, minus the freshness window. + +```rego +input.subject.type == "human" +input.subject.tenant == "tenant:platform" +input.subject.attributes.principal_type_source == "authentication-derived" +input.subject.attributes.tenant_source in {"registration-supplied", "directory-asserted"} +"net-kingdom-admins" in input.subject.attributes.groups +input.subject.attributes.assurance.level == "aal2" +input.subject.attributes.assurance.mfa == true +input.subject.attributes.assurance.source == "key-cape" +# no `age <= 900` for list +input.action == "list" +``` + +For the resource, the owner can choose between two scopes: + +- **(A) Resource-type-wide.** This covers any `decision-memo` of system + `informed-decision` in `tenant:platform`. It needs no package revision per + sitting. It relies on the consumer's structural recipient match to keep other + people's memos out of a person's list. **The consumer prefers this option + for comfort.** +- **(B) Exact-record union.** This covers the eight sitting records plus the + three T03 records, pinned by approval id and binding digest as today. It is + tighter. It needs a new version every time a sitting adds memos. It would + also need to accept T03's memo version 2, whereas the sitting rule pins + `memo_version == 1`. + +Either option could ship as a new version of the served sitting package (v3), +which also keeps `read` and every act exactly as in v2. It could also ship as +a separate package, but then the consumer would need a second PDP pin, because +the runtime carries only one package pin today. The consumer prefers **v3 of +`informed-decision.compact-sitting`**. + +## What informed-decision delivers on its side + +- `list` in `policy.ACTIONS` and in the consumer contract document; +- an overview that asks `list`, shows only the fields above, and still asks + `read` on the review page; +- positive and negative fixtures for flex-auth: stale MFA allowed for `list` + but refused for `read`; no group refused; agent refused; and, under option + (B), an unlisted memo refused; +- after your package lands, the admission input is updated to the new + package, version and digest, and the rollout is recorded. + +## Disclosure trade-off (for the owner to weigh) + +With option (A), a person holding any AAL2 session in `net-kingdom-admins` can +see the questions and statuses of memos addressed to them, without a +15-minute-fresh MFA. Today that needs fresh MFA. Brief, packet and all binding +stay behind the strict bar. diff --git a/intakes/intakes.md b/intakes/intakes.md index f7d0a8f..d21e4eb 100644 --- a/intakes/intakes.md +++ b/intakes/intakes.md @@ -443,3 +443,34 @@ description: >- repository takes Staff either way and is not asking to be moved. state_hub_intake_id: "01a0c23e-bd53-7ee0-9357-b223aa554842" ``` + + +## INFD-IN-0008 — Admit a `list` action so decisions can be reviewed comfortably + +```yaml +id: INFD-IN-0008 +kind: intake +title: Admit a `list` action so decisions can be reviewed comfortably +status: open +origin: demand +origin_ref: INFD-WP-0004 +priority: high +owner: flex-auth +repo: informed-decision +lane: blue +tags: +- cross-repo +- policy-request +created: '2026-09-21' +updated: '2026-09-21' +description: >- + The INFD-WP-0003 decision overview asks Flex Auth for `read` on each memo, and + the served compact-sitting v2 package refuses every row in production. Its + 900-second MFA window is designed for binding, and KeyCape carries forward + earlier authentication timestamps (INFD-IN-0005). It also does not name the + three SECRETS-WP-0010-T03 memos. ASK: admit a `list` action with the same + identity bar minus freshness. It should cover memos from both admitted + packages, preferably as compact-sitting v3 with a resource-type-wide scope. + `read` and every act stay unchanged. Full request, disclosure limits and + fixtures: docs/flex-auth-request-list-action.md. +``` diff --git a/workplans/INFD-WP-0004-comfortable-decision-review.md b/workplans/INFD-WP-0004-comfortable-decision-review.md new file mode 100644 index 0000000..8cf4f68 --- /dev/null +++ b/workplans/INFD-WP-0004-comfortable-decision-review.md @@ -0,0 +1,100 @@ +--- +id: INFD-WP-0004 +type: workplan +title: "Comfortable decision review — a `list` action for the overview" +domain: infotech +repo: informed-decision +status: active +owner: claude +topic_slug: netkingdom +created: "2026-09-21" +updated: "2026-09-21" +related: + - INFD-WP-0003 + - INFD-IN-0005 + - INFD-IN-0008 +origin: demand +origin_ref: "founder 2026-09-21: 'We should be able to review comfortably though.'" +--- + +# Comfortable decision review + +The `INFD-WP-0003` overview is live, but in production every row shows "The +permission service refused access", even after a fresh sign-in. Each row asks +Flex Auth for `read`. The served `informed-decision.compact-sitting` v2 +package gates `read` with a bar designed for binding: + +- The rule requires `assurance.at` to be at most 900 seconds old. KeyCape + carries earlier authentication timestamps forward (`INFD-IN-0005`), so a + browsing session rarely meets it. +- The package does not name the three `SECRETS-WP-0010-T03-*` memos at all. + +The founder wants to be able to review decisions comfortably. The plan is to +split *seeing your decisions* from *reviewing one for binding*: + +- Add a new consumer action, `list`, with limited disclosure. It has a + comfortable identity bar, and flex-auth admits it. +- `read` and every act keep their strict bar. + +## Establish why today's rows are refused + +```task +id: INFD-WP-0004-T01 +status: wait +priority: high +``` + +Waiting on the operator's read-only query of the live `policy_observations`: +`auth_age_s`, groups, level and methods for the latest checks. If the age is +over 900, `INFD-IN-0005` is confirmed as the cause for the eight sitting memos. +If a group, level or method differs from the rule, that is a separate identity +regression and needs fixing regardless of `list`. Record the finding under +`docs/evidence/`. + +## Request the `list` policy from flex-auth + +```task +id: INFD-WP-0004-T02 +status: progress +priority: high +``` + +The request is drafted in `docs/flex-auth-request-list-action.md` and recorded +as `INFD-IN-0008`, owned by flex-auth. Send it to the flex-auth inbox once the +founder approves the draft. Done when flex-auth publishes a package, version +and digest that answers `list`, with fixtures. + +## Consumer side: `list` action and limited-disclosure overview + +```task +id: INFD-WP-0004-T03 +status: todo +priority: high +``` + +- Add `list` to `policy.ACTIONS` and to `docs/flex-auth-review-contract.md`. +- The overview asks `list` per row instead of `read`. It renders only the memo + id and version, the question, the live engine status, and the person's own + responses (verb, version, time and submission state; no notes). +- The review page keeps `read`, and every act keeps its own action. +- Tests: `list` allowed while `read` is denied still shows the rows, and + opening one is still refused; a `list` deny redacts the row; no brief, + packet or notes leak on the home page. + +This task can be built and tested against fixtures before T02 lands, but it +must not be deployed before T02. The live v2 package denies `list`, so +deploying early would change nothing visible. + +## Admit and roll out + +```task +id: INFD-WP-0004-T04 +status: wait +priority: high +``` + +After T02, update `deploy/sitting-admission.json` with the new package, +version and digest. The operator then applies the configuration and the image +built from T03. Verify that the overview shows all eleven memos without a fresh +MFA, that opening a memo still enforces the strict `read` rule, and record the +rollout in `docs/evidence/`.