Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
178 changes: 125 additions & 53 deletions .github/workflows/main-estate-audit.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,48 @@
# This workflow is managed by gh actions-lock.
# SPDX-License-Identifier: MPL-2.0

name: Central Estate CI/CD Audit

# The estate audit, as FIVE component checks instead of one job of 26 steps.
#
# Why components. One job stopped at its first failing gate, so a single red
# gate hid the other 25 and every failure read "estate-audit: failing after
# 8s" with no gate named. Now each component is its own check run, and inside
# a component every gate runs even after an earlier one fails (the
# `!cancelled()` guard), so one push reports every failing gate at once.
#
# governance required-files, spdx-license, affirmation, referencing
# hygiene code-hygiene, formatting, linguist, secrets, vaulted-tokens
# manifests manifest, recipes-set
# languages idris2-abi, zig-unified-api-adapter, proof-runner, boj-cartridge
# advisory nine gates that cannot fail BY DESIGN (README: "What actually
# enforces"); a green tick here is information, not assurance.
#
# Removed: prat and semantic-audit. They were stubs (README, Known defect 5):
# semantic-audit printed "Semantic Audit Passed." unconditionally and prat
# passed any repo with a tests/ directory, so a green tick credited assurance
# that nothing checked. Their directories stay under actions/ only so that
# not-yet-migrated copies of the old 26-step workflow still start; delete them
# once every consumer calls this reusable workflow.
#
# Consumers call this workflow; they do not copy it (see README, "Consuming
# it"). The caller pins this file at a full SHA and is de-onboarded from its
# own actions.lock, the form proven for callers with sha_pinning_required.
#
# Refs (empirical cross-repo matrix, all witnessed 2026-09-17, runs
# 35277504987 / 35277227942 / 35278067796 / 35279718644 / 35280642055 /
# 35280317253):
# $/actions/* -> resolves at the CALLER's commit cross-repo: 0-job.
# ./actions/* + lock -> "local path actions not supported": 0-job.
# ./actions/* de-onboard -> ./ resolves against the CALLER: no action.yml.
# remote @main/tag + lock (onboarded) -> 0-job startup_failure cross-repo.
# remote @SHA + de-onboarded -> works (35279718644), deed/k9@SHA fetched.
# So every gate is a remote ref at a FULL SHA and this workflow is
# de-onboarded from actions.lock. The bare-by-SHA checkout fetches the CALLING
# repo, so the gates audit the caller's tree, which is the design intent.
# Gate IMPLEMENTATIONS are pinned to the SHA below: repin when actions/**
# changes (tests/lock-transitive-closure.sh fails until you do).

on:
push:
branches: [ "main" ]
Expand All @@ -17,88 +58,119 @@ concurrency:
cancel-in-progress: true

jobs:
estate-audit:
governance:
name: governance
runs-on: ubuntu-24.04
steps:
# Remote-form refs to THIS repo's actions at a FULL COMMIT SHA, with
# this workflow DE-ONBOARDED from actions.lock. The empirical cross-repo
# matrix (all witnessed 2026-09-17, runs 35277504987 / 35277227942 /
# 35278067796 / 35279718644 / 35280642055 / 35280317253):
# $/actions/* -> resolves at the RUNNING commit = the
# CALLER's commit cross-repo: 0-job death.
# ./actions/* + lock -> "local path actions not supported": 0-job.
# ./actions/* de-onboard -> jobs spawn, but ./ resolves against the
# CALLER's repo: "Can't find action.yml".
# remote @main/tag + lock (onboarded) -> 0-job startup_failure
# cross-repo (creation-time enforcement under
# the CALLER's jurisdiction; silent).
# remote @SHA + de-onboarded -> BOTH components proven: creation
# passes de-onboarded (35279718644 spawned),
# prepare downloads remote SHA composites
# under the caller's sha_pinning_required
# (same run: deed/k9@SHA fetched fine).
# The bare-by-SHA checkout fetches the CALLING repo cross-repo, so the
# 26 gates audit the caller's estate — the design intent. Trade-offs,
# disclosed: gate IMPLEMENTATIONS are pinned to the SHA above (repin
# when actions/** change; the onboarded code-hygiene-self-test.yml —
# $/ form, full lockfile enforcement — covers composite changes), and
# this workflow sits in the gh-actions-lock local-path/remote-self
# coverage gap ("1 workflow skipped", tolerated not enforced). Revisit
# when the Technical Preview supports $/ across workflow_call. Revisit when
# gh-actions-lock supports local-path actions or $/ across calls.
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- id: checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Required Files Gate
if: ${{ !cancelled() && steps.checkout.outcome == 'success' }}
uses: hyperpolymath/cicd-suite/actions/required-files-check@1aa6bfb657f8240db089a8eef1ad4a7ac198bcf0 # 2026-10-09 (#48)
- name: SPDX License Gate
if: ${{ !cancelled() && steps.checkout.outcome == 'success' }}
uses: hyperpolymath/cicd-suite/actions/spdx-license-check@1aa6bfb657f8240db089a8eef1ad4a7ac198bcf0 # 2026-10-09 (#48)
- name: Affirmation Document Gate
if: ${{ !cancelled() && steps.checkout.outcome == 'success' }}
uses: hyperpolymath/cicd-suite/actions/affirmation-check@1aa6bfb657f8240db089a8eef1ad4a7ac198bcf0 # 2026-10-09 (#48)
- name: Academic Referencing Gate
if: ${{ !cancelled() && steps.checkout.outcome == 'success' }}
uses: hyperpolymath/cicd-suite/actions/referencing-check@1aa6bfb657f8240db089a8eef1ad4a7ac198bcf0 # 2026-10-09 (#48)

hygiene:
name: hygiene
runs-on: ubuntu-24.04
steps:
- id: checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Code Hygiene Gate
if: ${{ !cancelled() && steps.checkout.outcome == 'success' }}
uses: hyperpolymath/cicd-suite/actions/code-hygiene-check@1aa6bfb657f8240db089a8eef1ad4a7ac198bcf0 # 2026-10-09 (#48)
- name: Formatting Validation Gate
if: ${{ !cancelled() && steps.checkout.outcome == 'success' }}
uses: hyperpolymath/cicd-suite/actions/formatting-check@1aa6bfb657f8240db089a8eef1ad4a7ac198bcf0 # 2026-10-09 (#48)
- name: Linguist & Banned Languages Gate
if: ${{ !cancelled() && steps.checkout.outcome == 'success' }}
uses: hyperpolymath/cicd-suite/actions/linguist-check@1aa6bfb657f8240db089a8eef1ad4a7ac198bcf0 # 2026-10-09 (#48)
- name: Are We UnAPI Gate (Secret Scanning)
if: ${{ !cancelled() && steps.checkout.outcome == 'success' }}
uses: hyperpolymath/cicd-suite/actions/secrets-check@1aa6bfb657f8240db089a8eef1ad4a7ac198bcf0 # 2026-10-09 (#48)
- name: Reasonably Good Token Validation Gate
if: ${{ !cancelled() && steps.checkout.outcome == 'success' }}
uses: hyperpolymath/cicd-suite/actions/vaulted-tokens-check@1aa6bfb657f8240db089a8eef1ad4a7ac198bcf0 # 2026-10-09 (#48)

manifests:
name: manifests
runs-on: ubuntu-24.04
steps:
- id: checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Manifest Validation Gate
if: ${{ !cancelled() && steps.checkout.outcome == 'success' }}
uses: hyperpolymath/cicd-suite/actions/manifest-check@1aa6bfb657f8240db089a8eef1ad4a7ac198bcf0 # 2026-10-09 (#48)
- name: Recipes Set Validation Gate
if: ${{ !cancelled() && steps.checkout.outcome == 'success' }}
uses: hyperpolymath/cicd-suite/actions/recipes-set-check@1aa6bfb657f8240db089a8eef1ad4a7ac198bcf0 # 2026-10-09 (#48)

languages:
name: languages
runs-on: ubuntu-24.04
steps:
- id: checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Idris2 ABI Purity Gate
if: ${{ !cancelled() && steps.checkout.outcome == 'success' }}
uses: hyperpolymath/cicd-suite/actions/idris2-abi-check@1aa6bfb657f8240db089a8eef1ad4a7ac198bcf0 # 2026-10-09 (#48)
- name: Zig UnifiedApiAdapter API Gate
if: ${{ !cancelled() && steps.checkout.outcome == 'success' }}
uses: hyperpolymath/cicd-suite/actions/zig-unified-api-adapter-check@1aa6bfb657f8240db089a8eef1ad4a7ac198bcf0 # 2026-10-09 (#48)
- name: Contractile Validation Gate
uses: hyperpolymath/cicd-suite/actions/contractile-validation-check@1aa6bfb657f8240db089a8eef1ad4a7ac198bcf0 # 2026-10-09 (#48)
- name: Recipes Set Validation Gate
uses: hyperpolymath/cicd-suite/actions/recipes-set-check@1aa6bfb657f8240db089a8eef1ad4a7ac198bcf0 # 2026-10-09 (#48)
- name: Affirmation Document Gate
uses: hyperpolymath/cicd-suite/actions/affirmation-check@1aa6bfb657f8240db089a8eef1ad4a7ac198bcf0 # 2026-10-09 (#48)
- name: Academic Referencing Gate
uses: hyperpolymath/cicd-suite/actions/referencing-check@1aa6bfb657f8240db089a8eef1ad4a7ac198bcf0 # 2026-10-09 (#48)
- name: Semantic Audit Gate
uses: hyperpolymath/cicd-suite/actions/semantic-audit-check@1aa6bfb657f8240db089a8eef1ad4a7ac198bcf0 # 2026-10-09 (#48)
- name: SPDX License Gate
uses: hyperpolymath/cicd-suite/actions/spdx-license-check@1aa6bfb657f8240db089a8eef1ad4a7ac198bcf0 # 2026-10-09 (#48)
- name: Proof Runner Gate
if: ${{ !cancelled() && steps.checkout.outcome == 'success' }}
uses: hyperpolymath/cicd-suite/actions/proof-runner-check@1aa6bfb657f8240db089a8eef1ad4a7ac198bcf0 # 2026-10-09 (#48)
- name: PRAT Testing Gate
uses: hyperpolymath/cicd-suite/actions/prat-check@1aa6bfb657f8240db089a8eef1ad4a7ac198bcf0 # 2026-10-09 (#48)
- name: BoJ Cartridge Validation Gate
if: ${{ !cancelled() && steps.checkout.outcome == 'success' }}
uses: hyperpolymath/cicd-suite/actions/boj-cartridge-check@1aa6bfb657f8240db089a8eef1ad4a7ac198bcf0 # 2026-10-09 (#48)

advisory:
name: advisory
runs-on: ubuntu-24.04
steps:
- id: checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Contractile Validation Gate
if: ${{ !cancelled() && steps.checkout.outcome == 'success' }}
uses: hyperpolymath/cicd-suite/actions/contractile-validation-check@1aa6bfb657f8240db089a8eef1ad4a7ac198bcf0 # 2026-10-09 (#48)
- name: Panic Attack & Pons Gate
if: ${{ !cancelled() && steps.checkout.outcome == 'success' }}
uses: hyperpolymath/cicd-suite/actions/custom-tools-check@1aa6bfb657f8240db089a8eef1ad4a7ac198bcf0 # 2026-10-09 (#48)
- name: WWW & Well-Known Compliance Gate
if: ${{ !cancelled() && steps.checkout.outcome == 'success' }}
uses: hyperpolymath/cicd-suite/actions/www-compliance-check@1aa6bfb657f8240db089a8eef1ad4a7ac198bcf0 # 2026-10-09 (#48)
- name: BoJ Cartridge Validation Gate
uses: hyperpolymath/cicd-suite/actions/boj-cartridge-check@1aa6bfb657f8240db089a8eef1ad4a7ac198bcf0 # 2026-10-09 (#48)
- name: Formatting Validation Gate
uses: hyperpolymath/cicd-suite/actions/formatting-check@1aa6bfb657f8240db089a8eef1ad4a7ac198bcf0 # 2026-10-09 (#48)
- name: Accreditations & Badges Gate
if: ${{ !cancelled() && steps.checkout.outcome == 'success' }}
uses: hyperpolymath/cicd-suite/actions/badges-check@1aa6bfb657f8240db089a8eef1ad4a7ac198bcf0 # 2026-10-09 (#48)
- name: Metrics Extraction Gate
if: ${{ !cancelled() && steps.checkout.outcome == 'success' }}
uses: hyperpolymath/cicd-suite/actions/metrics-check@1aa6bfb657f8240db089a8eef1ad4a7ac198bcf0 # 2026-10-09 (#48)
- name: Linguist & Banned Languages Gate
uses: hyperpolymath/cicd-suite/actions/linguist-check@1aa6bfb657f8240db089a8eef1ad4a7ac198bcf0 # 2026-10-09 (#48)
- name: Test & Benchmarks Dashboard Gate
if: ${{ !cancelled() && steps.checkout.outcome == 'success' }}
uses: hyperpolymath/cicd-suite/actions/tests-benches-check@1aa6bfb657f8240db089a8eef1ad4a7ac198bcf0 # 2026-10-09 (#48)
- name: Hosting & Site Status Gate
if: ${{ !cancelled() && steps.checkout.outcome == 'success' }}
uses: hyperpolymath/cicd-suite/actions/hosting-check@1aa6bfb657f8240db089a8eef1ad4a7ac198bcf0 # 2026-10-09 (#48)
- name: Git-Sea Analytics Gate
if: ${{ !cancelled() && steps.checkout.outcome == 'success' }}
uses: hyperpolymath/cicd-suite/actions/gitsea-check@1aa6bfb657f8240db089a8eef1ad4a7ac198bcf0 # 2026-10-09 (#48)
- name: Trust & Humans Validation Gate
if: ${{ !cancelled() && steps.checkout.outcome == 'success' }}
uses: hyperpolymath/cicd-suite/actions/trust-humans-check@1aa6bfb657f8240db089a8eef1ad4a7ac198bcf0 # 2026-10-09 (#48)
- name: Are We UnAPI Gate (Secret Scanning)
uses: hyperpolymath/cicd-suite/actions/secrets-check@1aa6bfb657f8240db089a8eef1ad4a7ac198bcf0 # 2026-10-09 (#48)
- name: Reasonably Good Token Validation Gate
uses: hyperpolymath/cicd-suite/actions/vaulted-tokens-check@1aa6bfb657f8240db089a8eef1ad4a7ac198bcf0 # 2026-10-09 (#48)
24 changes: 14 additions & 10 deletions ARCHITECTURE.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,17 @@ shared library: each gate is a self-contained GitHub composite action whose
entire implementation is the bash in its `action.yml`.

....
actions/<name>-check/action.yml one composite action per gate (26)
.github/workflows/ the audit workflow consumers copy
rollout_estate.sh copies that workflow into every estate repo
actions/<name>-check/action.yml one composite action per gate (26; 24 run)
.github/workflows/main-estate-audit.yml the reusable audit: five component jobs
templates/estate-audit-caller.yml the ten-line caller each repository holds
templates/track-estate-audit.yml weekly bot: moves the caller's pin to HEAD
scripts/deonboard-estate-audit.sh removes the caller from a repo's actions.lock
rollout_estate.sh installs the three above in every estate clone
....

Consumers do not depend on this repository as a whole. They reference
individual actions by path, so a broken gate affects only the repositories that
name it.
Consumers call the reusable workflow at a full SHA. They do not copy its steps.
A copy froze at whatever commit its lock held, so fixes made here never
arrived. The caller is one line to move, and the track bot moves it.

== Why composite, and why bash

Expand All @@ -40,7 +43,8 @@ the README carries the classification and not just prose.

== Blast radius

`rollout_estate.sh` copies the audit workflow into every repository in the
estate. A change to an action here therefore changes CI behaviour across all of
them at once, which is why consumers should pin by commit SHA rather than
`@main`, and why `CODEOWNERS` requires review on everything under `actions/`.
Every estate repository calls the audit workflow, so a change here reaches all
of them. It does not reach them at once: each caller pins a full SHA, and the
weekly track bot moves that pin by PR, whose own audit run is the check. That
PR is where a regression shows up, one repository at a time. `CODEOWNERS`
requires review on everything under `actions/`.
Loading
Loading