diff --git a/SCOPE.md b/SCOPE.md index 9250077..94814e7 100644 --- a/SCOPE.md +++ b/SCOPE.md @@ -4,15 +4,27 @@ > direction belongs in `INTENT.md`; the current stage belongs in `GOAL.md`; > current work and gates belong in `workplans/`. -## Status — 2026-09-11 +## Status — 2026-09-27 -**The protected browser review, policy consumer, Approval Engine adapter, -durable evidence store and scheduled Audit Core delivery are implemented. -The approval surface is not deployed.** +**Deployed and in live use.** `decisions.coulomb.social` serves +`forgejo.coulomb.social/coulomb/informed-decision@sha256:0557edff...` +in namespace `informed-decision` on railiance01, behind `key-cape` and the +`informed-decision.compact-sitting` Flex Auth package (currently v6). As +observed today: the durable evidence store carries 99 delivered audit events +and 15 confirmed human submissions; platform-root signed in and approved a +memo through this exact surface. This status was last "not deployed" on +2026-09-11 — everything below it in this section was written against a +production system, not a plan. -What exists and is tested (371 automated tests and 11 container checks; the -previous browser milestone passed 12 Chromium checks). Component tests use -actual Flex Auth, Approval Engine and Audit Core with synthetic identity/custody: +382 tests pass locally (66 skipped — the opt-in real-Approval-Engine suite, +`INFD_APPROVAL_ENGINE_SOURCE`); 440 pass with that suite enabled, 8 skipped. +11/11 container checks. The 2026-09-21 milestone passed Chromium 13/13 and +433 tests against real Flex Auth/Approval Engine/Audit Core; no newer +Chromium run has been recorded since. Four unrelated, pre-existing failures +persist in both configurations (`waitress` not installed locally; one +clock-adjacent browser-auth test) and are not this repository's regression. + +Component tests use actual Flex Auth, Approval Engine and Audit Core with synthetic identity/custody: - layer and stance declarations — `layer.yaml`, `pep-stance.yaml`, `informed_decision/stance.py`, with published-equals-shipped asserted; @@ -40,9 +52,14 @@ actual Flex Auth, Approval Engine and Audit Core with synthetic identity/custody accept/return/discuss/decline and visible original/unresolved entry state; - the **decision overview** on the signed-in home page (`INFD-WP-0003`): the reviewer's memos grouped as open, accepted, declined, returned, closed, - needing attention or not available. Each row has its own PDP read and a live - get-by-id engine status. The overview records nothing and never presents - or binds; + needing attention or not available. Each row now asks `list`, not `read` + (`INFD-WP-0004`) — a comfortable, 12-hour-fresh identity bar for *seeing* + your decisions, separate from the strict 900-second bar `read`/`accept`/etc. + keep for actually binding one. As of today each row also names the + **requesting party** — approval-engine's `binding.principal`, the party the + approval was issued on behalf of, distinct from the memo's own + `binding.principal` (the reviewer being bound). The overview records + nothing and never presents or binds; - `runtime.py` — explicit owner configuration, rotating credential-file readers, 30-second audit draining, heartbeat/reconciliation and delivery readiness. - `Containerfile`, `container.py`, `requirements.lock` and deployment renderer — @@ -50,30 +67,32 @@ actual Flex Auth, Approval Engine and Audit Core with synthetic identity/custody writer, backup/inspection commands and eight review-only Kubernetes objects. Network-isolated container restart/restore preserves unresolved submissions. -The 2026-09-11 fsGroup startup correction handles newly created private -directories on Kubernetes volumes; unsafe existing directories still refuse. -Its full local suite passes 335 tests with 39 optional checks skipped. The -corrected local image 92cde609 passes 11 container checks, and its source -adapter passes native audit delivery/retry/scope checks. Independent archive -readback, bearer lifecycle and service image scan/publication remain open. +The durable `Store` supplies transactional atomicity for every write path; +the legacy in-memory `evidence.Outbox` is a test double only, not part of the +deployed path. `/readyz` requires an owner runtime configuration and recent +audit delivery health — without either it returns 503 and rollouts are +refused by the readiness probe, not merely warned. -Remaining: native policy package/caller/assignment admission, registered human -login and deployed binding, independent production audit custody, image -publication/cutover, platform backup/restore and operator recovery admission. -The legacy `evidence.Outbox` remains an -in-memory test double; the new `Store` supplies durable atomicity. Browser -sessions are ephemeral, with no approval state. -Without owner runtime configuration `/readyz` returns 503. With it, readiness -requires recent audit delivery health; it does not assert native admission. -The origin's last observed deployment was an nginx placeholder on 2026-09-10. -See [browser-authentication.md](docs/browser-authentication.md) and +Two production incidents this repository did not cause, both diagnosed by +reading `policy_observations` directly on the live pod rather than guessing: +(1) `key-cape` was backdating a freshly-verified MFA to a stale `kc_login` +session cookie (`INFD-IN-0005`), and, separately, (2) `key-cape`'s +provider-metadata/JWKS discovery fetch was missing the split-horizon +`X-Forwarded-Proto`/`X-Forwarded-Host` headers its token exchange already +carried, which broke every login on Authelia 4.38 the moment a routine +restart hit that code path. Both are fixed and deployed in `key-cape` +(`911e9de`, `8be8065`); this repository's own review correctly treated both +as upstream `policy_denied`/`LoginError` outcomes to relay, not decide. + +See [browser-authentication.md](docs/browser-authentication.md), [durable-review-evidence.md](docs/durable-review-evidence.md) and -[protected-browser-review.md](docs/protected-browser-review.md). -The [deployment packet](deploy/README.md) records native wiring observations, -the missing Approval Engine namespace and remaining owner admission. - -`INFD-WP-0001-T08` remains open for the live end-to-end proof, which is gated on -`APPROVAL-WP-0002-T01` and a deployed `approval-engine`. +[protected-browser-review.md](docs/protected-browser-review.md). The +[deployment packet](deploy/README.md) documents the render/dry-run candidate +path; the actual live rollout is `docker build` → push to the Forgejo OCI +registry → pin the digest in `deploy/sitting-admission.json` → `kubectl set +image` (Recreate) → `kubectl exec` backup/inspect before and after, since +there is no CI pipeline in this repository (unlike `key-cape`'s Forgejo +Actions build-on-push). ## One-liner @@ -84,8 +103,26 @@ approver UI that `approval-engine` deliberately does not contain. ## Layer -**PEP-shaped**, ruled by `GH-DEC-2026-012`. Not an Engine. Companion §5 owed, -statute §6.4 in full. Declared in `layer.yaml` in this repository's own voice. +**Declared `layer: Staff`, role `pep-shaped`**, in `INTENT.md` frontmatter +(governing) and `layer.yaml` (derived, marked as such, agreeing) — +`GH-DEC-2026-017`, correcting the `layer: surface` this repository declared +by elimination from 2026-09-09 to 2026-09-21 (§3's vocabulary is closed at +four tokens; `surface` was never one of them). Not an Engine. Companion §5 +owed, statute §6.4 in full — `GH-DEC-2026-012`'s shape ruling is unchanged by +the layer correction. + +Open, no deadline, nothing waits on it: `INFD-IN-0007` asks how §3.4's +"Staff is interactive and non-deterministic, and MUST NOT hold state another +layer depends on at runtime" reaches a repository that is deterministic by +test and holds presentation evidence `audit-core` depends on. The value is +applied unconditionally either way; this asks only about the *fit*, for the +next repository in this position. Coupled to this repository's own requested +(not yet drafted) §4 catalog row. Separately, this repository approved two +narrow §11 declaration-form amendments on 2026-09-27 (`GH-DEC-2026-021`: A11 +r2 — `INTENT.md` frontmatter governs, a derived file must agree and disagreement +is itself a finding; A12 r3 — no version *pin* in a declaration, but a prose +citation like "outside §5 by the v0.5 scope rule" is provenance, not reached). +Both were already this repository's practice; approving changed no file. It emits one PIP-like fact — *what was presented* — as a claim, under three limits that are the substance of the permission rather than caveats on it: @@ -148,8 +185,12 @@ trail. - The evidence archive — `audit-core`. - Credentials materialized after a decision — `secrets-engine`. - Notification transport, ticketing, general workflow. -- **An approvals inbox.** Foreclosed upstream as well as here: - `approval-engine` exposes get-by-id only and will not add a list. +- **An approvals inbox backed by `approval-engine`.** Foreclosed upstream as + well as here: `approval-engine` exposes get-by-id only and will not add a + list. The decision overview (Status, above) is not this — it lists *this + repository's own memos*, sourced from the local `Store` plus a per-row + `list` PDP check and get-by-id engine status, never a listing capability + approval-engine itself provides. - L4/L5, QES, QTSP, qualified archival retention. - The mandate graph — so a Stage 1 `escalate` is an assertion, not a verified claim. @@ -159,9 +200,13 @@ trail. Stated here because a scope file that only lists capabilities overstates them. - **The decision path is not validated.** `GH-DEC-2026-010` requires a decision - be attributable to `access-engine`; no consumer can satisfy that today because - the envelope is unsigned (`FLEX-WP-0024`). This surface records - `decision_attributable: false` and must not describe validation as complete. + be attributable to `access-engine`. `FLEX-WP-0024` (finished, 2026-09-14) now + lets flex-auth sign an envelope when a key is configured — but this + repository does not verify a signature anywhere in `policy.py`, and + `store.py`'s schema hard-constrains `decision_attributable` to `0` + (`CHECK(decision_attributable=0)`). The gap flex-auth closed on its side is + still fully open on this one; nothing here must describe validation as + complete. - **The residual is open.** A compromised surface can present X and attest Y. `GH-DEC-2026-012` states it is not closed and does not credit this repository with closing it. @@ -177,18 +222,36 @@ Stated here because a scope file that only lists capabilities overstates them. state. `GH-DEC-2026-013` ruled directory-sourced terminal and admitted `key-cape`'s shape because its distinguishing case fails closed. Build to it as transitional. -- **Nothing is deployed**, so nothing is observed in production and nothing is - contained automatically. +- **Deployed does not mean contained.** This surface is live in production + and observed there (see Status), but that observation is manual — + `kubectl exec` plus `informed-decision-admin inspect`/`backup` around each + rollout. There is no automated post-deploy verification, no CI pipeline in + this repository, and no alerting wired to `/readyz` degrading. ## Open -- **Native browser registration and human proof** — T07 supplied the real - origin and submitted the contract. T08 retains registration rollout and a real - human login accepted by the deployed Approval Engine. -- **`audit-core` custody and live delivery** — source registration and cadence - have owner returns (`AUDIT-IN-0003`, `AUDIT-WP-0009` T04/T06/T07); native - credentials, independent receipt and reconciliation still require proof before - T08 ships. +- **`INFD-IN-0005`, narrowed.** The two live-blocking defects it predicted + (MFA backdated on reuse; a downstream fetch missing split-horizon headers) + are fixed and deployed. The original ask — Authelia `prompt=login`/`max_age` + support, so a step-up can be requested rather than merely checked after the + fact, plus an actionable freshness error in the browser instead of the flat + "Review unavailable" — remains open. Authelia 4.38 rejected that parameter + once already (`cbea539`); retrying it is gated on the Authelia upgrade this + repository does not own. +- **`INFD-IN-0007`** — see Layer. No deadline. +- **A reusable account/session-status component**, requested of `user-engine` + as `USER-IN-0002` on 2026-09-27: identity, MFA-freshness, logout, to replace + the bare "Signed in as uid=..." string and make the `list`-vs-`read` + freshness split (see Status) legible instead of a silent wall. Not started; + `user-engine` owns the data/API contract and whether it lands as a new + small repository or inside an existing one. +- **The decision_attributable gap** — see "What this repository does not + claim." Unowned by anyone as an active task; recorded so it is not + mistaken for closed now that flex-auth can sign. *Closed 2026-09-10:* the human token tenant (`GH-DEC-2026-013`, `key-cape` `329e48f`) and the evidence payload question (`GH-DEC-2026-014`). +*Closed since, not previously recorded here:* native browser registration and +human proof (`INFD-WP-0001-T08`) and `audit-core` custody/live delivery +(`AUDIT-IN-0003`, `AUDIT-WP-0009`) — both live and observed in production as +of this Status section.