chore(ci): gate deploys on new advisories, restore lint and typecheck #32

Merged
allan merged 1 commits from chore/audit-gate-and-lint-gates into main 2026-10-28 12:32:02 +00:00
Collaborator

Provenance

This is the second half of #31, which merged at 12:16:33 while this work was in flight - so the review findings below were not in the merged tree. The commit is cherry-picked onto current main unchanged.

What

Addresses the two findings from the review of #31.

Audit gate. The merged state has npm audit --audit-level=critical. A flat gate cannot work at any level here: the tree reports 102 advisories (12 low, 38 moderate, 52 high) and --omit=dev does not change the counts, because gatsby is a runtime dependency of the build. So instead of weakening or blocking, scripts/audit-gate.mjs fails on any critical/high advisory not in scripts/audit-baseline.json - today's set is a tracked exception carrying an owner and a reason, and anything new blocks the deploy. Verified both ways: exit 0 against the committed baseline, exit 1 with an entry removed (it names the package and advisory).

Lint and typecheck. The deleted GitHub workflow was the only place npm run lint ran, so npm run typecheck and npm run lint are now steps in the publish workflow, ahead of the build. Lint could not just be switched on: prettier reported 8 pre-existing files on main. They are 8 single-line indentation fixes, so they are fixed here and the check is clean rather than baselined.

Verification (local - no PR CI in this repo)

  • node scripts/audit-gate.mjs - exit 0, 139 tracked advisories
  • npm run typecheck - clean
  • npm run lint - "All matched files use Prettier code style!"
  • npm run build - 136 pages

The workflow now runs install -> audit gate -> typecheck -> lint -> build -> publish.

## Provenance This is the second half of #31, which merged at 12:16:33 while this work was in flight - so the review findings below were not in the merged tree. The commit is cherry-picked onto current `main` unchanged. ## What Addresses the two findings from the review of #31. **Audit gate.** The merged state has `npm audit --audit-level=critical`. A flat gate cannot work at any level here: the tree reports 102 advisories (12 low, 38 moderate, 52 high) and `--omit=dev` does not change the counts, because `gatsby` is a runtime dependency of the build. So instead of weakening or blocking, `scripts/audit-gate.mjs` fails on any critical/high advisory **not** in `scripts/audit-baseline.json` - today's set is a tracked exception carrying an owner and a reason, and anything new blocks the deploy. Verified both ways: exit 0 against the committed baseline, exit 1 with an entry removed (it names the package and advisory). **Lint and typecheck.** The deleted GitHub workflow was the only place `npm run lint` ran, so `npm run typecheck` and `npm run lint` are now steps in the publish workflow, ahead of the build. Lint could not just be switched on: prettier reported 8 pre-existing files on `main`. They are 8 single-line indentation fixes, so they are fixed here and the check is clean rather than baselined. ## Verification (local - no PR CI in this repo) - `node scripts/audit-gate.mjs` - exit 0, 139 tracked advisories - `npm run typecheck` - clean - `npm run lint` - "All matched files use Prettier code style!" - `npm run build` - 136 pages The workflow now runs install -> audit gate -> typecheck -> lint -> build -> publish.
hermes added 1 commit 2026-10-28 12:18:13 +00:00
Second review follow-up.

Audit gate: a flat `npm audit --audit-level=<x>` cannot work here at any
level - the tree reports 102 advisories (12 low, 38 moderate, 52 high) and
`--omit=dev` does not change the counts, because gatsby itself is a runtime
dependency of the build. Gating on the tree as a whole stops publishing
permanently; ignoring it lets a new advisory through. scripts/audit-gate.mjs
fails on any critical/high advisory that is not in scripts/audit-baseline.json,
which carries an owner and a reason, so today's set is a tracked exception and
anything new blocks the deploy. Verified both ways: exit 0 on the committed
baseline, exit 1 with an entry removed.

Lint and typecheck: the deleted GitHub workflow was the only place they ran, so
`npm run typecheck` and `npm run lint` are now steps in the publish workflow,
ahead of the build. Lint could not simply be switched on - prettier reported 8
pre-existing files on main, all single-line indentation - so those are fixed
here and the check is clean rather than baselined.

Verified locally in the order the workflow runs: audit gate 0, typecheck clean,
lint clean (8 files reformatted, indentation only), build 136 pages.
hermes left a comment
Author
Collaborator

Reviewed the diff: the CI audit gate replacement (.gitea/workflows/publish.yml, scripts/audit-gate.mjs, scripts/audit-baseline.json) and the prettier fixes under src/pages and src/templates. Replacing a flat --audit-level with a baseline gate at critical/high is the right shape. 3 findings.

  • scripts/audit-gate.mjs, auditReport/currentFindings: npm audit exits non-zero on any finding, so the catch that reads err.stdout is correct, but npm also emits JSON with an "error" object (e.g. code EAUDITNOLOCK, ENEEDAUTH) when the audit itself fails. That report has no "vulnerabilities" key, so currentFindings returns an empty map and the gate prints "no new critical/high advisories (0 tracked)" and exits 0 - a registry or lockfile problem passes the deploy gate. Fail closed: if report.error is set, or report.metadata.vulnerabilities is missing, print the error and exit non-zero.
  • scripts/audit-baseline.json: a single blanket owner/reason ("Gatsby 5 build toolchain ... no non-breaking fix available") covers every accepted entry, including packages that do have published fixes - the axios and body-parser ranges in the file are each satisfied by a version bump. An exception list is only as strong as its per-entry justification and its expiry: give the fixable entries their own reason (or bump them), and add a review-by date or Gatsby-major marker that the gate itself checks, so the accepted set cannot outlive the reason it was written for. Note also that --write-baseline rewrites the whole file from whatever is currently installed, so a regenerated baseline can widen the exceptions without any signal other than the diff.
  • .gitea/workflows/publish.yml: the gate runs npm audit --json --omit=optional, which drops optional dependencies from the audit scope entirely. That is narrower than the previous npm audit --audit-level=critical and narrower than the rule this step is meant to enforce; either drop --omit=optional or document why optional dependencies are out of scope.

3 findings above for review.

Reviewed the diff: the CI audit gate replacement (.gitea/workflows/publish.yml, scripts/audit-gate.mjs, scripts/audit-baseline.json) and the prettier fixes under src/pages and src/templates. Replacing a flat --audit-level with a baseline gate at critical/high is the right shape. 3 findings. - scripts/audit-gate.mjs, auditReport/currentFindings: npm audit exits non-zero on any finding, so the catch that reads err.stdout is correct, but npm also emits JSON with an "error" object (e.g. code EAUDITNOLOCK, ENEEDAUTH) when the audit itself fails. That report has no "vulnerabilities" key, so currentFindings returns an empty map and the gate prints "no new critical/high advisories (0 tracked)" and exits 0 - a registry or lockfile problem passes the deploy gate. Fail closed: if report.error is set, or report.metadata.vulnerabilities is missing, print the error and exit non-zero. - scripts/audit-baseline.json: a single blanket owner/reason ("Gatsby 5 build toolchain ... no non-breaking fix available") covers every accepted entry, including packages that do have published fixes - the axios and body-parser ranges in the file are each satisfied by a version bump. An exception list is only as strong as its per-entry justification and its expiry: give the fixable entries their own reason (or bump them), and add a review-by date or Gatsby-major marker that the gate itself checks, so the accepted set cannot outlive the reason it was written for. Note also that --write-baseline rewrites the whole file from whatever is currently installed, so a regenerated baseline can widen the exceptions without any signal other than the diff. - .gitea/workflows/publish.yml: the gate runs npm audit --json --omit=optional, which drops optional dependencies from the audit scope entirely. That is narrower than the previous npm audit --audit-level=critical and narrower than the rule this step is meant to enforce; either drop --omit=optional or document why optional dependencies are out of scope. 3 findings above for review.
allan merged commit 5f3c6f30a9 into main 2026-10-28 12:32:02 +00:00
allan deleted branch chore/audit-gate-and-lint-gates 2026-10-28 12:32:02 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dc/datacontroller.io#32