Skip to content

Add pnpm supply-chain policy (recipe A) - #13

Merged
pyramation merged 1 commit into
mainfrom
feat/pnpm-policy
Aug 6, 2026
Merged

Add pnpm supply-chain policy (recipe A)#13
pyramation merged 1 commit into
mainfrom
feat/pnpm-policy

Conversation

@pyramation

Copy link
Copy Markdown
Contributor

What changed

Rolls out the org pnpm supply-chain policy (recipe A) to this repo, per constructive-io/constructive-planning#1464.

  • Added pnpm-policy.yaml at the workspace root — the human-editable source of truth (2-day minimumReleaseAge for third-party releases, blockExoticSubdeps: true, our maintainer/scopes, allowBuilds, exceptions: []).
  • Added pnpm-policy and @constructive-io/pnpm-policy (pinned exact 0.2.1, the currently published version — not ^0.2.1) as devDependencies.
  • Added root scripts:
    • "policy": "pnpm-policy generate"
    • "policy:check": "pnpm-policy check"
  • Ran pnpm run policy to patch the derived settings into pnpm-workspace.yaml under the Managed by pnpm-policy marker, then pnpm install.
  • Wired pnpm run policy:check into the existing .github/workflows/ci.yml, immediately after the existing pnpm install step.

allowBuilds

Four packages' postinstall scripts are needed by this workspace; everything else is denied by default:

package reason
electron postinstall downloads the platform-specific Electron binary that apps/desktop runs against; without it there is no Electron runtime to launch.
esbuild postinstall downloads/selects the correct platform-specific esbuild native binary used by the build toolchain; without it esbuild has no binary to invoke.
nx lerna's postinstall builds the Nx project graph and asserts native platform support for the workspace; skipping it leaves lerna's task graph uninitialized.
unrs-resolver postinstall (via napi-postinstall) downloads/selects the correct prebuilt native binary for the TypeScript resolver used by eslint; without it the resolver has no binary to load.

Deviation: bumped CI's pinned pnpm version

CI pinned pnpm/action-setup to 10.12.2. The allowBuilds key that pnpm-policy generate emits (the current, non-deprecated format) requires pnpm >= 10.16 to be honored — on 10.12.2 pnpm silently ignores it (exits 0, prints an "Ignored build scripts" warning, and never runs the postinstall scripts electron/esbuild/nx/unrs-resolver need). Using the older onlyBuiltDependencies key instead (which 10.12.2 does run builds for) turned out to have its own problem: after running builds via that key, pnpm 10.12.2 additionally appends its own unmanaged allowBuilds: <pkg>: set this to true or false stub to pnpm-workspace.yaml, which drifts from the policy-managed file and makes policy:check fail on the very next install — including in CI, right after the pnpm install step this PR adds policy:check after.

Rather than ship a CI step that's guaranteed to fail, I bumped pnpm/action-setup's pinned version to 10.34.5 (latest 10.x, well above the 10.16 threshold). Verified this version runs postinstall scripts correctly and produces no drift. No other CI changes were made — the existing checkout/setup-node/build/lint/test steps are untouched.

No git/URL transitive dependencies were found in pnpm-lock.yaml, so blockExoticSubdeps: true is set as the default (no override needed).

Verification (all run against pnpm 10.34.5, matching the updated CI pin, and re-confirmed against the local pnpm 11.11.0)

  • pnpm run policy:checkpnpm-workspace.yaml matches the policy
  • pnpm install --frozen-lockfile → succeeds cleanly (with CI=true to skip the interactive modules-purge confirmation, same as any real CI runner) ✓
  • pnpm run policy run twice → pnpm-workspace.yaml shasum identical before/after (deterministic) ✓

Not merging

Per instructions, this PR is opened for review only — not merged.

🤖 Generated with Claude Code

https://claude.ai/code/session_01CEswUi4ANuB58rva48aHge

Adds pnpm-policy.yaml as the source of truth for what this workspace
trusts, generated into pnpm-workspace.yaml. Third-party releases wait
2 days before install: a compromised release is normally reported and
yanked within hours, so the short wait catches it without stalling
legitimate upgrades. The minimumReleaseAge exemption list (first-party
packages under our scopes/maintainer) is derived from the pinned
@constructive-io/pnpm-policy inventory package rather than hand-maintained,
so it stays correct as we publish new packages.

allowBuilds is scoped to the four packages whose postinstall scripts this
workspace actually needs (electron, esbuild, nx, unrs-resolver), each with
a real reason — everything else is denied by default.

Bumps CI's pinned pnpm from 10.12.2 to 10.34.5: the allowBuilds config key
pnpm-policy emits requires pnpm >= 10.16 to be honored (older pnpm silently
ignores it, skipping postinstall builds pnpm-lock.yaml needs). Wires
`pnpm run policy:check` into the existing CI workflow right after
`pnpm install`.

Ref constructive-io/constructive-planning#1464
@socket-security

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Added@​constructive-io/​pnpm-policy@​0.2.17610010091100
Addedpnpm-policy@​0.2.27610010090100

View full report

@pyramation
pyramation merged commit 8b848d4 into main Aug 6, 2026
5 checks passed
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