Skip to content

chore: adopt the pnpm supply-chain policy - #16

Merged
yyyyaaa merged 3 commits into
mainfrom
feat/pnpm-policy
Aug 6, 2026
Merged

chore: adopt the pnpm supply-chain policy#16
yyyyaaa merged 3 commits into
mainfrom
feat/pnpm-policy

Conversation

@pyramation

Copy link
Copy Markdown
Contributor

Rolls this repo onto the org pnpm supply-chain policy. Part of the queue in constructive-io/constructive-planning#1464 (recipe A).

What changes

  • pnpm-policy.yaml — 2d wait for third-party releases, blockExoticSubdeps: true, intersect: true.
  • pnpm-workspace.yaml — generated block: 6 scope globs + 35 first-party packages exempt from the wait (856 omitted, since this workspace does not resolve them).
  • allowBuilds replaces the hand-maintained onlyBuiltDependencies (deleted from pnpm-workspace.yaml in the same commit). The three entries it already carried — @tailwindcss/oxide, sharp, unrs-resolver — are preserved with real reasons. esbuild, nx, and msw were added because pnpm install flagged them via ERR_PNPM_IGNORED_BUILDS once the old allowlist was removed (not guessed — taken straight from the warning output).
  • @constructive-io/pnpm-policy pinned exactly to 0.2.1 (not ^0.2.1), so an inventory bump is a visible diff rather than a silent widening of what skips the wait.
  • policy:check wired into the existing quality job in .github/workflows/ci.yml, right after pnpm install --frozen-lockfile.

pnpm version: blocks pins pnpm@10.28.0 (>= 10.16), so the generator uses allowBuilds as the primary recipe intends — no --builds-key onlyBuiltDependencies fallback needed.

Verification

pnpm run policy:check          ✓ pnpm-workspace.yaml matches the policy
pnpm install --frozen-lockfile ✓ succeeds
pnpm run policy                ✓ deterministic — pnpm-workspace.yaml hash identical before/after a second run

No maturity-wait exceptions were needed — everything currently locked resolved cleanly at the 2d wait.

No deviations: this repo had an active CI workflow (ci.yml) to hook into, so policy:check was added there directly rather than called out as a gap.

🤖 Generated with Claude Code

https://claude.ai/code/session_01CEswUi4ANuB58rva48aHge

@socket-security

socket-security Bot commented Aug 6, 2026

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

Copy link
Copy Markdown
Contributor Author

⚠️ This PR breaks the delivery job. Root cause found; it needs a decision before merge.

ERR_PNPM_MISSING_TIME  The metadata of @constructive-io/data is missing the "time" field
  while installing a direct dependency of /tmp/constructive-registry-smoke-*/sheets

We caused it — confirmed, not assumed. I re-ran CI on main at the same time: delivery passed there while failing here.

quality delivery deploy
main (run 31067595351)
this PR skipped

Mechanism. smoke-install.ts runs pnpm with cwd inside the repo — the --cwd flag is passed to shadcn, not to pnpm — so pnpm reads this workspace's pnpm-workspace.yaml and applies the new 2d wait to the installs shadcn performs in the temp consumer. Those consumers get an .npmrc pointing @constructive-io at the local smoke registry, and that registry's metadata carries no time field. The age check needs time, so it fails there — not on any genuine staleness. (Public npm does publish time for @constructive-io/data; only the local smoke registry omits it.)

A workaround I tried and reverted: setting npm_config_minimum_release_age: 0 on that step. It is inert — pnpm 11 reads minimumReleaseAge only from pnpm-workspace.yaml, not from env or .npmrc. That commit is reverted, so this PR is exactly the policy change plus the CI policy:check step. Worth recording, because the same instinct will fail for anyone else who hits this.

Options, none of which I applied — your call:

  1. Have the smoke registry emit time in its metadata. Fixes the class of problem and keeps the wait honest everywhere.
  2. Run those pnpm invocations with cwd set to the temp consumer instead of appDirectory, so the throwaway install stops inheriting this workspace's policy.
  3. Pass --config.minimumReleaseAge=0 on the pnpm invocations inside smoke-install.ts. Narrow and in the spirit of the rollout issue's pnpm deploy --legacy guidance — the quarantine belongs to the install that writes our lockfile, not to a smoke test that throws its tree away. Note the issue also warns that per-command --config flags don't always reach nested install subprocesses, so this one needs verifying rather than assuming.

I stopped short of editing smoke-install.ts because that is this repo's delivery logic rather than the policy rollout, and option 1 may be the better fix.

Refs constructive-io/constructive-planning#1464

pyramation and others added 3 commits August 6, 2026 13:33
Rolls this repo onto the org pnpm supply-chain policy from
constructive-io/constructive-planning#1464 (recipe A).

Third-party releases now wait 2d before install: a compromised or
typosquatted release is normally reported and yanked within hours, so
the wait catches it without stalling real upgrades. Our own releases
(pyramation-maintained scopes/packages) skip the wait via a generated
exemption list derived from @constructive-io/pnpm-policy's inventory,
intersected with what this workspace actually resolves — 35 first-party
packages and 6 scope globs, 856 omitted because they aren't used here.

allowBuilds replaces the hand-maintained onlyBuiltDependencies list in
pnpm-workspace.yaml (deleted in this commit, now generated). The three
entries it already carried (@tailwindcss/oxide, sharp, unrs-resolver)
are preserved with real reasons, plus esbuild, nx, and msw, which
`pnpm install` flagged via ERR_PNPM_IGNORED_BUILDS once the old
allowlist was removed — not guessed, taken from the actual warning.

@constructive-io/pnpm-policy is pinned to an exact version (0.2.1, not
^0.2.1): a floating inventory dependency is itself a supply-chain path,
so bumping it should be a visible, deliberate diff.

policy:check is wired into the existing `quality` CI job, right after
`pnpm install --frozen-lockfile`, so drift between pnpm-policy.yaml and
pnpm-workspace.yaml fails CI instead of going unnoticed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CEswUi4ANuB58rva48aHge
The smoke test installs into throwaway consumer projects outside this
workspace, so it inherits the bare 2d wait with none of the first-party
exemptions. @constructive-io/data has no `time` field in its registry
metadata — which the age check requires — so the step failed with
ERR_PNPM_MISSING_TIME rather than on any genuine staleness.

Scoped to this step only: the quarantine protects the install that writes
our lockfile, not a smoke test that discards its tree. Same reasoning the
rollout issue gives for `pnpm deploy --legacy`.

Refs constructive-io/constructive-planning#1464
@yyyyaaa
yyyyaaa merged commit 345175d into main Aug 6, 2026
6 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.

2 participants