diff --git a/.eslintrc.cjs b/.eslintrc.cjs new file mode 100644 index 00000000..9bb9e3f6 --- /dev/null +++ b/.eslintrc.cjs @@ -0,0 +1,30 @@ +module.exports = { + root: true, + extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended", "prettier"], + plugins: ["@typescript-eslint", "prettier"], + parser: "@typescript-eslint/parser", + parserOptions: { + project: true, + }, + env: { + browser: true, + node: true, + }, + rules: { + "prettier/prettier": "error", + "semi": ["error", "never"], + "no-unused-vars": "off", + "@typescript-eslint/no-unused-vars": [ + "warn", + { + args: "all", + argsIgnorePattern: "^_", + caughtErrors: "all", + caughtErrorsIgnorePattern: "^_", + destructuredArrayIgnorePattern: "^_", + varsIgnorePattern: "^_", + ignoreRestSiblings: true, + }, + ], + }, +} diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 47fc4963..00000000 --- a/.eslintrc.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "root": true, - "parser": "@typescript-eslint/parser", - "plugins": ["@typescript-eslint", "prettier"], - "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended", "prettier"], - "env": { - "browser": true, - "node": true - }, - "rules": { - "prettier/prettier": "error", - "semi": ["error", "never"], - "no-unused-vars": "off", - "@typescript-eslint/no-unused-vars": [ - "error", - { - "args": "all", - "argsIgnorePattern": "^_", - "caughtErrors": "all", - "caughtErrorsIgnorePattern": "^_", - "destructuredArrayIgnorePattern": "^_", - "varsIgnorePattern": "^_", - "ignoreRestSiblings": true - } - ], - "@typescript-eslint/no-explicit-any": "off" - } -} - diff --git a/.github/workflows/check-pr.yml b/.github/workflows/check-pr.yml index 9f76accb..f4bd7cab 100644 --- a/.github/workflows/check-pr.yml +++ b/.github/workflows/check-pr.yml @@ -24,7 +24,7 @@ jobs: build requireScope: false scopes: | - (registry|explorer|registry-sdk|sdk|utils|workspace)(,(registry|explorer|registry-sdk|sdk|utils|workspace))* + (contracts|registry|explorer|registry-sdk|sdk|utils|workspace)(,(contracts|registry|explorer|registry-sdk|sdk|utils|workspace))* subjectPattern: ^[A-Z].+$ subjectPatternError: | The subject must start with an uppercase letter. @@ -38,7 +38,7 @@ jobs: with: requireScope: true scopes: | - (registry|explorer|registry-sdk|sdk|utils|workspace)(,(registry|explorer|registry-sdk|sdk|utils|workspace))* + (contracts|registry|explorer|registry-sdk|sdk|utils|workspace)(,(contracts|registry|explorer|registry-sdk|sdk|utils|workspace))* subjectPattern: ^[A-Z].+$ subjectPatternError: | The subject must start with an uppercase letter. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 26948661..21722387 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,7 +29,7 @@ jobs: - name: Install Bun uses: oven-sh/setup-bun@v2 with: - bun-version: 1.3.1 + bun-version: 1.3.8 - name: Cache Bun dependencies uses: actions/cache@v4 @@ -59,6 +59,9 @@ jobs: - name: Test run: bun run test + - name: Validate packages + run: bun run validate-packages + dependency-sync-check: name: Dependency Sync Check runs-on: ubuntu-latest @@ -69,7 +72,7 @@ jobs: - name: Install Bun uses: oven-sh/setup-bun@v2 with: - bun-version: 1.3.1 + bun-version: 1.3.8 - name: Cache Bun dependencies uses: actions/cache@v4 diff --git a/.github/workflows/publish-registry-sdk.yml b/.github/workflows/publish-registry-sdk.yml index 5a8028fe..197ff192 100644 --- a/.github/workflows/publish-registry-sdk.yml +++ b/.github/workflows/publish-registry-sdk.yml @@ -10,6 +10,11 @@ jobs: publish: name: Publish Registry SDK runs-on: ubuntu-latest + environment: npm-publish + permissions: + id-token: write # Required for OIDC + contents: read + steps: - name: Checkout repository uses: actions/checkout@v4 @@ -17,7 +22,7 @@ jobs: - name: Install Bun uses: oven-sh/setup-bun@v2 with: - bun-version: 1.3.1 + bun-version: 1.3.8 - name: Cache Bun dependencies uses: actions/cache@v4 @@ -34,22 +39,18 @@ jobs: run: bash scripts/sync-workspace-deps.sh check - name: Install system dependencies - if: github.ref == 'refs/heads/main' run: sudo apt-get install -y lsof jq zsh - name: Install Foundry - if: github.ref == 'refs/heads/main' uses: foundry-rs/foundry-toolchain@v1 with: version: v1.4.4 - name: Install Foundry dependencies - if: github.ref == 'refs/heads/main' run: forge install working-directory: packages/registry-contracts - name: Setup Turbo cache - if: github.ref == 'refs/heads/main' uses: actions/cache@v4 with: path: .turbo @@ -58,27 +59,31 @@ jobs: ${{ runner.os }}-turbo- - name: Build package - if: github.ref == 'refs/heads/main' run: bun run build --filter=@zkpassport/registry + - name: Setup Node.js for npm publish + uses: actions/setup-node@v4 + with: + node-version: '24' + registry-url: 'https://registry.npmjs.org' + - name: Check if version is published to npm - if: github.ref == 'refs/heads/main' id: version_check run: | - VERSION=$(bun -p "require('./packages/registry-sdk/package.json').version") - if ! bun pm view @zkpassport/registry@$VERSION version 2>/dev/null; then + VERSION=$(node -p "require('./packages/registry-sdk/package.json').version") + if ! npm view @zkpassport/registry@$VERSION version 2>/dev/null; then echo "publish=true" >> $GITHUB_OUTPUT echo "version=$VERSION" >> $GITHUB_OUTPUT fi - name: Publish new version to npm - if: steps.version_check.outputs.publish == 'true' && github.ref == 'refs/heads/main' + if: steps.version_check.outputs.publish == 'true' run: | + ../../scripts/prepublish.sh + PKG=$(bun pm pack --quiet | xargs) if [[ "${{ steps.version_check.outputs.version }}" =~ [0-9]+\.[0-9]+\.[0-9]+\- ]]; then - bun publish --tag beta + npm publish "$PKG" --ignore-scripts --provenance --access public --tag beta else - bun publish + npm publish "$PKG" --ignore-scripts --provenance --access public fi working-directory: packages/registry-sdk - env: - NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/publish-zkpassport-sdk.yml b/.github/workflows/publish-zkpassport-sdk.yml index 852c5939..fa311056 100644 --- a/.github/workflows/publish-zkpassport-sdk.yml +++ b/.github/workflows/publish-zkpassport-sdk.yml @@ -10,6 +10,11 @@ jobs: publish: name: Publish SDK runs-on: ubuntu-latest + environment: npm-publish + permissions: + id-token: write # Required for OIDC + contents: read + steps: - name: Checkout repository uses: actions/checkout@v4 @@ -17,7 +22,7 @@ jobs: - name: Install Bun uses: oven-sh/setup-bun@v2 with: - bun-version: 1.3.1 + bun-version: 1.3.8 - name: Cache Bun dependencies uses: actions/cache@v4 @@ -34,22 +39,18 @@ jobs: run: bash scripts/sync-workspace-deps.sh check - name: Install system dependencies - if: github.ref == 'refs/heads/main' run: sudo apt-get install -y lsof jq zsh - name: Install Foundry - if: github.ref == 'refs/heads/main' uses: foundry-rs/foundry-toolchain@v1 with: version: v1.4.4 - name: Install Foundry dependencies - if: github.ref == 'refs/heads/main' run: forge install working-directory: packages/registry-contracts - name: Setup Turbo cache - if: github.ref == 'refs/heads/main' uses: actions/cache@v4 with: path: .turbo @@ -58,27 +59,31 @@ jobs: ${{ runner.os }}-turbo- - name: Build package - if: github.ref == 'refs/heads/main' run: bun run build --filter=@zkpassport/sdk + - name: Setup Node.js for npm publish + uses: actions/setup-node@v4 + with: + node-version: '24' + registry-url: 'https://registry.npmjs.org' + - name: Check if version is published to npm - if: github.ref == 'refs/heads/main' id: version_check run: | - VERSION=$(bun -p "require('./packages/zkpassport-sdk/package.json').version") - if ! bun pm view @zkpassport/sdk@$VERSION version 2>/dev/null; then + VERSION=$(node -p "require('./packages/zkpassport-sdk/package.json').version") + if ! npm view @zkpassport/sdk@$VERSION version 2>/dev/null; then echo "publish=true" >> $GITHUB_OUTPUT echo "version=$VERSION" >> $GITHUB_OUTPUT fi - name: Publish new version to npm - if: steps.version_check.outputs.publish == 'true' && github.ref == 'refs/heads/main' + if: steps.version_check.outputs.publish == 'true' run: | + ../../scripts/prepublish.sh + PKG=$(bun pm pack --quiet | xargs) if [[ "${{ steps.version_check.outputs.version }}" =~ [0-9]+\.[0-9]+\.[0-9]+\- ]]; then - bun publish --tag beta + npm publish "$PKG" --ignore-scripts --provenance --access public --tag beta else - bun publish + npm publish "$PKG" --ignore-scripts --provenance --access public fi working-directory: packages/zkpassport-sdk - env: - NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/publish-zkpassport-utils.yml b/.github/workflows/publish-zkpassport-utils.yml index c5227033..407d3805 100644 --- a/.github/workflows/publish-zkpassport-utils.yml +++ b/.github/workflows/publish-zkpassport-utils.yml @@ -10,6 +10,11 @@ jobs: publish: name: Publish Utils runs-on: ubuntu-latest + environment: npm-publish + permissions: + id-token: write # Required for OIDC + contents: read + steps: - name: Checkout repository uses: actions/checkout@v4 @@ -17,7 +22,7 @@ jobs: - name: Install Bun uses: oven-sh/setup-bun@v2 with: - bun-version: 1.3.1 + bun-version: 1.3.8 - name: Cache Bun dependencies uses: actions/cache@v4 @@ -34,22 +39,18 @@ jobs: run: bash scripts/sync-workspace-deps.sh check - name: Install system dependencies - if: github.ref == 'refs/heads/main' run: sudo apt-get install -y lsof jq zsh - name: Install Foundry - if: github.ref == 'refs/heads/main' uses: foundry-rs/foundry-toolchain@v1 with: version: v1.4.4 - name: Install Foundry dependencies - if: github.ref == 'refs/heads/main' run: forge install working-directory: packages/registry-contracts - name: Setup Turbo cache - if: github.ref == 'refs/heads/main' uses: actions/cache@v4 with: path: .turbo @@ -58,27 +59,31 @@ jobs: ${{ runner.os }}-turbo- - name: Build package - if: github.ref == 'refs/heads/main' run: bun run build --filter=@zkpassport/utils + - name: Setup Node.js for npm publish + uses: actions/setup-node@v4 + with: + node-version: '24' + registry-url: 'https://registry.npmjs.org' + - name: Check if version is published to npm - if: github.ref == 'refs/heads/main' id: version_check run: | - VERSION=$(bun -p "require('./packages/zkpassport-utils/package.json').version") - if ! bun pm view @zkpassport/utils@$VERSION version 2>/dev/null; then + VERSION=$(node -p "require('./packages/zkpassport-utils/package.json').version") + if ! npm view @zkpassport/utils@$VERSION version 2>/dev/null; then echo "publish=true" >> $GITHUB_OUTPUT echo "version=$VERSION" >> $GITHUB_OUTPUT fi - name: Publish new version to npm - if: steps.version_check.outputs.publish == 'true' && github.ref == 'refs/heads/main' + if: steps.version_check.outputs.publish == 'true' run: | + ../../scripts/prepublish.sh + PKG=$(bun pm pack --quiet | xargs) if [[ "${{ steps.version_check.outputs.version }}" =~ [0-9]+\.[0-9]+\.[0-9]+\- ]]; then - bun publish --tag beta + npm publish "$PKG" --ignore-scripts --provenance --access public --tag beta else - bun publish + npm publish "$PKG" --ignore-scripts --provenance --access public fi working-directory: packages/zkpassport-utils - env: - NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/README.md b/README.md index 39daf043..aab27ff0 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,21 @@ # ZKPassport Monorepo -This monorepo contains the components of the ZKPassport Registry: +This monorepo contains the components of the ZKPassport project: - - **Registry Contracts**: Smart contracts for the on-chain registry + - **Registry Contracts**: Smart contracts for the onchain registry - **Registry SDK**: JavaScript SDK for interacting with the registry - **Registry Explorer**: Web app for exploring and verifying registry certificates + - **ZKPassport SDK**: SDK for integrating with ZKPassport + - **ZKPassport Utils**: Shared utilities used across ZKPassport packages ## Project Structure ``` zkpassport-packages/ ├── packages/ -│ ├── registry-contracts/ # Registry smart contracts -│ ├── registry-sdk/ # Registry JS SDK for querying the registry -│ ├── registry-explorer/ # Registry Explorer web app for exploring the registry +│ ├── registry-contracts/ # Registry Contracts +│ ├── registry-sdk/ # Registry SDK +│ ├── registry-explorer/ # Registry Explorer +│ ├── zkpassport-sdk/ # ZKPassport SDK +│ └── zkpassport-utils/ # ZKPassport Utils ``` diff --git a/bun.lock b/bun.lock index c8c91b3c..b1260ac3 100644 --- a/bun.lock +++ b/bun.lock @@ -5,18 +5,20 @@ "": { "name": "zkpassport-packages", "devDependencies": { + "@arethetypeswrong/cli": "^0.18.2", "@types/bun": "^1.3.1", "@types/debug": "^4.1.12", "@types/jest": "^30.0.0", "@types/node": "^24.0.13", + "@types/sinonjs__fake-timers": "^15.0.1", "@typescript-eslint/eslint-plugin": "^8.36.0", "@typescript-eslint/parser": "^8.36.0", "eslint": "^8.57.1", "eslint-config-prettier": "^10.1.2", "eslint-plugin-prettier": "^5.2.6", "prettier": "^3.6.2", + "publint": "^0.3.17", "rimraf": "^6.0.1", - "tsc-alias": "^1.8.16", "tsup": "^8.5.0", "turbo": "^2.6.0", "typescript": "^5.0.0", @@ -24,7 +26,7 @@ }, "packages/registry-contracts": { "name": "registry-contracts", - "version": "0.1.0", + "version": "0.2.1", }, "packages/registry-explorer": { "name": "registry-explorer", @@ -65,7 +67,7 @@ }, "packages/registry-sdk": { "name": "@zkpassport/registry", - "version": "0.12.0", + "version": "0.14.0", "dependencies": { "@zkpassport/poseidon2": "^0.6.2", "@zkpassport/utils": "workspace:*", @@ -82,11 +84,11 @@ }, "packages/zkpassport-sdk": { "name": "@zkpassport/sdk", - "version": "0.12.4", + "version": "0.14.2", "dependencies": { - "@aztec/bb.js": "2.0.3", + "@aztec/bb.js": "4.2.0-aztecnr-rc.2", "@noble/ciphers": "^1.2.1", - "@noble/hashes": "^1.7.2", + "@noble/hashes": "^2.0.1", "@noble/secp256k1": "^2.2.3", "@obsidion/bridge": "^0.11.2", "@zkpassport/registry": "workspace:*", @@ -108,12 +110,12 @@ }, "packages/zkpassport-utils": { "name": "@zkpassport/utils", - "version": "0.32.1", + "version": "0.36.1", "dependencies": { "@lapo/asn1js": "^2.0.4", "@noble/ciphers": "^1.0.0", - "@noble/curves": "^1.6.0", - "@noble/hashes": "^1.5.0", + "@noble/curves": "^2.0.1", + "@noble/hashes": "^2.0.1", "@noble/secp256k1": "^2.1.0", "@peculiar/asn1-cms": "^2.3.15", "@peculiar/asn1-ecc": "^2.3.15", @@ -121,6 +123,7 @@ "@peculiar/asn1-schema": "^2.3.15", "@peculiar/asn1-x509": "^2.3.15", "@peculiar/x509": "^1.12.3", + "@taceo/oprf-client": "^0.9.0", "@zk-kit/utils": "^1.2.1", "@zkpassport/poseidon2": "^0.6.2", "date-fns": "^4.1.0", @@ -137,85 +140,95 @@ "@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="], - "@aztec/bb.js": ["@aztec/bb.js@2.0.3", "", { "dependencies": { "comlink": "^4.4.1", "commander": "^12.1.0", "idb-keyval": "^6.2.1", "msgpackr": "^1.11.2", "pako": "^2.1.0", "pino": "^9.5.0", "tslib": "^2.4.0" }, "bin": { "bb.js": "dest/node/main.js" } }, "sha512-sI8lA2L8RMACsi6iBtcuKgGLx4crMzoAaTNtfP3VAaOpjoIwB3O/AMETz5IDGdkOA6tOqM2R0nWh1J+wDYPlVQ=="], + "@andrewbranch/untar.js": ["@andrewbranch/untar.js@1.0.3", "", {}, "sha512-Jh15/qVmrLGhkKJBdXlK1+9tY4lZruYjsgkDFj08ZmDiWVBLJcqkok7Z0/R0In+i1rScBpJlSvrTS2Lm41Pbnw=="], + + "@arethetypeswrong/cli": ["@arethetypeswrong/cli@0.18.2", "", { "dependencies": { "@arethetypeswrong/core": "0.18.2", "chalk": "^4.1.2", "cli-table3": "^0.6.3", "commander": "^10.0.1", "marked": "^9.1.2", "marked-terminal": "^7.1.0", "semver": "^7.5.4" }, "bin": { "attw": "dist/index.js" } }, "sha512-PcFM20JNlevEDKBg4Re29Rtv2xvjvQZzg7ENnrWFSS0PHgdP2njibVFw+dRUhNkPgNfac9iUqO0ohAXqQL4hbw=="], + + "@arethetypeswrong/core": ["@arethetypeswrong/core@0.18.2", "", { "dependencies": { "@andrewbranch/untar.js": "^1.0.3", "@loaderkit/resolve": "^1.0.2", "cjs-module-lexer": "^1.2.3", "fflate": "^0.8.2", "lru-cache": "^11.0.1", "semver": "^7.5.4", "typescript": "5.6.1-rc", "validate-npm-package-name": "^5.0.0" } }, "sha512-GiwTmBFOU1/+UVNqqCGzFJYfBXEytUkiI+iRZ6Qx7KmUVtLm00sYySkfe203C9QtPG11yOz1ZaMek8dT/xnlgg=="], + + "@aztec/bb.js": ["@aztec/bb.js@4.2.0-aztecnr-rc.2", "", { "dependencies": { "comlink": "^4.4.1", "commander": "^12.1.0", "idb-keyval": "^6.2.1", "msgpackr": "^1.11.2", "pako": "^2.1.0", "tslib": "^2.4.0" }, "bin": { "bb": "dest/node/bin/index.js" } }, "sha512-ksFWHrm8QYAXP059paItEKCM/UhpHg5Dwl/eSp2BI6EAtD9+JlonkOwJ+94TYai2y5Gz0qnrgd65dsvDwJelVQ=="], - "@babel/code-frame": ["@babel/code-frame@7.27.1", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg=="], + "@babel/code-frame": ["@babel/code-frame@7.29.0", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw=="], - "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="], + "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.28.5", "", {}, "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="], - "@emnapi/core": ["@emnapi/core@1.5.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" } }, "sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg=="], + "@braidai/lang": ["@braidai/lang@1.1.2", "", {}, "sha512-qBcknbBufNHlui137Hft8xauQMTZDKdophmLFv05r2eNmdIv/MlPuP4TdUknHG68UdWLgVZwgxVe735HzJNIwA=="], - "@emnapi/runtime": ["@emnapi/runtime@1.5.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ=="], + "@colors/colors": ["@colors/colors@1.5.0", "", {}, "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ=="], - "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="], + "@emnapi/core": ["@emnapi/core@1.10.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" } }, "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw=="], - "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.10", "", { "os": "aix", "cpu": "ppc64" }, "sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw=="], + "@emnapi/runtime": ["@emnapi/runtime@1.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA=="], - "@esbuild/android-arm": ["@esbuild/android-arm@0.25.10", "", { "os": "android", "cpu": "arm" }, "sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w=="], + "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w=="], - "@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.10", "", { "os": "android", "cpu": "arm64" }, "sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg=="], + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.7", "", { "os": "aix", "cpu": "ppc64" }, "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg=="], - "@esbuild/android-x64": ["@esbuild/android-x64@0.25.10", "", { "os": "android", "cpu": "x64" }, "sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg=="], + "@esbuild/android-arm": ["@esbuild/android-arm@0.27.7", "", { "os": "android", "cpu": "arm" }, "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ=="], - "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.10", "", { "os": "darwin", "cpu": "arm64" }, "sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA=="], + "@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.7", "", { "os": "android", "cpu": "arm64" }, "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ=="], - "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.10", "", { "os": "darwin", "cpu": "x64" }, "sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg=="], + "@esbuild/android-x64": ["@esbuild/android-x64@0.27.7", "", { "os": "android", "cpu": "x64" }, "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg=="], - "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.10", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg=="], + "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.7", "", { "os": "darwin", "cpu": "arm64" }, "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw=="], - "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.10", "", { "os": "freebsd", "cpu": "x64" }, "sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA=="], + "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.7", "", { "os": "darwin", "cpu": "x64" }, "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ=="], - "@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.10", "", { "os": "linux", "cpu": "arm" }, "sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg=="], + "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.7", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w=="], - "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.10", "", { "os": "linux", "cpu": "arm64" }, "sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ=="], + "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.7", "", { "os": "freebsd", "cpu": "x64" }, "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ=="], - "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.10", "", { "os": "linux", "cpu": "ia32" }, "sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ=="], + "@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.7", "", { "os": "linux", "cpu": "arm" }, "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA=="], - "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.10", "", { "os": "linux", "cpu": "none" }, "sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg=="], + "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.7", "", { "os": "linux", "cpu": "arm64" }, "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A=="], - "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.10", "", { "os": "linux", "cpu": "none" }, "sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA=="], + "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.7", "", { "os": "linux", "cpu": "ia32" }, "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg=="], - "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.10", "", { "os": "linux", "cpu": "ppc64" }, "sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA=="], + "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.7", "", { "os": "linux", "cpu": "none" }, "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q=="], - "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.10", "", { "os": "linux", "cpu": "none" }, "sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA=="], + "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.7", "", { "os": "linux", "cpu": "none" }, "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw=="], - "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.10", "", { "os": "linux", "cpu": "s390x" }, "sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew=="], + "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.7", "", { "os": "linux", "cpu": "ppc64" }, "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ=="], - "@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.10", "", { "os": "linux", "cpu": "x64" }, "sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA=="], + "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.7", "", { "os": "linux", "cpu": "none" }, "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ=="], - "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.10", "", { "os": "none", "cpu": "arm64" }, "sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A=="], + "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.7", "", { "os": "linux", "cpu": "s390x" }, "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw=="], - "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.10", "", { "os": "none", "cpu": "x64" }, "sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig=="], + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.7", "", { "os": "linux", "cpu": "x64" }, "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA=="], - "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.10", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw=="], + "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.7", "", { "os": "none", "cpu": "arm64" }, "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w=="], - "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.10", "", { "os": "openbsd", "cpu": "x64" }, "sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw=="], + "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.7", "", { "os": "none", "cpu": "x64" }, "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw=="], - "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.10", "", { "os": "none", "cpu": "arm64" }, "sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag=="], + "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.7", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A=="], - "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.10", "", { "os": "sunos", "cpu": "x64" }, "sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ=="], + "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.7", "", { "os": "openbsd", "cpu": "x64" }, "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg=="], - "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.10", "", { "os": "win32", "cpu": "arm64" }, "sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw=="], + "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.7", "", { "os": "none", "cpu": "arm64" }, "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw=="], - "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.10", "", { "os": "win32", "cpu": "ia32" }, "sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw=="], + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.7", "", { "os": "sunos", "cpu": "x64" }, "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA=="], - "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.10", "", { "os": "win32", "cpu": "x64" }, "sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw=="], + "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.7", "", { "os": "win32", "cpu": "arm64" }, "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA=="], - "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.9.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g=="], + "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.7", "", { "os": "win32", "cpu": "ia32" }, "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw=="], - "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.1", "", {}, "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ=="], + "@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.7", "", { "os": "win32", "cpu": "x64" }, "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg=="], + + "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.9.1", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ=="], + + "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.2", "", {}, "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew=="], "@eslint/eslintrc": ["@eslint/eslintrc@2.1.4", "", { "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^9.6.0", "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" } }, "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ=="], "@eslint/js": ["@eslint/js@8.57.1", "", {}, "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q=="], - "@floating-ui/core": ["@floating-ui/core@1.7.3", "", { "dependencies": { "@floating-ui/utils": "^0.2.10" } }, "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w=="], + "@floating-ui/core": ["@floating-ui/core@1.7.5", "", { "dependencies": { "@floating-ui/utils": "^0.2.11" } }, "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ=="], - "@floating-ui/dom": ["@floating-ui/dom@1.7.4", "", { "dependencies": { "@floating-ui/core": "^1.7.3", "@floating-ui/utils": "^0.2.10" } }, "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA=="], + "@floating-ui/dom": ["@floating-ui/dom@1.7.6", "", { "dependencies": { "@floating-ui/core": "^1.7.5", "@floating-ui/utils": "^0.2.11" } }, "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ=="], - "@floating-ui/react-dom": ["@floating-ui/react-dom@2.1.6", "", { "dependencies": { "@floating-ui/dom": "^1.7.4" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw=="], + "@floating-ui/react-dom": ["@floating-ui/react-dom@2.1.8", "", { "dependencies": { "@floating-ui/dom": "^1.7.6" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A=="], - "@floating-ui/utils": ["@floating-ui/utils@0.2.10", "", {}, "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ=="], + "@floating-ui/utils": ["@floating-ui/utils@0.2.11", "", {}, "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg=="], "@humanwhocodes/config-array": ["@humanwhocodes/config-array@0.13.0", "", { "dependencies": { "@humanwhocodes/object-schema": "^2.0.3", "debug": "^4.3.1", "minimatch": "^3.0.5" } }, "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw=="], @@ -223,15 +236,11 @@ "@humanwhocodes/object-schema": ["@humanwhocodes/object-schema@2.0.3", "", {}, "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA=="], - "@isaacs/balanced-match": ["@isaacs/balanced-match@4.0.1", "", {}, "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ=="], - - "@isaacs/brace-expansion": ["@isaacs/brace-expansion@5.0.0", "", { "dependencies": { "@isaacs/balanced-match": "^4.0.1" } }, "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA=="], - "@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="], - "@jest/diff-sequences": ["@jest/diff-sequences@30.0.1", "", {}, "sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw=="], + "@jest/diff-sequences": ["@jest/diff-sequences@30.3.0", "", {}, "sha512-cG51MVnLq1ecVUaQ3fr6YuuAOitHK1S4WUJHnsPFE/quQr33ADUx1FfrTCpMCRxvy0Yr9BThKpDjSlcTi91tMA=="], - "@jest/expect-utils": ["@jest/expect-utils@30.2.0", "", { "dependencies": { "@jest/get-type": "30.1.0" } }, "sha512-1JnRfhqpD8HGpOmQp180Fo9Zt69zNtC+9lR+kT7NVL05tNXIi+QC8Csz7lfidMoVLPD3FnOtcmp0CEFnxExGEA=="], + "@jest/expect-utils": ["@jest/expect-utils@30.3.0", "", { "dependencies": { "@jest/get-type": "30.1.0" } }, "sha512-j0+W5iQQ8hBh7tHZkTQv3q2Fh/M7Je72cIsYqC4OaktgtO7v1So9UTjp6uPBHIaB6beoF/RRsCgMJKvti0wADA=="], "@jest/get-type": ["@jest/get-type@30.1.0", "", {}, "sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA=="], @@ -239,7 +248,7 @@ "@jest/schemas": ["@jest/schemas@30.0.5", "", { "dependencies": { "@sinclair/typebox": "^0.34.0" } }, "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA=="], - "@jest/types": ["@jest/types@30.2.0", "", { "dependencies": { "@jest/pattern": "30.0.1", "@jest/schemas": "30.0.5", "@types/istanbul-lib-coverage": "^2.0.6", "@types/istanbul-reports": "^3.0.4", "@types/node": "*", "@types/yargs": "^17.0.33", "chalk": "^4.1.2" } }, "sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg=="], + "@jest/types": ["@jest/types@30.3.0", "", { "dependencies": { "@jest/pattern": "30.0.1", "@jest/schemas": "30.0.5", "@types/istanbul-lib-coverage": "^2.0.6", "@types/istanbul-reports": "^3.0.4", "@types/node": "*", "@types/yargs": "^17.0.33", "chalk": "^4.1.2" } }, "sha512-JHm87k7bA33hpBngtU8h6UBub/fqqA9uXfw+21j5Hmk7ooPHlboRNxHq0JcMtC+n8VJGP1mcfnD3Mk+XKe1oSw=="], "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="], @@ -249,7 +258,9 @@ "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="], - "@lapo/asn1js": ["@lapo/asn1js@2.1.0", "", { "bin": { "dumpASN1": "dumpASN1.js" } }, "sha512-SIRsS9jhhpsRxr1d5leFfdI6sEOQciQXShN7sIwoze+iEevvoKmLGG66PyLDgIEYeONq80sx48xs86eK4MItEw=="], + "@lapo/asn1js": ["@lapo/asn1js@2.1.3", "", { "bin": { "dumpASN1": "dumpASN1.js" } }, "sha512-eX1xNRPeP5dCtUpQg/lqHZjBd0//wJ05yn/4osewSc4rxC1KCXBfbUeCiQEdNREbGMa3xjZxjkYNY1AHzUkleQ=="], + + "@loaderkit/resolve": ["@loaderkit/resolve@1.0.5", "", { "dependencies": { "@braidai/lang": "^1.0.0" } }, "sha512-fhkdGM57xhJ7CO91MUgbQlb0ClP0AJ9vB3yoVnBTslYJqrJOCVEbOprZcxZlexdMbmTBPQqVcQYr+j4oRRtIZA=="], "@msgpackr-extract/msgpackr-extract-darwin-arm64": ["@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw=="], @@ -289,9 +300,9 @@ "@noble/ciphers": ["@noble/ciphers@1.3.0", "", {}, "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw=="], - "@noble/curves": ["@noble/curves@1.9.7", "", { "dependencies": { "@noble/hashes": "1.8.0" } }, "sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw=="], + "@noble/curves": ["@noble/curves@2.2.0", "", { "dependencies": { "@noble/hashes": "2.2.0" } }, "sha512-T/BoHgFXirb0ENSPBquzX0rcjXeM6Lo892a2jlYJkqk83LqZx0l1Of7DzlKJ6jkpvMrkHSnAcgb5JegL8SeIkQ=="], - "@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="], + "@noble/hashes": ["@noble/hashes@2.2.0", "", {}, "sha512-IYqDGiTXab6FniAgnSdZwgWbomxpy9FtYvLKs7wCUs2a8RkITG+DFGO1DM9cr+E3/RgADRpFjrKVaJ1z6sjtEg=="], "@noble/secp256k1": ["@noble/secp256k1@2.3.0", "", {}, "sha512-0TQed2gcBbIrh7Ccyw+y/uZQvbJwm7Ao4scBUxqpBCcsOlZG0O4KGfjtNAy/li4W8n1xt3dxrwJ0beZ2h2G6Kw=="], @@ -305,32 +316,36 @@ "@obsidion/bridge": ["@obsidion/bridge@0.11.2", "", { "dependencies": { "@noble/ciphers": "^1.2.1", "@noble/hashes": "^1.8.0", "@noble/secp256k1": "^2.2.3", "@types/pako": "^2.0.3", "debug": "^4.3.4", "pako": "^2.1.0", "ws": "^8.16.0" }, "peerDependencies": { "typescript": "^5.0.0" } }, "sha512-IX5g2c6TF9xKGFgnQBAq4TJLns+W2SfDgndE1orsLIQCRJ8UKsu5Mt+RwbI6sDu7PxVveZvmLEaiXhJl7NhJaQ=="], - "@peculiar/asn1-cms": ["@peculiar/asn1-cms@2.5.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.5.0", "@peculiar/asn1-x509": "^2.5.0", "@peculiar/asn1-x509-attr": "^2.5.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-p0SjJ3TuuleIvjPM4aYfvYw8Fk1Hn/zAVyPJZTtZ2eE9/MIer6/18ROxX6N/e6edVSfvuZBqhxAj3YgsmSjQ/A=="], + "@peculiar/asn1-cms": ["@peculiar/asn1-cms@2.7.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.7.0", "@peculiar/asn1-x509": "^2.7.0", "@peculiar/asn1-x509-attr": "^2.7.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-hew63shtzzvBcSHbhm+cyAmKe6AIfinT9hzEqSPjDC6opTTMKmTkQ0gHuN2KsWlvqiKw1S/fS94fhag/FJkioQ=="], + + "@peculiar/asn1-csr": ["@peculiar/asn1-csr@2.7.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.7.0", "@peculiar/asn1-x509": "^2.7.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-VVsAyGqErT9D1SY4aEqozThXMVI+ssVRiv2DDeYuvpBKLIgZ3hYs3Ay3u/VSoKq6ESFi9cf6rf3IOOzfwh7oMA=="], - "@peculiar/asn1-csr": ["@peculiar/asn1-csr@2.5.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.5.0", "@peculiar/asn1-x509": "^2.5.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-ioigvA6WSYN9h/YssMmmoIwgl3RvZlAYx4A/9jD2qaqXZwGcNlAxaw54eSx2QG1Yu7YyBC5Rku3nNoHrQ16YsQ=="], + "@peculiar/asn1-ecc": ["@peculiar/asn1-ecc@2.7.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.7.0", "@peculiar/asn1-x509": "^2.7.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-n7KEs/Q/wrB415cxy4fHOBhegp4NdJ15fkJPwcB/3/8iNBQC2L/N7SChJPKDJPZGYH0jD4Tg4/0vnHmwghnbKw=="], - "@peculiar/asn1-ecc": ["@peculiar/asn1-ecc@2.5.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.5.0", "@peculiar/asn1-x509": "^2.5.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-t4eYGNhXtLRxaP50h3sfO6aJebUCDGQACoeexcelL4roMFRRVgB20yBIu2LxsPh/tdW9I282gNgMOyg3ywg/mg=="], + "@peculiar/asn1-pfx": ["@peculiar/asn1-pfx@2.7.0", "", { "dependencies": { "@peculiar/asn1-cms": "^2.7.0", "@peculiar/asn1-pkcs8": "^2.7.0", "@peculiar/asn1-rsa": "^2.7.0", "@peculiar/asn1-schema": "^2.7.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-V/nrlQVmhg7lYAsM7E13UDL5erAwFv6kCIVFqNaMIHSVi7dngcT839JkRTkQBqznMG98l2XjxYk74ZztAohZzA=="], - "@peculiar/asn1-pfx": ["@peculiar/asn1-pfx@2.5.0", "", { "dependencies": { "@peculiar/asn1-cms": "^2.5.0", "@peculiar/asn1-pkcs8": "^2.5.0", "@peculiar/asn1-rsa": "^2.5.0", "@peculiar/asn1-schema": "^2.5.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-Vj0d0wxJZA+Ztqfb7W+/iu8Uasw6hhKtCdLKXLG/P3kEPIQpqGI4P4YXlROfl7gOCqFIbgsj1HzFIFwQ5s20ug=="], + "@peculiar/asn1-pkcs8": ["@peculiar/asn1-pkcs8@2.7.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.7.0", "@peculiar/asn1-x509": "^2.7.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-9GTl1nE8Mx1kTZ+7QyYatDyKsm34QcWRBFkY1iPvWC3X4Dona5s/tlLiQsx5WzVdZqiMBZNYT0buyw4/vbhnjw=="], - "@peculiar/asn1-pkcs8": ["@peculiar/asn1-pkcs8@2.5.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.5.0", "@peculiar/asn1-x509": "^2.5.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-L7599HTI2SLlitlpEP8oAPaJgYssByI4eCwQq2C9eC90otFpm8MRn66PpbKviweAlhinWQ3ZjDD2KIVtx7PaVw=="], + "@peculiar/asn1-pkcs9": ["@peculiar/asn1-pkcs9@2.7.0", "", { "dependencies": { "@peculiar/asn1-cms": "^2.7.0", "@peculiar/asn1-pfx": "^2.7.0", "@peculiar/asn1-pkcs8": "^2.7.0", "@peculiar/asn1-schema": "^2.7.0", "@peculiar/asn1-x509": "^2.7.0", "@peculiar/asn1-x509-attr": "^2.7.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-Bh7m+OuIaSEllPQcSd9OSp93F4ROWH7sbITWV8MI+8dwsjE5111/87VxiWVvYFKyww3vp39geLv9ENqhwWHcew=="], - "@peculiar/asn1-pkcs9": ["@peculiar/asn1-pkcs9@2.5.0", "", { "dependencies": { "@peculiar/asn1-cms": "^2.5.0", "@peculiar/asn1-pfx": "^2.5.0", "@peculiar/asn1-pkcs8": "^2.5.0", "@peculiar/asn1-schema": "^2.5.0", "@peculiar/asn1-x509": "^2.5.0", "@peculiar/asn1-x509-attr": "^2.5.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-UgqSMBLNLR5TzEZ5ZzxR45Nk6VJrammxd60WMSkofyNzd3DQLSNycGWSK5Xg3UTYbXcDFyG8pA/7/y/ztVCa6A=="], + "@peculiar/asn1-rsa": ["@peculiar/asn1-rsa@2.7.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.7.0", "@peculiar/asn1-x509": "^2.7.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-/qvENQrXyTZURjMqSeofHul0JJt2sNSzSwk36pl2olkHbaioMQgrASDZAlHXl0xUlnVbHj0uGgOrBMTb5x2aJQ=="], - "@peculiar/asn1-rsa": ["@peculiar/asn1-rsa@2.5.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.5.0", "@peculiar/asn1-x509": "^2.5.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-qMZ/vweiTHy9syrkkqWFvbT3eLoedvamcUdnnvwyyUNv5FgFXA3KP8td+ATibnlZ0EANW5PYRm8E6MJzEB/72Q=="], + "@peculiar/asn1-schema": ["@peculiar/asn1-schema@2.7.0", "", { "dependencies": { "@peculiar/utils": "^2.0.2", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-W8ZfWzLmQnrcky+eh3tni4IozMdqBDiHWU0N+vve/UGjMaUs8c0L7A2oEdkBXS8rTpWDpK/aoI3DG/L/hxmxPg=="], - "@peculiar/asn1-schema": ["@peculiar/asn1-schema@2.5.0", "", { "dependencies": { "asn1js": "^3.0.6", "pvtsutils": "^1.3.6", "tslib": "^2.8.1" } }, "sha512-YM/nFfskFJSlHqv59ed6dZlLZqtZQwjRVJ4bBAiWV08Oc+1rSd5lDZcBEx0lGDHfSoH3UziI2pXt2UM33KerPQ=="], + "@peculiar/asn1-x509": ["@peculiar/asn1-x509@2.7.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.7.0", "@peculiar/utils": "^2.0.2", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-mUn9RRrkGDnG4ALfunDmzyRW5dg+sWCj/pfnCCqEHYbkGxEpvUt6iVJv8Yw1cyp6SWZ26ZE5oSmI5SqEaen15g=="], - "@peculiar/asn1-x509": ["@peculiar/asn1-x509@2.5.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.5.0", "asn1js": "^3.0.6", "pvtsutils": "^1.3.6", "tslib": "^2.8.1" } }, "sha512-CpwtMCTJvfvYTFMuiME5IH+8qmDe3yEWzKHe7OOADbGfq7ohxeLaXwQo0q4du3qs0AII3UbLCvb9NF/6q0oTKQ=="], + "@peculiar/asn1-x509-attr": ["@peculiar/asn1-x509-attr@2.7.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.7.0", "@peculiar/asn1-x509": "^2.7.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-NS8e7SOgXipkzUPLF/sce7ukpMpWjhxYsH0n6Y+bHYo4TTxOb95Zv7hqwSuL212mj5YxovjdOKQOgH1As3E94w=="], - "@peculiar/asn1-x509-attr": ["@peculiar/asn1-x509-attr@2.5.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.5.0", "@peculiar/asn1-x509": "^2.5.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-9f0hPOxiJDoG/bfNLAFven+Bd4gwz/VzrCIIWc1025LEI4BXO0U5fOCTNDPbbp2ll+UzqKsZ3g61mpBp74gk9A=="], + "@peculiar/utils": ["@peculiar/utils@2.0.3", "", { "dependencies": { "tslib": "^2.8.1" } }, "sha512-+oL3HPFRIZ1St2K50lWCXiioIgSoxzz7R1J3uF6neO2yl1sgmpgY6XXJH4BdpoDkMWznQTeYF6oWNDZLCdQ4eQ=="], - "@peculiar/x509": ["@peculiar/x509@1.14.0", "", { "dependencies": { "@peculiar/asn1-cms": "^2.5.0", "@peculiar/asn1-csr": "^2.5.0", "@peculiar/asn1-ecc": "^2.5.0", "@peculiar/asn1-pkcs9": "^2.5.0", "@peculiar/asn1-rsa": "^2.5.0", "@peculiar/asn1-schema": "^2.5.0", "@peculiar/asn1-x509": "^2.5.0", "pvtsutils": "^1.3.6", "reflect-metadata": "^0.2.2", "tslib": "^2.8.1", "tsyringe": "^4.10.0" } }, "sha512-Yc4PDxN3OrxUPiXgU63c+ZRXKGE8YKF2McTciYhUHFtHVB0KMnjeFSU0qpztGhsp4P0uKix4+J2xEpIEDu8oXg=="], + "@peculiar/x509": ["@peculiar/x509@1.14.3", "", { "dependencies": { "@peculiar/asn1-cms": "^2.6.0", "@peculiar/asn1-csr": "^2.6.0", "@peculiar/asn1-ecc": "^2.6.0", "@peculiar/asn1-pkcs9": "^2.6.0", "@peculiar/asn1-rsa": "^2.6.0", "@peculiar/asn1-schema": "^2.6.0", "@peculiar/asn1-x509": "^2.6.0", "pvtsutils": "^1.3.6", "reflect-metadata": "^0.2.2", "tslib": "^2.8.1", "tsyringe": "^4.10.0" } }, "sha512-C2Xj8FZ0uHWeCXXqX5B4/gVFQmtSkiuOolzAgutjTfseNOHT3pUjljDZsTSxXFGgio54bCzVFqmEOUrIVk8RDA=="], "@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="], "@pkgr/core": ["@pkgr/core@0.2.9", "", {}, "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA=="], + "@publint/pack": ["@publint/pack@0.1.4", "", {}, "sha512-HDVTWq3H0uTXiU0eeSQntcVUTPP3GamzeXI41+x7uU9J65JgWQh3qWZHblR1i0npXfFtF+mxBiU2nJH8znxWnQ=="], + "@radix-ui/number": ["@radix-ui/number@1.1.1", "", {}, "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g=="], "@radix-ui/primitive": ["@radix-ui/primitive@1.1.3", "", {}, "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg=="], @@ -363,7 +378,7 @@ "@radix-ui/react-select": ["@radix-ui/react-select@2.2.6", "", { "dependencies": { "@radix-ui/number": "1.1.1", "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-focus-guards": "1.1.3", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-visually-hidden": "1.2.3", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ=="], - "@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="], + "@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.4", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA=="], "@radix-ui/react-tooltip": ["@radix-ui/react-tooltip@1.2.8", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-visually-hidden": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg=="], @@ -387,53 +402,59 @@ "@radix-ui/rect": ["@radix-ui/rect@1.1.1", "", {}, "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw=="], - "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.52.4", "", { "os": "android", "cpu": "arm" }, "sha512-BTm2qKNnWIQ5auf4deoetINJm2JzvihvGb9R6K/ETwKLql/Bb3Eg2H1FBp1gUb4YGbydMA3jcmQTR73q7J+GAA=="], + "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.60.2", "", { "os": "android", "cpu": "arm" }, "sha512-dnlp69efPPg6Uaw2dVqzWRfAWRnYVb1XJ8CyyhIbZeaq4CA5/mLeZ1IEt9QqQxmbdvagjLIm2ZL8BxXv5lH4Yw=="], + + "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.60.2", "", { "os": "android", "cpu": "arm64" }, "sha512-OqZTwDRDchGRHHm/hwLOL7uVPB9aUvI0am/eQuWMNyFHf5PSEQmyEeYYheA0EPPKUO/l0uigCp+iaTjoLjVoHg=="], - "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.52.4", "", { "os": "android", "cpu": "arm64" }, "sha512-P9LDQiC5vpgGFgz7GSM6dKPCiqR3XYN1WwJKA4/BUVDjHpYsf3iBEmVz62uyq20NGYbiGPR5cNHI7T1HqxNs2w=="], + "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.60.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-UwRE7CGpvSVEQS8gUMBe1uADWjNnVgP3Iusyda1nSRwNDCsRjnGc7w6El6WLQsXmZTbLZx9cecegumcitNfpmA=="], - "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.52.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-QRWSW+bVccAvZF6cbNZBJwAehmvG9NwfWHwMy4GbWi/BQIA/laTIktebT2ipVjNncqE6GLPxOok5hsECgAxGZg=="], + "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.60.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-gjEtURKLCC5VXm1I+2i1u9OhxFsKAQJKTVB8WvDAHF+oZlq0GTVFOlTlO1q3AlCTE/DF32c16ESvfgqR7343/g=="], - "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.52.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-hZgP05pResAkRJxL1b+7yxCnXPGsXU0fG9Yfd6dUaoGk+FhdPKCJ5L1Sumyxn8kvw8Qi5PvQ8ulenUbRjzeCTw=="], + "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.60.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-Bcl6CYDeAgE70cqZaMojOi/eK63h5Me97ZqAQoh77VPjMysA/4ORQBRGo3rRy45x4MzVlU9uZxs8Uwy7ZaKnBw=="], - "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.52.4", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-xmc30VshuBNUd58Xk4TKAEcRZHaXlV+tCxIXELiE9sQuK3kG8ZFgSPi57UBJt8/ogfhAF5Oz4ZSUBN77weM+mQ=="], + "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.60.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-LU+TPda3mAE2QB0/Hp5VyeKJivpC6+tlOXd1VMoXV/YFMvk/MNk5iXeBfB4MQGRWyOYVJ01625vjkr0Az98OJQ=="], - "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.52.4", "", { "os": "freebsd", "cpu": "x64" }, "sha512-WdSLpZFjOEqNZGmHflxyifolwAiZmDQzuOzIq9L27ButpCVpD7KzTRtEG1I0wMPFyiyUdOO+4t8GvrnBLQSwpw=="], + "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.60.2", "", { "os": "linux", "cpu": "arm" }, "sha512-2QxQrM+KQ7DAW4o22j+XZ6RKdxjLD7BOWTP0Bv0tmjdyhXSsr2Ul1oJDQqh9Zf5qOwTuTc7Ek83mOFaKnodPjg=="], - "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.52.4", "", { "os": "linux", "cpu": "arm" }, "sha512-xRiOu9Of1FZ4SxVbB0iEDXc4ddIcjCv2aj03dmW8UrZIW7aIQ9jVJdLBIhxBI+MaTnGAKyvMwPwQnoOEvP7FgQ=="], + "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.60.2", "", { "os": "linux", "cpu": "arm" }, "sha512-TbziEu2DVsTEOPif2mKWkMeDMLoYjx95oESa9fkQQK7r/Orta0gnkcDpzwufEcAO2BLBsD7mZkXGFqEdMRRwfw=="], - "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.52.4", "", { "os": "linux", "cpu": "arm" }, "sha512-FbhM2p9TJAmEIEhIgzR4soUcsW49e9veAQCziwbR+XWB2zqJ12b4i/+hel9yLiD8pLncDH4fKIPIbt5238341Q=="], + "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.60.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-bO/rVDiDUuM2YfuCUwZ1t1cP+/yqjqz+Xf2VtkdppefuOFS2OSeAfgafaHNkFn0t02hEyXngZkxtGqXcXwO8Rg=="], - "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.52.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-4n4gVwhPHR9q/g8lKCyz0yuaD0MvDf7dV4f9tHt0C73Mp8h38UCtSCSE6R9iBlTbXlmA8CjpsZoujhszefqueg=="], + "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.60.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-hr26p7e93Rl0Za+JwW7EAnwAvKkehh12BU1Llm9Ykiibg4uIr2rbpxG9WCf56GuvidlTG9KiiQT/TXT1yAWxTA=="], - "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.52.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-u0n17nGA0nvi/11gcZKsjkLj1QIpAuPFQbR48Subo7SmZJnGxDpspyw2kbpuoQnyK+9pwf3pAoEXerJs/8Mi9g=="], + "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.60.2", "", { "os": "linux", "cpu": "none" }, "sha512-pOjB/uSIyDt+ow3k/RcLvUAOGpysT2phDn7TTUB3n75SlIgZzM6NKAqlErPhoFU+npgY3/n+2HYIQVbF70P9/A=="], - "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.52.4", "", { "os": "linux", "cpu": "none" }, "sha512-0G2c2lpYtbTuXo8KEJkDkClE/+/2AFPdPAbmaHoE870foRFs4pBrDehilMcrSScrN/fB/1HTaWO4bqw+ewBzMQ=="], + "@rollup/rollup-linux-loong64-musl": ["@rollup/rollup-linux-loong64-musl@4.60.2", "", { "os": "linux", "cpu": "none" }, "sha512-2/w+q8jszv9Ww1c+6uJT3OwqhdmGP2/4T17cu8WuwyUuuaCDDJ2ojdyYwZzCxx0GcsZBhzi3HmH+J5pZNXnd+Q=="], - "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.52.4", "", { "os": "linux", "cpu": "ppc64" }, "sha512-teSACug1GyZHmPDv14VNbvZFX779UqWTsd7KtTM9JIZRDI5NUwYSIS30kzI8m06gOPB//jtpqlhmraQ68b5X2g=="], + "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.60.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-11+aL5vKheYgczxtPVVRhdptAM2H7fcDR5Gw4/bTcteuZBlH4oP9f5s9zYO9aGZvoGeBpqXI/9TZZihZ609wKw=="], - "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.52.4", "", { "os": "linux", "cpu": "none" }, "sha512-/MOEW3aHjjs1p4Pw1Xk4+3egRevx8Ji9N6HUIA1Ifh8Q+cg9dremvFCUbOX2Zebz80BwJIgCBUemjqhU5XI5Eg=="], + "@rollup/rollup-linux-ppc64-musl": ["@rollup/rollup-linux-ppc64-musl@4.60.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-i16fokAGK46IVZuV8LIIwMdtqhin9hfYkCh8pf8iC3QU3LpwL+1FSFGej+O7l3E/AoknL6Dclh2oTdnRMpTzFQ=="], - "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.52.4", "", { "os": "linux", "cpu": "none" }, "sha512-1HHmsRyh845QDpEWzOFtMCph5Ts+9+yllCrREuBR/vg2RogAQGGBRC8lDPrPOMnrdOJ+mt1WLMOC2Kao/UwcvA=="], + "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.60.2", "", { "os": "linux", "cpu": "none" }, "sha512-49FkKS6RGQoriDSK/6E2GkAsAuU5kETFCh7pG4yD/ylj9rKhTmO3elsnmBvRD4PgJPds5W2PkhC82aVwmUcJ7A=="], - "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.52.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-seoeZp4L/6D1MUyjWkOMRU6/iLmCU2EjbMTyAG4oIOs1/I82Y5lTeaxW0KBfkUdHAWN7j25bpkt0rjnOgAcQcA=="], + "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.60.2", "", { "os": "linux", "cpu": "none" }, "sha512-mjYNkHPfGpUR00DuM1ZZIgs64Hpf4bWcz9Z41+4Q+pgDx73UwWdAYyf6EG/lRFldmdHHzgrYyge5akFUW0D3mQ=="], - "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.52.4", "", { "os": "linux", "cpu": "x64" }, "sha512-Wi6AXf0k0L7E2gteNsNHUs7UMwCIhsCTs6+tqQ5GPwVRWMaflqGec4Sd8n6+FNFDw9vGcReqk2KzBDhCa1DLYg=="], + "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.60.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-ALyvJz965BQk8E9Al/JDKKDLH2kfKFLTGMlgkAbbYtZuJt9LU8DW3ZoDMCtQpXAltZxwBHevXz5u+gf0yA0YoA=="], - "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.52.4", "", { "os": "linux", "cpu": "x64" }, "sha512-dtBZYjDmCQ9hW+WgEkaffvRRCKm767wWhxsFW3Lw86VXz/uJRuD438/XvbZT//B96Vs8oTA8Q4A0AfHbrxP9zw=="], + "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.60.2", "", { "os": "linux", "cpu": "x64" }, "sha512-UQjrkIdWrKI626Du8lCQ6MJp/6V1LAo2bOK9OTu4mSn8GGXIkPXk/Vsp4bLHCd9Z9Iz2OTEaokUE90VweJgIYQ=="], - "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.52.4", "", { "os": "none", "cpu": "arm64" }, "sha512-1ox+GqgRWqaB1RnyZXL8PD6E5f7YyRUJYnCqKpNzxzP0TkaUh112NDrR9Tt+C8rJ4x5G9Mk8PQR3o7Ku2RKqKA=="], + "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.60.2", "", { "os": "linux", "cpu": "x64" }, "sha512-bTsRGj6VlSdn/XD4CGyzMnzaBs9bsRxy79eTqTCBsA8TMIEky7qg48aPkvJvFe1HyzQ5oMZdg7AnVlWQSKLTnw=="], - "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.52.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-8GKr640PdFNXwzIE0IrkMWUNUomILLkfeHjXBi/nUvFlpZP+FA8BKGKpacjW6OUUHaNI6sUURxR2U2g78FOHWQ=="], + "@rollup/rollup-openbsd-x64": ["@rollup/rollup-openbsd-x64@4.60.2", "", { "os": "openbsd", "cpu": "x64" }, "sha512-6d4Z3534xitaA1FcMWP7mQPq5zGwBmGbhphh2DwaA1aNIXUu3KTOfwrWpbwI4/Gr0uANo7NTtaykFyO2hPuFLg=="], - "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.52.4", "", { "os": "win32", "cpu": "ia32" }, "sha512-AIy/jdJ7WtJ/F6EcfOb2GjR9UweO0n43jNObQMb6oGxkYTfLcnN7vYYpG+CN3lLxrQkzWnMOoNSHTW54pgbVxw=="], + "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.60.2", "", { "os": "none", "cpu": "arm64" }, "sha512-NetAg5iO2uN7eB8zE5qrZ3CSil+7IJt4WDFLcC75Ymywq1VZVD6qJ6EvNLjZ3rEm6gB7XW5JdT60c6MN35Z85Q=="], - "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.52.4", "", { "os": "win32", "cpu": "x64" }, "sha512-UF9KfsH9yEam0UjTwAgdK0anlQ7c8/pWPU2yVjyWcF1I1thABt6WXE47cI71pGiZ8wGvxohBoLnxM04L/wj8mQ=="], + "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.60.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-NCYhOotpgWZ5kdxCZsv6Iudx0wX8980Q/oW4pNFNihpBKsDbEA1zpkfxJGC0yugsUuyDZ7gL37dbzwhR0VI7pQ=="], - "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.52.4", "", { "os": "win32", "cpu": "x64" }, "sha512-bf9PtUa0u8IXDVxzRToFQKsNCRz9qLYfR/MpECxl4mRoWYjAeFjgxj1XdZr2M/GNVpT05p+LgQOHopYDlUu6/w=="], + "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.60.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-RXsaOqXxfoUBQoOgvmmijVxJnW2IGB0eoMO7F8FAjaj0UTywUO/luSqimWBJn04WNgUkeNhh7fs7pESXajWmkg=="], + + "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.60.2", "", { "os": "win32", "cpu": "x64" }, "sha512-qdAzEULD+/hzObedtmV6iBpdL5TIbKVztGiK7O3/KYSf+HIzU257+MX1EXJcyIiDbMAqmbwaufcYPvyRryeZtA=="], + + "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.60.2", "", { "os": "win32", "cpu": "x64" }, "sha512-Nd/SgG27WoA9e+/TdK74KnHz852TLa94ovOYySo/yMPuTmpckK/jIF2jSwS3g7ELSKXK13/cVdmg1Z/DaCWKxA=="], "@rtsao/scc": ["@rtsao/scc@1.1.0", "", {}, "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g=="], - "@rushstack/eslint-patch": ["@rushstack/eslint-patch@1.14.0", "", {}, "sha512-WJFej426qe4RWOm9MMtP4V3CV4AucXolQty+GRgAWLgQXmpCuwzs7hEpxxhSc/znXUSxum9d/P/32MW0FlAAlA=="], + "@rushstack/eslint-patch": ["@rushstack/eslint-patch@1.16.1", "", {}, "sha512-TvZbIpeKqGQQ7X0zSCvPH9riMSFQFSggnfBjFZ1mEoILW+UuXCKwOoPcgjMwiUtRqFZ8jWhPJc4um14vC6I4ag=="], "@scure/base": ["@scure/base@1.2.6", "", {}, "sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg=="], @@ -441,21 +462,39 @@ "@scure/bip39": ["@scure/bip39@1.6.0", "", { "dependencies": { "@noble/hashes": "~1.8.0", "@scure/base": "~1.2.5" } }, "sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A=="], - "@sinclair/typebox": ["@sinclair/typebox@0.34.41", "", {}, "sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g=="], + "@sinclair/typebox": ["@sinclair/typebox@0.34.49", "", {}, "sha512-brySQQs7Jtn0joV8Xh9ZV/hZb9Ozb0pmazDIASBkYKCjXrXU3mpcFahmK/z4YDhGkQvP9mWJbVyahdtU5wQA+A=="], + + "@sindresorhus/is": ["@sindresorhus/is@4.6.0", "", {}, "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw=="], "@sinonjs/commons": ["@sinonjs/commons@3.0.1", "", { "dependencies": { "type-detect": "4.0.8" } }, "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ=="], - "@sinonjs/fake-timers": ["@sinonjs/fake-timers@15.0.0", "", { "dependencies": { "@sinonjs/commons": "^3.0.1" } }, "sha512-dlUB2oL+hDIYkIq/OWFBDhQAuU6kDey3eeMiYpVb7UXHhkMq/r1HloKXAbJwJZpYWkFWsydLjMqDpueMUEOjXQ=="], + "@sinonjs/fake-timers": ["@sinonjs/fake-timers@15.3.2", "", { "dependencies": { "@sinonjs/commons": "^3.0.1" } }, "sha512-mrn35Jl2pCpns+mE3HaZa1yPN5EYCRgiMI+135COjr2hr8Cls9DXqIZ57vZe2cz7y2XVSq92tcs6kGQcT1J8Rw=="], "@swc/counter": ["@swc/counter@0.1.3", "", {}, "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ=="], "@swc/helpers": ["@swc/helpers@0.5.5", "", { "dependencies": { "@swc/counter": "^0.1.3", "tslib": "^2.4.0" } }, "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A=="], - "@trysound/sax": ["@trysound/sax@0.2.0", "", {}, "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA=="], + "@taceo/oprf-client": ["@taceo/oprf-client@0.9.0", "", { "dependencies": { "@noble/curves": "^2.0.1", "@noble/hashes": "^2.0.1", "@taceo/oprf-core": "0.4.0" } }, "sha512-kokCCLYjLSH3I7n4D2Yhg1ybNquMRnbHh3r/YTgHIiXxJ+FLsbE9AGT8vhwTmwe2m4X1U3r57yKMsIiaeu/DAg=="], - "@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="], + "@taceo/oprf-core": ["@taceo/oprf-core@0.4.0", "", { "dependencies": { "@noble/curves": "^2.0.1", "@noble/hashes": "^2.0.1", "@taceo/poseidon2": "0.2.0" } }, "sha512-Mlo2pjb8O9HDGvjpcun06ZWrW7oBblQESr9EDhW1WvHLDkKDgdlKdx43EVzJMGHcFXaVT4/1MnC1De/5KTQTNg=="], - "@types/bun": ["@types/bun@1.3.1", "", { "dependencies": { "bun-types": "1.3.1" } }, "sha512-4jNMk2/K9YJtfqwoAa28c8wK+T7nvJFOjxI4h/7sORWcypRNxBpr+TPNaCfVWq70tLCJsqoFwcf0oI0JU/fvMQ=="], + "@taceo/poseidon2": ["@taceo/poseidon2@0.2.0", "", { "dependencies": { "@noble/curves": "^2.0.1" } }, "sha512-+EyFO7zaRrlsdzNEvzTLELDkrgjUgZgSlxGUSQghmmtlZ14nZklYX7D+gecyOkVe/47AGDtA+uZ9sdXiNB8rng=="], + + "@turbo/darwin-64": ["@turbo/darwin-64@2.9.8", "", { "os": "darwin", "cpu": "x64" }, "sha512-zU1P95ygDpsQ+2QHh7CVTqvYwi9UBlhKWzoIyUnP3vUoge7H9SQEzrd8dj+XcTrslAp9Db3vIBcXtMVoTEYDnA=="], + + "@turbo/darwin-arm64": ["@turbo/darwin-arm64@2.9.8", "", { "os": "darwin", "cpu": "arm64" }, "sha512-nKRFI5ZhCGUi4eXNlrojzWcT/CehMj0raot1WE4lw5qf66ZxZHbRbBqcwNEy+ZLY7RkJJRY+TaU89fuj3BcgGg=="], + + "@turbo/linux-64": ["@turbo/linux-64@2.9.8", "", { "os": "linux", "cpu": "x64" }, "sha512-Wf/kQpVDCaWM3P5d6lKvJnqjYn/ofUBGbT4h4vRFrdC4N6B/nsun03S2kQNJJMXpXg39woeS4CI367RMU3/OAg=="], + + "@turbo/linux-arm64": ["@turbo/linux-arm64@2.9.8", "", { "os": "linux", "cpu": "arm64" }, "sha512-v6S3HuKVoa9CEx16IxKj1i/+crxXx22A9O80zW1350zyUlcX0T/zLOxVf1k+ruK/7ssXnDJVg8uSYOxlYRedlA=="], + + "@turbo/windows-64": ["@turbo/windows-64@2.9.8", "", { "os": "win32", "cpu": "x64" }, "sha512-JaefWOJNBazDylAn3f+lLB34XMNu8nEBbgPRP/Ewysg81cBubGfcyyyzpQOGVuMwfaqdNAE/kitG7w3AbJn9/g=="], + + "@turbo/windows-arm64": ["@turbo/windows-arm64@2.9.8", "", { "os": "win32", "cpu": "arm64" }, "sha512-Or6ljjB4TiiwCdVKDYWew0SokQ9kep5zruL8P3nbum9WdkH5XA41rQID4Ulc215Z+R3DrB+qXSHPsJjU3/n2ng=="], + + "@tybys/wasm-util": ["@tybys/wasm-util@0.10.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg=="], + + "@types/bun": ["@types/bun@1.3.13", "", { "dependencies": { "bun-types": "1.3.13" } }, "sha512-9fqXWk5YIHGGnUau9TEi+qdlTYDAnOj+xLCmSTwXfAIqXr2x4tytJb43E9uCvt09zJURKXwAtkoH4nLQfzeTXw=="], "@types/d3-color": ["@types/d3-color@2.0.6", "", {}, "sha512-tbaFGDmJWHqnenvk3QGSvD3RVwr631BjKRD7Sc7VLRgrdX5mk5hTyoeBL6rXZaeoXzmZwIl1D2HPogEdt1rHBg=="], @@ -467,7 +506,7 @@ "@types/d3-zoom": ["@types/d3-zoom@2.0.7", "", { "dependencies": { "@types/d3-interpolate": "^2", "@types/d3-selection": "^2" } }, "sha512-JWke4E8ZyrKUQ68ESTWSK16fVb0OYnaiJ+WXJRYxKLn4aXU0o4CLYxMWBEiouUfO3TTCoyroOrGPcBG6u1aAxA=="], - "@types/debug": ["@types/debug@4.1.12", "", { "dependencies": { "@types/ms": "*" } }, "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ=="], + "@types/debug": ["@types/debug@4.1.13", "", { "dependencies": { "@types/ms": "*" } }, "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw=="], "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], @@ -485,43 +524,45 @@ "@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="], - "@types/node": ["@types/node@24.7.2", "", { "dependencies": { "undici-types": "~7.14.0" } }, "sha512-/NbVmcGTP+lj5oa4yiYxxeBjRivKQ5Ns1eSZeB99ExsEQ6rX5XYU1Zy/gGxY/ilqtD4Etx9mKyrPxZRetiahhA=="], + "@types/node": ["@types/node@24.12.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g=="], "@types/pako": ["@types/pako@2.0.4", "", {}, "sha512-VWDCbrLeVXJM9fihYodcLiIv0ku+AlOa/TQ1SvYOaBuyrSKgEcro95LJyIsJ4vSo6BXIxOKxiJAat04CmST9Fw=="], "@types/prop-types": ["@types/prop-types@15.7.15", "", {}, "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw=="], - "@types/react": ["@types/react@18.3.26", "", { "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" } }, "sha512-RFA/bURkcKzx/X9oumPG9Vp3D3JUgus/d0b67KB0t5S/raciymilkOa66olh78MUI92QLbEJevO7rvqU/kjwKA=="], + "@types/react": ["@types/react@18.3.28", "", { "dependencies": { "@types/prop-types": "*", "csstype": "^3.2.2" } }, "sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw=="], "@types/react-simple-maps": ["@types/react-simple-maps@3.0.6", "", { "dependencies": { "@types/d3-geo": "^2", "@types/d3-zoom": "^2", "@types/geojson": "*", "@types/react": "*" } }, "sha512-hR01RXt6VvsE41FxDd+Bqm1PPGdKbYjCYVtCgh38YeBPt46z3SwmWPWu2L3EdCAP6bd6VYEgztucihRw1C0Klg=="], + "@types/sinonjs__fake-timers": ["@types/sinonjs__fake-timers@15.0.1", "", {}, "sha512-Ko2tjWJq8oozHzHV+reuvS5KYIRAokHnGbDwGh/J64LntgpbuylF74ipEL24HCyRjf9FOlBiBHWBR1RlVKsI1w=="], + "@types/stack-utils": ["@types/stack-utils@2.0.3", "", {}, "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw=="], "@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="], - "@types/yargs": ["@types/yargs@17.0.33", "", { "dependencies": { "@types/yargs-parser": "*" } }, "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA=="], + "@types/yargs": ["@types/yargs@17.0.35", "", { "dependencies": { "@types/yargs-parser": "*" } }, "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg=="], "@types/yargs-parser": ["@types/yargs-parser@21.0.3", "", {}, "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ=="], - "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.46.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.46.1", "@typescript-eslint/type-utils": "8.46.1", "@typescript-eslint/utils": "8.46.1", "@typescript-eslint/visitor-keys": "8.46.1", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.46.1", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-rUsLh8PXmBjdiPY+Emjz9NX2yHvhS11v0SR6xNJkm5GM1MO9ea/1GoDKlHHZGrOJclL/cZ2i/vRUYVtjRhrHVQ=="], + "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.59.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.59.1", "@typescript-eslint/type-utils": "8.59.1", "@typescript-eslint/utils": "8.59.1", "@typescript-eslint/visitor-keys": "8.59.1", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.59.1", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-BOziFIfE+6osHO9FoJG4zjoHUcvI7fTNBSpdAwrNH0/TLvzjsk2oo8XSSOT2HhqUyhZPfHv4UOffoJ9oEEQ7Ag=="], - "@typescript-eslint/parser": ["@typescript-eslint/parser@8.46.1", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.46.1", "@typescript-eslint/types": "8.46.1", "@typescript-eslint/typescript-estree": "8.46.1", "@typescript-eslint/visitor-keys": "8.46.1", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-6JSSaBZmsKvEkbRUkf7Zj7dru/8ZCrJxAqArcLaVMee5907JdtEbKGsZ7zNiIm/UAkpGUkaSMZEXShnN2D1HZA=="], + "@typescript-eslint/parser": ["@typescript-eslint/parser@8.59.1", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.59.1", "@typescript-eslint/types": "8.59.1", "@typescript-eslint/typescript-estree": "8.59.1", "@typescript-eslint/visitor-keys": "8.59.1", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-HDQH9O/47Dxi1ceDhBXdaldtf/WV9yRYMjbjCuNk3qnaTD564qwv61Y7+gTxwxRKzSrgO5uhtw584igXVuuZkA=="], - "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.46.1", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.46.1", "@typescript-eslint/types": "^8.46.1", "debug": "^4.3.4" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-FOIaFVMHzRskXr5J4Jp8lFVV0gz5ngv3RHmn+E4HYxSJ3DgDzU7fVI1/M7Ijh1zf6S7HIoaIOtln1H5y8V+9Zg=="], + "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.59.1", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.59.1", "@typescript-eslint/types": "^8.59.1", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-+MuHQlHiEr00Of/IQbE/MmEoi44znZHbR/Pz7Opq4HryUOlRi+/44dro9Ycy8Fyo+/024IWtw8m4JUMCGTYxDg=="], - "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.46.1", "", { "dependencies": { "@typescript-eslint/types": "8.46.1", "@typescript-eslint/visitor-keys": "8.46.1" } }, "sha512-weL9Gg3/5F0pVQKiF8eOXFZp8emqWzZsOJuWRUNtHT+UNV2xSJegmpCNQHy37aEQIbToTq7RHKhWvOsmbM680A=="], + "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.59.1", "", { "dependencies": { "@typescript-eslint/types": "8.59.1", "@typescript-eslint/visitor-keys": "8.59.1" } }, "sha512-LwuHQI4pDOYVKvmH2dkaJo6YZCSgouVgnS/z7yBPKBMvgtBvyLqiLy9Z6b7+m/TRcX1NFYUqZetI5Y+aT4GEfg=="], - "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.46.1", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-X88+J/CwFvlJB+mK09VFqx5FE4H5cXD+H/Bdza2aEWkSb8hnWIQorNcscRl4IEo1Cz9VI/+/r/jnGWkbWPx54g=="], + "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.59.1", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-/0nEyPbX7gRsk0Uwfe4ALwwgxuA66d/l2mhRDNlAvaj4U3juhUtJNq0DsY8M2AYwwb9rEq2hrC3IcIcEt++iJA=="], - "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.46.1", "", { "dependencies": { "@typescript-eslint/types": "8.46.1", "@typescript-eslint/typescript-estree": "8.46.1", "@typescript-eslint/utils": "8.46.1", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-+BlmiHIiqufBxkVnOtFwjah/vrkF4MtKKvpXrKSPLCkCtAp8H01/VV43sfqA98Od7nJpDcFnkwgyfQbOG0AMvw=="], + "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.59.1", "", { "dependencies": { "@typescript-eslint/types": "8.59.1", "@typescript-eslint/typescript-estree": "8.59.1", "@typescript-eslint/utils": "8.59.1", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-klWPBR2ciQHS3f++ug/mVnWKPjBUo7icEL3FAO1lhAR1Z1i5NQYZ1EannMSRYcq5qCv5wNALlXr6fksRHyYl7w=="], - "@typescript-eslint/types": ["@typescript-eslint/types@8.46.1", "", {}, "sha512-C+soprGBHwWBdkDpbaRC4paGBrkIXxVlNohadL5o0kfhsXqOC6GYH2S/Obmig+I0HTDl8wMaRySwrfrXVP8/pQ=="], + "@typescript-eslint/types": ["@typescript-eslint/types@8.59.1", "", {}, "sha512-ZDCjgccSdYPw5Bxh+my4Z0lJU96ZDN7jbBzvmEn0FZx3RtU1C7VWl6NbDx94bwY3V5YsgwRzJPOgeY2Q/nLG8A=="], - "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.46.1", "", { "dependencies": { "@typescript-eslint/project-service": "8.46.1", "@typescript-eslint/tsconfig-utils": "8.46.1", "@typescript-eslint/types": "8.46.1", "@typescript-eslint/visitor-keys": "8.46.1", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-uIifjT4s8cQKFQ8ZBXXyoUODtRoAd7F7+G8MKmtzj17+1UbdzFl52AzRyZRyKqPHhgzvXunnSckVu36flGy8cg=="], + "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.59.1", "", { "dependencies": { "@typescript-eslint/project-service": "8.59.1", "@typescript-eslint/tsconfig-utils": "8.59.1", "@typescript-eslint/types": "8.59.1", "@typescript-eslint/visitor-keys": "8.59.1", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-OUd+vJS05sSkOip+BkZ/2NS8RMxrAAJemsC6vU3kmfLyeaJT0TftHkV9mcx2107MmsBVXXexhVu4F0TZXyMl4g=="], - "@typescript-eslint/utils": ["@typescript-eslint/utils@8.46.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", "@typescript-eslint/scope-manager": "8.46.1", "@typescript-eslint/types": "8.46.1", "@typescript-eslint/typescript-estree": "8.46.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-vkYUy6LdZS7q1v/Gxb2Zs7zziuXN0wxqsetJdeZdRe/f5dwJFglmuvZBfTUivCtjH725C1jWCDfpadadD95EDQ=="], + "@typescript-eslint/utils": ["@typescript-eslint/utils@8.59.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.59.1", "@typescript-eslint/types": "8.59.1", "@typescript-eslint/typescript-estree": "8.59.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-3pIeoXhCeYH9FSCBI8P3iNwJlGuzPlYKkTlen2O9T1DSeeg8UG8jstq6BLk+Mda0qup7mgk4z4XL4OzRaxZ8LA=="], - "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.46.1", "", { "dependencies": { "@typescript-eslint/types": "8.46.1", "eslint-visitor-keys": "^4.2.1" } }, "sha512-ptkmIf2iDkNUjdeu2bQqhFPV1m6qTnFFjg7PPDjxKWaMaP0Z6I9l30Jr3g5QqbZGdw8YdYvLp+XnqnWWZOg/NA=="], + "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.59.1", "", { "dependencies": { "@typescript-eslint/types": "8.59.1", "eslint-visitor-keys": "^5.0.0" } }, "sha512-LdDNl6C5iJExcM0Yh0PwAIBb9PrSiCsWamF/JyEZawm3kFDnRoaq3LGE4bpyRao/fWeGKKyw7icx0YxrLFC5Cg=="], "@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="], @@ -573,19 +614,21 @@ "@zkpassport/utils": ["@zkpassport/utils@workspace:packages/zkpassport-utils"], - "abitype": ["abitype@1.1.0", "", { "peerDependencies": { "typescript": ">=5.0.4", "zod": "^3.22.0 || ^4.0.0" }, "optionalPeers": ["typescript", "zod"] }, "sha512-6Vh4HcRxNMLA0puzPjM5GBgT4aAcFGKZzSgAXvuZ27shJP6NEpielTuqbBmZILR5/xd0PizkBGy5hReKz9jl5A=="], + "abitype": ["abitype@1.2.3", "", { "peerDependencies": { "typescript": ">=5.0.4", "zod": "^3.22.0 || ^4.0.0" }, "optionalPeers": ["typescript", "zod"] }, "sha512-Ofer5QUnuUdTFsBRwARMoWKOH1ND5ehwYhJ3OJ/BQO+StkwQjHw0XyVh4vDttzHB7QOFhPHa/o413PJ82gU/Tg=="], - "acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], + "acorn": ["acorn@8.16.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="], "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], "aes-js": ["aes-js@4.0.0-beta.5", "", {}, "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q=="], - "ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], + "ajv": ["ajv@6.15.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw=="], - "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + "ansi-escapes": ["ansi-escapes@7.3.0", "", { "dependencies": { "environment": "^1.0.0" } }, "sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg=="], - "ansi-styles": ["ansi-styles@5.2.0", "", {}, "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="], + "ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], + + "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], "any-promise": ["any-promise@1.3.0", "", {}, "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="], @@ -603,8 +646,6 @@ "array-includes": ["array-includes@3.1.9", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-abstract": "^1.24.0", "es-object-atoms": "^1.1.1", "get-intrinsic": "^1.3.0", "is-string": "^1.1.1", "math-intrinsics": "^1.1.0" } }, "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ=="], - "array-union": ["array-union@2.1.0", "", {}, "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw=="], - "array.prototype.findlast": ["array.prototype.findlast@1.2.5", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "es-shim-unscopables": "^1.0.2" } }, "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ=="], "array.prototype.findlastindex": ["array.prototype.findlastindex@1.2.6", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-abstract": "^1.23.9", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "es-shim-unscopables": "^1.1.0" } }, "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ=="], @@ -617,17 +658,15 @@ "arraybuffer.prototype.slice": ["arraybuffer.prototype.slice@1.0.4", "", { "dependencies": { "array-buffer-byte-length": "^1.0.1", "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "is-array-buffer": "^3.0.4" } }, "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ=="], - "asn1js": ["asn1js@3.0.6", "", { "dependencies": { "pvtsutils": "^1.3.6", "pvutils": "^1.1.3", "tslib": "^2.8.1" } }, "sha512-UOCGPYbl0tv8+006qks/dTgV9ajs97X2p0FAbyS2iyCRrmLSRolDaHdp+v/CLgnzHc3fVB+CwYiUmei7ndFcgA=="], + "asn1js": ["asn1js@3.0.10", "", { "dependencies": { "pvtsutils": "^1.3.6", "pvutils": "^1.1.5", "tslib": "^2.8.1" } }, "sha512-S2s3aOytiKdFRdulw2qPE51MzjzVOisppcVv7jVFR+Kw0kxwvFrDcYA0h7Ndqbmj0HkMIXYWaoj7fli8kgx1eg=="], "ast-types-flow": ["ast-types-flow@0.0.8", "", {}, "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ=="], "async-function": ["async-function@1.0.0", "", {}, "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA=="], - "atomic-sleep": ["atomic-sleep@1.0.0", "", {}, "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ=="], - "available-typed-arrays": ["available-typed-arrays@1.0.7", "", { "dependencies": { "possible-typed-array-names": "^1.0.0" } }, "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ=="], - "axe-core": ["axe-core@4.11.0", "", {}, "sha512-ilYanEU8vxxBexpJd8cWM4ElSQq4QctCLKih0TSfjIfCQTeyH/6zVrmIJfLPrKTKJRbiG+cfnZbQIjAlJmF1jQ=="], + "axe-core": ["axe-core@4.11.4", "", {}, "sha512-KunSNx+TVpkAw/6ULfhnx+HWRecjqZGTOyquAoWHYLRSdK1tB5Ihce1ZW+UY3fj33bYAFWPu7W/GRSmmrCGuxA=="], "axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="], @@ -637,17 +676,17 @@ "binary-extensions": ["binary-extensions@2.3.0", "", {}, "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="], - "bn.js": ["bn.js@5.2.2", "", {}, "sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw=="], + "bn.js": ["bn.js@5.2.3", "", {}, "sha512-EAcmnPkxpntVL+DS7bO1zhcZNvCkxqtkd0ZY53h06GNQ3DEkkGZ/gKgmDv6DdZQGj9BgfSPKtJJ7Dp1GPP8f7w=="], "boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="], - "brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], + "brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="], "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], "buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="], - "bun-types": ["bun-types@1.3.1", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-NMrcy7smratanWJ2mMXdpatalovtxVggkj11bScuWuiOoXTiKIu2eVS1/7qbyI/4yHedtsn175n4Sm4JcdHLXw=="], + "bun-types": ["bun-types@1.3.13", "", { "dependencies": { "@types/node": "*" } }, "sha512-QXKeHLlOLqQX9LgYaHJfzdBaV21T63HhFJnvuRCcjZiaUDpbs5ED1MgxbMra71CsryN/1dAoXuJJJwIv/2drVA=="], "bundle-require": ["bundle-require@5.1.0", "", { "dependencies": { "load-tsconfig": "^0.2.3" }, "peerDependencies": { "esbuild": ">=0.18" } }, "sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA=="], @@ -655,7 +694,7 @@ "cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="], - "call-bind": ["call-bind@1.0.8", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.2" } }, "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww=="], + "call-bind": ["call-bind@1.0.9", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "get-intrinsic": "^1.3.0", "set-function-length": "^1.2.2" } }, "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ=="], "call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="], @@ -665,18 +704,28 @@ "camelcase-css": ["camelcase-css@2.0.1", "", {}, "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA=="], - "caniuse-lite": ["caniuse-lite@1.0.30001750", "", {}, "sha512-cuom0g5sdX6rw00qOoLNSFCJ9/mYIsuSOA+yzpDw8eopiFqcVwQvZHqov0vmEighRxX++cfC0Vg1G+1Iy/mSpQ=="], + "caniuse-lite": ["caniuse-lite@1.0.30001791", "", {}, "sha512-yk0l/YSrOnFZk3UROpDLQD9+kC1l4meK/wed583AXrzoarMGJcbRi2Q4RaUYbKxYAsZ8sWmaSa/DsLmdBeI1vQ=="], "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - "chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="], + "char-regex": ["char-regex@1.0.2", "", {}, "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw=="], + + "chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="], + + "ci-info": ["ci-info@4.4.0", "", {}, "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg=="], - "ci-info": ["ci-info@4.3.1", "", {}, "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA=="], + "cjs-module-lexer": ["cjs-module-lexer@1.4.3", "", {}, "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q=="], "class-variance-authority": ["class-variance-authority@0.7.1", "", { "dependencies": { "clsx": "^2.1.1" } }, "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg=="], + "cli-highlight": ["cli-highlight@2.1.11", "", { "dependencies": { "chalk": "^4.0.0", "highlight.js": "^10.7.1", "mz": "^2.4.0", "parse5": "^5.1.1", "parse5-htmlparser2-tree-adapter": "^6.0.0", "yargs": "^16.0.0" }, "bin": { "highlight": "bin/highlight" } }, "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg=="], + + "cli-table3": ["cli-table3@0.6.5", "", { "dependencies": { "string-width": "^4.2.0" }, "optionalDependencies": { "@colors/colors": "1.5.0" } }, "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ=="], + "client-only": ["client-only@0.0.1", "", {}, "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="], + "cliui": ["cliui@7.0.4", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" } }, "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ=="], + "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="], "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], @@ -685,7 +734,7 @@ "comlink": ["comlink@4.4.2", "", {}, "sha512-OxGdvBmJuNKSCMO4NTl1L47VRp6xn2wG4F/2hYzB6tiCb709otOxtEYCSvK80PtjODfXXZu8ds+Nw5kVCjqd2g=="], - "commander": ["commander@9.5.0", "", {}, "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ=="], + "commander": ["commander@10.0.1", "", {}, "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug=="], "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], @@ -705,7 +754,7 @@ "csso": ["csso@5.0.5", "", { "dependencies": { "css-tree": "~2.2.0" } }, "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ=="], - "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="], + "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="], "d3-array": ["d3-array@3.2.4", "", { "dependencies": { "internmap": "1 - 2" } }, "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg=="], @@ -755,8 +804,6 @@ "didyoumean": ["didyoumean@1.2.2", "", {}, "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw=="], - "dir-glob": ["dir-glob@3.0.1", "", { "dependencies": { "path-type": "^4.0.0" } }, "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA=="], - "dlv": ["dlv@1.1.3", "", {}, "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="], "doctrine": ["doctrine@3.0.0", "", { "dependencies": { "esutils": "^2.0.2" } }, "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w=="], @@ -775,15 +822,19 @@ "emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], + "emojilib": ["emojilib@2.4.0", "", {}, "sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw=="], + "entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], - "es-abstract": ["es-abstract@1.24.0", "", { "dependencies": { "array-buffer-byte-length": "^1.0.2", "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "data-view-buffer": "^1.0.2", "data-view-byte-length": "^1.0.2", "data-view-byte-offset": "^1.0.1", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "es-set-tostringtag": "^2.1.0", "es-to-primitive": "^1.3.0", "function.prototype.name": "^1.1.8", "get-intrinsic": "^1.3.0", "get-proto": "^1.0.1", "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "internal-slot": "^1.1.0", "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", "is-data-view": "^1.0.2", "is-negative-zero": "^2.0.3", "is-regex": "^1.2.1", "is-set": "^2.0.3", "is-shared-array-buffer": "^1.0.4", "is-string": "^1.1.1", "is-typed-array": "^1.1.15", "is-weakref": "^1.1.1", "math-intrinsics": "^1.1.0", "object-inspect": "^1.13.4", "object-keys": "^1.1.1", "object.assign": "^4.1.7", "own-keys": "^1.0.1", "regexp.prototype.flags": "^1.5.4", "safe-array-concat": "^1.1.3", "safe-push-apply": "^1.0.0", "safe-regex-test": "^1.1.0", "set-proto": "^1.0.0", "stop-iteration-iterator": "^1.1.0", "string.prototype.trim": "^1.2.10", "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", "typed-array-buffer": "^1.0.3", "typed-array-byte-length": "^1.0.3", "typed-array-byte-offset": "^1.0.4", "typed-array-length": "^1.0.7", "unbox-primitive": "^1.1.0", "which-typed-array": "^1.1.19" } }, "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg=="], + "environment": ["environment@1.1.0", "", {}, "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q=="], + + "es-abstract": ["es-abstract@1.24.2", "", { "dependencies": { "array-buffer-byte-length": "^1.0.2", "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "data-view-buffer": "^1.0.2", "data-view-byte-length": "^1.0.2", "data-view-byte-offset": "^1.0.1", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "es-set-tostringtag": "^2.1.0", "es-to-primitive": "^1.3.0", "function.prototype.name": "^1.1.8", "get-intrinsic": "^1.3.0", "get-proto": "^1.0.1", "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "internal-slot": "^1.1.0", "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", "is-data-view": "^1.0.2", "is-negative-zero": "^2.0.3", "is-regex": "^1.2.1", "is-set": "^2.0.3", "is-shared-array-buffer": "^1.0.4", "is-string": "^1.1.1", "is-typed-array": "^1.1.15", "is-weakref": "^1.1.1", "math-intrinsics": "^1.1.0", "object-inspect": "^1.13.4", "object-keys": "^1.1.1", "object.assign": "^4.1.7", "own-keys": "^1.0.1", "regexp.prototype.flags": "^1.5.4", "safe-array-concat": "^1.1.3", "safe-push-apply": "^1.0.0", "safe-regex-test": "^1.1.0", "set-proto": "^1.0.0", "stop-iteration-iterator": "^1.1.0", "string.prototype.trim": "^1.2.10", "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", "typed-array-buffer": "^1.0.3", "typed-array-byte-length": "^1.0.3", "typed-array-byte-offset": "^1.0.4", "typed-array-length": "^1.0.7", "unbox-primitive": "^1.1.0", "which-typed-array": "^1.1.19" } }, "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg=="], "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="], "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="], - "es-iterator-helpers": ["es-iterator-helpers@1.2.1", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-abstract": "^1.23.6", "es-errors": "^1.3.0", "es-set-tostringtag": "^2.0.3", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.6", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "internal-slot": "^1.1.0", "iterator.prototype": "^1.1.4", "safe-array-concat": "^1.1.3" } }, "sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w=="], + "es-iterator-helpers": ["es-iterator-helpers@1.3.2", "", { "dependencies": { "call-bind": "^1.0.9", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-abstract": "^1.24.2", "es-errors": "^1.3.0", "es-set-tostringtag": "^2.1.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.3.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "internal-slot": "^1.1.0", "iterator.prototype": "^1.1.5", "math-intrinsics": "^1.1.0" } }, "sha512-HVLACW1TppGYjJ8H6/jqH/pqOtKRw6wMlrB23xfExmFWxFquAIWCmwoLsOyN96K4a5KbmOf5At9ZUO3GZbetAw=="], "es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="], @@ -793,7 +844,9 @@ "es-to-primitive": ["es-to-primitive@1.3.0", "", { "dependencies": { "is-callable": "^1.2.7", "is-date-object": "^1.0.5", "is-symbol": "^1.0.4" } }, "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g=="], - "esbuild": ["esbuild@0.25.10", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.10", "@esbuild/android-arm": "0.25.10", "@esbuild/android-arm64": "0.25.10", "@esbuild/android-x64": "0.25.10", "@esbuild/darwin-arm64": "0.25.10", "@esbuild/darwin-x64": "0.25.10", "@esbuild/freebsd-arm64": "0.25.10", "@esbuild/freebsd-x64": "0.25.10", "@esbuild/linux-arm": "0.25.10", "@esbuild/linux-arm64": "0.25.10", "@esbuild/linux-ia32": "0.25.10", "@esbuild/linux-loong64": "0.25.10", "@esbuild/linux-mips64el": "0.25.10", "@esbuild/linux-ppc64": "0.25.10", "@esbuild/linux-riscv64": "0.25.10", "@esbuild/linux-s390x": "0.25.10", "@esbuild/linux-x64": "0.25.10", "@esbuild/netbsd-arm64": "0.25.10", "@esbuild/netbsd-x64": "0.25.10", "@esbuild/openbsd-arm64": "0.25.10", "@esbuild/openbsd-x64": "0.25.10", "@esbuild/openharmony-arm64": "0.25.10", "@esbuild/sunos-x64": "0.25.10", "@esbuild/win32-arm64": "0.25.10", "@esbuild/win32-ia32": "0.25.10", "@esbuild/win32-x64": "0.25.10" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ=="], + "esbuild": ["esbuild@0.27.7", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.7", "@esbuild/android-arm": "0.27.7", "@esbuild/android-arm64": "0.27.7", "@esbuild/android-x64": "0.27.7", "@esbuild/darwin-arm64": "0.27.7", "@esbuild/darwin-x64": "0.27.7", "@esbuild/freebsd-arm64": "0.27.7", "@esbuild/freebsd-x64": "0.27.7", "@esbuild/linux-arm": "0.27.7", "@esbuild/linux-arm64": "0.27.7", "@esbuild/linux-ia32": "0.27.7", "@esbuild/linux-loong64": "0.27.7", "@esbuild/linux-mips64el": "0.27.7", "@esbuild/linux-ppc64": "0.27.7", "@esbuild/linux-riscv64": "0.27.7", "@esbuild/linux-s390x": "0.27.7", "@esbuild/linux-x64": "0.27.7", "@esbuild/netbsd-arm64": "0.27.7", "@esbuild/netbsd-x64": "0.27.7", "@esbuild/openbsd-arm64": "0.27.7", "@esbuild/openbsd-x64": "0.27.7", "@esbuild/openharmony-arm64": "0.27.7", "@esbuild/sunos-x64": "0.27.7", "@esbuild/win32-arm64": "0.27.7", "@esbuild/win32-ia32": "0.27.7", "@esbuild/win32-x64": "0.27.7" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w=="], + + "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], @@ -803,7 +856,7 @@ "eslint-config-prettier": ["eslint-config-prettier@10.1.8", "", { "peerDependencies": { "eslint": ">=7.0.0" }, "bin": { "eslint-config-prettier": "bin/cli.js" } }, "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w=="], - "eslint-import-resolver-node": ["eslint-import-resolver-node@0.3.9", "", { "dependencies": { "debug": "^3.2.7", "is-core-module": "^2.13.0", "resolve": "^1.22.4" } }, "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g=="], + "eslint-import-resolver-node": ["eslint-import-resolver-node@0.3.10", "", { "dependencies": { "debug": "^3.2.7", "is-core-module": "^2.16.1", "resolve": "^2.0.0-next.6" } }, "sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ=="], "eslint-import-resolver-typescript": ["eslint-import-resolver-typescript@3.10.1", "", { "dependencies": { "@nolyfill/is-core-module": "1.0.39", "debug": "^4.4.0", "get-tsconfig": "^4.10.0", "is-bun-module": "^2.0.0", "stable-hash": "^0.0.5", "tinyglobby": "^0.2.13", "unrs-resolver": "^1.6.2" }, "peerDependencies": { "eslint": "*", "eslint-plugin-import": "*", "eslint-plugin-import-x": "*" }, "optionalPeers": ["eslint-plugin-import", "eslint-plugin-import-x"] }, "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ=="], @@ -813,7 +866,7 @@ "eslint-plugin-jsx-a11y": ["eslint-plugin-jsx-a11y@6.10.2", "", { "dependencies": { "aria-query": "^5.3.2", "array-includes": "^3.1.8", "array.prototype.flatmap": "^1.3.2", "ast-types-flow": "^0.0.8", "axe-core": "^4.10.0", "axobject-query": "^4.1.0", "damerau-levenshtein": "^1.0.8", "emoji-regex": "^9.2.2", "hasown": "^2.0.2", "jsx-ast-utils": "^3.3.5", "language-tags": "^1.0.9", "minimatch": "^3.1.2", "object.fromentries": "^2.0.8", "safe-regex-test": "^1.0.3", "string.prototype.includes": "^2.0.1" }, "peerDependencies": { "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" } }, "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q=="], - "eslint-plugin-prettier": ["eslint-plugin-prettier@5.5.4", "", { "dependencies": { "prettier-linter-helpers": "^1.0.0", "synckit": "^0.11.7" }, "peerDependencies": { "@types/eslint": ">=8.0.0", "eslint": ">=8.0.0", "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", "prettier": ">=3.0.0" }, "optionalPeers": ["@types/eslint", "eslint-config-prettier"] }, "sha512-swNtI95SToIz05YINMA6Ox5R057IMAmWZ26GqPxusAp1TZzj+IdY9tXNWWD3vkF/wEqydCONcwjTFpxybBqZsg=="], + "eslint-plugin-prettier": ["eslint-plugin-prettier@5.5.5", "", { "dependencies": { "prettier-linter-helpers": "^1.0.1", "synckit": "^0.11.12" }, "peerDependencies": { "@types/eslint": ">=8.0.0", "eslint": ">=8.0.0", "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", "prettier": ">=3.0.0" }, "optionalPeers": ["@types/eslint", "eslint-config-prettier"] }, "sha512-hscXkbqUZ2sPithAuLm5MXL+Wph+U7wHngPBv9OMWwlP8iaflyxpjTYZkmdgB4/vPIhemRlBEoLrH7UC1n7aUw=="], "eslint-plugin-react": ["eslint-plugin-react@7.37.5", "", { "dependencies": { "array-includes": "^3.1.8", "array.prototype.findlast": "^1.2.5", "array.prototype.flatmap": "^1.3.3", "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", "es-iterator-helpers": "^1.2.1", "estraverse": "^5.3.0", "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", "object.entries": "^1.1.9", "object.fromentries": "^2.0.8", "object.values": "^1.2.1", "prop-types": "^15.8.1", "resolve": "^2.0.0-next.5", "semver": "^6.3.1", "string.prototype.matchall": "^4.0.12", "string.prototype.repeat": "^1.0.0" }, "peerDependencies": { "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA=="], @@ -825,7 +878,7 @@ "espree": ["espree@9.6.1", "", { "dependencies": { "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.4.1" } }, "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ=="], - "esquery": ["esquery@1.6.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg=="], + "esquery": ["esquery@1.7.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g=="], "esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="], @@ -837,7 +890,7 @@ "eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="], - "expect": ["expect@30.2.0", "", { "dependencies": { "@jest/expect-utils": "30.2.0", "@jest/get-type": "30.1.0", "jest-matcher-utils": "30.2.0", "jest-message-util": "30.2.0", "jest-mock": "30.2.0", "jest-util": "30.2.0" } }, "sha512-u/feCi0GPsI+988gU2FLcsHyAHTU0MX1Wg68NhAnN7z/+C5wqG+CY8J53N9ioe8RXgaoz0nBR/TYMf3AycUuPw=="], + "expect": ["expect@30.3.0", "", { "dependencies": { "@jest/expect-utils": "30.3.0", "@jest/get-type": "30.1.0", "jest-matcher-utils": "30.3.0", "jest-message-util": "30.3.0", "jest-mock": "30.3.0", "jest-util": "30.3.0" } }, "sha512-1zQrciTiQfRdo7qJM1uG4navm8DayFa2TgCSRlzUyNkhcJ6XUZF3hjnpkyr3VhAqPH7i/9GkG7Tv5abz6fqz0Q=="], "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], @@ -849,10 +902,12 @@ "fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="], - "fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="], + "fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="], "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], + "fflate": ["fflate@0.8.2", "", {}, "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A=="], + "file-entry-cache": ["file-entry-cache@6.0.1", "", { "dependencies": { "flat-cache": "^3.0.4" } }, "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg=="], "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], @@ -863,7 +918,7 @@ "flat-cache": ["flat-cache@3.2.0", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.3", "rimraf": "^3.0.2" } }, "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw=="], - "flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="], + "flatted": ["flatted@3.4.2", "", {}, "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA=="], "for-each": ["for-each@0.3.5", "", { "dependencies": { "is-callable": "^1.2.7" } }, "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg=="], @@ -883,6 +938,8 @@ "generator-function": ["generator-function@2.0.1", "", {}, "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g=="], + "get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="], + "get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="], "get-nonce": ["get-nonce@1.0.1", "", {}, "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q=="], @@ -891,9 +948,9 @@ "get-symbol-description": ["get-symbol-description@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6" } }, "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg=="], - "get-tsconfig": ["get-tsconfig@4.12.0", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-LScr2aNr2FbjAjZh2C6X6BxRx1/x+aTDExct/xyq2XKbYOiG5c0aK7pMsSuyc0brz3ibr/lbQiHD9jzt4lccJw=="], + "get-tsconfig": ["get-tsconfig@4.14.0", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA=="], - "glob": ["glob@11.0.3", "", { "dependencies": { "foreground-child": "^3.3.1", "jackspeak": "^4.1.1", "minimatch": "^10.0.3", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^2.0.0" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA=="], + "glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="], "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], @@ -901,8 +958,6 @@ "globalthis": ["globalthis@1.0.4", "", { "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" } }, "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ=="], - "globby": ["globby@11.1.0", "", { "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", "fast-glob": "^3.2.9", "ignore": "^5.2.0", "merge2": "^1.4.1", "slash": "^3.0.0" } }, "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g=="], - "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], @@ -921,7 +976,9 @@ "has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="], - "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="], + "hasown": ["hasown@2.0.3", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg=="], + + "highlight.js": ["highlight.js@10.7.3", "", {}, "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A=="], "i18n-iso-countries": ["i18n-iso-countries@7.14.0", "", { "dependencies": { "diacritics": "1.3.0" } }, "sha512-nXHJZYtNrfsi1UQbyRqm3Gou431elgLjKl//CYlnBGt5aTWdRPH1PiS2T/p/n8Q8LnqYqzQJik3Q7mkwvLokeg=="], @@ -1009,19 +1066,19 @@ "iterator.prototype": ["iterator.prototype@1.1.5", "", { "dependencies": { "define-data-property": "^1.1.4", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.6", "get-proto": "^1.0.0", "has-symbols": "^1.1.0", "set-function-name": "^2.0.2" } }, "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g=="], - "jackspeak": ["jackspeak@4.1.1", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" } }, "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ=="], + "jackspeak": ["jackspeak@2.3.6", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ=="], - "jest-diff": ["jest-diff@30.2.0", "", { "dependencies": { "@jest/diff-sequences": "30.0.1", "@jest/get-type": "30.1.0", "chalk": "^4.1.2", "pretty-format": "30.2.0" } }, "sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A=="], + "jest-diff": ["jest-diff@30.3.0", "", { "dependencies": { "@jest/diff-sequences": "30.3.0", "@jest/get-type": "30.1.0", "chalk": "^4.1.2", "pretty-format": "30.3.0" } }, "sha512-n3q4PDQjS4LrKxfWB3Z5KNk1XjXtZTBwQp71OP0Jo03Z6V60x++K5L8k6ZrW8MY8pOFylZvHM0zsjS1RqlHJZQ=="], - "jest-matcher-utils": ["jest-matcher-utils@30.2.0", "", { "dependencies": { "@jest/get-type": "30.1.0", "chalk": "^4.1.2", "jest-diff": "30.2.0", "pretty-format": "30.2.0" } }, "sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg=="], + "jest-matcher-utils": ["jest-matcher-utils@30.3.0", "", { "dependencies": { "@jest/get-type": "30.1.0", "chalk": "^4.1.2", "jest-diff": "30.3.0", "pretty-format": "30.3.0" } }, "sha512-HEtc9uFQgaUHkC7nLSlQL3Tph4Pjxt/yiPvkIrrDCt9jhoLIgxaubo1G+CFOnmHYMxHwwdaSN7mkIFs6ZK8OhA=="], - "jest-message-util": ["jest-message-util@30.2.0", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@jest/types": "30.2.0", "@types/stack-utils": "^2.0.3", "chalk": "^4.1.2", "graceful-fs": "^4.2.11", "micromatch": "^4.0.8", "pretty-format": "30.2.0", "slash": "^3.0.0", "stack-utils": "^2.0.6" } }, "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw=="], + "jest-message-util": ["jest-message-util@30.3.0", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@jest/types": "30.3.0", "@types/stack-utils": "^2.0.3", "chalk": "^4.1.2", "graceful-fs": "^4.2.11", "picomatch": "^4.0.3", "pretty-format": "30.3.0", "slash": "^3.0.0", "stack-utils": "^2.0.6" } }, "sha512-Z/j4Bo+4ySJ+JPJN3b2Qbl9hDq3VrXmnjjGEWD/x0BCXeOXPTV1iZYYzl2X8c1MaCOL+ewMyNBcm88sboE6YWw=="], - "jest-mock": ["jest-mock@30.2.0", "", { "dependencies": { "@jest/types": "30.2.0", "@types/node": "*", "jest-util": "30.2.0" } }, "sha512-JNNNl2rj4b5ICpmAcq+WbLH83XswjPbjH4T7yvGzfAGCPh1rw+xVNbtk+FnRslvt9lkCcdn9i1oAoKUuFsOxRw=="], + "jest-mock": ["jest-mock@30.3.0", "", { "dependencies": { "@jest/types": "30.3.0", "@types/node": "*", "jest-util": "30.3.0" } }, "sha512-OTzICK8CpE+t4ndhKrwlIdbM6Pn8j00lvmSmq5ejiO+KxukbLjgOflKWMn3KE34EZdQm5RqTuKj+5RIEniYhog=="], "jest-regex-util": ["jest-regex-util@30.0.1", "", {}, "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA=="], - "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=="], + "jest-util": ["jest-util@30.3.0", "", { "dependencies": { "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", "picomatch": "^4.0.3" } }, "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg=="], "jiti": ["jiti@1.21.7", "", { "bin": { "jiti": "bin/jiti.js" } }, "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A=="], @@ -1029,7 +1086,7 @@ "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], - "js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], + "js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="], "json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="], @@ -1063,15 +1120,17 @@ "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], - "lodash.sortby": ["lodash.sortby@4.7.0", "", {}, "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA=="], - "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=="], - "lru-cache": ["lru-cache@11.2.2", "", {}, "sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg=="], + "lru-cache": ["lru-cache@11.3.5", "", {}, "sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw=="], "lucide-react": ["lucide-react@0.468.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc" } }, "sha512-6koYRhnM2N0GGZIdXzSeiNwguv1gt/FAjZOiPl76roBi3xKEXa4WmfpxgQwTTL4KipXjefrnf3oV4IsYhi4JFA=="], - "magic-string": ["magic-string@0.30.19", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw=="], + "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], + + "marked": ["marked@9.1.6", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-jcByLnIFkd5gSXZmjNvS1TlmRhCXZjIzHYlaGkPlLIekG55JDR2Z4va9tZwCiP+/RDERiNhMOFu01xd6O5ct1Q=="], + + "marked-terminal": ["marked-terminal@7.3.0", "", { "dependencies": { "ansi-escapes": "^7.0.0", "ansi-regex": "^6.1.0", "chalk": "^5.4.1", "cli-highlight": "^2.1.11", "cli-table3": "^0.6.5", "node-emoji": "^2.2.0", "supports-hyperlinks": "^3.1.0" }, "peerDependencies": { "marked": ">=1 <16" } }, "sha512-t4rBvPsHc57uE/2nJOLmMbZCQ4tgAccAED3ngXQqW6g+TxA488JzJ+FK3lQkzBQOI1mRV/r/Kq+1ZlJ4D0owQw=="], "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="], @@ -1081,29 +1140,29 @@ "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], - "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], + "minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="], "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="], - "minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="], + "minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="], - "mlly": ["mlly@1.8.0", "", { "dependencies": { "acorn": "^8.15.0", "pathe": "^2.0.3", "pkg-types": "^1.3.1", "ufo": "^1.6.1" } }, "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g=="], + "mlly": ["mlly@1.8.2", "", { "dependencies": { "acorn": "^8.16.0", "pathe": "^2.0.3", "pkg-types": "^1.3.1", "ufo": "^1.6.3" } }, "sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA=="], "motion-dom": ["motion-dom@11.18.1", "", { "dependencies": { "motion-utils": "^11.18.1" } }, "sha512-g76KvA001z+atjfxczdRtw/RXOM3OMSdd1f4DL77qCTF/+avrRJiawSG4yDibEQ215sr9kpinSlX2pCTJ9zbhw=="], "motion-utils": ["motion-utils@11.18.1", "", {}, "sha512-49Kt+HKjtbJKLtgO/LKj9Ld+6vw9BjH5d9sc40R/kVyH8GLAXgT42M2NnuPcJNuA3s9ZfZBUcwIgpmZWGEE+hA=="], + "mri": ["mri@1.2.0", "", {}, "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="], + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], - "msgpackr": ["msgpackr@1.11.5", "", { "optionalDependencies": { "msgpackr-extract": "^3.0.2" } }, "sha512-UjkUHN0yqp9RWKy0Lplhh+wlpdt9oQBYgULZOiFhV3VclSF1JnSQWZ5r9gORQlNYaUKQoR8itv7g7z1xDDuACA=="], + "msgpackr": ["msgpackr@1.11.12", "", { "optionalDependencies": { "msgpackr-extract": "^3.0.2" } }, "sha512-RBdJ1Un7yGlXWajrkxcSa93nvQ0w4zBf60c0yYv7YtBelP8H2FA7XsfBbMHtXKXUMUxH7zV3Zuozh+kUQWhHvg=="], "msgpackr-extract": ["msgpackr-extract@3.0.3", "", { "dependencies": { "node-gyp-build-optional-packages": "5.2.2" }, "optionalDependencies": { "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.3", "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.3", "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.3", "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.3", "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.3", "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.3" }, "bin": { "download-msgpackr-prebuilds": "bin/download-prebuilds.js" } }, "sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA=="], - "mylas": ["mylas@2.1.14", "", {}, "sha512-BzQguy9W9NJgoVn2mRWzbFrFWWztGCcng2QI9+41frfk+Athwgx3qhqhvStz7ExeUUu7Kzw427sNzHpEZNINog=="], - "mz": ["mz@2.7.0", "", { "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", "thenify-all": "^1.0.0" } }, "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q=="], - "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], + "nanoid": ["nanoid@3.3.12", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ=="], "napi-postinstall": ["napi-postinstall@0.3.4", "", { "bin": { "napi-postinstall": "lib/cli.js" } }, "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ=="], @@ -1113,6 +1172,10 @@ "node-addon-api": ["node-addon-api@2.0.2", "", {}, "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA=="], + "node-emoji": ["node-emoji@2.2.0", "", { "dependencies": { "@sindresorhus/is": "^4.6.0", "char-regex": "^1.0.2", "emojilib": "^2.4.0", "skin-tone": "^2.0.0" } }, "sha512-Z3lTE9pLaJF47NyMhd4ww1yFTAP8YhYI8SleJiHzM46Fgpm5cnNzSl9XfzFNqbaz+VlJrIj3fXQ4DeN1Rjm6cw=="], + + "node-exports-info": ["node-exports-info@1.6.0", "", { "dependencies": { "array.prototype.flatmap": "^1.3.3", "es-errors": "^1.3.0", "object.entries": "^1.1.9", "semver": "^6.3.1" } }, "sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw=="], + "node-gyp-build": ["node-gyp-build@4.8.4", "", { "bin": { "node-gyp-build": "bin.js", "node-gyp-build-optional": "optional.js", "node-gyp-build-test": "build-test.js" } }, "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ=="], "node-gyp-build-optional-packages": ["node-gyp-build-optional-packages@5.2.2", "", { "dependencies": { "detect-libc": "^2.0.1" }, "bin": { "node-gyp-build-optional-packages": "bin.js", "node-gyp-build-optional-packages-optional": "optional.js", "node-gyp-build-optional-packages-test": "build-test.js" } }, "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw=="], @@ -1139,15 +1202,13 @@ "object.values": ["object.values@1.2.1", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA=="], - "on-exit-leak-free": ["on-exit-leak-free@2.1.2", "", {}, "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA=="], - "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="], "optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="], "own-keys": ["own-keys@1.0.1", "", { "dependencies": { "get-intrinsic": "^1.2.6", "object-keys": "^1.1.1", "safe-push-apply": "^1.0.0" } }, "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg=="], - "ox": ["ox@0.9.6", "", { "dependencies": { "@adraffy/ens-normalize": "^1.11.0", "@noble/ciphers": "^1.3.0", "@noble/curves": "1.9.1", "@noble/hashes": "^1.8.0", "@scure/bip32": "^1.7.0", "@scure/bip39": "^1.6.0", "abitype": "^1.0.9", "eventemitter3": "5.0.1" }, "peerDependencies": { "typescript": ">=5.4.0" }, "optionalPeers": ["typescript"] }, "sha512-8SuCbHPvv2eZLYXrNmC0EC12rdzXQLdhnOMlHDW2wiCPLxBrOOJwX5L5E61by+UjTPOryqQiRSnjIKCI+GykKg=="], + "ox": ["ox@0.14.20", "", { "dependencies": { "@adraffy/ens-normalize": "^1.11.0", "@noble/ciphers": "^1.3.0", "@noble/curves": "1.9.1", "@noble/hashes": "^1.8.0", "@scure/bip32": "^1.7.0", "@scure/bip39": "^1.6.0", "abitype": "^1.2.3", "eventemitter3": "5.0.1" }, "peerDependencies": { "typescript": ">=5.4.0" }, "optionalPeers": ["typescript"] }, "sha512-rby38C3nDn8eQkf29Zgw4hkCZJ64Qqi0zRPWL8ENUQ7JVuoITqrVtwWQgM/He19SCMUEc7hS/Sjw0jIOSLJhOw=="], "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], @@ -1155,10 +1216,16 @@ "package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="], + "package-manager-detector": ["package-manager-detector@1.6.0", "", {}, "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA=="], + "pako": ["pako@2.1.0", "", {}, "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug=="], "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], + "parse5": ["parse5@5.1.1", "", {}, "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug=="], + + "parse5-htmlparser2-tree-adapter": ["parse5-htmlparser2-tree-adapter@6.0.1", "", { "dependencies": { "parse5": "^6.0.1" } }, "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA=="], + "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], "path-is-absolute": ["path-is-absolute@1.0.1", "", {}, "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="], @@ -1167,33 +1234,23 @@ "path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="], - "path-scurry": ["path-scurry@2.0.0", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg=="], - - "path-type": ["path-type@4.0.0", "", {}, "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw=="], + "path-scurry": ["path-scurry@2.0.2", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg=="], "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], - "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], + "picomatch": ["picomatch@4.0.4", "", {}, "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A=="], "pify": ["pify@2.3.0", "", {}, "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog=="], - "pino": ["pino@9.13.1", "", { "dependencies": { "atomic-sleep": "^1.0.0", "on-exit-leak-free": "^2.1.0", "pino-abstract-transport": "^2.0.0", "pino-std-serializers": "^7.0.0", "process-warning": "^5.0.0", "quick-format-unescaped": "^4.0.3", "real-require": "^0.2.0", "safe-stable-stringify": "^2.3.1", "slow-redact": "^0.3.0", "sonic-boom": "^4.0.1", "thread-stream": "^3.0.0" }, "bin": { "pino": "bin.js" } }, "sha512-Szuj+ViDTjKPQYiKumGmEn3frdl+ZPSdosHyt9SnUevFosOkMY2b7ipxlEctNKPmMD/VibeBI+ZcZCJK+4DPuw=="], - - "pino-abstract-transport": ["pino-abstract-transport@2.0.0", "", { "dependencies": { "split2": "^4.0.0" } }, "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw=="], - - "pino-std-serializers": ["pino-std-serializers@7.0.0", "", {}, "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA=="], - "pirates": ["pirates@4.0.7", "", {}, "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA=="], "pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="], - "plimit-lit": ["plimit-lit@1.6.1", "", { "dependencies": { "queue-lit": "^1.5.1" } }, "sha512-B7+VDyb8Tl6oMJT9oSO2CW8XC/T4UcJGrwOVoNGwOQsQYhlpfajmrMj5xeejqaASq3V/EqThyOeATEOMuSEXiA=="], - "possible-typed-array-names": ["possible-typed-array-names@1.1.0", "", {}, "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg=="], - "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="], + "postcss": ["postcss@8.5.13", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-qif0+jGGZoLWdHey3UFHHWP0H7Gbmsk8T5VEqyYFbWqPr1XqvLGBbk/sl8V5exGmcYJklJOhOQq1pV9IcsiFag=="], "postcss-import": ["postcss-import@15.1.0", "", { "dependencies": { "postcss-value-parser": "^4.0.0", "read-cache": "^1.0.0", "resolve": "^1.1.7" }, "peerDependencies": { "postcss": "^8.0.0" } }, "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew=="], @@ -1209,35 +1266,31 @@ "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], - "prettier": ["prettier@3.6.2", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ=="], - - "prettier-linter-helpers": ["prettier-linter-helpers@1.0.0", "", { "dependencies": { "fast-diff": "^1.1.2" } }, "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w=="], + "prettier": ["prettier@3.8.3", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw=="], - "pretty-format": ["pretty-format@30.2.0", "", { "dependencies": { "@jest/schemas": "30.0.5", "ansi-styles": "^5.2.0", "react-is": "^18.3.1" } }, "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA=="], + "prettier-linter-helpers": ["prettier-linter-helpers@1.0.1", "", { "dependencies": { "fast-diff": "^1.1.2" } }, "sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg=="], - "process-warning": ["process-warning@5.0.0", "", {}, "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA=="], + "pretty-format": ["pretty-format@30.3.0", "", { "dependencies": { "@jest/schemas": "30.0.5", "ansi-styles": "^5.2.0", "react-is": "^18.3.1" } }, "sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ=="], "prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="], + "publint": ["publint@0.3.18", "", { "dependencies": { "@publint/pack": "^0.1.4", "package-manager-detector": "^1.6.0", "picocolors": "^1.1.1", "sade": "^1.8.1" }, "bin": { "publint": "src/cli.js" } }, "sha512-JRJFeBTrfx4qLwEuGFPk+haJOJN97KnPuK01yj+4k/Wj5BgoOK5uNsivporiqBjk2JDaslg7qJOhGRnpltGeog=="], + "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], "pvtsutils": ["pvtsutils@1.3.6", "", { "dependencies": { "tslib": "^2.8.1" } }, "sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg=="], - "pvutils": ["pvutils@1.1.3", "", {}, "sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ=="], - - "queue-lit": ["queue-lit@1.5.2", "", {}, "sha512-tLc36IOPeMAubu8BkW8YDBV+WyIgKlYU7zUNs0J5Vk9skSZ4JfGlPOqplP0aHdfv7HL0B2Pg6nwiq60Qc6M2Hw=="], + "pvutils": ["pvutils@1.1.5", "", {}, "sha512-KTqnxsgGiQ6ZAzZCVlJH5eOjSnvlyEgx1m8bkRJfOhmGRqfo5KLvmAlACQkrjEtOQ4B7wF9TdSLIs9O90MX9xA=="], "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], - "quick-format-unescaped": ["quick-format-unescaped@4.0.4", "", {}, "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg=="], - "react": ["react@18.3.1", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ=="], "react-dom": ["react-dom@18.3.1", "", { "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" }, "peerDependencies": { "react": "^18.3.1" } }, "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw=="], "react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="], - "react-remove-scroll": ["react-remove-scroll@2.7.1", "", { "dependencies": { "react-remove-scroll-bar": "^2.3.7", "react-style-singleton": "^2.2.3", "tslib": "^2.1.0", "use-callback-ref": "^1.3.3", "use-sidecar": "^1.1.3" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA=="], + "react-remove-scroll": ["react-remove-scroll@2.7.2", "", { "dependencies": { "react-remove-scroll-bar": "^2.3.7", "react-style-singleton": "^2.2.3", "tslib": "^2.1.0", "use-callback-ref": "^1.3.3", "use-sidecar": "^1.1.3" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q=="], "react-remove-scroll-bar": ["react-remove-scroll-bar@2.3.8", "", { "dependencies": { "react-style-singleton": "^2.2.2", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q=="], @@ -1251,9 +1304,7 @@ "readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], - "readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], - - "real-require": ["real-require@0.2.0", "", {}, "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg=="], + "readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], "reflect-metadata": ["reflect-metadata@0.2.2", "", {}, "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q=="], @@ -1265,7 +1316,9 @@ "registry-explorer": ["registry-explorer@workspace:packages/registry-explorer"], - "resolve": ["resolve@1.22.10", "", { "dependencies": { "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w=="], + "require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="], + + "resolve": ["resolve@1.22.12", "", { "dependencies": { "es-errors": "^1.3.0", "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA=="], "resolve-from": ["resolve-from@5.0.0", "", {}, "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="], @@ -1273,13 +1326,15 @@ "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], - "rimraf": ["rimraf@6.0.1", "", { "dependencies": { "glob": "^11.0.0", "package-json-from-dist": "^1.0.0" }, "bin": { "rimraf": "dist/esm/bin.mjs" } }, "sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A=="], + "rimraf": ["rimraf@6.1.3", "", { "dependencies": { "glob": "^13.0.3", "package-json-from-dist": "^1.0.1" }, "bin": { "rimraf": "dist/esm/bin.mjs" } }, "sha512-LKg+Cr2ZF61fkcaK1UdkH2yEBBKnYjTyWzTJT6KNPcSPaiT7HSdhtMXQuN5wkTX0Xu72KQ1l8S42rlmexS2hSA=="], - "rollup": ["rollup@4.52.4", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.52.4", "@rollup/rollup-android-arm64": "4.52.4", "@rollup/rollup-darwin-arm64": "4.52.4", "@rollup/rollup-darwin-x64": "4.52.4", "@rollup/rollup-freebsd-arm64": "4.52.4", "@rollup/rollup-freebsd-x64": "4.52.4", "@rollup/rollup-linux-arm-gnueabihf": "4.52.4", "@rollup/rollup-linux-arm-musleabihf": "4.52.4", "@rollup/rollup-linux-arm64-gnu": "4.52.4", "@rollup/rollup-linux-arm64-musl": "4.52.4", "@rollup/rollup-linux-loong64-gnu": "4.52.4", "@rollup/rollup-linux-ppc64-gnu": "4.52.4", "@rollup/rollup-linux-riscv64-gnu": "4.52.4", "@rollup/rollup-linux-riscv64-musl": "4.52.4", "@rollup/rollup-linux-s390x-gnu": "4.52.4", "@rollup/rollup-linux-x64-gnu": "4.52.4", "@rollup/rollup-linux-x64-musl": "4.52.4", "@rollup/rollup-openharmony-arm64": "4.52.4", "@rollup/rollup-win32-arm64-msvc": "4.52.4", "@rollup/rollup-win32-ia32-msvc": "4.52.4", "@rollup/rollup-win32-x64-gnu": "4.52.4", "@rollup/rollup-win32-x64-msvc": "4.52.4", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-CLEVl+MnPAiKh5pl4dEWSyMTpuflgNQiLGhMv8ezD5W/qP8AKvmYpCOKRRNOh7oRKnauBZ4SyeYkMS+1VSyKwQ=="], + "rollup": ["rollup@4.60.2", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.60.2", "@rollup/rollup-android-arm64": "4.60.2", "@rollup/rollup-darwin-arm64": "4.60.2", "@rollup/rollup-darwin-x64": "4.60.2", "@rollup/rollup-freebsd-arm64": "4.60.2", "@rollup/rollup-freebsd-x64": "4.60.2", "@rollup/rollup-linux-arm-gnueabihf": "4.60.2", "@rollup/rollup-linux-arm-musleabihf": "4.60.2", "@rollup/rollup-linux-arm64-gnu": "4.60.2", "@rollup/rollup-linux-arm64-musl": "4.60.2", "@rollup/rollup-linux-loong64-gnu": "4.60.2", "@rollup/rollup-linux-loong64-musl": "4.60.2", "@rollup/rollup-linux-ppc64-gnu": "4.60.2", "@rollup/rollup-linux-ppc64-musl": "4.60.2", "@rollup/rollup-linux-riscv64-gnu": "4.60.2", "@rollup/rollup-linux-riscv64-musl": "4.60.2", "@rollup/rollup-linux-s390x-gnu": "4.60.2", "@rollup/rollup-linux-x64-gnu": "4.60.2", "@rollup/rollup-linux-x64-musl": "4.60.2", "@rollup/rollup-openbsd-x64": "4.60.2", "@rollup/rollup-openharmony-arm64": "4.60.2", "@rollup/rollup-win32-arm64-msvc": "4.60.2", "@rollup/rollup-win32-ia32-msvc": "4.60.2", "@rollup/rollup-win32-x64-gnu": "4.60.2", "@rollup/rollup-win32-x64-msvc": "4.60.2", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-J9qZyW++QK/09NyN/zeO0dG/1GdGfyp9lV8ajHnRVLfo/uFsbji5mHnDgn/qYdUHyCkM2N+8VyspgZclfAh0eQ=="], "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], - "safe-array-concat": ["safe-array-concat@1.1.3", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "get-intrinsic": "^1.2.6", "has-symbols": "^1.1.0", "isarray": "^2.0.5" } }, "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q=="], + "sade": ["sade@1.8.1", "", { "dependencies": { "mri": "^1.1.0" } }, "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A=="], + + "safe-array-concat": ["safe-array-concat@1.1.4", "", { "dependencies": { "call-bind": "^1.0.9", "call-bound": "^1.0.4", "get-intrinsic": "^1.3.0", "has-symbols": "^1.1.0", "isarray": "^2.0.5" } }, "sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg=="], "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], @@ -1287,11 +1342,11 @@ "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=="], - "safe-stable-stringify": ["safe-stable-stringify@2.5.0", "", {}, "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA=="], + "sax": ["sax@1.6.0", "", {}, "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA=="], "scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="], - "semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="], + "semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], "set-function-length": ["set-function-length@1.2.2", "", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", "has-property-descriptors": "^1.0.2" } }, "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg=="], @@ -1305,7 +1360,7 @@ "side-channel": ["side-channel@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="], - "side-channel-list": ["side-channel-list@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" } }, "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA=="], + "side-channel-list": ["side-channel-list@1.0.1", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.4" } }, "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w=="], "side-channel-map": ["side-channel-map@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="], @@ -1313,18 +1368,14 @@ "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], - "slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="], - - "slow-redact": ["slow-redact@0.3.2", "", {}, "sha512-MseHyi2+E/hBRqdOi5COy6wZ7j7DxXRz9NkseavNYSvvWC06D8a5cidVZX3tcG5eCW3NIyVU4zT63hw0Q486jw=="], + "skin-tone": ["skin-tone@2.0.0", "", { "dependencies": { "unicode-emoji-modifier-base": "^1.0.0" } }, "sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA=="], - "sonic-boom": ["sonic-boom@4.2.0", "", { "dependencies": { "atomic-sleep": "^1.0.0" } }, "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww=="], + "slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="], - "source-map": ["source-map@0.8.0-beta.0", "", { "dependencies": { "whatwg-url": "^7.0.0" } }, "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA=="], + "source-map": ["source-map@0.7.6", "", {}, "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ=="], "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], - "split2": ["split2@4.2.0", "", {}, "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg=="], - "stable-hash": ["stable-hash@0.0.5", "", {}, "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA=="], "stack-utils": ["stack-utils@2.0.6", "", { "dependencies": { "escape-string-regexp": "^2.0.0" } }, "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ=="], @@ -1333,7 +1384,7 @@ "streamsearch": ["streamsearch@1.1.0", "", {}, "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg=="], - "string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], + "string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], "string-width-cjs": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], @@ -1361,21 +1412,23 @@ "styled-jsx": ["styled-jsx@5.1.1", "", { "dependencies": { "client-only": "0.0.1" }, "peerDependencies": { "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" } }, "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw=="], - "sucrase": ["sucrase@3.35.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", "glob": "^10.3.10", "lines-and-columns": "^1.1.6", "mz": "^2.7.0", "pirates": "^4.0.1", "ts-interface-checker": "^0.1.9" }, "bin": { "sucrase": "bin/sucrase", "sucrase-node": "bin/sucrase-node" } }, "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA=="], + "sucrase": ["sucrase@3.35.1", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", "lines-and-columns": "^1.1.6", "mz": "^2.7.0", "pirates": "^4.0.1", "tinyglobby": "^0.2.11", "ts-interface-checker": "^0.1.9" }, "bin": { "sucrase": "bin/sucrase", "sucrase-node": "bin/sucrase-node" } }, "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw=="], "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], + "supports-hyperlinks": ["supports-hyperlinks@3.2.0", "", { "dependencies": { "has-flag": "^4.0.0", "supports-color": "^7.0.0" } }, "sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig=="], + "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], "svg-country-flags": ["svg-country-flags@1.2.10", "", {}, "sha512-xrqwo0TYf/h2cfPvGpjdSuSguUbri4vNNizBnwzoZnX0xGo3O5nGJMlbYEp7NOYcnPGBm6LE2axqDWSB847bLw=="], - "svgo": ["svgo@3.3.2", "", { "dependencies": { "@trysound/sax": "0.2.0", "commander": "^7.2.0", "css-select": "^5.1.0", "css-tree": "^2.3.1", "css-what": "^6.1.0", "csso": "^5.0.5", "picocolors": "^1.0.0" }, "bin": "./bin/svgo" }, "sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw=="], + "svgo": ["svgo@3.3.3", "", { "dependencies": { "commander": "^7.2.0", "css-select": "^5.1.0", "css-tree": "^2.3.1", "css-what": "^6.1.0", "csso": "^5.0.5", "picocolors": "^1.0.0", "sax": "^1.5.0" }, "bin": "./bin/svgo" }, "sha512-+wn7I4p7YgJhHs38k2TNjy1vCfPIfLIJWR5MnCStsN8WuuTcBnRKcMHQLMM2ijxGZmDoZwNv8ipl5aTTen62ng=="], - "synckit": ["synckit@0.11.11", "", { "dependencies": { "@pkgr/core": "^0.2.9" } }, "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw=="], + "synckit": ["synckit@0.11.12", "", { "dependencies": { "@pkgr/core": "^0.2.9" } }, "sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ=="], - "tailwind-merge": ["tailwind-merge@2.6.0", "", {}, "sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA=="], + "tailwind-merge": ["tailwind-merge@2.6.1", "", {}, "sha512-Oo6tHdpZsGpkKG88HJ8RR1rg/RdnEkQEfMoEk2x1XRI3F1AxeU+ijRXpiVUF4UbLfcxxRGw6TbUINKYdWVsQTQ=="], - "tailwindcss": ["tailwindcss@3.4.18", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", "chokidar": "^3.6.0", "didyoumean": "^1.2.2", "dlv": "^1.1.3", "fast-glob": "^3.3.2", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", "jiti": "^1.21.7", "lilconfig": "^3.1.3", "micromatch": "^4.0.8", "normalize-path": "^3.0.0", "object-hash": "^3.0.0", "picocolors": "^1.1.1", "postcss": "^8.4.47", "postcss-import": "^15.1.0", "postcss-js": "^4.0.1", "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0", "postcss-nested": "^6.2.0", "postcss-selector-parser": "^6.1.2", "resolve": "^1.22.8", "sucrase": "^3.35.0" }, "bin": { "tailwind": "lib/cli.js", "tailwindcss": "lib/cli.js" } }, "sha512-6A2rnmW5xZMdw11LYjhcI5846rt9pbLSabY5XPxo+XWdxwZaFEn47Go4NzFiHu9sNNmr/kXivP1vStfvMaK1GQ=="], + "tailwindcss": ["tailwindcss@3.4.19", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", "chokidar": "^3.6.0", "didyoumean": "^1.2.2", "dlv": "^1.1.3", "fast-glob": "^3.3.2", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", "jiti": "^1.21.7", "lilconfig": "^3.1.3", "micromatch": "^4.0.8", "normalize-path": "^3.0.0", "object-hash": "^3.0.0", "picocolors": "^1.1.1", "postcss": "^8.4.47", "postcss-import": "^15.1.0", "postcss-js": "^4.0.1", "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0", "postcss-nested": "^6.2.0", "postcss-selector-parser": "^6.1.2", "resolve": "^1.22.8", "sucrase": "^3.35.0" }, "bin": { "tailwind": "lib/cli.js", "tailwindcss": "lib/cli.js" } }, "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ=="], "tailwindcss-animate": ["tailwindcss-animate@1.0.7", "", { "peerDependencies": { "tailwindcss": ">=3.0.0 || insiders" } }, "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA=="], @@ -1385,47 +1438,29 @@ "thenify-all": ["thenify-all@1.6.0", "", { "dependencies": { "thenify": ">= 3.1.0 < 4" } }, "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA=="], - "thread-stream": ["thread-stream@3.1.0", "", { "dependencies": { "real-require": "^0.2.0" } }, "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A=="], - "tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="], - "tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="], + "tinyglobby": ["tinyglobby@0.2.16", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg=="], "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], "topojson-client": ["topojson-client@3.1.0", "", { "dependencies": { "commander": "2" }, "bin": { "topo2geo": "bin/topo2geo", "topomerge": "bin/topomerge", "topoquantize": "bin/topoquantize" } }, "sha512-605uxS6bcYxGXw9qi62XyrV6Q3xwbndjachmNxu8HWTtVPxZfEJN9fd/SZS1Q54Sn2y0TMyMxFj/cJINqGHrKw=="], - "tr46": ["tr46@1.0.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA=="], - "tree-kill": ["tree-kill@1.2.2", "", { "bin": { "tree-kill": "cli.js" } }, "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A=="], - "ts-api-utils": ["ts-api-utils@2.1.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ=="], + "ts-api-utils": ["ts-api-utils@2.5.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA=="], "ts-interface-checker": ["ts-interface-checker@0.1.13", "", {}, "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="], - "tsc-alias": ["tsc-alias@1.8.16", "", { "dependencies": { "chokidar": "^3.5.3", "commander": "^9.0.0", "get-tsconfig": "^4.10.0", "globby": "^11.0.4", "mylas": "^2.1.9", "normalize-path": "^3.0.0", "plimit-lit": "^1.2.6" }, "bin": { "tsc-alias": "dist/bin/index.js" } }, "sha512-QjCyu55NFyRSBAl6+MTFwplpFcnm2Pq01rR/uxfqJoLMm6X3O14KEGtaSDZpJYaE1bJBGDjD0eSuiIWPe2T58g=="], - "tsconfig-paths": ["tsconfig-paths@3.15.0", "", { "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } }, "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg=="], "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], - "tsup": ["tsup@8.5.0", "", { "dependencies": { "bundle-require": "^5.1.0", "cac": "^6.7.14", "chokidar": "^4.0.3", "consola": "^3.4.0", "debug": "^4.4.0", "esbuild": "^0.25.0", "fix-dts-default-cjs-exports": "^1.0.0", "joycon": "^3.1.1", "picocolors": "^1.1.1", "postcss-load-config": "^6.0.1", "resolve-from": "^5.0.0", "rollup": "^4.34.8", "source-map": "0.8.0-beta.0", "sucrase": "^3.35.0", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.11", "tree-kill": "^1.2.2" }, "peerDependencies": { "@microsoft/api-extractor": "^7.36.0", "@swc/core": "^1", "postcss": "^8.4.12", "typescript": ">=4.5.0" }, "optionalPeers": ["@microsoft/api-extractor", "@swc/core", "postcss", "typescript"], "bin": { "tsup": "dist/cli-default.js", "tsup-node": "dist/cli-node.js" } }, "sha512-VmBp77lWNQq6PfuMqCHD3xWl22vEoWsKajkF8t+yMBawlUS8JzEI+vOVMeuNZIuMML8qXRizFKi9oD5glKQVcQ=="], + "tsup": ["tsup@8.5.1", "", { "dependencies": { "bundle-require": "^5.1.0", "cac": "^6.7.14", "chokidar": "^4.0.3", "consola": "^3.4.0", "debug": "^4.4.0", "esbuild": "^0.27.0", "fix-dts-default-cjs-exports": "^1.0.0", "joycon": "^3.1.1", "picocolors": "^1.1.1", "postcss-load-config": "^6.0.1", "resolve-from": "^5.0.0", "rollup": "^4.34.8", "source-map": "^0.7.6", "sucrase": "^3.35.0", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.11", "tree-kill": "^1.2.2" }, "peerDependencies": { "@microsoft/api-extractor": "^7.36.0", "@swc/core": "^1", "postcss": "^8.4.12", "typescript": ">=4.5.0" }, "optionalPeers": ["@microsoft/api-extractor", "@swc/core", "postcss", "typescript"], "bin": { "tsup": "dist/cli-default.js", "tsup-node": "dist/cli-node.js" } }, "sha512-xtgkqwdhpKWr3tKPmCkvYmS9xnQK3m3XgxZHwSUjvfTjp7YfXe5tT3GgWi0F2N+ZSMsOeWeZFh7ZZFg5iPhing=="], "tsyringe": ["tsyringe@4.10.0", "", { "dependencies": { "tslib": "^1.9.3" } }, "sha512-axr3IdNuVIxnaK5XGEUFTu3YmAQ6lllgrvqfEoR16g/HGnYY/6We4oWENtAnzK6/LpJ2ur9PAb80RBt7/U4ugw=="], - "turbo": ["turbo@2.6.0", "", { "optionalDependencies": { "turbo-darwin-64": "2.6.0", "turbo-darwin-arm64": "2.6.0", "turbo-linux-64": "2.6.0", "turbo-linux-arm64": "2.6.0", "turbo-windows-64": "2.6.0", "turbo-windows-arm64": "2.6.0" }, "bin": { "turbo": "bin/turbo" } }, "sha512-kC5VJqOXo50k0/0jnJDDjibLAXalqT9j7PQ56so0pN+81VR4Fwb2QgIE9dTzT3phqOTQuEXkPh3sCpnv5Isz2g=="], - - "turbo-darwin-64": ["turbo-darwin-64@2.6.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-6vHnLAubHj8Ib45Knu+oY0ZVCLO7WcibzAvt5b1E72YHqAs4y8meMAGMZM0jLqWPh/9maHDc16/qBCMxtW4pXg=="], - - "turbo-darwin-arm64": ["turbo-darwin-arm64@2.6.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-IU+gWMEXNBw8H0pxvE7nPEa5p6yahxbN8g/Q4Bf0AHymsAFqsScgV0peeNbWybdmY9jk1LPbALOsF2kY1I7ZiQ=="], - - "turbo-linux-64": ["turbo-linux-64@2.6.0", "", { "os": "linux", "cpu": "x64" }, "sha512-CKoiJ2ZFJLCDsWdRlZg+ew1BkGn8iCEGdePhISVpjsGwkJwSVhVu49z2zKdBeL1IhcSKS2YALwp9ellNZANJxw=="], - - "turbo-linux-arm64": ["turbo-linux-arm64@2.6.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-WroVCdCvJbrhNxNdw7XB7wHAfPPJPV+IXY+ZKNed+9VdfBu/2mQNfKnvqTuFTH7n+Pdpv8to9qwhXRTJe26upg=="], - - "turbo-windows-64": ["turbo-windows-64@2.6.0", "", { "os": "win32", "cpu": "x64" }, "sha512-7pZo5aGQPR+A7RMtWCZHusarJ6y15LQ+o3jOmpMxTic/W6Bad+jSeqo07TWNIseIWjCVzrSv27+0odiYRYtQdA=="], - - "turbo-windows-arm64": ["turbo-windows-arm64@2.6.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-1Ty+NwIksQY7AtFUCPrTpcKQE7zmd/f7aRjdT+qkqGFQjIjFYctEtN7qo4vpQPBgCfS1U3ka83A2u/9CfJQ3wQ=="], + "turbo": ["turbo@2.9.8", "", { "optionalDependencies": { "@turbo/darwin-64": "2.9.8", "@turbo/darwin-arm64": "2.9.8", "@turbo/linux-64": "2.9.8", "@turbo/linux-arm64": "2.9.8", "@turbo/windows-64": "2.9.8", "@turbo/windows-arm64": "2.9.8" }, "bin": { "turbo": "bin/turbo" } }, "sha512-REEB2rVTVDTf4hav1gJ5dIsGylWZrNonvjXFtk1dCi8gND3PhZtnYkyry1bra/Fo+iP6ctTEZbg6vWfdfHq/1A=="], "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], @@ -1443,11 +1478,13 @@ "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], - "ufo": ["ufo@1.6.1", "", {}, "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA=="], + "ufo": ["ufo@1.6.4", "", {}, "sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA=="], "unbox-primitive": ["unbox-primitive@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "has-bigints": "^1.0.2", "has-symbols": "^1.1.0", "which-boxed-primitive": "^1.1.1" } }, "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw=="], - "undici-types": ["undici-types@7.14.0", "", {}, "sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA=="], + "undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + + "unicode-emoji-modifier-base": ["unicode-emoji-modifier-base@1.0.0", "", {}, "sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g=="], "unrs-resolver": ["unrs-resolver@1.11.1", "", { "dependencies": { "napi-postinstall": "^0.3.0" }, "optionalDependencies": { "@unrs/resolver-binding-android-arm-eabi": "1.11.1", "@unrs/resolver-binding-android-arm64": "1.11.1", "@unrs/resolver-binding-darwin-arm64": "1.11.1", "@unrs/resolver-binding-darwin-x64": "1.11.1", "@unrs/resolver-binding-freebsd-x64": "1.11.1", "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", "@unrs/resolver-binding-linux-x64-musl": "1.11.1", "@unrs/resolver-binding-wasm32-wasi": "1.11.1", "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" } }, "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg=="], @@ -1459,11 +1496,9 @@ "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], - "viem": ["viem@2.38.2", "", { "dependencies": { "@noble/curves": "1.9.1", "@noble/hashes": "1.8.0", "@scure/bip32": "1.7.0", "@scure/bip39": "1.6.0", "abitype": "1.1.0", "isows": "1.0.7", "ox": "0.9.6", "ws": "8.18.3" }, "peerDependencies": { "typescript": ">=5.0.4" }, "optionalPeers": ["typescript"] }, "sha512-MJDiTDD9gfOT7lPQRimdmw+g46hU/aWJ3loqb+tN6UBOO00XEd0O4LJx+Kp5/uCRnMlJr8zJ1bNzCK7eG6gMjg=="], - - "webidl-conversions": ["webidl-conversions@4.0.2", "", {}, "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg=="], + "validate-npm-package-name": ["validate-npm-package-name@5.0.1", "", {}, "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ=="], - "whatwg-url": ["whatwg-url@7.1.0", "", { "dependencies": { "lodash.sortby": "^4.7.0", "tr46": "^1.0.1", "webidl-conversions": "^4.0.2" } }, "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg=="], + "viem": ["viem@2.48.8", "", { "dependencies": { "@noble/curves": "1.9.1", "@noble/hashes": "1.8.0", "@scure/bip32": "1.7.0", "@scure/bip39": "1.6.0", "abitype": "1.2.3", "isows": "1.0.7", "ox": "0.14.20", "ws": "8.18.3" }, "peerDependencies": { "typescript": ">=5.0.4" }, "optionalPeers": ["typescript"] }, "sha512-Xj3Nrt66SKtn06kczU91ELn9Difr84ZM5A62BTlaisT5lpgt058i2mBkfMZCXHGb1ocOLjzC2ztPhD0Lvky7uQ=="], "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], @@ -1473,41 +1508,65 @@ "which-collection": ["which-collection@1.0.2", "", { "dependencies": { "is-map": "^2.0.3", "is-set": "^2.0.3", "is-weakmap": "^2.0.2", "is-weakset": "^2.0.3" } }, "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw=="], - "which-typed-array": ["which-typed-array@1.1.19", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "for-each": "^0.3.5", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" } }, "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw=="], + "which-typed-array": ["which-typed-array@1.1.20", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "for-each": "^0.3.5", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" } }, "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg=="], "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="], "world-countries": ["world-countries@5.1.0", "", {}, "sha512-CXR6EBvTbArDlDDIWU3gfKb7Qk0ck2WNZ234b/A0vuecPzIfzzxH+O6Ejnvg1sT8XuiZjVlzOH0h08ZtaO7g0w=="], - "wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="], + "wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], "wrap-ansi-cjs": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], - "ws": ["ws@8.18.3", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg=="], + "ws": ["ws@8.20.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA=="], + + "y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="], + + "yargs": ["yargs@16.2.0", "", { "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.0", "y18n": "^5.0.5", "yargs-parser": "^20.2.2" } }, "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw=="], + + "yargs-parser": ["yargs-parser@20.2.9", "", {}, "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w=="], "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], + "@arethetypeswrong/core/typescript": ["typescript@5.6.1-rc", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-E3b2+1zEFu84jB0YQi9BORDjz9+jGbwwy1Zi3G0LUNw7a7cePUrHMRNy8aPh53nXpkFGVHSxIZo5vKTfYaFiBQ=="], + "@aztec/bb.js/commander": ["commander@12.1.0", "", {}, "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA=="], "@eslint/eslintrc/ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], - "@isaacs/cliui/strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="], + "@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], + + "@isaacs/cliui/strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], + + "@isaacs/cliui/wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="], "@next/eslint-plugin-next/glob": ["glob@10.3.10", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^2.3.5", "minimatch": "^9.0.1", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", "path-scurry": "^1.10.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g=="], - "@types/react-simple-maps/@types/d3-geo": ["@types/d3-geo@2.0.7", "", { "dependencies": { "@types/geojson": "*" } }, "sha512-RIXlxPdxvX+LAZFv+t78CuYpxYag4zuw9mZc+AwfB8tZpKU90rMEn2il2ADncmeZlb7nER9dDsJpRisA3lRvjA=="], + "@obsidion/bridge/@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="], + + "@radix-ui/react-collection/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="], - "@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + "@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="], - "@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="], + "@radix-ui/react-select/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="], - "anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + "@radix-ui/react-tooltip/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="], - "chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], + "@scure/bip32/@noble/curves": ["@noble/curves@1.9.1", "", { "dependencies": { "@noble/hashes": "1.8.0" } }, "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA=="], - "chokidar/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + "@scure/bip32/@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="], + + "@scure/bip39/@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="], + + "@types/react-simple-maps/@types/d3-geo": ["@types/d3-geo@2.0.7", "", { "dependencies": { "@types/geojson": "*" } }, "sha512-RIXlxPdxvX+LAZFv+t78CuYpxYag4zuw9mZc+AwfB8tZpKU90rMEn2il2ADncmeZlb7nER9dDsJpRisA3lRvjA=="], + + "@typescript-eslint/typescript-estree/minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="], + + "@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@5.0.1", "", {}, "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA=="], + + "anymatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], "csso/css-tree": ["css-tree@2.2.1", "", { "dependencies": { "mdn-data": "2.0.28", "source-map-js": "^1.0.1" } }, "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA=="], @@ -1515,6 +1574,8 @@ "eslint-import-resolver-node/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="], + "eslint-import-resolver-node/resolve": ["resolve@2.0.0-next.6", "", { "dependencies": { "es-errors": "^1.3.0", "is-core-module": "^2.16.1", "node-exports-info": "^1.6.0", "object-keys": "^1.1.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-3JmVl5hMGtJ3kMmB3zi3DL25KfkCEyy3Tw7Gmw7z5w8M9WlwoPFnIvwChzu1+cF3iaK3sp18hhPz8ANeimdJfA=="], + "eslint-module-utils/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="], "eslint-plugin-import/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="], @@ -1525,7 +1586,7 @@ "eslint-plugin-react/doctrine": ["doctrine@2.1.0", "", { "dependencies": { "esutils": "^2.0.2" } }, "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw=="], - "eslint-plugin-react/resolve": ["resolve@2.0.0-next.5", "", { "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA=="], + "eslint-plugin-react/resolve": ["resolve@2.0.0-next.6", "", { "dependencies": { "es-errors": "^1.3.0", "is-core-module": "^2.16.1", "node-exports-info": "^1.6.0", "object-keys": "^1.1.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-3JmVl5hMGtJ3kMmB3zi3DL25KfkCEyy3Tw7Gmw7z5w8M9WlwoPFnIvwChzu1+cF3iaK3sp18hhPz8ANeimdJfA=="], "eslint-plugin-react/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], @@ -1545,61 +1606,63 @@ "flat-cache/rimraf": ["rimraf@3.0.2", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" } }, "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="], - "glob/minimatch": ["minimatch@10.0.3", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.0" } }, "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw=="], - - "globby/ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], + "glob/minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="], "import-fresh/resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], - "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + "marked-terminal/chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="], + + "micromatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], "next/postcss": ["postcss@8.4.31", "", { "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ=="], + "node-exports-info/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + "ox/@noble/curves": ["@noble/curves@1.9.1", "", { "dependencies": { "@noble/hashes": "1.8.0" } }, "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA=="], + "ox/@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="], + + "parse5-htmlparser2-tree-adapter/parse5": ["parse5@6.0.1", "", {}, "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw=="], + + "pretty-format/ansi-styles": ["ansi-styles@5.2.0", "", {}, "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="], + "prop-types/react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="], "react-simple-maps/d3-geo": ["d3-geo@2.0.2", "", { "dependencies": { "d3-array": "^2.5.0" } }, "sha512-8pM1WGMLGFuhq9S+FpPURxic+gKzjluCD/CHTuUF3mXMeiCo0i6R0tO1s4+GArRFde96SLcW/kOFRjoAosPsFA=="], - "readdirp/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], - "stack-utils/escape-string-regexp": ["escape-string-regexp@2.0.0", "", {}, "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w=="], - "string-width/strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="], + "string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], "string-width-cjs/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], - "sucrase/commander": ["commander@4.1.1", "", {}, "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA=="], + "strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - "sucrase/glob": ["glob@10.3.10", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^2.3.5", "minimatch": "^9.0.1", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", "path-scurry": "^1.10.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g=="], + "strip-ansi-cjs/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "sucrase/commander": ["commander@4.1.1", "", {}, "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA=="], "svgo/commander": ["commander@7.2.0", "", {}, "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="], - "topojson-client/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="], + "tailwindcss/chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="], - "tsup/chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="], + "topojson-client/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="], "tsyringe/tslib": ["tslib@1.14.1", "", {}, "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="], "viem/@noble/curves": ["@noble/curves@1.9.1", "", { "dependencies": { "@noble/hashes": "1.8.0" } }, "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA=="], - "wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], - - "wrap-ansi/strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="], - - "wrap-ansi-cjs/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], - - "wrap-ansi-cjs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + "viem/@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="], - "@isaacs/cliui/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], + "viem/ws": ["ws@8.18.3", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg=="], - "@next/eslint-plugin-next/glob/jackspeak": ["jackspeak@2.3.6", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ=="], + "@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], - "@next/eslint-plugin-next/glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + "@next/eslint-plugin-next/glob/minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="], "@next/eslint-plugin-next/glob/path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="], - "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], + "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@5.0.5", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ=="], "csso/css-tree/mdn-data": ["mdn-data@2.0.28", "", {}, "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g=="], @@ -1607,30 +1670,24 @@ "flat-cache/rimraf/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], - "react-simple-maps/d3-geo/d3-array": ["d3-array@2.12.1", "", { "dependencies": { "internmap": "^1.0.0" } }, "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ=="], - - "string-width/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], + "glob/minimatch/brace-expansion": ["brace-expansion@5.0.5", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ=="], - "sucrase/glob/jackspeak": ["jackspeak@2.3.6", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ=="], - - "sucrase/glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + "react-simple-maps/d3-geo/d3-array": ["d3-array@2.12.1", "", { "dependencies": { "internmap": "^1.0.0" } }, "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ=="], - "sucrase/glob/path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="], + "tailwindcss/chokidar/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], - "tsup/chokidar/readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], + "tailwindcss/chokidar/readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], - "wrap-ansi-cjs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + "@next/eslint-plugin-next/glob/minimatch/brace-expansion": ["brace-expansion@2.1.0", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w=="], - "wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], + "@next/eslint-plugin-next/glob/path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], - "@next/eslint-plugin-next/glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], + "@typescript-eslint/typescript-estree/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], - "@next/eslint-plugin-next/glob/path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], + "glob/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], "react-simple-maps/d3-geo/d3-array/internmap": ["internmap@1.0.1", "", {}, "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw=="], - "sucrase/glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], - - "sucrase/glob/path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], + "tailwindcss/chokidar/readdirp/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], } } diff --git a/package.json b/package.json index 18ba863b..fd6570ed 100644 --- a/package.json +++ b/package.json @@ -4,29 +4,32 @@ "private": true, "scripts": { "build": "turbo run build", - "build:types": "turbo run build:types", "dev:build": "turbo run dev:build", + "validate-packages": "turbo run validate-package", "test": "turbo run test", "check": "turbo run check", "format": "turbo run format", - "clean": "turbo run clean && rimraf node_modules/.cache" + "clean": "turbo run clean && rimraf .turbo node_modules/.cache", + "clean:deep": "turbo run clean && rimraf .turbo **/node_modules && bun i" }, "workspaces": [ "packages/*" ], "devDependencies": { + "@arethetypeswrong/cli": "^0.18.2", "@types/bun": "^1.3.1", "@types/debug": "^4.1.12", "@types/jest": "^30.0.0", "@types/node": "^24.0.13", + "@types/sinonjs__fake-timers": "^15.0.1", "@typescript-eslint/eslint-plugin": "^8.36.0", "@typescript-eslint/parser": "^8.36.0", "eslint": "^8.57.1", "eslint-config-prettier": "^10.1.2", "eslint-plugin-prettier": "^5.2.6", "prettier": "^3.6.2", + "publint": "^0.3.17", "rimraf": "^6.0.1", - "tsc-alias": "^1.8.16", "tsup": "^8.5.0", "turbo": "^2.6.0", "typescript": "^5.0.0" diff --git a/packages/registry-contracts/foundry.toml b/packages/registry-contracts/foundry.toml index 1f33a543..93f9811a 100644 --- a/packages/registry-contracts/foundry.toml +++ b/packages/registry-contracts/foundry.toml @@ -11,10 +11,19 @@ optimizer_runs = 200 bytecode_hash = "none" # Remappings remappings = ["forge-std/=lib/forge-std/src/"] +# File system permissions +fs_permissions = [{ access = "read-write", path = "./deployments"}] [lint] lint_on_build = false -exclude_lints = ["screaming-snake-case-immutable", "unwrapped-modifier-logic"] +exclude_lints = ["mixed-case-function", "screaming-snake-case-immutable", "unwrapped-modifier-logic"] + +[fmt] +# tab_width = 4 +ignore = [ + "src/mocks", + "src/lib/Constants.sol" +] [rpc_endpoints] mainnet = "${MAINNET_RPC_URL}" diff --git a/packages/registry-contracts/package.json b/packages/registry-contracts/package.json index a5aba1b7..345186d9 100644 --- a/packages/registry-contracts/package.json +++ b/packages/registry-contracts/package.json @@ -1,6 +1,6 @@ { "name": "registry-contracts", - "version": "0.1.0", + "version": "0.2.1", "private": true, "scripts": { "dev": "script/bash/run-and-deploy.sh", diff --git a/packages/registry-contracts/script/DeployBase.s.sol b/packages/registry-contracts/script/DeployBase.s.sol new file mode 100644 index 00000000..bfe9f62a --- /dev/null +++ b/packages/registry-contracts/script/DeployBase.s.sol @@ -0,0 +1,39 @@ +/* + * DeployBase.s.sol + * + * Shared base contract for deploy scripts. Provides helpers for writing + * deployment data into the shared addresses file. + */ + +pragma solidity ^0.8.30; + +import {Script, console} from "forge-std/Script.sol"; + +abstract contract DeployBase is Script { + string internal constant DEPLOYMENTS_DIR = "./deployments"; + + function _ensureDeploymentsDir() internal { + if (!vm.exists(DEPLOYMENTS_DIR)) { + vm.createDir(DEPLOYMENTS_DIR, true); + } + } + + function _chainIdStr() internal view returns (string memory) { + return vm.toString(block.chainid); + } + + function _addressesFilePath() internal view returns (string memory) { + return string.concat(DEPLOYMENTS_DIR, "/addresses-", _chainIdStr(), ".json"); + } + + /// Write a serialized JSON object to a top-level key in `addresses-.json`. + function _writeToAddresses(string memory key, string memory json) internal { + _ensureDeploymentsDir(); + string memory path = _addressesFilePath(); + if (!vm.exists(path)) { + vm.writeJson("{}", path); + } + vm.writeJson(json, path, string.concat(".", key)); + console.log("Updated addresses file:", path); + } +} diff --git a/packages/registry-contracts/script/DeployCertificateRegistry.s.sol b/packages/registry-contracts/script/DeployCertificateRegistry.s.sol index 43a5b244..ce1b86e2 100644 --- a/packages/registry-contracts/script/DeployCertificateRegistry.s.sol +++ b/packages/registry-contracts/script/DeployCertificateRegistry.s.sol @@ -1,7 +1,13 @@ +/* + * DeployCertificateRegistry.s.sol + * + * Deploys the certificate registry. + */ + pragma solidity ^0.8.30; import {Script, console} from "forge-std/Script.sol"; -import {CertificateRegistry} from "../src/CertificateRegistry.sol"; +import {CertificateRegistry} from "../src/registries/CertificateRegistry.sol"; import {RootValidationMode} from "../src/IRegistryInstance.sol"; contract DeployCertificateRegistryScript is Script { diff --git a/packages/registry-contracts/script/DeployCircuitRegistry.s.sol b/packages/registry-contracts/script/DeployCircuitRegistry.s.sol index 28fc8dfd..6fdf20b8 100644 --- a/packages/registry-contracts/script/DeployCircuitRegistry.s.sol +++ b/packages/registry-contracts/script/DeployCircuitRegistry.s.sol @@ -1,7 +1,13 @@ +/* + * DeployCircuitRegistry.s.sol + * + * Deploys the circuit registry. + */ + pragma solidity ^0.8.30; import {Script, console} from "forge-std/Script.sol"; -import {CircuitRegistry} from "../src/CircuitRegistry.sol"; +import {CircuitRegistry} from "../src/registries/CircuitRegistry.sol"; import {RootValidationMode} from "../src/IRegistryInstance.sol"; contract DeployCircuitRegistryScript is Script { diff --git a/packages/registry-contracts/script/DeployProtocolController.s.sol b/packages/registry-contracts/script/DeployProtocolController.s.sol new file mode 100644 index 00000000..244c67ea --- /dev/null +++ b/packages/registry-contracts/script/DeployProtocolController.s.sol @@ -0,0 +1,61 @@ +/* + * DeployProtocolController.s.sol + * + * Deploys the protocol controller. + */ + +pragma solidity ^0.8.30; + +import {console} from "forge-std/Script.sol"; +import {stdJson} from "forge-std/StdJson.sol"; +import {DeployBase} from "./DeployBase.s.sol"; +import {ProtocolController} from "../src/ProtocolController.sol"; + +contract DeployProtocolControllerScript is DeployBase { + using stdJson for string; + + ProtocolController public controller; + + function setUp() public {} + + function run() public { + address adminAddress = vm.envAddress("PROTOCOL_CONTROLLER_ADMIN"); + require(adminAddress != address(0), "PROTOCOL_CONTROLLER_ADMIN must be set"); + + address rootRegistry = vm.envAddress("ROOT_REGISTRY_ADDRESS"); + require(rootRegistry != address(0), "ROOT_REGISTRY_ADDRESS must be set"); + + address rootRegistryOperator = vm.envAddress("ROOT_REGISTRY_OPERATOR_ADDRESS"); + require(rootRegistryOperator != address(0), "ROOT_REGISTRY_OPERATOR_ADDRESS must be set"); + + address rootVerifier = vm.envAddress("ROOT_VERIFIER_ADDRESS"); + require(rootVerifier != address(0), "ROOT_VERIFIER_ADDRESS must be set"); + + address rootVerifierOperator = vm.envAddress("ROOT_VERIFIER_OPERATOR_ADDRESS"); + require(rootVerifierOperator != address(0), "ROOT_VERIFIER_OPERATOR_ADDRESS must be set"); + + vm.startBroadcast(); + controller = new ProtocolController( + adminAddress, rootRegistry, rootRegistryOperator, rootVerifier, rootVerifierOperator + ); + vm.stopBroadcast(); + + console.log("ProtocolController deployed at:", address(controller)); + console.log("Admin:", controller.admin()); + console.log("Root Registry:", address(controller.rootRegistry())); + console.log("Root Registry Operator:", controller.rootRegistryOperator()); + console.log("Root Verifier:", address(controller.rootVerifier())); + console.log("Root Verifier Operator:", controller.rootVerifierOperator()); + + string memory section = "protocol_controller"; + vm.serializeAddress(section, "address", address(controller)); + vm.serializeAddress(section, "admin", adminAddress); + vm.serializeAddress(section, "root_registry", rootRegistry); + vm.serializeAddress(section, "root_registry_operator", rootRegistryOperator); + vm.serializeAddress(section, "root_verifier", rootVerifier); + vm.serializeAddress(section, "root_verifier_operator", rootVerifierOperator); + section = vm.serializeUint(section, "deployed_at", block.timestamp); + + _writeToAddresses("protocol_controller", section); + } +} diff --git a/packages/registry-contracts/script/DeployRegistryHelper.s.sol b/packages/registry-contracts/script/DeployRegistryHelper.s.sol index 9b850ebd..56e1d267 100644 --- a/packages/registry-contracts/script/DeployRegistryHelper.s.sol +++ b/packages/registry-contracts/script/DeployRegistryHelper.s.sol @@ -1,10 +1,18 @@ +/* + * DeployRegistryHelper.s.sol + * + * Deploys the registry helper, a read-only utility contract for querying + * data across the root registry's sub-registries. + */ + pragma solidity ^0.8.30; -import {Script, console} from "forge-std/Script.sol"; +import {console} from "forge-std/Script.sol"; +import {DeployBase} from "./DeployBase.s.sol"; import {RegistryHelper} from "../src/RegistryHelper.sol"; import {RootRegistry} from "../src/RootRegistry.sol"; -contract DeployRegistryHelperScript is Script { +contract DeployRegistryHelperScript is DeployBase { RegistryHelper public helper; function setUp() public {} @@ -19,5 +27,7 @@ contract DeployRegistryHelperScript is Script { vm.stopBroadcast(); console.log("RegistryHelper deployed at:", address(helper)); console.log("RegistryHelper using RootRegistry at:", rootRegistryAddress); + + _writeToAddresses("root_registry.helper", string.concat('"', vm.toString(address(helper)), '"')); } } diff --git a/packages/registry-contracts/script/DeployRootRegistry.s.sol b/packages/registry-contracts/script/DeployRootRegistry.s.sol index 2a5a1c74..0fc45e71 100644 --- a/packages/registry-contracts/script/DeployRootRegistry.s.sol +++ b/packages/registry-contracts/script/DeployRootRegistry.s.sol @@ -1,9 +1,22 @@ +/* + * DeployRootRegistry.s.sol + * + * ⚠️ FOR LOCAL TESTING ONLY — DO NOT USE IN PRODUCTION ⚠️ + * + * Deploys the root registry using a plain CREATE. The production RootRegistry + * is deployed via a CREATE2 factory with a salt to get a universal multichain address. + */ + pragma solidity ^0.8.30; -import {Script, console} from "forge-std/Script.sol"; +import {console} from "forge-std/Script.sol"; +import {stdJson} from "forge-std/StdJson.sol"; +import {DeployBase} from "./DeployBase.s.sol"; import {RootRegistry} from "../src/RootRegistry.sol"; -contract DeployRootRegistryScript is Script { +contract DeployRootRegistryScript is DeployBase { + using stdJson for string; + RootRegistry public registry; function setUp() public {} @@ -23,5 +36,13 @@ contract DeployRootRegistryScript is Script { console.log("RootRegistry deployed at:", address(registry)); console.log("Admin:", registry.admin()); console.log("Guardian:", registry.guardian()); + + string memory section = "root_registry"; + vm.serializeAddress(section, "address", address(registry)); + vm.serializeAddress(section, "admin", adminAddress); + vm.serializeAddress(section, "guardian", guardianAddress); + section = vm.serializeUint(section, "deployed_at", block.timestamp); + + _writeToAddresses("root_registry", section); } } diff --git a/packages/registry-contracts/script/DeployRootVerifier.s.sol b/packages/registry-contracts/script/DeployRootVerifier.s.sol new file mode 100644 index 00000000..491b5714 --- /dev/null +++ b/packages/registry-contracts/script/DeployRootVerifier.s.sol @@ -0,0 +1,151 @@ +/* + * DeployRootVerifier.s.sol + * + * ⚠️ FOR LOCAL TESTING ONLY — DO NOT USE IN PRODUCTION ⚠️ + * + * Deploys the ZKPassport root verifier, verifier helper, a subverifier, and mock + * proof verifiers using a plain CREATE. The production RootVerifier is deployed + * via a CREATE2 factory with a salt to get a universal multichain address. + */ + +pragma solidity ^0.8.30; + +import {console} from "forge-std/Script.sol"; +import {stdJson} from "forge-std/StdJson.sol"; +import {DeployBase} from "./DeployBase.s.sol"; +import {HonkVerifier} from "../src/mocks/MockHonkVerifier.sol"; +import {RootRegistry} from "../src/RootRegistry.sol"; +import {RootVerifier} from "../src/RootVerifier.sol"; +import {SubVerifier} from "../src/SubVerifier.sol"; +import {VerifierHelper} from "../src/VerifierHelper.sol"; +import {ProofVerifier} from "../src/lib/Types.sol"; + +contract DeployRootVerifierScript is DeployBase { + using stdJson for string; + + bytes32 public SUB_VERIFIER_VERSION; + bytes32 public CREATE2_SALT; + + bytes32[] public vkeyHashes = [ + bytes32(hex"0404040404040404040404040404040404040404040404040404040404040404"), + bytes32(hex"0505050505050505050505050505050505050505050505050505050505050505"), + bytes32(hex"0606060606060606060606060606060606060606060606060606060606060606"), + bytes32(hex"0707070707070707070707070707070707070707070707070707070707070707"), + bytes32(hex"0808080808080808080808080808080808080808080808080808080808080808"), + bytes32(hex"0909090909090909090909090909090909090909090909090909090909090909"), + bytes32(hex"1010101010101010101010101010101010101010101010101010101010101010"), + bytes32(hex"1111111111111111111111111111111111111111111111111111111111111111"), + bytes32(hex"1212121212121212121212121212121212121212121212121212121212121212"), + bytes32(hex"1313131313131313131313131313131313131313131313131313131313131313") + ]; + address[] public proofVerifiers = new address[](10); + + function setUp() public {} + + function run() public { + // Semver encoded as bytes32: first 2 bytes = major, next 2 = minor, next 2 = patch (e.g. 0x000000000001... = v0.0.1) + SUB_VERIFIER_VERSION = vm.envOr( + "SUB_VERIFIER_VERSION", bytes32(0x0000000000010000000000000000000000000000000000000000000000000000) + ); + CREATE2_SALT = vm.envOr("CREATE2_SALT", bytes32(0)); + + address adminAddress = vm.envAddress("ROOT_VERIFIER_ADMIN_ADDRESS"); + require(adminAddress != address(0), "ROOT_VERIFIER_ADMIN_ADDRESS must be set"); + + address guardianAddress = vm.envOr("ROOT_VERIFIER_GUARDIAN_ADDRESS", address(0)); + + RootRegistry rootRegistry = RootRegistry(vm.envAddress("ROOT_REGISTRY_ADDRESS")); + require(address(rootRegistry) != address(0), "ROOT_REGISTRY_ADDRESS must be set"); + + // bytes32 defaultOPRFPubKeyHash = vm.envOr("DEFAULT_OPRF_PUB_KEY_HASH", bytes32(0)); + + vm.startBroadcast(); + + // Deploy the root verifier + console.log("Deploying RootVerifier..."); + RootVerifier rootVerifier = new RootVerifier(adminAddress, guardianAddress, rootRegistry); + console.log("RootVerifier deployed at:", address(rootVerifier)); + + // Deploy the sub verifier + console.log("Deploying SubVerifier..."); + SubVerifier subVerifier = new SubVerifier{salt: CREATE2_SALT}(adminAddress, rootVerifier); + console.log("SubVerifier deployed at:", address(subVerifier)); + + // // Set the default OPRF pub key hash (skip if zero — admin can set later). + // if (defaultOPRFPubKeyHash != bytes32(0)) { + // subVerifier.setDefaultOPRFPubKeyHash(defaultOPRFPubKeyHash); + // } + + // Add the sub verifier to the root verifier + rootVerifier.addSubVerifier(SUB_VERIFIER_VERSION, subVerifier); + console.log("Sub verifier added to root verifier"); + + // Deploy the verifier helper + console.log("Deploying VerifierHelper..."); + VerifierHelper helper = new VerifierHelper{salt: CREATE2_SALT}(rootRegistry); + console.log("VerifierHelper deployed at:", address(helper)); + + // Add the helper to the root verifier + rootVerifier.addHelper(SUB_VERIFIER_VERSION, address(helper)); + console.log("Helper added to root verifier"); + + // Deploy the proof verifiers (mock HonkVerifier for each outer circuit count) + console.log("Deploying proof verifiers..."); + for (uint256 i = 0; i < 10; i++) { + proofVerifiers[i] = address(new HonkVerifier{salt: bytes32(i)}()); + console.log(" Outer proof verifier", i + 4, "deployed at:", proofVerifiers[i]); + } + + // Add proof verifiers to the sub verifier + ProofVerifier[] memory proofVerifiersArray = new ProofVerifier[](10); + for (uint256 i = 0; i < 10; i++) { + proofVerifiersArray[i] = ProofVerifier({vkeyHash: vkeyHashes[i], verifier: proofVerifiers[i]}); + } + subVerifier.addProofVerifiers(proofVerifiersArray); + console.log("Proof verifiers added to sub verifier"); + + vm.stopBroadcast(); + + _writeVerifierAddresses(rootVerifier, subVerifier, helper); + } + + function _writeVerifierAddresses(RootVerifier rootVerifier, SubVerifier subVerifier, VerifierHelper helper) + internal + { + uint256 v = uint256(SUB_VERIFIER_VERSION); + string memory versionStr = string.concat( + vm.toString(uint16(v >> 240)), ".", vm.toString(uint16(v >> 224)), ".", vm.toString(uint16(v >> 208)) + ); + + // Build proof_verifiers object + string memory pvJson = "pv"; + vm.serializeAddress(pvJson, "outer_count_4", proofVerifiers[0]); + vm.serializeAddress(pvJson, "outer_count_5", proofVerifiers[1]); + vm.serializeAddress(pvJson, "outer_count_6", proofVerifiers[2]); + vm.serializeAddress(pvJson, "outer_count_7", proofVerifiers[3]); + vm.serializeAddress(pvJson, "outer_count_8", proofVerifiers[4]); + vm.serializeAddress(pvJson, "outer_count_9", proofVerifiers[5]); + vm.serializeAddress(pvJson, "outer_count_10", proofVerifiers[6]); + vm.serializeAddress(pvJson, "outer_count_11", proofVerifiers[7]); + vm.serializeAddress(pvJson, "outer_count_12", proofVerifiers[8]); + pvJson = vm.serializeAddress(pvJson, "outer_count_13", proofVerifiers[9]); + + // Build version object: { subverifier, helper, proof_verifiers } + string memory versionJson = "version"; + vm.serializeAddress(versionJson, "subverifier", address(subVerifier)); + vm.serializeAddress(versionJson, "helper", address(helper)); + versionJson = vm.serializeString(versionJson, "proof_verifiers", pvJson); + + // Wrap in subverifiers: { "": { ... } } + string memory subverifiersJson = "subverifiers"; + subverifiersJson = vm.serializeString(subverifiersJson, versionStr, versionJson); + + // Build root_verifier section + string memory section = "root_verifier"; + vm.serializeAddress(section, "address", address(rootVerifier)); + vm.serializeString(section, "subverifiers", subverifiersJson); + section = vm.serializeUint(section, "deployed_at", block.timestamp); + + _writeToAddresses("root_verifier", section); + } +} diff --git a/packages/registry-contracts/script/DeploySanctionsRegistry.s.sol b/packages/registry-contracts/script/DeploySanctionsRegistry.s.sol index e6938873..3d58d96f 100644 --- a/packages/registry-contracts/script/DeploySanctionsRegistry.s.sol +++ b/packages/registry-contracts/script/DeploySanctionsRegistry.s.sol @@ -1,9 +1,16 @@ // SPDX-License-Identifier: Apache-2.0 -// Copyright © 2025 ZKPassport +// Copyright © 2026 ZKPassport + +/* + * DeploySanctionsRegistry.s.sol + * + * Deploys the sanctions registry. + */ + pragma solidity ^0.8.30; import {Script, console} from "forge-std/Script.sol"; -import {SanctionsRegistry} from "../src/SanctionsRegistry.sol"; +import {SanctionsRegistry} from "../src/registries/SanctionsRegistry.sol"; import {RootValidationMode} from "../src/IRegistryInstance.sol"; contract DeploySanctionsRegistryScript is Script { diff --git a/packages/registry-contracts/script/test/SeedRegistries.s.sol b/packages/registry-contracts/script/test/SeedRegistries.s.sol index 9390ea9a..50f9af7a 100644 --- a/packages/registry-contracts/script/test/SeedRegistries.s.sol +++ b/packages/registry-contracts/script/test/SeedRegistries.s.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -// Copyright © 2025 ZKPassport +// Copyright © 2026 ZKPassport pragma solidity ^0.8.30; import {Script, console} from "forge-std/Script.sol"; @@ -32,7 +32,7 @@ import {RegistryInstance} from "../../src/RegistryInstance.sol"; contract SeedRegistriesScript is Script { // These are the test fixture roots and CIDs from registry-sdk bytes32 constant DEFAULT_CERTIFICATE_REGISTRY_ROOT = - 0x03c239fdfafd89a568efac9175c32b998e208c4ab453d3615a31c83e65c90686; + 0x23e802a448e80b578b81ed587e325cd0dcfb0dac0e6cc6dd6464012fdcdcfd2d; bytes32 constant DEFAULT_CIRCUIT_REGISTRY_ROOT = 0x068f6e356f993bd2afaf3d3466efff1dd4bc06f61952ac336085b832b93289a7; bytes32 constant DEFAULT_SANCTIONS_REGISTRY_ROOT = 0x099699583ea7729a4a05821667645e927b74feb4e6e5382c6e4370e35ed2b23c; diff --git a/packages/registry-contracts/script/test/deploy-protocol-controller.sh b/packages/registry-contracts/script/test/deploy-protocol-controller.sh new file mode 100755 index 00000000..9115e1b0 --- /dev/null +++ b/packages/registry-contracts/script/test/deploy-protocol-controller.sh @@ -0,0 +1,64 @@ +#!/bin/bash + +# Test deployment script for the ProtocolController +# ⚠️ FOR TESTING ONLY - DO NOT USE IN PRODUCTION ⚠️ +# This script deploys the ProtocolController and transfers admin of RootRegistry +# and RootVerifier to the ProtocolController address. +# Expects ROOT_REGISTRY_ADDRESS and ROOT_VERIFIER_ADDRESS to already be set +# (run deploy-root-registry.sh and deploy-root-verifier.sh first) + +set -e + +# Hardcoded for test environment +export CHAIN_ID=31337 +export RPC_URL=${RPC_URL:-http://localhost:8545} + +export DEPLOYER_PRIVATE_KEY=${DEPLOYER_PRIVATE_KEY:-0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80} + +export PROTOCOL_CONTROLLER_ADMIN=${PROTOCOL_CONTROLLER_ADMIN:-0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266} +export ROOT_REGISTRY_OPERATOR_ADDRESS=${ROOT_REGISTRY_OPERATOR_ADDRESS:-0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc} +export ROOT_VERIFIER_OPERATOR_ADDRESS=${ROOT_VERIFIER_OPERATOR_ADDRESS:-0x976EA74026E726554dB657fA54763abd0C3a0aa9} + +export ROOT_REGISTRY_ADMIN_PRIVATE_KEY=${ROOT_REGISTRY_ADMIN_PRIVATE_KEY:-0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80} +export ROOT_VERIFIER_ADMIN_PRIVATE_KEY=${ROOT_VERIFIER_ADMIN_PRIVATE_KEY:-0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80} + +if [ -z "$ROOT_REGISTRY_ADDRESS" ]; then + echo "Error: ROOT_REGISTRY_ADDRESS must be set" + echo "Deploy the registry contracts first with deploy-root-registry.sh and export ROOT_REGISTRY_ADDRESS" + exit 1 +fi + +if [ -z "$ROOT_VERIFIER_ADDRESS" ]; then + echo "Error: ROOT_VERIFIER_ADDRESS must be set" + echo "Deploy the verifier contracts first with deploy-root-verifier.sh and export ROOT_VERIFIER_ADDRESS" + exit 1 +fi + +# Deploy the ProtocolController contract +echo "Deploying ProtocolController..." +forge script script/DeployProtocolController.s.sol:DeployProtocolControllerScript \ + --rpc-url $RPC_URL \ + --private-key $DEPLOYER_PRIVATE_KEY \ + --broadcast + +export PROTOCOL_CONTROLLER_ADDRESS=$(cat broadcast/DeployProtocolController.s.sol/$CHAIN_ID/run-latest.json | jq -r '.transactions[] | select(.transactionType=="CREATE") | .contractAddress') +echo "" +echo "ProtocolController deployed at: $PROTOCOL_CONTROLLER_ADDRESS" + +# Transfer RootRegistry admin to the ProtocolController +echo "Transferring RootRegistry admin to ProtocolController..." +cast send $ROOT_REGISTRY_ADDRESS "transferAdmin(address)" $PROTOCOL_CONTROLLER_ADDRESS --rpc-url $RPC_URL --private-key $ROOT_REGISTRY_ADMIN_PRIVATE_KEY + +# Transfer RootVerifier admin to the ProtocolController +echo "Transferring RootVerifier admin to ProtocolController..." +cast send $ROOT_VERIFIER_ADDRESS "transferAdmin(address)" $PROTOCOL_CONTROLLER_ADDRESS --rpc-url $RPC_URL --private-key $ROOT_VERIFIER_ADMIN_PRIVATE_KEY + +# Verify the admin transfers +REGISTRY_ADMIN=$(cast call $ROOT_REGISTRY_ADDRESS "admin()" --rpc-url $RPC_URL) +echo "RootRegistry admin: $REGISTRY_ADMIN" + +VERIFIER_ADMIN=$(cast call $ROOT_VERIFIER_ADDRESS "admin()" --rpc-url $RPC_URL) +echo "RootVerifier admin: $VERIFIER_ADMIN" + +CONTROLLER_ADMIN=$(cast call $PROTOCOL_CONTROLLER_ADDRESS "admin()" --rpc-url $RPC_URL) +echo "ProtocolController admin: $CONTROLLER_ADMIN" diff --git a/packages/registry-contracts/script/test/deploy.sh b/packages/registry-contracts/script/test/deploy-root-registry.sh similarity index 95% rename from packages/registry-contracts/script/test/deploy.sh rename to packages/registry-contracts/script/test/deploy-root-registry.sh index c7a31fc1..2f9a3b0c 100755 --- a/packages/registry-contracts/script/test/deploy.sh +++ b/packages/registry-contracts/script/test/deploy-root-registry.sh @@ -2,7 +2,8 @@ # Test deployment script for integration tests # ⚠️ FOR TESTING ONLY - DO NOT USE IN PRODUCTION ⚠️ -# This script deploys contracts to a local Anvil instance for testing purposes +# This script deploys the RootRegistry, RegistryHelper, and sub-registries (CertificateRegistry, CircuitRegistry, and SanctionsRegistry) +# to a local Anvil instance for testing purposes set -e @@ -50,6 +51,11 @@ forge script script/DeployRegistryHelper.s.sol:DeployRegistryHelperScript --rpc- REGISTRY_HELPER_ADDRESS=$(cat broadcast/DeployRegistryHelper.s.sol/$CHAIN_ID/run-latest.json | jq -r '.transactions[] | select(.transactionType=="CREATE") | .contractAddress') echo "RegistryHelper deployed at: $REGISTRY_HELPER_ADDRESS" +if [[ " $* " == *" --skip-registries "* ]]; then + echo "Skipping registry deployments..." + return +fi + # Deploy the CertificateRegistry contract echo "Deploying CertificateRegistry..." forge script script/DeployCertificateRegistry.s.sol:DeployCertificateRegistryScript --rpc-url $RPC_URL --private-key $DEPLOYER_PRIVATE_KEY --broadcast diff --git a/packages/registry-contracts/script/test/deploy-root-verifier.sh b/packages/registry-contracts/script/test/deploy-root-verifier.sh new file mode 100755 index 00000000..8fe4aceb --- /dev/null +++ b/packages/registry-contracts/script/test/deploy-root-verifier.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +# Test deployment script for RootVerifier, SubVerifier, VerifierHelper, and ProofVerifiers +# ⚠️ FOR TESTING ONLY - DO NOT USE IN PRODUCTION ⚠️ +# This script deploys all verifier contracts to a local Anvil instance +# Expects ROOT_REGISTRY_ADDRESS to already be deployed (run deploy-root-registry.sh first) + +set -e + +# Hardcoded for test environment +export CHAIN_ID=31337 +export RPC_URL=${RPC_URL:-http://localhost:8545} + +export DEPLOYER_PRIVATE_KEY=${DEPLOYER_PRIVATE_KEY:-0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80} + +export ROOT_VERIFIER_ADMIN_ADDRESS=${ROOT_VERIFIER_ADMIN_ADDRESS:-0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266} +export ROOT_VERIFIER_GUARDIAN_ADDRESS=${ROOT_VERIFIER_GUARDIAN_ADDRESS:-0x0000000000000000000000000000000000000000} + +if [ -z "$ROOT_REGISTRY_ADDRESS" ]; then + echo "Error: ROOT_REGISTRY_ADDRESS must be set" + echo "Deploy the registry contracts first with deploy-root-registry.sh and export ROOT_REGISTRY_ADDRESS" + exit 1 +fi + +# Deploy all verifier contracts (RootVerifier + VerifierHelper + SubVerifier + proof verifiers) +echo "Deploying ZKPassport verifier stack..." +forge script script/DeployRootVerifier.s.sol:DeployRootVerifierScript \ + --rpc-url $RPC_URL \ + --private-key $DEPLOYER_PRIVATE_KEY \ + --broadcast + +# Extract the RootVerifier address (first CREATE transaction) +export ROOT_VERIFIER_ADDRESS=$(cat broadcast/DeployRootVerifier.s.sol/$CHAIN_ID/run-latest.json | jq -r '[.transactions[] | select(.transactionType=="CREATE")][0].contractAddress') +echo "" +echo "RootVerifier deployed at: $ROOT_VERIFIER_ADDRESS" + +# Verify deployment +VERIFIER_ADMIN=$(cast call $ROOT_VERIFIER_ADDRESS "admin()" --rpc-url $RPC_URL) +echo "Verified admin: $VERIFIER_ADMIN" + +VERIFIER_REGISTRY=$(cast call $ROOT_VERIFIER_ADDRESS "rootRegistry()" --rpc-url $RPC_URL) +echo "Verified rootRegistry: $VERIFIER_REGISTRY" + +SUBVERIFIER_COUNT=$(cast call $ROOT_VERIFIER_ADDRESS "subverifierCount()" --rpc-url $RPC_URL) +echo "Verified subverifierCount: $SUBVERIFIER_COUNT" + +HELPER_COUNT=$(cast call $ROOT_VERIFIER_ADDRESS "helperCount()" --rpc-url $RPC_URL) +echo "Verified helperCount: $HELPER_COUNT" + +# Check for deployment artifact +if [ -f deployments/addresses-$CHAIN_ID.json ]; then + echo "" + echo "Deployment artifact written to deployments/addresses-$CHAIN_ID.json" +fi diff --git a/packages/registry-contracts/script/test/run-local.sh b/packages/registry-contracts/script/test/run-local.sh index 04ee6bda..5abe4c54 100755 --- a/packages/registry-contracts/script/test/run-local.sh +++ b/packages/registry-contracts/script/test/run-local.sh @@ -26,8 +26,12 @@ trap cleanup EXIT SIGINT SIGTERM sleep 1 # Run the deployment and seeding scripts -./script/test/deploy.sh -./script/test/seed-registries.sh +source ./script/test/deploy-root-registry.sh +source ./script/test/deploy-root-verifier.sh +source ./script/test/deploy-protocol-controller.sh +if [[ " $* " != *" --no-seed "* ]]; then + source ./script/test/seed-registries.sh +fi echo "Test environment ready!" echo "Anvil is running on http://localhost:8545 (Chain ID: 31337)" diff --git a/packages/registry-contracts/script/test/seed-registries.sh b/packages/registry-contracts/script/test/seed-registries.sh index 5bd957f3..fe7c40d1 100755 --- a/packages/registry-contracts/script/test/seed-registries.sh +++ b/packages/registry-contracts/script/test/seed-registries.sh @@ -13,7 +13,7 @@ export ETHERSCAN_API_KEY=${ETHERSCAN_API_KEY:-dummy} export ORACLE_ADDRESS=${ORACLE_ADDRESS:-0x70997970C51812dc3A010C7d01b50e0d17dc79C8} export ORACLE_PRIVATE_KEY=${ORACLE_PRIVATE_KEY:-0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d} -export CERTIFICATE_REGISTRY_ROOT=${CERTIFICATE_REGISTRY_ROOT:-0x03c239fdfafd89a568efac9175c32b998e208c4ab453d3615a31c83e65c90686} +export CERTIFICATE_REGISTRY_ROOT=${CERTIFICATE_REGISTRY_ROOT:-0x23e802a448e80b578b81ed587e325cd0dcfb0dac0e6cc6dd6464012fdcdcfd2d} export CIRCUIT_REGISTRY_ROOT=${CIRCUIT_REGISTRY_ROOT:-0x068f6e356f993bd2afaf3d3466efff1dd4bc06f61952ac336085b832b93289a7} export SANCTIONS_REGISTRY_ROOT=${SANCTIONS_REGISTRY_ROOT:-0x099699583ea7729a4a05821667645e927b74feb4e6e5382c6e4370e35ed2b23c} diff --git a/packages/registry-contracts/src/IProofVerifier.sol b/packages/registry-contracts/src/IProofVerifier.sol new file mode 100644 index 00000000..5cdc10cd --- /dev/null +++ b/packages/registry-contracts/src/IProofVerifier.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright © 2026 ZKPassport +/* + ______ _ _ _____ _______ _______ _______ _____ _____ ______ _______ + ____/ |____/ |_____] |_____| |______ |______ |_____] | | |_____/ | + /_____ | \_ | | | ______| ______| | |_____| | \_ | + +*/ + +pragma solidity ^0.8.30; + +interface IProofVerifier { + function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool); +} diff --git a/packages/registry-contracts/src/IRegistryInstance.sol b/packages/registry-contracts/src/IRegistryInstance.sol index 8ef2d64d..68a7e2a5 100644 --- a/packages/registry-contracts/src/IRegistryInstance.sol +++ b/packages/registry-contracts/src/IRegistryInstance.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -// Copyright © 2025 ZKPassport +// Copyright © 2026 ZKPassport /* ______ _ _ _____ _______ _______ _______ _____ _____ ______ _______ ____/ |____/ |_____] |_____| |______ |______ |_____] | | |_____/ | diff --git a/packages/registry-contracts/src/ProtocolController.sol b/packages/registry-contracts/src/ProtocolController.sol new file mode 100644 index 00000000..b28b4ef5 --- /dev/null +++ b/packages/registry-contracts/src/ProtocolController.sol @@ -0,0 +1,225 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright © 2026 ZKPassport +/* + ______ _ _ _____ _______ _______ _______ _____ _____ ______ _______ + ____/ |____/ |_____] |_____| |______ |______ |_____] | | |_____/ | + /_____ | \_ | | | ______| ______| | |_____| | \_ | + +*/ + +pragma solidity ^0.8.30; + +interface IRootRegistryAdmin { + function transferAdmin(address newAdmin) external; + function setGuardian(address newGuardian) external; + function addRegistry(bytes32 registryId, address registryAddress) external; + function updateRegistry(bytes32 registryId, address newAddress) external; + function removeRegistry(bytes32 registryId) external; + function updateConfig(bytes32 key, bytes32 value) external; + function pause() external; + function unpause() external; +} + +interface IRootVerifierAdmin { + function transferAdmin(address newAdmin) external; + function setGuardian(address newGuardian) external; + function addSubVerifier(bytes32 version, address subVerifier) external; + function removeSubVerifier(bytes32 version) external; + function updateSubVerifier(bytes32 version, address newSubVerifier) external; + function addHelper(bytes32 version, address newHelper) external; + function removeHelper(bytes32 version) external; + function updateHelper(bytes32 version, address newHelper) external; + function updateConfig(bytes32 key, bytes32 value) external; + function pause() external; + function unpause() external; +} + +/** + * @title ProtocolController + * @dev Manages operator roles for ZKPassport RootVerifier and RootRegistry contracts. + * The admin can reassign operator roles and transfer admin on the underlying + * contracts back to itself. Operators can call the respective admin functions + * on the underlying contracts through this controller. + */ +contract ProtocolController { + address public admin; + address public pendingAdmin; + address public rootRegistryOperator; + address public rootVerifierOperator; + + IRootRegistryAdmin public rootRegistry; + IRootVerifierAdmin public rootVerifier; + + event AdminTransferStarted(address indexed currentAdmin, address indexed pendingAdmin); + event AdminTransferred(address indexed oldAdmin, address indexed newAdmin); + event RootRegistryOperatorUpdated(address indexed oldOperator, address indexed newOperator); + event RootVerifierOperatorUpdated(address indexed oldOperator, address indexed newOperator); + + /// @dev Constructor to initialize the protocol controller + /// @param _admin The admin address + /// @param _rootRegistry The RootRegistry contract address + /// @param _rootRegistryOperator The operator address for the RootRegistry + /// @param _rootVerifier The RootVerifier contract address + /// @param _rootVerifierOperator The operator address for the RootVerifier + constructor( + address _admin, + address _rootRegistry, + address _rootRegistryOperator, + address _rootVerifier, + address _rootVerifierOperator + ) { + require(_admin != address(0), "Admin cannot be zero address"); + admin = _admin; + rootRegistry = IRootRegistryAdmin(_rootRegistry); + rootRegistryOperator = _rootRegistryOperator; + rootVerifier = IRootVerifierAdmin(_rootVerifier); + rootVerifierOperator = _rootVerifierOperator; + } + + modifier onlyAdmin() { + require(msg.sender == admin, "Not authorized: admin only"); + _; + } + + modifier onlyAdminOrRootRegistryOperator() { + require( + msg.sender == admin || msg.sender == rootRegistryOperator, + "Not authorized: admin or root registry operator only" + ); + _; + } + + modifier onlyAdminOrRootVerifierOperator() { + require( + msg.sender == admin || msg.sender == rootVerifierOperator, + "Not authorized: admin or root verifier operator only" + ); + _; + } + + // ===== Admin functions ===== + + /// @notice Initiates a two-step admin transfer to a new address + function transferAdmin(address newAdmin) external onlyAdmin { + require(newAdmin != address(0), "Admin cannot be zero address"); + pendingAdmin = newAdmin; + emit AdminTransferStarted(admin, newAdmin); + } + + /// @notice Completes the admin transfer; must be called by the pending admin + function acceptAdmin() external { + require(msg.sender == pendingAdmin, "Not authorized: pending admin only"); + address oldAdmin = admin; + admin = pendingAdmin; + pendingAdmin = address(0); + emit AdminTransferred(oldAdmin, msg.sender); + } + + /// @notice Restores admin of the RootRegistry contract from this controller back to the admin + function restoreRootRegistryAdmin() external onlyAdmin { + rootRegistry.transferAdmin(admin); + } + + /// @notice Restores admin of the RootVerifier contract from this controller back to the admin + function restoreRootVerifierAdmin() external onlyAdmin { + rootVerifier.transferAdmin(admin); + } + + /// @notice Sets the operator address for the RootRegistry + function setRootRegistryOperator(address newOperator) external onlyAdmin { + address oldOperator = rootRegistryOperator; + rootRegistryOperator = newOperator; + emit RootRegistryOperatorUpdated(oldOperator, newOperator); + } + + /// @notice Sets the operator address for the RootVerifier + function setRootVerifierOperator(address newOperator) external onlyAdmin { + address oldOperator = rootVerifierOperator; + rootVerifierOperator = newOperator; + emit RootVerifierOperatorUpdated(oldOperator, newOperator); + } + + // ===== Root Registry Operator functions ===== + + function rootRegistry_addRegistry(bytes32 registryId, address registryAddress) + external + onlyAdminOrRootRegistryOperator + { + rootRegistry.addRegistry(registryId, registryAddress); + } + + function rootRegistry_updateRegistry(bytes32 registryId, address newAddress) + external + onlyAdminOrRootRegistryOperator + { + rootRegistry.updateRegistry(registryId, newAddress); + } + + function rootRegistry_removeRegistry(bytes32 registryId) external onlyAdminOrRootRegistryOperator { + rootRegistry.removeRegistry(registryId); + } + + function rootRegistry_setGuardian(address newGuardian) external onlyAdminOrRootRegistryOperator { + rootRegistry.setGuardian(newGuardian); + } + + function rootRegistry_updateConfig(bytes32 key, bytes32 value) external onlyAdminOrRootRegistryOperator { + rootRegistry.updateConfig(key, value); + } + + function rootRegistry_pause() external onlyAdminOrRootRegistryOperator { + rootRegistry.pause(); + } + + function rootRegistry_unpause() external onlyAdminOrRootRegistryOperator { + rootRegistry.unpause(); + } + + // ===== Root Verifier Operator functions ===== + + function rootVerifier_addSubVerifier(bytes32 version, address subVerifier) + external + onlyAdminOrRootVerifierOperator + { + rootVerifier.addSubVerifier(version, subVerifier); + } + + function rootVerifier_removeSubVerifier(bytes32 version) external onlyAdminOrRootVerifierOperator { + rootVerifier.removeSubVerifier(version); + } + + function rootVerifier_updateSubVerifier(bytes32 version, address newSubVerifier) + external + onlyAdminOrRootVerifierOperator + { + rootVerifier.updateSubVerifier(version, newSubVerifier); + } + + function rootVerifier_addHelper(bytes32 version, address newHelper) external onlyAdminOrRootVerifierOperator { + rootVerifier.addHelper(version, newHelper); + } + + function rootVerifier_removeHelper(bytes32 version) external onlyAdminOrRootVerifierOperator { + rootVerifier.removeHelper(version); + } + + function rootVerifier_updateHelper(bytes32 version, address newHelper) external onlyAdminOrRootVerifierOperator { + rootVerifier.updateHelper(version, newHelper); + } + + function rootVerifier_setGuardian(address newGuardian) external onlyAdminOrRootVerifierOperator { + rootVerifier.setGuardian(newGuardian); + } + + function rootVerifier_updateConfig(bytes32 key, bytes32 value) external onlyAdminOrRootVerifierOperator { + rootVerifier.updateConfig(key, value); + } + + function rootVerifier_pause() external onlyAdminOrRootVerifierOperator { + rootVerifier.pause(); + } + + function rootVerifier_unpause() external onlyAdminOrRootVerifierOperator { + rootVerifier.unpause(); + } +} diff --git a/packages/registry-contracts/src/RegistryHelper.sol b/packages/registry-contracts/src/RegistryHelper.sol index 8c5ec405..716650b1 100644 --- a/packages/registry-contracts/src/RegistryHelper.sol +++ b/packages/registry-contracts/src/RegistryHelper.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -// Copyright © 2025 ZKPassport +// Copyright © 2026 ZKPassport /* ______ _ _ _____ _______ _______ _______ _____ _____ ______ _______ ____/ |____/ |_____] |_____| |______ |______ |_____] | | |_____/ | @@ -36,6 +36,46 @@ contract RegistryHelper { bool revoked; uint256 leaves; bytes32 cid; + bytes32 metadata1; + bytes32 metadata2; + bytes32 metadata3; + } + + /** + * @dev Build a RootDetails entry for a given root by reading from the registry's + * consolidated `historicalRoots` mapping. Extracted to avoid stack-too-deep errors + * in callers that would otherwise hold all 10 fields as locals. + */ + function _buildRootDetails(IRegistryInstance registry, bytes32 root, uint256 index) + private + view + returns (RootDetails memory details) + { + // Read the root details from the registry + ( + uint256 validFrom, + uint256 validTo, + bool revoked, + uint256 leaves, + bytes32 cid, + bytes32 metadata1, + bytes32 metadata2, + bytes32 metadata3 + ) = registry.historicalRoots(root); + + // Return the RootDetails entry + details = RootDetails({ + index: index, + root: root, + validFrom: validFrom, + validTo: validTo, + revoked: revoked, + leaves: leaves, + cid: cid, + metadata1: metadata1, + metadata2: metadata2, + metadata3: metadata3 + }); } /** @@ -80,22 +120,8 @@ contract RegistryHelper { // Populate the results array for (uint256 i = 0; i < actualLimit; i++) { bytes32 rootHash = registry.rootByIndex(currentIndex); - - // Get the root details - accessing all fields from the consolidated HistoricalRoot struct - (uint256 validFrom, uint256 validTo, bool revoked, uint256 leaves, bytes32 cid,,,) = - registry.historicalRoots(rootHash); - // Add to results - roots[i] = RootDetails({ - index: currentIndex, - root: rootHash, - validFrom: validFrom, - validTo: validTo, - revoked: revoked, - leaves: leaves, - cid: cid - }); - + roots[i] = _buildRootDetails(registry, rootHash, currentIndex); // Move to the next index currentIndex++; } @@ -147,22 +173,10 @@ contract RegistryHelper { bytes32 latestRoot = registry.latestRoot(); require(latestRoot != bytes32(0), "No roots exist yet"); - // Get the consolidated data from historicalRoots - (uint256 validFrom, uint256 validTo, bool revoked, uint256 leaves, bytes32 cid,,,) = - registry.historicalRoots(latestRoot); - // Get the index of the latest root uint256 index = registry.indexByRoot(latestRoot); - - return RootDetails({ - index: index, - root: latestRoot, - validFrom: validFrom, - validTo: validTo, - revoked: revoked, - leaves: leaves, - cid: cid - }); + // Build and return the RootDetails entry + return _buildRootDetails(registry, latestRoot, index); } /** @@ -178,13 +192,8 @@ contract RegistryHelper { bytes32 root = registry.rootByIndex(index); require(root != bytes32(0), "Root not found"); - // Get the consolidated data from historicalRoots - (uint256 validFrom, uint256 validTo, bool revoked, uint256 leaves, bytes32 cid,,,) = - registry.historicalRoots(root); - - return RootDetails({ - index: index, root: root, validFrom: validFrom, validTo: validTo, revoked: revoked, leaves: leaves, cid: cid - }); + // Return the RootDetails entry + return _buildRootDetails(registry, root, index); } /** @@ -201,13 +210,8 @@ contract RegistryHelper { uint256 index = registry.indexByRoot(root); require(index != 0, "Root not found"); - // Get the consolidated data from historicalRoots - (uint256 validFrom, uint256 validTo, bool revoked, uint256 leaves, bytes32 cid,,,) = - registry.historicalRoots(root); - - return RootDetails({ - index: index, root: root, validFrom: validFrom, validTo: validTo, revoked: revoked, leaves: leaves, cid: cid - }); + // Return the RootDetails entry + return _buildRootDetails(registry, root, index); } /** diff --git a/packages/registry-contracts/src/RegistryInstance.sol b/packages/registry-contracts/src/RegistryInstance.sol index 9b69c3bf..7011ce97 100644 --- a/packages/registry-contracts/src/RegistryInstance.sol +++ b/packages/registry-contracts/src/RegistryInstance.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -// Copyright © 2025 ZKPassport +// Copyright © 2026 ZKPassport /* ______ _ _ _____ _______ _______ _______ _____ _____ ______ _______ ____/ |____/ |_____] |_____| |______ |______ |_____] | | |_____/ | diff --git a/packages/registry-contracts/src/RootRegistry.sol b/packages/registry-contracts/src/RootRegistry.sol index af74ce17..0f9798a3 100644 --- a/packages/registry-contracts/src/RootRegistry.sol +++ b/packages/registry-contracts/src/RootRegistry.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -// Copyright © 2025 ZKPassport +// Copyright © 2026 ZKPassport /* ______ _ _ _____ _______ _______ _______ _____ _____ ______ _______ ____/ |____/ |_____] |_____| |______ |______ |_____] | | |_____/ | diff --git a/packages/registry-contracts/src/RootVerifier.sol b/packages/registry-contracts/src/RootVerifier.sol new file mode 100644 index 00000000..bb57a935 --- /dev/null +++ b/packages/registry-contracts/src/RootVerifier.sol @@ -0,0 +1,257 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright © 2026 ZKPassport +/* + ______ _ _ _____ _______ _______ _______ _____ _____ ______ _______ + ____/ |____/ |_____] |_____| |______ |______ |_____] | | |_____/ | + /_____ | \_ | | | ______| ______| | |_____| | \_ | + +*/ + +pragma solidity ^0.8.30; + +import {RootRegistry} from "./RootRegistry.sol"; +import {SubVerifier} from "./SubVerifier.sol"; +import {VerifierHelper} from "./VerifierHelper.sol"; +import {ProofVerificationParams} from "./lib/Types.sol"; + +/** + * @title ZKPassport Root Verifier + * @notice Main entry point for verifying ZKPassport identity proofs + */ +contract RootVerifier { + address public admin; + address public guardian; + bool public paused; + + // ZKPassport Root Registry + RootRegistry public rootRegistry; + + // Subverifier mapping + mapping(bytes32 => SubVerifier) public subverifiers; + // Counter for the number of subverifiers + uint256 public subverifierCount; + + // Helper mapping + mapping(bytes32 => VerifierHelper) public helpers; + // Counter for the number of helpers + uint256 public helperCount; + + // Config mapping + mapping(bytes32 key => bytes32 value) public config; + + // Events + event RootVerifierDeployed(address admin, address guardian, address rootRegistry); + event AdminUpdated(address indexed oldAdmin, address indexed newAdmin); + event GuardianUpdated(address indexed oldGuardian, address indexed newGuardian); + event RootRegistryUpdated(address indexed oldRootRegistry, address indexed newRootRegistry); + event SubVerifierAdded(bytes32 indexed version, address indexed subVerifier); + event SubVerifierRemoved(bytes32 indexed version, address indexed subVerifier); + event SubVerifierUpdated(bytes32 indexed version, address indexed oldSubVerifier, address indexed newSubVerifier); + event HelperAdded(bytes32 indexed version, address indexed helper); + event HelperRemoved(bytes32 indexed version, address indexed helper); + event HelperUpdated(bytes32 indexed version, address indexed oldHelper, address indexed newHelper); + event PausedStatusChanged(bool paused); + event ConfigUpdated(bytes32 indexed key, bytes32 oldValue, bytes32 newValue); + + /** + * @notice Constructor + * @param _admin The admin address + * @param _guardian The guardian address + * @param _rootRegistry The root registry address + */ + constructor(address _admin, address _guardian, RootRegistry _rootRegistry) { + require(_admin != address(0), "Admin cannot be zero address"); + admin = _admin; + guardian = _guardian; + rootRegistry = _rootRegistry; + emit RootVerifierDeployed(admin, guardian, address(_rootRegistry)); + } + + /** + * @notice Verifies a ZKPassport zero-knowledge proof + * @dev This function is called by the root verifier to verify a proof for a specific version + * @param params The proof verification parameters + * @return valid True if the proof is valid or false otherwise + * @return uniqueIdentifier The unique identifier associated with the ID used to generate the proof + * @return helper The helper for the calling contract to use to verify the committed inputs + */ + function verify(ProofVerificationParams calldata params) + external + view + whenNotPaused + returns (bool valid, bytes32 uniqueIdentifier, VerifierHelper helper) + { + SubVerifier subverifier = subverifiers[params.version]; + require(address(subverifier) != address(0), "Subverifier not found for version"); + (valid, uniqueIdentifier) = subverifier.verify(rootRegistry, params); + return (valid, uniqueIdentifier, helpers[params.version]); + } + + modifier onlyAdmin() { + require(msg.sender == admin, "Not authorized: admin only"); + _; + } + + modifier onlyAdminOrGuardian() { + require(msg.sender == admin || msg.sender == guardian, "Not authorized: admin or guardian only"); + _; + } + + modifier whenNotPaused() { + require(!paused, "Root verifier is paused"); + _; + } + + /** + * @notice Transfers the admin role to a new address + * @param newAdmin The new admin address + */ + function transferAdmin(address newAdmin) external onlyAdmin { + require(newAdmin != address(0), "Admin cannot be zero address"); + address oldAdmin = admin; + admin = newAdmin; + emit AdminUpdated(oldAdmin, newAdmin); + } + + /** + * @notice Sets the guardian role to a new address + * @param newGuardian The new guardian address + */ + function setGuardian(address newGuardian) external onlyAdmin { + address oldGuardian = guardian; + guardian = newGuardian; + emit GuardianUpdated(oldGuardian, newGuardian); + } + + /** + * @notice Adds a subverifier for a specific version + * @param version The version identifier + * @param subVerifier The address of the subverifier + */ + function addSubVerifier(bytes32 version, SubVerifier subVerifier) external onlyAdmin { + require(address(subVerifier) != address(0), "Subverifier cannot be zero address"); + require(version != bytes32(0), "Version cannot be zero"); + require(address(subverifiers[version]) == address(0), "Subverifier already exists for version"); + subverifiers[version] = subVerifier; + subverifierCount++; + emit SubVerifierAdded(version, address(subVerifier)); + } + + /** + * @notice Removes a subverifier for a specific version + * @param version The version identifier + */ + function removeSubVerifier(bytes32 version) external onlyAdmin { + require(version != bytes32(0), "Version cannot be zero"); + address subVerifier = address(subverifiers[version]); + require(subVerifier != address(0), "Subverifier not found for version"); + delete subverifiers[version]; + subverifierCount--; + emit SubVerifierRemoved(version, subVerifier); + } + + /** + * @notice Updates a subverifier for a specific version + * @param version The version identifier + * @param newSubVerifier The address of the new subverifier + */ + function updateSubVerifier(bytes32 version, address newSubVerifier) external onlyAdmin { + require(version != bytes32(0), "Version cannot be zero"); + require(newSubVerifier != address(0), "Subverifier cannot be zero address"); + require(address(subverifiers[version]) != address(0), "Subverifier not found for version"); + address oldSubVerifier = address(subverifiers[version]); + subverifiers[version] = SubVerifier(newSubVerifier); + emit SubVerifierUpdated(version, oldSubVerifier, newSubVerifier); + } + + /** + * @notice Gets the subverifier address for a specific version + * @dev Returns zero address if no subverifier exists for the given version + * @param version The version identifier + * @return The address of the subverifier contract, or zero address if not found + */ + function getSubVerifier(bytes32 version) external view returns (address) { + return address(subverifiers[version]); + } + + /** + * @notice Adds a helper for a specific version + * @param version The version identifier + * @param newHelper The address of the helper + */ + function addHelper(bytes32 version, address newHelper) external onlyAdmin { + require(newHelper != address(0), "Helper cannot be zero address"); + require(version != bytes32(0), "Version cannot be zero"); + require(address(helpers[version]) == address(0), "Helper already exists for version"); + helpers[version] = VerifierHelper(newHelper); + helperCount++; + emit HelperAdded(version, newHelper); + } + + /** + * @notice Removes a helper for a specific version + * @param version The version identifier + */ + function removeHelper(bytes32 version) external onlyAdmin { + require(version != bytes32(0), "Version cannot be zero"); + address helper = address(helpers[version]); + require(helper != address(0), "Helper not found for version"); + delete helpers[version]; + helperCount--; + emit HelperRemoved(version, helper); + } + + /** + * @notice Updates a helper for a specific version + * @param version The version identifier + * @param newHelper The address of the new helper + */ + function updateHelper(bytes32 version, address newHelper) external onlyAdmin { + require(version != bytes32(0), "Version cannot be zero"); + require(newHelper != address(0), "Helper cannot be zero address"); + require(address(helpers[version]) != address(0), "Helper not found for version"); + address oldHelper = address(helpers[version]); + helpers[version] = VerifierHelper(newHelper); + emit HelperUpdated(version, oldHelper, newHelper); + } + + /** + * @notice Gets the helper address for a specific version + * @dev Returns zero address if no helper exists for the given version + * @param version The version identifier + * @return The address of the helper contract, or zero address if not found + */ + function getHelper(bytes32 version) external view returns (address) { + return address(helpers[version]); + } + + /** + * @notice Update a config value + * @param key The config key + * @param value The config value + */ + function updateConfig(bytes32 key, bytes32 value) external onlyAdmin { + bytes32 oldValue = config[key]; + config[key] = value; + emit ConfigUpdated(key, oldValue, value); + } + + /** + * @notice Pause the root verifier + * @dev Only admin or guardian can pause the root verifier + * @dev This is a security measure to pause all proof verification operations in the event of an emergency + */ + function pause() external onlyAdminOrGuardian { + paused = true; + emit PausedStatusChanged(true); + } + + /** + * @notice Unpause the root verifier + * @dev Only admin can unpause the root verifier + */ + function unpause() external onlyAdmin { + paused = false; + emit PausedStatusChanged(false); + } +} diff --git a/packages/registry-contracts/src/SubVerifier.sol b/packages/registry-contracts/src/SubVerifier.sol new file mode 100644 index 00000000..4c9410b8 --- /dev/null +++ b/packages/registry-contracts/src/SubVerifier.sol @@ -0,0 +1,301 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright © 2026 ZKPassport +/* + ______ _ _ _____ _______ _______ _______ _____ _____ ______ _______ + ____/ |____/ |_____] |_____| |______ |______ |_____] | | |_____/ | + /_____ | \_ | | | ______| ______| | |_____| | \_ | + +*/ + +pragma solidity ^0.8.30; + +import {RootVerifier} from "./RootVerifier.sol"; +import {RootRegistry} from "./RootRegistry.sol"; +import {IProofVerifier} from "./IProofVerifier.sol"; +import {ProofVerificationParams, NullifierType, ProofVerifier} from "./lib/Types.sol"; +import {PublicInput, RegistryID} from "./lib/Constants.sol"; +import {DateUtils} from "./lib/DateUtils.sol"; +import {StringUtils} from "./lib/StringUtils.sol"; + +contract SubVerifier { + address public admin; + bool public paused; + + // The address of the root verifier + RootVerifier public rootVerifier; + + // Mapping from vkey hash of each outer circuit to its proof verifier (UltraHonk verifier) address + // Maps use the vkeyHash of the outer circuit to the ProofVerifier contract address + mapping(bytes32 => address) public proofVerifiers; + + // Hash of the protocol-default OPRF public key. + // bytes32 public defaultOPRFPubKeyHash; + + event SubVerifierDeployed(address indexed admin, address indexed rootVerifier); + event AdminUpdated(address indexed oldAdmin, address indexed newAdmin); + event ProofVerifierAdded(address indexed proofVerifier, bytes32 indexed vkeyHash); + event ProofVerifierRemoved(address indexed proofVerifier, bytes32 indexed vkeyHash); + event PausedStatusChanged(bool paused); + + // event DefaultOPRFPubKeyHashUpdated(bytes32 oldHash, bytes32 newHash); + + /** + * @dev Constructor + * @param _admin The admin address + * @param _rootVerifier The address of the ZKPassport root verifier + */ + constructor(address _admin, RootVerifier _rootVerifier) { + require(_admin != address(0), "Admin cannot be zero address"); + admin = _admin; + require(address(_rootVerifier) != address(0), "Root verifier cannot be zero address"); + rootVerifier = _rootVerifier; + emit SubVerifierDeployed(admin, address(_rootVerifier)); + } + + modifier onlyAdmin() { + require(msg.sender == admin, "Not authorized: admin only"); + _; + } + + modifier onlyRootVerifier() { + require(msg.sender == address(rootVerifier), "This function can only be called from the root verifier"); + _; + } + + modifier whenNotPaused() { + require(!paused, "Contract is paused"); + _; + } + + function transferAdmin(address newAdmin) external onlyAdmin { + require(newAdmin != address(0), "Admin cannot be zero address"); + address oldAdmin = admin; + admin = newAdmin; + emit AdminUpdated(oldAdmin, newAdmin); + } + + function setPaused(bool _paused) external onlyAdmin { + paused = _paused; + emit PausedStatusChanged(_paused); + } + + // /** + // * @notice Update the protocol-default OPRF public key hash trusted by this SubVerifier. + // * @param newHash The new default OPRF public key hash + // */ + // function setDefaultOPRFPubKeyHash(bytes32 newHash) external onlyAdmin { + // bytes32 oldHash = defaultOPRFPubKeyHash; + // defaultOPRFPubKeyHash = newHash; + // emit DefaultOPRFPubKeyHashUpdated(oldHash, newHash); + // } + + function addProofVerifiers(ProofVerifier[] calldata _proofVerifiers) external onlyAdmin { + for (uint256 i = 0; i < _proofVerifiers.length; i++) { + proofVerifiers[_proofVerifiers[i].vkeyHash] = _proofVerifiers[i].verifier; + emit ProofVerifierAdded(_proofVerifiers[i].verifier, _proofVerifiers[i].vkeyHash); + } + } + + function removeProofVerifiers(bytes32[] calldata vkeyHashes) external onlyAdmin { + for (uint256 i = 0; i < vkeyHashes.length; i++) { + address proofVerifier = proofVerifiers[vkeyHashes[i]]; + if (proofVerifier != address(0)) { + delete proofVerifiers[vkeyHashes[i]]; + emit ProofVerifierRemoved(proofVerifier, vkeyHashes[i]); + } + } + } + + function _checkDateValidity(uint256 currentDateTimeStamp, uint256 validityPeriodInSeconds) + internal + view + returns (bool) + { + return DateUtils.isDateValid(currentDateTimeStamp, validityPeriodInSeconds); + } + + /** + * @notice Verifies that the proof was generated for the given scope (domain) and subscope (service scope) + * @param publicInputs The public inputs of the proof + * @param scope The scope (domain) to check against + * @param subscope The subscope (service scope) to check against + * @return True if valid, false otherwise + */ + function _verifyScopes(bytes32[] calldata publicInputs, string calldata scope, string calldata subscope) + internal + pure + returns (bool) + { + // One byte is dropped at the end + // What we call scope internally is derived from the domain + bytes32 scopeHash = StringUtils.isEmpty(scope) ? bytes32(0) : sha256(abi.encodePacked(scope)) >> 8; + // What we call the subscope internally is the service scope specified manually in the SDK + bytes32 subscopeHash = StringUtils.isEmpty(subscope) ? bytes32(0) : sha256(abi.encodePacked(subscope)) >> 8; + return + publicInputs[PublicInput.SCOPE_INDEX] == scopeHash + && publicInputs[PublicInput.SUBSCOPE_INDEX] == subscopeHash; + } + + function _verifyCommittedInputs(bytes32[] memory paramCommitments, bytes calldata committedInputs) internal pure { + uint256 offset = 0; + uint256 index = 0; + while (offset < committedInputs.length && index < paramCommitments.length) { + // The committed inputs are formatted as follows: + // - 1 byte: proof type + // - 2 bytes: length of the committed inputs + // - N bytes: committed inputs for a given proof + uint16 length = uint16(bytes2(committedInputs[offset + 1:offset + 3])); + // One byte is dropped inside the circuit as BN254 is limited to 254 bits + // We also add 3 bytes to take into account the proof type and length + bytes32 calculatedCommitment = sha256(abi.encodePacked(committedInputs[offset:offset + length + 3])) >> 8; + require(calculatedCommitment == paramCommitments[index], "Invalid commitment"); + offset += length + 3; + index++; + } + // Check that all the committed inputs have been covered, otherwise something is wrong + require(offset == committedInputs.length, "Invalid committed inputs length"); + require(index == paramCommitments.length, "Invalid parameter commitments"); + } + + // Temporarily disabled to match the deployed RootVerifier ABI on Sepolia. + // /** + // * @notice For salted (OPRF-derived) nullifier proofs, asserts the proof's oprf_pk_hash + // * matches the expected OPRF public key hash. No-op for non-salted proofs. + // * @dev The expected hash is the service's `serviceConfig.oprfPubKeyHash` if non-zero, + // * otherwise this SubVerifier's `defaultOPRFPubKeyHash`. + // * @param publicInputs The public inputs of the proof + // * @param nullifierType The nullifier type extracted from the proof's public inputs + // * @param serviceOPRFPubKeyHash The service's OPRF public key hash override (bytes32(0) means use protocol default) + // */ + // function _verifyOPRFPubKeyHash( + // bytes32[] calldata publicInputs, + // NullifierType nullifierType, + // bytes32 serviceOPRFPubKeyHash + // ) internal view { + // if (nullifierType != NullifierType.SALTED_NULLIFIER && nullifierType != NullifierType.SALTED_MOCK_NULLIFIER) { + // return; + // } + // bytes32 expected = serviceOPRFPubKeyHash != bytes32(0) ? serviceOPRFPubKeyHash : defaultOPRFPubKeyHash; + // require(publicInputs[publicInputs.length - 1] == expected, "Invalid OPRF public key"); + // } + + function _getProofVerifier(bytes32 vkeyHash) internal view returns (address) { + address verifier = proofVerifiers[vkeyHash]; + require(verifier != address(0), "Verifier not found"); + return verifier; + } + + function _validateCertificateRoot(RootRegistry _rootRegistry, bytes32 certificateRoot, uint256 timestamp) + internal + view + { + require( + _rootRegistry.isRootValid(RegistryID.CERTIFICATE, certificateRoot, timestamp), + "Invalid certificate registry root" + ); + } + + function _validateCircuitRoot(RootRegistry _rootRegistry, bytes32 circuitRoot, uint256 timestamp) internal view { + require(_rootRegistry.isRootValid(RegistryID.CIRCUIT, circuitRoot, timestamp), "Invalid circuit registry root"); + } + + /** + * @notice Verifies a ZKPassport proof + * @dev This function is called by the root verifier to verify a proof for a specific version + * @param rootRegistry The root registry + * @param params The proof verification parameters + * @return isValid True if the proof is valid, false otherwise + * @return uniqueIdentifier The unique identifier associated to the identity document that generated the proof + */ + function verify(RootRegistry rootRegistry, ProofVerificationParams calldata params) + external + view + whenNotPaused + onlyRootVerifier + returns (bool isValid, bytes32 uniqueIdentifier) + { + // Get the verifier for the Outer Circuit corresponding to the vkey hash + address verifier = _getProofVerifier(params.proofVerificationData.vkeyHash); + + uint256 currentTimestamp = uint256(params.proofVerificationData.publicInputs[PublicInput.CURRENT_DATE_INDEX]); + + // Validate certificate registry root + _validateCertificateRoot( + rootRegistry, + params.proofVerificationData.publicInputs[PublicInput.CERTIFICATE_REGISTRY_ROOT_INDEX], + currentTimestamp + ); + + // Validate circuit registry root + _validateCircuitRoot( + rootRegistry, + params.proofVerificationData.publicInputs[PublicInput.CIRCUIT_REGISTRY_ROOT_INDEX], + currentTimestamp + ); + + // Checks the date of the proof + // This is the current date used as public input in the disclosure proofs + // so verifying it here guarantees that the disclosure proofs were generated with this date + require( + _checkDateValidity(currentTimestamp, params.serviceConfig.validityPeriodInSeconds), + "The proof was generated outside the validity period" + ); + + // Validate scopes + // It is recommended to verify this against static variables in your contract + // by calling `helper.verifyScopes(publicInputs, domain, scope)` or setting the domain and scope + // in the params inside your smart contract function before calling `verifier.verify(params)` + // Check SampleContract.sol for an example + require( + _verifyScopes( + params.proofVerificationData.publicInputs, params.serviceConfig.domain, params.serviceConfig.scope + ), + "Invalid domain or scope" + ); + + // Verifies the commitments against the committed inputs + // Trailing public inputs (in order): [length-3] nullifier_type, [length-2] scoped_nullifier, [length-1] oprf_pk_hash. + _verifyCommittedInputs( + // Extracts the commitments from the public inputs + params.proofVerificationData + .publicInputs[PublicInput.PARAM_COMMITMENTS_INDEX:params.proofVerificationData.publicInputs.length - 3], + params.committedInputs + ); + + NullifierType nullifierType = NullifierType( + uint256(params.proofVerificationData.publicInputs[params.proofVerificationData.publicInputs.length - 3]) + ); + + // Allow mock proofs in dev mode + // Note: On mainnets, this stage won't be reached as the ZKR certificates will not be part + // of the mainnet registries and the verification will fail at _validateCertificateRoot + require( + (nullifierType != NullifierType.NON_SALTED_MOCK_NULLIFIER + && nullifierType != NullifierType.SALTED_MOCK_NULLIFIER) || params.serviceConfig.devMode, + "Mock proofs are only allowed in dev mode" + ); + + require( + nullifierType == NullifierType.NON_SALTED_NULLIFIER || nullifierType == NullifierType.SALTED_NULLIFIER + || params.serviceConfig.devMode, + "Unsupported nullifier type" + ); + + // Temporarily disabled to match the deployed RootVerifier ABI on Sepolia. + // _verifyOPRFPubKeyHash( + // params.proofVerificationData.publicInputs, nullifierType, params.serviceConfig.oprfPubKeyHash + // ); + + // Call the proof verifier for the given Outer Circuit to verify if the actual proof is valid + isValid = IProofVerifier(verifier) + .verify(params.proofVerificationData.proof, params.proofVerificationData.publicInputs); + + // Get the unique identifier from the public inputs + // Layout: [length-3] nullifier_type, [length-2] scoped_nullifier, [length-1] oprf_pk_hash + uint256 uniqueIdentifierIndex = params.proofVerificationData.publicInputs.length - 2; + uniqueIdentifier = params.proofVerificationData.publicInputs[uniqueIdentifierIndex]; + + // Return the validity of the proof verification and the unique identifier + return (isValid, uniqueIdentifier); + } +} diff --git a/packages/registry-contracts/src/VerifierHelper.sol b/packages/registry-contracts/src/VerifierHelper.sol new file mode 100644 index 00000000..bb8ac033 --- /dev/null +++ b/packages/registry-contracts/src/VerifierHelper.sol @@ -0,0 +1,489 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright © 2026 ZKPassport +/* + ______ _ _ _____ _______ _______ _______ _____ _____ ______ _______ + ____/ |____/ |_____] |_____| |______ |______ |_____] | | |_____/ | + /_____ | \_ | | | ______| ______| | |_____| | \_ | + +*/ + +pragma solidity ^0.8.30; + +import {RootRegistry} from "./RootRegistry.sol"; +import {DateUtils} from "./lib/DateUtils.sol"; +import {StringUtils} from "./lib/StringUtils.sol"; +import {InputsExtractor} from "./lib/InputsExtractor.sol"; +import {SECONDS_BETWEEN_1900_AND_1970, PublicInput, AppAttest, RegistryID} from "./lib/Constants.sol"; +import {ProofType, DisclosedData, BoundData, FaceMatchMode, Environment, OS} from "./lib/Types.sol"; + +contract VerifierHelper { + RootRegistry public immutable rootRegistry; + + constructor(RootRegistry _rootRegistry) { + require(address(_rootRegistry) != address(0), "Root registry cannot be zero address"); + rootRegistry = _rootRegistry; + } + + /** + * @notice Gets the data disclosed by the proof + * @param committedInputs The committed inputs + * @param isIDCard Whether the proof is an ID card + * @return disclosedData The data disclosed by the proof + */ + function getDisclosedData(bytes calldata committedInputs, bool isIDCard) + external + pure + returns (DisclosedData memory disclosedData) + { + (, bytes memory discloseBytes) = InputsExtractor.getDiscloseProofInputs(committedInputs); + disclosedData = InputsExtractor.getDisclosedData(discloseBytes, isIDCard); + } + + /** + * @notice Checks if the age is above or equal to the given age + * @param minAge The age must be above or equal to this age + * @param committedInputs The committed inputs + * @return True if the age is above or equal to the given age, false otherwise + */ + function isAgeAboveOrEqual(uint8 minAge, bytes calldata committedInputs) public pure returns (bool) { + (uint8 min, uint8 max) = InputsExtractor.getAgeProofInputs(committedInputs); + require(max == 0, "The proof upper bound must be 0, please use isAgeBetween instead"); + return minAge == min; + } + + /** + * @notice Checks if the age is above the given age + * @param minAge The age must be above this age + * @param committedInputs The committed inputs + * @return True if the age is above the given age, false otherwise + */ + function isAgeAbove(uint8 minAge, bytes calldata committedInputs) public pure returns (bool) { + return isAgeAboveOrEqual(minAge + 1, committedInputs); + } + + /** + * @notice Checks if the age is in the given range + * @param minAge The age must be greater than or equal to this age + * @param maxAge The age must be less than or equal to this age + * @param committedInputs The committed inputs + * @return True if the age is in the given range, false otherwise + */ + function isAgeBetween(uint8 minAge, uint8 maxAge, bytes calldata committedInputs) public pure returns (bool) { + (uint8 min, uint8 max) = InputsExtractor.getAgeProofInputs(committedInputs); + require(minAge <= maxAge, "Min age must be less than or equal to max age"); + require(min != 0, "The proof lower bound must be non-zero, please use isAgeBelowOrEqual instead"); + require(max != 0, "The proof upper bound must be non-zero, please use isAgeAboveOrEqual instead"); + return minAge == min && maxAge == max; + } + + /** + * @notice Checks if the age is below or equal to the given age + * @param maxAge The age must be below or equal to this age + * @param committedInputs The committed inputs + * @return True if the age is below or equal to the given age, false otherwise + */ + function isAgeBelowOrEqual(uint8 maxAge, bytes calldata committedInputs) public pure returns (bool) { + (uint8 min, uint8 max) = InputsExtractor.getAgeProofInputs(committedInputs); + require(min == 0, "The proof lower bound must be 0, please use isAgeBetween instead"); + return maxAge == max; + } + + /** + * @notice Checks if the age is below the given age + * @param maxAge The age must be below this age + * @param committedInputs The committed inputs + * @return True if the age is below the given age, false otherwise + */ + function isAgeBelow(uint8 maxAge, bytes calldata committedInputs) public pure returns (bool) { + require(maxAge > 0, "Max age must be greater than 0"); + return isAgeBelowOrEqual(maxAge - 1, committedInputs); + } + + /** + * @notice Checks if the age is equal to the given age + * @param age The age must be equal to this age + * @param committedInputs The committed inputs + * @return True if the age is equal to the given age, false otherwise + */ + function isAgeEqual(uint8 age, bytes calldata committedInputs) public pure returns (bool) { + return isAgeBetween(age, age, committedInputs); + } + + function _isDateAfterOrEqual(uint256 minDate, ProofType proofType, bytes calldata committedInputs) + private + pure + returns (bool) + { + (uint256 min, uint256 max) = InputsExtractor.getDateProofInputs(committedInputs, proofType); + require(proofType == ProofType.BIRTHDATE || proofType == ProofType.EXPIRY_DATE, "Invalid proof type"); + if (proofType == ProofType.BIRTHDATE) { + require(max == 0, "The proof upper bound must be 0, please use isBirthdateBetween instead"); + // Birthdate comparison dates use 1900 as the starting epoch so the proof can take in value + // prior to 1970, so we need to subtract the difference between 1900 and 1970 (starting UNIX epoch) + return minDate == min - SECONDS_BETWEEN_1900_AND_1970; + } else { + require(max == 0, "The proof upper bound must be 0, please use isExpiryDateBetween instead"); + return minDate == min; + } + } + + function _isDateBetween(uint256 minDate, uint256 maxDate, ProofType proofType, bytes calldata committedInputs) + private + pure + returns (bool) + { + (uint256 min, uint256 max) = InputsExtractor.getDateProofInputs(committedInputs, proofType); + require(minDate <= maxDate, "Min date must be less than or equal to max date"); + require(proofType == ProofType.BIRTHDATE || proofType == ProofType.EXPIRY_DATE, "Invalid proof type"); + if (proofType == ProofType.BIRTHDATE) { + require(min != 0, "The proof lower bound must be non-zero, please use isBirthdateBelowOrEqual instead"); + require(max != 0, "The proof upper bound must be non-zero, please use isBirthdateAboveOrEqual instead"); + // Birthdate comparison dates use 1900 as the starting epoch so the proof can take in values + // prior to 1970, so we need to subtract the difference between 1900 and 1970 (starting UNIX epoch) + return minDate == min - SECONDS_BETWEEN_1900_AND_1970 && maxDate == max - SECONDS_BETWEEN_1900_AND_1970; + } else { + require(min != 0, "The proof lower bound must be non-zero, please use isExpiryDateBelowOrEqual instead"); + require(max != 0, "The proof upper bound must be non-zero, please use isExpiryDateAboveOrEqual instead"); + return minDate == min && maxDate == max; + } + } + + function _isDateBeforeOrEqual(uint256 maxDate, ProofType proofType, bytes calldata committedInputs) + private + pure + returns (bool) + { + (uint256 min, uint256 max) = InputsExtractor.getDateProofInputs(committedInputs, proofType); + require(min == 0, "The proof lower bound must be 0, please use _isDateBetween instead"); + require(proofType == ProofType.BIRTHDATE || proofType == ProofType.EXPIRY_DATE, "Invalid proof type"); + if (proofType == ProofType.BIRTHDATE) { + require(max != 0, "The proof upper bound must be non-zero, please use isBirthdateAboveOrEqual instead"); + // Birthdate comparison dates use 1900 as the starting epoch so the proof can take in value + // prior to 1970, so we need to subtract the difference between 1900 and 1970 (starting UNIX epoch) + return maxDate == max - SECONDS_BETWEEN_1900_AND_1970; + } else { + require(max != 0, "The proof upper bound must be non-zero, please use isExpiryDateAboveOrEqual instead"); + return maxDate == max; + } + } + + /** + * @notice Checks if the birthdate is after or equal to the given date + * @param minDate The birthdate must be after or equal to this date + * @param committedInputs The committed inputs + * @return True if the birthdate is after or equal to the given date, false otherwise + */ + function isBirthdateAfterOrEqual(uint256 minDate, bytes calldata committedInputs) public pure returns (bool) { + return _isDateAfterOrEqual(minDate, ProofType.BIRTHDATE, committedInputs); + } + + /** + * @notice Checks if the birthdate is after the given date + * @param minDate The birthdate must be after this date + * @param committedInputs The committed inputs + * @return True if the birthdate is after the given date, false otherwise + */ + function isBirthdateAfter(uint256 minDate, bytes calldata committedInputs) public pure returns (bool) { + return _isDateAfterOrEqual(minDate + 1 days, ProofType.BIRTHDATE, committedInputs); + } + + /** + * @notice Checks if the birthdate is between the given dates + * @param minDate The birthdate must be after or equal to this date + * @param maxDate The birthdate must be before or equal to this date + * @param committedInputs The committed inputs + * @return True if the birthdate is between the given dates, false otherwise + */ + function isBirthdateBetween(uint256 minDate, uint256 maxDate, bytes calldata committedInputs) + public + pure + returns (bool) + { + return _isDateBetween(minDate, maxDate, ProofType.BIRTHDATE, committedInputs); + } + + /** + * @notice Checks if the birthdate is before or equal to the given date + * @param maxDate The birthdate must be before or equal to this date + * @param committedInputs The committed inputs + * @return True if the birthdate is before or equal to the given date, false otherwise + */ + function isBirthdateBeforeOrEqual(uint256 maxDate, bytes calldata committedInputs) public pure returns (bool) { + return _isDateBeforeOrEqual(maxDate, ProofType.BIRTHDATE, committedInputs); + } + + /** + * @notice Checks if the birthdate is before the given date + * @param maxDate The birthdate must be before this date + * @param committedInputs The committed inputs + * @return True if the birthdate is before the given date, false otherwise + */ + function isBirthdateBefore(uint256 maxDate, bytes calldata committedInputs) public pure returns (bool) { + return _isDateBeforeOrEqual(maxDate - 1 days, ProofType.BIRTHDATE, committedInputs); + } + + /** + * @notice Checks if the birthdate is equal to the given date + * @param date The birthdate must be equal to this date + * @param committedInputs The committed inputs + * @return True if the birthdate is equal to the given date, false otherwise + */ + function isBirthdateEqual(uint256 date, bytes calldata committedInputs) public pure returns (bool) { + return _isDateBetween(date, date, ProofType.BIRTHDATE, committedInputs); + } + + /** + * @notice Checks if the expiry date is after or equal to the given date + * @param minDate The expiry date must be after or equal to this date + * @param committedInputs The committed inputs + * @return True if the expiry date is after or equal to the given date, false otherwise + */ + function isExpiryDateAfterOrEqual(uint256 minDate, bytes calldata committedInputs) public pure returns (bool) { + return _isDateAfterOrEqual(minDate, ProofType.EXPIRY_DATE, committedInputs); + } + + /** + * @notice Checks if the expiry date is after the given date + * @param minDate The expiry date must be after this date + * @param committedInputs The committed inputs + * @return True if the expiry date is after the given date, false otherwise + */ + function isExpiryDateAfter(uint256 minDate, bytes calldata committedInputs) public pure returns (bool) { + return _isDateAfterOrEqual(minDate + 1 days, ProofType.EXPIRY_DATE, committedInputs); + } + + /** + * @notice Checks if the expiry date is between the given dates + * @param minDate The expiry date must be after or equal to this date + * @param maxDate The expiry date must be before or equal to this date + * @param committedInputs The committed inputs + * @return True if the expiry date is between the given dates, false otherwise + */ + function isExpiryDateBetween(uint256 minDate, uint256 maxDate, bytes calldata committedInputs) + public + pure + returns (bool) + { + return _isDateBetween(minDate, maxDate, ProofType.EXPIRY_DATE, committedInputs); + } + + /** + * @notice Checks if the expiry date is before or equal to the given date + * @param maxDate The expiry date must be before or equal to this date + * @param committedInputs The committed inputs + * @return True if the expiry date is before or equal to the given date, false otherwise + */ + function isExpiryDateBeforeOrEqual(uint256 maxDate, bytes calldata committedInputs) public pure returns (bool) { + return _isDateBeforeOrEqual(maxDate, ProofType.EXPIRY_DATE, committedInputs); + } + + /** + * @notice Checks if the expiry date is before the given date + * @param maxDate The expiry date must be before this date + * @param committedInputs The committed inputs + * @return True if the expiry date is before the given date, false otherwise + */ + function isExpiryDateBefore(uint256 maxDate, bytes calldata committedInputs) public pure returns (bool) { + return _isDateBeforeOrEqual(maxDate - 1 days, ProofType.EXPIRY_DATE, committedInputs); + } + + /** + * @notice Checks if the expiry date is equal to the given date + * @param date The expiry date must be equal to this date + * @param committedInputs The committed inputs + * @return True if the expiry date is equal to the given date, false otherwise + */ + function isExpiryDateEqual(uint256 date, bytes calldata committedInputs) public pure returns (bool) { + return _isDateBetween(date, date, ProofType.EXPIRY_DATE, committedInputs); + } + + function isCountryInOrOut(string[] memory countryList, ProofType proofType, bytes calldata committedInputs) + private + pure + returns (bool) + { + (string[] memory inputCountryList, uint256 inputCountryListLength) = + InputsExtractor.getCountryProofInputs(committedInputs, proofType); + if (countryList.length != inputCountryListLength) { + return false; + } + for (uint256 i = 0; i < inputCountryListLength; i++) { + if (!StringUtils.equals(countryList[i], inputCountryList[i])) { + return false; + } + } + return true; + } + + /** + * @notice Checks if the nationality is in the list of countries + * @param countryList The list of countries (needs to match exactly the list of countries in the proof) + * @param committedInputs The committed inputs + * @return True if the nationality is in the list of countries, false otherwise + */ + function isNationalityIn(string[] memory countryList, bytes calldata committedInputs) external pure returns (bool) { + return isCountryInOrOut(countryList, ProofType.NATIONALITY_INCLUSION, committedInputs); + } + + /** + * @notice Checks if the issuing country is in the list of countries + * @param countryList The list of countries (needs to match exactly the list of countries in the proof) + * @param committedInputs The committed inputs + * @return True if the issuing country is in the list of countries, false otherwise + */ + function isIssuingCountryIn(string[] memory countryList, bytes calldata committedInputs) + external + pure + returns (bool) + { + return isCountryInOrOut(countryList, ProofType.ISSUING_COUNTRY_INCLUSION, committedInputs); + } + + /** + * @notice Checks if the nationality is not in the list of countries + * @param countryList The list of countries (needs to match exactly the list of countries in the proof) + * Note: The list of countries must be sorted in alphabetical order + * @param committedInputs The committed inputs + * @return True if the nationality is not in the list of countries, false otherwise + */ + function isNationalityOut(string[] memory countryList, bytes calldata committedInputs) + external + pure + returns (bool) + { + return isCountryInOrOut(countryList, ProofType.NATIONALITY_EXCLUSION, committedInputs); + } + + /** + * @notice Checks if the issuing country is not in the list of countries + * @param countryList The list of countries (needs to match exactly the list of countries in the proof) + * Note: The list of countries must be sorted in alphabetical order + * @param committedInputs The committed inputs + * @return True if the issuing country is not in the list of countries, false otherwise + */ + function isIssuingCountryOut(string[] memory countryList, bytes calldata committedInputs) + external + pure + returns (bool) + { + return isCountryInOrOut(countryList, ProofType.ISSUING_COUNTRY_EXCLUSION, committedInputs); + } + + /** + * @notice Gets the data bound to the proof + * @param committedInputs The committed inputs + * @return boundData The data bound to the proof + */ + function getBoundData(bytes calldata committedInputs) external pure returns (BoundData memory boundData) { + bytes memory data = InputsExtractor.getBindProofInputs(committedInputs); + (boundData.senderAddress, boundData.chainId, boundData.customData) = InputsExtractor.getBoundData(data); + } + + /** + * @notice Checks if the sanctions root is valid against the expected sanction list(s) + * @param currentTimestamp The current timestamp (preferably from the proof rather than the block timestamp). + * This is used to check the validity of the sanctions root at that specific time. + * @param isStrict Whether the sanctions check was strict or not + * @param committedInputs The committed inputs + * @return True if the sanctions root is valid against the expected sanction list(s), false otherwise + */ + function isSanctionsRootValid(uint256 currentTimestamp, bool isStrict, bytes calldata committedInputs) + external + view + returns (bool) + { + return _isSanctionsRootValid(currentTimestamp, isStrict, committedInputs); + } + + function _isSanctionsRootValid(uint256 currentTimestamp, bool isStrict, bytes calldata committedInputs) + internal + view + returns (bool) + { + (bytes32 proofSanctionsRoot, bool retrievedIsStrict) = InputsExtractor.getSanctionsProofInputs(committedInputs); + require(isStrict == retrievedIsStrict, "Invalid sanctions check mode"); + return rootRegistry.isRootValid(RegistryID.SANCTIONS, proofSanctionsRoot, currentTimestamp); + } + + /** + * @notice Enforces that the proof checks against the expected sanction list(s) + * @param currentTimestamp The current timestamp (preferably from the proof rather than the block timestamp). + * This is used to check the validity of the sanctions root at that specific time. + * @param isStrict Whether the sanctions check was strict or not + * @param committedInputs The committed inputs + */ + function enforceSanctionsRoot(uint256 currentTimestamp, bool isStrict, bytes calldata committedInputs) + external + view + { + bool isValid = _isSanctionsRootValid(currentTimestamp, isStrict, committedInputs); + require(isValid, "Invalid sanctions registry root"); + } + + /** + * @notice Checks if the proof is tied to a FaceMatch verification + * @param faceMatchMode The FaceMatch mode expected to be used in the verification + * @param os The operating system on which the proof should have been generated (Any (0), iOS (1), Android (2)) + * @param committedInputs The committed inputs + * @return True if the proof is tied to a valid FaceMatch verification, false otherwise + */ + function isFaceMatchVerified(FaceMatchMode faceMatchMode, OS os, bytes calldata committedInputs) + external + pure + returns (bool) + { + ( + bytes32 rootKeyHash, + Environment environment, + bytes32 appIdHash, + bytes32 integrityPublicKeyHash, + FaceMatchMode retrievedFaceMatchMode + ) = InputsExtractor.getFacematchProofInputs(committedInputs); + bool isProduction = environment == Environment.PRODUCTION; + bool isCorrectMode = retrievedFaceMatchMode == faceMatchMode; + bool isCorrectRootKeyHash = (rootKeyHash == AppAttest.APPLE_ROOT_KEY_HASH && (os == OS.IOS || os == OS.ANY)) + || ((rootKeyHash == AppAttest.GOOGLE_RSA_ROOT_KEY_HASH + || rootKeyHash == AppAttest.GOOGLE_ECDSA_ROOT_KEY_HASH) + && (os == OS.ANDROID || os == OS.ANY)); + bool isCorrectAppIdHash = (appIdHash == AppAttest.IOS_APP_ID_HASH && (os == OS.IOS || os == OS.ANY)) + || (appIdHash == AppAttest.ANDROID_APP_ID_HASH && (os == OS.ANDROID || os == OS.ANY)); + // The integrity public key hash is 0 for iOS as it's logic specific to Android + bool isCorrectIntegrityPublicKeyHash = (integrityPublicKeyHash == bytes32(0) && (os == OS.IOS || os == OS.ANY)) + || (integrityPublicKeyHash == AppAttest.ANDROID_INTEGRITY_PUBLIC_KEY_HASH + && (os == OS.ANDROID || os == OS.ANY)); + return + isProduction && isCorrectMode && isCorrectRootKeyHash && isCorrectAppIdHash + && isCorrectIntegrityPublicKeyHash; + } + + /** + * @notice Gets the timestamp the proof was generated at + * @param publicInputs The public inputs of the proof + * @return The timestamp the proof was generated at + */ + function getProofTimestamp(bytes32[] calldata publicInputs) external pure returns (uint256) { + return uint256(publicInputs[PublicInput.CURRENT_DATE_INDEX]); + } + + /** + * @notice Verifies that the proof was generated for the given scope (domain) and subscope (service scope) + * @param publicInputs The public inputs of the proof + * @param scope The scope (domain) to check against + * @param subscope The subscope (service scope) to check against + * @return True if valid, false otherwise + */ + function verifyScopes(bytes32[] calldata publicInputs, string calldata scope, string calldata subscope) + external + pure + returns (bool) + { + // One byte is dropped at the end + // What we call scope internally is derived from the domain + bytes32 scopeHash = StringUtils.isEmpty(scope) ? bytes32(0) : sha256(abi.encodePacked(scope)) >> 8; + // What we call the subscope internally is the service scope specified manually in the SDK + bytes32 subscopeHash = StringUtils.isEmpty(subscope) ? bytes32(0) : sha256(abi.encodePacked(subscope)) >> 8; + return + publicInputs[PublicInput.SCOPE_INDEX] == scopeHash + && publicInputs[PublicInput.SUBSCOPE_INDEX] == subscopeHash; + } +} diff --git a/packages/registry-contracts/src/lib/Constants.sol b/packages/registry-contracts/src/lib/Constants.sol new file mode 100644 index 00000000..bf6f9c44 --- /dev/null +++ b/packages/registry-contracts/src/lib/Constants.sol @@ -0,0 +1,134 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright © 2026 ZKPassport +/* + ______ _ _ _____ _______ _______ _______ _____ _____ ______ _______ + ____/ |____/ |_____] |_____| |______ |______ |_____] | | |_____/ | + /_____ | \_ | | | ______| ______| | |_____| | \_ | + +*/ + +pragma solidity ^0.8.30; + +uint256 constant SECONDS_BETWEEN_1900_AND_1970 = 2208988800; +uint256 constant COUNTRY_LIST_LENGTH = 200; +uint256 constant BOUND_DATA_LENGTH = 509; +uint256 constant TIMESTAMP_LENGTH = 8; + +// Registry IDs +library RegistryID { + bytes32 constant CERTIFICATE = bytes32(0x0000000000000000000000000000000000000000000000000000000000000001); + bytes32 constant CIRCUIT = bytes32(0x0000000000000000000000000000000000000000000000000000000000000002); + bytes32 constant SANCTIONS = bytes32(0x0000000000000000000000000000000000000000000000000000000000000003); +} + +// The lengths of the preimages of the `param_commitments` of the various disclosure circuits. +// Note: this is excluding the 3 bytes for the proof type and length +library CommittedInputLen { + uint256 constant COMPARE_AGE = 2; + uint256 constant COMPARE_BIRTHDATE = 16; + uint256 constant COMPARE_EXPIRY = 16; + uint256 constant DISCLOSE_BYTES = 180; + uint256 constant INCL_ISSUING_COUNTRY = 600; + uint256 constant EXCL_ISSUING_COUNTRY = 600; + uint256 constant INCL_NATIONALITY = 600; + uint256 constant EXCL_NATIONALITY = 600; + uint256 constant BIND = 509; + uint256 constant SANCTIONS = 33; + uint256 constant FACEMATCH = 98; +} + +// Gather all the public input indices in one place +library PublicInput { + uint256 constant CERTIFICATE_REGISTRY_ROOT_INDEX = 0; + uint256 constant CIRCUIT_REGISTRY_ROOT_INDEX = 1; + uint256 constant CURRENT_DATE_INDEX = 2; + uint256 constant SCOPE_INDEX = 3; + uint256 constant SUBSCOPE_INDEX = 4; + uint256 constant PARAM_COMMITMENTS_INDEX = 5; + // The length of the public inputs excluding the param commitments + uint256 constant PUBLIC_INPUTS_EXCLUDING_PARAM_COMMITMENTS_LENGTH = 8; +} + +// Gather all the MRZ indices in one place +library MRZIndex { + // Index for the country of issuance of the passport + uint256 constant PASSPORT_MRZ_ISSUING_COUNTRY_INDEX = 2; + // Index for the three letter code of the country of citizenship + // Note that the first three letter code (index 2) in the MRZ is the country of issuance + // not citizenship. It is important to keep in mind for residence permits + // where the issuing country differs from the citizenship country + uint256 constant PASSPORT_MRZ_NATIONALITY_INDEX = 54; + // Index for the gender of the passport holder (M, F or < if unspecified) + uint256 constant PASSPORT_MRZ_GENDER_INDEX = 64; + // Index for the date of expiry (YYMMDD) + uint256 constant PASSPORT_MRZ_EXPIRY_DATE_INDEX = 65; + // Index for the date of birth (YYMMDD) in TD1 (i.e. passport) MRZ + uint256 constant PASSPORT_MRZ_BIRTHDATE_INDEX = 57; + // Index for the document number in the MRZ + uint256 constant PASSPORT_MRZ_DOCUMENT_NUMBER_INDEX = 44; + // Index for the document type in the MRZ + uint256 constant PASSPORT_MRZ_DOCUMENT_TYPE_INDEX = 0; + // Index for the name of the passport holder + uint256 constant PASSPORT_MRZ_NAME_INDEX = 5; + + // Index for the country of issuance of the ID card + uint256 constant ID_CARD_MRZ_ISSUING_COUNTRY_INDEX = 2; + // Note that the first three letter code (index 2) in the MRZ is the country of issuance + // not citizenship. It is important to keep in mind for residence permits + // where the issuing country differs from the citizenship country + uint256 constant ID_CARD_MRZ_NATIONALITY_INDEX = 45; + // Index for the gender of the passport holder (M, F or < if unspecified) + uint256 constant ID_CARD_MRZ_GENDER_INDEX = 37; + // Index for the date of expiry (YYMMDD) + uint256 constant ID_CARD_MRZ_EXPIRY_DATE_INDEX = 38; + // Index for the date of birth (YYMMDD) in TD3 (i.e. ID cards) MRZ + uint256 constant ID_CARD_MRZ_BIRTHDATE_INDEX = 30; + // Index for the document number in the MRZ + uint256 constant ID_CARD_MRZ_DOCUMENT_NUMBER_INDEX = 5; + // Index for the document type in the MRZ + uint256 constant ID_CARD_MRZ_DOCUMENT_TYPE_INDEX = 0; + // Index for the name of the passport holder + uint256 constant ID_CARD_MRZ_NAME_INDEX = 60; +} + +// Gather all the MRZ field lengths in one place +library MRZLength { + uint256 constant PASSPORT_MRZ_LENGTH = 88; + uint256 constant ID_CARD_MRZ_LENGTH = 90; + uint256 constant MRZ_MAX_LENGTH = 90; + uint256 constant PASSPORT_MRZ_ISSUING_COUNTRY_LENGTH = 3; + uint256 constant ID_CARD_MRZ_ISSUING_COUNTRY_LENGTH = 3; + uint256 constant PASSPORT_MRZ_NATIONALITY_LENGTH = 3; + uint256 constant ID_CARD_MRZ_NATIONALITY_LENGTH = 3; + uint256 constant PASSPORT_MRZ_GENDER_LENGTH = 1; + uint256 constant ID_CARD_MRZ_GENDER_LENGTH = 1; + uint256 constant PASSPORT_MRZ_BIRTHDATE_LENGTH = 6; + uint256 constant ID_CARD_MRZ_BIRTHDATE_LENGTH = 6; + uint256 constant PASSPORT_MRZ_EXPIRY_DATE_LENGTH = 6; + uint256 constant ID_CARD_MRZ_EXPIRY_DATE_LENGTH = 6; + uint256 constant PASSPORT_MRZ_DOCUMENT_NUMBER_LENGTH = 9; + uint256 constant ID_CARD_MRZ_DOCUMENT_NUMBER_LENGTH = 9; + uint256 constant PASSPORT_MRZ_DOCUMENT_TYPE_LENGTH = 2; + uint256 constant ID_CARD_MRZ_DOCUMENT_TYPE_LENGTH = 2; + uint256 constant PASSPORT_MRZ_NAME_LENGTH = 39; + uint256 constant ID_CARD_MRZ_NAME_LENGTH = 30; + uint256 constant PASSPORT_MRZ_YEAR_OF_BIRTH_LENGTH = 2; + uint256 constant ID_CARD_MRZ_YEAR_OF_BIRTH_LENGTH = 2; +} + +library AppAttest { + // ZKPassport iOS App ID hash + // Little-endian packed and poseidon2 hash of `YL5MS3Z639.app.zkpassport.zkpassport` + bytes32 constant IOS_APP_ID_HASH = 0x1fa73686cf510f8f85757b0602de0dd72a13e68ae2092462be8b72662e7f179b; + // ZKPassport Android App ID hash + // Little-endian packed and poseidon2 hash of `app.zkpassport.zkpassport` + bytes32 constant ANDROID_APP_ID_HASH = 0x24d9929b248be7eeecaa98e105c034a50539610f3fdd4cb9c8983ef4100d615d; + // The hash of Apple's root certificate public key + bytes32 constant APPLE_ROOT_KEY_HASH = 0x2532418a107c5306fa8308c22255792cf77e4a290cbce8a840a642a3e591340b; + // The hash of Google's RSA root certificate public key + bytes32 constant GOOGLE_RSA_ROOT_KEY_HASH = 0x16700a2d9168a194fc85f237af5829b5a2be05b8ae8ac4879ada34cf54a9c211; + // The hash of Google's ECDSA (P384) root certificate public key + bytes32 constant GOOGLE_ECDSA_ROOT_KEY_HASH = 0x0e1889bec6c1d686abcf08360ff404f803ab345881ea8cba6aad33b7f7f7ffe0; + // The hash of the Android integrity public key + bytes32 constant ANDROID_INTEGRITY_PUBLIC_KEY_HASH = 0x12e3dc7cc8fec0205b51ff21825630865028f3be5bc64a6eec9ee5e71221319f; +} diff --git a/packages/registry-contracts/src/lib/DateUtils.sol b/packages/registry-contracts/src/lib/DateUtils.sol new file mode 100644 index 00000000..5f1186b9 --- /dev/null +++ b/packages/registry-contracts/src/lib/DateUtils.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright © 2026 ZKPassport +/* + ______ _ _ _____ _______ _______ _______ _____ _____ ______ _______ + ____/ |____/ |_____] |_____| |______ |______ |_____] | | |_____/ | + /_____ | \_ | | | ______| ______| | |_____| | \_ | + +*/ + +pragma solidity ^0.8.30; + +/** + * @title DateUtils + * @dev Utility functions for date operations + */ +library DateUtils { + /** + * @dev Validates if a date is within a validity period + * @param timestamp The timestamp in seconds since the Unix epoch + * @param validityPeriodInSeconds The validity period in seconds + * @return True if the date is valid and within the validity period + */ + function isDateValid(uint256 timestamp, uint256 validityPeriodInSeconds) internal view returns (bool) { + uint256 validityPeriodTimestamp = timestamp + validityPeriodInSeconds; + return block.timestamp >= timestamp && validityPeriodTimestamp > timestamp + && validityPeriodTimestamp > block.timestamp; + } +} diff --git a/packages/registry-contracts/src/lib/InputsExtractor.sol b/packages/registry-contracts/src/lib/InputsExtractor.sol new file mode 100644 index 00000000..d3f55772 --- /dev/null +++ b/packages/registry-contracts/src/lib/InputsExtractor.sol @@ -0,0 +1,359 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright © 2026 ZKPassport +/* + ______ _ _ _____ _______ _______ _______ _____ _____ ______ _______ + ____/ |____/ |_____] |_____| |______ |______ |_____] | | |_____/ | + /_____ | \_ | | | ______| ______| | |_____| | \_ | + +*/ + +pragma solidity ^0.8.30; + +import { + MRZIndex, + MRZLength, + CommittedInputLen, + COUNTRY_LIST_LENGTH, + BOUND_DATA_LENGTH, + TIMESTAMP_LENGTH +} from "./Constants.sol"; +import {DisclosedData, ProofType, FaceMatchMode, Environment, BoundDataIdentifier} from "./Types.sol"; + +/** + * @title InputsExtractor + * @dev Utility functions for extracting inputs from committed inputs + */ +library InputsExtractor { + function getDisclosedData(bytes calldata discloseBytes, bool isIDCard) + public + pure + returns (DisclosedData memory disclosedData) + { + if (!isIDCard) { + disclosedData.name = string( + discloseBytes[MRZIndex.PASSPORT_MRZ_NAME_INDEX:MRZIndex.PASSPORT_MRZ_NAME_INDEX + + MRZLength.PASSPORT_MRZ_NAME_LENGTH + ] + ); + disclosedData.issuingCountry = string( + discloseBytes[MRZIndex.PASSPORT_MRZ_ISSUING_COUNTRY_INDEX:MRZIndex.PASSPORT_MRZ_ISSUING_COUNTRY_INDEX + + MRZLength.PASSPORT_MRZ_ISSUING_COUNTRY_LENGTH + ] + ); + disclosedData.nationality = string( + discloseBytes[MRZIndex.PASSPORT_MRZ_NATIONALITY_INDEX:MRZIndex.PASSPORT_MRZ_NATIONALITY_INDEX + + MRZLength.PASSPORT_MRZ_NATIONALITY_LENGTH + ] + ); + disclosedData.gender = string( + discloseBytes[MRZIndex.PASSPORT_MRZ_GENDER_INDEX:MRZIndex.PASSPORT_MRZ_GENDER_INDEX + + MRZLength.PASSPORT_MRZ_GENDER_LENGTH + ] + ); + disclosedData.birthDate = string( + discloseBytes[MRZIndex.PASSPORT_MRZ_BIRTHDATE_INDEX:MRZIndex.PASSPORT_MRZ_BIRTHDATE_INDEX + + MRZLength.PASSPORT_MRZ_BIRTHDATE_LENGTH + ] + ); + disclosedData.expiryDate = string( + discloseBytes[MRZIndex.PASSPORT_MRZ_EXPIRY_DATE_INDEX:MRZIndex.PASSPORT_MRZ_EXPIRY_DATE_INDEX + + MRZLength.PASSPORT_MRZ_EXPIRY_DATE_LENGTH + ] + ); + disclosedData.documentNumber = string( + discloseBytes[MRZIndex.PASSPORT_MRZ_DOCUMENT_NUMBER_INDEX:MRZIndex.PASSPORT_MRZ_DOCUMENT_NUMBER_INDEX + + MRZLength.PASSPORT_MRZ_DOCUMENT_NUMBER_LENGTH + ] + ); + disclosedData.documentType = string( + discloseBytes[MRZIndex.PASSPORT_MRZ_DOCUMENT_TYPE_INDEX:MRZIndex.PASSPORT_MRZ_DOCUMENT_TYPE_INDEX + + MRZLength.PASSPORT_MRZ_DOCUMENT_TYPE_LENGTH + ] + ); + } else { + disclosedData.name = string( + discloseBytes[MRZIndex.ID_CARD_MRZ_NAME_INDEX:MRZIndex.ID_CARD_MRZ_NAME_INDEX + + MRZLength.ID_CARD_MRZ_NAME_LENGTH + ] + ); + disclosedData.issuingCountry = string( + discloseBytes[MRZIndex.ID_CARD_MRZ_ISSUING_COUNTRY_INDEX:MRZIndex.ID_CARD_MRZ_ISSUING_COUNTRY_INDEX + + MRZLength.ID_CARD_MRZ_ISSUING_COUNTRY_LENGTH + ] + ); + disclosedData.nationality = string( + discloseBytes[MRZIndex.ID_CARD_MRZ_NATIONALITY_INDEX:MRZIndex.ID_CARD_MRZ_NATIONALITY_INDEX + + MRZLength.ID_CARD_MRZ_NATIONALITY_LENGTH + ] + ); + disclosedData.gender = string( + discloseBytes[MRZIndex.ID_CARD_MRZ_GENDER_INDEX:MRZIndex.ID_CARD_MRZ_GENDER_INDEX + + MRZLength.ID_CARD_MRZ_GENDER_LENGTH + ] + ); + disclosedData.birthDate = string( + discloseBytes[MRZIndex.ID_CARD_MRZ_BIRTHDATE_INDEX:MRZIndex.ID_CARD_MRZ_BIRTHDATE_INDEX + + MRZLength.ID_CARD_MRZ_BIRTHDATE_LENGTH + ] + ); + disclosedData.expiryDate = string( + discloseBytes[MRZIndex.ID_CARD_MRZ_EXPIRY_DATE_INDEX:MRZIndex.ID_CARD_MRZ_EXPIRY_DATE_INDEX + + MRZLength.ID_CARD_MRZ_EXPIRY_DATE_LENGTH + ] + ); + disclosedData.documentNumber = string( + discloseBytes[MRZIndex.ID_CARD_MRZ_DOCUMENT_NUMBER_INDEX:MRZIndex.ID_CARD_MRZ_DOCUMENT_NUMBER_INDEX + + MRZLength.ID_CARD_MRZ_DOCUMENT_NUMBER_LENGTH + ] + ); + disclosedData.documentType = string( + discloseBytes[MRZIndex.ID_CARD_MRZ_DOCUMENT_TYPE_INDEX:MRZIndex.ID_CARD_MRZ_DOCUMENT_TYPE_INDEX + + MRZLength.ID_CARD_MRZ_DOCUMENT_TYPE_LENGTH + ] + ); + } + } + + function getDiscloseProofInputs(bytes calldata committedInputs) + public + pure + returns (bytes memory discloseMask, bytes memory discloseBytes) + { + uint256 offset = 0; + uint256 foundCount = 0; + while (offset < committedInputs.length) { + ProofType proofType = ProofType(uint8(committedInputs[offset])); + uint16 length = uint16(bytes2(committedInputs[offset + 1:offset + 3])); + offset += 3; + if (proofType == ProofType.DISCLOSE && length == CommittedInputLen.DISCLOSE_BYTES) { + discloseMask = committedInputs[offset:offset + MRZLength.MRZ_MAX_LENGTH]; + discloseBytes = committedInputs[offset + MRZLength.MRZ_MAX_LENGTH:offset + MRZLength.MRZ_MAX_LENGTH * 2]; + foundCount++; + } + offset += length; + } + require(foundCount > 0, "Disclose proof inputs not found"); + require(foundCount == 1, "Found multiple disclose proofs, the proof should only have one"); + } + + function getDateProofInputs(bytes calldata committedInputs, ProofType proofType) + public + pure + returns (uint256 minDate, uint256 maxDate) + { + uint256 offset = 0; + uint256 foundCount = 0; + while (offset < committedInputs.length) { + ProofType retrievedProofType = ProofType(uint8(committedInputs[offset])); + uint16 length = uint16(bytes2(committedInputs[offset + 1:offset + 3])); + offset += 3; + if (proofType == retrievedProofType && length == CommittedInputLen.COMPARE_EXPIRY) { + // Get rid of the padding 0s bytes as the timestamp is contained within the first 64 bits + // i.e. 256 - 64 = 192 + minDate = uint256(bytes32(committedInputs[offset:offset + TIMESTAMP_LENGTH])) >> 192; + maxDate = + uint256(bytes32(committedInputs[offset + TIMESTAMP_LENGTH:offset + TIMESTAMP_LENGTH * 2])) >> 192; + foundCount++; + } + offset += length; + } + if (proofType == ProofType.BIRTHDATE) { + require(foundCount > 0, "Compare birthdate proof inputs not found"); + require(foundCount == 1, "Found multiple compare birthdate proofs, the proof should only have one"); + } else { + require(foundCount > 0, "Compare expiry date proof inputs not found"); + require(foundCount == 1, "Found multiple compare expiry date proofs, the proof should only have one"); + } + } + + function getAgeProofInputs(bytes calldata committedInputs) public pure returns (uint8 minAge, uint8 maxAge) { + uint256 offset = 0; + uint256 foundCount = 0; + while (offset < committedInputs.length) { + ProofType retrievedProofType = ProofType(uint8(committedInputs[offset])); + uint16 length = uint16(bytes2(committedInputs[offset + 1:offset + 3])); + offset += 3; + if (retrievedProofType == ProofType.AGE && length == CommittedInputLen.COMPARE_AGE) { + minAge = uint8(committedInputs[offset]); + maxAge = uint8(committedInputs[offset + 1]); + foundCount++; + } + offset += length; + } + require(foundCount > 0, "Compare age proof inputs not found"); + require(foundCount == 1, "Found multiple compare age proofs, the proof should only have one"); + } + + function getCountryListLength(bytes calldata committedInputs, ProofType proofType) + public + pure + returns (uint256 countryListLength) + { + uint256 offset = 0; + while (offset < committedInputs.length) { + ProofType retrievedProofType = ProofType(uint8(committedInputs[offset])); + uint16 length = uint16(bytes2(committedInputs[offset + 1:offset + 3])); + offset += 3; + if (proofType == retrievedProofType && length == CommittedInputLen.INCL_NATIONALITY) { + for (uint256 j = 0; j < COUNTRY_LIST_LENGTH; j++) { + // The circuit constrains that once we've reached the first `0`, + // we won't encounter any further nonzero values. + // We don't need to include the padding bytes + if (committedInputs[offset] == 0) return j; + offset += 3; + } + offset += length - COUNTRY_LIST_LENGTH * 3; + } else { + offset += length; + } + } + } + + function getCountryProofInputs(bytes calldata committedInputs, ProofType proofType) + public + pure + returns (string[] memory countryList, uint256 countryListLength) + { + require( + proofType == ProofType.NATIONALITY_INCLUSION || proofType == ProofType.ISSUING_COUNTRY_INCLUSION + || proofType == ProofType.NATIONALITY_EXCLUSION || proofType == ProofType.ISSUING_COUNTRY_EXCLUSION, + "Invalid proof type" + ); + uint256 offset = 0; + uint256 foundCount = 0; + countryListLength = getCountryListLength(committedInputs, proofType); + countryList = new string[](countryListLength); + while (offset < committedInputs.length) { + ProofType retrievedProofType = ProofType(uint8(committedInputs[offset])); + uint16 length = uint16(bytes2(committedInputs[offset + 1:offset + 3])); + offset += 3; + if (proofType == retrievedProofType && length == CommittedInputLen.INCL_NATIONALITY) { + for (uint256 j = 0; j < countryListLength; j++) { + countryList[j] = string(committedInputs[offset:offset + 3]); + offset += 3; + } + offset += length - countryListLength * 3; + foundCount++; + } else { + offset += length; + } + } + if (proofType == ProofType.ISSUING_COUNTRY_INCLUSION) { + require(foundCount > 0, "Inclusion country proof inputs not found"); + require(foundCount == 1, "Found multiple inclusion country proofs, the proof should only have one"); + } else if (proofType == ProofType.ISSUING_COUNTRY_EXCLUSION) { + require(foundCount > 0, "Exclusion country proof inputs not found"); + require(foundCount == 1, "Found multiple exclusion country proofs, the proof should only have one"); + } else if (proofType == ProofType.NATIONALITY_INCLUSION) { + require(foundCount > 0, "Inclusion nationality proof inputs not found"); + require(foundCount == 1, "Found multiple inclusion nationality proofs, the proof should only have one"); + } else if (proofType == ProofType.NATIONALITY_EXCLUSION) { + require(foundCount > 0, "Exclusion nationality proof inputs not found"); + require(foundCount == 1, "Found multiple exclusion nationality proofs, the proof should only have one"); + } + } + + function getBindProofInputs(bytes calldata committedInputs) public pure returns (bytes memory data) { + uint256 offset = 0; + uint256 foundCount = 0; + while (offset < committedInputs.length) { + ProofType retrievedProofType = ProofType(uint8(committedInputs[offset])); + uint16 length = uint16(bytes2(committedInputs[offset + 1:offset + 3])); + offset += 3; + if (retrievedProofType == ProofType.BIND && length == CommittedInputLen.BIND) { + data = committedInputs[offset:offset + BOUND_DATA_LENGTH]; + foundCount++; + } + offset += length; + } + require(foundCount > 0, "Bind data proof inputs not found"); + require(foundCount == 1, "Found multiple bind data proofs, the proof should only have one"); + } + + function getSanctionsProofInputs(bytes calldata committedInputs) + public + pure + returns (bytes32 sanctionsTreesCommitment, bool isStrict) + { + uint256 offset = 0; + uint256 foundCount = 0; + while (offset < committedInputs.length) { + ProofType retrievedProofType = ProofType(uint8(committedInputs[offset])); + uint16 length = uint16(bytes2(committedInputs[offset + 1:offset + 3])); + offset += 3; + if (retrievedProofType == ProofType.SANCTIONS && length == CommittedInputLen.SANCTIONS) { + sanctionsTreesCommitment = bytes32(committedInputs[offset:offset + 32]); + isStrict = uint8(committedInputs[offset + 32]) == 1; + foundCount++; + } + offset += length; + } + require(foundCount > 0, "Sanctions proof inputs not found"); + require(foundCount == 1, "Found multiple sanctions proofs, the proof should only have one"); + } + + function getBoundData(bytes calldata data) + public + pure + returns (address senderAddress, uint256 chainId, string memory customData) + { + uint256 offset = 0; + while (offset < BOUND_DATA_LENGTH) { + if (data[offset] == bytes1(uint8(BoundDataIdentifier.USER_ADDRESS))) { + uint16 addressLength = uint16(bytes2(data[offset + 1:offset + 3])); + senderAddress = address(bytes20(data[offset + 3:offset + 3 + addressLength])); + offset += 2 + addressLength + 1; + } else if (data[offset] == bytes1(uint8(BoundDataIdentifier.CHAIN_ID))) { + uint16 chainIdLength = uint16(bytes2(data[offset + 1:offset + 3])); + require(chainIdLength <= 32, "Chain id length too long"); + // bytes32 right pads while we want to left pad + // so we shift the bytes to the right by 256 - (chainIdLength * 8) + chainId = uint256(bytes32(data[offset + 3:offset + 3 + chainIdLength]) >> (256 - (chainIdLength * 8))); + offset += 2 + chainIdLength + 1; + } else if (data[offset] == bytes1(uint8(BoundDataIdentifier.CUSTOM_DATA))) { + uint16 customDataLength = uint16(bytes2(data[offset + 1:offset + 3])); + customData = string(data[offset + 3:offset + 3 + customDataLength]); + offset += 2 + customDataLength + 1; + } else { + // Check that the data length is valid + require(offset > 0 && offset <= BOUND_DATA_LENGTH, "Invalid data length"); + // Check that the padding is valid + for (uint256 i = offset; i < BOUND_DATA_LENGTH; i++) { + require(data[i] == 0, "Invalid padding"); + } + break; + } + } + } + + function getFacematchProofInputs(bytes calldata committedInputs) + public + pure + returns ( + bytes32 rootKeyHash, + Environment environment, + bytes32 appIdHash, + bytes32 integrityPublicKeyHash, + FaceMatchMode facematchMode + ) + { + uint256 offset = 0; + uint256 foundCount = 0; + while (offset < committedInputs.length) { + ProofType retrievedProofType = ProofType(uint8(committedInputs[offset])); + uint16 length = uint16(bytes2(committedInputs[offset + 1:offset + 3])); + offset += 3; + if (retrievedProofType == ProofType.FACEMATCH && length == CommittedInputLen.FACEMATCH) { + rootKeyHash = bytes32(committedInputs[offset:offset + 32]); + environment = Environment(uint8(committedInputs[offset + 32])); + appIdHash = bytes32(committedInputs[offset + 33:offset + 65]); + integrityPublicKeyHash = bytes32(committedInputs[offset + 65:offset + 97]); + facematchMode = FaceMatchMode(uint8(committedInputs[offset + 97])); + foundCount++; + } + offset += length; + } + require(foundCount > 0, "Facematch proof inputs not found"); + require(foundCount == 1, "Found multiple facematch proofs, the proof should only have one"); + } +} diff --git a/packages/registry-contracts/src/lib/StringUtils.sol b/packages/registry-contracts/src/lib/StringUtils.sol new file mode 100644 index 00000000..1718d347 --- /dev/null +++ b/packages/registry-contracts/src/lib/StringUtils.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright © 2026 ZKPassport +/* + ______ _ _ _____ _______ _______ _______ _____ _____ ______ _______ + ____/ |____/ |_____] |_____| |______ |______ |_____] | | |_____/ | + /_____ | \_ | | | ______| ______| | |_____| | \_ | + +*/ + +pragma solidity ^0.8.30; + +library StringUtils { + function equals(string memory a, string memory b) internal pure returns (bool) { + return keccak256(bytes(a)) == keccak256(bytes(b)); + } + + function isEmpty(string memory a) internal pure returns (bool) { + return bytes(a).length == 0; + } +} diff --git a/packages/registry-contracts/src/lib/Types.sol b/packages/registry-contracts/src/lib/Types.sol new file mode 100644 index 00000000..a6422109 --- /dev/null +++ b/packages/registry-contracts/src/lib/Types.sol @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright © 2026 ZKPassport +/* + ______ _ _ _____ _______ _______ _______ _____ _____ ______ _______ + ____/ |____/ |_____] |_____| |______ |______ |_____] | | |_____/ | + /_____ | \_ | | | ______| ______| | |_____| | \_ | + +*/ + +pragma solidity ^0.8.30; + +struct ProofVerifier { + bytes32 vkeyHash; + address verifier; +} + +enum ProofType { + DISCLOSE, + AGE, + BIRTHDATE, + EXPIRY_DATE, + NATIONALITY_INCLUSION, + NATIONALITY_EXCLUSION, + ISSUING_COUNTRY_INCLUSION, + ISSUING_COUNTRY_EXCLUSION, + BIND, + SANCTIONS, + FACEMATCH +} + +enum BoundDataIdentifier { + NONE, + USER_ADDRESS, + CHAIN_ID, + CUSTOM_DATA +} + +enum FaceMatchMode { + NONE, + REGULAR, + STRICT +} + +enum Environment { + DEVELOPMENT, + PRODUCTION +} + +enum NullifierType { + NON_SALTED_NULLIFIER, + SALTED_NULLIFIER, + NON_SALTED_MOCK_NULLIFIER, + SALTED_MOCK_NULLIFIER +} + +enum OS { + ANY, + IOS, + ANDROID +} + +// ProofVerificationParams +// │ +// ├── bytes32 version // Version identifier of the verifier +// │ +// ├── ProofVerificationData proofVerificationData +// │ ├── bytes32 vkeyHash // Verification key hash +// │ ├── bytes proof // The actual ZK proof +// │ └── bytes32[] publicInputs // Array of public inputs (7+ elements) +// │ │ // Use PublicInputsCast.asStruct() for structured access: +// │ ├── [0] certificate_registry_root // Field - struct.certificateRegistryRoot +// │ ├── [1] circuit_registry_root // Field - struct.circuitRegistryRoot +// │ ├── [2] current_date // u64 - PublicInputsCast.getCurrentDate(struct) +// │ ├── [3] service_scope // Field - struct.serviceScope +// │ ├── [4] service_subscope // Field - struct.serviceSubscope +// │ ├── [5:5+N] param_commitments // Field[N] - PublicInputsCast.getParamCommitment(array, index) +// │ ├── [5+N] nullifier_type // u8 - PublicInputsCast.getNullifierType(array, paramCount) +// │ ├── [6+N] scoped_nullifier // Field - PublicInputsCast.getScopedNullifier(array, paramCount) +// │ └── [7+N] oprf_pk_hash // Poseidon2(pk.x, pk.y) for SALTED, 0 for NON_SALTED +// │ +// ├── bytes committedInputs // Preimages of param_commitments +// │ +// └── ServiceConfig serviceConfig +// ├── uint256 validityPeriodInSeconds // How long the proof is valid +// ├── string domain // Service domain +// ├── string scope // Service scope +// ├── bool devMode // Development mode flag +// └── bytes32 oprfPubKeyHash // Per-service OPRF pk hash override; 0 = use SubVerifier default +struct ProofVerificationParams { + bytes32 version; + ProofVerificationData proofVerificationData; + bytes committedInputs; + ServiceConfig serviceConfig; +} + +struct ProofVerificationData { + bytes32 vkeyHash; + bytes proof; + bytes32[] publicInputs; +} + +struct ServiceConfig { + uint256 validityPeriodInSeconds; + string domain; + string scope; + bool devMode; + // Temporarily disabled to match the deployed RootVerifier ABI + // bytes32 oprfPubKeyHash; +} + +struct DisclosedData { + string name; + string issuingCountry; + string nationality; + string gender; + string birthDate; + string expiryDate; + string documentNumber; + string documentType; +} + +struct BoundData { + address senderAddress; + uint256 chainId; + string customData; +} diff --git a/packages/registry-contracts/src/mocks/MockHonkVerifier.sol b/packages/registry-contracts/src/mocks/MockHonkVerifier.sol new file mode 100644 index 00000000..4519bff7 --- /dev/null +++ b/packages/registry-contracts/src/mocks/MockHonkVerifier.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.30; + +contract HonkVerifier { + function verify(bytes calldata, bytes32[] calldata) external pure returns (bool) { + return true; + } +} diff --git a/packages/registry-contracts/src/CertificateRegistry.sol b/packages/registry-contracts/src/registries/CertificateRegistry.sol similarity index 80% rename from packages/registry-contracts/src/CertificateRegistry.sol rename to packages/registry-contracts/src/registries/CertificateRegistry.sol index 439a614a..5ca93914 100644 --- a/packages/registry-contracts/src/CertificateRegistry.sol +++ b/packages/registry-contracts/src/registries/CertificateRegistry.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -// Copyright © 2025 ZKPassport +// Copyright © 2026 ZKPassport /* ______ _ _ _____ _______ _______ _______ _____ _____ ______ _______ ____/ |____/ |_____] |_____| |______ |______ |_____] | | |_____/ | @@ -9,8 +9,8 @@ pragma solidity ^0.8.30; -import {RegistryInstance} from "./RegistryInstance.sol"; -import {RootValidationMode} from "./IRegistryInstance.sol"; +import {RegistryInstance} from "../RegistryInstance.sol"; +import {RootValidationMode} from "../IRegistryInstance.sol"; /** * @title CertificateRegistry diff --git a/packages/registry-contracts/src/CircuitRegistry.sol b/packages/registry-contracts/src/registries/CircuitRegistry.sol similarity index 80% rename from packages/registry-contracts/src/CircuitRegistry.sol rename to packages/registry-contracts/src/registries/CircuitRegistry.sol index cb81e4d1..34d54854 100644 --- a/packages/registry-contracts/src/CircuitRegistry.sol +++ b/packages/registry-contracts/src/registries/CircuitRegistry.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -// Copyright © 2025 ZKPassport +// Copyright © 2026 ZKPassport /* ______ _ _ _____ _______ _______ _______ _____ _____ ______ _______ ____/ |____/ |_____] |_____| |______ |______ |_____] | | |_____/ | @@ -9,8 +9,8 @@ pragma solidity ^0.8.30; -import {RegistryInstance} from "./RegistryInstance.sol"; -import {RootValidationMode} from "./IRegistryInstance.sol"; +import {RegistryInstance} from "../RegistryInstance.sol"; +import {RootValidationMode} from "../IRegistryInstance.sol"; /** * @title CircuitRegistry diff --git a/packages/registry-contracts/src/SanctionsRegistry.sol b/packages/registry-contracts/src/registries/SanctionsRegistry.sol similarity index 80% rename from packages/registry-contracts/src/SanctionsRegistry.sol rename to packages/registry-contracts/src/registries/SanctionsRegistry.sol index 0cd235e6..55a65c1d 100644 --- a/packages/registry-contracts/src/SanctionsRegistry.sol +++ b/packages/registry-contracts/src/registries/SanctionsRegistry.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -// Copyright © 2025 ZKPassport +// Copyright © 2026 ZKPassport /* ______ _ _ _____ _______ _______ _______ _____ _____ ______ _______ ____/ |____/ |_____] |_____| |______ |______ |_____] | | |_____/ | @@ -9,8 +9,8 @@ pragma solidity ^0.8.30; -import {RegistryInstance} from "./RegistryInstance.sol"; -import {RootValidationMode} from "./IRegistryInstance.sol"; +import {RegistryInstance} from "../RegistryInstance.sol"; +import {RootValidationMode} from "../IRegistryInstance.sol"; /** * @title SanctionsRegistry diff --git a/packages/registry-contracts/test/ProtocolController.t.sol b/packages/registry-contracts/test/ProtocolController.t.sol new file mode 100644 index 00000000..b6b99363 --- /dev/null +++ b/packages/registry-contracts/test/ProtocolController.t.sol @@ -0,0 +1,454 @@ +pragma solidity ^0.8.30; + +import "forge-std/Test.sol"; +import "../src/ProtocolController.sol"; +import {RootRegistry} from "../src/RootRegistry.sol"; +import {RootVerifier} from "../src/RootVerifier.sol"; + +contract ProtocolControllerTest is Test { + RootRegistry public rootRegistry; + RootVerifier public rootVerifier; + ProtocolController public controller; + + address public admin = makeAddr("admin"); + address public registryOperator = makeAddr("registryOperator"); + address public verifierOperator = makeAddr("verifierOperator"); + address public user = makeAddr("user"); + address public newAddr = makeAddr("newAddr"); + + function setUp() public { + rootRegistry = new RootRegistry(address(this), address(0)); + rootVerifier = new RootVerifier(address(this), address(0), RootRegistry(address(0))); + controller = new ProtocolController({ + _admin: admin, + _rootRegistry: address(rootRegistry), + _rootRegistryOperator: registryOperator, + _rootVerifier: address(rootVerifier), + _rootVerifierOperator: verifierOperator + }); + + rootRegistry.transferAdmin(address(controller)); + rootVerifier.transferAdmin(address(controller)); + } + + // ===== Deployment ===== + + function testDeployment() public view { + assertEq(controller.admin(), admin); + assertEq(controller.rootRegistryOperator(), registryOperator); + assertEq(controller.rootVerifierOperator(), verifierOperator); + assertEq(address(controller.rootRegistry()), address(rootRegistry)); + assertEq(address(controller.rootVerifier()), address(rootVerifier)); + } + + function testDeployRevertsWithZeroAdmin() public { + vm.expectRevert("Admin cannot be zero address"); + new ProtocolController( + address(0), address(rootRegistry), registryOperator, address(rootVerifier), verifierOperator + ); + } + + // ===== Admin: two-step admin transfer ===== + + function testTransferAdmin() public { + // Step 1: admin initiates transfer + vm.prank(admin); + controller.transferAdmin(newAddr); + assertEq(controller.pendingAdmin(), newAddr); + assertEq(controller.admin(), admin); + + // Step 2: new admin accepts + vm.prank(newAddr); + controller.acceptAdmin(); + assertEq(controller.admin(), newAddr); + assertEq(controller.pendingAdmin(), address(0)); + + // New admin can act, old admin cannot + vm.prank(newAddr); + controller.setRootRegistryOperator(user); + assertEq(controller.rootRegistryOperator(), user); + + vm.prank(admin); + vm.expectRevert("Not authorized: admin only"); + controller.setRootRegistryOperator(user); + } + + function testTransferAdminReverts() public { + vm.prank(user); + vm.expectRevert("Not authorized: admin only"); + controller.transferAdmin(newAddr); + + vm.prank(admin); + vm.expectRevert("Admin cannot be zero address"); + controller.transferAdmin(address(0)); + } + + function testAcceptAdminRevertsForNonPendingAdmin() public { + vm.prank(admin); + controller.transferAdmin(newAddr); + + vm.prank(user); + vm.expectRevert("Not authorized: pending admin only"); + controller.acceptAdmin(); + + // Original admin also cannot accept + vm.prank(admin); + vm.expectRevert("Not authorized: pending admin only"); + controller.acceptAdmin(); + } + + function testAdminCanOverwritePendingAdmin() public { + vm.prank(admin); + controller.transferAdmin(newAddr); + assertEq(controller.pendingAdmin(), newAddr); + + // Admin changes their mind + vm.prank(admin); + controller.transferAdmin(user); + assertEq(controller.pendingAdmin(), user); + + // Old pending admin can no longer accept + vm.prank(newAddr); + vm.expectRevert("Not authorized: pending admin only"); + controller.acceptAdmin(); + + // New pending admin can accept + vm.prank(user); + controller.acceptAdmin(); + assertEq(controller.admin(), user); + } + + // ===== Admin: operator role management ===== + + function testSetRootRegistryOperator() public { + vm.prank(admin); + controller.setRootRegistryOperator(newAddr); + assertEq(controller.rootRegistryOperator(), newAddr); + } + + function testSetRootVerifierOperator() public { + vm.prank(admin); + controller.setRootVerifierOperator(newAddr); + assertEq(controller.rootVerifierOperator(), newAddr); + } + + function testSetOperatorRolesRevertsForNonAdmin() public { + vm.startPrank(user); + vm.expectRevert("Not authorized: admin only"); + controller.setRootRegistryOperator(newAddr); + vm.expectRevert("Not authorized: admin only"); + controller.setRootVerifierOperator(newAddr); + vm.stopPrank(); + } + + // ===== Admin: restore underlying contract admins ===== + + function testRestoreRootRegistryAdmin() public { + vm.prank(admin); + controller.restoreRootRegistryAdmin(); + assertEq(rootRegistry.admin(), admin); + } + + function testRestoreRootVerifierAdmin() public { + vm.prank(admin); + controller.restoreRootVerifierAdmin(); + assertEq(rootVerifier.admin(), admin); + } + + function testRestoreContractAdminsRevertsForNonAdmin() public { + vm.startPrank(user); + vm.expectRevert("Not authorized: admin only"); + controller.restoreRootRegistryAdmin(); + vm.expectRevert("Not authorized: admin only"); + controller.restoreRootVerifierAdmin(); + vm.stopPrank(); + } + + // ===== Registry operator: delegation ===== + + function testRegistryOperatorDelegation() public { + bytes32 id = keccak256("registry1"); + bytes32 k = keccak256("key"); + bytes32 val = keccak256("val"); + address anotherAddr = makeAddr("anotherAddr"); + + vm.startPrank(registryOperator); + + controller.rootRegistry_addRegistry(id, newAddr); + assertEq(address(rootRegistry.registries(id)), newAddr); + + controller.rootRegistry_updateRegistry(id, anotherAddr); + assertEq(address(rootRegistry.registries(id)), anotherAddr); + + controller.rootRegistry_removeRegistry(id); + assertEq(address(rootRegistry.registries(id)), address(0)); + + controller.rootRegistry_setGuardian(newAddr); + assertEq(rootRegistry.guardian(), newAddr); + + controller.rootRegistry_updateConfig(k, val); + assertEq(rootRegistry.config(k), val); + + controller.rootRegistry_pause(); + assertTrue(rootRegistry.paused()); + + controller.rootRegistry_unpause(); + assertFalse(rootRegistry.paused()); + + vm.stopPrank(); + } + + function testRegistryOperatorFunctionsRevertForUnauthorized() public { + bytes32 id = keccak256("r"); + + vm.startPrank(user); + vm.expectRevert("Not authorized: admin or root registry operator only"); + controller.rootRegistry_addRegistry(id, newAddr); + vm.expectRevert("Not authorized: admin or root registry operator only"); + controller.rootRegistry_updateRegistry(id, newAddr); + vm.expectRevert("Not authorized: admin or root registry operator only"); + controller.rootRegistry_removeRegistry(id); + vm.expectRevert("Not authorized: admin or root registry operator only"); + controller.rootRegistry_setGuardian(newAddr); + vm.expectRevert("Not authorized: admin or root registry operator only"); + controller.rootRegistry_updateConfig(id, id); + vm.expectRevert("Not authorized: admin or root registry operator only"); + controller.rootRegistry_pause(); + vm.expectRevert("Not authorized: admin or root registry operator only"); + controller.rootRegistry_unpause(); + vm.stopPrank(); + } + + function testAdminCanCallRegistryFunctions() public { + bytes32 id = keccak256("registry1"); + vm.prank(admin); + controller.rootRegistry_addRegistry(id, newAddr); + assertEq(address(rootRegistry.registries(id)), newAddr); + } + + // ===== Verifier operator: delegation ===== + + function testVerifierOperatorDelegation() public { + bytes32 v = keccak256("v1"); + bytes32 k = keccak256("key"); + bytes32 val = keccak256("val"); + + vm.startPrank(verifierOperator); + + controller.rootVerifier_addSubVerifier(v, newAddr); + assertEq(rootVerifier.getSubVerifier(v), newAddr); + + controller.rootVerifier_updateSubVerifier(v, user); + assertEq(rootVerifier.getSubVerifier(v), user); + + controller.rootVerifier_removeSubVerifier(v); + assertEq(rootVerifier.getSubVerifier(v), address(0)); + + controller.rootVerifier_addHelper(v, newAddr); + assertEq(rootVerifier.getHelper(v), newAddr); + + controller.rootVerifier_updateHelper(v, user); + assertEq(rootVerifier.getHelper(v), user); + + controller.rootVerifier_removeHelper(v); + assertEq(rootVerifier.getHelper(v), address(0)); + + controller.rootVerifier_setGuardian(newAddr); + assertEq(rootVerifier.guardian(), newAddr); + + controller.rootVerifier_updateConfig(k, val); + assertEq(rootVerifier.config(k), val); + + controller.rootVerifier_pause(); + assertTrue(rootVerifier.paused()); + + controller.rootVerifier_unpause(); + assertFalse(rootVerifier.paused()); + + vm.stopPrank(); + } + + function testVerifierOperatorFunctionsRevertForUnauthorized() public { + bytes32 v = keccak256("v1"); + + vm.startPrank(user); + vm.expectRevert("Not authorized: admin or root verifier operator only"); + controller.rootVerifier_addSubVerifier(v, newAddr); + vm.expectRevert("Not authorized: admin or root verifier operator only"); + controller.rootVerifier_removeSubVerifier(v); + vm.expectRevert("Not authorized: admin or root verifier operator only"); + controller.rootVerifier_updateSubVerifier(v, newAddr); + vm.expectRevert("Not authorized: admin or root verifier operator only"); + controller.rootVerifier_addHelper(v, newAddr); + vm.expectRevert("Not authorized: admin or root verifier operator only"); + controller.rootVerifier_removeHelper(v); + vm.expectRevert("Not authorized: admin or root verifier operator only"); + controller.rootVerifier_updateHelper(v, newAddr); + vm.expectRevert("Not authorized: admin or root verifier operator only"); + controller.rootVerifier_setGuardian(newAddr); + vm.expectRevert("Not authorized: admin or root verifier operator only"); + controller.rootVerifier_updateConfig(v, v); + vm.expectRevert("Not authorized: admin or root verifier operator only"); + controller.rootVerifier_pause(); + vm.expectRevert("Not authorized: admin or root verifier operator only"); + controller.rootVerifier_unpause(); + vm.stopPrank(); + } + + function testAdminCanCallVerifierFunctions() public { + bytes32 v = keccak256("v1"); + vm.prank(admin); + controller.rootVerifier_addSubVerifier(v, newAddr); + assertEq(rootVerifier.getSubVerifier(v), newAddr); + } + + // ===== Cross-role isolation ===== + + function testCrossRoleIsolation() public { + vm.prank(registryOperator); + vm.expectRevert("Not authorized: admin or root verifier operator only"); + controller.rootVerifier_pause(); + + vm.prank(verifierOperator); + vm.expectRevert("Not authorized: admin or root registry operator only"); + controller.rootRegistry_pause(); + } + + function testOperatorsCannotCallAdminOnlyFunctions() public { + vm.prank(registryOperator); + vm.expectRevert("Not authorized: admin only"); + controller.transferAdmin(newAddr); + + vm.prank(verifierOperator); + vm.expectRevert("Not authorized: admin only"); + controller.transferAdmin(newAddr); + } + + // ===== Operator role reassignment ===== + + function testNewRegistryOperatorCanActAfterReassignment() public { + vm.prank(admin); + controller.setRootRegistryOperator(newAddr); + + vm.prank(newAddr); + controller.rootRegistry_pause(); + assertTrue(rootRegistry.paused()); + + vm.prank(registryOperator); + vm.expectRevert("Not authorized: admin or root registry operator only"); + controller.rootRegistry_unpause(); + } + + function testNewVerifierOperatorCanActAfterReassignment() public { + vm.prank(admin); + controller.setRootVerifierOperator(newAddr); + + vm.prank(newAddr); + controller.rootVerifier_pause(); + assertTrue(rootVerifier.paused()); + + vm.prank(verifierOperator); + vm.expectRevert("Not authorized: admin or root verifier operator only"); + controller.rootVerifier_unpause(); + } + + // ===== Admin transfer round-trip ===== + + function testRootRegistryAdminTransferToControllerAndBack() public { + address multisig = makeAddr("multisig"); + + RootRegistry freshRegistry = new RootRegistry(multisig, address(0)); + assertEq(freshRegistry.admin(), multisig); + + ProtocolController ctrl = new ProtocolController({ + _admin: multisig, + _rootRegistry: address(freshRegistry), + _rootRegistryOperator: address(0), + _rootVerifier: address(0), + _rootVerifierOperator: address(0) + }); + + // Multisig transfers RootRegistry admin to the controller + vm.prank(multisig); + freshRegistry.transferAdmin(address(ctrl)); + assertEq(freshRegistry.admin(), address(ctrl)); + + // Multisig can no longer act directly on the RootRegistry + vm.prank(multisig); + vm.expectRevert("Not authorized: admin or guardian only"); + freshRegistry.pause(); + + // Controller (via multisig as admin) can now act on the RootRegistry + vm.prank(multisig); + ctrl.rootRegistry_pause(); + assertTrue(freshRegistry.paused()); + + vm.prank(multisig); + ctrl.rootRegistry_unpause(); + assertFalse(freshRegistry.paused()); + + // Multisig (as controller admin) transfers RootRegistry admin back to itself + vm.prank(multisig); + ctrl.restoreRootRegistryAdmin(); + assertEq(freshRegistry.admin(), multisig); + + // Controller can no longer act on the RootRegistry + vm.prank(multisig); + vm.expectRevert("Not authorized: admin or guardian only"); + ctrl.rootRegistry_pause(); + + // Multisig can act directly on the RootRegistry again + vm.prank(multisig); + freshRegistry.pause(); + assertTrue(freshRegistry.paused()); + } + + function testRootVerifierAdminTransferToControllerAndBack() public { + address multisig = makeAddr("multisig"); + + RootVerifier freshVerifier = new RootVerifier(multisig, address(0), RootRegistry(address(0))); + assertEq(freshVerifier.admin(), multisig); + + ProtocolController ctrl = new ProtocolController({ + _admin: multisig, + _rootRegistry: address(0), + _rootRegistryOperator: address(0), + _rootVerifier: address(freshVerifier), + _rootVerifierOperator: address(0) + }); + + // Multisig transfers RootVerifier admin to the controller + vm.prank(multisig); + freshVerifier.transferAdmin(address(ctrl)); + assertEq(freshVerifier.admin(), address(ctrl)); + + // Multisig can no longer act directly on the RootVerifier + vm.prank(multisig); + vm.expectRevert("Not authorized: admin or guardian only"); + freshVerifier.pause(); + + // Controller (via multisig as admin) can now act on the RootVerifier + vm.prank(multisig); + ctrl.rootVerifier_pause(); + assertTrue(freshVerifier.paused()); + + vm.prank(multisig); + ctrl.rootVerifier_unpause(); + assertFalse(freshVerifier.paused()); + + // Multisig (as controller admin) transfers RootVerifier admin back to itself + vm.prank(multisig); + ctrl.restoreRootVerifierAdmin(); + assertEq(freshVerifier.admin(), multisig); + + // Controller can no longer act on the RootVerifier + vm.prank(multisig); + vm.expectRevert("Not authorized: admin or guardian only"); + ctrl.rootVerifier_pause(); + + // Multisig can act directly on the RootVerifier again + vm.prank(multisig); + freshVerifier.pause(); + assertTrue(freshVerifier.paused()); + } +} diff --git a/packages/registry-contracts/test/RegistryHelper.t.sol b/packages/registry-contracts/test/RegistryHelper.t.sol index 7ca40745..e56791b6 100644 --- a/packages/registry-contracts/test/RegistryHelper.t.sol +++ b/packages/registry-contracts/test/RegistryHelper.t.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.30; import "forge-std/Test.sol"; import "../src/RootRegistry.sol"; -import "../src/CertificateRegistry.sol"; +import "../src/registries/CertificateRegistry.sol"; import "../src/RegistryHelper.sol"; import {TestConstants} from "./TestConstants.sol"; import {MockRegistry} from "./MockRegistry.sol"; @@ -347,6 +347,53 @@ contract RegistryHelperTest is Test { helper.getRootDetailsByRoot(CERTIFICATE_REGISTRY_ID, bytes32(uint256(1))); } + function testRootDetailsIncludesMetadataFields() public { + bytes32 root1 = bytes32(uint256(1)); + bytes32 root2 = bytes32(uint256(2)); + bytes32 ipfsCid1 = bytes32(uint256(100)); + bytes32 ipfsCid2 = bytes32(uint256(200)); + bytes32 m1a = bytes32(uint256(0xaaaa)); + bytes32 m2a = bytes32(uint256(0xbbbb)); + bytes32 m3a = bytes32(uint256(0xcccc)); + bytes32 m1b = bytes32(uint256(0xdddd)); + bytes32 m2b = bytes32(uint256(0xeeee)); + bytes32 m3b = bytes32(uint256(0xffff)); + + vm.prank(oracle); + registry.updateRootWithMetadata(root1, bytes32(0), block.timestamp, 100, ipfsCid1, m1a, m2a, m3a); + vm.warp(block.timestamp + 1); + vm.prank(oracle); + registry.updateRootWithMetadata(root2, root1, block.timestamp, 200, ipfsCid2, m1b, m2b, m3b); + + // getRootDetailsByRoot exposes metadata + RegistryHelper.RootDetails memory byRoot = helper.getRootDetailsByRoot(CERTIFICATE_REGISTRY_ID, root1); + assertEq(byRoot.metadata1, m1a); + assertEq(byRoot.metadata2, m2a); + assertEq(byRoot.metadata3, m3a); + + // getRootDetailsByIndex exposes metadata + RegistryHelper.RootDetails memory byIndex = helper.getRootDetailsByIndex(CERTIFICATE_REGISTRY_ID, 2); + assertEq(byIndex.metadata1, m1b); + assertEq(byIndex.metadata2, m2b); + assertEq(byIndex.metadata3, m3b); + + // getLatestRootDetails exposes metadata + RegistryHelper.RootDetails memory latest = helper.getLatestRootDetails(CERTIFICATE_REGISTRY_ID); + assertEq(latest.metadata1, m1b); + assertEq(latest.metadata2, m2b); + assertEq(latest.metadata3, m3b); + + // getHistoricalRoots exposes metadata for each entry + (RegistryHelper.RootDetails[] memory page,) = helper.getHistoricalRoots(CERTIFICATE_REGISTRY_ID, 1, 10); + assertEq(page.length, 2); + assertEq(page[0].metadata1, m1a); + assertEq(page[0].metadata2, m2a); + assertEq(page[0].metadata3, m3a); + assertEq(page[1].metadata1, m1b); + assertEq(page[1].metadata2, m2b); + assertEq(page[1].metadata3, m3b); + } + function testIsRootValidAtTimestamp() public { // Set up registry with valid mock vm.prank(admin); diff --git a/packages/registry-contracts/test/RootRegistry.t.sol b/packages/registry-contracts/test/RootRegistry.t.sol index 015aeb03..4737e475 100644 --- a/packages/registry-contracts/test/RootRegistry.t.sol +++ b/packages/registry-contracts/test/RootRegistry.t.sol @@ -200,6 +200,38 @@ contract RootRegistryTest is Test { registry.addRegistry(circuitRegistryId, mockValidRegistry); } + function testTransferAdminRoundTrip() public { + address multisig = makeAddr("multisig"); + + // Admin (acting as initial deployer) transfers to multisig + vm.prank(admin); + registry.transferAdmin(multisig); + assertEq(registry.admin(), multisig); + + // Old admin can no longer act + vm.prank(admin); + vm.expectRevert("Not authorized: admin only"); + registry.addRegistry(certificateRegistryId, mockValidRegistry); + + // Multisig can act + vm.prank(multisig); + registry.addRegistry(certificateRegistryId, mockValidRegistry); + + // Multisig transfers back to original admin + vm.prank(multisig); + registry.transferAdmin(admin); + assertEq(registry.admin(), admin); + + // Original admin can act again + vm.prank(admin); + registry.addRegistry(circuitRegistryId, mockValidRegistry); + + // Multisig can no longer act + vm.prank(multisig); + vm.expectRevert("Not authorized: admin only"); + registry.addRegistry(keccak256("another"), mockValidRegistry); + } + function testCannotTransferAdminToZeroAddress() public { // Admin tries to transfer admin role to zero address vm.prank(admin); diff --git a/packages/registry-explorer/app/certificates/diff/page.tsx b/packages/registry-explorer/app/certificates/diff/page.tsx index a8c29544..01938c07 100644 --- a/packages/registry-explorer/app/certificates/diff/page.tsx +++ b/packages/registry-explorer/app/certificates/diff/page.tsx @@ -4,50 +4,399 @@ import { Button } from "@/components/ui/button" import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" import { LoadingAnimation } from "@/components/LoadingAnimation" import { Alert, AlertDescription } from "@/components/ui/alert" -import { ArrowLeft, AlertCircle, GitCompare, ArrowUpDown } from "lucide-react" +import { + ArrowLeft, + AlertCircle, + GitCompare, + ArrowUpDown, + ChevronDown, + ChevronUp, + ChevronLeft, + ChevronRight, +} from "lucide-react" import Link from "next/link" import { useSearchParams, useRouter } from "next/navigation" -import { useEffect, useState, Suspense } from "react" -import { PackagedCertificatesFile } from "@zkpassport/registry" -import { countryCodeAlpha3ToName, PackagedCertificate } from "@zkpassport/utils" -import { getCertificateUrl, getChainId } from "@/lib/certificate-url" +import { useEffect, useState, useMemo, Suspense } from "react" +import { + countryCodeAlpha3ToName, + PackagedCertificate, + PackagedCertificatesFile, + BRAINPOOL_CURVES_ABBR as BRAINPOOL_ABBR, +} from "@zkpassport/utils" +import { normalizeHash } from "@/lib/utils" +import { getCertificateUrl } from "@/lib/certificate-url" +import { useHistoricalCertificateRoots } from "@/hooks/useHistoricalCertificateRoots" +import { useNetwork } from "@/components/NetworkProvider" + +// ─── Types ──────────────────────────────────────────────────────────────────── interface DiffState { beforeData: PackagedCertificatesFile | null afterData: PackagedCertificatesFile | null + beforeRootHash: string | null + afterRootHash: string | null + beforeUrl: string | null + afterUrl: string | null isLoading: boolean error: string | null } +type ChangeCategory = + | "added" + | "removed" + | "trust_increased" + | "trust_decreased" + | "trust_changed" + | "other" + +interface FieldChange { + field: string + oldValue: string + newValue: string +} + interface CertificateChange { certificate: PackagedCertificate - changeType: "added" | "removed" | "modified" + changeType: ChangeCategory + beforeCertificate?: PackagedCertificate oldTags?: string[] newTags?: string[] - oldHashAlgorithm?: string - newHashAlgorithm?: string + fieldChanges?: FieldChange[] } interface CertificateDiff { - added: PackagedCertificate[] - removed: PackagedCertificate[] - modified: CertificateChange[] + added: CertificateChange[] + removed: CertificateChange[] + trustIncreased: CertificateChange[] + trustDecreased: CertificateChange[] + trustChanged: CertificateChange[] + other: CertificateChange[] +} + +// ─── Category display order & styling ───────────────────────────────────────── + +const CATEGORY_ORDER: ChangeCategory[] = [ + "added", + "removed", + "trust_increased", + "trust_decreased", + "trust_changed", + "other", +] + +const CATEGORY_CONFIG: Record< + ChangeCategory, + { + label: string + summarySign: string + icon: string + color: string + darkColor: string + bg: string + border: string + } +> = { + added: { + label: "Added", + summarySign: "+", + icon: "+", + color: "text-green-600", + darkColor: "dark:text-green-400", + bg: "bg-green-50 dark:bg-green-900/20", + border: "border-green-200 dark:border-green-800", + }, + removed: { + label: "Removed", + summarySign: "−", + icon: "−", + color: "text-red-600", + darkColor: "dark:text-red-400", + bg: "bg-red-50 dark:bg-red-900/20", + border: "border-red-200 dark:border-red-800", + }, + trust_increased: { + label: "Trust Increased", + summarySign: "↑", + icon: "↑", + color: "text-teal-600", + darkColor: "dark:text-teal-400", + bg: "bg-teal-50 dark:bg-teal-900/20", + border: "border-teal-200 dark:border-teal-800", + }, + trust_decreased: { + label: "Trust Decreased", + summarySign: "↓", + icon: "↓", + color: "text-amber-600", + darkColor: "dark:text-amber-400", + bg: "bg-amber-50 dark:bg-amber-900/20", + border: "border-amber-200 dark:border-amber-800", + }, + trust_changed: { + label: "Trust Changed", + summarySign: "~", + icon: "~", + color: "text-blue-600", + darkColor: "dark:text-blue-400", + bg: "bg-blue-50 dark:bg-blue-900/20", + border: "border-blue-200 dark:border-blue-800", + }, + other: { + label: "Other", + summarySign: "~", + icon: "?", + color: "text-purple-600", + darkColor: "dark:text-purple-400", + bg: "bg-purple-50 dark:bg-purple-900/20", + border: "border-purple-200 dark:border-purple-800", + }, +} + +// ─── Helpers ────────────────────────────────────────────────────────────────── + +/** Normalise legacy "ICAO" tag to "UN" */ +const normalizeTags = (tags?: string[]): string[] => + (tags || []).map((tag: string) => (tag === "ICAO" ? "UN" : tag)) + +// ─── Reusable masterlist tags component ────────────────────────────────────── + +/** Renders masterlist tags with color-coded diffs (added / removed / unchanged). */ +function MasterlistTags({ + oldTags, + newTags, + tags, + showLabel = false, + className = "", +}: { + /** Previous tags (for diff mode) */ + oldTags?: string[] + /** New tags (for diff mode) */ + newTags?: string[] + /** Plain tags when there is no diff */ + tags?: string[] + /** Whether to prefix with "Masterlists:" label */ + showLabel?: boolean + className?: string +}) { + // Diff mode: oldTags & newTags are both provided + if (oldTags && newTags) { + const removedTags = oldTags.filter((t) => !newTags.includes(t)) + const addedTags = newTags.filter((t) => !oldTags.includes(t)) + const unchangedTags = oldTags.filter((t) => newTags.includes(t)) + const allTags = [ + ...removedTags.map((tag) => ({ tag, type: "removed" as const })), + ...addedTags.map((tag) => ({ tag, type: "added" as const })), + ...unchangedTags.map((tag) => ({ tag, type: "unchanged" as const })), + ] + + if (allTags.length === 0) + return showLabel ? Masterlists: None : null + + return ( + + {showLabel && Masterlists: } + {allTags.map(({ tag, type }, i) => ( + + {type === "removed" && ( + {tag} + )} + {type === "added" && ( + {tag} + )} + {type === "unchanged" && {tag}} + {i < allTags.length - 1 && ", "} + + ))} + + ) + } + + // Plain mode: just show the tags + const normalised = normalizeTags(tags) + if (normalised.length === 0) return null + + return ( + + {showLabel && Masterlists: } + {normalised.join(", ")} + + ) +} + +/** Compare every field *except* tags & fingerprint between two certs */ +const detectFieldChanges = ( + before: PackagedCertificate, + after: PackagedCertificate, +): FieldChange[] => { + const changes: FieldChange[] = [] + const fmtDate = (ts: number) => new Date(ts * 1000).toLocaleDateString("en-GB") + + if (before.country !== after.country) { + changes.push({ field: "Country", oldValue: before.country, newValue: after.country }) + } + if (before.signature_algorithm !== after.signature_algorithm) { + changes.push({ + field: "Signature Algorithm", + oldValue: before.signature_algorithm, + newValue: after.signature_algorithm, + }) + } + if (JSON.stringify(before.public_key) !== JSON.stringify(after.public_key)) { + const describeKey = (pk: PackagedCertificate["public_key"]) => { + if (!pk) return "N/A" + if (pk.type === "RSA") return `RSA-${pk.key_size}` + if (pk.type === "EC") return `EC ${pk.curve}` + return "Unknown" + } + changes.push({ + field: "Public Key", + oldValue: describeKey(before.public_key), + newValue: describeKey(after.public_key), + }) + } + if (JSON.stringify(before.validity) !== JSON.stringify(after.validity)) { + changes.push({ + field: "Validity", + oldValue: `${fmtDate(before.validity.not_before)} – ${fmtDate(before.validity.not_after)}`, + newValue: `${fmtDate(after.validity.not_before)} – ${fmtDate(after.validity.not_after)}`, + }) + } + if (before.subject_key_identifier !== after.subject_key_identifier) { + changes.push({ + field: "Subject Key Identifier", + oldValue: before.subject_key_identifier || "N/A", + newValue: after.subject_key_identifier || "N/A", + }) + } + if (before.authority_key_identifier !== after.authority_key_identifier) { + changes.push({ + field: "Authority Key Identifier", + oldValue: before.authority_key_identifier || "N/A", + newValue: after.authority_key_identifier || "N/A", + }) + } + if (before.type !== after.type) { + changes.push({ field: "Type", oldValue: before.type || "N/A", newValue: after.type || "N/A" }) + } + if ( + JSON.stringify(before.private_key_usage_period) !== + JSON.stringify(after.private_key_usage_period) + ) { + changes.push({ + field: "Private Key Usage Period", + oldValue: JSON.stringify(before.private_key_usage_period ?? "N/A"), + newValue: JSON.stringify(after.private_key_usage_period ?? "N/A"), + }) + } + + return changes } +/** Look up changes array for a given category key */ +const getDiffCategory = (diff: CertificateDiff, category: ChangeCategory): CertificateChange[] => { + switch (category) { + case "added": + return diff.added + case "removed": + return diff.removed + case "trust_increased": + return diff.trustIncreased + case "trust_decreased": + return diff.trustDecreased + case "trust_changed": + return diff.trustChanged + case "other": + return diff.other + } +} + +const getTotalChanges = (diff: CertificateDiff): number => + CATEGORY_ORDER.reduce((sum, cat) => sum + getDiffCategory(diff, cat).length, 0) + +// ─── Main component ─────────────────────────────────────────────────────────── + function CertificateDiffContent() { const searchParams = useSearchParams() const router = useRouter() + const { chainId } = useNetwork() const beforeRoot = searchParams.get("before") const afterRoot = searchParams.get("after") const [diffState, setDiffState] = useState({ beforeData: null, afterData: null, + beforeRootHash: null, + afterRootHash: null, + beforeUrl: null, + afterUrl: null, isLoading: false, error: null, }) - // Fetch certificate data from root hashes + const [visibleTypes, setVisibleTypes] = useState>({ + added: true, + removed: true, + trust_increased: true, + trust_decreased: true, + trust_changed: true, + other: true, + }) + + const toggleVisibility = (type: ChangeCategory) => { + setVisibleTypes((prev) => ({ ...prev, [type]: !prev[type] })) + } + + const { roots: historicalRoots } = useHistoricalCertificateRoots() + + // Chronological order (oldest first) — the hook returns newest-first + const chronoRoots = useMemo(() => [...historicalRoots].reverse(), [historicalRoots]) + + const beforeIdx = chronoRoots.findIndex( + (r) => normalizeHash(r.root) === normalizeHash(beforeRoot || ""), + ) + const afterIdx = chronoRoots.findIndex( + (r) => normalizeHash(r.root) === normalizeHash(afterRoot || ""), + ) + + const canGoPrevious = beforeIdx > 0 + const canGoNext = afterIdx >= 0 && afterIdx < chronoRoots.length - 1 + + const navigateToPreviousDiff = () => { + if (canGoPrevious) { + const newBefore = chronoRoots[beforeIdx - 1].root + const newAfter = chronoRoots[beforeIdx].root + router.push( + `/certificates/diff?before=${encodeURIComponent(newBefore)}&after=${encodeURIComponent(newAfter)}`, + ) + } + } + + const navigateToNextDiff = () => { + if (canGoNext) { + const newBefore = chronoRoots[afterIdx].root + const newAfter = chronoRoots[afterIdx + 1].root + router.push( + `/certificates/diff?before=${encodeURIComponent(newBefore)}&after=${encodeURIComponent(newAfter)}`, + ) + } + } + + const [expandedCards, setExpandedCards] = useState>(new Set()) + + const toggleCard = (id: string) => { + setExpandedCards((prev) => { + const next = new Set(prev) + if (next.has(id)) { + next.delete(id) + } else { + next.add(id) + } + return next + }) + } + + // ── Fetch certificate data from root hashes ────────────────────────────── + useEffect(() => { const fetchCertificateData = async () => { if (!beforeRoot || !afterRoot) { @@ -60,8 +409,6 @@ function CertificateDiffContent() { setDiffState((prev) => ({ ...prev, isLoading: true, error: null })) - // Get chain ID and construct URLs from root hashes, local JSON files, or direct URLs - const chainId = getChainId() const beforeUrl = beforeRoot.startsWith("http") ? beforeRoot : beforeRoot.endsWith(".json") @@ -84,7 +431,6 @@ function CertificateDiffContent() { `Failed to fetch before data: ${beforeResponse.status} ${beforeResponse.statusText}`, ) } - if (!afterResponse.ok) { throw new Error( `Failed to fetch after data: ${afterResponse.status} ${afterResponse.statusText}`, @@ -95,10 +441,24 @@ function CertificateDiffContent() { beforeResponse.json(), afterResponse.json(), ]) + // Normalise fingerprints + for (const cert of beforeData.certificates) { + if (cert.fingerprint) cert.fingerprint = normalizeHash(cert.fingerprint) + } + for (const cert of afterData.certificates) { + if (cert.fingerprint) cert.fingerprint = normalizeHash(cert.fingerprint) + } + + const beforeRootHash = beforeRoot.startsWith("http") ? beforeData.root : beforeRoot + const afterRootHash = afterRoot.startsWith("http") ? afterData.root : afterRoot setDiffState({ beforeData, afterData, + beforeRootHash, + afterRootHash, + beforeUrl: beforeRoot.startsWith("http") ? beforeRoot : null, + afterUrl: afterRoot.startsWith("http") ? afterRoot : null, isLoading: false, error: null, }) @@ -112,12 +472,13 @@ function CertificateDiffContent() { } fetchCertificateData() - }, [beforeRoot, afterRoot]) + }, [beforeRoot, afterRoot, chainId]) - const formatRoot = (root: string) => { - if (root.endsWith(".json") || root.startsWith("http")) { - return root - } + // ── Utility ────────────────────────────────────────────────────────────── + + const formatRoot = (root: string | null): string => { + if (!root || typeof root !== "string") return "" + if (root.endsWith(".json") || root.startsWith("http")) return root return root.startsWith("0x") ? root : `0x${root}` } @@ -130,199 +491,312 @@ function CertificateDiffContent() { } } - // Function to generate unique certificate key - const getCertificateKey = (cert: PackagedCertificate): string => { - const publicKeyParts = [] - if (cert.public_key?.type === "RSA") { - publicKeyParts.push(cert.public_key.type, cert.public_key.modulus, cert.public_key.exponent) - } else if (cert.public_key?.type === "EC") { - publicKeyParts.push( - cert.public_key.type, - cert.public_key.curve, - cert.public_key.public_key_x, - cert.public_key.public_key_y, - ) - } - const parts = [cert.country, cert.signature_algorithm, cert.hash_algorithm, ...publicKeyParts] - return parts.join("|") - } + // ── Diff calculation (fingerprint-based) ───────────────────────────────── - // Function to calculate certificate differences const calculateCertificateDiff = ( beforeCerts: PackagedCertificate[], afterCerts: PackagedCertificate[], + // eslint-disable-next-line @typescript-eslint/no-unused-vars + afterTimestamp?: number, ): CertificateDiff => { const beforeMap = new Map() const afterMap = new Map() - // Create maps using the proper unique identifier + // Build maps keyed by fingerprint beforeCerts.forEach((cert) => { - const key = getCertificateKey(cert) - if (key) { - beforeMap.set(key, cert) - } + if (cert.fingerprint) beforeMap.set(cert.fingerprint, cert) }) - afterCerts.forEach((cert) => { - const key = getCertificateKey(cert) - if (key) { - afterMap.set(key, cert) - } + if (cert.fingerprint) afterMap.set(cert.fingerprint, cert) }) - const added: PackagedCertificate[] = [] - const removed: PackagedCertificate[] = [] - const modified: CertificateChange[] = [] + const diff: CertificateDiff = { + added: [], + removed: [], + trustIncreased: [], + trustDecreased: [], + trustChanged: [], + other: [], + } - // Find added certificates - afterMap.forEach((cert, id) => { - if (!beforeMap.has(id)) { - added.push(cert) + // Added: present in after but absent from before + afterMap.forEach((cert, fp) => { + if (!beforeMap.has(fp)) { + diff.added.push({ certificate: cert, changeType: "added" }) } }) - // Find removed certificates and modified certificates - beforeMap.forEach((beforeCert, id) => { - if (!afterMap.has(id)) { - removed.push(beforeCert) + // Removed / modified: iterate before list + beforeMap.forEach((beforeCert, fp) => { + if (!afterMap.has(fp)) { + // Fingerprint gone → removed + diff.removed.push({ certificate: beforeCert, changeType: "removed" }) } else { - const afterCert = afterMap.get(id)! - - // Compare tags and hash algorithm - const beforeTags = beforeCert.tags || [] - const afterTags = afterCert.tags || [] + // Present in both → check what changed + const afterCert = afterMap.get(fp)! + const beforeTags = normalizeTags(beforeCert.tags) + const afterTags = normalizeTags(afterCert.tags) const tagsChanged = beforeTags.length !== afterTags.length || - beforeTags.some((tag) => !afterTags.includes(tag)) || - afterTags.some((tag) => !beforeTags.includes(tag)) + beforeTags.some((t) => !afterTags.includes(t)) || + afterTags.some((t) => !beforeTags.includes(t)) - const hashAlgorithmChanged = beforeCert.hash_algorithm !== afterCert.hash_algorithm + const fieldChanges = detectFieldChanges(beforeCert, afterCert) - if (tagsChanged || hashAlgorithmChanged) { - modified.push({ + if (tagsChanged) { + const change: CertificateChange = { certificate: afterCert, - changeType: "modified", + changeType: "trust_changed", + beforeCertificate: beforeCert, oldTags: beforeTags, newTags: afterTags, - oldHashAlgorithm: hashAlgorithmChanged ? beforeCert.hash_algorithm : undefined, - newHashAlgorithm: hashAlgorithmChanged ? afterCert.hash_algorithm : undefined, + fieldChanges: fieldChanges.length > 0 ? fieldChanges : undefined, + } + + const addedTags = afterTags.filter((t) => !beforeTags.includes(t)) + const removedTags = beforeTags.filter((t) => !afterTags.includes(t)) + + if (addedTags.length > 0 && removedTags.length === 0) { + // Only new tags were added — pure trust increase + change.changeType = "trust_increased" + diff.trustIncreased.push(change) + } else if (removedTags.length > 0 && addedTags.length === 0) { + // Only existing tags were removed — pure trust decrease + change.changeType = "trust_decreased" + diff.trustDecreased.push(change) + } else { + diff.trustChanged.push(change) + } + } else if (fieldChanges.length > 0) { + diff.other.push({ + certificate: afterCert, + changeType: "other", + beforeCertificate: beforeCert, + fieldChanges, }) } } }) - return { added, removed, modified } + return diff } - const renderCertificateChange = ( - cert: PackagedCertificate, - changeType: "added" | "removed" | "modified", - oldTags?: string[], - newTags?: string[], - oldHashAlgorithm?: string, - newHashAlgorithm?: string, - ) => { - const getChangeTypeStyle = (type: "added" | "removed" | "modified") => { - switch (type) { - case "added": - return "border-green-200 bg-green-50 dark:border-green-800 dark:bg-green-900/20" - case "removed": - return "border-red-200 bg-red-50 dark:border-red-800 dark:bg-red-900/20" - case "modified": - return "border-blue-200 bg-blue-50 dark:border-blue-800 dark:bg-blue-900/20" - } - } + // ── Render a single certificate change card ────────────────────────────── - const getChangeTypeIcon = (type: "added" | "removed" | "modified") => { - switch (type) { - case "added": - return + - case "removed": - return - - case "modified": - return ~ + const renderCertificateChange = (change: CertificateChange) => { + const config = CATEGORY_CONFIG[change.changeType] + const cert = change.certificate + + // Stable unique ID for expand/collapse state + const cardId = cert.fingerprint + ? `${change.changeType}-${cert.fingerprint}` + : `${change.changeType}-${cert.country}-${cert.signature_algorithm}-${cert.validity?.not_before || ""}` + const isExpanded = expandedCards.has(cardId) + + // Concise algorithm + key description for summary line + const algoDesc = (() => { + const algo = cert.signature_algorithm || "" + if (cert.public_key?.type === "EC") { + const curve = cert.public_key.curve || "" + const displayCurve = BRAINPOOL_ABBR[curve as keyof typeof BRAINPOOL_ABBR] ?? curve + return `${algo} - ${displayCurve}`.trim() } - } + if (cert.public_key?.type === "RSA") return `${algo} ${cert.public_key.key_size || ""}`.trim() + return algo || "Unknown" + })() - return ( -
-
- {getChangeTypeIcon(changeType)} - {changeType} -
+ // Validity period for summary + const validityStr = + cert.validity?.not_before && cert.validity?.not_after + ? `${new Date(cert.validity.not_before * 1000).toLocaleDateString("en-GB")} to ${new Date(cert.validity.not_after * 1000).toLocaleDateString("en-GB")}` + : "" -
-
- {countryCodeAlpha3ToName(cert.country)} {" "} - ({cert.country}) -
-
- {cert.signature_algorithm} {cert.public_key?.key_size || "Unknown Key Size"} •{" "} - {oldHashAlgorithm && newHashAlgorithm ? ( - <> - - {oldHashAlgorithm} - {" "} - - {newHashAlgorithm} + const countryName = countryCodeAlpha3ToName(cert.country) + const showExpiredBadge = + cert.validity?.not_after != null && Date.now() > cert.validity.not_after * 1000 + // Compute effective old/new tags for the MasterlistTags component: + // - "added" certs: all tags are new (green) + // - "removed" certs: all tags are removed (red strikethrough) + // - trust changes: use the change's oldTags/newTags directly + const certTags = normalizeTags(cert.tags) + const effectiveOldTags = + change.oldTags ?? + (change.changeType === "added" ? [] : change.changeType === "removed" ? certTags : undefined) + const effectiveNewTags = + change.newTags ?? + (change.changeType === "added" ? certTags : change.changeType === "removed" ? [] : undefined) + + return ( +
+ {/* Header row — always visible, clickable to toggle */} +
- {cert.subject_key_identifier && ( -
- SKI: {cert.subject_key_identifier} -
+ {algoDesc && ( + + {" - "} + {algoDesc} + + )} + {validityStr && ( + + {" - "} + {validityStr} + + )} + {showExpiredBadge && ( + + Expired + + )} +
+ {/* Right-aligned masterlist tags with diff colors */} + + )} -
+ {isExpanded ? ( + + ) : ( + + )} + - {changeType === "modified" && oldTags && newTags ? ( -
- Tags:{" "} - {(() => { - const removedTags = oldTags.filter((tag) => !newTags.includes(tag)) - const addedTags = newTags.filter((tag) => !oldTags.includes(tag)) - const unchangedTags = oldTags.filter((tag) => newTags.includes(tag)) - - const allTags = [ - ...removedTags.map((tag) => ({ tag, type: "removed" })), - ...addedTags.map((tag) => ({ tag, type: "added" })), - ...unchangedTags.map((tag) => ({ tag, type: "unchanged" })), - ] - - if (allTags.length === 0) return "None" - - return allTags.map(({ tag, type }, index) => ( - - {type === "removed" && ( - {tag} + {/* Expanded details */} + {isExpanded && ( +
+
+ {/* Certificate core info */} +
+ {countryName} {" "} + ({cert.country}) +
+
+ {cert.signature_algorithm} {cert.public_key?.key_size || "Unknown Key Size"} +
+ {cert.validity?.not_before && cert.validity?.not_after && ( +
+ + Validity Period:{" "} + {new Date(cert.validity.not_before * 1000).toLocaleDateString("en-GB")} to{" "} + {new Date(cert.validity.not_after * 1000).toLocaleDateString("en-GB")} + + {showExpiredBadge && ( + + Expired + )} - {type === "added" && ( - {tag} +
+ )} + + {/* Public key details */} + {cert.public_key && ( +
+
+ {cert.public_key.type === "RSA" && "RSA Public Key"} + {cert.public_key.type === "EC" && + `EC Public Key (${cert.public_key.curve || "Unknown Curve"})`} +
+ {cert.public_key.type === "RSA" && ( + <> +
+ n: {cert.public_key.modulus} +
+
+ e: {cert.public_key.exponent} +
+ )} - {type === "unchanged" && {tag}} - {index < allTags.length - 1 && ", "} - - )) - })()} -
- ) : cert.tags && cert.tags.length > 0 ? ( -
- Tags: {cert.tags.join(", ")} + {cert.public_key.type === "EC" && ( + <> +
+ x: {cert.public_key.public_key_x} +
+
+ y: {cert.public_key.public_key_y} +
+ + )} +
+ )} + + {/* Identifiers */} + {cert.fingerprint && ( +
+ Fingerprint: {cert.fingerprint} +
+ )} + {cert.authority_key_identifier && ( +
+ AKI: {cert.authority_key_identifier} +
+ )} + {cert.subject_key_identifier && ( +
+ SKI: {cert.subject_key_identifier} +
+ )} + + {/* Tags diff for trust-related changes */} + {(effectiveOldTags && effectiveNewTags) || (cert.tags && cert.tags.length > 0) ? ( +
+ +
+ ) : null} + + {/* Field changes */} + {change.fieldChanges && change.fieldChanges.length > 0 && ( +
+ Field changes: + {change.fieldChanges.map((fc, i) => ( +
+ {fc.field}:{" "} + + {fc.oldValue} + + {" → "} + + {fc.newValue} + +
+ ))} +
+ )} +
- ) : null} + )}
) } + // ── Render change list ─────────────────────────────────────────────────── + const renderDiffList = (diff: CertificateDiff) => { - const totalChanges = diff.added.length + diff.removed.length + diff.modified.length + const totalChanges = getTotalChanges(diff) if (totalChanges === 0) { return ( @@ -332,35 +806,53 @@ function CertificateDiffContent() { ) } + const hasAnyVisible = CATEGORY_ORDER.some((cat) => visibleTypes[cat]) + if (!hasAnyVisible) { + return ( +
+ All change types are hidden. Click on the cards above to show changes. +
+ ) + } + + const visibleCount = CATEGORY_ORDER.reduce( + (sum, cat) => sum + (visibleTypes[cat] ? getDiffCategory(diff, cat).length : 0), + 0, + ) + return (
- {totalChanges} change{totalChanges !== 1 ? "s" : ""} found + {visibleCount !== totalChanges ? ( + <> + Showing {visibleCount} of {totalChanges} change + {totalChanges !== 1 ? "s" : ""} + + ) : ( + <> + {totalChanges} change{totalChanges !== 1 ? "s" : ""} found + + )}
- {diff.added.map((cert) => renderCertificateChange(cert, "added"))} - {diff.removed.map((cert) => renderCertificateChange(cert, "removed"))} - {diff.modified.map((change) => - renderCertificateChange( - change.certificate, - "modified", - change.oldTags, - change.newTags, - change.oldHashAlgorithm, - change.newHashAlgorithm, - ), + {CATEGORY_ORDER.map((cat) => + visibleTypes[cat] + ? getDiffCategory(diff, cat).map((change) => renderCertificateChange(change)) + : null, )}
) } + // ── Render summary cards ───────────────────────────────────────────────── + const renderDiffSummary = (diff: CertificateDiff) => { if (!diffState.beforeData || !diffState.afterData) return null const beforeCount = diffState.beforeData.certificates?.length || 0 const afterCount = diffState.afterData.certificates?.length || 0 - const totalChanges = diff.added.length + diff.removed.length + diff.modified.length + const totalChanges = getTotalChanges(diff) return ( @@ -372,31 +864,29 @@ function CertificateDiffContent() {
- {/* Change Cards First */} - {diff.added.length > 0 && ( -
-
- +{diff.added.length} -
-
Added
-
- )} - {diff.removed.length > 0 && ( -
-
- -{diff.removed.length} -
-
Removed
-
- )} - {diff.modified.length > 0 && ( -
-
- ~{diff.modified.length} -
-
Modified
-
- )} + {/* Category cards */} + {CATEGORY_ORDER.map((cat) => { + const items = getDiffCategory(diff, cat) + if (items.length === 0) return null + const config = CATEGORY_CONFIG[cat] + return ( + + ) + })} {totalChanges === 0 && (
0
@@ -404,14 +894,14 @@ function CertificateDiffContent() {
)} - {/* Context Cards at the End */} + {/* Context: before / after counts */}
{beforeCount}
Before
-
+
{afterCount}
@@ -423,15 +913,41 @@ function CertificateDiffContent() { ) } + // ── Page layout ────────────────────────────────────────────────────────── + return ( -
-
+
+
+ {chronoRoots.length > 0 && ( +
+ + +
+ )}
{diffState.error && ( @@ -453,6 +969,20 @@ function CertificateDiffContent() { <>

Comparing Certificate Roots

+ {diffState.afterData?.timestamp && ( +
+ Updated on {" "} + {new Date(diffState.afterData.timestamp * 1000).toLocaleString("en-US", { + year: "numeric", + month: "long", + day: "numeric", + hour: "2-digit", + minute: "2-digit", + second: "2-digit", + timeZoneName: "short", + })} +
+ )}
@@ -460,7 +990,23 @@ function CertificateDiffContent() { Before: - {formatRoot(beforeRoot)} + {diffState.beforeRootHash + ? formatRoot(diffState.beforeRootHash) + : formatRoot(beforeRoot)} + {diffState.beforeUrl && ( + + ( + + {diffState.beforeUrl} + + ) + + )}
@@ -468,7 +1014,23 @@ function CertificateDiffContent() { After: - {formatRoot(afterRoot)} + {diffState.afterRootHash + ? formatRoot(diffState.afterRootHash) + : formatRoot(afterRoot)} + {diffState.afterUrl && ( + + ( + + {diffState.afterUrl} + + ) + + )}
@@ -494,6 +1056,7 @@ function CertificateDiffContent() { const diff = calculateCertificateDiff( diffState.beforeData.certificates || [], diffState.afterData.certificates || [], + diffState.afterData.timestamp, ) return ( @@ -521,7 +1084,7 @@ export default function CertificateDiffPage() { return ( +
diff --git a/packages/registry-explorer/app/certificates/history/page.tsx b/packages/registry-explorer/app/certificates/history/page.tsx index ca57223a..e252bf11 100644 --- a/packages/registry-explorer/app/certificates/history/page.tsx +++ b/packages/registry-explorer/app/certificates/history/page.tsx @@ -10,7 +10,7 @@ function HistoricalRootsContent() { if (error) { return ( -
+

Error Loading Roots

{error}
@@ -19,6 +19,11 @@ function HistoricalRootsContent() { return (
+

+ {isLoading && roots.length === 0 + ? "Browse all historical certificate roots stored in the registry" + : `${roots.length} historical certificate root${roots.length !== 1 ? "s" : ""} found`} +

{isLoading && roots.length === 0 ? (
@@ -46,15 +51,16 @@ export default function HistoricalRootsPage() { return (

Historical Certificate Roots

-

- Browse all historical certificate roots stored in the registry -

- - -
+ <> +

+ Browse all historical certificate roots stored in the registry +

+
+ +
+ } > diff --git a/packages/registry-explorer/app/certificates/page.tsx b/packages/registry-explorer/app/certificates/page.tsx index ea64cd89..b22d94f8 100644 --- a/packages/registry-explorer/app/certificates/page.tsx +++ b/packages/registry-explorer/app/certificates/page.tsx @@ -3,7 +3,7 @@ import CertificateSearch from "@/components/CertificateSearch" export default function CertificatesPage() { return ( -
+

Certificate Registry Explorer

Loading...
}> diff --git a/packages/registry-explorer/app/layout.tsx b/packages/registry-explorer/app/layout.tsx index cf66dff7..c7e348f5 100644 --- a/packages/registry-explorer/app/layout.tsx +++ b/packages/registry-explorer/app/layout.tsx @@ -1,4 +1,5 @@ import { DebugInitializer } from "@/components/DebugInitializer" +import { NetworkProvider } from "@/components/NetworkProvider" import { ThemeProvider } from "@/components/ThemeProvider" import type { Metadata } from "next" import localFont from "next/font/local" @@ -88,8 +89,10 @@ export default function RootLayout({ > - -
{children}
+ + +
{children}
+
diff --git a/packages/registry-explorer/app/map/page.tsx b/packages/registry-explorer/app/map/page.tsx index 7b6da66c..bcadaa1c 100644 --- a/packages/registry-explorer/app/map/page.tsx +++ b/packages/registry-explorer/app/map/page.tsx @@ -32,8 +32,6 @@ function MapPageContent() { useEffect(() => { const processCertificates = async () => { if (certificates && certificates.length > 0) { - console.log("Processing certificates:", certificates.length) - // Group certificates by country const certsByCountry: Record = {} certificates.forEach((cert) => { @@ -43,7 +41,6 @@ function MapPageContent() { certsByCountry[cert.country].push(cert) }) setCertificatesByCountry(certsByCountry) - console.log("Certificates by country:", Object.keys(certsByCountry).length, "countries") // Convert to Map for coverage calculation const certsByCountryMap = new Map(Object.entries(certsByCountry)) @@ -92,7 +89,6 @@ function MapPageContent() { } }) setCountryData(newCountryData) - console.log("Country data created with coverage:", newCountryData) } } diff --git a/packages/registry-explorer/app/page.tsx b/packages/registry-explorer/app/page.tsx index a5e0a662..b36bb88c 100644 --- a/packages/registry-explorer/app/page.tsx +++ b/packages/registry-explorer/app/page.tsx @@ -1,3 +1,5 @@ +"use client" + import { Button } from "@/components/ui/button" import { Card, diff --git a/packages/registry-explorer/components/CertificateRootCard.tsx b/packages/registry-explorer/components/CertificateRootCard.tsx index d5546ad4..583e4c7a 100644 --- a/packages/registry-explorer/components/CertificateRootCard.tsx +++ b/packages/registry-explorer/components/CertificateRootCard.tsx @@ -10,7 +10,7 @@ import { } from "@/components/ui/card" import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip" import { RootDetails } from "@zkpassport/registry" -import { Copy, GitCompare } from "lucide-react" +import { Copy, FileText, GitCompare } from "lucide-react" import Link from "next/link" import { useState } from "react" @@ -21,6 +21,7 @@ interface CertificateRootCardProps { export function CertificateRootCard({ rootDetails, previousRoot }: CertificateRootCardProps) { const [copied, setCopied] = useState(false) + const [validityCopied, setValidityCopied] = useState(false) const { root, revoked, validFrom, validTo, cid, leaves, isLatest, index } = rootDetails function formatCid(cid: string): string { @@ -43,6 +44,13 @@ export function CertificateRootCard({ rootDetails, previousRoot }: CertificateRo }) } + const copyValidFromTimestamp = () => { + navigator.clipboard.writeText(Math.floor(validFrom.getTime() / 1000).toString()).then(() => { + setValidityCopied(true) + setTimeout(() => setValidityCopied(false), 2000) + }) + } + // Determine if this is the genesis root const isGenesisRoot = index === 1 @@ -51,7 +59,7 @@ export function CertificateRootCard({ rootDetails, previousRoot }: CertificateRo
- {isLatest ? "Current Root" : "Historical Root"} + {isLatest ? "Current Root" : isGenesisRoot ? "Genesis Root" : "Historical Root"}
{revoked && Revoked} @@ -99,15 +107,29 @@ export function CertificateRootCard({ rootDetails, previousRoot }: CertificateRo
Validity Period:
-
- {validFrom.toLocaleDateString()} to{" "} - {validTo !== undefined ? validTo.toLocaleDateString() : "Present"} -
+ + + +
+ {validFrom.toLocaleDateString()} to{" "} + {validTo !== undefined ? validTo.toLocaleDateString() : "Present"} +
+
+ +

+ {validityCopied ? "Copied!" : Math.floor(validFrom.getTime() / 1000).toString()} +

+
+
+
IPFS CID:
- + {formatCid(cid)}
@@ -121,8 +143,11 @@ export function CertificateRootCard({ rootDetails, previousRoot }: CertificateRo
- {previousRoot && ( {isLatestRoot && ( - - Latest Root + + Latest )}
@@ -124,23 +133,27 @@ export default function CertificateSearch() {
{availableRoots.length > 0 && ( -
-
)}
@@ -167,172 +190,90 @@ export default function CertificateSearch() {
{/* Stats Cards */} -
-
-
-
-
- - - -
-
-
-
- Total Certificates -
-
-
- {certificates.length} -
-
-
-
+
+
+
+
+
+ Total Certificates +
+
+ {certificates.length} +
+
-
-
-
-
- - - -
-
-
-
- Countries -
-
-
- {uniqueCountries.length} -
-
-
-
+
+
+
+
+ Countries +
+
+ {uniqueCountries.length} +
+
-
-
-
-
- - - -
-
-
-
- RSA Certificates -
-
-
- {certificates.filter((cert) => isRSA(cert)).length} -
-
-
-
+
+
+
+
+ RSA Certificates +
+
+ {certificates.filter((cert) => isRSA(cert)).length} +
+
-
-
-
-
- - - -
-
-
-
- ECDSA Certificates -
-
-
- {certificates.filter((cert) => isECDSA(cert)).length} -
-
-
-
+
+
+
+
+ ECDSA Certificates +
+
+ {certificates.filter((cert) => isECDSA(cert)).length} +
+
{/* Search and Filter Section with Card UI */} -
-

- - - +
+

+ Filter Certificates

@@ -364,7 +305,8 @@ export default function CertificateSearch() { {filteredCertificates.length > 0 && (
Showing {filteredCertificates.length}{" "} - {filteredCertificates.length === 1 ? "certificate" : "certificates"} + {filteredCertificates.length === 1 ? "certificate" : "certificates"} across{" "} + {new Set(filteredCertificates.map((c) => c.country)).size} countries
)}
@@ -378,26 +320,28 @@ export default function CertificateSearch() {