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
+1
-1
@@ -513,7 +513,7 @@ Compute choice — App Service vs. Container Apps vs. AKS — is a Phase 0 sub-d
|
||||
### 9.3 IaC and CI/CD
|
||||
|
||||
- **IaC**: Bicep (matches Azure-native tooling and OCTO templates). Tracked in `infra/`.
|
||||
- **CI**: GitHub Actions (or Azure DevOps, matching OWC — confirm at Phase 0).
|
||||
- **CI**: Gitea Actions on `gitea.doesworks.net` (decided 2026-10-01 — Gitea is the DOES CI host). Workflow at `.gitea/workflows/ci.yml`.
|
||||
- **Pipeline gates**: unit tests, SAST (ruff + a security-focused linter like bandit), SCA (pip-audit or safety), secret scanning (gitleaks), SBOM (CycloneDX; `YPMS-POAM-042`).
|
||||
- **Deploy**: environment promotion (dev → test → prod) with approvals for prod.
|
||||
- **Migrations**: Alembic auto-applied via a migration container at deploy time; migrations are immutable once merged (OWC hard rule).
|
||||
|
||||
+5
-5
@@ -27,7 +27,7 @@ Phase 0 delivers a runnable local repo that every future phase bolts onto. It do
|
||||
| **501 stubs for other entities** | Every entity enumerated in ARCH §6.1 (Guardian, Host, Worksite, Position, Program, Application, Enrollment, TimeEntry, Timesheet, PayrollBatch, TransportationVoucher, Attachment, Note, IntegrationEvent, Notification, EducationRecord, FosterIndicator, ConsentRecord, Cohort, EligibilityRule, JobPosting, HostContact, Certification, Orientation, TaxDocument) shipped as a 501-returning router that **still fires RBAC + audit**. Permission gaps surface at Phase 0, not Phase N. |
|
||||
| **Retention scaffold** | `retention_policy` attribute declared on entity models (per ARCH §6.4). Nightly job wired but no-op in Phase 0 — enforcement lands with the entity-specific implementations in later phases. |
|
||||
| **Alembic baseline** | One initial migration containing all model tables. Phase 0 baseline is `0001_baseline.py`; immutable once merged. |
|
||||
| **CI-ready layout** | GitHub Actions workflow (matches OWC): lint (ruff), type check (mypy or pyright — match OWC), tests (pytest), SAST (bandit), SCA (pip-audit), secret scan (gitleaks), SBOM (CycloneDX). Blocks merge on failure. |
|
||||
| **CI-ready layout** | Gitea Actions workflow (`.gitea/workflows/ci.yml`; Gitea is the DOES CI host, decided 2026-10-01): lint (ruff), type check (mypy or pyright — match OWC), tests (pytest), SAST (bandit), SCA (pip-audit), secret scan (gitleaks), SBOM (CycloneDX). Blocks merge on failure. |
|
||||
| **Test discipline** | ≥ 80% coverage on `framework/` and `security/`. Every other module needs at least one happy-path test. |
|
||||
| **Docs** | `README.md` (runnable quickstart, entity-adding template), `CONTRIBUTING.md` (hard rules, mirrored from OWC), `PHASE0_PLAN.md` (this file), `docs/nist-mapping.md` (stub). |
|
||||
|
||||
@@ -78,7 +78,7 @@ Every Phase 0 component maps to a source-RFP requirement or a NIST control. Tabl
|
||||
| **0.5** | Registrant vertical slice | ✅ **Complete 2026-09-30.** `Registrant` model + schemas + router (`src/ypms/youth/`) + migration `0003_registrants`. SSN AES-256-GCM encrypted at the app layer (`security/column_crypto.py`), write-only on the model, serializer emits only `XXX-XX-1234`. `pii_read` audit on GET, list, and history; every state change emits an audit row with ciphertext redacted via new `__audit_redact__` framework hook. Portal-only roles restricted to own row (Phase 0 minimum; PARENT_USER blocked until Guardian). 98 tests, 94.83% coverage. Coverage doc at `docs/coverage/registrant.md`. |
|
||||
| **0.6** | 501-stub routers for remaining entities | ✅ **Complete 2026-09-30.** 26 stub entities registered in `src/ypms/stubs.py`, each with a router from `framework/stub_router.py` exposing one route per matrix action (8). Every route runs the real RBAC check and writes an audit row before returning 501. `tests/test_stubs.py` sweeps entity × role × route against the matrix JSON (501 + one audit row when granted; 403 + none when not). Registrant restore moved to the matrix `Restore` action. 138 tests, 95.05% coverage. |
|
||||
| **0.7** | Retention scaffold | ✅ **Complete 2026-10-01.** Every mapped table resolves a `RetentionPolicy` (entity models declare `retention_policy`; vendored framework tables mapped by name). PIA §9 interim periods encoded in `src/ypms/retention_classes.py`, all unapproved pending `YPMS-POAM-054`; classes without a PIA basis report as `unset`. Report-only job in `src/ypms/framework/retention.py` (`python -m ypms.framework.retention`) logs "0 records to purge" and writes a `retention_run` audit row. Stub entity models + migration `0004_stub_entity_tables`. Migration-vs-model drift test added. 156 tests, 95.91% coverage. |
|
||||
| **0.8** | CI pipeline | GitHub Actions workflow with lint (ruff), types (mypy/pyright — match OWC's pick), tests, bandit, pip-audit, gitleaks, SBOM. Green build on `main`. |
|
||||
| **0.8** | CI pipeline | 🟡 **Pipeline complete 2026-10-01; green-on-`main` pending a Gitea runner.** `.gitea/workflows/ci.yml`: ruff, mypy, pytest (80% floor, includes migration-drift test), bandit, pip-audit (runtime deps), gitleaks (pinned + sha256-verified, full history), CycloneDX SBOM artifact. Every step passes locally. Running the gates fixed a broken pip-audit invocation, removed `ecdsa` by swapping python-jose → PyJWT, and enforced a 32-byte `JWT_SECRET`. Closes when the first run on `main` is green. |
|
||||
| **0.9** | Docs + acceptance | `README.md` with runnable quickstart; `CONTRIBUTING.md` with hard rules; `docs/nist-mapping.md` skeleton; this file marked complete. |
|
||||
|
||||
Each milestone independently mergeable.
|
||||
@@ -146,7 +146,7 @@ ypms/
|
||||
├── pyproject.toml
|
||||
├── alembic.ini
|
||||
├── .env.example
|
||||
├── .github/workflows/ci.yml
|
||||
├── .gitea/workflows/ci.yml
|
||||
├── migrations/versions/0001_baseline.py
|
||||
├── src/ypms/
|
||||
│ ├── __init__.py
|
||||
@@ -275,7 +275,7 @@ Phase 0 is complete when:
|
||||
## 9. What I need from you
|
||||
|
||||
1. **Match OWC's Azure Gov deployment target?** OWC currently runs Docker locally; its Azure Gov deployment is Phase 19/20. YPMS Phase 0 is local-only too. Confirm we're **not** provisioning Azure Gov in Phase 0 — Azure comes with Phase 1 (Key Vault swap-in) or later.
|
||||
2. **Match OWC's CI provider?** OWC uses `[TBD — confirm]`. I'll default to GitHub Actions unless OWC is on Azure DevOps; then I match. Say which.
|
||||
2. ~~**Match OWC's CI provider?**~~ **Resolved 2026-10-01:** Gitea Actions — Gitea is where DOES CI runs. OWC has no CI yet; it should follow.
|
||||
3. **8 initial roles OK, or want a different seed set?** Current default: `DOES_SYSTEM_ADMIN`, `OYP_STAFF`, `ELIGIBILITY_EXAMINER`, `PAYROLL_ADMIN`, `REPORTING_ANALYST`, `HOST_USER`, `PARENT_USER`, `YOUTH_USER`. Missing roles surface fast at Phase 1; adding one later is a seed update.
|
||||
4. **First entity as Registrant, or something smaller?** Registrant is the natural vertical slice because everything else hangs off it. Smaller options: `Program` (mostly reference data) or `HostContact` (simple). I lean Registrant because the encryption + masking + PII-read audit path is what Phase 0 needs to prove.
|
||||
5. **Test-runner + type-checker to match OWC?** Confirm: pytest for tests, and pick mypy or pyright to match OWC.
|
||||
@@ -283,7 +283,7 @@ Phase 0 is complete when:
|
||||
If you just say "proceed" I'll:
|
||||
|
||||
- Start with milestone 0.1 (repo scaffold + Docker Compose),
|
||||
- Default GitHub Actions, mypy, the 8 roles above, Registrant as the slice, and no Azure Gov in Phase 0,
|
||||
- Default Gitea Actions (resolved), mypy, the 8 roles above, Registrant as the slice, and no Azure Gov in Phase 0,
|
||||
- Merge each milestone independently as it lands.
|
||||
|
||||
---
|
||||
|
||||
+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.**
|
||||
@@ -93,7 +93,7 @@ These four items are the tailorings recorded in the SSP Appendix D and control-m
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| **YPMS-POAM-040** | High | Architecture & tech-stack decision recorded | NIST PL-8 / SA-3 | DOES CIO | ✅ Stack decision closed 2026-09-30: Python 3.12 / FastAPI / SQLAlchemy / Postgres on Azure Government (OWC alignment). ✅ Architecture document v0.1 drafted 2026-09-30 (`ypms/ARCHITECTURE.md`). ✅ Phase 0 plan drafted 2026-09-30 (`ypms/PHASE0_PLAN.md`). M1: DC OCTO security architecture review — 45 days. | 2026-11-15 | 🟡 In Progress |
|
||||
| **YPMS-POAM-041** | High | Azure Government tenant + non-prod environments provisioned | NIST CM-2 / CM-6 | DOES CIO + DC OCTO | M1: subscription request — 30 days. M2: dev + test environments — 60 days. M3: CIS Azure Foundations baseline applied — 90 days. | 2027-01-15 | 🔴 Open |
|
||||
| **YPMS-POAM-042** | High | CI/CD pipeline with SAST, SCA, secret scanning, SBOM | NIST SA-11 / SR-3 / SR-11 / CM-8 | DOES CIO | M1: pipeline scaffold — 30 days. M2: SAST + SCA gates — 60 days. M3: SBOM generation per release (CycloneDX) — 90 days. | 2027-01-31 | 🔴 Open |
|
||||
| **YPMS-POAM-042** | High | CI/CD pipeline with SAST, SCA, secret scanning, SBOM | NIST SA-11 / SR-3 / SR-11 / CM-8 | DOES CIO | M1: pipeline scaffold — 30 days. M2: SAST + SCA gates — 60 days. M3: SBOM generation per release (CycloneDX) — 90 days. **2026-10-01: M1–M3 implemented in `.gitea/workflows/ci.yml` (SBOM per CI run); open until the first green run on `main` (needs a Gitea runner).** | 2027-01-31 | 🟡 In progress |
|
||||
| **YPMS-POAM-043** | High | Sentinel integration (DOES OIT ships application + Azure resource logs to DC OCTO Sentinel) | NIST AU-6 / SI-4 | DOES CIO + DC OCTO CISO | M1: log-schema agreement with OCTO SOC — 30 days. M2: Sentinel workspace and ingestion — 60 days. M3: correlation rules and alert playbooks — 120 days. | 2027-02-28 | 🔴 Open |
|
||||
| **YPMS-POAM-044** | High | Backup + restore procedure documented and tested | NIST CP-9 / CP-9(1) | DOES CIO + OIT Ops | M1: procedure documented — 30 days. M2: initial restore drill — 60 days. M3: annual drill cadence established — 90 days. | 2027-02-15 | 🔴 Open |
|
||||
|
||||
@@ -179,6 +179,7 @@ Closures retained for traceability.
|
||||
| — | Phase 0 milestone 0.5 shipped (partial closure of YPMS-POAM-040) | 2026-09-30 | Registrant vertical slice: model, schemas, router, migration 0003. SSN app-layer encrypted (AES-256-GCM, column-bound AAD) and masked in the serializer (C.5.7.50 / SC-28). `pii_read` audit on every read path (C.5.6.9 #5 / AU-14). Audit + version-history snapshots redact ciphertext via `__audit_redact__`. Portal-only roles limited to own row. 98 tests passing, 94.83% coverage. Evidence trace at `docs/coverage/registrant.md`. |
|
||||
| — | Phase 0 milestone 0.6 shipped (partial closure of YPMS-POAM-040) | 2026-09-30 | 501-stub routers for 26 entities; every route enforces RBAC and writes an audit row before returning 501 (source RFP C.5.7.27; NIST AC-3, AU-12). Matrix-driven test sweep covers every entity × role × action. Permission-matrix review items recorded in PHASE0_STATUS.md. 138 tests passing, 95.05% coverage. |
|
||||
| — | Phase 0 milestone 0.7 shipped (partial closure of YPMS-POAM-040) | 2026-10-01 | Retention scaffold (NIST AU-11, SI-12; source RFP C.5.7.42): every table carries a policy; PIA §9 interim periods encoded but unapproved; report-only nightly job logs eligible counts and audits each run. Implementation is ready to consume the signed schedule from YPMS-POAM-054 (flip `approved`, cite authority). 156 tests passing, 95.91% coverage. |
|
||||
| — | Phase 0 milestone 0.8 pipeline complete (partial closure of YPMS-POAM-040; advances YPMS-POAM-042) | 2026-10-01 | Gitea Actions workflow with lint, strict types, tests + coverage floor, migration drift test, SAST, SCA on runtime deps, full-history secret scan, CycloneDX SBOM. All gates pass locally; green-on-main pending runner registration. Removed `ecdsa` (PYSEC-2026-1325) by moving JWT to PyJWT; enforced 32-byte JWT secret (RFC 7518). 158 tests passing, 95.83% coverage. |
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in new issue
Block a user