informed-decision/workplans/INFD-WP-0003-my-decisions-overview.md

130 lines
5.2 KiB
Markdown
Raw Normal View History

---
id: INFD-WP-0003
type: workplan
title: "My decisions overview — pending memos and the outcome of past dispositions"
domain: infotech
repo: informed-decision
status: finished
owner: claude
topic_slug: netkingdom
created: "2026-09-21"
updated: "2026-09-21"
related:
- INFD-WP-0001
- INFD-WP-0002
origin: demand
origin_ref: "founder request 2026-09-21: review decisions taken, whether they were accepted, and which are still open"
state_hub_workstream_id: "d47a50d6-d429-5018-8858-f721023ca579"
---
# My decisions overview
Founder request 2026-09-21: in the informed-decision UI, see (a) the
decisions I have taken and whether they were accepted, and (b) the decisions
still open for me to take.
Today the signed-in home page offers only a free-text memo-identifier box
(`informed_decision/web.py`, `GET /`). A person has to already know each memo
id, and nothing shows the outcome of a past disposition unless that exact
review is reopened.
## Why this does not breach the Stage 1 boundaries
- **Not an approval-engine inbox.** The list is built from memos that
informed-decision itself holds, addressed to the signed-in subject
(`memo.binding.principal.id`). approval-engine is still called get-by-id
only, for approval ids those memos already carry. It never polls for work.
- **Not owned approval state.** Engine status is read live on each render and
never stored. Local state is limited to our own evidence: the disposition and
the submission correlation (`submissions.state`, `approved_at`).
- **Not a decision point.** The overview decides nothing. Every row goes
through the same fresh PDP `read` check that `ReviewController.open` uses
before any memo content is rendered. If that check is denied or unavailable,
the row shows the memo id and "not available" and nothing else (fail closed).
- **Not a binding view.** The overview creates no presentation record.
Binding still happens only on the existing review page.
## Row classification (latest memo version, addressed to me)
| Group | Condition |
|---|---|
| **Needs attention** | submission `in_flight` / `unresolved`: outcome unconfirmed, operator recovery |
| **Open for you** | no accept/decline by me on the latest version, no submission, engine status `requested`/`approved` |
| **Decided — accepted** | submission `confirmed` (show `approved_at`) plus live engine status (`approved`, `consumed`, …) |
| **Decided — declined** | decline disposition on the latest version |
| **Returned / discussion** | return/discuss on the latest version with no newer version yet (awaiting revision) |
| **Closed without you** | engine status `expired`/`revoked`/`superseded` and no disposition by me |
Each row links to the existing review (`/review?memo_id=…`), which already
recovers the original presentation when an intent exists. The earlier
dispositions on older memo versions appear as a short history under the row.
## Store listing for the signed-in subject
```task
id: INFD-WP-0003-T01
status: done
priority: high
state_hub_task_id: "2b878f29-492a-5187-a594-36a12aaa932d"
```
Add `Store.memos_for(subject)`, which returns the latest version of every memo
whose binding principal is `subject` (a `person`). Add
`Store.dispositions_by(subject, memo_id)`, which returns that subject's
dispositions across all versions, together with any submission row. This is
read-only. Tests go in `tests/test_durable_store.py`.
## Controller overview with per-row PDP read and live engine status
```task
id: INFD-WP-0003-T02
status: done
priority: high
state_hub_task_id: "b4172f0c-7cd3-5780-bf50-62670df7e416"
```
Add `ReviewController.overview(session)`, which returns classified rows. Each
row gets its own `_authorize(session, memo, "read")` and `get_approval`. A row
whose PDP check fails is redacted to its id only. A failure of the approval
engine on one row only degrades that row's status to "status unavailable". It
never degrades the whole page. The overview never creates a presentation. Tests
go in `tests/test_review_controller.py`, using the existing fakes: allow, deny,
policy unavailable, engine down, and each classification.
## Home page rendering
```task
id: INFD-WP-0003-T03
status: done
priority: high
state_hub_task_id: "b0dfae8b-e8f8-5257-b275-8d486a067c6b"
```
When a review is configured and the person is signed in, `GET /` renders the
overview grouped as above, with open items first. The manual memo-id form stays
below the overview as a fallback. This is server-rendered only: no scripts, the
same CSP, all text escaped. Tests: a WSGI test in `tests/test_browser_auth.py`
or `test_review_component.py`, plus one Chromium check in
`tests/browser_review.mjs` if that harness is cheap to extend.
## Docs and scope
```task
id: INFD-WP-0003-T04
status: done
priority: medium
state_hub_task_id: "6c38b102-943d-5bde-96ac-3e15e2e8e8ab"
```
Update `docs/protected-browser-review.md` and `SCOPE.md` with the overview and
the boundary argument above.
## Outcome — 2026-09-21
All four tasks are done. After sign-in, `GET /` shows the grouped overview
above the memo identifier form. There are 432 automated tests with actual
Approval Engine, Audit Core and Flex Auth, and 13 Chromium checks.
There are no actionable residuals. Deployment of the surface stays with
`INFD-WP-0001-T08` and the deployment packet. It is not new work from this plan.