Skip to content

[M0-R][CI] Add mandatory scientific quality gates and protected PR workflow - #67

Open
andreazedda wants to merge 4 commits into
masterfrom
codex/issue-13-m0-r-ci-gates-20260822
Open

[M0-R][CI] Add mandatory scientific quality gates and protected PR workflow#67
andreazedda wants to merge 4 commits into
masterfrom
codex/issue-13-m0-r-ci-gates-20260822

Conversation

@andreazedda

@andreazedda andreazedda commented Aug 22, 2026

Copy link
Copy Markdown
Owner

Closes #13
References #23
References #26

Verified baseline and scope

  • Verified canonical base: bf097810b337dc6b766cda04497005670cd96513.
  • Candidate head: 4f6a0c8714609f02a4a55f693419c7178bfa46e2.
  • Scope: mandatory locked CI, local/CI safety parity, synthetic CI settings, PR/issue governance, immutable action pins, bounded workflow timeouts, dependency-gate maintenance, and branch-protection preparation.
  • Non-goals: no new scientific model, solver, coefficient, tolerance, parameter default, observation semantic, schema semantic, dataset, user interface, clinical rule, production settings architecture, or issue [M0-R][QA] Enforce the minimum scientific invariants and define the extended test architecture #23 test programme.
  • Intended use remains E1_research_prototype; clinical decision support, patient-specific prediction validation, and causal-effect identification remain false.

Workflow graph and required status

repository-hygiene
quality
django-integrity (Python 3.11 and 3.12)
scientific-regression
dependency-security
container-build
        |
        v
required

Stable required context: M0-R CI / required. Every mandatory job has a timeout, the workflow uses contents: read, superseded PR/branch runs cancel, and the aggregator fails unless every dependency reports success.

Immutable action inventory

All repository workflow actions are pinned to verified full commit SHAs with release comments: checkout v4.2.2, setup-python v5.6.0, setup-uv v7.6.0, upload-pages-artifact v3.0.1, deploy-pages v4.0.5, setup-qemu v3.6.0, setup-buildx v3.11.1, docker login v3.4.0, metadata v5.8.0, build-push v6.18.0, gitleaks v2.3.9, and upload-artifact v4.6.2. The exact inventory is in docs/operations/TESTING.md.

Test evidence

  • Final mandatory run: https://github.com/andreazedda/bmyCure4MM/actions/runs/32580299555 — all jobs and required pass.
  • Legacy frozen compatibility run: https://github.com/andreazedda/bmyCure4MM/actions/runs/32580299416 — all jobs pass.
  • Secret scan: https://github.com/andreazedda/bmyCure4MM/actions/runs/32580299342 — passes.
  • uv==0.12.3; uv lock --check and frozen chemistry sync pass.
  • Workflow and issue-form YAML parse; every job is bounded; every external action uses a 40-character SHA.
  • Python 3.11: Django check and strict synthetic deploy check pass; migration drift is zero; all 423 tests pass.
  • Python 3.12: Django check and strict synthetic deploy check pass; migration drift is zero; all 423 tests pass.
  • Ruff check and format check pass; mypy passes.
  • Scientific-focused suite: 231 tests pass.
  • Safety-focused suite: 188 tests pass; five deterministic CI-governance tests pass.
  • Dependency audit: no untriaged known vulnerabilities; eight exact documented low/moderate exceptions remain.
  • The complete local wrapper passes every non-container phase. Local Docker execution is unavailable because no daemon is running; the hosted build and smoke checks pass.

Baseline characterization found failures attributable to the chemistry extra not being installed, an import-time manual live-server script, and two stale assertions contradicted by already-merged behavior. The candidate installs the authoritative chemistry extra, makes the manual script import-safe, and updates only those stale assertions without changing product behavior.

Numerical-baseline comparison

Before and after both pass dependency-lock-baseline-v1 with no differences. The canonical seeded report remains 28,247 bytes with SHA-256 708b828060bb06d5842f95850479c1f270c565e69c1fc8d2f40b0e97862ac957. No golden fixture, equation, coefficient, solver setting, model version, or numerical output changed.

Privacy and safety evidence

  • No private data was accessed or added; ignored local_private/ was never traversed.
  • The safety script supports staged local diffs and explicit CI base/head refs, fails closed on invalid refs, scans tracked invariants, and hides matched content.
  • .dockerignore excludes private, environment, database, media, log, artifact, data, and output paths before Docker receives the build context.
  • CI settings replace external secrets with a synthetic key and isolate database, media, logs, static output, cache, email, and Celery state under bounded temporary paths.
  • Every base Django file handler honors the isolated log root. The image contains no generated media/log content, private path, database, or .env.
  • A pre-existing tutorial birth-date example was replaced with a synthetic age band.

Dependency changes

sqlparse is updated from 0.5.4 to patched 0.6.0 in pyproject.toml and uv.lock to remediate four high-severity advisories disclosed after the baseline. A newly disclosed moderate Django 4.2 GeoDjango advisory is narrowly triaged because the affected GIS surface is absent and no 4.2 patch exists; the documented Django 5.2 migration must remove that exception. No new CI dependency was added.

Docker evidence

The hosted gate builds the locked image without pushing, verifies Git/source OCI labels, verifies no private/database/environment path entered the image, verifies empty media/log directories, and passes Django's synthetic-settings check inside the image. This is a current M0-R build/smoke result, not a claim of production readiness.

Branch protection and reviewer feasibility

master protection is active: pull requests and an up-to-date GitHub Actions required check are required; conversation resolution and admin enforcement are enabled; force pushes and branch deletion are disabled. The only verified collaborator is the PR author, so required approving reviews is honestly set to zero; there is no eligible second reviewer. Stale approvals will be dismissed if approvals are later enabled. Issue #13 and this PR remain open unless the owner explicitly documents a temporary solo-maintainer exception in an ADR or issue comment.

The stale branch andreazedda/issue7 has zero unique commits relative to master, no open PR dependency, and all relevant commits are contained by master. It is retained until protection is safely audited.

Rollback and residual risk

Rollback is a revert of the four focused commits. It creates no migration, database transformation, model-version transition, dataset invalidation, or numerical-fixture update. Reverting would restore the previous advisory exposure and remove the new mandatory gate, so protection should be updated before any such rollback. Residual risks are the documented Django/pytest audit exceptions, the absence of an eligible independent reviewer, and GitHub runner warnings that the pinned checkout/setup-python releases target deprecated Node 20 metadata while the runner currently forces Node 24.

Checklist

  • Linked issue, source of truth, scope, non-goals, and medium governance/security risk declared.
  • Model, schema, data, evidence, intended-use, and authorization impacts declared; none expands scientific or clinical behavior.
  • No migration required; migration drift is zero.
  • No numerical output changed and before/after evidence is attached above.
  • No private data, PHI, credentials, databases, or private payloads were added or accessed.
  • Local staged safety gate executed successfully.
  • Screenshots are not part of this change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[M0-R][CI] Consolidate existing workflows into mandatory scientific quality gates and protected PR governance

1 participant