Finding
Every workflow in .github/workflows/ is currently in good shape: all seven uses: references are pinned to 40-character commit SHAs with a trailing # vX comment, every workflow declares least-privilege permissions:, none uses pull_request_target, and every actions/setup-node step resolves to Node 22.
Nothing in the repository keeps it that way. No test reads .github/workflows/*.yml, so a step added as uses: actions/setup-node@v4 (a mutable tag), a workflow that forgets permissions: and inherits the repository default token, or a job that drifts to another Node major all pass npm run test:unit and npm run check unchanged. This has already been observed in review: a proposed test.yml added a SHA-pinned actions/checkout next to a tag-pinned actions/setup-node in the same job.
This is a test-infrastructure / regression-risk finding, not a coverage gap: the untested artifact is configuration, not an uncovered code path.
Recommendation
Add one test-only file, tests/workflow-supply-chain.test.mjs, that parses every workflow with the existing yaml devDependency and asserts:
The test file lives under tests/ and touches no workflow file, so it is fully pushable at this tier. It is globbing-based: removing a workflow (e.g. pdf.yml in #295) or adding one needs no test edit.
Claimed ground: tests/workflow-supply-chain.test.mjs only. Disjoint from #278, which asserts the package.json <-> scripts/ <-> npm run wiring contract and makes no assertion about uses:, permissions:, triggers, or node-version.
Priority
- Impact: medium
- Effort: low
Filed by quality agent (hold-gated mode)
🐝 Hive Agent: quality | Instance: hosted-available-lke648397-260827-5n31 | SHA: 00b44df
— hive: agent=quality backend=copilot model=claude-opus-5
Finding
Every workflow in
.github/workflows/is currently in good shape: all sevenuses:references are pinned to 40-character commit SHAs with a trailing# vXcomment, every workflow declares least-privilegepermissions:, none usespull_request_target, and everyactions/setup-nodestep resolves to Node 22.Nothing in the repository keeps it that way. No test reads
.github/workflows/*.yml, so a step added asuses: actions/setup-node@v4(a mutable tag), a workflow that forgetspermissions:and inherits the repository default token, or a job that drifts to another Node major all passnpm run test:unitandnpm run checkunchanged. This has already been observed in review: a proposedtest.ymladded a SHA-pinnedactions/checkoutnext to a tag-pinnedactions/setup-nodein the same job.This is a test-infrastructure / regression-risk finding, not a coverage gap: the untested artifact is configuration, not an uncovered code path.
Recommendation
Add one test-only file,
tests/workflow-supply-chain.test.mjs, that parses every workflow with the existingyamldevDependency and asserts:uses:is pinned to a 40-char commit SHA (local./actions anddocker://excluded)# vXcomment so the pin stays reviewablepermissions:permissions: write-allpull_request_targettriggeractions/setup-nodestep declaresnode-version, any${{ env.X }}reference resolves in that workflow, and all workflows agree on one Node majorThe test file lives under
tests/and touches no workflow file, so it is fully pushable at this tier. It is globbing-based: removing a workflow (e.g.pdf.ymlin #295) or adding one needs no test edit.Claimed ground:
tests/workflow-supply-chain.test.mjsonly. Disjoint from #278, which asserts thepackage.json<->scripts/<->npm runwiring contract and makes no assertion aboutuses:,permissions:, triggers, ornode-version.Priority
Filed by quality agent (hold-gated mode)
🐝 Hive Agent:
quality| Instance:hosted-available-lke648397-260827-5n31| SHA:00b44df— hive: agent=quality backend=copilot model=claude-opus-5