CI validation and candidate provenance

Release publication from GitHub Releases

.github/workflows/release.yml handles published final releases in the public repository. Drafts and prereleases do not publish. Release tags must be vMAJOR.MINOR.PATCH, match the single package version in src/sphinx_traceability_view/_version.py, and identify a commit already in main. Publishing is serialized; the workflow never creates or moves a tag.

Before publishing a draft GitHub Release, attach the qualified wheel, source archive and SHA256SUMS containing exactly those two filenames and hashes. The release-test runner retains all three under its candidate’s artifacts directory. Do not attach an older version or rebuild after qualification. The workflow downloads those exact public assets, checks their hashes, version, long description and runtime/source contents against the tagged source, and runs twine check --strict. Text source comparisons tolerate Git’s LF/CRLF conversion; packaged browser binaries retain exact byte checks. An altered or incomplete archive fails publication. Existing releases are never replaced.

The read-only Windows build job reruns development CI against the downloaded wheel, including isolated installation, and produces a clean documentation publication from the release tag. Full Windows/Firefox/file/HTTP and capacity qualification is a separate prerequisite recorded in Release test executions. The release workflow does not infer that qualification from a green CI result.

Only the separate Ubuntu publish-pypi job receives OIDC permission. It downloads the checked artifact, verifies its checksums, and uses the pinned PyPA action with attestations. It does not check out or run repository code. The pypi environment and PyPI Trusted Publisher must identify owner sysblacksmith, repository STV_sphinx-traceability-view, workflow release.yml and environment pypi. No API token or stored secret is used. Publishing fails visibly if the version already exists; it does not skip files.

After PyPI succeeds, an isolated deploy-docs job deploys the validated HTML through the github-pages environment. That environment must allow tag pattern v* in addition to main for the separate manual Pages workflow. The pypi environment should allow release tags only. Environment approval rules, if configured by the owner, still apply.

This updates the single documentation site to the tagged release, rather than publishing unreleased main content on every push. The manual Documentation Pages workflow remains available for explicitly requested previews/deployments. Do not publish an older final release after a newer one: the workflow is serialized but does not maintain multiple versioned documentation sites.

For a failed build/PyPI job, fix the failure and rerun the failed jobs; successful jobs need not be repeated. If PyPI succeeded but Pages failed, rerun only the failed Pages job. PyPI uploads are irreversible; do not delete/recreate a release or replace its attached qualified files to conceal an error. Use a new version when the distributed package must change.

See PyPA Trusted Publishing guidance and GitHub release events.

Retained original preparation notes

The sections below preserve the earlier CI/provenance and first-publication design. Their statements about unpublished releases, visibility or unapplied settings describe that preparation stage; current release automation is above.

Scope and trust boundary

.github/workflows/validation.yml checks pushes to main, pull requests and manual runs. Core validation runs on a hosted Windows runner with Python 3.13 and Node 22: it checks workflow policy, regenerates browser assets from the lockfile, rejects asset drift, runs JavaScript tests, builds the sdist/wheel, provisions the offline runtime wheelhouse and runs non-browser Python integration checks. A separate Python 3.10 runtime job installs the package and builds the minimal Sphinx fixture with its installed extension. Runtime dependencies come from package metadata rather than a duplicated CI list. Reports retain resolved versions and JUnit evidence.

Actions are pinned to full upstream commit hashes. Both workflows default to a read-only contents token, disable persisted checkout credentials, bound job runtimes and use hosted runners. Pull requests never receive OIDC/attestation permissions. There are no user secrets, pull_request_target/workflow_run triggers, release creation or package-publishing steps. Weekly Dependabot proposals keep pinned action updates reviewable; they do not auto-merge.

Validation scope is development assurance, not release acceptance. Browser and capacity cases remain in the separately authorized release qualification. The full engineering Sphinx build, graph validation and diagram-link checks use the versioned tools/method package in this checkout and run in CI without a private method checkout or credentials.

Checksums and manual provenance

.github/workflows/provenance.yml is manual-only and runs only for main. Its build job repeats core validation and retains candidate wheel/source bytes, SHA256SUMS and build-info.json for 14 days. Metadata identifies the source commit, dirty-worktree state, Python and GitHub run context. Checksums are emitted with LF bytes so GNU verification works across Windows builds and Linux consumers. Checksums detect changed bytes; they do not by themselves authenticate origin.

Once the repository is public, a separate Ubuntu job downloads the same artifact, verifies its checksums and uses GitHub’s build-provenance attestation action. Only that job has OIDC and attestation-write permissions. It does not check out source, install packages or execute repository code; its sole shell command is the fixed checksum verification command. Attestation subjects are the wheel/source archives. Private-repository runs explicitly report that attestation is skipped by this workflow. No run creates a GitHub Release, changes a version or publishes a package.

GitHub’s attestation availability and verification guidance explains the public/private plan restrictions. After an actual successful hosted run, download the retained archives and verify them before any future publication:

sha256sum --strict --check SHA256SUMS
gh attestation verify <archive> --repo sysblacksmith/STV_sphinx-traceability-view

Compare the attestation’s source commit and workflow identity with the approved candidate. Later release preparation must retain the exact qualified bytes, checksums, provenance and qualification evidence; rebuilding the same filename is not evidence of the same artifact. No attestation exists until a hosted job actually generates one. A locally generated build-info file is not a signature.

Branch-protection proposal and remaining owner steps

The current main branch is unprotected. GitHub rejects ruleset access for the present private-plan combination; detailed protection access is also denied to the integration. No remote setting was changed.

.github/main-protection.json is a concrete, unapplied owner-review proposal: require both named CI checks on an up-to-date branch, require a pull request and resolved conversations, enforce protections for administrators, and prohibit force pushes/deletion. It specifies zero peer approvals so a solo maintainer can merge after checks; it does not claim an independent-review barrier. The owner can increase the approval count if another reviewer is available.

After changing visibility/plan and obtaining successful hosted status checks, review the profile and actual check names before applying it through GitHub’s settings/API. No visibility/plan change, hosted workflow dispatch or protection mutation is authorized by this preparation alone. PRSA-006 remains partially remediated until those hosted checks, actual provenance and chosen remote protections can be confirmed. See Limited automated validatio... (STV_PR_012) and PRSA-006 CI and provenance preparation for local evidence and remaining limits.

Public evidence presentation

Canonical requirement, case and execution records remain visible in the website. Historical records are rendered with private tooling repository locations omitted. Logs, inventories, screenshots and binary attachments remain unchanged in the engineering checkout. Historical raw downloads and execution screenshots are excluded from the website; source-copy downloads are disabled. This publication policy does not rewrite previous hashes, outcomes or acceptance. It does not remove any material from Git history or qualify a public repository visibility change. The final HTML tree and downloadable archives are scanned before publication; a private tooling reference fails the check.

GitHub Pages publication

.github/workflows/pages.yml is manual-only and builds main with read-only repository permissions. It installs the pinned documentation dependencies, runs the staged publication builder and validates the requirement graph and published diagram targets. Only docs/_build/html is uploaded as the Pages artifact; temporary build output and local audit reports are not uploaded.

Each build uses fresh staging and doctree directories, validates the result, then replaces the complete HTML tree so obsolete pages and assets disappear. The old HTML and this build’s temporary directories are removed afterward. Build or audit failures leave current HTML unchanged; promotion failures restore it. If restoration itself fails, the script reports and retains the recovery backup instead of deleting the last good copy. Capture command output when diagnostic logs are needed; temporary build trees are not kept by default.

The publish input defaults to false: this prepares a downloadable preview artifact without deployment. When explicitly selected, deployment additionally requires a public repository and main. A separate job uses the github-pages environment with Pages/OIDC write permissions; it only deploys the artifact and does not check out or execute project code. Actions are pinned to full commits.

First-publication procedure:

  1. Merge the preparation and obtain successful Validation checks for main.

  2. Run Documentation Pages on main with publish unchecked. Download its artifact and review the site, including the demo and detail navigation.

  3. Confirm the final repository/history disclosure review, then make the repository public in its GitHub settings.

  4. Apply the reviewed .github/main-protection.json profile after confirming the required check names. Set Pages Source to GitHub Actions and restrict the github-pages deployment environment to main.

  5. Run Documentation Pages on main with publish checked. Verify the deployed site while signed out, including nested pages, STV details, diagrams and downloads. Add the verified URL to the repository website field.

The expected site is STV documentation. These instructions describe the prepared workflow; they do not claim that remote settings have been applied or that deployment has succeeded. Publishing docs does not create a software release. Candidate attestations remain a separate manual provenance operation.

For GitHub’s settings and deployment requirements, see configuring a publishing source and custom Pages workflows.