Skip to content

fix(ci): green the two failing governance jobs (SPDX, action pins, reusable staleness)#292

Merged
hyperpolymath merged 2 commits into
mainfrom
fix/governance-red
Jul 21, 2026
Merged

fix(ci): green the two failing governance jobs (SPDX, action pins, reusable staleness)#292
hyperpolymath merged 2 commits into
mainfrom
fix/governance-red

Conversation

@hyperpolymath

@hyperpolymath hyperpolymath commented Jul 21, 2026

Copy link
Copy Markdown
Owner

Turns governance from 2-of-10-red to green. Each fix was replicated locally against the real gate script before pushing — no speculative pushes.

What was failing, and why it was invisible until now

governance has 10 jobs; only Workflow security linter and Check Workflow Staleness were red. Both had been masked by BROKEN-M1 (allowed_actions: selected + empty patterns_allowed), which made the whole workflow startup_failure with zero jobs. Once the policy was set to all, the jobs ran and reported honestly.

Three commits, each clearing a gate that revealed the next

Commit Gate Fix
d3f61c70 Workflow security linter — SPDX pages.yml had no SPDX header. Added. Also deleted the retired scorecard-enforcer.yml, which Check Workflow Staleness fails on by name.
9bb4f99e Workflow security linter — action pinning With SPDX passing, the linter's next step failed: pages.yml held the only 4 tag-ref uses: in the repo. SHA-pinned all four.
c32bc07b Check Workflow Staleness governance-reusable + scorecard-reusable pins were 75 commits / 26 days behind — outside the recency window on both arms. Refreshed d135b058813ecf.

Why pages.yml was unpinned in the first place

It has never successfully run. Its one and only run, from #288, was the BROKEN-M1 startup_failure — so no linter had ever seen it. Preconditions were checked before pinning it green: hyperpolymath/ddraig-ssg is public with Ddraig.idr at root, and Pages is build_type=workflow on boj-server.net.

Evidence for the re-pin

Scoped to exactly the two reusables the gate names. check-workflow-staleness.sh inspects only governance-reusable, hypatia-scan-reusable and scorecard-reusable — which is why mirror.yml sits at the same d135b05 and was not flagged. It is deliberately left alone.

  • governance-reusable — identical 10 jobs before and after, so no new required check appears. The three gates whose behaviour changes were each run locally against this tree: Guix/Nix PASS (guix.scm is present, so the Nix fallback and the absent flake.nix are moot), docs PASS (README + LICENSE + CONTRIBUTING), banned-languages 0 tracked .groovy/.gradle files. Both gates fetch their scripts from standards@main rather than from the pin, so these are the scripts CI actually runs.
  • scorecard-reusable — the entire diff is an SPDX correction (PMPL-1.0-or-laterMPL-2.0) plus timeout-minutes: 15. Stated explicitly because scorecard.yml has no pull_request trigger, so this PR's checks do not exercise it; the diff is the evidence, not a green tick. Its first real run is the next push to main.

Local verification

  • check-workflow-staleness.sh → exit 0
  • 66/66 uses: SHA-pinned; 25/25 workflows carry SPDX + top-level permissions:; all 25 parse as YAML

Not in scope

SonarQube and Hypatia fail independently of these changes and are triaged separately.

🤖 Generated with Claude Code

…cer.yml

Two of the governance gate's failures, both surfaced only after the repository's
Actions policy was fixed (the workflows previously startup_failure'd before any
job could run).

Workflow security linter
  ERROR: .github/workflows/pages.yml missing SPDX header

  pages.yml is the active Ddraig SSG docs deploy added in #288; it was the only
  workflow of 26 without the header. Added, matching the form used by
  proofs.yml. Not deleted — it is live, and pages-deploy.yml is a different
  thing (Cloudflare Workers, not GitHub Pages).

Check Workflow Staleness
  ERROR: scorecard-enforcer.yml is retired. Use scorecard.yml ->
         standards scorecard-reusable.yml instead.

  Removed. The replacement scorecard.yml is present. This also clears the
  separate `OpenSSF Scorecard Enforcer` run failure.

  Confirmed safe to delete: the Base ruleset (14285163) requires only
  `Dependabot`, `Hypatia Neurosymbolic Analysis` and `Hypatia`, so removing
  this workflow cannot strand a PR on a permanently-"Expected" required check.

Deliberately NOT addressed here — the staleness gate's two remaining complaints
both concern shared CI fate and want coordination, not a drive-by fix:

  - governance-reusable.yml / scorecard-reusable.yml pin d135b05bfc64 is 75
    commits / 26d behind standards HEAD (refresh toward 8813ecf2a841).
    Re-pinning consumers changes behaviour estate-wide, and at least one
    reusable (secret-scanner) is known not to inherit its config to callers.
  - OSSF Scorecard uploading SARIF to Code Scanning while not running for every
    PR head commit.

Verified locally by replicating the linter's own check across all 25 remaining
workflows: every one carries an SPDX header and a top-level `permissions:`.
pages.yml still parses as valid YAML.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@@ -1,3 +1,8 @@
# SPDX-License-Identifier: MPL-2.0
@@ -1,3 +1,8 @@
# SPDX-License-Identifier: MPL-2.0
@@ -1,3 +1,8 @@
# SPDX-License-Identifier: MPL-2.0
@@ -1,3 +1,8 @@
# SPDX-License-Identifier: MPL-2.0
@github-actions

Copy link
Copy Markdown

🔍 Hypatia Security Scan

Findings: 226 issues detected

Severity Count
🔴 Critical 15
🟠 High 134
🟡 Medium 77

⚠️ Action Required: Critical security issues found!

View findings
[
  {
    "reason": "Action actions/checkout@v4 needs attention",
    "type": "unpinned_action",
    "file": "pages-deploy.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Action actions/checkout@v4 needs attention",
    "type": "unpinned_action",
    "file": "pages.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Action actions/checkout@v4 needs attention",
    "type": "unpinned_action",
    "file": "pages.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Action actions/upload-pages-artifact@v3 needs attention",
    "type": "unpinned_action",
    "file": "pages.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Action actions/deploy-pages@v4 needs attention",
    "type": "unpinned_action",
    "file": "pages.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in build.yml",
    "type": "missing_timeout_minutes",
    "file": "build.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in pages-deploy.yml",
    "type": "missing_timeout_minutes",
    "file": "pages-deploy.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in push-email-notify.yml",
    "type": "missing_timeout_minutes",
    "file": "push-email-notify.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in instant-sync.yml",
    "type": "secret_action_without_presence_gate",
    "file": "instant-sync.yml",
    "action": "peter-evans/repository-dispatch",
    "rule_module": "workflow_audit",
    "severity": "high"
  },
  {
    "reason": "Issue in codeql.yml",
    "type": "codeql_missing_actions_language",
    "file": "codeql.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  }
]

Powered by Hypatia Neurosymbolic CI/CD Intelligence

@hyperpolymath
hyperpolymath marked this pull request as ready for review July 21, 2026 12:33
@hyperpolymath
hyperpolymath merged commit e54b17a into main Jul 21, 2026
46 of 49 checks passed
@hyperpolymath
hyperpolymath deleted the fix/governance-red branch July 21, 2026 12:37
@github-actions

Copy link
Copy Markdown

🔍 Hypatia Security Scan

Findings: 226 issues detected

Severity Count
🔴 Critical 15
🟠 High 134
🟡 Medium 77

⚠️ Action Required: Critical security issues found!

View findings
[
  {
    "reason": "Action actions/checkout@v4 needs attention",
    "type": "unpinned_action",
    "file": "pages-deploy.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Action actions/checkout@v4 needs attention",
    "type": "unpinned_action",
    "file": "pages.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Action actions/checkout@v4 needs attention",
    "type": "unpinned_action",
    "file": "pages.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Action actions/upload-pages-artifact@v3 needs attention",
    "type": "unpinned_action",
    "file": "pages.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Action actions/deploy-pages@v4 needs attention",
    "type": "unpinned_action",
    "file": "pages.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in build.yml",
    "type": "missing_timeout_minutes",
    "file": "build.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in pages-deploy.yml",
    "type": "missing_timeout_minutes",
    "file": "pages-deploy.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in push-email-notify.yml",
    "type": "missing_timeout_minutes",
    "file": "push-email-notify.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in instant-sync.yml",
    "type": "secret_action_without_presence_gate",
    "file": "instant-sync.yml",
    "action": "peter-evans/repository-dispatch",
    "rule_module": "workflow_audit",
    "severity": "high"
  },
  {
    "reason": "Issue in codeql.yml",
    "type": "codeql_missing_actions_language",
    "file": "codeql.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  }
]

Powered by Hypatia Neurosymbolic CI/CD Intelligence

@hyperpolymath hyperpolymath changed the title fix(ci): add SPDX header to pages.yml; remove retired scorecard-enforcer.yml fix(ci): green the two failing governance jobs (SPDX, action pins, reusable staleness) Jul 21, 2026
hyperpolymath added a commit that referenced this pull request Jul 21, 2026
…le pins (#293)

Clears the **last two red `governance` jobs**. Follow-up to #292 —
opened as a new PR off `main` per this repo's squash-merge convention
(`.claude/CLAUDE.md`), not as extra commits on the merged branch.

Every fix was replicated locally against the **real** gate script before
pushing.

## Why these only surfaced now

`governance` has 10 jobs. BROKEN-M1 (`allowed_actions: selected` + empty
`patterns_allowed`) made the whole workflow `startup_failure` with
**zero jobs**, so all 10 were invisible. With the policy set to `all`, 8
report green and these 2 report honestly. #292 then cleared the SPDX arm
and the retired-workflow rule, revealing what sat behind them.

## 1 · `Workflow security linter` — action pinning

`pages.yml` held the only **4 tag-ref `uses:`** in the repo (out of 66).
It had **never actually run** — its one and only run was the BROKEN-M1
`startup_failure` — so no linter had ever inspected it.

| Action | Pinned to | Change |
|---|---|---|
| `actions/checkout` | `de0fac2e` (v6.0.2) | v4 → v6.0.2, matching the
pin **41 other workflows here already use** |
| `actions/upload-pages-artifact` | `56afc609` (v3.0.1) | pin-only —
exactly what `@v3` resolves to today |
| `actions/deploy-pages` | `d6db9016` (v4.0.5) | pin-only — exactly what
`@v4` resolves to today |

Two are pure pins with no behaviour change. `checkout` moves for repo
consistency; worth flagging that `pages.yml` is the **only container
job** here, so this is the first time that pin runs inside
`idris2-pack`.

Preconditions verified before pinning a never-run workflow green:
`hyperpolymath/ddraig-ssg` is public with `Ddraig.idr` at root, and
Pages is `build_type=workflow` on `boj-server.net`.

## 2 · `Check Workflow Staleness` — reusable pin recency

The gate allows *≤50 commits behind standards HEAD **OR** ≤14 days old*.
`d135b05` was **75 commits / 26 days** behind — outside on both arms.
Refreshed to `8813ecf`.

Scoped to exactly the two reusables the gate names.
`check-workflow-staleness.sh` inspects only `governance-reusable`,
`hypatia-scan-reusable` and `scorecard-reusable` — which is why
**`mirror.yml` sits at the same `d135b05` and was not flagged**. It is
left alone deliberately rather than swept along.

### Evidence, not assumption

**`governance-reusable`** — identical 10 jobs before and after, so no
new required check appears. The three gates whose behaviour changes were
each run locally against this tree:

| Gate | Result |
|---|---|
| Guix primary / Nix fallback | **PASS** — `guix.scm` present, so the
Nix fallback (and the absent `flake.nix`) is moot |
| Code quality + docs | **PASS** — README + LICENSE + CONTRIBUTING all
present |
| banned languages (+ new Groovy) | **0** tracked `.groovy`/`.gradle`
files |

Both gates fetch their scripts from `standards@main` rather than from
the pin, so these are the scripts CI will actually run.

**`scorecard-reusable`** — the entire `d135b05..8813ecf` diff is an SPDX
correction (`PMPL-1.0-or-later` → `MPL-2.0`) plus `timeout-minutes: 15`.
Called out explicitly because `scorecard.yml` has **no `pull_request`
trigger**, so this PR's checks do *not* exercise it. The diff is the
evidence; its first real run is the next push to `main`.

## Local verification

- `check-workflow-staleness.sh` → **exit 0**
- 66/66 `uses:` SHA-pinned
- 25/25 workflows carry SPDX + top-level `permissions:`
- all 25 parse as YAML

## Not in scope

`SonarQube` and `Hypatia` fail independently of these changes; triaged
separately.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
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.

2 participants