Phase 0 milestone 0.9: docs + acceptance
ci / test (push) Has been cancelled

- README rewritten: Docker and native quickstarts, try-it flow, gate
  commands, promote-a-stub steps.
- CONTRIBUTING rules 9-13 (pii_read on PII reads, __audit_redact__ for
  encrypted columns, retention policy per table, models.py registry,
  vendored-code change discipline); PR checklist updated.
- docs/nist-mapping.md: per-control file:line evidence and remaining gap.
- NIST_800_53_CONTROL_MAPPING.md v0.3: Phase 0 notes on 28 rows
  (12 implemented, 12 partial, 4 progress notes on hybrid/tailored rows)
  plus a status-shift table.
- PHASE0_PLAN: 0.9 complete; Definition of Done 12/14 checked with how
  each was verified. Open: first green Gitea CI run, Docker/Postgres boot.
- POA&M and status handoff updated; status TL;DR no longer claims an
  unverified Docker boot.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Chris TonjesandClaude Opus 5.5 committed 2026-10-01 14:37:40 -04:00
1 parent 99a50dc86c
commit e3c4cb0cdc
7 files changed
+241 -111

No files matched your search

+30 -17
View File
@@ -1,7 +1,7 @@
# Phase 0 — Handoff status
**Last updated:** 2026-10-01
**Phase:** 0 — Foundations (in flight)
**Phase:** 0 — Foundations (built; exit pending two infra checks)
**Owner:** Chris Tonjes, DOES CIO (System Owner / ISSO / AO)
**Companion docs:** [`PHASE0_PLAN.md`](PHASE0_PLAN.md) (scope + milestones), [`ARCHITECTURE.md`](ARCHITECTURE.md) (design), [`README.md`](README.md) (runnable quickstart)
@@ -9,7 +9,7 @@
## TL;DR
Phase 0 milestones **0.1 → 0.7** are shipped; **0.8 (CI)** is complete except for its green-on-`main` exit check, which needs a Gitea Actions runner registered on `gitea.doesworks.net`. **0.9 (docs + acceptance)** is next. All ATO artifacts (SSP, control mapping, POA&M, PIA) are drafted at v0.1–v0.3 and awaiting review signatures. The repo builds, tests are green (**158 passing, 95.83% coverage**), and Docker Compose boots. `main` is pushed to Gitea.
All nine Phase 0 milestones are built. **Phase 0 exits on two infrastructure checks**, neither of which can run on the dev workstation: (1) the first green Gitea Actions run on `main` — needs an `act_runner` registered on `gitea.doesworks.net`; (2) `docker compose up` against real Postgres. Definition of Done (PHASE0_PLAN §8) is 12 of 14 checked; everything else was verified end to end over HTTP from a clean clone. Tests green (**167 passing, ~96% coverage**); every CI gate passes locally. Control mapping is at v0.3 with file:line evidence (12 ✅ / 12 🟡). `main` is pushed to Gitea.
---
@@ -17,15 +17,15 @@ Phase 0 milestones **0.1 → 0.7** are shipped; **0.8 (CI)** is complete except
| Dimension | Status |
|---|---|
| Phase | 0 (Foundations), milestones 0.1–0.7 shipped; 0.8 pending runner |
| Phase | 0 (Foundations), milestones 0.1–0.9 built; exit pending CI runner + Docker/Postgres boot |
| Git branch | `main`, tracking `origin/main` (Gitea `https://gitea.doesworks.net/chris.tonjes/YPMS.git`) |
| Tests | **158 passing**, **95.83% coverage** (floor 80% enforced in CI) |
| Tests | **167 passing**, **~96% coverage** (floor 80% enforced in CI) |
| CI | `.gitea/workflows/ci.yml` — all gates pass locally; runs queue as "Waiting" until a runner is registered |
| Lint / types | `ruff` clean, `mypy` clean (43 files, strict) |
| Runtime | FastAPI + Postgres on Docker Compose; boots to `/healthz` + `/readyz`; `/auth/*` and `/registrants/*` live; 26 stub entities return 501 behind RBAC + audit |
| Runtime | Verified booting natively (uvicorn + SQLite) from a clean clone; Docker Compose + Postgres not yet run; `/auth/*` and `/registrants/*` live; 26 stub entities return 501 behind RBAC + audit |
| Migrations | 4 revisions (`0001`–`0004_stub_entity_tables`); all apply cleanly to SQLite in the drift test; live Postgres run pending (no Docker on the dev workstation) |
| Seed | 8 roles + permissions matrix + bootstrap admin (`chris` / `DOES_SYSTEM_ADMIN`) |
| ATO docs | SSP v0.3, control mapping v0.2, POA&M v0.1, PIA v0.1 — all drafts, awaiting signatures |
| ATO docs | SSP v0.3, control mapping **v0.3 (Phase 0 evidence)**, POA&M v0.1, PIA v0.1 — all drafts, awaiting signatures |
---
@@ -115,15 +115,29 @@ Guardrails baked in: `OYP_STAFF` can't see FERPA/CFSA (that's `ELIGIBILITY_EXAMI
- Every step passes locally. Gitea has queued runs #1–#5 (and this push) as **Waiting** — no runner is online.
- **To close 0.8:** register an `act_runner` against `gitea.doesworks.net` with an `ubuntu-latest` label mapped to an act-compatible image (e.g. `catthehacker/ubuntu:act-22.04`), outbound to github.com + PyPI. Then confirm the newest run on `main` is green.
### 0.9 — Docs + acceptance ✅
- **README** rewritten: Docker and native (no-Docker) quickstarts, a try-it curl flow, all gate commands, and step-by-step "promote a stub to a real entity".
- **CONTRIBUTING** rules 9–13: PII reads emit `pii_read`; encrypted columns go in `__audit_redact__`; every table has a retention policy; model modules registered in `models.py`; vendored-code changes need a reason + upstream list entry. PR checklist and suppression rule updated.
- **`docs/nist-mapping.md`** — per-control code evidence with linked file:line and the remaining gap. **Control mapping v0.3** carries the same notes per row plus a status-shift table: 12 ✅, 12 🟡; AU-11, CM-3, SI-12 keep 🤝 and SC-8 keeps ⚠️, each with a progress note.
- **Closed gaps found while preparing evidence** (each promised by PHASE0_PLAN §6/§7 but not yet built):
- **Failed logins weren't audited** (AU-2, C.5.7.39). Now `login_failed` with reason `bad_credentials` / `unknown_user` / `inactive` / `throttled`. The typed username is stored only when it matches a real account.
- **SI-11:** app-wide handler returns `{"error":"internal_error","request_id":…}`; logs type + stack frames, never the message (driver errors echo PII); engine `hide_parameters=True`.
- **Startup retention check:** `create_app` refuses to boot if any table lacks a policy.
- **CM-3:** `migrations/IMMUTABLE.sha256` pins merged revisions; test fails on edits.
- Alembic `fileConfig(disable_existing_loggers=False)` — in-process migrations were silencing app loggers in tests.
- **End-to-end check** from a clean clone: migrate → seed → uvicorn → login, Registrant create/read/update/delete, stub 501, audit trail, ciphertext-only at rest, no SSN in the server log.
---
## What's next
### Immediate next milestone: 0.9 — Docs + acceptance
### Phase 0 exit — two infrastructure checks
`README.md` with runnable quickstart (expand the existing one), `CONTRIBUTING.md` hard rules (add the new ones: every table needs a retention policy; new model modules go in `models.py`; suppressions are per-finding), `docs/nist-mapping.md` skeleton, and flip `NIST_800_53_CONTROL_MAPPING.md` rows for the Phase-0-wired controls from 📝 to ✅/🟡 with file evidence (PHASE0_PLAN §7 acceptance). Phase 0 is done when 0.8's runner is green and 0.9's checklist is signed.
1. **CI green on `main`.** Register an `act_runner` on `gitea.doesworks.net` (label `ubuntu-latest` → an act-compatible image such as `catthehacker/ubuntu:act-22.04`; outbound to github.com and PyPI). The queued runs will start; confirm the newest on `main` passes. Closes 0.8 and the CI item in PLAN §8.
2. **Docker + Postgres boot.** On a Docker-capable machine: `cp .env.example .env && docker compose up --build`, then the README "Try it" flow. Closes the last PLAN §8 item and gives the first live Postgres run of migrations 0001–0004. If Postgres disagrees with SQLite anywhere, fix in a new migration.
Then Phase 1 (applications + identity + parental consent) starts.
Then: sign off Phase 0, and draft `PHASE1_PLAN.md` (applications + identity + parental consent — ARCH §12). Decisions that should be made before Phase 1 starts: the four permission-matrix review items below, the 0002 constraint follow-up, and `YPMS-POAM-050` (youth identity model), which Phase 1 is built around.
### Upstream to OWC (accumulated)
@@ -336,9 +350,9 @@ Then the ATO artifacts as needed:
---
## POA&M state (as of 2026-09-30)
## POA&M state (as of 2026-10-01)
- **62 items total** — 2 fully closed, 4 partial closures under `YPMS-POAM-040`
- **62 items total** — 2 fully closed; 9 Phase 0 milestone partial closures logged under `YPMS-POAM-040`; `YPMS-POAM-042` (CI/SBOM) in progress pending the runner
- **6 open decisions** (see Open Questions table above)
- **Immediate remaining action items:**
- PIA route to Privacy Officer + OGC review
@@ -348,14 +362,13 @@ Then the ATO artifacts as needed:
---
## Signals to watch for as we approach milestone 0.9
## Signals to watch for at Phase 0 exit / Phase 1 start
- Control-mapping status flips need file:line evidence, not "implemented in Phase 0". Auditors trace the path.
- Don't weaken a gate to get green (no blanket bandit skips, no `--cov-fail-under` drop). Suppressions are per-finding with a reason — e.g. the inline `gitleaks:allow` on the test JWT secret in `tests/conftest.py`.
- If the first real CI run fails on something local runs didn't catch (runner image, network), fix the workflow, not the gate.
- Phase 1 promotes Guardian and ConsentRecord from stubs: follow README "Adding an entity", and give both the Registrant treatment (`pii_read`, `__audit_redact__` for anything encrypted, coverage doc).
- PARENT_USER access to a child's Registrant hangs on the Guardian link — replace the Phase 0 "parents see nothing" rule in `youth/router.py`, don't layer around it.
- Keep `docs/nist-mapping.md` and the control-mapping rows in step; line numbers drift, so refresh them at each phase gate.
- Retention execution (actual disposal) is Phase 5 work, alongside the OSSE/CFSA ingest pipelines. Don't add it in passing.
- Any entity that will hold PII in Phase 1+ (Guardian, TaxDocument, Attachment) should get the Registrant treatment then — `pii_read` on reads, `__audit_redact__` on encrypted columns.
---
**End of handoff v0.5.**
**End of handoff v0.6.**