Registrant model + schemas + router + migration 0003, exercising the vendored framework end-to-end (CRUDService, RBAC, audit, version history). - SSN app-layer encrypted (AES-256-GCM, HKDF key, column-bound AAD, versioned format) in security/column_crypto.py; write-only on the model; serializer exposes only ssn_masked (XXX-XX-1234). C.5.7.50 / SC-28. - pii_read audit on GET, list (one row per page with ids), and history. C.5.6.9 #5 / AU-14. - Portal-only callers (YOUTH/PARENT/HOST) limited to own row via Registrant.user_id; out-of-scope is 404. PARENT_USER sees nothing until Guardian lands. History gated on VersionHistory, not View. - minor_flag derived from dob at read time. Framework changes (flag to OWC on re-vendor): - crud._to_dict honors __audit_redact__, keeping ciphertext out of audit_log and version_history. - crud._to_dict serializes date (not only datetime) for JSON columns. - CRUDService.history annotation uses builtins.list (method shadowed it). 98 tests passing, 94.83% coverage; ruff + mypy clean. Coverage trace at docs/coverage/registrant.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
YPMS — Youth Program Management System
DC Department of Employment Services / Office of Youth Programs — in-house build replacing seven legacy tools (MBSYEP intake, TMS timekeeping, PF3 admin, manual payroll scripts, MicroStrategy, and two supporting apps) with a single Python / FastAPI / Postgres system on Azure Government.
Status: Pre-development. Phase 0 (foundations) in flight.
System owner + ISSO + AO: Chris Tonjes, DOES CIO.
Full context: OVERVIEW.md, ARCHITECTURE.md, PHASE0_PLAN.md.
Quickstart (local)
Requires Docker Desktop (or equivalent). Ports 8000 (app), 5433 (Postgres), 8081 (Adminer) must be free.
cp .env.example .env
docker compose up --build
App at http://localhost:8000. OpenAPI docs at http://localhost:8000/docs.
curl http://localhost:8000/healthz # → {"status":"ok"}
curl http://localhost:8000/readyz # → {"status":"ok"} once db is up
Adminer (DB explorer) at http://localhost:8081. Connect with:
- System: PostgreSQL
- Server:
db - Username / Password / Database:
ypms/ypms/ypms
Stop with Ctrl+C; wipe local DB with docker compose down -v.
Tests
Local (no Docker required for the tests):
python -m venv .venv && source .venv/bin/activate
pip install -e '.[dev]'
pytest
Coverage:
pytest --cov=src/ypms --cov-report=term-missing
Tests use SQLite in-memory for speed. Postgres-specific behaviour gets its own Postgres-only fixture when a migration or query needs it (see ARCHITECTURE.md §4.8).
Repo shape
Full tree in ARCHITECTURE.md §5.1. High points:
src/ypms/main.py— FastAPI factorysrc/ypms/settings.py— pydantic-settings configsrc/ypms/db.py— SQLAlchemy engine, session,Basesrc/ypms/logging.py— structlog + sensitive-field sanitizersrc/ypms/middleware.py— request idsrc/ypms/framework/— vendored from OWC, milestone 0.2src/ypms/security/— auth + RBAC + column encryption, milestones 0.3–0.4src/ypms/youth/— Registrant entity (vertical slice), milestone 0.5- Other entity packages — 501 stubs, milestone 0.6
migrations/— Alembic, immutable-once-mergedtests/— pytest, SQLite by default
Adding an entity
Once the framework lands in milestone 0.2, adding a new entity follows the OWC add-entity pattern (model → schemas → router → main.py registration → migration → permissions seed entry → test → coverage doc). Full instructions land here at milestone 0.2 completion.
Contributing
See CONTRIBUTING.md for the hard rules. Highlights: migrations are immutable once merged, every state-mutating route emits an audit row, framework/security modules must not carry domain logic, no --no-verify or # type: ignore without a written reason.
Compliance
SYSTEM_SECURITY_PLAN.mdv0.3 — NIST 800-53 Moderate SSPNIST_800_53_CONTROL_MAPPING.mdv0.2 — full control-family mapPRIVACY_IMPACT_ASSESSMENT.mdv0.1 — PIA covering minors, SSN, banking, FERPA, CFSAPOAM.mdv0.1 — POA&M with 62 items and 2 closures as of 2026-09-30
License / usage
Internal DOES system. Not for external distribution.