--- id: INFD-WP-0003 type: workplan title: "My decisions overview — pending memos and the outcome of past dispositions" domain: infotech repo: informed-decision status: proposed 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: todo 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: todo 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: todo 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: todo 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.