Skip to content

ci: add trusted npm release gates - #67

Merged
jsleemaster merged 6 commits into
mainfrom
codex/critical-roadmap-hardening
Jul 16, 2026
Merged

ci: add trusted npm release gates#67
jsleemaster merged 6 commits into
mainfrom
codex/critical-roadmap-hardening

Conversation

@jsleemaster

Copy link
Copy Markdown
Owner

What changed

  • add a manual, OIDC-only npm publish workflow with exact main/source SHA binding
  • prepare one tarball, pass the same immutable Actions artifact through approval, and publish without repacking
  • require draft release target, assets, GitHub asset digests, and absent version tag before npm publication
  • pin every GitHub Action to a full commit SHA and disable persisted checkout credentials
  • add SECURITY.md, the release contract, and a dependency-free supply-chain validator

Why

The repository had no trusted-publishing path, no required supply-chain policy check, mutable Action tags, and release documentation that could not prove the npm artifact, provenance, and GitHub release referred to the same source.

Impact

This does not publish npm or mutate consumer files. It adds release-only CI policy and documentation. Live npm-release, trusted publisher, release immutability, registry publication, and provenance readback remain explicit post-merge gates.

Validation

  • npm run validate
  • git diff --check 36be35f..HEAD
  • npm pack --dry-run
  • Node syntax check for the validator
  • YAML parsing for all workflows
  • 32 negative mutation cases covering trigger, permission, checkout, repack, metadata, concurrency, draft, tag, step-order, and YAML-scalar bypasses
  • independent task review: Critical 0, Important 0, ready to merge

Repository note: there is one maintainer, so GitHub's independent approval requirement cannot be satisfied by a second collaborator. Do not confuse the independent task review above with a GitHub approval; any merge must use the existing documented admin exception after CI is green.

Refs #57
Refs #55

@jsleemaster
jsleemaster marked this pull request as ready for review July 16, 2026 07:23
@jsleemaster
jsleemaster merged commit c8b16c8 into main Jul 16, 2026
3 checks passed
@jsleemaster
jsleemaster deleted the codex/critical-roadmap-hardening branch July 16, 2026 07:24

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5c8a7949f9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

requireText(publish, 'release-artifact/${{ needs.prepare.outputs.tarball }}', publishFile);
requireText(publish, 'npm publish "release-artifact/${{ needs.prepare.outputs.tarball }}"', publishFile);
check(
publish.trimEnd().endsWith('run: npm publish "release-artifact/${{ needs.prepare.outputs.tarball }}"'),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Reject earlier npm publish commands

Because this only checks that the file ends with the approved npm publish, validate:supply-chain still passes if a new publish-job step after Download prepared release artifact runs npm publish ... before the artifact/draft-release gates; I verified by inserting such a step and the validator still reported OK. Since npm publish --help identifies this as “Publish a package”, that bypass would publish once the npm-release environment is approved, before the machine checks this workflow is meant to enforce.

Useful? React with 👍 / 👎.


const workflowDir = '.github/workflows';
const workflowFiles = fs.readdirSync(workflowDir)
.filter((name) => name.endsWith('.yml'))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Scan .yaml workflow files too

GitHub Actions accepts both .yml and .yaml workflow files (official syntax docs: “must have either a .yml or .yaml file extension”), but this directory scan drops everything except .yml. A future .github/workflows/*.yaml file can use mutable actions or checkout credentials and validate:supply-chain will still pass—I verified with an evil.yaml containing actions/checkout@v4—so the supply-chain policy is not actually repo-wide.

Useful? React with 👍 / 👎.

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.

1 participant