- 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>
4.7 KiB
Contributing to YPMS
Hard rules — mirrored from OWC's CONTRIBUTING.md because the two systems share a stack, an ownership model, and an ISSO. If a rule feels wrong for YPMS, propose an amendment in a PR to this file, don't quietly break it.
Repository conventions
-
Migrations are immutable once merged. Add a new Alembic revision, never edit
0001_baseline.pyor its successors. If a schema change requires undoing an older migration, the fix is a new revision, not a rewrite. Every migration is a paper trail an auditor can walk. Every revision's SHA-256 is pinned inmigrations/IMMUTABLE.sha256— add a line with each new migration; a test fails if a pinned file changes. Migrations never import app code. -
Don't add domain logic to
src/ypms/framework/orsrc/ypms/security/. Those are reused by every entity; entity-specific code belongs insrc/ypms/<entity>/. If a framework enhancement is genuinely needed, propose it in its own PR with a written reason. -
Every state-mutating route emits an audit row. Enforced by
CRUDService, the router factory, and the stub router. Don't write handlers that bypass them. -
501 stubs still fire RBAC + audit. Deferred actions must route through
require_permissionand emit an audit event. Permission gaps surface at Phase 0 review, not at feature-completion. -
Tests required.
src/ypms/framework/andsrc/ypms/security/need ≥ 80% coverage. Everything else: at least one happy-path test. -
No
--no-verify,# noqa,# type: ignore,# nosec, orgitleaks:allowwithout an inline comment naming the specific reason. Suppressions are per-finding, never blanket. Don't lower a CI gate to get green. -
Sensitive fields never in logs. SSN, banking, tokens, passwords, encryption keys — route through
sanitize_for_logbefore emitting or don't emit. Seesrc/ypms/logging.py. -
No commits attributed to a person who didn't write them. Set
user.nameanduser.emailingit configto yourself before committing. Co-author trailers are welcome and encouraged for pairing. -
Reads of sensitive PII emit
pii_read. Any GET, list, or history route returning SSN-bearing, banking, FERPA, CFSA, or immigration data callsframework.pii_auditafter RBAC passes (NIST AU-14). -
Encrypted columns go through
security.column_cryptoand into__audit_redact__. Otherwise their ciphertext lands inaudit_logandversion_history. Sensitive values are write-only on the model and masked in the read schema. -
Every mapped table declares a retention policy. The app refuses to start otherwise. Don't invent durations — use a
retention_classes.pyclass, or an unset one citing the POA&M item that owns the decision. -
New model modules go in
src/ypms/models.py. Alembic, the retention job, and the tests all read that one list. -
Changes to vendored OWC code need a written reason in the module docstring and get added to the "Upstream to OWC" list in the current phase status doc.
Change control
- Every substantive change ties to a POA&M ID, a phase-plan milestone, or an issue. Include the reference in the PR description.
PHASE{N}_PLAN.mdis authoritative for the current phase's scope. Older plans lose to the current one on conflict.- Cross-phase work needs a written scope-conflict note before it lands.
Security review
- Any change touching auth, RBAC, encryption, or audit gets a second reviewer.
- Changes to
src/ypms/security/require the ISSO's approval (currently Chris Tonjes). - Additions to the RBAC seed require the same review as code changes — permissions are policy in this codebase.
PR checklist
- Tests pass locally (
pytest). - Coverage doesn't drop below 80% on
framework/orsecurity/. ruff check,mypyclean.- SAST (
bandit), SCA (pip-audit --strict .), and secret scan (gitleaks) clean, or per-finding waivers with reasons. - Migration added (if schema changed) and pinned in
migrations/IMMUTABLE.sha256; no edits to older migrations. - New tables have a retention policy; new model modules are in
src/ypms/models.py. - Any new endpoint has RBAC + audit + a test; PII reads emit
pii_read. - Any new sensitive field routes through the app-layer encryption helpers.
docs/nist-mapping.mdupdated if the change wires a new NIST control.- POA&M item updated if the change closes or advances one.
- Commit message names the phase milestone or POA&M ID it advances.
Merging
- Squash-merge is the default. Merge commit messages should read like release notes for that PR.
- Force-pushes to
mainare not allowed. Force-pushes to feature branches during review are fine. - CI (Gitea Actions,
.gitea/workflows/ci.yml) must be green.