refactor: generate CI workflow from gate contracts
This commit is contained in:
@@ -45,10 +45,16 @@ including Ed448, are rejected even if a document labels its algorithm
|
||||
`.vite` files), the build manifest, module inventory, release verification,
|
||||
secret-scan result, and local supply-chain evidence once. The candidate
|
||||
manifest hashes the raw lockfile bytes and requires that digest to equal the
|
||||
dependency inventory's `lockfileSha256`. The two provider jobs download this
|
||||
same archive separately and receive `CANDIDATE_LOCKFILE_PATH` and
|
||||
`CANDIDATE_DIST_SHA256`; configured `VULNERABILITY_PROVIDER_COMMAND` and
|
||||
`PROVENANCE_PROVIDER_COMMAND` must emit the signed reports.
|
||||
dependency inventory's `lockfileSha256`. Before upload, the producer validates
|
||||
the manifest-bound exact archive member set and every member digest, then
|
||||
publishes the archive SHA-256 as an immutable job output. The two provider jobs
|
||||
download this same archive separately, compare that output digest, validate the
|
||||
exact member set before extracting only into isolated roots, and receive
|
||||
`CANDIDATE_LOCKFILE_PATH` and `CANDIDATE_DIST_SHA256`; configured
|
||||
`VULNERABILITY_PROVIDER_COMMAND` and `PROVENANCE_PROVIDER_COMMAND` must emit the
|
||||
signed reports. After each external command returns, provider upload validation
|
||||
rechecks the unchanged archive and extracted candidate, parses the provider JSON
|
||||
with its strict schema, and binds its dist and lockfile digests before upload.
|
||||
|
||||
If either provider input is absent, local verification remains meaningful but
|
||||
`artifacts/security/supply-chain-verification.json` records
|
||||
@@ -57,8 +63,59 @@ If either provider input is absent, local verification remains meaningful but
|
||||
set and digests, then read-only revalidates the archived executable schemas,
|
||||
raw lockfile, module inventory, build outputs, release coherence, SBOM,
|
||||
provenance, security scan and supply-chain coherence. It never rebuilds or
|
||||
rewrites candidate evidence. Scanner or signing outages are not converted to
|
||||
an empty PASS.
|
||||
rewrites candidate evidence. Promotion uploads the already verified archive
|
||||
itself with the two provider reports and verification records; it does not
|
||||
create a replacement archive from extracted files. Scanner or signing outages
|
||||
are not converted to an empty PASS.
|
||||
|
||||
The generated workflow is also a supply-chain control. `config/ci/gates.json`
|
||||
is its sole typed authority. Run `corepack pnpm generate:ci-workflow` after a
|
||||
contract change and `corepack pnpm check:ci-workflow` (or the encompassing
|
||||
`corepack pnpm check:ci`) to reject byte drift in the checked-in Gitea adapter.
|
||||
|
||||
Action resolution is separately closed over one typed, runtime-frozen registry
|
||||
in `scripts/contracts/ci-gates.ts`. Every generated `uses:` value is an absolute
|
||||
upstream URL pinned to a full commit SHA:
|
||||
|
||||
- `https://github.com/actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5`
|
||||
(`v4.3.1`)
|
||||
- `https://github.com/actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020`
|
||||
(`v4.4.0`)
|
||||
- `https://github.com/ChristopherHX/gitea-upload-artifact@81f940d004763f986ba3582c007fd842dd5cb0d7`
|
||||
(patched `v4` branch)
|
||||
- `https://github.com/ChristopherHX/gitea-download-artifact@75635f32b4c1c41c4b3d64e8f85210112ed4c9c7`
|
||||
(patched `v4` branch)
|
||||
|
||||
Unknown actions, relative repositories, tags/branches and short SHAs are
|
||||
rejected. Gitea 1.22's official Actions documentation recommends the
|
||||
`ChristopherHX` patched artifact forks for v4 compatibility; the supported
|
||||
deployment baseline is nevertheless Gitea 1.26.4+ with Gitea Runner 1.0.0+.
|
||||
A real end-to-end provider smoke on the staging Gitea instance remains
|
||||
mandatory before any generated job becomes a required check.
|
||||
|
||||
External provider supervision is fail-closed and requires a Linux runner with
|
||||
an executable `/usr/bin/bwrap`. Bubblewrap mounts the repository workspace
|
||||
read-only, hides `.git`, pins the trusted Node executable at
|
||||
`/usr/local/bin/node`, and exposes only the sibling `untrusted` raw-evidence
|
||||
directory as writable. Provider commands run non-interactively through
|
||||
`/bin/sh -eu -c`, receive a minimized environment plus only their own
|
||||
provider-prefixed credentials, and have a 30-minute limit. They must consume
|
||||
the supplied candidate paths and digests, write exactly the configured raw
|
||||
report, and must not depend on workspace mutation, host home/toolcache access,
|
||||
or direct access to the sealed evidence path. Missing sandbox support, stale or
|
||||
misplaced outputs, command failure/timeout, and post-command candidate drift
|
||||
all stop publication.
|
||||
|
||||
The final promotion verification/staging step must be immediately adjacent to
|
||||
the promoted-release upload, and that upload must not use `always()`. This
|
||||
reduces the post-verification mutation window but does not seal a pathname
|
||||
across two action steps. The runner is therefore required to be trusted,
|
||||
exclusive and single-tenant, with no provider command or other same-UID process
|
||||
surviving from staging into the immediately following upload. The artifact
|
||||
service and transfer actions also remain outside the candidate's cryptographic
|
||||
identity: every downstream consumer must revalidate the downloaded archive,
|
||||
manifest member digests and signed provider evidence. Producer-side adjacency
|
||||
does not provide consumer-side digest revalidation.
|
||||
|
||||
Approved vulnerability exceptions require vulnerability/package identity,
|
||||
owner, a different reviewer, reason and expiry. Expired or self-approved
|
||||
|
||||
Reference in New Issue
Block a user