diff --git a/.claude/hooks/check-new-deps/package.json b/.claude/hooks/check-new-deps/package.json
index ebfb39ac..1da79119 100644
--- a/.claude/hooks/check-new-deps/package.json
+++ b/.claude/hooks/check-new-deps/package.json
@@ -11,7 +11,7 @@
},
"dependencies": {
"@socketregistry/packageurl-js": "1.4.2",
- "@socketsecurity/lib": "5.18.2",
+ "@socketsecurity/lib": "5.21.0",
"@socketsecurity/sdk": "4.0.1"
},
"devDependencies": {
diff --git a/.config/esbuild.config.mts b/.config/esbuild.config.mts
index fcb578fb..96b5286c 100644
--- a/.config/esbuild.config.mts
+++ b/.config/esbuild.config.mts
@@ -241,8 +241,21 @@ function createNodeProtocolPlugin() {
* minimal lookup covering just those types.
*/
function createLibStubPlugin() {
+ // Heavy lib modules that are eagerly required but never exercised
+ // by the SDK's actual code paths.
+ //
+ // Never-reached by SDK gateway modules:
+ // - globs.js / sorts.js → only used by fs helpers the SDK skips
+ // - external/npm-pack.js / pico-pack.js → Arborist/pacote/fast-glob,
+ // SDK only needs validateFiles() from fs
+ //
+ // Never-reached transitive external shims:
+ // - external/cacache.js → destructures from npm-pack (already stubbed),
+ // SDK's cache-with-ttl path degrades gracefully
+ // - external/del.js → pulled in by fs's lazy getDel() for safeDelete,
+ // SDK never calls safeDelete/safeDeleteSync
const libStubPattern =
- /@socketsecurity\/lib\/dist\/(globs|sorts|external\/(npm-pack|pico-pack))\.js$/
+ /@socketsecurity\/lib\/dist\/(globs|sorts|external\/(npm-pack|pico-pack|cacache|del))\.js$/
const mimeDbPattern = /mime-db\/db\.json$/
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index a45102b9..4971707c 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -21,6 +21,6 @@ concurrency:
jobs:
ci:
name: Run CI Pipeline
- uses: SocketDev/socket-registry/.github/workflows/ci.yml@bbe46386c0a2bc6baefd02916234956a38e622d5 # main
+ uses: SocketDev/socket-registry/.github/workflows/ci.yml@d638c11f4bc7ac637e0f61f05729a54d68af40e0 # main
with:
test-script: 'pnpm run test --all --skip-build'
diff --git a/.github/workflows/generate.yml b/.github/workflows/generate.yml
index 9f5d7055..fe636165 100644
--- a/.github/workflows/generate.yml
+++ b/.github/workflows/generate.yml
@@ -46,14 +46,14 @@ jobs:
echo "Sleeping for $delay seconds..."
sleep $delay
- - uses: SocketDev/socket-registry/.github/actions/setup-and-install@bbe46386c0a2bc6baefd02916234956a38e622d5 # main
+ - uses: SocketDev/socket-registry/.github/actions/setup-and-install@d638c11f4bc7ac637e0f61f05729a54d68af40e0 # main
- name: Configure push credentials
env:
GH_TOKEN: ${{ github.token }}
run: git remote set-url origin "https://x-access-token:${GH_TOKEN}@github.com/${{ github.repository }}.git"
- - uses: SocketDev/socket-registry/.github/actions/setup-git-signing@bbe46386c0a2bc6baefd02916234956a38e622d5 # main
+ - uses: SocketDev/socket-registry/.github/actions/setup-git-signing@d638c11f4bc7ac637e0f61f05729a54d68af40e0 # main
with:
gpg-private-key: ${{ secrets.BOT_GPG_PRIVATE_KEY }}
@@ -145,5 +145,5 @@ jobs:
> \`\`\`
EOF
- - uses: SocketDev/socket-registry/.github/actions/cleanup-git-signing@bbe46386c0a2bc6baefd02916234956a38e622d5 # main
+ - uses: SocketDev/socket-registry/.github/actions/cleanup-git-signing@d638c11f4bc7ac637e0f61f05729a54d68af40e0 # main
if: always()
diff --git a/.github/workflows/provenance.yml b/.github/workflows/provenance.yml
index d1ade5c4..dc529fe7 100644
--- a/.github/workflows/provenance.yml
+++ b/.github/workflows/provenance.yml
@@ -16,11 +16,6 @@ on:
options:
- '0'
- '1'
- publish-without-sfw:
- description: 'Publish directly to npm, bypassing Socket firewall shims'
- required: false
- default: false
- type: boolean
permissions: {}
@@ -30,14 +25,13 @@ jobs:
permissions:
contents: write # To create GitHub releases
id-token: write # For npm trusted publishing via OIDC
- uses: SocketDev/socket-registry/.github/workflows/provenance.yml@bbe46386c0a2bc6baefd02916234956a38e622d5 # main
+ uses: SocketDev/socket-registry/.github/workflows/provenance.yml@d638c11f4bc7ac637e0f61f05729a54d68af40e0 # main
with:
debug: ${{ inputs.debug }}
dist-tag: ${{ inputs.dist-tag }}
package-name: '@socketsecurity/sdk'
publish-script: 'publish:ci'
- publish-without-sfw: ${{ inputs.publish-without-sfw }}
setup-script: 'ci:validate'
use-trusted-publishing: true
secrets:
- SOCKET_API_KEY: ${{ secrets.SOCKET_API_KEY }}
+ SOCKET_API_KEY: ${{ secrets.SOCKET_API_TOKEN }}
diff --git a/.github/workflows/weekly-update.yml b/.github/workflows/weekly-update.yml
index e8809b0c..a083d1a9 100644
--- a/.github/workflows/weekly-update.yml
+++ b/.github/workflows/weekly-update.yml
@@ -1,348 +1,20 @@
-name: 🔄 Weekly Dependency Update
+name: 🔄 Weekly Update
on:
schedule:
- # Run weekly on Monday at 9 AM UTC
- cron: '0 9 * * 1'
workflow_dispatch:
- inputs:
- dry-run:
- description: 'Check for updates without creating PR'
- required: false
- type: boolean
- default: false
permissions:
contents: read
jobs:
- check-updates:
- name: Check for dependency updates
- runs-on: ubuntu-latest
- permissions:
- contents: read
- outputs:
- has-updates: ${{ steps.check.outputs.has-updates }}
- steps:
- - uses: SocketDev/socket-registry/.github/actions/setup-and-install@bbe46386c0a2bc6baefd02916234956a38e622d5 # main
-
- - name: Check for npm updates
- id: check
- shell: bash
- run: |
- echo "Checking for npm package updates..."
- HAS_UPDATES=false
- NPM_UPDATES=$(pnpm outdated 2>/dev/null || true)
- if [ -n "$NPM_UPDATES" ] && ! echo "$NPM_UPDATES" | grep -q "No outdated"; then
- echo "npm packages have updates available"
- HAS_UPDATES=true
- fi
- echo "has-updates=$HAS_UPDATES" >> $GITHUB_OUTPUT
-
- apply-updates:
- name: Apply updates with Claude Code
- needs: check-updates
- if: needs.check-updates.outputs.has-updates == 'true' && inputs.dry-run != true
- runs-on: ubuntu-latest
- permissions:
- actions: write
- contents: write
- pull-requests: write
- steps:
- - uses: SocketDev/socket-registry/.github/actions/setup-and-install@bbe46386c0a2bc6baefd02916234956a38e622d5 # main
-
- - name: Create update branch
- id: branch
- env:
- GH_TOKEN: ${{ github.token }}
- run: |
- BRANCH_NAME="weekly-update-$(date +%Y%m%d)"
- git remote set-url origin "https://x-access-token:${GH_TOKEN}@github.com/${{ github.repository }}.git"
- # Branch from HEAD~1 so the PR is behind main, making the
- # "Update branch" button available to trigger enterprise checks.
- git checkout -b "$BRANCH_NAME" HEAD~1
- echo "branch=$BRANCH_NAME" >> $GITHUB_OUTPUT
-
- - uses: SocketDev/socket-registry/.github/actions/setup-git-signing@bbe46386c0a2bc6baefd02916234956a38e622d5 # main
- with:
- gpg-private-key: ${{ secrets.BOT_GPG_PRIVATE_KEY }}
-
- - name: Update dependencies (haiku)
- id: update
- timeout-minutes: 10
- env:
- ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
- GITHUB_ACTIONS: 'true'
- run: |
- if [ -z "$ANTHROPIC_API_KEY" ]; then
- echo "ANTHROPIC_API_KEY not set - skipping automated update"
- echo "success=false" >> $GITHUB_OUTPUT
- exit 0
- fi
-
- set +e
- pnpm exec claude --print \
- --allowedTools "Bash(pnpm:*)" "Bash(git add:*)" "Bash(git commit:*)" "Bash(git status:*)" "Bash(git diff:*)" "Bash(git log:*)" "Bash(git rev-parse:*)" "Read" "Write" "Edit" "Glob" "Grep" \
- --model haiku \
- --max-turns 15 \
- "$(cat <<'PROMPT'
- /updating
-
-
- You are an automated CI agent in a weekly dependency update workflow.
- Git is configured with GPG signing. A branch has been created for you.
-
-
-
- Update all dependencies to their latest versions.
- Create one atomic commit per dependency update with a conventional commit message.
- Leave all changes local — the workflow handles pushing and PR creation.
- Skip running builds, tests, and type checks — CI runs those separately.
-
-
-
- Each updated dependency has its own commit.
- The lockfile is consistent with package.json changes.
- No uncommitted changes remain in the working tree.
-
- PROMPT
- )" \
- 2>&1 | tee claude-update.log
- CLAUDE_EXIT=${PIPESTATUS[0]}
- set -e
-
- if [ "$CLAUDE_EXIT" -eq 0 ]; then
- echo "success=true" >> $GITHUB_OUTPUT
- else
- echo "success=false" >> $GITHUB_OUTPUT
- fi
-
- - name: Run tests
- id: tests
- if: steps.update.outputs.success == 'true'
- continue-on-error: true
- run: |
- set +e
- pnpm build 2>&1 | tee build-output.log
- BUILD_EXIT=${PIPESTATUS[0]}
-
- pnpm test 2>&1 | tee test-output.log
- TEST_EXIT=${PIPESTATUS[0]}
- set -e
-
- if [ "$BUILD_EXIT" -eq 0 ] && [ "$TEST_EXIT" -eq 0 ]; then
- echo "result=pass" >> $GITHUB_OUTPUT
- else
- echo "result=fail" >> $GITHUB_OUTPUT
- fi
-
- - name: Fix test failures (sonnet)
- id: claude
- if: steps.tests.outputs.result == 'fail'
- timeout-minutes: 15
- env:
- ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
- GITHUB_ACTIONS: 'true'
- run: |
- BUILD_LOG=$(cat build-output.log 2>/dev/null || echo "No build output")
- TEST_LOG=$(cat test-output.log 2>/dev/null || echo "No test output")
-
- set +e
- pnpm exec claude --print \
- --allowedTools "Bash(pnpm:*)" "Bash(git add:*)" "Bash(git commit:*)" "Bash(git status:*)" "Bash(git diff:*)" "Bash(git log:*)" "Bash(git rev-parse:*)" "Read" "Write" "Edit" "Glob" "Grep" \
- --model sonnet \
- --max-turns 25 \
- "$(cat <
- You are an automated CI agent fixing test failures after a dependency update.
- Git is configured with GPG signing. Dependencies were already updated and committed.
-
-
-
- BUILD OUTPUT:
- ${BUILD_LOG}
-
- TEST OUTPUT:
- ${TEST_LOG}
-
-
-
- The dependency updates above caused build or test failures.
- Analyze the failure logs, identify root causes, and fix them.
- Create one atomic commit per fix with a conventional commit message.
- Leave all changes local — the workflow handles pushing and PR creation.
-
-
-
- All build and test failures are resolved.
- Each fix has its own commit.
- No uncommitted changes remain in the working tree.
-
- PROMPT
- )" \
- 2>&1 | tee claude-fix.log
- CLAUDE_EXIT=${PIPESTATUS[0]}
- set -e
-
- if [ "$CLAUDE_EXIT" -eq 0 ]; then
- echo "success=true" >> $GITHUB_OUTPUT
- else
- echo "success=false" >> $GITHUB_OUTPUT
- fi
-
- - name: Set final status
- id: final
- if: always()
- env:
- UPDATE_SUCCESS: ${{ steps.update.outputs.success }}
- TESTS_RESULT: ${{ steps.tests.outputs.result }}
- FIX_SUCCESS: ${{ steps.claude.outputs.success }}
- run: |
- if [ "$UPDATE_SUCCESS" != "true" ]; then
- echo "success=false" >> $GITHUB_OUTPUT
- elif [ "$TESTS_RESULT" != "fail" ]; then
- echo "success=true" >> $GITHUB_OUTPUT
- elif [ "$FIX_SUCCESS" = "true" ]; then
- echo "success=true" >> $GITHUB_OUTPUT
- else
- echo "success=false" >> $GITHUB_OUTPUT
- fi
-
- - name: Validate changes
- id: validate
- if: steps.final.outputs.success == 'true'
- run: |
- UNEXPECTED=""
- for file in $(git diff --name-only origin/main..HEAD); do
- case "$file" in
- package.json|*/package.json|pnpm-lock.yaml|*/pnpm-lock.yaml|.npmrc|pnpm-workspace.yaml) ;;
- src/*|test/*) ;;
- *) UNEXPECTED="$UNEXPECTED $file" ;;
- esac
- done
- if [ -n "$UNEXPECTED" ]; then
- echo "::error::Unexpected files modified by Claude:$UNEXPECTED"
- echo "valid=false" >> $GITHUB_OUTPUT
- else
- echo "valid=true" >> $GITHUB_OUTPUT
- fi
-
- - name: Check for changes
- id: changes
- run: |
- if [ -n "$(git status --porcelain)" ] || [ "$(git rev-list --count HEAD ^origin/main)" -gt 0 ]; then
- echo "has-changes=true" >> $GITHUB_OUTPUT
- else
- echo "has-changes=false" >> $GITHUB_OUTPUT
- fi
-
- - name: Push branch
- if: steps.final.outputs.success == 'true' && steps.validate.outputs.valid == 'true' && steps.changes.outputs.has-changes == 'true'
- env:
- BRANCH_NAME: ${{ steps.branch.outputs.branch }}
- run: git push origin "$BRANCH_NAME"
-
- - name: Create Pull Request
- if: steps.final.outputs.success == 'true' && steps.validate.outputs.valid == 'true' && steps.changes.outputs.has-changes == 'true'
- env:
- GH_TOKEN: ${{ github.token }}
- BRANCH_NAME: ${{ steps.branch.outputs.branch }}
- run: |
- COMMITS=$(git log --oneline origin/main..HEAD)
- COMMIT_COUNT=$(git rev-list --count origin/main..HEAD)
-
- PR_BODY="## Weekly Dependency Update"$'\n\n'
- PR_BODY+="Automated weekly update of npm packages."$'\n\n'
- PR_BODY+="---"$'\n\n'
- PR_BODY+="### Commits (${COMMIT_COUNT})"$'\n\n'
- PR_BODY+=""$'\n'
- PR_BODY+="View commit history
"$'\n\n'
- PR_BODY+="\`\`\`"$'\n'
- PR_BODY+="${COMMITS}"$'\n'
- PR_BODY+="\`\`\`"$'\n\n'
- PR_BODY+=" "$'\n\n'
- PR_BODY+="---"$'\n\n'
- PR_BODY+="Generated by [weekly-update.yml](.github/workflows/weekly-update.yml)"
-
- gh pr create \
- --title "chore(deps): weekly dependency update ($(date +%Y-%m-%d))" \
- --body "$PR_BODY" \
- --draft \
- --head "$BRANCH_NAME" \
- --base main
-
- # Pushes made with GITHUB_TOKEN don't trigger other workflows.
- # Use workflow_dispatch to directly trigger CI on the PR branch.
- - name: Trigger CI checks
- if: steps.final.outputs.success == 'true' && steps.validate.outputs.valid == 'true' && steps.changes.outputs.has-changes == 'true'
- env:
- GH_TOKEN: ${{ github.token }}
- BRANCH_NAME: ${{ steps.branch.outputs.branch }}
- run: gh workflow run ci.yml --ref "$BRANCH_NAME"
-
- - name: Add job summary
- if: steps.final.outputs.success == 'true' && steps.validate.outputs.valid == 'true' && steps.changes.outputs.has-changes == 'true'
- env:
- GH_TOKEN: ${{ github.token }}
- BRANCH_NAME: ${{ steps.branch.outputs.branch }}
- run: |
- COMMIT_COUNT=$(git rev-list --count origin/main..HEAD)
- pr_number=$(gh pr list --head "$BRANCH_NAME" --json number --jq '.[0].number' || echo "")
- pr_url="https://github.com/${{ github.repository }}/pull/${pr_number}"
-
- cat >> "$GITHUB_STEP_SUMMARY" < **Note:** Enterprise required workflows (e.g. Audit GHA Workflows) won't trigger
- > automatically on bot PRs. Click **"Update branch"** on the PR to trigger them,
- > or push an empty commit to the branch:
- >
- > \`\`\`sh
- > git fetch origin ${BRANCH_NAME} && git checkout ${BRANCH_NAME}
- > git commit --allow-empty -m "chore: trigger enterprise checks"
- > git push origin ${BRANCH_NAME}
- > \`\`\`
- EOF
-
- - name: Upload Claude output
- if: always()
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
- with:
- name: claude-output-${{ github.run_id }}
- path: |
- claude-update.log
- claude-fix.log
- build-output.log
- test-output.log
- retention-days: 7
-
- - uses: SocketDev/socket-registry/.github/actions/cleanup-git-signing@bbe46386c0a2bc6baefd02916234956a38e622d5 # main
- if: always()
-
- notify:
- name: Notify results
- needs: [check-updates, apply-updates]
- if: always()
- runs-on: ubuntu-latest
- permissions:
- contents: read
- steps:
- - name: Report status
- env:
- HAS_UPDATES: ${{ needs.check-updates.outputs.has-updates }}
- DRY_RUN: ${{ inputs.dry-run }}
- run: |
- if [ "$HAS_UPDATES" = "true" ]; then
- if [ "$DRY_RUN" = "true" ]; then
- echo "Updates available (dry-run mode - no PR created)"
- else
- echo "Weekly update workflow completed"
- echo "Check the PRs tab for the automated update PR"
- fi
- else
- echo "All dependencies are up to date - no action needed!"
- fi
+ weekly-update:
+ uses: SocketDev/socket-registry/.github/workflows/weekly-update.yml@d638c11f4bc7ac637e0f61f05729a54d68af40e0 # main
+ with:
+ test-setup-script: 'pnpm run build'
+ test-script: 'pnpm test'
+ secrets:
+ ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
+ BOT_GPG_PRIVATE_KEY: ${{ secrets.BOT_GPG_PRIVATE_KEY }}
+ SOCKET_API_KEY: ${{ secrets.SOCKET_API_KEY }}
diff --git a/package.json b/package.json
index 6813cc32..6b221797 100644
--- a/package.json
+++ b/package.json
@@ -71,7 +71,7 @@
"@babel/traverse": "7.26.4",
"@babel/types": "7.26.3",
"@oxlint/migrate": "1.52.0",
- "@socketsecurity/lib": "5.18.2",
+ "@socketsecurity/lib": "5.21.0",
"@sveltejs/acorn-typescript": "1.0.8",
"@types/babel__traverse": "7.28.0",
"@types/node": "24.9.2",
@@ -111,5 +111,5 @@
"node": ">=18.20.8",
"pnpm": ">=11.0.0-rc.0"
},
- "packageManager": "pnpm@11.0.0-rc.0"
+ "packageManager": "pnpm@11.0.0-rc.2"
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 5e18d7be..bf8bfbb5 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -7,45 +7,45 @@ importers:
configDependencies: {}
packageManagerDependencies:
'@pnpm/exe':
- specifier: 11.0.0-rc.0
- version: 11.0.0-rc.0
+ specifier: 11.0.0-rc.2
+ version: 11.0.0-rc.2
pnpm:
- specifier: 11.0.0-rc.0
- version: 11.0.0-rc.0
+ specifier: 11.0.0-rc.2
+ version: 11.0.0-rc.2
packages:
- '@pnpm/exe@11.0.0-rc.0':
- resolution: {integrity: sha512-lpa3BGQaCvH5BGS256VTyJ4+Ib2PiA5gipTfTs7MTL02utSYXcWarP0OeDhw++Cg/tgrCVRDYWcUjHOy/KNTtA==}
+ '@pnpm/exe@11.0.0-rc.2':
+ resolution: {integrity: sha512-EkL8nZApA0wUA7c5hDdbeuyNUkmkDRBn8evxx4O79SMlEX1D6XspEu9EkLmT+sqrHsAwKzHTHsNYwTSOuKavRg==}
hasBin: true
- '@pnpm/linux-arm64@11.0.0-rc.0':
- resolution: {integrity: sha512-6JIbPFu8y7RevLIpOH/rhML9JtnLgAa9VVVGl8A02+sRdF415Q3cldz+N9Oh3ZNLi2JZWtvHRa5UE2FRFELOJQ==}
+ '@pnpm/linux-arm64@11.0.0-rc.2':
+ resolution: {integrity: sha512-aw7wUq6ffXAfP7r9ZKa7GQmCoh/2EJcdb5ghkc8cgz0O2RZCmIaHqMV2O049iSAtblANkOu5uhwAZW7DKMJa3A==}
cpu: [arm64]
os: [linux]
- '@pnpm/linux-x64@11.0.0-rc.0':
- resolution: {integrity: sha512-5nSOBz07hmznMKJ88LaO/mk6BXCOMs3cA7VkwAz7ehWvtxeT1Dqez2Rnf5nK//BgEF1jQ8cgjff6MWaSmiYY8A==}
+ '@pnpm/linux-x64@11.0.0-rc.2':
+ resolution: {integrity: sha512-aCItGORv4lUjYldScyhd7uxgXQI3s1B1s99u5Eb42KRRC4Q8DAf7dboXbLGk7rQLjx8F9xIiaD7QX7YR8+MWEQ==}
cpu: [x64]
os: [linux]
- '@pnpm/macos-arm64@11.0.0-rc.0':
- resolution: {integrity: sha512-X1KgttzXrspprRU4JV3y1rxraX/H8AzXhuO3tDJj01nbUhps0kkjdfJziLJFFYN74bwSO8DgFWmJ5w5V+Hp0Cg==}
+ '@pnpm/macos-arm64@11.0.0-rc.2':
+ resolution: {integrity: sha512-WsLK8St9Hpwp26qqdFVdLdDlJ3CLJVIkcFwP7G9b+HtkPZOx+Z9AGZ8iam1B7HSrf8XomZWlq0vntHDsc2uPTg==}
cpu: [arm64]
os: [darwin]
- '@pnpm/macos-x64@11.0.0-rc.0':
- resolution: {integrity: sha512-Ra/CuHN7hrqScrl9w3zPDcMbY5AjAZMqTDKXL/1qP/GlY4lOJp24sQrH19y3pQGoUKoxlvVo0S4I29ZX2Wsf7A==}
+ '@pnpm/macos-x64@11.0.0-rc.2':
+ resolution: {integrity: sha512-hiC0khjWqSu6l25rs52izVhPM+6IVbp89pLRyBMYTe5x2a9iydUsCloPl7E+SuNiZ5cNnG28qj3PDzc5upeH/Q==}
cpu: [x64]
os: [darwin]
- '@pnpm/win-arm64@11.0.0-rc.0':
- resolution: {integrity: sha512-vum6DgUMO6hxYdhJBUkdNpnXW0TU/iKRUuZca6qgn/uckhaobENsuaN0pG1ga49G26I+jL5C8GfVBmdnRenm6w==}
+ '@pnpm/win-arm64@11.0.0-rc.2':
+ resolution: {integrity: sha512-+bo8RmPQyPCKq+h1GE/QHJ7Ybt/4bWZLUSgXJQS6UOB7ar56g2g4ii1X5+8htkkdXxS5Uoj2TVqRjKp6hkkAdA==}
cpu: [arm64]
os: [win32]
- '@pnpm/win-x64@11.0.0-rc.0':
- resolution: {integrity: sha512-avY9Gz97pvcWO7nRL1AoJToVwljZIybX9A09buGpgrxTSTGjfs6bbFE+d+576ro02MHqhTn6qUnkCbPyKPcWrA==}
+ '@pnpm/win-x64@11.0.0-rc.2':
+ resolution: {integrity: sha512-srkbMALQgb4taTzKMlwqBZV+JHTh15jN4/FOVOGQ5XadjXdpJOievkvp/m87WankP8MX8th+mJhD9RX/rDOSOw==}
cpu: [x64]
os: [win32]
@@ -105,40 +105,40 @@ packages:
resolution: {integrity: sha512-DmCG8GzysnCZ15bres3N5AHCmwBwYgp0As6xjhQ47rAUTUXxJiK+lLUxaGsX3hd/30qUpVElh05PbGuxRPgJwA==}
engines: {node: '>= 10'}
- pnpm@11.0.0-rc.0:
- resolution: {integrity: sha512-Hwjq3uoCXpFEjebV3uQqbJR2QlcADAQ6nja4/xKEmnLry5xl/BiFCUdHJJ5S9T2Lc62hGBRGu6gYZoEMik0/bA==}
+ pnpm@11.0.0-rc.2:
+ resolution: {integrity: sha512-JkEMwm1mi63d4ToKzyx1ytALgqR3vMHi/mKd1B1reP4/stm7Ujr/951qkfBr6bkKYDJUPzC19zkxI5yCCqXwAQ==}
engines: {node: '>=22.13'}
hasBin: true
snapshots:
- '@pnpm/exe@11.0.0-rc.0':
+ '@pnpm/exe@11.0.0-rc.2':
dependencies:
'@reflink/reflink': 0.1.19
optionalDependencies:
- '@pnpm/linux-arm64': 11.0.0-rc.0
- '@pnpm/linux-x64': 11.0.0-rc.0
- '@pnpm/macos-arm64': 11.0.0-rc.0
- '@pnpm/macos-x64': 11.0.0-rc.0
- '@pnpm/win-arm64': 11.0.0-rc.0
- '@pnpm/win-x64': 11.0.0-rc.0
+ '@pnpm/linux-arm64': 11.0.0-rc.2
+ '@pnpm/linux-x64': 11.0.0-rc.2
+ '@pnpm/macos-arm64': 11.0.0-rc.2
+ '@pnpm/macos-x64': 11.0.0-rc.2
+ '@pnpm/win-arm64': 11.0.0-rc.2
+ '@pnpm/win-x64': 11.0.0-rc.2
- '@pnpm/linux-arm64@11.0.0-rc.0':
+ '@pnpm/linux-arm64@11.0.0-rc.2':
optional: true
- '@pnpm/linux-x64@11.0.0-rc.0':
+ '@pnpm/linux-x64@11.0.0-rc.2':
optional: true
- '@pnpm/macos-arm64@11.0.0-rc.0':
+ '@pnpm/macos-arm64@11.0.0-rc.2':
optional: true
- '@pnpm/macos-x64@11.0.0-rc.0':
+ '@pnpm/macos-x64@11.0.0-rc.2':
optional: true
- '@pnpm/win-arm64@11.0.0-rc.0':
+ '@pnpm/win-arm64@11.0.0-rc.2':
optional: true
- '@pnpm/win-x64@11.0.0-rc.0':
+ '@pnpm/win-x64@11.0.0-rc.2':
optional: true
'@reflink/reflink-darwin-arm64@0.1.19':
@@ -176,7 +176,7 @@ snapshots:
'@reflink/reflink-win32-arm64-msvc': 0.1.19
'@reflink/reflink-win32-x64-msvc': 0.1.19
- pnpm@11.0.0-rc.0: {}
+ pnpm@11.0.0-rc.2: {}
---
lockfileVersion: '9.0'
@@ -186,7 +186,7 @@ settings:
excludeLinksFromLockfile: false
overrides:
- defu: '>=6.1.6'
+ defu: '>=6.1.7'
vite: 7.3.2
importers:
@@ -212,8 +212,8 @@ importers:
specifier: 1.52.0
version: 1.52.0(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)
'@socketsecurity/lib':
- specifier: 5.18.2
- version: 5.18.2(typescript@5.9.3)
+ specifier: 5.21.0
+ version: 5.21.0(typescript@5.9.3)
'@sveltejs/acorn-typescript':
specifier: 1.0.8
version: 1.0.8(acorn@8.15.0)
@@ -284,6 +284,22 @@ importers:
specifier: 4.0.3
version: 4.0.3(@types/node@24.9.2)(jiti@2.6.1)(yaml@2.8.3)
+ .claude/hooks/check-new-deps:
+ dependencies:
+ '@socketregistry/packageurl-js':
+ specifier: 1.4.2
+ version: 1.4.2
+ '@socketsecurity/lib':
+ specifier: 5.21.0
+ version: 5.21.0(typescript@5.9.3)
+ '@socketsecurity/sdk':
+ specifier: 4.0.1
+ version: 4.0.1
+ devDependencies:
+ '@types/node':
+ specifier: 24.9.2
+ version: 24.9.2
+
packages:
'@antfu/ni@27.0.1':
@@ -1340,8 +1356,12 @@ packages:
resolution: {integrity: sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==}
engines: {node: '>=18'}
- '@socketsecurity/lib@5.18.2':
- resolution: {integrity: sha512-h6aGfphQ9jdVjUMGIKJcsIvT6BmzBo0OD20HzeK+6KQJi2HupfCUzIH26vDPxf+aYVmrX0/hKJDYI5sXfTGx9A==}
+ '@socketregistry/packageurl-js@1.4.2':
+ resolution: {integrity: sha512-yt9UfUzD02wZ7kwb67oe4jxG2D9JtgPqjrK/ans2BovFyeie0w8hvRR0MuOWM4mUt2371oFPp7NB6O5ZjYJmlw==}
+ engines: {node: '>=18.20.8', pnpm: '>=11.0.0-rc.0'}
+
+ '@socketsecurity/lib@5.21.0':
+ resolution: {integrity: sha512-cSqdq2kOBSuH3u8rfDhViCrN7IJPqzAvzklUYrEFhohUgJkky0+YYQ/gbSwRehZDGY8mqv+6lKGrt4OKWnNsdQ==}
engines: {node: '>=22', pnpm: '>=11.0.0-rc.0'}
peerDependencies:
typescript: '>=5.0.0'
@@ -1349,6 +1369,10 @@ packages:
typescript:
optional: true
+ '@socketsecurity/sdk@4.0.1':
+ resolution: {integrity: sha512-fe3DQp2dFwhc0G6Za36GIMSV+QaPAP5L96K3ZOtywt9nhbwxc9IQwqzdOVztdn5Rbez3t9EHU9Esj24/hWdP0g==}
+ engines: {node: '>=18.20.8', pnpm: '>=11.0.0-rc.0'}
+
'@standard-schema/spec@1.1.0':
resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==}
@@ -1593,8 +1617,8 @@ packages:
resolution: {integrity: sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==}
engines: {node: '>=10'}
- defu@6.1.6:
- resolution: {integrity: sha512-f8mefEW4WIVg4LckePx3mALjQSPQgFlg9U8yaPdlsbdYcHQyj9n2zL2LJEA52smeYxOvmd/nB7TpMtHGMTHcug==}
+ defu@6.1.7:
+ resolution: {integrity: sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==}
del@8.0.1:
resolution: {integrity: sha512-gPqh0mKTPvaUZGAuHbrBUYKZWBNAeHG7TU3QH5EhVwPMyKvmfJaNXhcD2jTcXsJRRcffuho4vaYweu80dRrMGA==}
@@ -3061,10 +3085,14 @@ snapshots:
'@sindresorhus/merge-streams@2.3.0': {}
- '@socketsecurity/lib@5.18.2(typescript@5.9.3)':
+ '@socketregistry/packageurl-js@1.4.2': {}
+
+ '@socketsecurity/lib@5.21.0(typescript@5.9.3)':
optionalDependencies:
typescript: 5.9.3
+ '@socketsecurity/sdk@4.0.1': {}
+
'@standard-schema/spec@1.1.0': {}
'@sveltejs/acorn-typescript@1.0.8(acorn@8.15.0)':
@@ -3295,7 +3323,7 @@ snapshots:
decamelize@5.0.1: {}
- defu@6.1.6: {}
+ defu@6.1.7: {}
del@8.0.1:
dependencies:
@@ -4063,7 +4091,7 @@ snapshots:
unconfig@7.5.0:
dependencies:
'@quansync/fs': 1.0.0
- defu: 6.1.6
+ defu: 6.1.7
jiti: 2.6.1
quansync: 1.0.0
unconfig-core: 7.5.0
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
index 255ee20b..cc6ac7c0 100644
--- a/pnpm-workspace.yaml
+++ b/pnpm-workspace.yaml
@@ -2,11 +2,18 @@ resolutionMode: highest
loglevel: error
trustPolicy: no-downgrade
+# Register .claude/hooks/* as workspace packages so taze (run via
+# `pnpm run update`) sees and bumps their package.json manifests
+# alongside the root. Keeps hook deps in lockstep with the main tree.
+packages:
+ - .claude/hooks/*
+
allowBuilds:
+ '@pnpm/exe': true
esbuild: true
overrides:
- defu: '>=6.1.6'
+ defu: '>=6.1.7'
vite: 7.3.2
# Wait 7 days (10080 minutes) before installing newly published packages.
diff --git a/scripts/build.mts b/scripts/build.mts
index 01d5aba1..4f89f5cd 100644
--- a/scripts/build.mts
+++ b/scripts/build.mts
@@ -14,7 +14,8 @@ import { build, context } from 'esbuild'
import { isQuiet } from '@socketsecurity/lib/argv/flags'
import { parseArgs } from '@socketsecurity/lib/argv/parse'
import { getDefaultLogger } from '@socketsecurity/lib/logger'
-import { printFooter, printHeader } from '@socketsecurity/lib/stdio/header'
+import { printFooter } from '@socketsecurity/lib/stdio/footer'
+import { printHeader } from '@socketsecurity/lib/stdio/header'
import {
analyzeMetafile,
diff --git a/scripts/check.mts b/scripts/check.mts
index e1f9eb0d..5b2d3fb6 100644
--- a/scripts/check.mts
+++ b/scripts/check.mts
@@ -16,7 +16,8 @@
import process from 'node:process'
import { getDefaultLogger } from '@socketsecurity/lib/logger'
-import { printFooter, printHeader } from '@socketsecurity/lib/stdio/header'
+import { printFooter } from '@socketsecurity/lib/stdio/footer'
+import { printHeader } from '@socketsecurity/lib/stdio/header'
import { runParallel } from './utils/run-command.mts'
diff --git a/scripts/publish.mts b/scripts/publish.mts
index 420abb6c..a4a880bd 100644
--- a/scripts/publish.mts
+++ b/scripts/publish.mts
@@ -270,8 +270,12 @@ async function publishPackage(options: PublishOptions = {}): Promise {
// Prepare publish args.
const publishArgs = ['publish', '--access', access, '--tag', tag]
- // Add provenance by default (works with trusted publishers).
- if (!dryRun) {
+ // Add provenance attestation in CI only. `npm publish --provenance`
+ // requires the GitHub Actions OIDC id-token endpoint; running locally
+ // fails with "Provenance generation in GitHub Actions requires
+ // 'id-token: write' permission". Gated so local non-dry-run publishes
+ // (emergency cases) still work.
+ if (!dryRun && process.env['GITHUB_ACTIONS'] === 'true') {
publishArgs.push('--provenance')
}
diff --git a/test/unit/promise-queue.test.mts b/test/unit/promise-queue.test.mts
index 717ac0e7..6c7cdd9b 100644
--- a/test/unit/promise-queue.test.mts
+++ b/test/unit/promise-queue.test.mts
@@ -75,52 +75,56 @@ describe('PromiseQueue', () => {
})
describe.sequential('Max Queue Length', () => {
- it('should drop oldest tasks when queue is full', async () => {
+ it('should reject newest submission when queue is full', async () => {
+ // Since @socketsecurity/lib 5.21.0, a bounded PromiseQueue rejects
+ // the NEWEST submission when `maxQueueLength` is exceeded, so
+ // already-enqueued work the caller has committed to awaiting is
+ // preserved. (Prior behavior: dropped the oldest, which discarded
+ // in-flight work.)
const limitedQueue = new PromiseQueue(1, 2)
const completed: number[] = []
- // Add first task that will run immediately
+ // Add first task that will run immediately.
limitedQueue.add(async () => {
await new Promise(resolve => setTimeout(resolve, 50))
completed.push(1)
return 1
})
- // Give task1 time to start
+ // Give task1 time to start.
await new Promise(resolve => setTimeout(resolve, 10))
- // Task2 will be queued
- const task2Promise = limitedQueue.add(async () => {
+ // Task2 will be queued.
+ limitedQueue.add(async () => {
completed.push(2)
return 2
})
- // Task3 will be queued (queue has 2 items: task2, task3)
+ // Task3 will be queued (queue has 2 items: task2, task3).
limitedQueue.add(async () => {
completed.push(3)
return 3
})
- // Task4 will cause task2 to be dropped (queue is full at maxQueueLength=2)
- limitedQueue.add(async () => {
+ // Task4 is the newest submission and should be rejected because
+ // the queue is full at maxQueueLength=2.
+ const task4Promise = limitedQueue.add(async () => {
completed.push(4)
return 4
})
- // Task2 should be rejected
- await expect(task2Promise).rejects.toThrow(
+ await expect(task4Promise).rejects.toThrow(
'Task dropped: queue length exceeded',
)
- // Wait for all running and queued tasks to complete
+ // Wait for all running and queued tasks to complete.
await limitedQueue.onIdle()
- // Only 3 tasks should have completed (task2 was dropped)
+ // Task4 was rejected; task1 + task2 + task3 all ran.
expect(completed).toContain(1)
- // Task2 was dropped
- expect(completed).not.toContain(2)
+ expect(completed).toContain(2)
expect(completed).toContain(3)
- expect(completed).toContain(4)
+ expect(completed).not.toContain(4)
expect(completed.length).toBe(3)
})