Skip to content

Continuous Integration And Release Contract

Assertions

CIR-001 - Workflow topology is event-driven and immutable

Contract: The repository MUST contain only CI, dependency submission, Pages, PR-body, and release workflows. Every GitHub-hosted job MUST run on ubuntu-26.04; external actions MUST use full commit SHAs; validator images MUST use immutable digests; checkout credentials MUST not persist; and every workflow MUST declare permissions and concurrency.

Evidence:

CIR-002 - Quality, compatibility, package, and OpenSSH remain visible gates

Contract: Reusable CI MUST assign source/policy, compatibility/coverage, distribution, hermetic OpenSSH, dependency review with an every-event exact-lock audit, Python and Actions CodeQL, and version progression to visible scoped jobs. Compatibility MUST run once for each declared Python minor; every other expensive gate MUST run once per invocation. No umbrella job MAY repeat another job's tests or build.

Evidence:

CIR-003 - Write permissions are job-scoped

Contract: Default workflow permission MUST be read-only contents. Only CodeQL MAY write security events, dependency submission MAY write contents, Pages deploy MAY write Pages and OIDC, PR-body automation MAY write pull requests, PyPI publication MAY write OIDC, and final GitHub publication MAY write contents. Each exception MUST be confined to its owning job.

Evidence:

CIR-004 - PR-body automation treats head content as bounded data

Contract: PR-body automation MUST be the only pull_request_target boundary, run only for pull requests that change CHANGELOG.md, execute only trusted default-branch code, read a bounded head changelog through the API as inert data, preserve manual body text, and refuse concurrent overwrite.

Evidence:

CIR-005 - Version progression compares exact base and head

Contract: Pull requests and later main pushes MUST compare the exact base and proposed .version values. The first repository commit MAY compare against 0.0.0. Same-version recovery MAY occur only for an unpublished version newer than the latest stable release.

Evidence:

CIR-006 - Publication builds once and never replaces conflict

Contract: Reusable CI's distribution job MUST build and smoke the wheel/sdist once and, for the trusted release caller only, upload that exact pair as one immutable workflow artifact. No other maintained workflow MAY set that upload input. Release jobs MUST consume it without any rebuild for PyPI and GitHub. Published or draft tags, targets, notes, metadata, asset names, sizes, and hashes MUST be verified; conflict MUST fail without moving tags, deleting assets, or overwriting files.

Evidence:

CIR-007 - Dependency submission is trusted-main-only

Contract: Dependency submission MUST trigger only on direct main pushes that change dependency ownership, a lock, or snapshot automation; derive and validate all four manifests offline; verify the expected repository and payload shape; and use only its job-scoped standard token and contents write.

Evidence:

CIR-008 - Documentation changes build before merge and deploy from main

Contract: Documentation and docs-tool changes MUST trigger a strict non-deploying Pages build on pull requests. Direct main builds MUST audit routes, links, anchors, assets, canonical URLs, sitemap XML/gzip, robots, root files, and the absence of insecure HTTP references before a deploy job receives Pages and OIDC writes.

Evidence:

CIR-009 - Contract evidence is machine-checked

Contract: Contract files MUST be the only normative documentation, MUST use unique sequential IDs, and MUST link every assertion to at least one existing test definition. User, maintenance, and site-only inputs MUST remain separate, and every relative documentation link MUST resolve.

Evidence:

CIR-010 - Repository ownership is explicit

Contract: CODEOWNERS MUST assign every repository path to @kogeler, so a default-branch ruleset can require code-owner review for every change.

Evidence:

CIR-011 - PyPI publication is secretless, exact, and recoverable

Contract: Release state MUST inspect PyPI and GitHub independently. A missing PyPI version MUST publish only the gated wheel/sdist through the pypi Environment, PyPI Trusted Publishing, a job-scoped OIDC token, and the pinned official PyPA action. Stored credentials and blind duplicate skipping MUST be absent. Existing PyPI files MUST match local names, types, sizes, hashes, and yanked state before GitHub recovery continues.

Evidence:

CIR-012 - Mutable pins have executable owners

Contract: Project versions, dependency pins, action commits, image digests, runner labels, and release conventions MUST be owned by the executable configuration that consumes them. Tests MUST verify structure and relationships without duplicating unrelated mutable literals.

Evidence:

CIR-013 - Automation is scoped to a Python library

Contract: CI and release automation MUST create only the standard pure Python wheel and source distribution. It MUST NOT contain standalone application, native executable, container-image, Node application, or Rust build processes. Quality, tests, distributions, and OpenSSH acceptance MUST each have one workflow owner, and publication MUST not rebuild CI artifacts.

Evidence: