ci(workflows): fix boj-build YAML + gate mirror secrets on presence#362
Merged
Conversation
Follow-up to #360 (the remaining real workflow_audit items; owner chose 'new separate job' for boj-build and 'harden all 6' for the mirrors). boj-build.yml — was invalid YAML: the 'K9-SVC Validation' and 'Contractile Check' steps were indented at job level instead of step level, so GitHub could not load the workflow at all. Moved them into a new ungated job 'validate-contractiles' that runs on every push (the trigger-boj job is gated on BOJ_SERVER_URL, which must not gate repo self-validation). Both jobs gained timeout-minutes: 10. The completeness check was also wrong (hard-coded 'must trust dust lust adjust intend' — 'lust' does not exist, 'bust' was missing, and intend's file is Intentfile.a2ml not Intendfile); it now reads the canonical verb set from the registry (.machine_readable/contractiles/INDEX.a2ml), as INDEX itself instructs consumers to do. Verified green locally: all 6 contractiles present. mirror-reusable.yml — the six SSH-based mirror jobs (gitlab, bitbucket, codeberg, sourcehut, disroot, gitea) ran webfactory/ssh-agent with an inherited SSH key gated only on vars.<FORGE>_MIRROR_ENABLED, so an enabled-but-unconfigured repo fed ssh-agent an empty key and failed. Applied the existing Radicle pattern: gate the ssh-agent and push steps on secrets.<FORGE>_SSH_KEY != '' and add a Skipped notice step on == '' so the job ends cleanly with an actionable ::notice:: instead of erroring. https://claude.ai/code/session_01XZhw6Fq27eoeyEB4LR3a2c
🔍 Hypatia Security ScanFindings: 141 issues detected
View findings[
{
"reason": "Action for the check script)\n uses: actions/checkout@de0f needs attention",
"type": "unpinned_action",
"file": "governance-reusable.yml",
"action": "pin_sha",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Action for the check script)\n uses: actions/checkout@de0f needs attention",
"type": "unpinned_action",
"file": "governance-reusable.yml",
"action": "pin_sha",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in governance.yml",
"type": "missing_timeout_minutes",
"file": "governance.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in mirror.yml",
"type": "missing_timeout_minutes",
"file": "mirror.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in scorecard.yml",
"type": "missing_timeout_minutes",
"file": "scorecard.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in secret-scanner.yml",
"type": "missing_timeout_minutes",
"file": "secret-scanner.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in scorecard-enforcer.yml",
"type": "scorecard_publish_with_run_step",
"file": "scorecard-enforcer.yml",
"action": "split_scorecard_publish_job",
"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"
},
{
"reason": "Python file detected -- banned language",
"type": "banned_language_file",
"file": "/home/runner/work/standards/standards/a2ml-templates/state-scm-to-v2.py",
"action": "flag",
"rule_module": "cicd_rules",
"severity": "critical"
},
{
"reason": "TypeScript file detected -- banned language",
"type": "banned_language_file",
"file": "/home/runner/work/standards/standards/lol/test/vitest.config.ts",
"action": "flag",
"rule_module": "cicd_rules",
"severity": "critical"
}
]Powered by Hypatia Neurosymbolic CI/CD Intelligence |
hyperpolymath
added a commit
that referenced
this pull request
Jun 3, 2026
## Scan the `actions` language with CodeQL Adds an `actions` entry to the CodeQL matrix (`build-mode: none`) so CodeQL scans the repo's GitHub Actions workflow files for security issues, alongside the existing `javascript-typescript` analysis. Resolves the Hypatia `workflow_audit` finding `codeql_missing_actions_language` (surfaced on #362 once the medium-severity timeout noise was cleared). ```diff include: - language: javascript-typescript build-mode: none + - language: actions + build-mode: none ``` ### Why a separate PR Per owner request — this enables a **new analysis target**, isolated from the workflow-hygiene work (#360, #362) so the new scan is easy to review on its own. It may surface new code-scanning alerts on existing workflows; those would be triaged normally. ### Also in this PR: registry sync (required to pass `registry-verify`) This branch was cut before #356 + #361 landed on `main`. After merging `main` in, the `registry-verify` gate failed because **`main`'s committed `.machine_readable/REGISTRY.a2ml` is itself stale** — #361's estate-wide workflow edits changed files under tracked spec-home dirs without re-running `just registry`, leaving 9 `source_hash` entries out of date. Regenerated deterministically via `scripts/build-registry.sh`; `--check` now exits clean. (Heads-up: `main`'s own `registry-verify` is likely red until this lands or a dedicated regen does.) PR diff vs `main`: `codeql.yml` (+2) and the regenerated `REGISTRY.a2ml`. 🤖 Draft. https://claude.ai/code/session_01XZhw6Fq27eoeyEB4LR3a2c Co-authored-by: Claude <noreply@anthropic.com>
Resolves a conflict in boj-build.yml: main's #361 fixed the malformed workflow by DELETING the two orphaned steps, while this PR fixes them by moving them into a new ungated 'validate-contractiles' job (the owner- chosen approach). Kept this PR's validate-contractiles job and adopted main's 'timeout-minutes: 10' on trigger-boj (removed the duplicate timeout key the auto-merge produced). Registry is in sync on the merge result (this PR touches no tracked spec home); main's earlier registry drift was already cleared by #364/#366. https://claude.ai/code/session_01XZhw6Fq27eoeyEB4LR3a2c
🔍 Hypatia Security ScanFindings: 147 issues detected
View findings[
{
"reason": "Action for the check script)\n uses: actions/checkout@de0f needs attention",
"type": "unpinned_action",
"file": "governance-reusable.yml",
"action": "pin_sha",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Action for the check script)\n uses: actions/checkout@de0f needs attention",
"type": "unpinned_action",
"file": "governance-reusable.yml",
"action": "pin_sha",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in governance.yml",
"type": "missing_timeout_minutes",
"file": "governance.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in mirror.yml",
"type": "missing_timeout_minutes",
"file": "mirror.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in scorecard.yml",
"type": "missing_timeout_minutes",
"file": "scorecard.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in secret-scanner.yml",
"type": "missing_timeout_minutes",
"file": "secret-scanner.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in scorecard-enforcer.yml",
"type": "scorecard_publish_with_run_step",
"file": "scorecard-enforcer.yml",
"action": "split_scorecard_publish_job",
"rule_module": "workflow_audit",
"severity": "high"
},
{
"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": "Python file detected -- banned language",
"type": "banned_language_file",
"file": "/home/runner/work/standards/standards/a2ml-templates/state-scm-to-v2.py",
"action": "flag",
"rule_module": "cicd_rules",
"severity": "critical"
},
{
"reason": "TypeScript file detected -- banned language",
"type": "banned_language_file",
"file": "/home/runner/work/standards/standards/lol/test/vitest.config.ts",
"action": "flag",
"rule_module": "cicd_rules",
"severity": "critical"
}
]Powered by Hypatia Neurosymbolic CI/CD Intelligence |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Workflow hardening — round 2
Follow-up to #360, closing the remaining real
workflow_auditfindings (the rest were false positives — see below). Owner decisions: new separate job for boj-build, harden all 6 mirror jobs.boj-build.yml— fix invalid YAML + correct the validationThe
K9-SVC ValidationandContractile Checksteps were indented at job level instead of step level, so the file was invalid YAML and GitHub could not load the workflow at all.validate-contractilesthat runs on every push. (They validate this repo's contractile set, so they must not sit behindtrigger-boj'sif: BOJ_SERVER_URL configuredguard.)timeout-minutes: 10.must trust dust lust adjust intend— butlustdoesn't exist,bustwas missing, and intend's file isIntentfile.a2ml(notIntendfile). It now reads the canonical verb set from the registry (.machine_readable/contractiles/INDEX.a2ml), exactly as INDEX instructs consumers to do — so it's correct now and self-maintaining as verbs change.adjust, bust, dust, intend, must, trust) present; script exits 0.mirror-reusable.yml— secret-presence gate on the 6 SSH mirrorsThe gitlab/bitbucket/codeberg/sourcehut/disroot/gitea jobs ran
webfactory/ssh-agentwith an inherited SSH key gated only onvars.<FORGE>_MIRROR_ENABLED. An enabled-but-unconfigured repo fed ssh-agent an empty key and failed. Applied the existing Radicle pattern already in this file:ssh-agent+ push steps onsecrets.<FORGE>_SSH_KEY != ''Skipped (<FORGE>_SSH_KEY not configured)step on== ''that emits an actionable::notice::and ends the job cleanly.On the findings not addressed (deliberately)
unpinned_action(governance-reusable.yml) — false positive. Everyuses:is already pinned to a full 40-char SHA; Hypatia truncates it to@de0fin its own message.missing_timeout_minuteson governance.yml / mirror.yml / scorecard.yml / secret-scanner.yml — false positives. These are reusable-workflow caller jobs;timeout-minutesis invalid on auses:job. Their timeouts live in the called workflows (fixed in ci(workflows): add timeout-minutes to every job + fix changelog YAML #360 + here).scorecard_publish_with_run_step(scorecard-enforcer.yml) — false positive. Thescorecardjob that publishes already contains onlyuses:steps; therun:steps are in separate jobs. Already compliant (the author documented the split).Validation
timeout-minutes.!= ''gates (6 ssh-agent + 6 push + 3 radicle) and 7 skip-notice steps.🤖 Draft.
https://claude.ai/code/session_01XZhw6Fq27eoeyEB4LR3a2c
Generated by Claude Code