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) })