Skip to content

Check pgstencil's npm signature and provenance attestation before a Hosted production deploy - #1245

Merged
nedtwigg merged 4 commits into
mainfrom
hosted-deploy-provenance
Oct 20, 2026
Merged

nedtwigg merged 4 commits into
mainfrom
hosted-deploy-provenance

Conversation

@nedtwigg

@nedtwigg nedtwigg commented Oct 20, 2026 •

Copy link
Copy Markdown
Member

Hosted's production verify job, which deploy needs, now asks npm whether each installed pgstencil package has a valid registry signature and a verified SLSA provenance attestation before anything ships.

Until now the production workflow checked pgstencil only through verifyPackages, which reads each package's own dist/provenance.json. The attestation checks in docs/specs/security-hosted.md -> "Deployment boundary" ran only in the nightly security audit, so a pgstencil bump deployed between two nightly runs went out on the self-reported file alone.

What changed

  • .github/workflows/hosted-production.yml: after the existing verifyPackages step, one step runs npm audit signatures --json --include-attestations in hosted/ and uses jq to fail the job unless neither pgstencil nor @pgstencil/auth is listed as invalid or missing, and both appear as verified with a provenance attestation. npm's own exit code covers every package in Hosted's tree, so it is ignored and only pgstencil's packages gate the deploy. Permissions, pins, and actions are unchanged; no token is needed.
  • S119 in docs/specs/security-hosted.md now has the verify job's check as its first clause. The deeper check, that the attestation's certificate names pgstencil's release workflow on main at the dist/provenance.json commit, stays with the nightly audit, as does S120 (the commit is on pgstencil main and passed its audit). The reasoning is in security-hosted.rationale.md.
  • .github/audit/hosted.md: the attestation instructions now run the same npm command in hosted/ as the job does, and judge S119's new clause against that step.
  • Relay guarantee row in security-hosted.md: it now says entitlement is rechecked whenever a request or socket is admitted, and that a socket already open for a removed or de-entitled computer is closed no later than the room's sweep. That is the bound S115 already sets; the old wording implied every request is rechecked.

Tests

  • Ran the step's commands locally against the installed pgstencil 0.4.0: it passes. Fed the jq filter edited copies of that output: dropping either package from verified, removing its provenance attestation, or listing it as invalid or missing each fails; an invalid unrelated package passes; npm's error output fails.
  • pnpm lint:workflows, node --test hosted/scripts/*.test.mjs, node scripts/spec-lint.mjs, node scripts/md-unwrap.mjs.

This touches .github/, so the owner merges it.

🤖 Generated with Claude Code

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

Deploying mouseterm with  Cloudflare Pages  Cloudflare Pages

Latest commit: bf57ff9
Status: ✅  Deploy successful!
Preview URL: https://c0e8da9a.mouseterm.pages.dev
Branch Preview URL: https://hosted-deploy-provenance.mouseterm.pages.dev

View logs

@dormouse-bot dormouse-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The diff looks correct and I have no findings. I'm holding the approval only because Workflow Lint is red at this head. The failure isn't from this PR: zizmor flags ref-version-mismatch on the swatinem/rust-cache pin at .github/workflows/ci.yml:403, and main's latest CI run (39445113310) fails Workflow Lint with the same annotation.

…d production deploy

The production verify job now runs hosted/scripts/pgstencil-provenance.mjs,
which verifies each installed pgstencil package's npm SLSA attestation (the
Fulcio signer and source digest, the statement's subject against the locked
integrity, its workflow and commit) and that the commit is on pgstencil main
with a passing security-audit. These checks previously ran only nightly. The
specs make the deploy-time check the audited property, the hosted audit
prompt runs the same script, and the Relay guarantee row now states that an
open socket closes by the room's sweep.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@nedtwigg
nedtwigg force-pushed the hosted-deploy-provenance branch from 80d4524 to a52bb1e Compare October 20, 2026 15:53
…spec text

Move verifyPackages into hosted/scripts/pgstencil-provenance.mjs, which
production.mjs now imports for its preflight and deploy call, so the
provenance script no longer loads the deploy orchestration. Drop a test
the subject cases already cover, and point the audit prompt, hosted.md,
and the rationale at S119/S120 and the code instead of restating them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…duction verify job

Replace the provenance script with one workflow step: `npm audit signatures --include-attestations` in `hosted/`, failing the job unless both pgstencil packages have a valid registry signature and a verified provenance attestation. The nightly audit keeps the deeper check that the attestation names pgstencil's release workflow at the provenance commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@nedtwigg nedtwigg changed the title Check pgstencil's signed provenance and audited commit before a Hosted production deploy Check pgstencil's npm signature and provenance attestation before a Hosted production deploy Oct 20, 2026
Comment thread docs/specs/security-hosted.md Outdated
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@nedtwigg
nedtwigg merged commit 16d2137 into main Oct 20, 2026
11 checks passed
@nedtwigg
nedtwigg deleted the hosted-deploy-provenance branch October 20, 2026 16:35
@nedtwigg nedtwigg mentioned this pull request Oct 21, 2026
7 tasks done
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