diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
new file mode 100644
index 0000000..8640359
--- /dev/null
+++ b/.github/CODEOWNERS
@@ -0,0 +1,17 @@
+# API config / startup surfaces
+/src/config.ts @metanallok
+/src/main.ts @metanallok
+/src/app.ts @metanallok
+
+# Solana / Futarchy / external data surfaces
+/src/services/solanaService.ts @metanallok
+/src/services/futarchyService.ts @metanallok
+/src/services/launchpadService.ts @metanallok
+/src/services/meteoraService.ts @metanallok
+/src/services/databaseService.ts @metanallok
+/src/services/externalDatabaseService.ts @metanallok
+
+# Operational scripts
+/scripts/safe-update.ts @metanallok
+/scripts/backfill.ts @metanallok
+/scripts/backfillV06.ts @metanallok
diff --git a/.github/branch-protection.md b/.github/branch-protection.md
new file mode 100644
index 0000000..be48888
--- /dev/null
+++ b/.github/branch-protection.md
@@ -0,0 +1,28 @@
+# GitHub protection for `master`
+
+## What the package-protection check does
+
+**Merge-blocking:**
+- **Lockfile drift** — `bun.lock` must match `package.json`.
+- **Socket package scan** — runs through Bun's security scanner on every install.
+- **Exact dependency pinning** — package manifests must use exact versions or `workspace:*`.
+- **Minimum dependency age** — newly introduced external npm packages must be at least 14 days old.
+- **Phantom deps** — imported packages must be declared in `package.json`.
+
+**Review hint:**
+- **Sensitive wallet / program diff** — warns on Solana address literals, program IDs, wallet-routing identifiers, signing paths, and `new PublicKey(` changes. CODEOWNERS is the merge gate for sensitive paths.
+
+## Recommended branch protection for `master`
+
+1. Require a pull request before merging.
+2. Require at least 1 approval.
+3. Dismiss stale approvals when new commits are pushed.
+4. Require conversation resolution before merging.
+5. Require status checks to pass before merging.
+6. Require the `package-protection` job from the `Package Protection` workflow.
+7. Require code owner review so `.github/CODEOWNERS` gates sensitive API, Solana, and operational-script paths.
+
+## Emergency bypass
+
+- Label: `emergency-override` downgrades repo-guard and phantom-dep failures to warnings.
+- Lockfile drift / install failures are never bypassed.
diff --git a/.github/workflows/package-protection.yml b/.github/workflows/package-protection.yml
new file mode 100644
index 0000000..a43cc70
--- /dev/null
+++ b/.github/workflows/package-protection.yml
@@ -0,0 +1,179 @@
+name: Package Protection
+
+on:
+ pull_request:
+
+permissions:
+ contents: read
+ pull-requests: write
+
+jobs:
+ package-protection:
+ runs-on: ubuntu-latest
+ env:
+ EMERGENCY_BYPASS: ${{ contains(github.event.pull_request.labels.*.name, 'emergency-override') }}
+
+ steps:
+ - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
+ with:
+ fetch-depth: 0
+
+ - name: Fetch PR base branch
+ run: git fetch origin "${{ github.base_ref }}" --depth=1
+
+ - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
+ with:
+ bun-version: 1.3.14
+
+ - name: Verify lockfile and scan packages
+ id: lockfile
+ continue-on-error: true
+ run: bun install --frozen-lockfile
+
+ - name: Run repository guard checks
+ id: guard
+ continue-on-error: true
+ env:
+ GITHUB_BASE_REF: ${{ github.base_ref }}
+ PACKAGE_MIN_AGE_DAYS: 14
+ REPO_GUARD_SUMMARY_PATH: repo-guard-summary.md
+ run: bun run repo:guard
+
+ - name: Check for undeclared dependencies (phantom deps)
+ id: knip
+ if: steps.lockfile.outcome == 'success'
+ continue-on-error: true
+ run: |
+ set +e
+ bun run deps:check > knip-raw.txt 2>&1
+ knip_exit=$?
+ grep -E '^[^:[:space:]]+\.(ts|tsx|js|mjs|cjs|jsx): [^[:space:]]' knip-raw.txt > knip-output.txt || true
+ echo "--- knip-raw.txt (full) ---"
+ cat knip-raw.txt
+ echo "--- knip-output.txt (filtered findings) ---"
+ cat knip-output.txt
+ if [ "$knip_exit" -ne 0 ] && [ -s knip-output.txt ]; then
+ while IFS= read -r line; do
+ file="${line%%:*}"
+ pkgs="${line#*: }"
+ echo "::error file=${file}::Undeclared import(s): ${pkgs}. Declare them in package.json — hoisting works locally but breaks in production Docker."
+ done < knip-output.txt
+ fi
+ exit $knip_exit
+
+ - name: Build PR comment
+ id: comment
+ env:
+ LOCKFILE_OUTCOME: ${{ steps.lockfile.outcome }}
+ GUARD_OUTCOME: ${{ steps.guard.outcome }}
+ KNIP_OUTCOME: ${{ steps.knip.outcome }}
+ run: |
+ {
+ echo ""
+ echo "**Package Protection**"
+ echo
+
+ if [ "$LOCKFILE_OUTCOME" = "success" ]; then
+ echo "- Lockfile + Socket scan: pass"
+ else
+ echo "- Lockfile + Socket scan: fail"
+ echo " - Run \\`bun install\\` and commit the updated lockfile."
+ fi
+
+ if [ "$GUARD_OUTCOME" = "success" ]; then
+ echo "- Repo guard: pass"
+ else
+ if [ "$EMERGENCY_BYPASS" = "true" ]; then
+ echo "- Repo guard: bypassed with \\`emergency-override\\`"
+ else
+ echo "- Repo guard: fail"
+ fi
+ fi
+
+ if [ "$KNIP_OUTCOME" = "success" ]; then
+ echo "- Phantom deps: pass"
+ elif [ "$KNIP_OUTCOME" = "skipped" ]; then
+ echo "- Phantom deps: skipped (lockfile check failed — fix that first)"
+ elif [ -s knip-output.txt ]; then
+ count=$(wc -l < knip-output.txt | tr -d ' ')
+ echo "- Phantom deps: fail — ${count} file(s) import packages not declared in package.json."
+ echo
+ echo "Undeclared imports (${count})
"
+ echo
+ echo '```'
+ cat knip-output.txt
+ echo '```'
+ echo
+ echo " "
+ else
+ echo "- Phantom deps: fail — check logs for details."
+ fi
+
+ echo
+ if [ -f repo-guard-summary.md ]; then
+ cat repo-guard-summary.md
+ else
+ echo "_Repository guard summary was not generated._"
+ fi
+ } > body.md
+
+ delimiter="PACKAGE_PROTECTION_BODY_$(date +%s%N)"
+ echo "body<<${delimiter}" >> "$GITHUB_OUTPUT"
+ cat body.md >> "$GITHUB_OUTPUT"
+ echo "${delimiter}" >> "$GITHUB_OUTPUT"
+
+ - name: Find existing comment
+ uses: peter-evans/find-comment@3eae4d37986fb5a8592848f6a574fdf654e61f9e # v3
+ id: find
+ with:
+ issue-number: ${{ github.event.pull_request.number }}
+ body-includes: ""
+
+ - name: Create or update PR comment
+ uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4
+ with:
+ issue-number: ${{ github.event.pull_request.number }}
+ comment-id: ${{ steps.find.outputs.comment-id }}
+ body: ${{ steps.comment.outputs.body }}
+ edit-mode: replace
+
+ - name: Fail if any check failed
+ env:
+ LOCKFILE_OUTCOME: ${{ steps.lockfile.outcome }}
+ GUARD_OUTCOME: ${{ steps.guard.outcome }}
+ KNIP_OUTCOME: ${{ steps.knip.outcome }}
+ run: |
+ failed=()
+ bypassed=()
+
+ if [ "$LOCKFILE_OUTCOME" != "success" ]; then
+ failed+=("lockfile / Socket scan")
+ fi
+
+ if [ "$GUARD_OUTCOME" != "success" ]; then
+ if [ "$EMERGENCY_BYPASS" = "true" ]; then
+ bypassed+=("repo guard")
+ else
+ failed+=("repo guard")
+ fi
+ fi
+
+ if [ "$KNIP_OUTCOME" = "failure" ]; then
+ if [ "$EMERGENCY_BYPASS" = "true" ]; then
+ bypassed+=("phantom deps")
+ else
+ failed+=("phantom deps")
+ fi
+ fi
+
+ if [ ${#bypassed[@]} -gt 0 ]; then
+ echo "::warning::Bypassed via emergency-override label: ${bypassed[*]}"
+ fi
+
+ if [ ${#failed[@]} -gt 0 ]; then
+ echo "::error::Package Protection failed:"
+ for item in "${failed[@]}"; do
+ echo "::error:: - ${item}"
+ done
+ exit 1
+ fi
diff --git a/.npmrc b/.npmrc
new file mode 100644
index 0000000..cffe8cd
--- /dev/null
+++ b/.npmrc
@@ -0,0 +1 @@
+save-exact=true
diff --git a/bun.lock b/bun.lock
index 0cfad57..368b3f0 100644
--- a/bun.lock
+++ b/bun.lock
@@ -22,12 +22,12 @@
"ts-node": "10.9.2",
},
"devDependencies": {
- "@types/bun": "latest",
+ "@socketsecurity/bun-security-scanner": "1.1.2",
+ "@types/bun": "1.3.3",
"@types/pg": "8.20.0",
"@types/supertest": "7.2.0",
- },
- "peerDependencies": {
- "typescript": "^5.9.3",
+ "knip": "6.3.0",
+ "typescript": "5.9.3",
},
},
},
@@ -46,6 +46,12 @@
"@cspotcode/source-map-support": ["@cspotcode/source-map-support@0.8.1", "", { "dependencies": { "@jridgewell/trace-mapping": "0.3.9" } }, "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw=="],
+ "@emnapi/core": ["@emnapi/core@1.10.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" } }, "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw=="],
+
+ "@emnapi/runtime": ["@emnapi/runtime@1.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA=="],
+
+ "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w=="],
+
"@jest/diff-sequences": ["@jest/diff-sequences@30.0.1", "", {}, "sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw=="],
"@jest/expect-utils": ["@jest/expect-utils@30.2.0", "", { "dependencies": { "@jest/get-type": "30.1.0" } }, "sha512-1JnRfhqpD8HGpOmQp180Fo9Zt69zNtC+9lR+kT7NVL05tNXIi+QC8Csz7lfidMoVLPD3FnOtcmp0CEFnxExGEA=="],
@@ -72,16 +78,108 @@
"@metaplex-foundation/cusper": ["@metaplex-foundation/cusper@0.0.2", "", {}, "sha512-S9RulC2fFCFOQraz61bij+5YCHhSO9llJegK8c8Y6731fSi6snUSQJdCUqYS8AIgR0TKbQvdvgSyIIdbDFZbBA=="],
+ "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.4", "", { "dependencies": { "@tybys/wasm-util": "^0.10.1" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" } }, "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow=="],
+
"@noble/curves": ["@noble/curves@1.9.7", "", { "dependencies": { "@noble/hashes": "1.8.0" } }, "sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw=="],
"@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="],
+ "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="],
+
+ "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="],
+
+ "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="],
+
"@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="],
+ "@oxc-parser/binding-android-arm-eabi": ["@oxc-parser/binding-android-arm-eabi@0.121.0", "", { "os": "android", "cpu": "arm" }, "sha512-n07FQcySwOlzap424/PLMtOkbS7xOu8nsJduKL8P3COGHKgKoDYXwoAHCbChfgFpHnviehrLWIPX0lKGtbEk/A=="],
+
+ "@oxc-parser/binding-android-arm64": ["@oxc-parser/binding-android-arm64@0.121.0", "", { "os": "android", "cpu": "arm64" }, "sha512-/Dd1xIXboYAicw+twT2utxPD7bL8qh7d3ej0qvaYIMj3/EgIrGR+tSnjCUkiCT6g6uTC0neSS4JY8LxhdSU/sA=="],
+
+ "@oxc-parser/binding-darwin-arm64": ["@oxc-parser/binding-darwin-arm64@0.121.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-A0jNEvv7QMtCO1yk205t3DWU9sWUjQ2KNF0hSVO5W9R9r/R1BIvzG01UQAfmtC0dQm7sCrs5puixurKSfr2bRQ=="],
+
+ "@oxc-parser/binding-darwin-x64": ["@oxc-parser/binding-darwin-x64@0.121.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-SsHzipdxTKUs3I9EOAPmnIimEeJOemqRlRDOp9LIj+96wtxZejF51gNibmoGq8KoqbT1ssAI5po/E3J+vEtXGA=="],
+
+ "@oxc-parser/binding-freebsd-x64": ["@oxc-parser/binding-freebsd-x64@0.121.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-v1APOTkCp+RWOIDAHRoaeW/UoaHF15a60E8eUL6kUQXh+i4K7PBwq2Wi7jm8p0ymID5/m/oC1w3W31Z/+r7HQw=="],
+
+ "@oxc-parser/binding-linux-arm-gnueabihf": ["@oxc-parser/binding-linux-arm-gnueabihf@0.121.0", "", { "os": "linux", "cpu": "arm" }, "sha512-PmqPQuqHZyFVWA4ycr0eu4VnTMmq9laOHZd+8R359w6kzuNZPvmmunmNJ8ybkm769A0nCoVp3TJ6dUz7B3FYIQ=="],
+
+ "@oxc-parser/binding-linux-arm-musleabihf": ["@oxc-parser/binding-linux-arm-musleabihf@0.121.0", "", { "os": "linux", "cpu": "arm" }, "sha512-vF24htj+MOH+Q7y9A8NuC6pUZu8t/C2Fr/kDOi2OcNf28oogr2xadBPXAbml802E8wRAVfbta6YLDQTearz+jw=="],
+
+ "@oxc-parser/binding-linux-arm64-gnu": ["@oxc-parser/binding-linux-arm64-gnu@0.121.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-wjH8cIG2Lu/3d64iZpbYr73hREMgKAfu7fqpXjgM2S16y2zhTfDIp8EQjxO8vlDtKP5Rc7waZW72lh8nZtWrpA=="],
+
+ "@oxc-parser/binding-linux-arm64-musl": ["@oxc-parser/binding-linux-arm64-musl@0.121.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-qT663J/W8yQFw3dtscbEi9LKJevr20V7uWs2MPGTnvNZ3rm8anhhE16gXGpxDOHeg9raySaSHKhd4IGa3YZvuw=="],
+
+ "@oxc-parser/binding-linux-ppc64-gnu": ["@oxc-parser/binding-linux-ppc64-gnu@0.121.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-mYNe4NhVvDBbPkAP8JaVS8lC1dsoJZWH5WCjpw5E+sjhk1R08wt3NnXYUzum7tIiWPfgQxbCMcoxgeemFASbRw=="],
+
+ "@oxc-parser/binding-linux-riscv64-gnu": ["@oxc-parser/binding-linux-riscv64-gnu@0.121.0", "", { "os": "linux", "cpu": "none" }, "sha512-+QiFoGxhAbaI/amqX567784cDyyuZIpinBrJNxUzb+/L2aBRX67mN6Jv40pqduHf15yYByI+K5gUEygCuv0z9w=="],
+
+ "@oxc-parser/binding-linux-riscv64-musl": ["@oxc-parser/binding-linux-riscv64-musl@0.121.0", "", { "os": "linux", "cpu": "none" }, "sha512-9ykEgyTa5JD/Uhv2sttbKnCfl2PieUfOjyxJC/oDL2UO0qtXOtjPLl7H8Kaj5G7p3hIvFgu3YWvAxvE0sqY+hQ=="],
+
+ "@oxc-parser/binding-linux-s390x-gnu": ["@oxc-parser/binding-linux-s390x-gnu@0.121.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-DB1EW5VHZdc1lIRjOI3bW/wV6R6y0xlfvdVrqj6kKi7Ayu2U3UqUBdq9KviVkcUGd5Oq+dROqvUEEFRXGAM7EQ=="],
+
+ "@oxc-parser/binding-linux-x64-gnu": ["@oxc-parser/binding-linux-x64-gnu@0.121.0", "", { "os": "linux", "cpu": "x64" }, "sha512-s4lfobX9p4kPTclvMiH3gcQUd88VlnkMTF6n2MTMDAyX5FPNRhhRSFZK05Ykhf8Zy5NibV4PbGR6DnK7FGNN6A=="],
+
+ "@oxc-parser/binding-linux-x64-musl": ["@oxc-parser/binding-linux-x64-musl@0.121.0", "", { "os": "linux", "cpu": "x64" }, "sha512-P9KlyTpuBuMi3NRGpJO8MicuGZfOoqZVRP1WjOecwx8yk4L/+mrCRNc5egSi0byhuReblBF2oVoDSMgV9Bj4Hw=="],
+
+ "@oxc-parser/binding-openharmony-arm64": ["@oxc-parser/binding-openharmony-arm64@0.121.0", "", { "os": "none", "cpu": "arm64" }, "sha512-R+4jrWOfF2OAPPhj3Eb3U5CaKNAH9/btMveMULIrcNW/hjfysFQlF8wE0GaVBr81dWz8JLgQlsxwctoL78JwXw=="],
+
+ "@oxc-parser/binding-wasm32-wasi": ["@oxc-parser/binding-wasm32-wasi@0.121.0", "", { "dependencies": { "@napi-rs/wasm-runtime": "^1.1.1" }, "cpu": "none" }, "sha512-5TFISkPTymKvsmIlKasPVTPuWxzCcrT8pM+p77+mtQbIZDd1UC8zww4CJcRI46kolmgrEX6QpKO8AvWMVZ+ifw=="],
+
+ "@oxc-parser/binding-win32-arm64-msvc": ["@oxc-parser/binding-win32-arm64-msvc@0.121.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-V0pxh4mql4XTt3aiEtRNUeBAUFOw5jzZNxPABLaOKAWrVzSr9+XUaB095lY7jqMf5t8vkfh8NManGB28zanYKw=="],
+
+ "@oxc-parser/binding-win32-ia32-msvc": ["@oxc-parser/binding-win32-ia32-msvc@0.121.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-4Ob1qvYMPnlF2N9rdmKdkQFdrq16QVcQwBsO8yiPZXof0fHKFF+LmQV501XFbi7lHyrKm8rlJRfQ/M8bZZPVLw=="],
+
+ "@oxc-parser/binding-win32-x64-msvc": ["@oxc-parser/binding-win32-x64-msvc@0.121.0", "", { "os": "win32", "cpu": "x64" }, "sha512-BOp1KCzdboB1tPqoCPXgntgFs0jjeSyOXHzgxVFR7B/qfr3F8r4YDacHkTOUNXtDgM8YwKnkf3rE5gwALYX7NA=="],
+
+ "@oxc-project/types": ["@oxc-project/types@0.121.0", "", {}, "sha512-CGtOARQb9tyv7ECgdAlFxi0Fv7lmzvmlm2rpD/RdijOO9rfk/JvB1CjT8EnoD+tjna/IYgKKw3IV7objRb+aYw=="],
+
+ "@oxc-resolver/binding-android-arm-eabi": ["@oxc-resolver/binding-android-arm-eabi@11.19.1", "", { "os": "android", "cpu": "arm" }, "sha512-aUs47y+xyXHUKlbhqHUjBABjvycq6YSD7bpxSW7vplUmdzAlJ93yXY6ZR0c1o1x5A/QKbENCvs3+NlY8IpIVzg=="],
+
+ "@oxc-resolver/binding-android-arm64": ["@oxc-resolver/binding-android-arm64@11.19.1", "", { "os": "android", "cpu": "arm64" }, "sha512-oolbkRX+m7Pq2LNjr/kKgYeC7bRDMVTWPgxBGMjSpZi/+UskVo4jsMU3MLheZV55jL6c3rNelPl4oD60ggYmqA=="],
+
+ "@oxc-resolver/binding-darwin-arm64": ["@oxc-resolver/binding-darwin-arm64@11.19.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-nUC6d2i3R5B12sUW4O646qD5cnMXf2oBGPLIIeaRfU9doJRORAbE2SGv4eW6rMqhD+G7nf2Y8TTJTLiiO3Q/dQ=="],
+
+ "@oxc-resolver/binding-darwin-x64": ["@oxc-resolver/binding-darwin-x64@11.19.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-cV50vE5+uAgNcFa3QY1JOeKDSkM/9ReIcc/9wn4TavhW/itkDGrXhw9jaKnkQnGbjJ198Yh5nbX/Gr2mr4Z5jQ=="],
+
+ "@oxc-resolver/binding-freebsd-x64": ["@oxc-resolver/binding-freebsd-x64@11.19.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-xZOQiYGFxtk48PBKff+Zwoym7ScPAIVp4c14lfLxizO2LTTTJe5sx9vQNGrBymrf/vatSPNMD4FgsaaRigPkqw=="],
+
+ "@oxc-resolver/binding-linux-arm-gnueabihf": ["@oxc-resolver/binding-linux-arm-gnueabihf@11.19.1", "", { "os": "linux", "cpu": "arm" }, "sha512-lXZYWAC6kaGe/ky2su94e9jN9t6M0/6c+GrSlCqL//XO1cxi5lpAhnJYdyrKfm0ZEr/c7RNyAx3P7FSBcBd5+A=="],
+
+ "@oxc-resolver/binding-linux-arm-musleabihf": ["@oxc-resolver/binding-linux-arm-musleabihf@11.19.1", "", { "os": "linux", "cpu": "arm" }, "sha512-veG1kKsuK5+t2IsO9q0DErYVSw2azvCVvWHnfTOS73WE0STdLLB7Q1bB9WR+yHPQM76ASkFyRbogWo1GR1+WbQ=="],
+
+ "@oxc-resolver/binding-linux-arm64-gnu": ["@oxc-resolver/binding-linux-arm64-gnu@11.19.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-heV2+jmXyYnUrpUXSPugqWDRpnsQcDm2AX4wzTuvgdlZfoNYO0O3W2AVpJYaDn9AG4JdM6Kxom8+foE7/BcSig=="],
+
+ "@oxc-resolver/binding-linux-arm64-musl": ["@oxc-resolver/binding-linux-arm64-musl@11.19.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-jvo2Pjs1c9KPxMuMPIeQsgu0mOJF9rEb3y3TdpsrqwxRM+AN6/nDDwv45n5ZrUnQMsdBy5gIabioMKnQfWo9ew=="],
+
+ "@oxc-resolver/binding-linux-ppc64-gnu": ["@oxc-resolver/binding-linux-ppc64-gnu@11.19.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-vLmdNxWCdN7Uo5suays6A/+ywBby2PWBBPXctWPg5V0+eVuzsJxgAn6MMB4mPlshskYbppjpN2Zg83ArHze9gQ=="],
+
+ "@oxc-resolver/binding-linux-riscv64-gnu": ["@oxc-resolver/binding-linux-riscv64-gnu@11.19.1", "", { "os": "linux", "cpu": "none" }, "sha512-/b+WgR+VTSBxzgOhDO7TlMXC1ufPIMR6Vj1zN+/x+MnyXGW7prTLzU9eW85Aj7Th7CCEG9ArCbTeqxCzFWdg2w=="],
+
+ "@oxc-resolver/binding-linux-riscv64-musl": ["@oxc-resolver/binding-linux-riscv64-musl@11.19.1", "", { "os": "linux", "cpu": "none" }, "sha512-YlRdeWb9j42p29ROh+h4eg/OQ3dTJlpHSa+84pUM9+p6i3djtPz1q55yLJhgW9XfDch7FN1pQ/Vd6YP+xfRIuw=="],
+
+ "@oxc-resolver/binding-linux-s390x-gnu": ["@oxc-resolver/binding-linux-s390x-gnu@11.19.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-EDpafVOQWF8/MJynsjOGFThcqhRHy417sRyLfQmeiamJ8qVhSKAn2Dn2VVKUGCjVB9C46VGjhNo7nOPUi1x6uA=="],
+
+ "@oxc-resolver/binding-linux-x64-gnu": ["@oxc-resolver/binding-linux-x64-gnu@11.19.1", "", { "os": "linux", "cpu": "x64" }, "sha512-NxjZe+rqWhr+RT8/Ik+5ptA3oz7tUw361Wa5RWQXKnfqwSSHdHyrw6IdcTfYuml9dM856AlKWZIUXDmA9kkiBQ=="],
+
+ "@oxc-resolver/binding-linux-x64-musl": ["@oxc-resolver/binding-linux-x64-musl@11.19.1", "", { "os": "linux", "cpu": "x64" }, "sha512-cM/hQwsO3ReJg5kR+SpI69DMfvNCp+A/eVR4b4YClE5bVZwz8rh2Nh05InhwI5HR/9cArbEkzMjcKgTHS6UaNw=="],
+
+ "@oxc-resolver/binding-openharmony-arm64": ["@oxc-resolver/binding-openharmony-arm64@11.19.1", "", { "os": "none", "cpu": "arm64" }, "sha512-QF080IowFB0+9Rh6RcD19bdgh49BpQHUW5TajG1qvWHvmrQznTZZjYlgE2ltLXyKY+qs4F/v5xuX1XS7Is+3qA=="],
+
+ "@oxc-resolver/binding-wasm32-wasi": ["@oxc-resolver/binding-wasm32-wasi@11.19.1", "", { "dependencies": { "@napi-rs/wasm-runtime": "^1.1.1" }, "cpu": "none" }, "sha512-w8UCKhX826cP/ZLokXDS6+milN8y4X7zidsAttEdWlVoamTNf6lhBJldaWr3ukTDiye7s4HRcuPEPOXNC432Vg=="],
+
+ "@oxc-resolver/binding-win32-arm64-msvc": ["@oxc-resolver/binding-win32-arm64-msvc@11.19.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-nJ4AsUVZrVKwnU/QRdzPCCrO0TrabBqgJ8pJhXITdZGYOV28TIYystV1VFLbQ7DtAcaBHpocT5/ZJnF78YJPtQ=="],
+
+ "@oxc-resolver/binding-win32-ia32-msvc": ["@oxc-resolver/binding-win32-ia32-msvc@11.19.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-EW+ND5q2Tl+a3pH81l1QbfgbF3HmqgwLfDfVithRFheac8OTcnbXt/JxqD2GbDkb7xYEqy1zNaVFRr3oeG8npA=="],
+
+ "@oxc-resolver/binding-win32-x64-msvc": ["@oxc-resolver/binding-win32-x64-msvc@11.19.1", "", { "os": "win32", "cpu": "x64" }, "sha512-6hIU3RQu45B+VNTY4Ru8ppFwjVS/S5qwYyGhBotmjxfEKk41I2DlGtRfGJndZ5+6lneE2pwloqunlOyZuX/XAw=="],
+
"@paralleldrive/cuid2": ["@paralleldrive/cuid2@2.3.1", "", { "dependencies": { "@noble/hashes": "^1.1.5" } }, "sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw=="],
"@sinclair/typebox": ["@sinclair/typebox@0.34.41", "", {}, "sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g=="],
+ "@socketsecurity/bun-security-scanner": ["@socketsecurity/bun-security-scanner@1.1.2", "", {}, "sha512-TdsAg6SMolubyZ6HfIjLWlANfHvhV6i7pdWof4OQ33zPEwXJm2ilA755levHMR618MKq22+06Ag8efiVKowxqA=="],
+
"@solana/buffer-layout": ["@solana/buffer-layout@4.0.1", "", { "dependencies": { "buffer": "~6.0.3" } }, "sha512-E1ImOIAD1tBZFRdjeM4/pzTiTApC0AOBGwyAMS4fwIodCWArzJ3DWdoh8cKxeFM2fElkxBh2Aqts1BPC373rHA=="],
"@solana/buffer-layout-utils": ["@solana/buffer-layout-utils@0.2.0", "", { "dependencies": { "@solana/buffer-layout": "^4.0.0", "@solana/web3.js": "^1.32.0", "bigint-buffer": "^1.1.5", "bignumber.js": "^9.0.1" } }, "sha512-szG4sxgJGktbuZYDg2FfNmkMi0DYQoVjN2h7ta1W1hPrwzarcFLBq9UpX1UjNXsNpT9dn+chgprtWGioUAr4/g=="],
@@ -120,6 +218,8 @@
"@tsconfig/node16": ["@tsconfig/node16@1.0.4", "", {}, "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA=="],
+ "@tybys/wasm-util": ["@tybys/wasm-util@0.10.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg=="],
+
"@types/bn.js": ["@types/bn.js@5.2.0", "", { "dependencies": { "@types/node": "*" } }, "sha512-DLbJ1BPqxvQhIGbeu8VbUC1DiAiahHtAYvA0ZEAa4P31F7IaArc8z3C3BRQdWX4mtLQuABG4yzp76ZrS02Ui1Q=="],
"@types/body-parser": ["@types/body-parser@1.19.6", "", { "dependencies": { "@types/connect": "*", "@types/node": "*" } }, "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g=="],
@@ -326,12 +426,18 @@
"eyes": ["eyes@0.1.8", "", {}, "sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ=="],
+ "fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="],
+
"fast-safe-stringify": ["fast-safe-stringify@2.1.1", "", {}, "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA=="],
"fast-stable-stringify": ["fast-stable-stringify@1.0.0", "", {}, "sha512-wpYMUmFu5f00Sm0cj2pfivpmawLZ0NKdviQ4w9zJeR8JVtOpOxHmLaJuj0vxvGqMJQWyP/COUkF75/57OKyRag=="],
"fastestsmallesttextencoderdecoder": ["fastestsmallesttextencoderdecoder@1.0.22", "", {}, "sha512-Pb8d48e+oIuY4MaM64Cd7OW1gt4nxCHs7/ddPPZ/Ic3sg8yVGM7O9wDvZ7us6ScaUupzM+pfBolwtYhN1IxBIw=="],
+ "fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="],
+
+ "fd-package-json": ["fd-package-json@2.0.0", "", { "dependencies": { "walk-up-path": "^4.0.0" } }, "sha512-jKmm9YtsNXN789RS/0mSzOC1NUq9mkVd65vbSSVsKdjGvYXBuE4oWe2QOEoFeRmJg+lPuZxpmrfFclNhoRMneQ=="],
+
"file-uri-to-path": ["file-uri-to-path@1.0.0", "", {}, "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="],
"fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
@@ -342,6 +448,8 @@
"form-data": ["form-data@4.0.5", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w=="],
+ "formatly": ["formatly@0.3.0", "", { "dependencies": { "fd-package-json": "^2.0.0" }, "bin": { "formatly": "bin/index.mjs" } }, "sha512-9XNj/o4wrRFyhSMJOvsuyMwy8aUfBaZ1VrqHVfohyXf0Sw0e+yfKG+xZaY3arGCOMdwFsqObtzVOc1gU9KiT9w=="],
+
"formidable": ["formidable@3.5.4", "", { "dependencies": { "@paralleldrive/cuid2": "^2.2.2", "dezalgo": "^1.0.4", "once": "^1.4.0" } }, "sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug=="],
"forwarded": ["forwarded@0.2.0", "", {}, "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="],
@@ -358,6 +466,8 @@
"get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="],
+ "get-tsconfig": ["get-tsconfig@4.13.7", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-7tN6rFgBlMgpBML5j8typ92BKFi2sFQvIdpAqLA2beia5avZDrMs0FLZiM5etShWq5irVyGcGMEA1jcDaK7A/Q=="],
+
"glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
"gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="],
@@ -428,10 +538,14 @@
"jest-util": ["jest-util@30.2.0", "", { "dependencies": { "@jest/types": "30.2.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", "picomatch": "^4.0.2" } }, "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA=="],
+ "jiti": ["jiti@2.7.0", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ=="],
+
"js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
"json-stringify-safe": ["json-stringify-safe@5.0.1", "", {}, "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA=="],
+ "knip": ["knip@6.3.0", "", { "dependencies": { "@nodelib/fs.walk": "^1.2.3", "fast-glob": "^3.3.3", "formatly": "^0.3.0", "get-tsconfig": "4.13.7", "jiti": "^2.6.0", "minimist": "^1.2.8", "oxc-parser": "^0.121.0", "oxc-resolver": "^11.19.1", "picocolors": "^1.1.1", "picomatch": "^4.0.1", "smol-toml": "^1.6.1", "strip-json-comments": "5.0.3", "unbash": "^2.2.0", "yaml": "^2.8.2", "zod": "^4.1.11" }, "bin": { "knip": "bin/knip.js", "knip-bun": "bin/knip-bun.js" } }, "sha512-g6dVPoTw6iNm3cubC5IWxVkVsd0r5hXhTBTbAGIEQN53GdA2ZM/slMTPJ7n5l8pBebNQPHpxjmKxuR4xVQ2/hQ=="],
+
"loose-envify": ["loose-envify@1.4.0", "", { "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, "bin": { "loose-envify": "cli.js" } }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="],
"lower-case": ["lower-case@2.0.2", "", { "dependencies": { "tslib": "^2.0.3" } }, "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg=="],
@@ -444,6 +558,8 @@
"merge-descriptors": ["merge-descriptors@2.0.0", "", {}, "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g=="],
+ "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="],
+
"methods": ["methods@1.1.2", "", {}, "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w=="],
"micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="],
@@ -456,6 +572,8 @@
"minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="],
+ "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
+
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
"negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="],
@@ -482,6 +600,10 @@
"once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],
+ "oxc-parser": ["oxc-parser@0.121.0", "", { "dependencies": { "@oxc-project/types": "^0.121.0" }, "optionalDependencies": { "@oxc-parser/binding-android-arm-eabi": "0.121.0", "@oxc-parser/binding-android-arm64": "0.121.0", "@oxc-parser/binding-darwin-arm64": "0.121.0", "@oxc-parser/binding-darwin-x64": "0.121.0", "@oxc-parser/binding-freebsd-x64": "0.121.0", "@oxc-parser/binding-linux-arm-gnueabihf": "0.121.0", "@oxc-parser/binding-linux-arm-musleabihf": "0.121.0", "@oxc-parser/binding-linux-arm64-gnu": "0.121.0", "@oxc-parser/binding-linux-arm64-musl": "0.121.0", "@oxc-parser/binding-linux-ppc64-gnu": "0.121.0", "@oxc-parser/binding-linux-riscv64-gnu": "0.121.0", "@oxc-parser/binding-linux-riscv64-musl": "0.121.0", "@oxc-parser/binding-linux-s390x-gnu": "0.121.0", "@oxc-parser/binding-linux-x64-gnu": "0.121.0", "@oxc-parser/binding-linux-x64-musl": "0.121.0", "@oxc-parser/binding-openharmony-arm64": "0.121.0", "@oxc-parser/binding-wasm32-wasi": "0.121.0", "@oxc-parser/binding-win32-arm64-msvc": "0.121.0", "@oxc-parser/binding-win32-ia32-msvc": "0.121.0", "@oxc-parser/binding-win32-x64-msvc": "0.121.0" } }, "sha512-ek9o58+SCv6AV7nchiAcUJy1DNE2CC5WRdBcO0mF+W4oRjNQfPO7b3pLjTHSFECpHkKGOZSQxx3hk8viIL5YCg=="],
+
+ "oxc-resolver": ["oxc-resolver@11.19.1", "", { "optionalDependencies": { "@oxc-resolver/binding-android-arm-eabi": "11.19.1", "@oxc-resolver/binding-android-arm64": "11.19.1", "@oxc-resolver/binding-darwin-arm64": "11.19.1", "@oxc-resolver/binding-darwin-x64": "11.19.1", "@oxc-resolver/binding-freebsd-x64": "11.19.1", "@oxc-resolver/binding-linux-arm-gnueabihf": "11.19.1", "@oxc-resolver/binding-linux-arm-musleabihf": "11.19.1", "@oxc-resolver/binding-linux-arm64-gnu": "11.19.1", "@oxc-resolver/binding-linux-arm64-musl": "11.19.1", "@oxc-resolver/binding-linux-ppc64-gnu": "11.19.1", "@oxc-resolver/binding-linux-riscv64-gnu": "11.19.1", "@oxc-resolver/binding-linux-riscv64-musl": "11.19.1", "@oxc-resolver/binding-linux-s390x-gnu": "11.19.1", "@oxc-resolver/binding-linux-x64-gnu": "11.19.1", "@oxc-resolver/binding-linux-x64-musl": "11.19.1", "@oxc-resolver/binding-openharmony-arm64": "11.19.1", "@oxc-resolver/binding-wasm32-wasi": "11.19.1", "@oxc-resolver/binding-win32-arm64-msvc": "11.19.1", "@oxc-resolver/binding-win32-ia32-msvc": "11.19.1", "@oxc-resolver/binding-win32-x64-msvc": "11.19.1" } }, "sha512-qE/CIg/spwrTBFt5aKmwe3ifeDdLfA2NESN30E42X/lII5ClF8V7Wt6WIJhcGZjp0/Q+nQ+9vgxGk//xZNX2hg=="],
+
"pako": ["pako@2.1.0", "", {}, "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug=="],
"parseurl": ["parseurl@1.3.3", "", {}, "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="],
@@ -528,6 +650,8 @@
"qs": ["qs@6.14.0", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w=="],
+ "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],
+
"range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="],
"raw-body": ["raw-body@3.0.2", "", { "dependencies": { "bytes": "~3.1.2", "http-errors": "~2.0.1", "iconv-lite": "~0.7.0", "unpipe": "~1.0.0" } }, "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA=="],
@@ -536,10 +660,16 @@
"readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="],
+ "resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="],
+
+ "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="],
+
"router": ["router@2.2.0", "", { "dependencies": { "debug": "^4.4.0", "depd": "^2.0.0", "is-promise": "^4.0.0", "parseurl": "^1.3.3", "path-to-regexp": "^8.0.0" } }, "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ=="],
"rpc-websockets": ["rpc-websockets@9.3.1", "", { "dependencies": { "@swc/helpers": "^0.5.11", "@types/uuid": "^8.3.4", "@types/ws": "^8.2.2", "buffer": "^6.0.3", "eventemitter3": "^5.0.1", "uuid": "^8.3.2", "ws": "^8.5.0" }, "optionalDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" } }, "sha512-bY6a+i/lEtBJ/mUxwsCTgevoV1P0foXTVA7UoThzaIWbM+3NDqorf8NBWs5DmqKTFeA1IoNzgvkWjFCPgnzUiQ=="],
+ "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="],
+
"safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="],
"safe-regex-test": ["safe-regex-test@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-regex": "^1.2.1" } }, "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw=="],
@@ -568,6 +698,8 @@
"slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="],
+ "smol-toml": ["smol-toml@1.6.1", "", {}, "sha512-dWUG8F5sIIARXih1DTaQAX4SsiTXhInKf1buxdY9DIg4ZYPZK5nGM1VRIYmEbDbsHt7USo99xSLFu5Q1IqTmsg=="],
+
"snake-case": ["snake-case@3.0.4", "", { "dependencies": { "dot-case": "^3.0.4", "tslib": "^2.0.3" } }, "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg=="],
"split2": ["split2@4.2.0", "", {}, "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg=="],
@@ -580,6 +712,8 @@
"stream-json": ["stream-json@1.9.1", "", { "dependencies": { "stream-chain": "^2.2.5" } }, "sha512-uWkjJ+2Nt/LO9Z/JyKZbMusL8Dkh97uUBTv3AJQ74y07lVahLY4eEFsPsE97pxYBwr8nnjMAIch5eqI0gPShyw=="],
+ "strip-json-comments": ["strip-json-comments@5.0.3", "", {}, "sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw=="],
+
"superagent": ["superagent@10.3.0", "", { "dependencies": { "component-emitter": "^1.3.1", "cookiejar": "^2.1.4", "debug": "^4.3.7", "fast-safe-stringify": "^2.1.1", "form-data": "^4.0.5", "formidable": "^3.5.4", "methods": "^1.1.2", "mime": "2.6.0", "qs": "^6.14.1" } }, "sha512-B+4Ik7ROgVKrQsXTV0Jwp2u+PXYLSlqtDAhYnkkD+zn3yg8s/zjA2MeGayPoY/KICrbitwneDHrjSotxKL+0XQ=="],
"superstruct": ["superstruct@0.15.5", "", {}, "sha512-4AOeU+P5UuE/4nOUkmcQdW5y7i9ndt1cQd/3iUe+LTz3RxESf/W/5lg4B74HbDMMv8PHnPnGCQFH45kBcrQYoQ=="],
@@ -610,6 +744,8 @@
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
+ "unbash": ["unbash@2.2.0", "", {}, "sha512-X2wH19RAPZE3+ldGicOkoj/SIA83OIxcJ6Cuaw23hf8Xc6fQpvZXY0SftE2JgS0QhYLUG4uwodSI3R53keyh7w=="],
+
"undefsafe": ["undefsafe@2.0.5", "", {}, "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA=="],
"undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="],
@@ -626,6 +762,8 @@
"vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="],
+ "walk-up-path": ["walk-up-path@4.0.0", "", {}, "sha512-3hu+tD8YzSLGuFYtPRb48vdhKMi0KQV5sn+uWr8+7dMEq/2G/dtLrdDinkLjqq5TIbIBjYJ4Ax/n3YiaW7QM8A=="],
+
"webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="],
"whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="],
@@ -638,8 +776,12 @@
"xtend": ["xtend@4.0.2", "", {}, "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="],
+ "yaml": ["yaml@2.9.0", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA=="],
+
"yn": ["yn@3.1.1", "", {}, "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q=="],
+ "zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="],
+
"@jest/pattern/@types/node": ["@types/node@24.10.1", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ=="],
"@jest/types/@types/node": ["@types/node@24.10.1", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ=="],
diff --git a/bunfig.toml b/bunfig.toml
new file mode 100644
index 0000000..6a9829b
--- /dev/null
+++ b/bunfig.toml
@@ -0,0 +1,10 @@
+[install]
+exact = true
+
+[install.security]
+# Socket security scanner hooks into `bun install` via Bun's security plugin
+# API. Every install (dev + CI) scans direct and transitive deps against
+# Socket's threat database and blocks malicious packages.
+# Works in free mode without an API key. Set SOCKET_API_KEY for enhanced
+# scanning tied to the Socket org (packages scope).
+scanner = "@socketsecurity/bun-security-scanner"
diff --git a/package.json b/package.json
index 1413a68..579c37e 100644
--- a/package.json
+++ b/package.json
@@ -4,11 +4,6 @@
"type": "module",
"private": true,
"version": "2.0.0",
- "devDependencies": {
- "@types/bun": "latest",
- "@types/pg": "8.20.0",
- "@types/supertest": "7.2.0"
- },
"scripts": {
"dev": "bun --watch src/main.ts",
"build": "tsc",
@@ -23,10 +18,9 @@
"safe-update": "bun run scripts/safe-update.ts",
"safe-update:dry": "bun run scripts/safe-update.ts --dry-run",
"compare:dune-vs-v06": "bun run scripts/compareDuneVsV06.ts",
- "typecheck": "tsc --noEmit"
- },
- "peerDependencies": {
- "typescript": "^5.9.3"
+ "typecheck": "tsc --noEmit",
+ "repo:guard": "bun scripts/repo-guard.ts",
+ "deps:check": "knip --include unlisted --reporter compact"
},
"dependencies": {
"@coral-xyz/anchor": "0.32.1",
@@ -44,5 +38,17 @@
"prom-client": "15.1.3",
"supertest": "7.2.2",
"ts-node": "10.9.2"
- }
+ },
+ "devDependencies": {
+ "@types/bun": "1.3.3",
+ "@types/pg": "8.20.0",
+ "@types/supertest": "7.2.0",
+ "@socketsecurity/bun-security-scanner": "1.1.2",
+ "knip": "6.3.0",
+ "typescript": "5.9.3"
+ },
+ "installConfig": {
+ "exact": true
+ },
+ "packageManager": "bun@1.3.14"
}
diff --git a/scripts/repo-guard.ts b/scripts/repo-guard.ts
new file mode 100644
index 0000000..fc271fa
--- /dev/null
+++ b/scripts/repo-guard.ts
@@ -0,0 +1,676 @@
+import { execFileSync } from "node:child_process";
+import { readdirSync, readFileSync, writeFileSync } from "node:fs";
+import { join, relative } from "node:path";
+
+type CheckStatus = "pass" | "fail" | "skip" | "warn";
+
+type PackageViolation = {
+ file: string;
+ section: string;
+ dependency: string;
+ version: string;
+};
+
+type PackageAgeViolation = {
+ dependency: string;
+ version: string;
+ publishedAt: string;
+ ageDays: number;
+ usedIn: string[];
+};
+
+type PackageAgeResult =
+ | { status: "pass"; violations: PackageAgeViolation[] }
+ | { status: "fail"; violations: PackageAgeViolation[] }
+ | { status: "skip"; violations: PackageAgeViolation[]; reason: string };
+
+type SensitiveFinding = {
+ file: string;
+ line: number;
+ kind: string;
+ text: string;
+};
+
+const ROOT = process.cwd();
+const SUMMARY_PATH =
+ process.env.REPO_GUARD_SUMMARY_PATH ??
+ join(process.env.TMPDIR ?? "/tmp", "repo-guard-summary.md");
+const BASE_REF = process.env.GITHUB_BASE_REF ?? "";
+const IS_CI = process.env.CI === "true";
+const PACKAGE_MIN_AGE_DAYS = Number.parseInt(
+ process.env.PACKAGE_MIN_AGE_DAYS ?? "14",
+ 10
+);
+
+const dependencySections = [
+ "dependencies",
+ "devDependencies",
+ "optionalDependencies",
+ "peerDependencies",
+ "overrides",
+] as const;
+
+const ignoredDirectories = new Set([
+ ".git",
+ ".next",
+ "dist",
+ "node_modules",
+ "coverage",
+]);
+
+const exactVersionPattern =
+ /^\d+\.\d+\.\d+(?:-[0-9A-Za-z-.]+)?(?:\+[0-9A-Za-z-.]+)?$/;
+
+const sensitiveFiles = [
+ "src/config.ts",
+ "src/main.ts",
+ "src/app.ts",
+ "src/services/solanaService.ts",
+ "src/services/futarchyService.ts",
+ "src/services/launchpadService.ts",
+ "src/services/meteoraService.ts",
+ "src/services/databaseService.ts",
+ "src/services/externalDatabaseService.ts",
+ "scripts/safe-update.ts",
+ "scripts/backfill.ts",
+ "scripts/backfillV06.ts",
+];
+
+// Files whose purpose is to define the guard rules themselves, or to document
+// them. Their diffs trivially match the heuristics and create noise without
+// signal.
+const excludedFromSensitiveDiff = new Set([
+ "scripts/repo-guard.ts",
+ ".github/CODEOWNERS",
+ ".github/CODEOWNERS.example",
+ ".github/branch-protection.md",
+ ".github/workflows/package-protection.yml",
+]);
+
+const suspiciousContentRules: Array<{ kind: string; pattern: RegExp }> = [
+ {
+ kind: "Hardcoded Solana address or program literal",
+ pattern: /["'`](?:[1-9A-HJ-NP-Za-km-z]{32,44})["'`]/,
+ },
+ {
+ kind: "Program ID constant or variable change",
+ pattern: /\b[A-Z0-9_]*PROGRAM_ID\b|\bprogramId\b/,
+ },
+ {
+ kind: "Wallet or destination routing change",
+ pattern:
+ /\b(?:PAYMENT_DESTINATION_ADDRESS|WALLET|TREASURY|RECIPIENT|DESTINATION|AUTHORITY)\b/i,
+ },
+ {
+ kind: "Signing or transaction submission path change",
+ pattern:
+ /\b(?:signTransaction|signAllTransactions|sendTransaction|verifyPaymentTransaction)\b/,
+ },
+ {
+ kind: "Public key construction change",
+ pattern: /\bnew PublicKey\s*\(/,
+ },
+];
+
+function run(command: string, args: string[]): string {
+ return execFileSync(command, args, {
+ cwd: ROOT,
+ encoding: "utf8",
+ }).trim();
+}
+
+function walk(dir: string, acc: string[]): string[] {
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
+ if (ignoredDirectories.has(entry.name)) {
+ continue;
+ }
+
+ const fullPath = join(dir, entry.name);
+ if (entry.isDirectory()) {
+ walk(fullPath, acc);
+ continue;
+ }
+
+ if (entry.isFile() && entry.name === "package.json") {
+ acc.push(relative(ROOT, fullPath));
+ }
+ }
+
+ return acc;
+}
+
+function readJsonAtRef(
+ ref: string,
+ filePath: string
+): Record | null {
+ try {
+ const content = execFileSync("git", ["show", `${ref}:${filePath}`], {
+ cwd: ROOT,
+ encoding: "utf8",
+ stdio: ["ignore", "pipe", "ignore"],
+ });
+ return JSON.parse(content) as Record;
+ } catch {
+ return null;
+ }
+}
+
+// Scopes the exact-dependency map down to entries whose version differs from
+// the PR base. Prevents every PR from tripping the age gate for ~14 days after
+// an unrelated dep bump lands on the base branch.
+function filterExactDependenciesToChanges(
+ all: Map>,
+ diffBase: string
+): Map> {
+ const locationPattern = /^(.+) \((\w+)\)$/;
+ const changed = new Map>();
+
+ for (const [key, locations] of all.entries()) {
+ const atIndex = key.lastIndexOf("@");
+ const dependency = key.slice(0, atIndex);
+ const headVersion = key.slice(atIndex + 1);
+
+ for (const location of locations) {
+ const match = locationPattern.exec(location);
+ if (!match) {
+ continue;
+ }
+ const file = match[1]!;
+ const section = match[2]!;
+
+ const basePkg = readJsonAtRef(diffBase, file);
+ const baseSection =
+ basePkg && typeof basePkg[section] === "object" && basePkg[section] !== null
+ ? (basePkg[section] as Record)
+ : null;
+ const baseVersion = baseSection?.[dependency];
+
+ if (baseVersion === headVersion) {
+ continue;
+ }
+
+ const set = changed.get(key) ?? new Set();
+ set.add(location);
+ changed.set(key, set);
+ }
+ }
+
+ return changed;
+}
+
+function isAllowedDependencyVersion(version: string): boolean {
+ if (exactVersionPattern.test(version)) {
+ return true;
+ }
+
+ if (version === "workspace:*") {
+ return true;
+ }
+
+ return false;
+}
+
+function collectPackageDependencyData(): {
+ violations: PackageViolation[];
+ exactDependencies: Map>;
+} {
+ const packageFiles = walk(ROOT, []).sort();
+ const violations: PackageViolation[] = [];
+ const exactDependencies = new Map>();
+
+ for (const packageFile of packageFiles) {
+ const packageJson = JSON.parse(readFileSync(join(ROOT, packageFile), "utf8"));
+
+ for (const section of dependencySections) {
+ const dependencies = packageJson[section];
+ if (!dependencies || typeof dependencies !== "object") {
+ continue;
+ }
+
+ for (const [dependency, version] of Object.entries(dependencies)) {
+ if (typeof version !== "string") {
+ continue;
+ }
+
+ if (isAllowedDependencyVersion(version)) {
+ if (version !== "workspace:*") {
+ const key = `${dependency}@${version}`;
+ const locations = exactDependencies.get(key) ?? new Set();
+ locations.add(`${packageFile} (${section})`);
+ exactDependencies.set(key, locations);
+ }
+ continue;
+ }
+
+ violations.push({
+ file: packageFile,
+ section,
+ dependency,
+ version,
+ });
+ }
+ }
+ }
+
+ return { violations, exactDependencies };
+}
+
+async function fetchPackagePublishTime(
+ dependency: string,
+ version: string
+): Promise {
+ // npm accepts fully encoded scoped names, but keep the canonical scoped
+ // package shape (`@scope%2fname`) to avoid registry/proxy compatibility
+ // issues with `%40scope%2Fname`.
+ const registryName = dependency.startsWith("@")
+ ? dependency.replace("/", "%2F")
+ : encodeURIComponent(dependency);
+
+ const response = await fetch(
+ `https://registry.npmjs.org/${registryName}`,
+ {
+ headers: {
+ Accept: "application/json",
+ },
+ }
+ );
+
+ if (!response.ok) {
+ throw new Error(`npm registry returned ${response.status} for ${dependency}`);
+ }
+
+ const packageMeta = (await response.json()) as {
+ time?: Record;
+ };
+
+ const publishedAt = packageMeta.time?.[version];
+ if (!publishedAt) {
+ throw new Error(`publish time not found for ${dependency}@${version}`);
+ }
+
+ return publishedAt;
+}
+
+async function checkPackageMinimumAge(
+ exactDependencies: Map>
+): Promise {
+ const violations: PackageAgeViolation[] = [];
+ const now = Date.now();
+
+ for (const [key, usedIn] of [...exactDependencies.entries()].sort()) {
+ const atIndex = key.lastIndexOf("@");
+ const dependency = key.slice(0, atIndex);
+ const version = key.slice(atIndex + 1);
+ const publishedAt = await fetchPackagePublishTime(dependency, version);
+ const ageDays = Math.floor(
+ (now - new Date(publishedAt).getTime()) / (1000 * 60 * 60 * 24)
+ );
+
+ if (ageDays >= PACKAGE_MIN_AGE_DAYS) {
+ continue;
+ }
+
+ violations.push({
+ dependency,
+ version,
+ publishedAt,
+ ageDays,
+ usedIn: [...usedIn].sort(),
+ });
+ }
+
+ return violations;
+}
+
+
+function getDiffBase(): string | null {
+ if (!BASE_REF) {
+ return null;
+ }
+
+ return run("git", ["merge-base", "HEAD", `origin/${BASE_REF}`]);
+}
+
+function collectChangedFiles(diffBase: string): Set {
+ const output = run("git", ["diff", "--name-only", `${diffBase}...HEAD`]);
+ return new Set(output.split("\n").filter(Boolean));
+}
+
+function checkSensitiveDiff():
+ | { status: "skip"; findings: SensitiveFinding[]; touchedSensitiveFiles: string[] }
+ | { status: "pass" | "fail" | "warn"; findings: SensitiveFinding[]; touchedSensitiveFiles: string[] } {
+ const diffBase = getDiffBase();
+ if (!diffBase) {
+ return {
+ status: "skip",
+ findings: [],
+ touchedSensitiveFiles: [],
+ };
+ }
+
+ const changedFiles = collectChangedFiles(diffBase);
+ const touchedSensitiveFiles = sensitiveFiles.filter((file) => changedFiles.has(file));
+
+ const diff = run("git", [
+ "diff",
+ "--unified=0",
+ "--no-color",
+ `${diffBase}...HEAD`,
+ ]);
+
+ const findings: SensitiveFinding[] = [];
+ let currentFile = "";
+ let nextLineNumber = 0;
+
+ for (const rawLine of diff.split("\n")) {
+ if (rawLine.startsWith("+++ b/")) {
+ currentFile = rawLine.slice(6);
+ continue;
+ }
+
+ if (rawLine.startsWith("--- ")) {
+ continue;
+ }
+
+ if (rawLine.startsWith("@@")) {
+ const match = rawLine.match(/\+(\d+)(?:,(\d+))?/);
+ nextLineNumber = match ? Number.parseInt(match[1]!, 10) : 0;
+ continue;
+ }
+
+ if (excludedFromSensitiveDiff.has(currentFile)) {
+ continue;
+ }
+
+ // Documentation (Markdown, plain text, READMEs) naturally contains words
+ // like "wallet", "authority", or example Solana addresses; the heuristics
+ // are intended to catch changes to *code*, not docs. Skip prose files.
+ if (/\.(md|mdx|txt|rst)$/i.test(currentFile)) {
+ continue;
+ }
+
+ if (!rawLine.startsWith("+") || rawLine.startsWith("+++")) {
+ if (rawLine.startsWith("-") && !rawLine.startsWith("---")) {
+ continue;
+ }
+
+ if (!rawLine.startsWith("-")) {
+ continue;
+ }
+ }
+
+ const sign = rawLine[0];
+ const lineText = rawLine.slice(1);
+ if (!currentFile || !lineText.trim()) {
+ if (sign === "+") {
+ nextLineNumber += 1;
+ }
+ continue;
+ }
+
+ const matchedKinds = suspiciousContentRules
+ .filter((rule) => rule.pattern.test(lineText))
+ .map((rule) => rule.kind);
+
+ if (matchedKinds.length > 0) {
+ findings.push({
+ file: currentFile,
+ line: nextLineNumber,
+ kind: matchedKinds.join("; "),
+ text: `${sign}${lineText}`.trim(),
+ });
+ }
+
+ if (sign === "+") {
+ nextLineNumber += 1;
+ }
+ }
+
+ if (findings.length === 0 && touchedSensitiveFiles.length === 0) {
+ return {
+ status: "pass",
+ findings,
+ touchedSensitiveFiles,
+ };
+ }
+
+ // Sensitive-diff is a review-assist, not a merge gate. Merge-blocking for
+ // sensitive paths is handled by CODEOWNERS + branch protection (the review
+ // required by @metanallok on files listed in .github/CODEOWNERS). This
+ // check surfaces the findings for reviewer visibility — in the PR comment
+ // and as GitHub annotations — without failing CI.
+ return {
+ status: "warn",
+ findings,
+ touchedSensitiveFiles,
+ };
+}
+
+function renderPackageSection(violations: PackageViolation[]): string[] {
+ if (violations.length === 0) {
+ return [
+ "### Exact dependency versions",
+ "",
+ "- Status: pass",
+ "- All `dependencies`, `devDependencies`, `optionalDependencies`, and `peerDependencies` use exact versions or `workspace:*`.",
+ ];
+ }
+
+ return [
+ "### Exact dependency versions",
+ "",
+ "- Status: fail",
+ "- The following dependency specs are not exact:",
+ ...violations.map(
+ (violation) =>
+ `- \`${violation.file}\` -> \`${violation.section}.${violation.dependency}\` uses \`${violation.version}\``
+ ),
+ ];
+}
+
+function renderPackageAgeSection(violations: PackageAgeViolation[]): string[] {
+ if (violations.length === 0) {
+ return [
+ "### Package minimum age",
+ "",
+ `- Status: pass`,
+ `- All pinned external packages are at least ${PACKAGE_MIN_AGE_DAYS} days old.`,
+ ];
+ }
+
+ return [
+ "### Package minimum age",
+ "",
+ "- Status: fail",
+ `- The following packages are newer than ${PACKAGE_MIN_AGE_DAYS} days:`,
+ ...violations.map(
+ (violation) =>
+ `- \`${violation.dependency}@${violation.version}\` is ${violation.ageDays} days old (published ${violation.publishedAt}) and is used in ${violation.usedIn
+ .map((item) => `\`${item}\``)
+ .join(", ")}`
+ ),
+ ];
+}
+
+function renderPackageAgeResult(result: PackageAgeResult): string[] {
+ if (result.status === "skip") {
+ return [
+ "### Package minimum age",
+ "",
+ "- Status: skipped",
+ `- The npm registry age check could not run in this environment: ${result.reason}`,
+ ];
+ }
+
+ return renderPackageAgeSection(result.violations);
+}
+
+
+function renderSensitiveSection(
+ result: ReturnType
+): string[] {
+ if (result.status === "skip") {
+ return [
+ "### Sensitive wallet / program changes",
+ "",
+ "- Status: skipped",
+ "- No PR base ref was available, so diff-based security checks did not run.",
+ ];
+ }
+
+ const heading = [
+ "### Sensitive wallet / program changes",
+ "",
+ `- Status: ${result.status}`,
+ ];
+
+ if (result.status === "pass") {
+ return [
+ ...heading,
+ "- No suspicious wallet routing, signing-path, or program-ID changes were detected in this PR diff.",
+ ];
+ }
+
+ const lines = [...heading];
+
+ lines.push(
+ "- Suspicious wallet routing, signing-path, or program-ID changes detected. This is a review hint, not a merge gate — CODEOWNERS + branch protection enforce the actual review requirement. Please take a closer look at the lines below."
+ );
+
+ if (result.touchedSensitiveFiles.length > 0) {
+ lines.push(
+ `- High-sensitivity files touched: ${result.touchedSensitiveFiles
+ .map((file) => `\`${file}\``)
+ .join(", ")}`
+ );
+ }
+
+ if (result.findings.length > 0) {
+ lines.push("- Matching diff lines:");
+ lines.push(
+ ...result.findings.slice(0, 20).map(
+ (finding) =>
+ `- \`${finding.file}:${finding.line}\` ${finding.kind} -> \`${finding.text}\``
+ )
+ );
+ } else if (result.touchedSensitiveFiles.length > 0) {
+ lines.push("- No single diff line matched the heuristics, but a known high-sensitivity file was modified.");
+ }
+
+ return lines;
+}
+
+async function main() {
+ const { violations: packageViolations, exactDependencies } =
+ collectPackageDependencyData();
+ let packageAgeResult: PackageAgeResult;
+
+ const diffBase = getDiffBase();
+
+ if (!diffBase) {
+ packageAgeResult = {
+ status: "skip",
+ violations: [],
+ reason:
+ "no PR base ref (GITHUB_BASE_REF) was available, so the age check could not be scoped to PR-introduced changes.",
+ };
+ } else {
+ try {
+ const changedExactDependencies = filterExactDependenciesToChanges(
+ exactDependencies,
+ diffBase
+ );
+ const packageAgeViolations = await checkPackageMinimumAge(
+ changedExactDependencies
+ );
+ packageAgeResult = {
+ status: packageAgeViolations.length === 0 ? "pass" : "fail",
+ violations: packageAgeViolations,
+ };
+ } catch (error) {
+ if (IS_CI) {
+ throw error;
+ }
+
+ packageAgeResult = {
+ status: "skip",
+ violations: [],
+ reason: error instanceof Error ? error.message : String(error),
+ };
+ }
+ }
+
+ const sensitiveDiff = checkSensitiveDiff();
+
+ const packageStatus: CheckStatus =
+ packageViolations.length === 0 ? "pass" : "fail";
+ const packageAgeStatus: CheckStatus = packageAgeResult.status;
+
+ // sensitive-diff is intentionally NOT part of overallFailed. It's a review
+ // hint surfaced via PR comment + GitHub annotations. Merge-blocking for
+ // sensitive paths is CODEOWNERS + branch protection's job.
+ const overallFailed =
+ packageStatus === "fail" || packageAgeStatus === "fail";
+
+ const lines = [
+ "## Repository Guard",
+ "",
+ ...renderPackageSection(packageViolations),
+ "",
+ ...renderPackageAgeResult(packageAgeResult),
+ "",
+ ...renderSensitiveSection(sensitiveDiff),
+ "",
+ `Overall status: ${overallFailed ? "fail" : "pass"}`,
+ "",
+ "_Transitive supply-chain threats are covered by the Socket scanner (via \`@socketsecurity/bun-security-scanner\` in \`bunfig.toml\`), which runs on every \`bun install\`. This guard blocks merge on direct-dep pinning and age policy; the sensitive-diff section is a review hint, not a merge gate (CODEOWNERS handles the actual review requirement)._",
+ ];
+
+ const summary = `${lines.join("\n")}\n`;
+ writeFileSync(SUMMARY_PATH, summary);
+
+ // Sensitive-diff annotations are emitted as `::warning::` so they show up
+ // in the Files Changed view for reviewers but don't fail the job. This
+ // runs regardless of overallFailed — a clean lockfile/age check shouldn't
+ // silence a review hint.
+ if (sensitiveDiff.status === "warn") {
+ for (const finding of sensitiveDiff.findings.slice(0, 20)) {
+ console.log(
+ `::warning file=${finding.file},line=${finding.line}::${finding.kind}: ${finding.text}`
+ );
+ }
+ for (const file of sensitiveDiff.touchedSensitiveFiles) {
+ console.log(
+ `::warning file=${file}::High-sensitivity file modified — please review carefully.`
+ );
+ }
+ }
+
+ if (overallFailed) {
+ console.error("");
+ console.error("Repository Guard failed. Details:");
+ console.error("");
+ console.error(summary);
+
+ for (const violation of packageViolations) {
+ console.error(
+ `::error file=${violation.file}::${violation.section}.${violation.dependency} uses \`${violation.version}\` — pin to an exact version.`
+ );
+ }
+
+ if (packageAgeResult.status === "fail") {
+ for (const violation of packageAgeResult.violations) {
+ const usedIn = violation.usedIn.join(", ");
+ console.error(
+ `::error file=${violation.usedIn[0] ?? "package.json"}::${violation.dependency}@${violation.version} is only ${violation.ageDays} days old (published ${violation.publishedAt}, min age ${PACKAGE_MIN_AGE_DAYS}d). Used in: ${usedIn}`
+ );
+ }
+ }
+
+ process.exit(1);
+ }
+
+ console.log(summary);
+}
+
+await main();