aiwg
Version:
Deployment tool and support utility for AI context. Copies agents, skills, commands, rules, and behaviors into the paths each AI platform reads (Claude Code, Codex, Copilot, Cursor, Warp, OpenClaw, and 6 more) so one source of truth works across 10 platfo
219 lines (158 loc) • 6.52 kB
Markdown
namespace: aiwg
name: pnpm-release-age-gate
platforms: [all]
description: Configure pnpm's minimumReleaseAge gate (7-day default, 10-day high-sensitivity) plus blockExoticSubdeps for workspace-scope dep-source enforcement. Includes Corepack detection and lockfile-caveat warning.
# pnpm-release-age-gate
Use this skill when a user has chosen pnpm as their package manager
and wants to apply the same release-age-gate hardening that
`npm-release-age-gate` provides for npm. pnpm is often the **preferred
baseline** for new projects because `minimumReleaseAge` AND
`blockExoticSubdeps` can be enforced at the workspace level — npm
has no equivalent for the latter.
## Triggers
- "pnpm release age gate"
- "pnpm minimumReleaseAge"
- "pnpm blockExoticSubdeps"
- "pnpm supply chain hardening"
- "configure pnpm 7 day gate"
## Prerequisites
- pnpm v9.0+ installed (`pnpm --version`)
- `package.json` exists at repo root
If pnpm is below v9.0, the skill should refuse to proceed and direct
the user to upgrade — `minimumReleaseAge` was introduced in v9.0 and
older versions silently ignore it.
## Configuration paths — pick one based on workspace shape
### Option A — Single-package repo (most common)
Add the gate to `.npmrc` at repo root:
```ini
# Refuse dependency versions published less than 7 days ago.
# pnpm interprets the value in MINUTES. 10080 = 7 days; 14400 = 10 days.
# Defends against newly-published malicious versions.
minimum-release-age=10080
# Reject git+, tarball-URL, file:, link: sources — these bypass
# registry signature verification (companion to npm-supply-chain-audit
# dep-source policy).
block-exotic-subdeps=true
```
### Option B — Multi-package workspace
Add the gate to `pnpm-workspace.yaml`:
```yaml
packages:
- 'packages/*'
- 'apps/*'
# Workspace-scope release-age enforcement.
# Value is in MINUTES. 10080 = 7 days; 14400 = 10 days.
minimumReleaseAge: 10080
# Reject non-registry dep sources fleet-wide.
blockExoticSubdeps: true
```
Workspace-scope is the pnpm advantage over npm — every nested package
inherits the gate without per-package config.
### Option C — Operator-wide via pnpm global config
```bash
pnpm config set minimum-release-age 10080 # minutes — 7 days
pnpm config set block-exotic-subdeps true
```
Use this only when the entire dev machine should apply the gate
across all projects. Per-repo config (Option A or B) is preferred —
it travels with the repo and works in CI without machine setup.
## Unit conversion reference
pnpm uses **minutes** for `minimumReleaseAge`:
| Days | Minutes value |
|---|---|
| 1 | `1440` |
| 7 (recommended default) | `10080` |
| 10 (high-sensitivity profile) | `14400` |
| 14 | `20160` |
| 30 | `43200` |
This differs from npm (`min-release-age` in **days**) and Bun
(`install.minimumReleaseAge` in **seconds**). Document the unit
inline when committing the config so future readers don't misread it.
## Lockfile caveat
The gate must be active **before** `pnpm install` or `pnpm update`
resolves dependencies. If the existing `pnpm-lock.yaml` was generated
without the gate, the gate is checked on the NEXT resolution pass —
not retroactively against the lockfile.
To apply the gate retroactively:
```bash
# Force re-resolution with the gate active
rm pnpm-lock.yaml
pnpm install
```
This is destructive to existing pins and may pull in newer
intermediate versions. Coordinate with the team before running.
## Corepack detection
Check whether the project pins a pnpm version via Corepack:
```bash
node -p "require('./package.json').packageManager"
```
Output like `pnpm@9.15.0` means Corepack will use that exact version
in CI. The skill should:
1. Confirm the pinned version is ≥ v9.0 (else flag — gate is silently ignored)
2. Document the pinned version in the audit output
3. Suggest a Corepack pin if the project doesn't have one yet:
```bash
corepack use pnpm@latest
# writes packageManager to package.json
```
## Override policy
Genuine emergency overrides:
```bash
# One-off install bypassing the gate
pnpm install <pkg>@<version> --ignore-min-release-age
# Permanently allow a specific package (rare; record rationale in
# a SECURITY-OVERRIDE.md or equivalent)
```
Document every override with reason + sunset date. Overrides should
be reviewed quarterly.
## CI integration
Add a verification step to the publish/build workflow:
```yaml
- name: Verify pnpm gate active
run: |
set -euo pipefail
AGE=$(pnpm config get minimum-release-age 2>/dev/null || echo "0")
EXOTIC=$(pnpm config get block-exotic-subdeps 2>/dev/null || echo "false")
if [ "$AGE" -lt 10080 ] || [ "$EXOTIC" != "true" ]; then
echo "✗ pnpm gate not configured to baseline (minimumReleaseAge≥10080, blockExoticSubdeps=true)"
exit 1
fi
echo "✓ pnpm gate active: $AGE minutes, blockExoticSubdeps=$EXOTIC"
```
## What to inspect during review
- `.npmrc` OR `pnpm-workspace.yaml` for `minimumReleaseAge` and `blockExoticSubdeps`
- `package.json` `packageManager` field for Corepack pin
- CI workflow has the verification step above
- `pnpm-lock.yaml` was generated AFTER the gate was committed (timestamp check)
## Output format
When auditing an existing pnpm project, produce a structured report
at `.aiwg/security/working/pnpm-release-age-audit.md`:
```markdown
# pnpm Release-Age Gate Audit
**pnpm version**: <version> (Corepack pinned: yes/no)
**Workspace shape**: single-package / multi-package
**Gate active**: yes (10080 min) / yes (custom: <value>) / no
**blockExoticSubdeps**: true / false / unset
## Findings
### <severity> — <description>
- File: <path>
- Issue: <what's wrong>
- Fix: <exact change>
## Clean Checks
- ...
## Recommendations
- ...
```
## See Also
- [`npm-release-age-gate` skill](../npm-release-age-gate/SKILL.md) — npm equivalent
- [`yarn-release-age-gate` skill](../yarn-release-age-gate/SKILL.md) — Yarn equivalent
- [`bun-release-age-gate` skill](../bun-release-age-gate/SKILL.md) — Bun equivalent
- [`npm-supply-chain-audit` skill](../npm-supply-chain-audit/SKILL.md) — companion audit
- [`supply-chain-hardening-quickstart` skill](../supply-chain-hardening-quickstart/SKILL.md) — orchestrator
## References
- pnpm `minimumReleaseAge`: <https://pnpm.io/settings#minimumreleaseage>
- pnpm `blockExoticSubdeps`: <https://pnpm.io/settings#blockexoticsubdeps>
- pnpm workspace settings: <https://pnpm.io/pnpm-workspace_yaml>
- Corepack: <https://github.com/nodejs/corepack>