Record milestone 0.8 status: pipeline complete, green-on-main pending Gitea runner
ci / test (push) Has been cancelled
ci / test (push) Has been cancelled
PHASE0_PLAN 0.8 marked in progress with the remaining exit check; ARCHITECTURE 9.3 and the plan's CI-provider question resolved to Gitea Actions; YPMS-POAM-042 to in progress; status handoff gets 0.8 details, runner-registration steps, local gate commands, and the accumulated upstream-to-OWC list. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
5f2d885fdc
commit
170280ed38
4 files changed
+47
-23
No files matched your search
+39
-16
@@ -9,7 +9,7 @@
|
||||
|
||||
## TL;DR
|
||||
|
||||
Phase 0 milestones **0.1 → 0.7** are shipped. **0.8 (CI pipeline)** is next, then **0.9 (docs + acceptance)**. 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 (**156 passing, 95.91% coverage**), and Docker Compose boots. `main` is pushed to Gitea.
|
||||
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.
|
||||
|
||||
---
|
||||
|
||||
@@ -17,9 +17,10 @@ Phase 0 milestones **0.1 → 0.7** are shipped. **0.8 (CI pipeline)** is next, t
|
||||
|
||||
| Dimension | Status |
|
||||
|---|---|
|
||||
| Phase | 0 (Foundations), milestones 0.1–0.7 shipped |
|
||||
| Phase | 0 (Foundations), milestones 0.1–0.7 shipped; 0.8 pending runner |
|
||||
| Git branch | `main`, tracking `origin/main` (Gitea `https://gitea.doesworks.net/chris.tonjes/YPMS.git`) |
|
||||
| Tests | **156 passing**, **95.91% coverage** (floor 80% enforced in CI) |
|
||||
| Tests | **158 passing**, **95.83% 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 |
|
||||
| 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) |
|
||||
@@ -39,7 +40,7 @@ Read [`PHASE0_PLAN.md`](PHASE0_PLAN.md) for the full scope tables. High points b
|
||||
- `alembic.ini` + empty baseline migration
|
||||
- `src/ypms/main.py` — FastAPI factory with `/healthz` + `/readyz`
|
||||
- `src/ypms/settings.py`, `logging.py` (structlog + `sanitize_for_log`), `db.py`, `middleware.py` (RequestId)
|
||||
- `.github/workflows/ci.yml` — lint, types, tests+80% coverage, bandit, pip-audit, gitleaks
|
||||
- `.github/workflows/ci.yml` — lint, types, tests+80% coverage, bandit, pip-audit, gitleaks (moved to `.gitea/workflows/` in 0.8)
|
||||
- `README.md`, `CONTRIBUTING.md`
|
||||
|
||||
### 0.2 — Framework vendor-in ✅
|
||||
@@ -107,20 +108,30 @@ Guardrails baked in: `OYP_STAFF` can't see FERPA/CFSA (that's `ELIGIBILITY_EXAMI
|
||||
- `src/ypms/models.py` — the one import-all list (Alembic env, retention job, test fixtures).
|
||||
- `tests/framework/test_retention.py::test_migrations_match_models` — upgrades a scratch SQLite DB to head and diffs against `Base.metadata`. Verified it fails on an unmigrated column.
|
||||
|
||||
### 0.8 — CI pipeline 🟡 (green-on-main pending runner)
|
||||
|
||||
- `.gitea/workflows/ci.yml` (moved from `.github/`): checkout (full history) → Python 3.12 → ruff → mypy → pytest + 80% floor → bandit → `pip-audit --strict .` (runtime deps) → gitleaks 8.30.1 (pinned, sha256-verified) → CycloneDX SBOM from a clean runtime-only venv, uploaded as artifact `sbom`.
|
||||
- **Running the gates for real found four things:** the old `pip-audit --disable-pip` step was a usage error and could never pass; `ecdsa` (PYSEC-2026-1325, no fix) via python-jose → swapped to **PyJWT**; PyJWT flagged an 11-byte test JWT secret → `JWT_SECRET` now **requires ≥ 32 bytes** (RFC 7518 §3.2) at settings load; bandit B101 on an `assert` in the retention job.
|
||||
- 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.
|
||||
|
||||
---
|
||||
|
||||
## What's next
|
||||
|
||||
### Immediate next milestone: 0.8 — CI pipeline
|
||||
### Immediate next milestone: 0.9 — Docs + acceptance
|
||||
|
||||
`.github/workflows/ci.yml` already runs ruff, mypy, pytest (80% floor), bandit, pip-audit, gitleaks. 0.8 is getting it green on the actual CI host and adding SBOM (CycloneDX; `YPMS-POAM-042`). **Open question first:** the repo lives on Gitea, so GitHub Actions won't run as-is — Gitea Actions (largely workflow-compatible) vs. Azure DevOps (ARCH §9.3 says match OWC). Confirm what OWC uses before building.
|
||||
|
||||
### After 0.8
|
||||
|
||||
- **0.9** — Docs + acceptance (README expanded, `docs/nist-mapping.md` skeleton, "Phase 0 done" acceptance checklist)
|
||||
`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.
|
||||
|
||||
Then Phase 1 (applications + identity + parental consent) starts.
|
||||
|
||||
### Upstream to OWC (accumulated)
|
||||
|
||||
1. `crud.py` pagination cursor fix (0.2).
|
||||
2. `crud._to_dict` `__audit_redact__` hook + `date` serialization (0.5) — OWC claimant SSN has the same exposure.
|
||||
3. `CRUDService.history` `builtins.list` annotation (0.5).
|
||||
4. python-jose → PyJWT to drop `ecdsa` (0.8).
|
||||
|
||||
### Schema follow-up (surfaced by 0.7 drift test)
|
||||
|
||||
Migration `0002_framework_tables` creates named unique constraints (`uq_roles_code`, `uq_users_username`, `uq_users_email`) **and** unique indexes on the same columns; the models declare only the indexes. Harmless (double enforcement on Postgres) but real drift. 0002 is immutable — options are a `0005` that drops the three constraints, or leave as-is. Allow-listed in `KNOWN_0002_DRIFT` until decided.
|
||||
@@ -202,7 +213,7 @@ git -C /Users/christonjes/cc/ypms config user.email <addr>
|
||||
| `security/column_crypto.py` | 100% |
|
||||
| `framework/stub_router.py`, `stubs.py` | 100% |
|
||||
| `framework/retention.py`, `retention_classes.py`, `stub_models.py` | 99–100% |
|
||||
| Overall | **95.91%** |
|
||||
| Overall | **95.83%** |
|
||||
|
||||
`framework/router.py` is still excluded from coverage — Registrant uses a hand-built router, so `make_router` gets its first real callers in 0.6. Coverage config in `pyproject.toml`.
|
||||
|
||||
@@ -254,7 +265,14 @@ mypy src # types (strict)
|
||||
pytest -q --cov=src/ypms --cov-report=term --cov-fail-under=80
|
||||
```
|
||||
|
||||
The GitHub Actions workflow at `.github/workflows/ci.yml` runs the same commands plus `bandit`, `pip-audit`, and `gitleaks`.
|
||||
Before pushing, also run the remaining CI gates:
|
||||
|
||||
```bash
|
||||
bandit -q -r src -c pyproject.toml
|
||||
pip-audit --strict . # runtime dependency set from pyproject
|
||||
```
|
||||
|
||||
The Gitea Actions workflow at `.gitea/workflows/ci.yml` runs all of the above plus gitleaks and the SBOM build.
|
||||
|
||||
---
|
||||
|
||||
@@ -290,6 +308,10 @@ The GitHub Actions workflow at `.github/workflows/ci.yml` runs the same commands
|
||||
|
||||
15. **New model modules go in `src/ypms/models.py`.** Alembic, the retention job, and the test DB all read that list.
|
||||
|
||||
16. **`JWT_SECRET` must be ≥ 32 bytes or the app won't start** (`Settings` validation). Old `.env` files with `dev-secret-change-me` need updating.
|
||||
|
||||
17. **JWT library is PyJWT, not python-jose** (diverges from OWC). Catch `jwt.PyJWTError`, not `JWTError`.
|
||||
|
||||
---
|
||||
|
||||
## File map
|
||||
@@ -326,13 +348,14 @@ Then the ATO artifacts as needed:
|
||||
|
||||
---
|
||||
|
||||
## Signals to watch for as we approach milestone 0.8
|
||||
## Signals to watch for as we approach milestone 0.9
|
||||
|
||||
- Don't weaken a gate to get green (no blanket bandit skips, no `--cov-fail-under` drop). Suppressions are per-finding with a reason.
|
||||
- The drift test runs Alembic inside pytest; CI needs the repo root as cwd so `alembic.ini` resolves.
|
||||
- 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.
|
||||
- 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.4.**
|
||||
**End of handoff v0.5.**
|
||||
Reference in new issue
Block a user