diff --git a/.changeset/dependency-updates.md b/.changeset/dependency-updates.md new file mode 100644 index 0000000..d895390 --- /dev/null +++ b/.changeset/dependency-updates.md @@ -0,0 +1,7 @@ +--- +"@3flabs/guardian": minor +"@3flabs/guardian-defaults": patch +"@3flabs/guardian-coordinator": patch +--- + +Update runtime dependencies. `better-result` moves to 3.x: the exported error classes (`UnauthenticatedError`, `ValidationFailedError`, …) still extend its `TaggedError`, so hosts that call `isTaggedError` / `matchError` on Guardian errors with their own copy of `better-result` should be on 3.x too. Also picks up viem 2.56, zod 4.6, elysia 1.4.30, `@noble/hashes` 2.4, `@aws-sdk/client-kms` 3.1130, and `@google-cloud/kms` 6.1 (Node ≥ 22 only; the coordinator runs on Bun). diff --git a/.changeset/retargetter-request-path.md b/.changeset/retargetter-request-path.md new file mode 100644 index 0000000..8c237eb --- /dev/null +++ b/.changeset/retargetter-request-path.md @@ -0,0 +1,7 @@ +--- +"@3flabs/guardian-defaults": minor +"@3flabs/guardian-coordinator": minor +"@3flabs/guardian-test-fixtures": minor +--- + +Add an opt-in retargetter path to the §A.1 checks. When the request contract's `owner()` is on the new `acceptedRetargetters` policy set (`GUARDIAN_ACCEPTED_RETARGETTERS`), the factory, owner and puller / consumer role checks are skipped in favour of the retargetter's live `operation()`: the contract must be the retargetter's attached operation request and the operation's repayment deadline must be at least `minRetargetterRepaymentBufferSeconds` ahead (`GUARDIAN_MIN_RETARGETTER_REPAYMENT_BUFFER_SECONDS`, default 80 days — the contract's `MIN_DEADLINE_BUFFER`). §A.4 whitelist ops inherit it per request contract. Every other request contract keeps the classic path. Ships `retargetterAbi` and a `MockRetargetter` test fixture. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c1385e1..4d50605 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -52,15 +52,17 @@ jobs: # `packages/guardian-test-fixtures/artifacts/`. Pinned to v1.7.1 # — the latest foundry release, matching local dev and the # bundled fixtures — rather than `stable` so runs are - # reproducible. Known tradeoff: the action fetches the foundryup - # installer from foundry HEAD at run time, so the action SHA pin - # does not pin the installer script, and foundryup's attestation - # check is best-effort (it skips rather than fails when `gh` / - # the attestation API is unavailable) — the binaries are NOT - # cryptographically verified end-to-end. Accepted for now; the - # alternative is vendoring a checksummed tarball download. + # reproducible. Known tradeoff: the action fetches the standalone + # foundryup installer (foundry-rs/foundryup) at run time, so the + # action SHA pin does not pin the installer, and foundryup's + # attestation check is best-effort (it skips rather than fails + # when `gh` / the attestation API is unavailable) — the binaries + # are NOT cryptographically verified end-to-end. Accepted for now; + # the alternative is vendoring a checksummed tarball download. + # v1.9+ is required: foundryup is now a compiled binary, and the + # v1.8.0 action ran it through `bash` (foundry-toolchain#170). - name: Install Foundry - uses: foundry-rs/foundry-toolchain@c7450ba673e133f5ee30098b3b54f444d3a2ca2d # v1.8.0 + uses: foundry-rs/foundry-toolchain@908c540300062bd5a7e473851cdb4282204cee09 # v1.9.1 with: version: v1.7.1 diff --git a/Dockerfile.guardian-coordinator b/Dockerfile.guardian-coordinator index 60c4256..1cc1b38 100644 --- a/Dockerfile.guardian-coordinator +++ b/Dockerfile.guardian-coordinator @@ -1,4 +1,4 @@ -FROM oven/bun:1.3.14-alpine AS build +FROM oven/bun:1.4.2-alpine AS build WORKDIR /app COPY package.json bun.lock tsconfig.base.json ./ @@ -15,7 +15,7 @@ RUN bun run --cwd packages/guardian build \ && bun run --cwd packages/guardian-defaults build \ && bun run --cwd packages/guardian-coordinator build -FROM oven/bun:1.3.14-alpine AS runtime +FROM oven/bun:1.4.2-alpine AS runtime WORKDIR /app ENV NODE_ENV=production diff --git a/README.md b/README.md index 3f3f8f6..a6f2cbe 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ bun run build # tsc emit .js + .d.ts per package The root `build` / `test` / `test:integration` / `typecheck` scripts invoke each package explicitly via `bun run --cwd packages/ …`, so a missing package script fails loudly. -Bun itself is pinned through the root `packageManager` field (`bun@1.3.14`); CI reads it +Bun itself is pinned through the root `packageManager` field (`bun@1.4.2`); CI reads it via setup-bun's `bun-version-file`, so bumping Bun is a single-line change. Per-package work: diff --git a/bun.lock b/bun.lock index 7ac191f..92a3fd5 100644 --- a/bun.lock +++ b/bun.lock @@ -5,29 +5,29 @@ "": { "name": "@3flabs/guardian-monorepo", "devDependencies": { - "@changesets/cli": "^2.31.0", - "@types/bun": "^1.3.14", - "oxfmt": "^0.54.0", - "oxlint": "^1.69.0", + "@changesets/cli": "^2.31.1", + "@types/bun": "^1.4.2", + "oxfmt": "^0.67.0", + "oxlint": "^1.82.0", "typescript": "^5.9.3", - "vitest": "^4.1.8", + "vitest": "^5.0.0", }, }, "packages/guardian": { "name": "@3flabs/guardian", "version": "0.5.0", "dependencies": { - "@elysiajs/openapi": "^1.4.15", - "@noble/hashes": "^2.2.0", - "better-result": "^2.9.2", - "elysia": "^1.4.28", - "viem": "^2.52.2", - "zod": "^4.0.0", + "@elysiajs/openapi": "^1.4.16", + "@noble/hashes": "^2.4.0", + "better-result": "^3.0.1", + "elysia": "^1.4.30", + "viem": "^2.56.3", + "zod": "^4.6.2", }, "devDependencies": { "@3flabs/guardian-test-fixtures": "workspace:*", "typescript": "^5.9.3", - "vitest": "^4.1.8", + "vitest": "^5.0.0", }, }, "packages/guardian-coordinator": { @@ -39,16 +39,16 @@ "dependencies": { "@3flabs/guardian": "workspace:*", "@3flabs/guardian-defaults": "workspace:*", - "@aws-sdk/client-kms": "^3.1075.0", - "@google-cloud/kms": "^5.5.1", + "@aws-sdk/client-kms": "^3.1130.0", + "@google-cloud/kms": "^6.1.0", "@noble/curves": "1.9.1", - "better-result": "^2.9.2", - "viem": "^2.52.2", - "zod": "^4.0.0", + "better-result": "^3.0.1", + "viem": "^2.56.3", + "zod": "^4.6.2", }, "devDependencies": { "typescript": "^5.9.3", - "vitest": "^4.1.8", + "vitest": "^5.0.0", }, }, "packages/guardian-defaults": { @@ -56,34 +56,34 @@ "version": "0.3.2", "dependencies": { "@3flabs/guardian": "workspace:*", - "better-result": "^2.9.2", + "better-result": "^3.0.1", "pino": "^10.3.1", "pino-pretty": "^13.1.3", - "viem": "^2.52.2", - "zod": "^4.0.0", + "viem": "^2.56.3", + "zod": "^4.6.2", }, "devDependencies": { "@3flabs/guardian-test-fixtures": "workspace:*", "typescript": "^5.9.3", - "vitest": "^4.1.8", + "vitest": "^5.0.0", }, }, "packages/guardian-test-fixtures": { "name": "@3flabs/guardian-test-fixtures", "version": "0.0.1", "dependencies": { - "prool": "^0.2.4", - "viem": "^2.52.2", + "prool": "^0.2.15", + "viem": "^2.56.3", }, "devDependencies": { "typescript": "^5.9.3", - "vitest": "^4.1.8", + "vitest": "^5.0.0", }, }, }, "overrides": { "brace-expansion": "5.0.8", - "elysia": "1.4.29", + "elysia": "1.4.30", "tar": "7.5.19", "ws": "8.21.1", }, @@ -98,49 +98,37 @@ "@adraffy/ens-normalize": ["@adraffy/ens-normalize@1.11.1", "", {}, "sha512-nhCBV3quEgesuf7c7KYfperqSS14T8bYuvJ8PcLJp6znkZpFc0AuW4qBtr8eKVyPPe/8RSr7sglCWPU5eaxwKQ=="], - "@aws-crypto/crc32": ["@aws-crypto/crc32@5.2.0", "", { "dependencies": { "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "tslib": "^2.6.2" } }, "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg=="], + "@aws-sdk/client-kms": ["@aws-sdk/client-kms@3.1130.0", "", { "dependencies": { "@aws-sdk/core": "^3.978.0", "@aws-sdk/credential-provider-node": "^3.972.83", "@aws-sdk/types": "^3.974.5", "@smithy/core": "^3.33.3", "@smithy/fetch-http-handler": "^5.7.2", "@smithy/node-http-handler": "^4.11.3", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-hRmzoskEF9a9M9antlDbQsEKKWfR9B0ypYeFACUYLQnqN4Jsx2JU8N5dJsSWbpgwslpwnWDWXkOatyV/IechXg=="], - "@aws-crypto/sha256-browser": ["@aws-crypto/sha256-browser@5.2.0", "", { "dependencies": { "@aws-crypto/sha256-js": "^5.2.0", "@aws-crypto/supports-web-crypto": "^5.2.0", "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "@aws-sdk/util-locate-window": "^3.0.0", "@smithy/util-utf8": "^2.0.0", "tslib": "^2.6.2" } }, "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw=="], + "@aws-sdk/core": ["@aws-sdk/core@3.978.0", "", { "dependencies": { "@aws-sdk/types": "^3.974.5", "@aws-sdk/xml-builder": "^3.972.40", "@aws/lambda-invoke-store": "^0.3.0", "@smithy/core": "^3.33.3", "@smithy/signature-v4": "^5.6.12", "@smithy/types": "^4.17.2", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-2yX9LUmxPklVjSGTb8dfnWRJSiFQ3TeH2nn7G1mdKHTfnabzF0+gfrS8rYfLWmZrQ8A3mEcxMJjRc51dL5KWaA=="], - "@aws-crypto/sha256-js": ["@aws-crypto/sha256-js@5.2.0", "", { "dependencies": { "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "tslib": "^2.6.2" } }, "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA=="], + "@aws-sdk/credential-provider-env": ["@aws-sdk/credential-provider-env@3.972.71", "", { "dependencies": { "@aws-sdk/core": "^3.978.0", "@aws-sdk/types": "^3.974.5", "@smithy/core": "^3.33.3", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-JN+JHruYZw3GUZB8YGAlDk4wTDPOEAEEdEzj5nS0xodWR4smzHsN7PnK2j6IeOsDIj2aqua5DSbhXl9Gtf90FQ=="], - "@aws-crypto/supports-web-crypto": ["@aws-crypto/supports-web-crypto@5.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg=="], + "@aws-sdk/credential-provider-http": ["@aws-sdk/credential-provider-http@3.972.73", "", { "dependencies": { "@aws-sdk/core": "^3.978.0", "@aws-sdk/types": "^3.974.5", "@smithy/core": "^3.33.3", "@smithy/fetch-http-handler": "^5.7.2", "@smithy/node-http-handler": "^4.11.3", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-uyYYnJOnlis8uQzaYGPd7N1JoioCoNpXgnkXYixsWJXHXgXyYi8WXJSDfofxJeWfQIGWLe2Nwyq60Uc7MZdVOg=="], - "@aws-crypto/util": ["@aws-crypto/util@5.2.0", "", { "dependencies": { "@aws-sdk/types": "^3.222.0", "@smithy/util-utf8": "^2.0.0", "tslib": "^2.6.2" } }, "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ=="], + "@aws-sdk/credential-provider-ini": ["@aws-sdk/credential-provider-ini@3.973.16", "", { "dependencies": { "@aws-sdk/core": "^3.978.0", "@aws-sdk/credential-provider-env": "^3.972.71", "@aws-sdk/credential-provider-http": "^3.972.73", "@aws-sdk/credential-provider-login": "^3.972.78", "@aws-sdk/credential-provider-process": "^3.972.71", "@aws-sdk/credential-provider-sso": "^3.973.15", "@aws-sdk/credential-provider-web-identity": "^3.972.77", "@aws-sdk/nested-clients": "^3.997.45", "@aws-sdk/types": "^3.974.5", "@smithy/core": "^3.33.3", "@smithy/credential-provider-imds": "^4.4.16", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-i++ly+0Uxa+u3ebSSyr0S/3CFhFJDxCXT3+Zj+mW2bXenEx5bKGCdTIKFu39SgXBNhWDjex/8cXUx9MUTMCrTw=="], - "@aws-sdk/client-kms": ["@aws-sdk/client-kms@3.1075.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "^3.974.23", "@aws-sdk/credential-provider-node": "^3.972.58", "@aws-sdk/types": "^3.973.13", "@smithy/core": "^3.24.6", "@smithy/fetch-http-handler": "^5.4.6", "@smithy/node-http-handler": "^4.7.6", "@smithy/types": "^4.14.3", "tslib": "^2.6.2" } }, "sha512-Y++vxbiNFUWBD0E8RHau6yhx0xSWVTSGoWiKDWN4whA2YbW+p6OVDsLCMGVO/B41gRTSt9sqaLSDMaKY/zI/ww=="], + "@aws-sdk/credential-provider-login": ["@aws-sdk/credential-provider-login@3.972.78", "", { "dependencies": { "@aws-sdk/core": "^3.978.0", "@aws-sdk/nested-clients": "^3.997.45", "@aws-sdk/types": "^3.974.5", "@smithy/core": "^3.33.3", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-eUtswnXu0+Ii9ieRK+0L7aPFV3Z/dnW2VntJzjBP9xs8s+8p5nBNuymIXtXwZ+5r5+XJP3e32nMkuZ/r0HozEA=="], - "@aws-sdk/core": ["@aws-sdk/core@3.974.23", "", { "dependencies": { "@aws-sdk/types": "^3.973.13", "@aws-sdk/xml-builder": "^3.972.31", "@aws/lambda-invoke-store": "^0.2.2", "@smithy/core": "^3.24.6", "@smithy/signature-v4": "^5.4.6", "@smithy/types": "^4.14.3", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-MiWR/uWjxjFXGzrE0Ghc5lWxUxzHsUWFhV+OX7M4cR9SrmrnZs6TXavnCWnzzdwJeFri34xQo81rvGNzK3c4BQ=="], + "@aws-sdk/credential-provider-node": ["@aws-sdk/credential-provider-node@3.972.83", "", { "dependencies": { "@aws-sdk/credential-provider-env": "^3.972.71", "@aws-sdk/credential-provider-http": "^3.972.73", "@aws-sdk/credential-provider-ini": "^3.973.16", "@aws-sdk/credential-provider-process": "^3.972.71", "@aws-sdk/credential-provider-sso": "^3.973.15", "@aws-sdk/credential-provider-web-identity": "^3.972.77", "@aws-sdk/types": "^3.974.5", "@smithy/core": "^3.33.3", "@smithy/credential-provider-imds": "^4.4.16", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-jdso7ejzfRnatxMUZK4S/U6KbaDPCvfIV4XL+IQAPFDBt5rj5Fq595euqlK8Le4lNCMFR9oUpt+1l0aMgaayOQ=="], - "@aws-sdk/credential-provider-env": ["@aws-sdk/credential-provider-env@3.972.49", "", { "dependencies": { "@aws-sdk/core": "^3.974.23", "@aws-sdk/types": "^3.973.13", "@smithy/core": "^3.24.6", "@smithy/types": "^4.14.3", "tslib": "^2.6.2" } }, "sha512-liB3yQNHCM9k/gu/w36XHMKPluT7HTlnGUhRbBGSISDQkcr/Sy1zsZabiuvQj8WG5yW573u9RehrBvvnIQ9OEQ=="], + "@aws-sdk/credential-provider-process": ["@aws-sdk/credential-provider-process@3.972.71", "", { "dependencies": { "@aws-sdk/core": "^3.978.0", "@aws-sdk/types": "^3.974.5", "@smithy/core": "^3.33.3", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-lYmXJa4gvq4xN1lrT5NiP5vIYYKcGWAdj8y+8o6dlcateB5eF3Dn8DtmjjHKfMBrTPAMr2pebIiX/UOj8c1/UA=="], - "@aws-sdk/credential-provider-http": ["@aws-sdk/credential-provider-http@3.972.51", "", { "dependencies": { "@aws-sdk/core": "^3.974.23", "@aws-sdk/types": "^3.973.13", "@smithy/core": "^3.24.6", "@smithy/fetch-http-handler": "^5.4.6", "@smithy/node-http-handler": "^4.7.6", "@smithy/types": "^4.14.3", "tslib": "^2.6.2" } }, "sha512-XET0H2oofciJ5lMRWNIvRjAP7Q3wv2XT+JtJJEdhPWUMwe3TvQ9qcxonpu7vXmNngncvFpi4E2It+Tamas/naA=="], + "@aws-sdk/credential-provider-sso": ["@aws-sdk/credential-provider-sso@3.973.15", "", { "dependencies": { "@aws-sdk/core": "^3.978.0", "@aws-sdk/nested-clients": "^3.997.45", "@aws-sdk/token-providers": "3.1129.0", "@aws-sdk/types": "^3.974.5", "@smithy/core": "^3.33.3", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-6Jhcf4v0pSFdjk1EW2kvzuEBKD+UZ2uNcHUIglKKLndD20YhvkL2kdmDOV5/j4mYuWWwe/a1FQ1aomU86/Cg5Q=="], - "@aws-sdk/credential-provider-ini": ["@aws-sdk/credential-provider-ini@3.972.56", "", { "dependencies": { "@aws-sdk/core": "^3.974.23", "@aws-sdk/credential-provider-env": "^3.972.49", "@aws-sdk/credential-provider-http": "^3.972.51", "@aws-sdk/credential-provider-login": "^3.972.55", "@aws-sdk/credential-provider-process": "^3.972.49", "@aws-sdk/credential-provider-sso": "^3.972.55", "@aws-sdk/credential-provider-web-identity": "^3.972.55", "@aws-sdk/nested-clients": "^3.997.23", "@aws-sdk/types": "^3.973.13", "@smithy/core": "^3.24.6", "@smithy/credential-provider-imds": "^4.3.7", "@smithy/types": "^4.14.3", "tslib": "^2.6.2" } }, "sha512-IAmc61hbgQiHht9U3x0tnRwz0lzdwOwD/i9voRgdJrKamF+JtmrBOsW9GwB7mfFonNWOWL4qARWYrF8veEMe3w=="], + "@aws-sdk/credential-provider-web-identity": ["@aws-sdk/credential-provider-web-identity@3.972.77", "", { "dependencies": { "@aws-sdk/core": "^3.978.0", "@aws-sdk/nested-clients": "^3.997.45", "@aws-sdk/types": "^3.974.5", "@smithy/core": "^3.33.3", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-uylIQSUWpfLuH2LovxEEfwzJGM/SabLOfLMg6YXu/E8jJEKUdpdILCVCQCdFvHyu/7dLJOHPMfrSwduxO56NkQ=="], - "@aws-sdk/credential-provider-login": ["@aws-sdk/credential-provider-login@3.972.55", "", { "dependencies": { "@aws-sdk/core": "^3.974.23", "@aws-sdk/nested-clients": "^3.997.23", "@aws-sdk/types": "^3.973.13", "@smithy/core": "^3.24.6", "@smithy/types": "^4.14.3", "tslib": "^2.6.2" } }, "sha512-hBBkANo3cDn+h2qxxzER4a+J8JCO9o9Z/YYmU7iky6AcaarX5RRdRcHNC6SLdwY0vAXQygn6soUbDqPn3GghaA=="], + "@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.997.45", "", { "dependencies": { "@aws-sdk/core": "^3.978.0", "@aws-sdk/signature-v4-multi-region": "^3.996.46", "@aws-sdk/types": "^3.974.5", "@smithy/core": "^3.33.3", "@smithy/fetch-http-handler": "^5.7.2", "@smithy/node-http-handler": "^4.11.3", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-mooq9Q+jLa18VoM7HouczmslZU60iiB0aKc/Ztnq/luIL1ud0z4DnYprLR/ZO1gp331S9tJctM1HZr7u6YKBXQ=="], - "@aws-sdk/credential-provider-node": ["@aws-sdk/credential-provider-node@3.972.58", "", { "dependencies": { "@aws-sdk/credential-provider-env": "^3.972.49", "@aws-sdk/credential-provider-http": "^3.972.51", "@aws-sdk/credential-provider-ini": "^3.972.56", "@aws-sdk/credential-provider-process": "^3.972.49", "@aws-sdk/credential-provider-sso": "^3.972.55", "@aws-sdk/credential-provider-web-identity": "^3.972.55", "@aws-sdk/types": "^3.973.13", "@smithy/core": "^3.24.6", "@smithy/credential-provider-imds": "^4.3.7", "@smithy/types": "^4.14.3", "tslib": "^2.6.2" } }, "sha512-OyCLVmSI7pZO8hxwNVX6pXhTVlJqRBTp+ijdEfJSUj0RyjHnF602OfAarOzGq6wkGodeFkYBt8MmJ6A6ycRgWw=="], + "@aws-sdk/signature-v4-multi-region": ["@aws-sdk/signature-v4-multi-region@3.996.46", "", { "dependencies": { "@aws-sdk/types": "^3.974.5", "@smithy/signature-v4": "^5.6.12", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-L+2xZTye/2T96f3lwCws0Zw6GG2JHZW9e8FpVgGBeeExSKyeoZ6CWRpBml/7DNiK/O26jrgPM9F+Ay8VkgzUWQ=="], - "@aws-sdk/credential-provider-process": ["@aws-sdk/credential-provider-process@3.972.49", "", { "dependencies": { "@aws-sdk/core": "^3.974.23", "@aws-sdk/types": "^3.973.13", "@smithy/core": "^3.24.6", "@smithy/types": "^4.14.3", "tslib": "^2.6.2" } }, "sha512-C8h36lBuC/RnBSsjlO+dn6xZm3KbAl5vpJaVPAfQnMmz2/OISmKOc8XZcqMQgO2ADwBYNRMM6Kf3vz9G/TulMQ=="], + "@aws-sdk/token-providers": ["@aws-sdk/token-providers@3.1129.0", "", { "dependencies": { "@aws-sdk/core": "^3.978.0", "@aws-sdk/nested-clients": "^3.997.45", "@aws-sdk/types": "^3.974.5", "@smithy/core": "^3.33.3", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-Sbl3rpzQdsG4ZK2zh0JWUYyZPKKorJlVOddA2T0DVbKJFrsW8J6wgnslxxUH04+WaBMr4A1HzJZvZX0xUvkniA=="], - "@aws-sdk/credential-provider-sso": ["@aws-sdk/credential-provider-sso@3.972.55", "", { "dependencies": { "@aws-sdk/core": "^3.974.23", "@aws-sdk/nested-clients": "^3.997.23", "@aws-sdk/token-providers": "3.1074.0", "@aws-sdk/types": "^3.973.13", "@smithy/core": "^3.24.6", "@smithy/types": "^4.14.3", "tslib": "^2.6.2" } }, "sha512-1FkOz74Ea5QGS9jtIoXp55T/IkSS3spv+nLTT07fRY/+T5xmEOqaYBVIaEmX4zTNvbV6g2lrtlaVKWEoNyJt3w=="], + "@aws-sdk/types": ["@aws-sdk/types@3.974.5", "", { "dependencies": { "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-LkwLL2BLbC6wNNm4JaH9mbEqBMdOZCct6VAYqhdN4U1xrWM+fUJQEfbHwQgDypapOWTRtlk25akb5afM0P8CIQ=="], - "@aws-sdk/credential-provider-web-identity": ["@aws-sdk/credential-provider-web-identity@3.972.55", "", { "dependencies": { "@aws-sdk/core": "^3.974.23", "@aws-sdk/nested-clients": "^3.997.23", "@aws-sdk/types": "^3.973.13", "@smithy/core": "^3.24.6", "@smithy/types": "^4.14.3", "tslib": "^2.6.2" } }, "sha512-g2BoECD1q01kTPByi56+VLVvdWDzMkKIcr77qixpqH0okw2t0U5CoPv+6S8v/D1Y2Wa6QKKtn6XAtDzP+Kfpvg=="], + "@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.972.40", "", { "dependencies": { "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-wlFmCIGUlwF4zx/kncw+bmxTQh1HeSJq4mYV/V5cZUSJadDP3kXvGW8Rn21cimj/7y9ju+47oYWXi97vF7czaA=="], - "@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.997.23", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "^3.974.23", "@aws-sdk/signature-v4-multi-region": "^3.996.35", "@aws-sdk/types": "^3.973.13", "@smithy/core": "^3.24.6", "@smithy/fetch-http-handler": "^5.4.6", "@smithy/node-http-handler": "^4.7.6", "@smithy/types": "^4.14.3", "tslib": "^2.6.2" } }, "sha512-gO93ZPsI2bxeFZD42f1/qjDw6FAZkNZcKRO94LIiT03fzOmcJ9e/tunxjVjA1Rl69ClmVJzz8H3G9CdKef10PA=="], - - "@aws-sdk/signature-v4-multi-region": ["@aws-sdk/signature-v4-multi-region@3.996.35", "", { "dependencies": { "@aws-sdk/types": "^3.973.13", "@smithy/signature-v4": "^5.4.6", "@smithy/types": "^4.14.3", "tslib": "^2.6.2" } }, "sha512-6L/VWs+Wch2stHemCGTmUNqKLMzURxQDK5boNG3Jn3kAOp71meDUuS5sbObpEvFxHDq0uWeSLFDNSYsjNt+Dlg=="], - - "@aws-sdk/token-providers": ["@aws-sdk/token-providers@3.1074.0", "", { "dependencies": { "@aws-sdk/core": "^3.974.23", "@aws-sdk/nested-clients": "^3.997.23", "@aws-sdk/types": "^3.973.13", "@smithy/core": "^3.24.6", "@smithy/types": "^4.14.3", "tslib": "^2.6.2" } }, "sha512-pv80IzgGW4RnXWtft692chZOM9i6PhebVsLCcnaM4dBEPZva2fE6FXAHs76G7Rc7s3yGyX/68G0nZMrUy+Vmpg=="], - - "@aws-sdk/types": ["@aws-sdk/types@3.973.13", "", { "dependencies": { "@smithy/types": "^4.14.3", "tslib": "^2.6.2" } }, "sha512-pEHZqRkAlHfnfAU9tK+WpKv/gBNjGJrHMgA3A0iYRGyswBS2t0pfez+lWlwktb3Bqa0ovh7w/QJTFwp3fDxLNg=="], - - "@aws-sdk/util-locate-window": ["@aws-sdk/util-locate-window@3.965.8", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-uUbMs1cBZPafD0ohUj6EwNf0fPZ534NvBxHox4hjX+0Rxq5paSYUem7+hi833pYrzrcnBATKIYpR02MDXT5M9g=="], - - "@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.972.31", "", { "dependencies": { "@smithy/types": "^4.14.3", "tslib": "^2.6.2" } }, "sha512-SzE4Pgyl+hDF+BuyuzxUSpwnuUu9lJuO1YGgteG89/4Qv0+2IQiVQqdbPV32IozLvXWQChPQcdkk/sKvb1QHiQ=="], - - "@aws/lambda-invoke-store": ["@aws/lambda-invoke-store@0.2.4", "", {}, "sha512-iY8yvjE0y651BixKNPgmv1WrQc+GZ142sb0z4gYnChDDY2YqI4P/jsSopBWrKfAt7LOJAkOXt7rC/hms+WclQQ=="], + "@aws/lambda-invoke-store": ["@aws/lambda-invoke-store@0.3.0", "", {}, "sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ=="], "@babel/runtime": ["@babel/runtime@7.29.2", "", {}, "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g=="], @@ -152,7 +140,7 @@ "@changesets/changelog-git": ["@changesets/changelog-git@0.2.1", "", { "dependencies": { "@changesets/types": "^6.1.0" } }, "sha512-x/xEleCFLH28c3bQeQIyeZf8lFXyDFVn1SgcBiR2Tw/r4IAWlk1fzxCEZ6NxQAjF2Nwtczoen3OA2qR+UawQ8Q=="], - "@changesets/cli": ["@changesets/cli@2.31.0", "", { "dependencies": { "@changesets/apply-release-plan": "^7.1.1", "@changesets/assemble-release-plan": "^6.0.10", "@changesets/changelog-git": "^0.2.1", "@changesets/config": "^3.1.4", "@changesets/errors": "^0.2.0", "@changesets/get-dependents-graph": "^2.1.4", "@changesets/get-release-plan": "^4.0.16", "@changesets/git": "^3.0.4", "@changesets/logger": "^0.1.1", "@changesets/pre": "^2.0.2", "@changesets/read": "^0.6.7", "@changesets/should-skip-package": "^0.1.2", "@changesets/types": "^6.1.0", "@changesets/write": "^0.4.0", "@inquirer/external-editor": "^1.0.2", "@manypkg/get-packages": "^1.1.3", "ansi-colors": "^4.1.3", "enquirer": "^2.4.1", "fs-extra": "^7.0.1", "mri": "^1.2.0", "package-manager-detector": "^0.2.0", "picocolors": "^1.1.0", "resolve-from": "^5.0.0", "semver": "^7.5.3", "spawndamnit": "^3.0.1", "term-size": "^2.1.0" }, "bin": { "changeset": "bin.js" } }, "sha512-AhI4enNTgHu2IZr6K4WZyf0EPch4XVMn1yOMFmCD9gsfBGqMYaHXls5HyDv6/CL5axVQABz68eG30eCtbr2wFg=="], + "@changesets/cli": ["@changesets/cli@2.31.1", "", { "dependencies": { "@changesets/apply-release-plan": "^7.1.1", "@changesets/assemble-release-plan": "^6.0.10", "@changesets/changelog-git": "^0.2.1", "@changesets/config": "^3.1.4", "@changesets/errors": "^0.2.0", "@changesets/get-dependents-graph": "^2.1.4", "@changesets/get-release-plan": "^4.0.16", "@changesets/git": "^3.0.4", "@changesets/logger": "^0.1.1", "@changesets/pre": "^2.0.2", "@changesets/read": "^0.6.7", "@changesets/should-skip-package": "^0.1.2", "@changesets/types": "^6.1.0", "@changesets/write": "^0.4.0", "@inquirer/external-editor": "^1.0.2", "@manypkg/get-packages": "^1.1.3", "ansi-colors": "^4.1.3", "enquirer": "^2.4.1", "fs-extra": "^7.0.1", "mri": "^1.2.0", "package-manager-detector": "^0.2.0", "picocolors": "^1.1.0", "resolve-from": "^5.0.0", "semver": "^7.5.3", "spawndamnit": "^3.0.1", "term-size": "^2.1.0" }, "bin": { "changeset": "bin.js" } }, "sha512-uO05WTcRBwuVOJVSW8Cmpqw6q0WDL53ajGCMyszutvOe5toOnunbpM4jZzf+qxBOz7i0AzopZ8diBuewjmF40w=="], "@changesets/config": ["@changesets/config@3.1.4", "", { "dependencies": { "@changesets/errors": "^0.2.0", "@changesets/get-dependents-graph": "^2.1.4", "@changesets/logger": "^0.1.1", "@changesets/should-skip-package": "^0.1.2", "@changesets/types": "^6.1.0", "@manypkg/get-packages": "^1.1.3", "fs-extra": "^7.0.1", "micromatch": "^4.0.8" } }, "sha512-pf0bvD/v6WI2cRlZ6hzpjtZdSlXDXMAJ+Iz7xfFzV4ZxJ8OGGAON+1qYc99ZPrijnt4xp3VGG7eNvAOGS24V1Q=="], @@ -180,7 +168,7 @@ "@changesets/write": ["@changesets/write@0.4.0", "", { "dependencies": { "@changesets/types": "^6.1.0", "fs-extra": "^7.0.1", "human-id": "^4.1.1", "prettier": "^2.7.1" } }, "sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q=="], - "@elysiajs/openapi": ["@elysiajs/openapi@1.4.15", "", { "peerDependencies": { "elysia": ">= 1.4.0" } }, "sha512-HDtGIrWfFJk6UJS7qbgRmjifbSqnnRGDM3CsU/GVJkxLbEVEkNuQDf+Quh9fGbytSrJ8g4+tX9eVjshYhCH29w=="], + "@elysiajs/openapi": ["@elysiajs/openapi@1.4.16", "", { "peerDependencies": { "@sinclair/typebox": ">= 0.34.0 < 1", "elysia": ">= 1.4.0", "typescript": ">= 5.0.0" } }, "sha512-kj8RBffE4J6myjm7nPPj6Dw1ujWt45NkdGW5sG9u3T0OfUzKN71s630/LEjajGo5jRZqFF3VHyk40lwXH2AbmQ=="], "@emnapi/core": ["@emnapi/core@1.10.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" } }, "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw=="], @@ -188,7 +176,7 @@ "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w=="], - "@google-cloud/kms": ["@google-cloud/kms@5.5.1", "", { "dependencies": { "google-gax": "^5.0.0" } }, "sha512-7O3mnspIlotzToIsSrv+YfnGhGdncOyZmjI0gG/r+jcsYN0t8WCa8v9YGuZ0F1VRa+49p/hUT/6ZQh9/s79PfA=="], + "@google-cloud/kms": ["@google-cloud/kms@6.1.0", "", { "dependencies": { "google-gax": "^6.0.0" } }, "sha512-Rl3dVdfjElLKG7GgiS71JYN2q8IaOu2Ea3BwxxLNxSA5F9MSC/4g08xuM62Asfj+pEkIVOlNOrR6K9YTM9Wt/A=="], "@grpc/grpc-js": ["@grpc/grpc-js@1.14.4", "", { "dependencies": { "@grpc/proto-loader": "^0.8.0", "@js-sdsl/ordered-map": "^4.4.2" } }, "sha512-k9Dj3DV/itK9D06Y8f190Qgop7/Ui+D0njFV3LHMPwPT75DpXLQohE9Wmz0QElrJnzsjB7KPWiKJbOl7IPDArQ=="], @@ -196,11 +184,13 @@ "@inquirer/external-editor": ["@inquirer/external-editor@1.0.3", "", { "dependencies": { "chardet": "^2.1.1", "iconv-lite": "^0.7.0" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA=="], - "@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=="], - "@isaacs/fs-minipass": ["@isaacs/fs-minipass@4.0.1", "", { "dependencies": { "minipass": "^7.0.4" } }, "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w=="], - "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="], + "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], + + "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.6.0", "", {}, "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw=="], + + "@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=="], "@js-sdsl/ordered-map": ["@js-sdsl/ordered-map@4.4.2", "", {}, "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw=="], @@ -214,7 +204,7 @@ "@noble/curves": ["@noble/curves@1.9.1", "", { "dependencies": { "@noble/hashes": "1.8.0" } }, "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA=="], - "@noble/hashes": ["@noble/hashes@2.2.0", "", {}, "sha512-IYqDGiTXab6FniAgnSdZwgWbomxpy9FtYvLKs7wCUs2a8RkITG+DFGO1DM9cr+E3/RgADRpFjrKVaJ1z6sjtEg=="], + "@noble/hashes": ["@noble/hashes@2.4.0", "", {}, "sha512-X5XaVWZIBCT7HHZGm5I7ZQXDwLG+bGXuSrMQAW+7Zvl87h1kmc1ZB1VSRJcpUfoUrGQp4Fkoxm5kZ+Ms+aW+eA=="], "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], @@ -222,88 +212,88 @@ "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], + "@opentelemetry/api": ["@opentelemetry/api@1.9.1", "", {}, "sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q=="], + "@oxc-project/types": ["@oxc-project/types@0.127.0", "", {}, "sha512-aIYXQBo4lCbO4z0R3FHeucQHpF46l2LbMdxRvqvuRuW2OxdnSkcng5B8+K12spgLDj93rtN3+J2Vac/TIO+ciQ=="], - "@oxfmt/binding-android-arm-eabi": ["@oxfmt/binding-android-arm-eabi@0.54.0", "", { "os": "android", "cpu": "arm" }, "sha512-NAtpl/SiaeU103e7/OmZw0MvUnsUUopW7hEm/ecegJg7YM0skQaA0IXEZoyTV6NUdiNPupdIUreRqUZTShbn/g=="], + "@oxfmt/binding-android-arm-eabi": ["@oxfmt/binding-android-arm-eabi@0.67.0", "", { "os": "android", "cpu": "arm" }, "sha512-2olh3ioEmc4gRzQm7jxyB1b/PFBoFvTq8KdgYySeNpysDtA6DEg2Mvya4/I6flhL7G0eOrE8RD7JCNCIMhE16Q=="], - "@oxfmt/binding-android-arm64": ["@oxfmt/binding-android-arm64@0.54.0", "", { "os": "android", "cpu": "arm64" }, "sha512-B4VZfBUlKK1rmMChsssNZbkZjE8+FzG3avMjGgMDwbGxXRoXkoeXiAZ+78Oa+eyDPHvDCiUb4zH/vmCOUSafLQ=="], + "@oxfmt/binding-android-arm64": ["@oxfmt/binding-android-arm64@0.67.0", "", { "os": "android", "cpu": "arm64" }, "sha512-ulfw8EHN1MBq/MFFDXw2/M1VAFu5mRUcnuZ8Hqbv9viAnFzO9t1jKSAsDqKYYDGMlytF/uj6Z5z5n/tHupnKhw=="], - "@oxfmt/binding-darwin-arm64": ["@oxfmt/binding-darwin-arm64@0.54.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-i02vF75b+ePsQP3tHqSxVYI5S6b8X/xqdPu7/mDHXtpgXLTYXi3jJmfHU0j+dnZZDKaYTx/ioCK7QYJmtiJR2g=="], + "@oxfmt/binding-darwin-arm64": ["@oxfmt/binding-darwin-arm64@0.67.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-MfONZx/O2o9M5v2jDFol556G9+A+P9xCuJ4DZ+qhE+RnaCdoscy6Eu5nq1dbuNxhwdJyZ6kLI7fnG9mwEeOeGg=="], - "@oxfmt/binding-darwin-x64": ["@oxfmt/binding-darwin-x64@0.54.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-8VMFvGvooXj7mswkbrhdVZ2/sgiDaBzWpkkbtO+qGDLV4EfJd67nQadHkQC0ZNbaWA9ajXfqI6i7PZLIeDzxEQ=="], + "@oxfmt/binding-darwin-x64": ["@oxfmt/binding-darwin-x64@0.67.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-CYnIx5LvFVJnyJcCqwH2jxMKjFjqo5678MPjdmNFoSGMhlOvZ/xRZqvhDcolKrXc8fezW3AKh+C4wyoFuWOSSg=="], - "@oxfmt/binding-freebsd-x64": ["@oxfmt/binding-freebsd-x64@0.54.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-0cRHnp43WN1Jrc5s0BdbdKgR1XirdvHy7TAFi3JEsoEVQVJxTXMbpVd76sxXlgRswNMDhVFSJw+y7Eb8mEavFQ=="], + "@oxfmt/binding-freebsd-x64": ["@oxfmt/binding-freebsd-x64@0.67.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-7/iF1orvIS9mxhKUqnmtMgm+OrSQ5acPwuvdQrm6ECgqbwPmC+Pw9cdke3sNfVN6pT2hbJ58+jP8BCThl5HXOg=="], - "@oxfmt/binding-linux-arm-gnueabihf": ["@oxfmt/binding-linux-arm-gnueabihf@0.54.0", "", { "os": "linux", "cpu": "arm" }, "sha512-JyQAk3hK/OEtup7Rw6kZwfdzbKqTVD5jXXb8Xpfay29suwZyfBDMVW/bj4RqEPySYWc6zCp198pOluf8n5uYzg=="], + "@oxfmt/binding-linux-arm-gnueabihf": ["@oxfmt/binding-linux-arm-gnueabihf@0.67.0", "", { "os": "linux", "cpu": "arm" }, "sha512-yy+OGys07IZOpOmYPZoObKyUQLkfxeQqeCypk+1jaZd8HGo77hzvU1Jg8X3+W75o+9lszOjBfg0nkGtlwYywXw=="], - "@oxfmt/binding-linux-arm-musleabihf": ["@oxfmt/binding-linux-arm-musleabihf@0.54.0", "", { "os": "linux", "cpu": "arm" }, "sha512-qnvLatTpM8vtvjOfcckBOzJjk+n6ce/wwpP8OFeUrD5aNLYcKyWAitwj+Rk3PK9jGanbZvKsJnv14JGQ6XqFdw=="], + "@oxfmt/binding-linux-arm-musleabihf": ["@oxfmt/binding-linux-arm-musleabihf@0.67.0", "", { "os": "linux", "cpu": "arm" }, "sha512-wPIeeigXgJpwNw3wydYRt3U9iN9Y/ejpOZuYL9IA7igxWs7LIQMOkhKxTumRvy6dIv0iXKk3RTw3Vmjg0i+2sg=="], - "@oxfmt/binding-linux-arm64-gnu": ["@oxfmt/binding-linux-arm64-gnu@0.54.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-SMkhnCzIYZYDk9vw3W/80eeYKmrMpGF0Giuxt4HruFlCH7jEtnPeb3SdQKMfgYi/dgtaf+hZAb5XWPYnxqCQ3w=="], + "@oxfmt/binding-linux-arm64-gnu": ["@oxfmt/binding-linux-arm64-gnu@0.67.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-0+XNxcdbkTfxdcD4qW6Ci9n+mBNJ8xTBumnxKvKBmRFOdx0Wf8/KiHjCJayooXmYkqRpRVd98Q5egvzx5BLSgQ=="], - "@oxfmt/binding-linux-arm64-musl": ["@oxfmt/binding-linux-arm64-musl@0.54.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-QrwJlBFFKnxOd95TAaszpMbZBLzMoYMpGaQTZF8oibacnF5rv8l12IhILhQRPmksWiBqg0YSe2Mnl7ayeJAHSA=="], + "@oxfmt/binding-linux-arm64-musl": ["@oxfmt/binding-linux-arm64-musl@0.67.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-I75LKPJyNOYUzkqAiAMIE31+Ye7xtQXZdoty1IXn4B+bw5Zpmez5wfG19ejGpNnS/BzQ7LFS+7jxuTPb+vHiZw=="], - "@oxfmt/binding-linux-ppc64-gnu": ["@oxfmt/binding-linux-ppc64-gnu@0.54.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-WILatiol/TUHTlhod7R09+7Az/XlhKwmY1MHfLZNmewltPWNN/EwxP2rQSHahibZ/cB8gmckEBjBOByD+5bYsQ=="], + "@oxfmt/binding-linux-ppc64-gnu": ["@oxfmt/binding-linux-ppc64-gnu@0.67.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-c2M5iRpe1QMZSRE/UvZoPdXBWb5Ic/ycvOyNiKCqPwQ/OyOKIMiJs02ynlNnjb7ZZJnRXYLmGcohoINOcwDK3w=="], - "@oxfmt/binding-linux-riscv64-gnu": ["@oxfmt/binding-linux-riscv64-gnu@0.54.0", "", { "os": "linux", "cpu": "none" }, "sha512-f05YMG4BH4G8S4ME6UM6fi1MnJ9094mrnvO5Pa4SJlMfWlUM+1/ZWMEF4NnjM7shZAvbHsHRuVYpUo0PHC4P9Q=="], + "@oxfmt/binding-linux-riscv64-gnu": ["@oxfmt/binding-linux-riscv64-gnu@0.67.0", "", { "os": "linux", "cpu": "none" }, "sha512-dQzzYlV24Udhfm5ECuSdgqRvFJU/CGHzcYYEO3dLM6W6+CHiBFrq9OjIllkdCcPhsoSQ8o223Dja84MOSzed9A=="], - "@oxfmt/binding-linux-riscv64-musl": ["@oxfmt/binding-linux-riscv64-musl@0.54.0", "", { "os": "linux", "cpu": "none" }, "sha512-UfL+2hj1ClNqcCRT9s8vBU4axDpjxgVxX96G+9DYAYjoc5b0u15CJtn2jgsi9iM+EbGNc5CW1HVRgwVu76UsSA=="], + "@oxfmt/binding-linux-riscv64-musl": ["@oxfmt/binding-linux-riscv64-musl@0.67.0", "", { "os": "linux", "cpu": "none" }, "sha512-rFNq1CgX4qMJANOq42LkAs90JE80GpiaEohAV2qn/gT2hGjQTW1zBO5zQBxArI4926pM1OSzo3CN0tBszGBIaA=="], - "@oxfmt/binding-linux-s390x-gnu": ["@oxfmt/binding-linux-s390x-gnu@0.54.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-3/XZe931Hka+J6NjnaqJzYpsWWxDTuRdUdwSQHnOuJEgbC+SehIMFJS8hsEjV7LBhVSL2OCnRLvbVW8O97XIyw=="], + "@oxfmt/binding-linux-s390x-gnu": ["@oxfmt/binding-linux-s390x-gnu@0.67.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-Sky6rEdz2o5IGq01lPhS12yEvDdChVEcaYrcLHkveh4Fx0qPjljE/Iul6SX/bRMl6lNc8J7J/mDQdzgBdA++Pg=="], - "@oxfmt/binding-linux-x64-gnu": ["@oxfmt/binding-linux-x64-gnu@0.54.0", "", { "os": "linux", "cpu": "x64" }, "sha512-Ik93RlObtu43GbxApafayFjwYE06L6Xr08cSwpBPYbDrLp2ReZx0Jm1DqwRyYRnukUJy+rK2WaEvUQOxdytU9Q=="], + "@oxfmt/binding-linux-x64-gnu": ["@oxfmt/binding-linux-x64-gnu@0.67.0", "", { "os": "linux", "cpu": "x64" }, "sha512-vPXmlNORV8AZq2Ocxh07pxwMjfENUWCV/eZArnao0qC3NO/hDeTVkQvee7SJJUbIiF5PZbBa4kYmaXnu7Rk58w=="], - "@oxfmt/binding-linux-x64-musl": ["@oxfmt/binding-linux-x64-musl@0.54.0", "", { "os": "linux", "cpu": "x64" }, "sha512-yZcakmPlD86CNymknd7KfW+FH+qfbqJH+i0h69CYfV1+KMoVeM9UED+8+TDVoU4haxI0NxY7RPCvRLy3Sqd2Qg=="], + "@oxfmt/binding-linux-x64-musl": ["@oxfmt/binding-linux-x64-musl@0.67.0", "", { "os": "linux", "cpu": "x64" }, "sha512-x/WAtFqYtVr3vZ9ni8nr4kn9whSitg8fOljq/pZzBpxopRdY1BMLZCZkrbIbaBcYkm46qGbqVea2FCWmtQ2P9w=="], - "@oxfmt/binding-openharmony-arm64": ["@oxfmt/binding-openharmony-arm64@0.54.0", "", { "os": "none", "cpu": "arm64" }, "sha512-GiVBZNnEZnKu00f1jTg49nomv187d0GQX+O+ocykoLeiaALuEO+swoTehHn9TehTfi7V8H0i0e/yvUjCqnwk1w=="], + "@oxfmt/binding-openharmony-arm64": ["@oxfmt/binding-openharmony-arm64@0.67.0", "", { "os": "none", "cpu": "arm64" }, "sha512-eRw9Neh4/aA6i+q/R3WU1gGQINhVM0J4fXIm6t27caOamkr/37uAkp1IdBx4zlJH97hmXR63z/q9n5c5dN7MzA=="], - "@oxfmt/binding-win32-arm64-msvc": ["@oxfmt/binding-win32-arm64-msvc@0.54.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-J0SSB8Z1Fre2sxRolYcW6Rl1RQmKdQ2hnHyq4YJrfBRiXTObLw4DXnIVraM/UyqGqwOi7yTrQA4VT7DPxlHVKA=="], + "@oxfmt/binding-win32-arm64-msvc": ["@oxfmt/binding-win32-arm64-msvc@0.67.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-YIMvb+sGNYN2uc6+QK2HLPeEKM2vl7QZ5onQzpAJRb6pnf0DwUFP5R8tdS9R0l8hdUil2gu4Uxd0Yxrop0iT4w=="], - "@oxfmt/binding-win32-ia32-msvc": ["@oxfmt/binding-win32-ia32-msvc@0.54.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-O61UDVj8zz6yXJjkHPf05VaMLOXmEF8P5kf/N0W7AQMmd6bcQogl+KJc7rMutKTL524oE9iH32JXZClBFmEQIg=="], + "@oxfmt/binding-win32-ia32-msvc": ["@oxfmt/binding-win32-ia32-msvc@0.67.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-LzmU9MyACPzwNDIK0ItMedHPz735Ug7ELWguxo4/kuy6zWuDoeglOAEFCY8jLg0PzRpFO3hDyLFe2Gu2eFDeGA=="], - "@oxfmt/binding-win32-x64-msvc": ["@oxfmt/binding-win32-x64-msvc@0.54.0", "", { "os": "win32", "cpu": "x64" }, "sha512-1MDpqJPiFqxWtIHas8vkb1VZ7f7eKyTffAwmO8isxQYMaG1OFKsH666BWLeXQLO+IWNfiMssLD55hbR1lIPTqg=="], + "@oxfmt/binding-win32-x64-msvc": ["@oxfmt/binding-win32-x64-msvc@0.67.0", "", { "os": "win32", "cpu": "x64" }, "sha512-sbQOIDNLUEeVZcAJcSL5VURn7kfjvilPviody4Yl5n8lQCDtUm+C9oHTTwZS/m4d/Z6Vv3jNEiAofH932NPPCg=="], - "@oxlint/binding-android-arm-eabi": ["@oxlint/binding-android-arm-eabi@1.69.0", "", { "os": "android", "cpu": "arm" }, "sha512-DKQQbD5cZ/MYfDgDI7YGyGD9FSxABlsBsYFo5p26lloob543tP9+4N3guwdXIYJN+7HSZxLe8YJuwcOWw5qnHg=="], + "@oxlint/binding-android-arm-eabi": ["@oxlint/binding-android-arm-eabi@1.82.0", "", { "os": "android", "cpu": "arm" }, "sha512-a3LB+C5Dsj5b/qtmG/mv5WrzuiXEpg1KF5nXWcEvaoN5TYAqkIvxPOwTPp3Jy/FoGpRo8zsTFhMElMXfeoOEzA=="], - "@oxlint/binding-android-arm64": ["@oxlint/binding-android-arm64@1.69.0", "", { "os": "android", "cpu": "arm64" }, "sha512-lEhb+I5pr4inux+JFwfCa1HRq3Os7NirEFQ0H1I35SVEHPm6byX0Ah47xmRha3qi6LAkxUcxViL8o/9PivjzBg=="], + "@oxlint/binding-android-arm64": ["@oxlint/binding-android-arm64@1.82.0", "", { "os": "android", "cpu": "arm64" }, "sha512-OBlhRgNqFblGpGenno/aqOfJLOkQ2B8Ig3iDAalfn0H8hJGZKXPeexCRTDm6uwv6YUjSA9Xnwt1y/Bgj5ZH8uw=="], - "@oxlint/binding-darwin-arm64": ["@oxlint/binding-darwin-arm64@1.69.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-GY2YE8lOZW59BW1Ia1y+1gR0XyjrZRvVWHAr8LGeGhYHE0OQJ/7cRKXTkx1P+E9/6awEc3SX8a68SFTjh/E//A=="], + "@oxlint/binding-darwin-arm64": ["@oxlint/binding-darwin-arm64@1.82.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-dsopxqtY5ZdyT9uLHyGt1SyiLop6hi7hWI3PKpePodkRQOkLaCm+OE4fR9CAz9qdfjiFO8531tX/QDyP/psjFg=="], - "@oxlint/binding-darwin-x64": ["@oxlint/binding-darwin-x64@1.69.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-ax1oZnOjHX3LB7myQyHEaQkDwfLb6str3/nSP6O7EVUviQGNkEGzGV0EqcBJWK+Ufwx0l4xPgyYayurvhAdl2Q=="], + "@oxlint/binding-darwin-x64": ["@oxlint/binding-darwin-x64@1.82.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-94Lu0SgTClKColU66g1VDuigV3HkcbkJBnTtZjGYfE8UPugaWDgKrm2icjC6HJVUYler2OXaHP/X0TBy8+CowQ=="], - "@oxlint/binding-freebsd-x64": ["@oxlint/binding-freebsd-x64@1.69.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-kHWeHv4g2h8NY+mpCxzCtY4uerMJWTN/TSnNj1CPbakFpHEJ6cTya2wWV0pDSYWOJ2+0UiEbhn3AtXxHtsnKjg=="], + "@oxlint/binding-freebsd-x64": ["@oxlint/binding-freebsd-x64@1.82.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-hne/V06ewhh1i0w8+l7GDNROAGCGPmyFuOwiP7YTRu0JycyStJ4785dmF8xU5p0uUwt2emvIF9vc7Xjis+cJ0g=="], - "@oxlint/binding-linux-arm-gnueabihf": ["@oxlint/binding-linux-arm-gnueabihf@1.69.0", "", { "os": "linux", "cpu": "arm" }, "sha512-gq84vM1a1oEehXo27YCDzGVcxPsZDI1yswZwz2Da1/cbnWtrL16XZZnz0G/+gIU8edtHpfjxq5c+vWEHqJfWoQ=="], + "@oxlint/binding-linux-arm-gnueabihf": ["@oxlint/binding-linux-arm-gnueabihf@1.82.0", "", { "os": "linux", "cpu": "arm" }, "sha512-aWY2xtbZf1LneW9Qsv/n2Sp8gOu74JrlQzEtj4coHX2SHFrCfhmAumaU+sI/A5nr+yoTRTSmI/pL2s6ADlNSkw=="], - "@oxlint/binding-linux-arm-musleabihf": ["@oxlint/binding-linux-arm-musleabihf@1.69.0", "", { "os": "linux", "cpu": "arm" }, "sha512-kIqEa98JQ0VRyrcncxA417m2AzasqTlD+FyVT1AksjvjkqQcvm7pBWYvoW3/mpyOP2XYvi5nSCCTIe6De1yu5g=="], + "@oxlint/binding-linux-arm-musleabihf": ["@oxlint/binding-linux-arm-musleabihf@1.82.0", "", { "os": "linux", "cpu": "arm" }, "sha512-Fe+TtXCXMh/5f7kWlZ2VAwsMumZWtraFlKVk1NJlL52/beGwfDE7ov+/8gVirHzWokzGu7X65hSPq0ucPDskWQ=="], - "@oxlint/binding-linux-arm64-gnu": ["@oxlint/binding-linux-arm64-gnu@1.69.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-j+xYiXozxGWx2cpjCrwwGR4awTxPFsRv3JZrv23RCogEPMc4R7UqjHW47p/RG0aRlbWiROCJ8coUfCwy0dvzHA=="], + "@oxlint/binding-linux-arm64-gnu": ["@oxlint/binding-linux-arm64-gnu@1.82.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-6azCZ6OJudlvipNttXCCQcyeFfcJ/NvUZdSN1z8elo73kCHtyQC7WTiUcSjWYvJ1jaq9KDUyMAoAS/vNzhBomA=="], - "@oxlint/binding-linux-arm64-musl": ["@oxlint/binding-linux-arm64-musl@1.69.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-xEPpNppTfN1l/nM7gYSf9iocscu/as+p/7vxkLeLEKnYU+09Dm+5V6IhDYDh+Uz6FajEupWwCLt5SOG0y1PCKg=="], + "@oxlint/binding-linux-arm64-musl": ["@oxlint/binding-linux-arm64-musl@1.82.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-PLEaSD8IAIIlwW4dwOd9YaxuxeOpwiXL4J24rcnE4iNtyM5j9Q9/3+gti08oXpx0u2ygNjRDx9xjWWpQonuJEw=="], - "@oxlint/binding-linux-ppc64-gnu": ["@oxlint/binding-linux-ppc64-gnu@1.69.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-Ug0+eU7HJBlek+SjklYH62IlOMirEJsdxpihH0kSqX0XdrDD4NdHpQc10fK1JC35yn6KrrcN+uYzlHD38XAf8Q=="], + "@oxlint/binding-linux-ppc64-gnu": ["@oxlint/binding-linux-ppc64-gnu@1.82.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-D94em/BwknNTn4vqxjHh5wb2oL566eFhArabqKIr0cNZMHOJuiraFp1A8tXpH05bbE5tqwEfLXTI0MWEGtn3Dw=="], - "@oxlint/binding-linux-riscv64-gnu": ["@oxlint/binding-linux-riscv64-gnu@1.69.0", "", { "os": "linux", "cpu": "none" }, "sha512-iEyI3GIg0l/s3G4qy2TlaaWKdzj4PJJStwtlocpDTC00PY9hZueotf6OKUj9+yfQh0lrpBW/pLMgTztbAHKJEg=="], + "@oxlint/binding-linux-riscv64-gnu": ["@oxlint/binding-linux-riscv64-gnu@1.82.0", "", { "os": "linux", "cpu": "none" }, "sha512-MOprxBaoYU2D4VgxXCl3ghydThWtx7Um1lL51kGYNeQ5Al7WzsH7/tqGdNtbLrIWnjq3bsm13+nz/gRIxjrOXw=="], - "@oxlint/binding-linux-riscv64-musl": ["@oxlint/binding-linux-riscv64-musl@1.69.0", "", { "os": "linux", "cpu": "none" }, "sha512-NjHjpiI4WIKSMwuoJSZi5VToPeoYOS1FR52HLIDG6lidMdqquusgtODb4iLk0+lb1q3Z0nv2/aPRcC/olmpQGg=="], + "@oxlint/binding-linux-riscv64-musl": ["@oxlint/binding-linux-riscv64-musl@1.82.0", "", { "os": "linux", "cpu": "none" }, "sha512-5h55QsfJ/luDXZzC20k6SNOY1Az+dCP9WvntKtcUWh2JhckAdwApY2ZusaBTwLENnReXU+A2fJtSrYvZJNKNPg=="], - "@oxlint/binding-linux-s390x-gnu": ["@oxlint/binding-linux-s390x-gnu@1.69.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-Ai/prDewoItkDXbp38gwGZi41DycZbUTZJ3UidwoHgQC0/DaqC2TGdtBTQLJ6hSD+SAxASzh8+/eSBPmxfOacA=="], + "@oxlint/binding-linux-s390x-gnu": ["@oxlint/binding-linux-s390x-gnu@1.82.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-IE8NJNLlHr0CaXyGJPGVn0eTkUyoj1I2UfA8x7I4PSOYKsQ/6btVC7Pywrj5onk0cMH25r6Z38SoN3AvE5Zuog=="], - "@oxlint/binding-linux-x64-gnu": ["@oxlint/binding-linux-x64-gnu@1.69.0", "", { "os": "linux", "cpu": "x64" }, "sha512-Gt3KHgp46mRKz4sJeaASmKvD8ayXookRw07RMf+NowhEztGGDZ7VrXpoW96XuKJLjFukWizOFVNjmYb/u7caNQ=="], + "@oxlint/binding-linux-x64-gnu": ["@oxlint/binding-linux-x64-gnu@1.82.0", "", { "os": "linux", "cpu": "x64" }, "sha512-XUUUxaBo9XKl+J1B9EmP1cTGQPddzeURvoGkfwh/94PGnbW+hBprDljneoI2M1jzC1bzrIV3ihc7iM9UXl8+tg=="], - "@oxlint/binding-linux-x64-musl": ["@oxlint/binding-linux-x64-musl@1.69.0", "", { "os": "linux", "cpu": "x64" }, "sha512-7tQhJ2+p/oHv1zcfnjYI7YVzC/7iBaVOfIvFYtxdJ5F45mWgEdrCyXZXZGfiLey5t/5JhOhsaMnnv1kAzckd7g=="], + "@oxlint/binding-linux-x64-musl": ["@oxlint/binding-linux-x64-musl@1.82.0", "", { "os": "linux", "cpu": "x64" }, "sha512-SWLSFulX9TDuH6yvbPYp4+VNn6jkkIvvI+KiujDM5rWBRHEfkesCC/pCneIIUr6ovkxZ5fRtpi2v5Cz5FrMJZg=="], - "@oxlint/binding-openharmony-arm64": ["@oxlint/binding-openharmony-arm64@1.69.0", "", { "os": "none", "cpu": "arm64" }, "sha512-vmWz6TKp/3hfA4lksR0zHBv/6xuX1jhym6eqOjdH2DXsDDHZWcp2f0KG0VCAnlVbIrjk29G4wAWMXb/Hn1YobA=="], + "@oxlint/binding-openharmony-arm64": ["@oxlint/binding-openharmony-arm64@1.82.0", "", { "os": "none", "cpu": "arm64" }, "sha512-BQy35f6ZUdNr9a6c7B7orxQTcLjByGT2z3WAgmRovpRwmPYAaJ+NTplmMzhdjdJ4qSchfMNZy/Ukg+qRg6zseQ=="], - "@oxlint/binding-win32-arm64-msvc": ["@oxlint/binding-win32-arm64-msvc@1.69.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-9RExaLgmaw6IoIkU9cTpT71mLfI0xZ86iZH8x518LVsOkjquJMYqb9P7KpC8lgd1t0Dxs41p2pxynq4XR3Ttzw=="], + "@oxlint/binding-win32-arm64-msvc": ["@oxlint/binding-win32-arm64-msvc@1.82.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-V4QhSTg5gctZue8RJjsGi7NpQPThr/p1/HfmiMC5kfe1KFEup9SQRVub4A6kijQjdHfxj7bLL1KO3QO7/5bwMQ=="], - "@oxlint/binding-win32-ia32-msvc": ["@oxlint/binding-win32-ia32-msvc@1.69.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-1907kRPF8/PrcIw1E7LMs9JbVrpgnt/MvFdss3an8oDkYNAACXzTntV3t3869ZZhMZxb2AzRGbz1pA/jdFatXA=="], + "@oxlint/binding-win32-ia32-msvc": ["@oxlint/binding-win32-ia32-msvc@1.82.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-TUSCLaKB2yktpFAJ/r3HAUYsaV/3DT7JS4iNKyoh3a9YNwD0UG7Ezh4D8m23654vQcU6P/RQrCAjRPKe4peP/A=="], - "@oxlint/binding-win32-x64-msvc": ["@oxlint/binding-win32-x64-msvc@1.69.0", "", { "os": "win32", "cpu": "x64" }, "sha512-w8SOXv3mT9Fi6jY8OXdXCfnvX/3KNLXGNr4HEz2TA7S4Mv/PYAOmpB8y/ge40mxvBMgGNaSaaDwZpAsQn7HtWA=="], + "@oxlint/binding-win32-x64-msvc": ["@oxlint/binding-win32-x64-msvc@1.82.0", "", { "os": "win32", "cpu": "x64" }, "sha512-VTVoRIWJTb+wvUX8EYoPArfFH02whuR10goFXE/LHRRX33ajRrFgqbcONXZMiF4C5rnattfkm87HqYn8jb8hmQ=="], "@pinojs/redact": ["@pinojs/redact@0.4.0", "", {}, "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg=="], - "@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="], - "@protobufjs/aspromise": ["@protobufjs/aspromise@1.1.2", "", {}, "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ=="], "@protobufjs/base64": ["@protobufjs/base64@1.1.2", "", {}, "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg=="], @@ -366,25 +356,17 @@ "@sindresorhus/merge-streams": ["@sindresorhus/merge-streams@4.0.0", "", {}, "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ=="], - "@smithy/core": ["@smithy/core@3.26.0", "", { "dependencies": { "@aws-crypto/crc32": "5.2.0", "@smithy/types": "^4.15.0", "tslib": "^2.6.2" } }, "sha512-mLUktFAn+Pa2agl1J7VgtYNFWCX8/b4GMJSK1hCu4YCvtBfM6F8Os3EP4ry+DFFlXOf3wyvlgXhuUdFoy52D3g=="], + "@smithy/core": ["@smithy/core@3.33.3", "", { "dependencies": { "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-CsOeKq/9kA3y6VJHt+/+VTCtBaxJ4OTFpgrjIUhPpDIKxBci1k2bJaQASF2h/ELWrulGp+t97DZ0mevfAD8idg=="], - "@smithy/credential-provider-imds": ["@smithy/credential-provider-imds@4.4.2", "", { "dependencies": { "@smithy/core": "^3.26.0", "@smithy/types": "^4.15.0", "tslib": "^2.6.2" } }, "sha512-18UMDMyrAbDcpmL1gLUA7ww0fRTcdCrSjSJOi2Sbld+tVjwD/pW+OAwjlScFLR7vvBnhZrIPQ7kVuTf1mnJLug=="], + "@smithy/credential-provider-imds": ["@smithy/credential-provider-imds@4.5.2", "", { "dependencies": { "@smithy/core": "^3.33.2", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-A9uSdn72ozbRUSit0eib0TW7nXuNPlaeM0zcGkJ+nE6tFcSDbnmtwoxbTCFBukVQcszDAyvsd7+rTduPTXpygg=="], - "@smithy/fetch-http-handler": ["@smithy/fetch-http-handler@5.5.2", "", { "dependencies": { "@smithy/core": "^3.26.0", "@smithy/types": "^4.15.0", "tslib": "^2.6.2" } }, "sha512-Ei/UK/QMhq0rKaMqGPlOAkE2yS9DZeYmZdk1RAKc3vp3zxgleZHZyBLlZv8yLsxljX4svCRuMTD6u3LLIcU4Bg=="], + "@smithy/fetch-http-handler": ["@smithy/fetch-http-handler@5.8.0", "", { "dependencies": { "@smithy/core": "^3.33.3", "@smithy/types": "^4.18.0", "tslib": "^2.6.2" } }, "sha512-ycSJu3tFAQ4v04CBB0agqFMVsSQ1iG3yw+SpgxRqKfaURpQD4CZ8Wn0zPMmSnOuTpTh65Vz+EA0rMrw089wvkA=="], - "@smithy/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="], + "@smithy/node-http-handler": ["@smithy/node-http-handler@4.12.1", "", { "dependencies": { "@smithy/core": "^3.33.3", "@smithy/types": "^4.18.0", "tslib": "^2.6.2" } }, "sha512-ThMkboGeONWXAelq9FvGsuJC4rOi+qyC4/zhUF58xYpxUg5sQKx2VXZYJmtNjr4dSuBJ1HeJXETQILCz3wOHvw=="], - "@smithy/node-http-handler": ["@smithy/node-http-handler@4.8.2", "", { "dependencies": { "@smithy/core": "^3.26.0", "@smithy/types": "^4.15.0", "tslib": "^2.6.2" } }, "sha512-wfl1uwrAqMH9/pi4kqBo5LBcFwrJLxuDLqL7p7qNcJIFcyZDUc6pzhYk4CYv+DP7fIUpQCZumwNnkhPKS52osQ=="], + "@smithy/signature-v4": ["@smithy/signature-v4@5.7.3", "", { "dependencies": { "@smithy/core": "^3.33.3", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-7ImGm+FkHRLcBaRttIAMZ6bzJZWb2cJGoYjq46F2UjycujWzrL9GEN9h4w7eQyXJYnltrUhxbbieBAIRrdqpow=="], - "@smithy/signature-v4": ["@smithy/signature-v4@5.5.2", "", { "dependencies": { "@smithy/core": "^3.26.0", "@smithy/types": "^4.15.0", "tslib": "^2.6.2" } }, "sha512-7xHpmPY4rt0IOmeAA8EfjgEH8isT+587TCdy9H6a7d4OMi5CQ0oEHhWllunvPu4j4Cq0vTFwdxXN/kABWPjdyA=="], - - "@smithy/types": ["@smithy/types@4.15.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-Z5TAOxygoFvybJV3igo5SloFflSokHx2hu1eFA+DxDTcn+FtKxUSui+rbTRG1pAafMA888Z3MVvCWUuvCrTXjg=="], - - "@smithy/util-buffer-from": ["@smithy/util-buffer-from@2.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA=="], - - "@smithy/util-utf8": ["@smithy/util-utf8@2.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A=="], - - "@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], + "@smithy/types": ["@smithy/types@4.18.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-CgB6HHWer/vrKps24ulRIbpcpb7K4xAU7SkZ7YHzBPlwHsvsrCJFEXK421s+cJzX+ZrqtA/TuU5w1HzI7k9N8A=="], "@tokenizer/inflate": ["@tokenizer/inflate@0.4.1", "", { "dependencies": { "debug": "^4.4.3", "token-types": "^6.1.1" } }, "sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA=="], @@ -392,7 +374,7 @@ "@tybys/wasm-util": ["@tybys/wasm-util@0.10.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg=="], - "@types/bun": ["@types/bun@1.3.14", "", { "dependencies": { "bun-types": "1.3.14" } }, "sha512-h1hFqFVcvAvD9j9K7ZW7vd82aSA+rTdznZa+5bwvCwqSB1jmmfLcbIWhOLx1/+boy/xmjgCs/OMUL8hRJSmnPw=="], + "@types/bun": ["@types/bun@1.4.2", "", { "dependencies": { "bun-types": "1.4.2" } }, "sha512-GimotNn7+ZV0uVArItBbriZsR1oNf0+WTzPkdcFrzShI7k2norL0uzEaJT8T33dWr7O/c9ZDuAFQrctKCi72oQ=="], "@types/chai": ["@types/chai@5.2.3", "", { "dependencies": { "@types/deep-eql": "*", "assertion-error": "^2.0.1" } }, "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA=="], @@ -402,19 +384,9 @@ "@types/node": ["@types/node@25.6.0", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ=="], - "@vitest/expect": ["@vitest/expect@4.1.8", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", "@vitest/spy": "4.1.8", "@vitest/utils": "4.1.8", "chai": "^6.2.2", "tinyrainbow": "^3.1.0" } }, "sha512-h3nDO677RDLEGlBxyQ5CW8RlMThSKSRLUePLOx09gNIWRL40edgA1GCZSZgf1W55MFAG6/Sw14KeaAnqv0NKdQ=="], - - "@vitest/mocker": ["@vitest/mocker@4.1.8", "", { "dependencies": { "@vitest/spy": "4.1.8", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "optionalPeers": ["msw", "vite"] }, "sha512-LEiN/xe4OSIbKe9HQIp5OC24agGD9J5CnmMgsLohVVoOPWL9a2sBoR6VBx43jQZb7Kr1l4RCuyCJzcAa0+dojw=="], + "@vitest/mocker": ["@vitest/mocker@5.0.0", "", { "dependencies": { "@jridgewell/trace-mapping": "0.3.31", "@vitest/spy": "5.0.0", "estree-walker": "^3.0.3", "magic-string": "^1.2.3" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "optionalPeers": ["msw", "vite"] }, "sha512-66PGTMIiVJP3t4a5yxU9qPtf7MdTBs8jmToMvy+HVflB3Yy13WJZTtPePdvU+wjRV02SKK5doLbSA6o9pwOmiA=="], - "@vitest/pretty-format": ["@vitest/pretty-format@4.1.8", "", { "dependencies": { "tinyrainbow": "^3.1.0" } }, "sha512-9GasEBxpZ1VYIpqHf/0+YGg121uSNwCKOJqIrTwWP/TB7DmFCiaBpNl3aPZzoLWfWkuqhbH8vJIVobZkvdo2cA=="], - - "@vitest/runner": ["@vitest/runner@4.1.8", "", { "dependencies": { "@vitest/utils": "4.1.8", "pathe": "^2.0.3" } }, "sha512-EmVxeBAfMJvycdjd6Hm+RbFBbA9fKvo0Kx37hNpBYoYeavH3RNsBXWDooR1mgD52dCrxIIuP7UotpfiwOikvcg=="], - - "@vitest/snapshot": ["@vitest/snapshot@4.1.8", "", { "dependencies": { "@vitest/pretty-format": "4.1.8", "@vitest/utils": "4.1.8", "magic-string": "^0.30.21", "pathe": "^2.0.3" } }, "sha512-acfZboRmAIf05DEKcBQy33VXojFJjtUdLyo7oOmV9kebb2xdU01UknNiPuPZoJZQyO7DF0gZdTGTpeAzET9QPQ=="], - - "@vitest/spy": ["@vitest/spy@4.1.8", "", {}, "sha512-6EevtBp6OZOPF7bmz36HrGMeP3txgVSrgebWxHOafDXGkhIzfXK14f8KF6MuFfgXXUeHxmpD3BQxkV00/3s5mA=="], - - "@vitest/utils": ["@vitest/utils@4.1.8", "", { "dependencies": { "@vitest/pretty-format": "4.1.8", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.1.0" } }, "sha512-uOJamYALNhfJ6iolExyQM40yIQwDqYnkKtQ5VCiSe17E33H0aQ/u+1GlRuz4LZBk6Mm3sg90G9hEbmEt37C1Zg=="], + "@vitest/spy": ["@vitest/spy@5.0.0", "", {}, "sha512-uy+luWBAPw9XfthoHi5AkfHUnuPYEESjl0p/r+meoBnU8bxg5GDQ3Ey8MjcJ6sqahkL4PFyrvfMJJBw7LbU06g=="], "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=="], @@ -434,25 +406,21 @@ "atomic-sleep": ["atomic-sleep@1.0.0", "", {}, "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ=="], - "balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], - "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="], "better-path-resolve": ["better-path-resolve@1.0.0", "", { "dependencies": { "is-windows": "^1.0.0" } }, "sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g=="], - "better-result": ["better-result@2.9.2", "", {}, "sha512-WIFoBPCdnTOdk9inkE1ZRvCZ4P0CpSkAiLlchC65N7n9DcjZ3NhqkBOlafzpOVnO8ixyi37kicmSJ3ENhPZl7Q=="], + "better-result": ["better-result@3.0.1", "", {}, "sha512-rnCeqEXkKPHmz5MO5ZroPRDyHe4YvlNPyy7qj8cVcWs/GnvSvC3086G74/220W+wWcIWlXgzvcjskFV0A4blUQ=="], "bignumber.js": ["bignumber.js@9.3.1", "", {}, "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ=="], "bowser": ["bowser@2.14.1", "", {}, "sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg=="], - "brace-expansion": ["brace-expansion@5.0.8", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-JZyDyq3D4AUifKTPOB7DELf6XsB3WdPuNxCtob1vFXPsSXhdAiHBWJ/tJ8HAc9aH84BK+5JFZLNkJKx3G9kzQg=="], - "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], "buffer-equal-constant-time": ["buffer-equal-constant-time@1.0.1", "", {}, "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="], - "bun-types": ["bun-types@1.3.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ=="], + "bun-types": ["bun-types@1.4.2", "", { "dependencies": { "@types/node": "*" } }, "sha512-bxV1FgK7yBIzjRe5zBozIM4Bem11ZJcCXSrjWRG3YWLt8yFDePu4cLjpebO8OvPeIE9trbyPF4fuj3Cia4Fj3w=="], "chai": ["chai@6.2.2", "", {}, "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg=="], @@ -470,8 +438,6 @@ "colorette": ["colorette@2.0.20", "", {}, "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w=="], - "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="], - "cookie": ["cookie@1.1.1", "", {}, "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ=="], "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], @@ -490,11 +456,9 @@ "duplexify": ["duplexify@4.1.3", "", { "dependencies": { "end-of-stream": "^1.4.1", "inherits": "^2.0.3", "readable-stream": "^3.1.1", "stream-shift": "^1.0.2" } }, "sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA=="], - "eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="], - "ecdsa-sig-formatter": ["ecdsa-sig-formatter@1.0.11", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ=="], - "elysia": ["elysia@1.4.29", "", { "dependencies": { "cookie": "^1.1.1", "exact-mirror": "^0.2.7", "fast-decode-uri-component": "^1.0.1", "memoirist": "^0.4.0" }, "peerDependencies": { "@sinclair/typebox": ">= 0.34.0 < 1", "@types/bun": ">= 1.2.0", "file-type": ">= 20.0.0", "openapi-types": ">= 12.0.0", "typescript": ">= 5.0.0" }, "optionalPeers": ["@types/bun", "typescript"] }, "sha512-GwMRGGwSdjfPt+w3LA0fqTuYJtS8uVRJicvoar98/HrO5qdFKDc9CwjIb6Kja+v39lkY+58hr2JvdR9jQzlUuA=="], + "elysia": ["elysia@1.4.30", "", { "dependencies": { "cookie": "^1.1.1", "exact-mirror": "^0.2.7", "fast-decode-uri-component": "^1.0.1", "memoirist": "^0.4.0" }, "peerDependencies": { "@sinclair/typebox": ">= 0.34.0 < 1", "@types/bun": ">= 1.2.0", "file-type": ">= 20.0.0", "openapi-types": ">= 12.0.0", "typescript": ">= 5.0.0" }, "optionalPeers": ["@types/bun", "typescript"] }, "sha512-S2qqV0CbM4faB1hQQ5IYoeYnAUinjHlzRduxaBc4OoNqh0GjOc8k6tt3hv5ozWcG6Svr6hugw6JL4zNke4jwfA=="], "emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], @@ -502,7 +466,7 @@ "enquirer": ["enquirer@2.4.1", "", { "dependencies": { "ansi-colors": "^4.1.1", "strip-ansi": "^6.0.1" } }, "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ=="], - "es-module-lexer": ["es-module-lexer@2.1.0", "", {}, "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ=="], + "es-module-lexer": ["es-module-lexer@2.3.2", "", {}, "sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw=="], "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], @@ -516,7 +480,7 @@ "execa": ["execa@9.6.1", "", { "dependencies": { "@sindresorhus/merge-streams": "^4.0.0", "cross-spawn": "^7.0.6", "figures": "^6.1.0", "get-stream": "^9.0.0", "human-signals": "^8.0.1", "is-plain-obj": "^4.1.0", "is-stream": "^4.0.1", "npm-run-path": "^6.0.0", "pretty-ms": "^9.2.0", "signal-exit": "^4.1.0", "strip-final-newline": "^4.0.0", "yoctocolors": "^2.1.1" } }, "sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA=="], - "expect-type": ["expect-type@1.3.0", "", {}, "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA=="], + "expect-type": ["expect-type@1.4.0", "", {}, "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA=="], "extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="], @@ -546,8 +510,6 @@ "follow-redirects": ["follow-redirects@1.16.0", "", {}, "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw=="], - "foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="], - "formdata-polyfill": ["formdata-polyfill@4.0.10", "", { "dependencies": { "fetch-blob": "^3.1.2" } }, "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g=="], "fs-extra": ["fs-extra@7.0.1", "", { "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw=="], @@ -556,7 +518,7 @@ "gaxios": ["gaxios@7.1.5", "", { "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", "node-fetch": "^3.3.2" } }, "sha512-5FZy72Rh8LhtjmvDrKkI+lVhrsQrVKVsItxMoDm5mNQE+xR0WVIIs+jzPSJgBvKVsLi24fZhXJIsNI0bihDzFg=="], - "gcp-metadata": ["gcp-metadata@8.1.3", "", { "dependencies": { "gaxios": "7.1.3", "google-logging-utils": "1.1.3", "json-bigint": "^1.0.0" } }, "sha512-ziTrzUhhpL9Zk5k0HHzgP/KIpWDJT0VMBC/ynt/QIBvTW+UUcSivQRl6VlwTf/EilDxtSWklHoRsKy1c4k+59w=="], + "gcp-metadata": ["gcp-metadata@9.0.3", "", { "dependencies": { "gaxios": "^7.1.3", "google-logging-utils": "^2.0.0", "json-bigint": "^1.0.0" } }, "sha512-2YYnIlHaKBGT2IPg3G2M57hia9Galz15zsEOvw9T3oRf0lSn6KN6VcHQLqby7x8ksYKnjXvp3rp2KJyLCN6zfQ=="], "get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="], @@ -564,22 +526,18 @@ "get-stream": ["get-stream@9.0.1", "", { "dependencies": { "@sec-ant/readable-stream": "^0.4.1", "is-stream": "^4.0.1" } }, "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA=="], - "glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="], - "glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], "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=="], - "google-auth-library": ["google-auth-library@10.5.0", "", { "dependencies": { "base64-js": "^1.3.0", "ecdsa-sig-formatter": "^1.0.11", "gaxios": "^7.0.0", "gcp-metadata": "^8.0.0", "google-logging-utils": "^1.0.0", "gtoken": "^8.0.0", "jws": "^4.0.0" } }, "sha512-7ABviyMOlX5hIVD60YOfHw4/CxOfBhyduaYB+wbFWCWoni4N7SLcV46hrVRktuBbZjFC9ONyqamZITN7q3n32w=="], + "google-auth-library": ["google-auth-library@11.0.2", "", { "dependencies": { "base64-js": "^1.3.0", "ecdsa-sig-formatter": "^1.0.11", "gaxios": "^7.1.4", "gcp-metadata": "^9.0.0", "google-logging-utils": "^2.0.0", "jws": "^4.0.0" } }, "sha512-vzpgPutxrghPsnjrjpzLX2bdv8IOL719Rh0oEjGnQu8YCIbnbMuTTQ5zU9LcKvLdOPgCxBwppbvnhgW90Qna5Q=="], - "google-gax": ["google-gax@5.0.7", "", { "dependencies": { "@grpc/grpc-js": "^1.12.6", "@grpc/proto-loader": "^0.8.0", "duplexify": "^4.1.3", "google-auth-library": "10.5.0", "google-logging-utils": "1.1.3", "node-fetch": "^3.3.2", "object-hash": "^3.0.0", "proto3-json-serializer": "3.0.4", "protobufjs": "^7.5.4", "retry-request": "^8.0.2", "rimraf": "^5.0.1" } }, "sha512-EhiqaWWJ+9h7sCcKJTsoo6tMcjokVHhWsbSuWCnZJT4vIBP3y4mAoFLnt9SzgkVZeq24ZsFaArr06nnYYku2yA=="], + "google-gax": ["google-gax@6.3.0", "", { "dependencies": { "@grpc/grpc-js": "^1.12.6", "@grpc/proto-loader": "^0.8.0", "@opentelemetry/api": "^1.9.0", "duplexify": "^4.1.3", "google-auth-library": "^11.0.0", "google-logging-utils": "^2.0.0", "node-fetch": "^3.3.2", "object-hash": "^3.0.0", "proto3-json-serializer": "^4.0.0", "protobufjs": "^7.5.4", "retry-request": "^9.0.0" } }, "sha512-9/kD2yhNJJDAoxZMw+v/d53W6bibgHXr0uU2RRfkC2/r5uH1sBo1nzuaSUq1lKgipZ3O4HvksA7/rRBvkFHFkA=="], - "google-logging-utils": ["google-logging-utils@1.1.3", "", {}, "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA=="], + "google-logging-utils": ["google-logging-utils@2.0.1", "", {}, "sha512-HMhaQghlOTvbcb3c4T5jmmOMtG3JUF1iOQMezaJXL86CDS+Tm2vHd0IeLFRAx3+ewd+bo9E1HFHoy17X5aJa9A=="], "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], - "gtoken": ["gtoken@8.0.0", "", { "dependencies": { "gaxios": "^7.0.0", "jws": "^4.0.0" } }, "sha512-+CqsMbHPiSTdtSO14O51eMNlrp9N79gmeqmXeouJOhfucAedHw9noVe/n5uJk3tbKE6a+6ZCQg3RPhVhHByAIw=="], - "help-me": ["help-me@5.0.0", "", {}, "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg=="], "http-proxy": ["http-proxy@1.18.1", "", { "dependencies": { "eventemitter3": "^4.0.0", "follow-redirects": "^1.0.0", "requires-port": "^1.0.0" } }, "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ=="], @@ -622,8 +580,6 @@ "isows": ["isows@1.0.7", "", { "peerDependencies": { "ws": "*" } }, "sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg=="], - "jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="], - "joycon": ["joycon@3.1.1", "", {}, "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw=="], "js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="], @@ -668,9 +624,7 @@ "long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="], - "lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], - - "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], + "magic-string": ["magic-string@1.3.1", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.6.0" } }, "sha512-rm91zr2Ou+XueDTohjQQjdQEcYM6zVi8KVUCG8Ec3vHwUEKrhSdCNyfuIywkA6hcCAteIn0ZOtAHA6eGpiX+Pg=="], "memoirist": ["memoirist@0.4.0", "", {}, "sha512-zxTgA0mSYELa66DimuNQDvyLq36AwDlTuVRbnQtB+VuTcKWm5Qc4z3WkSpgsFWHNhexqkIooqpv4hdcqrX5Nmg=="], @@ -678,8 +632,6 @@ "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], - "minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="], - "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="], "minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="], @@ -700,7 +652,7 @@ "object-hash": ["object-hash@3.0.0", "", {}, "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw=="], - "obug": ["obug@2.1.1", "", {}, "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ=="], + "obug": ["obug@2.2.1", "", {}, "sha512-XrsrhT5sybtKI6wakr2SPOlGZWWYbUXZ7a0jT8/QOeAPau+1X/bSegNe5YR75oJmEZQbKningirmGOEJCIk61Q=="], "on-exit-leak-free": ["on-exit-leak-free@2.1.2", "", {}, "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA=="], @@ -710,11 +662,11 @@ "outdent": ["outdent@0.5.0", "", {}, "sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q=="], - "ox": ["ox@0.14.29", "", { "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-M5j87Ec4V99MQdRct/g09eWXW60g6zhHTUs1lr4deUtrPDnezBdCJTgKd7pxqTpSZBFveV0ALi9jMMuT1qKyNg=="], + "ox": ["ox@0.14.44", "", { "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-O54qXXHEk4ySamMSyBpI0AeBegS5frxU6+LA6Jb9Sf6kMOxcTNaxYmwZfpOu22DIQsdKfgQxHq8EsAGaoBQScA=="], - "oxfmt": ["oxfmt@0.54.0", "", { "dependencies": { "tinypool": "2.1.0" }, "optionalDependencies": { "@oxfmt/binding-android-arm-eabi": "0.54.0", "@oxfmt/binding-android-arm64": "0.54.0", "@oxfmt/binding-darwin-arm64": "0.54.0", "@oxfmt/binding-darwin-x64": "0.54.0", "@oxfmt/binding-freebsd-x64": "0.54.0", "@oxfmt/binding-linux-arm-gnueabihf": "0.54.0", "@oxfmt/binding-linux-arm-musleabihf": "0.54.0", "@oxfmt/binding-linux-arm64-gnu": "0.54.0", "@oxfmt/binding-linux-arm64-musl": "0.54.0", "@oxfmt/binding-linux-ppc64-gnu": "0.54.0", "@oxfmt/binding-linux-riscv64-gnu": "0.54.0", "@oxfmt/binding-linux-riscv64-musl": "0.54.0", "@oxfmt/binding-linux-s390x-gnu": "0.54.0", "@oxfmt/binding-linux-x64-gnu": "0.54.0", "@oxfmt/binding-linux-x64-musl": "0.54.0", "@oxfmt/binding-openharmony-arm64": "0.54.0", "@oxfmt/binding-win32-arm64-msvc": "0.54.0", "@oxfmt/binding-win32-ia32-msvc": "0.54.0", "@oxfmt/binding-win32-x64-msvc": "0.54.0" }, "peerDependencies": { "svelte": "^5.0.0", "vite-plus": "*" }, "optionalPeers": ["svelte", "vite-plus"], "bin": { "oxfmt": "bin/oxfmt" } }, "sha512-DjnMwn7smSLF+Mc2+pRItnuPftm/dkUFpY/d4+33y9TfKrsHZo8GLhmUg9BrOIUEy94Rlom1Q11N6vuhE+e0oQ=="], + "oxfmt": ["oxfmt@0.67.0", "", { "dependencies": { "tinypool": "2.1.2" }, "optionalDependencies": { "@oxfmt/binding-android-arm-eabi": "0.67.0", "@oxfmt/binding-android-arm64": "0.67.0", "@oxfmt/binding-darwin-arm64": "0.67.0", "@oxfmt/binding-darwin-x64": "0.67.0", "@oxfmt/binding-freebsd-x64": "0.67.0", "@oxfmt/binding-linux-arm-gnueabihf": "0.67.0", "@oxfmt/binding-linux-arm-musleabihf": "0.67.0", "@oxfmt/binding-linux-arm64-gnu": "0.67.0", "@oxfmt/binding-linux-arm64-musl": "0.67.0", "@oxfmt/binding-linux-ppc64-gnu": "0.67.0", "@oxfmt/binding-linux-riscv64-gnu": "0.67.0", "@oxfmt/binding-linux-riscv64-musl": "0.67.0", "@oxfmt/binding-linux-s390x-gnu": "0.67.0", "@oxfmt/binding-linux-x64-gnu": "0.67.0", "@oxfmt/binding-linux-x64-musl": "0.67.0", "@oxfmt/binding-openharmony-arm64": "0.67.0", "@oxfmt/binding-win32-arm64-msvc": "0.67.0", "@oxfmt/binding-win32-ia32-msvc": "0.67.0", "@oxfmt/binding-win32-x64-msvc": "0.67.0" }, "peerDependencies": { "svelte": "^5.0.0", "vite-plus": "*" }, "optionalPeers": ["svelte", "vite-plus"], "bin": { "oxfmt": "bin/oxfmt" } }, "sha512-vV7sSiPsaO0mSxdoUdayipVDFPzW/UQ+hrezEHa20+Tx1dnMdZLSRHMT0PdS67FFbhd74M1n08asW21aLGeCrA=="], - "oxlint": ["oxlint@1.69.0", "", { "optionalDependencies": { "@oxlint/binding-android-arm-eabi": "1.69.0", "@oxlint/binding-android-arm64": "1.69.0", "@oxlint/binding-darwin-arm64": "1.69.0", "@oxlint/binding-darwin-x64": "1.69.0", "@oxlint/binding-freebsd-x64": "1.69.0", "@oxlint/binding-linux-arm-gnueabihf": "1.69.0", "@oxlint/binding-linux-arm-musleabihf": "1.69.0", "@oxlint/binding-linux-arm64-gnu": "1.69.0", "@oxlint/binding-linux-arm64-musl": "1.69.0", "@oxlint/binding-linux-ppc64-gnu": "1.69.0", "@oxlint/binding-linux-riscv64-gnu": "1.69.0", "@oxlint/binding-linux-riscv64-musl": "1.69.0", "@oxlint/binding-linux-s390x-gnu": "1.69.0", "@oxlint/binding-linux-x64-gnu": "1.69.0", "@oxlint/binding-linux-x64-musl": "1.69.0", "@oxlint/binding-openharmony-arm64": "1.69.0", "@oxlint/binding-win32-arm64-msvc": "1.69.0", "@oxlint/binding-win32-ia32-msvc": "1.69.0", "@oxlint/binding-win32-x64-msvc": "1.69.0" }, "peerDependencies": { "oxlint-tsgolint": ">=0.22.1", "vite-plus": "*" }, "optionalPeers": ["oxlint-tsgolint", "vite-plus"], "bin": { "oxlint": "bin/oxlint" } }, "sha512-ypZkK/aDc5NQV8zIR6s2H2Tl3aNW8FmJ1m9+2qsaYuRenl8vgnHNCGwTHviWJdUQzglOlHFchgopdtGhSy17Rw=="], + "oxlint": ["oxlint@1.82.0", "", { "optionalDependencies": { "@oxlint/binding-android-arm-eabi": "1.82.0", "@oxlint/binding-android-arm64": "1.82.0", "@oxlint/binding-darwin-arm64": "1.82.0", "@oxlint/binding-darwin-x64": "1.82.0", "@oxlint/binding-freebsd-x64": "1.82.0", "@oxlint/binding-linux-arm-gnueabihf": "1.82.0", "@oxlint/binding-linux-arm-musleabihf": "1.82.0", "@oxlint/binding-linux-arm64-gnu": "1.82.0", "@oxlint/binding-linux-arm64-musl": "1.82.0", "@oxlint/binding-linux-ppc64-gnu": "1.82.0", "@oxlint/binding-linux-riscv64-gnu": "1.82.0", "@oxlint/binding-linux-riscv64-musl": "1.82.0", "@oxlint/binding-linux-s390x-gnu": "1.82.0", "@oxlint/binding-linux-x64-gnu": "1.82.0", "@oxlint/binding-linux-x64-musl": "1.82.0", "@oxlint/binding-openharmony-arm64": "1.82.0", "@oxlint/binding-win32-arm64-msvc": "1.82.0", "@oxlint/binding-win32-ia32-msvc": "1.82.0", "@oxlint/binding-win32-x64-msvc": "1.82.0" }, "peerDependencies": { "oxlint-tsgolint": ">=7.0.2001", "vite-plus": "*" }, "optionalPeers": ["oxlint-tsgolint", "vite-plus"], "bin": { "oxlint": "bin/oxlint" } }, "sha512-+iFM1BGw1ntYJt3QngbJmjbrGxPaKMUADOXOijpWGnYcBPq8YZnQftSS1C+pVcDYy9YxqDVJKQqQkTazTQMboQ=="], "p-filter": ["p-filter@2.1.0", "", { "dependencies": { "p-map": "^2.0.0" } }, "sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw=="], @@ -726,8 +678,6 @@ "p-try": ["p-try@2.2.0", "", {}, "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="], - "package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="], - "package-manager-detector": ["package-manager-detector@0.2.11", "", { "dependencies": { "quansync": "^0.2.7" } }, "sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ=="], "parse-ms": ["parse-ms@4.0.0", "", {}, "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw=="], @@ -736,15 +686,11 @@ "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], - "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=="], - "path-type": ["path-type@4.0.0", "", {}, "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw=="], - "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], - "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], - "picomatch": ["picomatch@4.0.4", "", {}, "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A=="], + "picomatch": ["picomatch@4.0.7", "", {}, "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA=="], "pify": ["pify@4.0.1", "", {}, "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g=="], @@ -764,9 +710,9 @@ "process-warning": ["process-warning@5.0.0", "", {}, "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA=="], - "prool": ["prool@0.2.4", "", { "dependencies": { "change-case": "5.4.4", "eventemitter3": "^5.0.1", "execa": "^9.1.0", "get-port": "^7.1.0", "http-proxy": "^1.18.1", "tar": "7.2.0" }, "peerDependencies": { "@pimlico/alto": "*", "testcontainers": ">=11.10.0" }, "optionalPeers": ["@pimlico/alto", "testcontainers"] }, "sha512-KAGs6e++7MJNQ/vq8Xrk6akz0lRk6AmhuGzSHkluX3kwVj2XjNDDOYSINZwahRv3xfSD0rXYv3iA/2vXw7z47w=="], + "prool": ["prool@0.2.15", "", { "dependencies": { "change-case": "5.4.4", "eventemitter3": "^5.0.1", "execa": "^9.1.0", "get-port": "^7.1.0", "http-proxy": "^1.18.1", "tar": "7.2.0" }, "peerDependencies": { "@pimlico/alto": "*", "testcontainers": ">=11.10.0" }, "optionalPeers": ["@pimlico/alto", "testcontainers"] }, "sha512-hgGNd8SKmX7Eckpqlu3DsN9SELsbR2XOOoT+BPrvghMevTgE35kn18HgPSLIn1iqAkTYYjoauZw6xefu7DSaZQ=="], - "proto3-json-serializer": ["proto3-json-serializer@3.0.4", "", { "dependencies": { "protobufjs": "^7.4.0" } }, "sha512-E1sbAYg3aEbXrq0n1ojJkRHQJGE1kaE/O6GLA94y8rnJBfgvOPTOd1b9hOceQK1FFZI9qMh1vBERCyO2ifubcw=="], + "proto3-json-serializer": ["proto3-json-serializer@4.0.2", "", { "dependencies": { "protobufjs": "^7.5.4" } }, "sha512-VUQlb/J2WjOG8BKhdLwJUz+MKxSMtBGYh+TaNmRtiYVhlIzXjzeAGIx7gtc3lXlA2iURzfF2+cXaQvC2ofwzpg=="], "protobufjs": ["protobufjs@7.6.4", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.5", "@protobufjs/eventemitter": "^1.1.1", "@protobufjs/fetch": "^1.1.1", "@protobufjs/float": "^1.0.2", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.1", "@types/node": ">=13.7.0", "long": "^5.3.2" } }, "sha512-RJJPTTpvFfHcWLkIa2JFWK4XvtSzS0yEWDmunqHXli1h3JlkbcQZXDZdcWxv+JK3Xsl5/UFDPZ0iGm7DAengYw=="], @@ -790,12 +736,10 @@ "resolve-from": ["resolve-from@5.0.0", "", {}, "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="], - "retry-request": ["retry-request@8.0.3", "", { "dependencies": { "extend": "^3.0.2", "teeny-request": "^10.0.0" } }, "sha512-qqoc4kkGgP9cmQDWELlOpAmfgJOg0Yi7MT82ZjiPWu451ayju4itwomjM4/dBEliify8C1b3tSaeCOldugtwPQ=="], + "retry-request": ["retry-request@9.0.1", "", { "dependencies": { "extend": "^3.0.2", "teeny-request": "^11.0.0" } }, "sha512-4kGHEBl0ME6gR+8QB1sPMyg58jUxLUcCZNeqLDrfqzk0eWQN8XJFmeu7fmZCjlZCRW0S2u64Ik1HkO/0sWgCYQ=="], "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], - "rimraf": ["rimraf@5.0.10", "", { "dependencies": { "glob": "^10.3.7" }, "bin": { "rimraf": "dist/esm/bin.mjs" } }, "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ=="], - "rolldown": ["rolldown@1.0.0-rc.17", "", { "dependencies": { "@oxc-project/types": "=0.127.0", "@rolldown/pluginutils": "1.0.0-rc.17" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-rc.17", "@rolldown/binding-darwin-arm64": "1.0.0-rc.17", "@rolldown/binding-darwin-x64": "1.0.0-rc.17", "@rolldown/binding-freebsd-x64": "1.0.0-rc.17", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.17", "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.17", "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.17", "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.17", "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.17", "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.17", "@rolldown/binding-linux-x64-musl": "1.0.0-rc.17", "@rolldown/binding-openharmony-arm64": "1.0.0-rc.17", "@rolldown/binding-wasm32-wasi": "1.0.0-rc.17", "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.17", "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.17" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-ZrT53oAKrtA4+YtBWPQbtPOxIbVDbxT0orcYERKd63VJTF13zPcgXTvD4843L8pcsI7M6MErt8QtON6lrB9tyA=="], "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], @@ -832,7 +776,7 @@ "stackback": ["stackback@0.0.2", "", {}, "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="], - "std-env": ["std-env@4.1.0", "", {}, "sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ=="], + "std-env": ["std-env@4.2.0", "", {}, "sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw=="], "stream-events": ["stream-events@1.0.5", "", { "dependencies": { "stubs": "^3.0.0" } }, "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg=="], @@ -840,14 +784,10 @@ "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=="], - "string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="], "strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - "strip-ansi-cjs": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - "strip-bom": ["strip-bom@3.0.0", "", {}, "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA=="], "strip-final-newline": ["strip-final-newline@4.0.0", "", {}, "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw=="], @@ -860,21 +800,19 @@ "tar": ["tar@7.5.19", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.1.0", "yallist": "^5.0.0" } }, "sha512-4LeEWl96twnS2Q7Bz4MGqgazLqO+hJN63GZxXoIqh1T3VweYD997gbU1ItNsQafqqXTXd5WFyFdReLtwvRBNiw=="], - "teeny-request": ["teeny-request@10.1.3", "", { "dependencies": { "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.1", "node-fetch": "^3.3.2", "stream-events": "^1.0.5" } }, "sha512-5yDliI1uWkYPo7W+Zvrxg6YmoWuj5iC5EydewqrRTvc68nyMTZhlPPlLg6cptUGfbQAb+N9XDPDPzF6N081lug=="], + "teeny-request": ["teeny-request@11.0.1", "", { "dependencies": { "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.1", "node-fetch": "^3.3.2", "stream-events": "^1.0.5" } }, "sha512-bNr5j2YjSdajgCVsp+8JVjRf1uHIbpNISLeKp/7V1NnVMX3Gh6H/kECNGlm2Q3I68ACODQ0iv6aZ3Rvm8WgLGA=="], "term-size": ["term-size@2.2.1", "", {}, "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg=="], "thread-stream": ["thread-stream@4.2.0", "", { "dependencies": { "real-require": "^1.0.0" } }, "sha512-e2zZ96wSChazBsbENf/Pcm/4swHt2cEKQ92rhUjkL9GCKiTDJIaTBenjE/m9DXi0QBmTMDkFDdOomUy20A1tDQ=="], - "tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="], - - "tinyexec": ["tinyexec@1.1.2", "", {}, "sha512-dAqSqE/RabpBKI8+h26GfLq6Vb3JVXs30XYQjdMjaj/c2tS8IYYMbIzP599KtRj7c57/wYApb3QjgRgXmrCukA=="], + "tinybench": ["tinybench@6.1.4", "", {}, "sha512-9APumHG7r4yOk4X4WlkmE71aZcv1gvin1czO3OQ1U9iJcFA5Ja/ygyb0vPOVHTthFozUYs8CLoLUlM8grb2lTQ=="], - "tinyglobby": ["tinyglobby@0.2.16", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg=="], + "tinyexec": ["tinyexec@1.3.0", "", {}, "sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ=="], - "tinypool": ["tinypool@2.1.0", "", {}, "sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw=="], + "tinyglobby": ["tinyglobby@0.2.17", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g=="], - "tinyrainbow": ["tinyrainbow@3.1.0", "", {}, "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw=="], + "tinypool": ["tinypool@2.1.2", "", {}, "sha512-9YodfrxS9g9IbFr/KOjE5bAeJ0p61n3bW6mqvy0jtoeKd1kTW1Cxm0oulm6KX2lyM9Gl6WIe8nEbY7LWv5ZJww=="], "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], @@ -894,11 +832,11 @@ "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], - "viem": ["viem@2.52.2", "", { "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.29", "ws": "8.20.1" }, "peerDependencies": { "typescript": ">=5.0.4" }, "optionalPeers": ["typescript"] }, "sha512-HSU12p5aD/kAPZfrlbCUqdiP4P/c6hQ9AhfTS51VbLUQIjkWd1d5EjrCx/SCxZ0zhZVRn4Iv5X5WDqXPG8Ubew=="], + "viem": ["viem@2.56.3", "", { "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.44", "ws": "8.21.0" }, "peerDependencies": { "typescript": ">=5.0.4" }, "optionalPeers": ["typescript"] }, "sha512-vUObq3GO7D3lz9gPNEE/xd5jIUnMbeVDWewh252o54pDEDlW4pDe6FEd/qTGL5RyK52cGHMM7kQ3wjxhilEvkQ=="], "vite": ["vite@8.0.10", "", { "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", "postcss": "^8.5.10", "rolldown": "1.0.0-rc.17", "tinyglobby": "^0.2.16" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.1.0", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-rZuUu9j6J5uotLDs+cAA4O5H4K1SfPliUlQwqa6YEwSrWDZzP4rhm00oJR5snMewjxF5V/K3D4kctsUTsIU9Mw=="], - "vitest": ["vitest@4.1.8", "", { "dependencies": { "@vitest/expect": "4.1.8", "@vitest/mocker": "4.1.8", "@vitest/pretty-format": "4.1.8", "@vitest/runner": "4.1.8", "@vitest/snapshot": "4.1.8", "@vitest/spy": "4.1.8", "@vitest/utils": "4.1.8", "es-module-lexer": "^2.0.0", "expect-type": "^1.3.0", "magic-string": "^0.30.21", "obug": "^2.1.1", "pathe": "^2.0.3", "picomatch": "^4.0.3", "std-env": "^4.0.0-rc.1", "tinybench": "^2.9.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.1.0", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", "@vitest/browser-playwright": "4.1.8", "@vitest/browser-preview": "4.1.8", "@vitest/browser-webdriverio": "4.1.8", "@vitest/coverage-istanbul": "4.1.8", "@vitest/coverage-v8": "4.1.8", "@vitest/ui": "4.1.8", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@opentelemetry/api", "@types/node", "@vitest/browser-playwright", "@vitest/browser-preview", "@vitest/browser-webdriverio", "@vitest/coverage-istanbul", "@vitest/coverage-v8", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-flY6ScbCIt9HThs+C5HS7jvGOB560DJtk/Z15IQROTA6zEy49Nh8T/dofWTQL+n3vswqn87sbJNiuqw1SDp5Ig=="], + "vitest": ["vitest@5.0.0", "", { "dependencies": { "@types/chai": "^5.2.2", "@vitest/mocker": "5.0.0", "chai": "^6.2.2", "es-module-lexer": "^2.3.2", "expect-type": "^1.4.0", "magic-string": "^1.2.3", "obug": "^2.1.4", "picomatch": "^4.0.7", "std-env": "^4.2.0", "tinybench": "6.1.4", "tinyexec": "1.3.0", "tinyglobby": "^0.2.17", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^22.0.0 || >=24.0.0", "@vitest/browser-playwright": "5.0.0", "@vitest/browser-preview": "5.0.0", "@vitest/browser-webdriverio": "^5.0.0-beta.5 || >=5.0.0", "@vitest/coverage-istanbul": "5.0.0", "@vitest/coverage-v8": "5.0.0", "@vitest/ui": "5.0.0", "happy-dom": "*", "jsdom": "*", "vite": "^6.4.0 || ^7.0.0 || ^8.0.0" }, "optionalPeers": ["@edge-runtime/vm", "@opentelemetry/api", "@types/node", "@vitest/browser-playwright", "@vitest/browser-preview", "@vitest/browser-webdriverio", "@vitest/coverage-istanbul", "@vitest/coverage-v8", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "./vitest.mjs" } }, "sha512-gpsMNoRhMjMktVxPtstOH4/PJuPyovVaMDr4oDilXaGH1EcqM2OE96SoHT2VIQ6fTGtTjqmHDrEu2X9RQiXf8Q=="], "web-streams-polyfill": ["web-streams-polyfill@3.3.3", "", {}, "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw=="], @@ -908,8 +846,6 @@ "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.21.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw=="], @@ -924,13 +860,9 @@ "yoctocolors": ["yoctocolors@2.1.2", "", {}, "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug=="], - "zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="], - - "@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=="], + "zod": ["zod@4.6.2", "", {}, "sha512-lh5RCAGFa1Cm2hjtNwLQhSs/AsqdWnTQaBER9fEwN/88pSh7KOtJavtBx/0VlkN/uFd61SwYmljLMDAsHlvzBQ=="], - "@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=="], + "@jridgewell/trace-mapping/@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="], "@manypkg/find-root/@types/node": ["@types/node@12.20.55", "", {}, "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ=="], @@ -946,8 +878,6 @@ "@scure/bip39/@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="], - "gcp-metadata/gaxios": ["gaxios@7.1.3", "", { "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", "node-fetch": "^3.3.2", "rimraf": "^5.0.1" } }, "sha512-YGGyuEdVIjqxkxVH1pUTMY/XtmmsApXrCVv5EU25iX6inEPbV+VakJfLealkBtJN69AQmh1eGOdCl9Sm1UP6XQ=="], - "http-proxy/eventemitter3": ["eventemitter3@4.0.7", "", {}, "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="], "micromatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], @@ -962,11 +892,9 @@ "viem/@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="], - "@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], - - "@isaacs/cliui/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], + "vite/picomatch": ["picomatch@4.0.4", "", {}, "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A=="], - "@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], + "vite/tinyglobby": ["tinyglobby@0.2.16", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg=="], "read-yaml-file/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="], } diff --git a/package.json b/package.json index 8ff9d17..f0abe08 100644 --- a/package.json +++ b/package.json @@ -3,11 +3,11 @@ "private": true, "version": "0.0.0", "type": "module", - "packageManager": "bun@1.3.14", + "packageManager": "bun@1.4.2", "workspaces": ["packages/*"], "overrides": { "brace-expansion": "5.0.8", - "elysia": "1.4.29", + "elysia": "1.4.30", "tar": "7.5.19", "ws": "8.21.1" }, @@ -28,11 +28,11 @@ "changeset:publish": "bun run scripts/rewrite-workspace-deps.ts && changeset publish" }, "devDependencies": { - "@changesets/cli": "^2.31.0", - "@types/bun": "^1.3.14", - "oxfmt": "^0.54.0", - "oxlint": "^1.69.0", + "@changesets/cli": "^2.31.1", + "@types/bun": "^1.4.2", + "oxfmt": "^0.67.0", + "oxlint": "^1.82.0", "typescript": "^5.9.3", - "vitest": "^4.1.8" + "vitest": "^5.0.0" } } diff --git a/packages/guardian-coordinator/README.md b/packages/guardian-coordinator/README.md index 5cdc982..8090d5c 100644 --- a/packages/guardian-coordinator/README.md +++ b/packages/guardian-coordinator/README.md @@ -68,6 +68,19 @@ Optional env: whatever its owner and role holders turn out to be, including grants made after it was listed, so keep it to contracts whose configuration is under the same control as the Guardian's own key material. Every bypass is logged at warn level. +- `GUARDIAN_ACCEPTED_RETARGETTERS` optional `chainId=addr,addr;chainId=addr`. Request + contracts whose `owner()` is a listed Retargetter take the §A.1 retargetter path for both + `set_request` and `request_whitelisting`: factory-provenance, owner, and puller / consumer + role verification are skipped (no role-events scan) and the retargetter's live + `operation()` is checked instead — the request contract must be its attached operation + request, with a repayment deadline at least + `GUARDIAN_MIN_RETARGETTER_REPAYMENT_BUFFER_SECONDS` ahead. Unset (the default) keeps + every request contract on the classic path. The path trusts the retargetter's code for + provenance and role configuration, so list only retargetters deployed under the same + control as the accepted factories. +- `GUARDIAN_MIN_RETARGETTER_REPAYMENT_BUFFER_SECONDS` default `6912000` (80 days, the + Retargetter's on-chain `MIN_DEADLINE_BUFFER`); minimum runway the retargetter operation's + repayment deadline must have for the retargetter path to pass. - `GUARDIAN_SIGN_TIMEOUT_MS` default `6000`; budget for one whole validate-and-sign call, including the on-chain reads. Raise it when role-events scans over a wide `GUARDIAN_EVENT_SCAN_MAX_LOOKBACK_BLOCKS` — or `request_whitelisting` batches, which diff --git a/packages/guardian-coordinator/package.json b/packages/guardian-coordinator/package.json index 4c396c8..2906a78 100644 --- a/packages/guardian-coordinator/package.json +++ b/packages/guardian-coordinator/package.json @@ -39,16 +39,16 @@ "dependencies": { "@3flabs/guardian": "workspace:*", "@3flabs/guardian-defaults": "workspace:*", - "@aws-sdk/client-kms": "^3.1075.0", - "@google-cloud/kms": "^5.5.1", + "@aws-sdk/client-kms": "^3.1130.0", + "@google-cloud/kms": "^6.1.0", "@noble/curves": "1.9.1", - "better-result": "^2.9.2", - "viem": "^2.52.2", - "zod": "^4.0.0" + "better-result": "^3.0.1", + "viem": "^2.56.3", + "zod": "^4.6.2" }, "devDependencies": { "typescript": "^5.9.3", - "vitest": "^4.1.8" + "vitest": "^5.0.0" }, "repository": { "type": "git", diff --git a/packages/guardian-coordinator/src/cli.ts b/packages/guardian-coordinator/src/cli.ts index b88a556..068abc1 100644 --- a/packages/guardian-coordinator/src/cli.ts +++ b/packages/guardian-coordinator/src/cli.ts @@ -48,6 +48,7 @@ const DEFAULT_MAX_DEADLINE_SECONDS_AHEAD = 600; const DEFAULT_EVENT_SCAN_BLOCK_RANGE = 10_000n; const DEFAULT_EVENT_SCAN_MAX_LOOKBACK_BLOCKS = 1_000_000n; const DEFAULT_MAX_NONCE_ABOVE_FLOOR = 100n; +const DEFAULT_MIN_RETARGETTER_REPAYMENT_BUFFER_SECONDS = 80 * 24 * 60 * 60; const DEFAULT_REMOTE_SIGNER_TIMEOUT_MS = 6_000; const DEFAULT_SWAP_PRICE_TOLERANCE_BPS = 1; const MULTICALL3_ADDRESS = "0xca11bde05977b3631167028862be2a173976ca11"; @@ -73,6 +74,16 @@ export function buildGuardianFromEnv( "GUARDIAN_TRUSTED_REQUEST_CONTRACTS", ) : undefined, + // Retargetters whose own Requests skip factory / owner / role + // verification in favour of the retargetter's live operation state. + // Unset = every request contract takes the classic path. + acceptedRetargetters: env.GUARDIAN_ACCEPTED_RETARGETTERS?.trim() + ? parseAddressMap(env.GUARDIAN_ACCEPTED_RETARGETTERS, "GUARDIAN_ACCEPTED_RETARGETTERS") + : undefined, + minRetargetterRepaymentBufferSeconds: nonNegativeInt( + env.GUARDIAN_MIN_RETARGETTER_REPAYMENT_BUFFER_SECONDS, + DEFAULT_MIN_RETARGETTER_REPAYMENT_BUFFER_SECONDS, + ), acceptedRequestFactories: parseAddressMap( required(env, "GUARDIAN_REQUEST_FACTORIES"), "GUARDIAN_REQUEST_FACTORIES", diff --git a/packages/guardian-coordinator/tests/coordinator.test.ts b/packages/guardian-coordinator/tests/coordinator.test.ts index 7f3d591..dc107b0 100644 --- a/packages/guardian-coordinator/tests/coordinator.test.ts +++ b/packages/guardian-coordinator/tests/coordinator.test.ts @@ -716,6 +716,40 @@ describe("guardian coordinator", () => { ).toThrow(/GUARDIAN_TRUSTED_REQUEST_CONTRACTS contains invalid address/); }); + it("parses the retargetter policy from env", () => { + const env = { ...CLI_ENV, GUARDIAN_SIGNER_KEY: `0x${"11".repeat(32)}` }; + + // Optional set; a checksum-invalid address is rejected at construction. + expect(() => + buildCliGuardianFromEnv({ + ...env, + GUARDIAN_ACCEPTED_RETARGETTERS: "1=0x52908400098527886E0F7030069857D2E4169Ee7", + }), + ).toThrow(/GUARDIAN_ACCEPTED_RETARGETTERS contains invalid address/); + expect( + buildCliGuardianFromEnv({ + ...env, + GUARDIAN_ACCEPTED_RETARGETTERS: "1=0x95026A338084241E739250f4F9d2F5745dE81bDd", + }).metadata.supportedChains, + ).toEqual([1]); + + // The buffer defaults to the on-chain 80-day floor and rejects + // negative / fractional values (they would fail every retargetter + // request) at construction rather than per request. + expect( + buildCliGuardianFromEnv({ + ...env, + GUARDIAN_MIN_RETARGETTER_REPAYMENT_BUFFER_SECONDS: "0", + }).metadata.supportedChains, + ).toEqual([1]); + expect(() => + buildCliGuardianFromEnv({ ...env, GUARDIAN_MIN_RETARGETTER_REPAYMENT_BUFFER_SECONDS: "-1" }), + ).toThrow(/non-negative integer/); + expect(() => + buildCliGuardianFromEnv({ ...env, GUARDIAN_MIN_RETARGETTER_REPAYMENT_BUFFER_SECONDS: "1.5" }), + ).toThrow(/non-negative integer/); + }); + it("makes the validate-and-sign budget configurable", () => { const env = { ...CLI_ENV, GUARDIAN_SIGNER_KEY: `0x${"11".repeat(32)}` }; diff --git a/packages/guardian-defaults/README.md b/packages/guardian-defaults/README.md index 5e3656e..ccfcfcc 100644 --- a/packages/guardian-defaults/README.md +++ b/packages/guardian-defaults/README.md @@ -547,6 +547,23 @@ limit equal to the configured range never reject a chunk. delegates provenance, ownership, and role configuration to whoever controls the listed contract — including grants made after it was listed — so treat the set as an extension of the Guardian's own trust boundary; every bypass is logged at warn level. +- **Retargetter path** — `acceptedRetargetters` (optional) switches §A.1 to a second + verification path for request contracts whose `owner()` is a listed Retargetter + (`grunt/src/manager/rebalancer/Retargetter.sol`). A Retargetter deploys its own Request + in `startRetargetting` — through its bound factory, with itself as owner, puller and + consumer — so the factory, owner and puller / consumer role checks are emitted as skipped + (no role-events scan) and one further read, the retargetter's `operation()`, backs the + two checks that replace them: the request contract must be the retargetter's currently + attached operation request, and that operation's `repaymentDeadline` must be at least + `minRetargetterRepaymentBufferSeconds` ahead of now (default 80 days, the contract's + `MIN_DEADLINE_BUFFER` — below it the retargetter refuses to start its loan clock, so a + signature could never be consumed; the Request is deployed with 90 days). The deadline + check still applies, and §A.4 whitelist ops inherit the path per request contract. + Nothing is cached on this path: attachment is live operation state that flips at + operation boundaries, and a previously cached classic-path entry whose owner is now a + listed retargetter is bypassed rather than replayed. A listed retargetter that does not + answer `operation()` is an operator misconfiguration and fails `503`, never a cached + client-blamed `422`. Every other request contract takes the classic path unchanged. - **Scan budget** — `eventScanDeadlineMs` (optional) bounds a single scan's wall clock; when exceeded the request fails `503 upstream_unavailable` instead of holding the handler indefinitely. @@ -581,6 +598,8 @@ case-insensitive. type IntentRequestBindingPolicy = { maxDeadlineSecondsAhead: number; trustedRequestContracts?: ReadonlyMap>; // listed ⇒ skip every on-chain check + acceptedRetargetters?: ReadonlyMap>; // owner listed ⇒ retargetter path + minRetargetterRepaymentBufferSeconds?: number; // default 80 days (DEFAULT_MIN_RETARGETTER_REPAYMENT_BUFFER_SECONDS) acceptedRequestFactories: ReadonlyMap>; acceptedOwners: ReadonlyMap>; acceptedPullers: ReadonlyMap>; @@ -633,6 +652,7 @@ to implement adjacent flows the Guardian doesn't sign for): | `fundAbi` | Fund contract — `Ownable.owner()` plus role / order-state views. | | `requestAbi` | Request contract — `Ownable.owner()` plus the `RolesUpdated` event scanned in §A.1. | | `requestFactoryAbi` | Request factory — `isRequest(addr)` for §A.1, `RequestCreated` event for the deployment-block lookup. | +| `retargetterAbi` | Retargetter — `operation()` (attached `request` + `repaymentDeadline`) for the §A.1 retargetter path. | | `positionManagerAbi` | Position manager — `owner / assets / pendingFees / virtualShareOffset` for §A.3. | | `positionManagerFactoryAbi` | Position-manager factory — `isPositionManager(addr)` for §A.3. | | `whitelistBookAbi` | Whitelist book — `validatorNonceFloor` and `isNonceConsumed` for §A.4. | diff --git a/packages/guardian-defaults/package.json b/packages/guardian-defaults/package.json index 62c60f4..4e9e73f 100644 --- a/packages/guardian-defaults/package.json +++ b/packages/guardian-defaults/package.json @@ -46,16 +46,16 @@ }, "dependencies": { "@3flabs/guardian": "workspace:*", - "better-result": "^2.9.2", + "better-result": "^3.0.1", "pino": "^10.3.1", "pino-pretty": "^13.1.3", - "viem": "^2.52.2", - "zod": "^4.0.0" + "viem": "^2.56.3", + "zod": "^4.6.2" }, "devDependencies": { "@3flabs/guardian-test-fixtures": "workspace:*", "typescript": "^5.9.3", - "vitest": "^4.1.8" + "vitest": "^5.0.0" }, "repository": { "type": "git", diff --git a/packages/guardian-defaults/src/abi/index.ts b/packages/guardian-defaults/src/abi/index.ts index 8a4cc8b..c11eeb0 100644 --- a/packages/guardian-defaults/src/abi/index.ts +++ b/packages/guardian-defaults/src/abi/index.ts @@ -6,6 +6,8 @@ export { requestAbi, ROLE_PULLER, ROLE_CONSUMER } from "./request.js"; export { requestFactoryAbi } from "./request-factory.js"; +export { retargetterAbi } from "./retargetter.js"; + export { positionManagerAbi, VIRTUAL_ASSETS } from "./position-manager.js"; export { positionManagerFactoryAbi } from "./position-manager-factory.js"; diff --git a/packages/guardian-defaults/src/abi/retargetter.ts b/packages/guardian-defaults/src/abi/retargetter.ts new file mode 100644 index 0000000..d06a316 --- /dev/null +++ b/packages/guardian-defaults/src/abi/retargetter.ts @@ -0,0 +1,50 @@ +/** + * Minimal viem ABI for `Retargetter` (3F protocol). Only the surface the + * §A.1 retargetter path reads is included. + * + * `operation()` returns the in-flight retargetting operation. The + * Guardian consumes two members: + * + * - `request` — the Request contract the retargetter deployed in + * `startRetargetting` and still holds as its active operation + * (`address(0)` when idle or inside a SYNC flash-loan window). + * - `repaymentDeadline` — that Request's repayment deadline, mirrored + * into the operation at start (`REPAYMENT_DEADLINE_OFFSET`, 90 days). + * On chain the loan clock can only start while at least + * `MIN_DEADLINE_BUFFER` (80 days) remains before it. + * + * Mirrors `grunt/src/manager/rebalancer/Retargetter.sol` (`operation()`) + * and `grunt/src/libs/funds/Order.sol` (the `Order` tuple). + */ +export const retargetterAbi = [ + { + type: "function", + stateMutability: "view", + name: "operation", + inputs: [], + outputs: [ + { name: "positionManager", type: "address" }, + { name: "request", type: "address" }, + { name: "fund", type: "address" }, + { name: "startedAt", type: "uint40" }, + { name: "repaymentDeadline", type: "uint40" }, + { name: "operationMaxYieldBps", type: "uint16" }, + { name: "horizon", type: "uint32" }, + { name: "tickDuration", type: "uint24" }, + { name: "tickThreshold", type: "uint24" }, + { + name: "order", + type: "tuple", + components: [ + { name: "mode", type: "uint8" }, + { name: "owner", type: "address" }, + { name: "receiver", type: "address" }, + { name: "input", type: "uint256" }, + { name: "output", type: "uint256" }, + { name: "salt", type: "bytes32" }, + ], + }, + { name: "orderLive", type: "bool" }, + ], + }, +] as const; diff --git a/packages/guardian-defaults/src/checks/index.ts b/packages/guardian-defaults/src/checks/index.ts index 41d0d3c..644329d 100644 --- a/packages/guardian-defaults/src/checks/index.ts +++ b/packages/guardian-defaults/src/checks/index.ts @@ -15,6 +15,7 @@ export { export { buildIntentRequestBindingChecks, + DEFAULT_MIN_RETARGETTER_REPAYMENT_BUFFER_SECONDS, zA1OnChainData, type A1Deps, type A1OnChainData, diff --git a/packages/guardian-defaults/src/checks/intent-request-binding.ts b/packages/guardian-defaults/src/checks/intent-request-binding.ts index a4bb31f..a9ee0eb 100644 --- a/packages/guardian-defaults/src/checks/intent-request-binding.ts +++ b/packages/guardian-defaults/src/checks/intent-request-binding.ts @@ -13,6 +13,7 @@ import type { StandardSchemaV1 } from "../cache/standard-schema.js"; import type { AsyncCache } from "../cache/types.js"; import { requestAbi, ROLE_CONSUMER, ROLE_PULLER } from "../abi/request.js"; import { morphoFlashLoanRequestFactoryAbi, requestFactoryAbi } from "../abi/request-factory.js"; +import { retargetterAbi } from "../abi/retargetter.js"; import { checkDeadline, checkMembership, @@ -60,6 +61,38 @@ import type { CheckRunner, CheckRunnerError } from "./types.js"; * key material, and prefer the accepted-set checks everywhere else. * Omitted = every request contract is fully validated. * + * - `acceptedRetargetters` — Retargetter contracts + * (`grunt/src/manager/rebalancer/Retargetter.sol`) the operator has + * vetted. A Retargetter deploys its own Request in + * `startRetargetting` — through its bound factory, with itself as + * owner, puller and consumer — so when `owner()` of the request + * contract is on this set §A.1 takes the RETARGETTER PATH instead of + * the classic one: the factory, owner and puller / consumer role + * checks are emitted as `skipped:true` (no role-events scan, no + * `getBlockNumber`, no `getLogs`) and two checks against the + * retargetter's live `operation()` take their place — the request + * contract MUST be the retargetter's currently attached operation + * request, and that operation's `repaymentDeadline` MUST be at least + * `minRetargetterRepaymentBufferSeconds` ahead of now. The deadline + * check still applies. Nothing is cached on this path: attachment is + * live operation state that flips at operation boundaries, and the + * path costs no scan, so there is nothing to amortise. This delegates + * provenance and role configuration to the retargetter's code, so + * keep the set to retargetters whose deployment is under the same + * control as the accepted factories. Omitted = every request contract + * takes the classic path. + * + * - `minRetargetterRepaymentBufferSeconds` — how far ahead of now the + * retargetter operation's `repaymentDeadline` must sit for the + * retargetter path to pass. Default + * {@link DEFAULT_MIN_RETARGETTER_REPAYMENT_BUFFER_SECONDS} (80 days), + * mirroring the contract's `MIN_DEADLINE_BUFFER`: the retargetter + * refuses to start its loan clock with less than that remaining, so a + * signature issued below it could never be consumed on chain. The + * Request is deployed with a 90-day deadline, leaving a 10-day window + * in which bindings can be signed. Only consulted when + * `acceptedRetargetters` is set; must be a non-negative integer. + * * - `acceptedPullers` / `acceptedConsumers` — every address holding * `_ROLE_PULLER` (resp. `_ROLE_CONSUMER`) on the request contract, * derived from a `RolesUpdated` event replay, MUST be on these @@ -99,6 +132,8 @@ import type { CheckRunner, CheckRunnerError } from "./types.js"; export type IntentRequestBindingPolicy = { readonly maxDeadlineSecondsAhead: number; readonly trustedRequestContracts?: ReadonlyMap>; + readonly acceptedRetargetters?: ReadonlyMap>; + readonly minRetargetterRepaymentBufferSeconds?: number; readonly acceptedRequestFactories: ReadonlyMap>; readonly acceptedFlashLoanRequestFactories?: ReadonlyMap>; readonly acceptedFlashLoanRequestExecutors?: ReadonlyMap>; @@ -111,6 +146,13 @@ export type IntentRequestBindingPolicy = { readonly onLookbackExhausted?: "skip" | "fail"; }; +/** + * Default `minRetargetterRepaymentBufferSeconds`: 80 days, the + * Retargetter's on-chain `MIN_DEADLINE_BUFFER` + * (`grunt/src/libs/manager/rebalancer/LibRetargetterConstants.sol`). + */ +export const DEFAULT_MIN_RETARGETTER_REPAYMENT_BUFFER_SECONDS = 80 * 24 * 60 * 60; + /** * Cached representation of the §A.1 on-chain reads. Stored verbatim by * any `AsyncCache` and replayed against the *current* @@ -140,6 +182,9 @@ export type IntentRequestBindingPolicy = { * made by `evaluateA1` against the live policy, so this entry can * safely outlive a policy change. * + * The retargetter path (see `acceptedRetargetters`) never produces an + * entry: its data is live operation state, read fresh on every call. + * * `holders` is a plain `Map` for parity with * `scanRoleHolders`. Cross-process cache adapters (Redis, KV) MUST * serialise it themselves — the cache interface is value-opaque. @@ -235,6 +280,14 @@ export type A1Deps = { * as `skipped:true`, no RPC is issued, and only the deadline check runs. * See {@link IntentRequestBindingPolicy} for what that delegation costs. * + * A request contract whose stage-1 `owner()` is on the policy's optional + * `acceptedRetargetters` set takes the retargetter path instead of + * stage 2: checks 1–4 are emitted as `skipped:true` and one further + * read — the retargetter's `operation()` — backs two checks in their + * place (the contract is the attached operation request; the operation's + * repayment deadline is at least `minRetargetterRepaymentBufferSeconds` + * ahead). The result is never cached. + * * Stage 1 — single multicall (`allowFailure: true`): * - `request.owner()` * - the configured provenance check for each accepted factory @@ -275,6 +328,7 @@ export type A1Deps = { export function buildIntentRequestBindingChecks( deps: A1Deps, ): CheckRunner { + assertRetargetterPolicy("buildIntentRequestBindingChecks", deps.policy); return async ( ctx: SigningContext, body: IntentRequestBindingBody, @@ -340,11 +394,28 @@ export async function runA1( "A.1: cache.get failed; treating as miss", ); } + // A classic-path entry written before its owner was listed as a + // retargetter must not keep the contract on the classic path until + // the TTL runs out: the retargetter path reads live state, so treat + // the entry as a miss and let the fresh fetch branch. + if ( + onChain !== undefined && + onChain.kind !== "noFactory" && + isAcceptedRetargetter(onChain.owner, chainId, policy) + ) { + onChain = undefined; + } } if (onChain === undefined) { const fetched = await fetchA1OnChain(ctx, chainId, requestContract, policy); if (fetched.isErr()) return Result.err(fetched.error); + if (fetched.value.kind === "retargetter") { + // Live operation state — evaluated fresh, never written back. + return rollupA1( + evaluateRetargetter(fetched.value, requestContract, nowUnix, policy, deadlineCheck), + ); + } onChain = fetched.value; if (cache !== undefined) { @@ -362,18 +433,35 @@ export async function runA1( return rollupA1(evaluateA1(onChain, chainId, policy, deadlineCheck)); } +/** + * Live state read on the retargetter path. Deliberately NOT part of + * {@link A1OnChainData}: `attachedRequest` flips at operation boundaries + * (`startRetargetting` sets it, resolution clears it), so it is never + * cached and never replayed. + */ +type RetargetterOnChainData = { + readonly kind: "retargetter"; + /** The request contract's `owner()` — the retargetter itself. */ + readonly retargetter: Address; + /** `operation().request`; `address(0)` when the retargetter is idle. */ + readonly attachedRequest: Address; + /** `operation().repaymentDeadline`, Unix seconds. */ + readonly repaymentDeadline: bigint; +}; + /** * Performs the on-chain reads needed for §A.1. Returns the raw data * (factory match, owner, role-holder map) that `evaluateA1` consumes * — split out so the cache can replay results without re-issuing any - * RPCs. + * RPCs — or, when the stage-1 owner is an accepted retargetter, the + * uncacheable {@link RetargetterOnChainData} for `evaluateRetargetter`. */ async function fetchA1OnChain( ctx: SigningContext, chainId: number, requestContract: Address, policy: IntentRequestBindingPolicy, -): Promise> { +): Promise> { const acceptedFactories = policy.acceptedRequestFactories.get(chainId) ?? new Set(); const acceptedFlashLoanFactories = policy.acceptedFlashLoanRequestFactories?.get(chainId) ?? new Set(); @@ -464,6 +552,21 @@ async function fetchA1OnChain( } const owner = ownerSlot.result; + // ── Retargetter path ───────────────────────────────────────────── + // The owner is a vetted Retargetter: its own code deployed this + // request (through its bound factory, with itself as owner, puller + // and consumer), so provenance and role holders are implied by the + // attachment we verify next. The factory slots above are ignored + // rather than avoided — they share the multicall, and the owner is + // not known before it returns. + if (isAcceptedRetargetter(owner, chainId, policy)) { + ctx.logger.info( + { requestContract, retargetter: owner, chainId }, + "A.1: request contract is owned by an accepted retargetter; taking the retargetter path", + ); + return fetchRetargetterOperation(ctx, owner, requestContract); + } + const factoryHits = new Map(); const failedFactories: Address[] = []; for (const [i, { factory, functionName }] of factoryChecks.entries()) { @@ -720,15 +823,149 @@ function isTrustedRequestContract( chainId: number, policy: IntentRequestBindingPolicy, ): boolean { - const trusted = policy.trustedRequestContracts?.get(chainId); - if (trusted === undefined) return false; - const target = requestContract.toLowerCase(); - for (const candidate of trusted) { + return isOnChainSet(policy.trustedRequestContracts, chainId, requestContract); +} + +/** + * True iff `owner` is on the policy's `acceptedRetargetters` set for + * `chainId` (case-insensitive). An absent set lists nothing, so every + * request contract stays on the classic path unless an operator opts in. + */ +function isAcceptedRetargetter( + owner: Address, + chainId: number, + policy: IntentRequestBindingPolicy, +): boolean { + return isOnChainSet(policy.acceptedRetargetters, chainId, owner); +} + +/** Case-insensitive membership in an optional per-chain address set. */ +function isOnChainSet( + sets: ReadonlyMap> | undefined, + chainId: number, + address: Address, +): boolean { + const set = sets?.get(chainId); + if (set === undefined) return false; + const target = address.toLowerCase(); + for (const candidate of set) { if (candidate.toLowerCase() === target) return true; } return false; } +/** + * Construction-time guard shared by the §A.1 and §A.4 builders: a + * fractional or negative buffer would make the retargetter deadline + * check meaningless on every request, so reject it up front. + */ +export function assertRetargetterPolicy(builder: string, policy: IntentRequestBindingPolicy): void { + const buffer = policy.minRetargetterRepaymentBufferSeconds; + if (buffer !== undefined && (!Number.isInteger(buffer) || buffer < 0)) { + throw new TypeError( + `${builder}: minRetargetterRepaymentBufferSeconds must be a non-negative integer, ` + + `got ${buffer}`, + ); + } +} + +/** + * Reads the accepted retargetter's `operation()`. The retargetter + * address comes from OPERATOR configuration (it is the request's + * `owner()`, matched against `acceptedRetargetters`), so a + * deterministic failure — revert / no return data because the listed + * address is an EOA or not a Retargetter — is a configuration error, + * never a client-blamed 422: it is logged at error level and fails 503 + * like a misconfigured factory. Transport failures keep the 503 path. + */ +async function fetchRetargetterOperation( + ctx: SigningContext, + retargetter: Address, + requestContract: Address, +): Promise> { + try { + const [operation] = await ctx.client.multicall({ + contracts: [ + { address: retargetter, abi: retargetterAbi, functionName: "operation" }, + ] as const, + allowFailure: false, + }); + const [, attachedRequest, , , repaymentDeadline] = operation; + return Result.ok({ + kind: "retargetter", + retargetter, + attachedRequest, + repaymentDeadline: BigInt(repaymentDeadline), + }); + } catch (e) { + ctx.logger.error( + { err: sanitizeErr(e), retargetter, requestContract }, + isDeterministicContractCallFailure(e, ["operation"]) + ? "A.1: accepted retargetter did not answer operation(); check its configuration" + : "A.1: retargetter operation() read failed upstream", + ); + return Result.err( + new UpstreamUnavailableError({ + message: "retargetter operation read failed upstream", + status: 503, + }), + ); + } +} + +const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"; + +/** + * §A.1 entries for the retargetter path. The classic entries it stands + * in for are emitted as `skipped:true` so the §6.4.1 array still says + * which verifications did not happen, followed by the two checks that + * replace them. Pure: same input → same output. + */ +function evaluateRetargetter( + data: RetargetterOnChainData, + requestContract: Address, + nowUnixSeconds: number, + policy: IntentRequestBindingPolicy, + deadlineCheck: CheckEntry, +): readonly CheckEntry[] { + const attachedDescription = "request contract is the retargetter's attached operation request"; + const attachedCheck = + data.attachedRequest.toLowerCase() === requestContract.toLowerCase() + ? passed(attachedDescription) + : failed( + attachedDescription, + data.attachedRequest === ZERO_ADDRESS + ? `retargetter ${data.retargetter} has no active operation` + : `retargetter ${data.retargetter} is attached to ${data.attachedRequest}, not this contract`, + ); + + const buffer = BigInt( + policy.minRetargetterRepaymentBufferSeconds ?? DEFAULT_MIN_RETARGETTER_REPAYMENT_BUFFER_SECONDS, + ); + const floor = BigInt(nowUnixSeconds) + buffer; + const bufferDescription = + "retargetter repayment deadline is at least MIN_RETARGETTER_REPAYMENT_BUFFER ahead of now"; + const bufferCheck = + data.repaymentDeadline >= floor + ? passed(bufferDescription) + : failed( + bufferDescription, + `repayment deadline ${data.repaymentDeadline} is below floor ${floor} ` + + `(now=${nowUnixSeconds}, min-buffer=${buffer})`, + ); + + return [ + passed("owner of request contract is on the accepted-retargetters list"), + skipped("request contract was deployed by an accepted factory"), + skipped("owner of request contract is on the accepted-owners list"), + skipped("puller role on request contract is held only by accepted parties"), + skipped("consumer role on request contract is held only by accepted parties"), + attachedCheck, + bufferCheck, + deadlineCheck, + ]; +} + /** * §A.1 entries for a trusted request contract: the trust entry passes and * every check it stands in for is emitted as `skipped:true`, so the diff --git a/packages/guardian-defaults/src/checks/request-whitelisting.ts b/packages/guardian-defaults/src/checks/request-whitelisting.ts index d622cea..d7ffc44 100644 --- a/packages/guardian-defaults/src/checks/request-whitelisting.ts +++ b/packages/guardian-defaults/src/checks/request-whitelisting.ts @@ -25,6 +25,7 @@ import { import { type A1OnChainData, type IntentRequestBindingPolicy, + assertRetargetterPolicy, runA1, } from "./intent-request-binding.js"; import type { CheckRunner, CheckRunnerError } from "./types.js"; @@ -122,6 +123,7 @@ export function buildRequestWhitelistingChecks(deps: { `got ${policy.maxRequestContracts}`, ); } + assertRetargetterPolicy("buildRequestWhitelistingChecks", policy); return async ( ctx: SigningContext, diff --git a/packages/guardian-defaults/src/index.ts b/packages/guardian-defaults/src/index.ts index 7357fe6..ed9cbb0 100644 --- a/packages/guardian-defaults/src/index.ts +++ b/packages/guardian-defaults/src/index.ts @@ -38,6 +38,7 @@ export { buildRequestWhitelistingChecks, DEADLINE_CHECK_DESCRIPTION, DEFAULT_MAX_REQUEST_CONTRACTS, + DEFAULT_MIN_RETARGETTER_REPAYMENT_BUFFER_SECONDS, checkDeadline, checkMembership, checkNonceWindow, @@ -64,6 +65,7 @@ export { positionManagerFactoryAbi, requestAbi, requestFactoryAbi, + retargetterAbi, whitelistBookAbi, ORDER_STATE, ORDER_STATE_NAME, diff --git a/packages/guardian-defaults/tests/checks-intent-request-binding.test.ts b/packages/guardian-defaults/tests/checks-intent-request-binding.test.ts index 4533f56..61c8520 100644 --- a/packages/guardian-defaults/tests/checks-intent-request-binding.test.ts +++ b/packages/guardian-defaults/tests/checks-intent-request-binding.test.ts @@ -60,6 +60,43 @@ const trustedPolicy: IntentRequestBindingPolicy = { trustedRequestContracts: new Map([[1, new Set([RC])]]), }; +const RETARGETTER = "0x0000000000000000000000000000000000007e7a" as Address; +const OTHER_RC = "0xdddddddddddddddddddddddddddddddddddddddd" as Address; +const ZERO = "0x0000000000000000000000000000000000000000" as Address; +const DAY = 24 * 60 * 60; +/** `ctx()` default clock, in Unix seconds. */ +const NOW = 1_700_000_000; + +/** + * Same accepted sets, plus RETARGETTER on the accepted-retargetters list. + * RC is NOT on any accepted set and the factory stub answers `false`, so + * a pass can only come from the retargetter path. + */ +const retargetterPolicy: IntentRequestBindingPolicy = { + ...policy, + acceptedRetargetters: new Map([[1, new Set([RETARGETTER])]]), +}; + +/** + * `Retargetter.operation()` return tuple, in ABI order. Only `request` + * (index 1) and `repaymentDeadline` (index 4) are read by the runner. + */ +function operation(args: { request: Address; repaymentDeadline: number }): readonly unknown[] { + return [ + ZERO, // positionManager + args.request, + ZERO, // fund + 0n, // startedAt + BigInt(args.repaymentDeadline), + 0, // operationMaxYieldBps + 0, // horizon + 0, // tickDuration + 0, // tickThreshold + { mode: 0, owner: ZERO, receiver: ZERO, input: 0n, output: 0n, salt: `0x${"00".repeat(32)}` }, + false, // orderLive + ]; +} + const baseBody = { chainId: 1, facility: "0x0000000000000000000000000000000000000099" as Address, @@ -1270,6 +1307,336 @@ describe("buildIntentRequestBindingChecks", () => { }); }); +describe("buildIntentRequestBindingChecks — retargetter path", () => { + it("takes the retargetter path when owner() is an accepted retargetter, ignoring the factory answer", async () => { + const stub = makeClient({ + multicallResponses: [ + // Stage 1: owner is the retargetter; the factory does NOT claim RC. + [RETARGETTER, false], + // Retargetter.operation(): RC attached, 90 days of repayment runway. + [operation({ request: RC, repaymentDeadline: NOW + 90 * DAY })], + ], + }); + const run = buildIntentRequestBindingChecks({ policy: retargetterPolicy }); + + const result = await run(ctx(stub.client), baseBody); + + if (result.isErr()) throw result.error; + expect(result.value).toEqual([ + { + description: "owner of request contract is on the accepted-retargetters list", + passed: true, + skipped: false, + }, + { + description: "request contract was deployed by an accepted factory", + passed: true, + skipped: true, + }, + { + description: "owner of request contract is on the accepted-owners list", + passed: true, + skipped: true, + }, + { + description: "puller role on request contract is held only by accepted parties", + passed: true, + skipped: true, + }, + { + description: "consumer role on request contract is held only by accepted parties", + passed: true, + skipped: true, + }, + { + description: "request contract is the retargetter's attached operation request", + passed: true, + skipped: false, + }, + { + description: + "retargetter repayment deadline is at least MIN_RETARGETTER_REPAYMENT_BUFFER ahead of now", + passed: true, + skipped: false, + }, + { + description: "deadline within MAX_DEADLINE_SECONDS_AHEAD of now", + passed: true, + skipped: false, + }, + ]); + // Exactly two reads — stage 1 and operation() — and no scan. + expect(stub.multicalls.map((m) => m.functionNames)).toEqual([ + ["owner", "isRequest"], + ["operation"], + ]); + expect(stub.getBlockNumberCalls).toBe(0); + expect(stub.getLogsCalls).toBe(0); + }); + + it("fails when the retargetter is attached to a different request contract", async () => { + const stub = makeClient({ + multicallResponses: [ + [RETARGETTER, false], + [operation({ request: OTHER_RC, repaymentDeadline: NOW + 90 * DAY })], + ], + }); + const run = buildIntentRequestBindingChecks({ policy: retargetterPolicy }); + + const result = await run(ctx(stub.client), baseBody); + + expect(result.isErr()).toBe(true); + if (!result.isErr()) return; + expect(result.error).toBeInstanceOf(ValidationFailedError); + const attached = (result.error as ValidationFailedError).checks.find((c) => + c.description.includes("attached operation request"), + ); + expect(attached?.passed).toBe(false); + expect(attached?.reason).toContain(OTHER_RC); + // The buffer check is still evaluated (and passes) — one read, all entries. + const buffer = (result.error as ValidationFailedError).checks.find((c) => + c.description.includes("MIN_RETARGETTER_REPAYMENT_BUFFER"), + ); + expect(buffer?.passed).toBe(true); + }); + + it("fails when the retargetter has no active operation (request = address(0))", async () => { + const stub = makeClient({ + multicallResponses: [ + [RETARGETTER, false], + [operation({ request: ZERO, repaymentDeadline: 0 })], + ], + }); + const run = buildIntentRequestBindingChecks({ policy: retargetterPolicy }); + + const result = await run(ctx(stub.client), baseBody); + + expect(result.isErr()).toBe(true); + if (!result.isErr()) return; + const attached = (result.error as ValidationFailedError).checks.find((c) => + c.description.includes("attached operation request"), + ); + expect(attached?.passed).toBe(false); + expect(attached?.reason).toContain("no active operation"); + }); + + it("fails when the repayment deadline is below the default 80-day buffer, and passes at exactly the floor", async () => { + const below = makeClient({ + multicallResponses: [ + [RETARGETTER, false], + [operation({ request: RC, repaymentDeadline: NOW + 80 * DAY - 1 })], + ], + }); + const run = buildIntentRequestBindingChecks({ policy: retargetterPolicy }); + + const rejected = await run(ctx(below.client), baseBody); + expect(rejected.isErr()).toBe(true); + if (rejected.isErr()) { + expect(rejected.error).toBeInstanceOf(ValidationFailedError); + const buffer = (rejected.error as ValidationFailedError).checks.find((c) => + c.description.includes("MIN_RETARGETTER_REPAYMENT_BUFFER"), + ); + expect(buffer?.passed).toBe(false); + expect(buffer?.reason).toContain(`min-buffer=${80 * DAY}`); + } + + const atFloor = makeClient({ + multicallResponses: [ + [RETARGETTER, false], + [operation({ request: RC, repaymentDeadline: NOW + 80 * DAY })], + ], + }); + expect((await run(ctx(atFloor.client), baseBody)).isOk()).toBe(true); + }); + + it("honours a custom minRetargetterRepaymentBufferSeconds (0 = only not yet expired)", async () => { + const run = buildIntentRequestBindingChecks({ + policy: { ...retargetterPolicy, minRetargetterRepaymentBufferSeconds: 0 }, + }); + + const now = makeClient({ + multicallResponses: [ + [RETARGETTER, false], + [operation({ request: RC, repaymentDeadline: NOW })], + ], + }); + expect((await run(ctx(now.client), baseBody)).isOk()).toBe(true); + + const expired = makeClient({ + multicallResponses: [ + [RETARGETTER, false], + [operation({ request: RC, repaymentDeadline: NOW - 1 })], + ], + }); + expect((await run(ctx(expired.client), baseBody)).isErr()).toBe(true); + }); + + it("still enforces the signature deadline on the retargetter path", async () => { + const stub = makeClient({ + multicallResponses: [ + [RETARGETTER, false], + [operation({ request: RC, repaymentDeadline: NOW + 90 * DAY })], + ], + }); + const run = buildIntentRequestBindingChecks({ policy: retargetterPolicy }); + + const result = await run(ctx(stub.client), { ...baseBody, deadline: NOW + 1_000 }); + + expect(result.isErr()).toBe(true); + if (!result.isErr()) return; + const deadline = (result.error as ValidationFailedError).checks.find((c) => + c.description.includes("MAX_DEADLINE_SECONDS_AHEAD"), + ); + expect(deadline?.passed).toBe(false); + }); + + it("keeps the classic path for an owner that is not on the accepted-retargetters set", async () => { + // OWNER is an accepted owner but not a retargetter; the factory + // answer (`false`) now matters and fails check #1 — no operation() read. + const stub = makeClient({ multicallResponses: [[OWNER, false]] }); + const run = buildIntentRequestBindingChecks({ policy: retargetterPolicy }); + + const result = await run(ctx(stub.client), baseBody); + + expect(result.isErr()).toBe(true); + if (!result.isErr()) return; + expect(result.error).toBeInstanceOf(ValidationFailedError); + const factory = (result.error as ValidationFailedError).checks.find((c) => + c.description.includes("deployed by"), + ); + expect(factory?.passed).toBe(false); + expect(stub.multicalls).toHaveLength(1); + }); + + it("scopes the accepted-retargetters set per chain and ignores address case", async () => { + const run = buildIntentRequestBindingChecks({ + policy: { + ...policy, + // Listed for chain 1 only, in the opposite case to the on-chain owner. + acceptedRetargetters: new Map([[1, new Set([RETARGETTER.toUpperCase()])]]), + }, + }); + + // Chain 8453 is not covered, so the classic path runs and fails on + // the factory check without ever reading operation(). + const otherChainStub = makeClient({ multicallResponses: [[RETARGETTER, false]] }); + const other = await run(ctx(otherChainStub.client), { ...baseBody, chainId: 8453 }); + expect(other.isErr()).toBe(true); + expect(otherChainStub.multicalls).toHaveLength(1); + + const stub = makeClient({ + multicallResponses: [ + [RETARGETTER, false], + [operation({ request: RC, repaymentDeadline: NOW + 90 * DAY })], + ], + }); + expect((await run(ctx(stub.client), baseBody)).isOk()).toBe(true); + }); + + it("matches the attached request case-insensitively", async () => { + const stub = makeClient({ + multicallResponses: [ + [RETARGETTER, false], + [operation({ request: RC.toUpperCase() as Address, repaymentDeadline: NOW + 90 * DAY })], + ], + }); + const run = buildIntentRequestBindingChecks({ policy: retargetterPolicy }); + expect((await run(ctx(stub.client), baseBody)).isOk()).toBe(true); + }); + + it("fails 503 — never a 422 — when the listed retargetter does not answer operation() (operator misconfiguration)", async () => { + const zeroData = new ContractFunctionExecutionError(new AbiDecodingZeroDataError(), { + abi: [], + functionName: "operation", + }); + const stub = makeClient({ multicallResponses: [[RETARGETTER, false], zeroData] }); + const cache = inMemoryCache(zA1OnChainData); + const run = buildIntentRequestBindingChecks({ policy: retargetterPolicy, cache }); + + const result = await run(ctx(stub.client), baseBody); + + expect(result.isErr()).toBe(true); + if (!result.isErr()) return; + expect(result.error).toBeInstanceOf(UpstreamUnavailableError); + expect(await cache.get(`1:${RC.toLowerCase()}`)).toBeUndefined(); + }); + + it("propagates an operation() transport failure as UpstreamUnavailableError", async () => { + const stub = makeClient({ + multicallResponses: [[RETARGETTER, false], new HttpRequestError({ url: "http://rpc" })], + }); + const run = buildIntentRequestBindingChecks({ policy: retargetterPolicy }); + + const result = await run(ctx(stub.client), baseBody); + + expect(result.isErr()).toBe(true); + if (result.isErr()) expect(result.error).toBeInstanceOf(UpstreamUnavailableError); + }); + + it("never writes the cache, and re-reads on every call", async () => { + const stub = makeClient({ + multicallResponses: [ + [RETARGETTER, false], + [operation({ request: RC, repaymentDeadline: NOW + 90 * DAY })], + [RETARGETTER, false], + [operation({ request: RC, repaymentDeadline: NOW + 90 * DAY })], + ], + }); + const cache = inMemoryCache(zA1OnChainData); + const run = buildIntentRequestBindingChecks({ policy: retargetterPolicy, cache }); + + expect((await run(ctx(stub.client), baseBody)).isOk()).toBe(true); + // Attachment is live operation state: nothing to amortise, and an + // entry must never outlive the operation that made it true. + expect(await cache.get(`1:${RC.toLowerCase()}`)).toBeUndefined(); + expect((await run(ctx(stub.client), baseBody)).isOk()).toBe(true); + expect(stub.multicalls).toHaveLength(4); + }); + + it("bypasses a cached classic-path entry whose owner is now an accepted retargetter", async () => { + // A `resolved` entry written before the retargetter was listed would + // otherwise keep RC on the classic path (and failing the owner + // check) until the TTL ran out. + const cache = inMemoryCache(zA1OnChainData); + await cache.set(`1:${RC.toLowerCase()}`, { + kind: "resolved", + factory: FACTORY, + owner: RETARGETTER, + holders: new Map([[RETARGETTER, ROLE_PULLER | ROLE_CONSUMER]]), + } satisfies A1OnChainData); + const stub = makeClient({ + multicallResponses: [ + [RETARGETTER, true], + [operation({ request: RC, repaymentDeadline: NOW + 90 * DAY })], + ], + }); + const run = buildIntentRequestBindingChecks({ policy: retargetterPolicy, cache }); + + const result = await run(ctx(stub.client), baseBody); + + if (result.isErr()) throw result.error; + expect(result.value[0]?.description).toBe( + "owner of request contract is on the accepted-retargetters list", + ); + expect(stub.multicalls).toHaveLength(2); + // The stale entry is left to expire — the bypass reads, it does not evict. + expect(await cache.get(`1:${RC.toLowerCase()}`)).toBeDefined(); + }); + + it("throws at construction for a fractional or negative minRetargetterRepaymentBufferSeconds", () => { + expect(() => + buildIntentRequestBindingChecks({ + policy: { ...retargetterPolicy, minRetargetterRepaymentBufferSeconds: 1.5 }, + }), + ).toThrow(TypeError); + expect(() => + buildIntentRequestBindingChecks({ + policy: { ...retargetterPolicy, minRetargetterRepaymentBufferSeconds: -1 }, + }), + ).toThrow(/non-negative integer/); + }); +}); + describe("scanRoleHolders", () => { function recordingClient(args: { onGetLogs?: () => void } = {}): { client: PublicClient; diff --git a/packages/guardian-defaults/tests/checks-request-whitelisting.test.ts b/packages/guardian-defaults/tests/checks-request-whitelisting.test.ts index 8d05ef5..1cf5a3e 100644 --- a/packages/guardian-defaults/tests/checks-request-whitelisting.test.ts +++ b/packages/guardian-defaults/tests/checks-request-whitelisting.test.ts @@ -261,6 +261,79 @@ describe("buildRequestWhitelistingChecks", () => { ]); }); + it("takes the retargetter path per contract in a whitelist batch", async () => { + const RETARGETTER = "0x0000000000000000000000000000000000007e7a" as Address; + const ZERO = "0x0000000000000000000000000000000000000000" as Address; + const NOW = 1_700_000_000; + const stub = makeClient({ + multicallResponses: [ + // RC1 stage-1: owner is the retargetter (the factory answer is ignored). + [RETARGETTER, false], + // RC1: Retargetter.operation() — RC1 attached, 90 days of runway. + [ + [ + ZERO, + RC1, + ZERO, + 0n, + BigInt(NOW + 90 * 24 * 60 * 60), + 0, + 0, + 0, + 0, + { + mode: 0, + owner: ZERO, + receiver: ZERO, + input: 0n, + output: 0n, + salt: `0x${"00".repeat(32)}`, + }, + false, + ], + ], + // RC2 stage-1: classic path. + [OWNER, true], + // whitelist book stage: floor + consumed + [10n, false], + ], + getLogs: (params) => ((params.address ?? []).includes(RC2) ? happyEvents(RC2) : []), + latestBlock: 5_500n, + }); + + const r = await buildRequestWhitelistingChecks({ + policy: { ...policy, acceptedRetargetters: new Map([[1, new Set([RETARGETTER])]]) }, + guardianSigner: GUARDIAN, + })(ctx(stub.client), { + chainId: 1, + whitelistBook: BOOK, + operation: "whitelist", + requestContracts: [RC1, RC2], + nonce: "100", + deadline: 1_700_000_500, + }); + + if (r.isErr()) throw r.error; + expect( + r.value.filter((c) => c.description.endsWith(`(for ${RC1})`)).map((c) => c.description), + ).toEqual([ + `owner of request contract is on the accepted-retargetters list (for ${RC1})`, + `request contract was deployed by an accepted factory (for ${RC1})`, + `owner of request contract is on the accepted-owners list (for ${RC1})`, + `puller role on request contract is held only by accepted parties (for ${RC1})`, + `consumer role on request contract is held only by accepted parties (for ${RC1})`, + `request contract is the retargetter's attached operation request (for ${RC1})`, + `retargetter repayment deadline is at least MIN_RETARGETTER_REPAYMENT_BUFFER ahead of now (for ${RC1})`, + ]); + expect(r.value.filter((c) => c.description.endsWith(`(for ${RC2})`))).toHaveLength(4); + expect(stub.multicalls.map((m) => m.addresses)).toEqual([ + [RC1.toLowerCase(), FACTORY.toLowerCase()], + [RETARGETTER.toLowerCase()], + [RC2.toLowerCase(), FACTORY.toLowerCase()], + [BOOK.toLowerCase(), BOOK.toLowerCase()], + ]); + }); + it("unwhitelist op runs only nonce + deadline checks", async () => { const stub = makeClient({ multicallResponses: [[10n, false]], @@ -609,6 +682,15 @@ describe("buildRequestWhitelistingChecks", () => { expect(stub.multicalls.length).toBe(0); }); + it("throws at construction for a fractional minRetargetterRepaymentBufferSeconds", () => { + expect(() => + buildRequestWhitelistingChecks({ + policy: { ...policy, minRetargetterRepaymentBufferSeconds: 0.5 }, + guardianSigner: GUARDIAN, + }), + ).toThrow(/minRetargetterRepaymentBufferSeconds/); + }); + it("throws at construction for a non-positive or fractional maxRequestContracts", () => { for (const bad of [0, -1, 1.5]) { expect(() => diff --git a/packages/guardian-defaults/tests/integration/intent-request-binding.integration.test.ts b/packages/guardian-defaults/tests/integration/intent-request-binding.integration.test.ts index d8525bd..a5b45ba 100644 --- a/packages/guardian-defaults/tests/integration/intent-request-binding.integration.test.ts +++ b/packages/guardian-defaults/tests/integration/intent-request-binding.integration.test.ts @@ -1,5 +1,5 @@ import { beforeAll, describe, expect, it } from "vitest"; -import { type Address } from "viem"; +import { encodeFunctionData, parseAbi, type Address } from "viem"; import { ValidationFailedError } from "@3flabs/guardian"; import { type AddressBook, createIntegrationFixture } from "@3flabs/guardian-test-fixtures"; @@ -114,3 +114,140 @@ describe("§A.1 intent-request-binding — on-chain", () => { expect(res.error).toBeInstanceOf(ValidationFailedError); }); }); + +describe("§A.1 intent-request-binding — retargetter path, on-chain", () => { + const fixture = createIntegrationFixture(); + beforeAll(fixture.setup); + + function retargetterPolicyFor(book: AddressBook): IntentRequestBindingPolicy { + return { + ...policyFor(book), + acceptedRetargetters: new Map([[31337, new Set([book.mockRetargetter])]]), + }; + } + + it("keeps a retargetter-owned request on the classic path when no retargetter is listed", async () => { + const { book, clients } = fixture.snapshot(); + const ctx = makeSigningContext({ client: clients.publicClient, chainId: book.chainId }); + const run = buildIntentRequestBindingChecks({ policy: policyFor(book) }); + + // The retargetter's Request comes from the accepted factory, but its + // owner / puller / consumer is the retargetter itself, which is on + // none of the classic accepted sets. + const res = await run(ctx, { + chainId: book.chainId, + facility: book.facility, + intent: { id: "1" }, + requestContract: book.retargetterRequest, + deadline: Math.floor(Date.now() / 1000) + 300, + }); + + expect(res.isErr()).toBe(true); + if (!res.isErr()) return; + expect(res.error).toBeInstanceOf(ValidationFailedError); + const owner = (res.error as ValidationFailedError).checks.find((c) => + c.description.includes("accepted-owners"), + ); + expect(owner?.passed).toBe(false); + }); + + it("passes for the retargetter's attached request via its live operation()", async () => { + const { book, clients } = fixture.snapshot(); + const ctx = makeSigningContext({ client: clients.publicClient, chainId: book.chainId }); + const run = buildIntentRequestBindingChecks({ policy: retargetterPolicyFor(book) }); + + const res = await run(ctx, { + chainId: book.chainId, + facility: book.facility, + intent: { id: "1" }, + requestContract: book.retargetterRequest, + deadline: Math.floor(Date.now() / 1000) + 300, + }); + + expect(res.isOk(), res.isErr() ? JSON.stringify(res.error) : "").toBe(true); + if (!res.isOk()) return; + for (const c of res.value) expect(c.passed, c.description).toBe(true); + expect(res.value.map((c) => [c.description, c.skipped])).toEqual([ + ["owner of request contract is on the accepted-retargetters list", false], + ["request contract was deployed by an accepted factory", true], + ["owner of request contract is on the accepted-owners list", true], + ["puller role on request contract is held only by accepted parties", true], + ["consumer role on request contract is held only by accepted parties", true], + ["request contract is the retargetter's attached operation request", false], + [ + "retargetter repayment deadline is at least MIN_RETARGETTER_REPAYMENT_BUFFER ahead of now", + false, + ], + ["deadline within MAX_DEADLINE_SECONDS_AHEAD of now", false], + ]); + }); + + it("fails when the operation's repayment deadline is inside the buffer", async () => { + const { book, clients } = fixture.snapshot(); + const ctx = makeSigningContext({ client: clients.publicClient, chainId: book.chainId }); + // The fixture Request has ~90 days of runway; demand more than that. + const run = buildIntentRequestBindingChecks({ + policy: { + ...retargetterPolicyFor(book), + minRetargetterRepaymentBufferSeconds: 91 * 24 * 3600, + }, + }); + + const res = await run(ctx, { + chainId: book.chainId, + facility: book.facility, + intent: { id: "1" }, + requestContract: book.retargetterRequest, + deadline: Math.floor(Date.now() / 1000) + 300, + }); + + expect(res.isErr()).toBe(true); + if (!res.isErr()) return; + expect(res.error).toBeInstanceOf(ValidationFailedError); + const buffer = (res.error as ValidationFailedError).checks.find((c) => + c.description.includes("MIN_RETARGETTER_REPAYMENT_BUFFER"), + ); + expect(buffer?.passed).toBe(false); + }); + + // Mutates the mock's attachment — keep it last in this block. + it("fails once the retargetter is attached to another request", async () => { + const { book, clients } = fixture.snapshot(); + // `setOperation` is unauthenticated by design (see + // contracts/MockRetargetter.sol); re-attach the retargetter to the + // classic fixture Request so `book.retargetterRequest` is no longer + // its operation request. + const block = await clients.publicClient.getBlock(); + const tx = await clients.walletClient.sendTransaction({ + account: clients.walletClient.account!, + to: book.mockRetargetter, + data: encodeFunctionData({ + abi: parseAbi(["function setOperation(address,uint40)"]), + functionName: "setOperation", + args: [book.request, Number(block.timestamp) + 90 * 24 * 3600], + }), + chain: clients.walletClient.chain, + }); + await clients.publicClient.waitForTransactionReceipt({ hash: tx }); + + const ctx = makeSigningContext({ client: clients.publicClient, chainId: book.chainId }); + const run = buildIntentRequestBindingChecks({ policy: retargetterPolicyFor(book) }); + + const res = await run(ctx, { + chainId: book.chainId, + facility: book.facility, + intent: { id: "1" }, + requestContract: book.retargetterRequest, + deadline: Math.floor(Date.now() / 1000) + 300, + }); + + expect(res.isErr()).toBe(true); + if (!res.isErr()) return; + expect(res.error).toBeInstanceOf(ValidationFailedError); + const attached = (res.error as ValidationFailedError).checks.find((c) => + c.description.includes("attached operation request"), + ); + expect(attached?.passed).toBe(false); + expect(attached?.reason).toContain(book.request); + }); +}); diff --git a/packages/guardian-test-fixtures/README.md b/packages/guardian-test-fixtures/README.md index b4f97a5..a528a98 100644 --- a/packages/guardian-test-fixtures/README.md +++ b/packages/guardian-test-fixtures/README.md @@ -5,7 +5,7 @@ ## What it does - Boots a [prool](https://github.com/wevm/prool)-managed anvil pool, bound to `127.0.0.1` only. Each vitest worker gets its own anvil instance, multiplexed by the worker id (`process.env.VITEST_POOL_ID`) under the path `http://127.0.0.1:/`. `startAnvilPool` accepts optional `port` and `limit` options (`limit` defaults to 64 and caps how many anvil instances the pool will spawn); a fixed-port `EADDRINUSE` surfaces as a catchable promise rejection. -- Deploys the Guardian-relevant slice of the 3F protocol (Facility, IntentDescriptor, TransferGuard, PositionManagerFactory + a real PositionManager, RequestFactory + a real Request, RequestWhitelist via fresh ERC-1967 proxy, an `OwnableMockFund` standing in for §A.2's fund). Mirrors `grunt/test/facility/FacilityBase.t.sol` minus the Morpho borrow market. +- Deploys the Guardian-relevant slice of the 3F protocol (Facility, IntentDescriptor, TransferGuard, PositionManagerFactory + a real PositionManager, RequestFactory + a real Request, RequestWhitelist via fresh ERC-1967 proxy, an `OwnableMockFund` standing in for §A.2's fund, a `MockRetargetter` owning a second real Request for the §A.1 retargetter path). Mirrors `grunt/test/facility/FacilityBase.t.sol` minus the Morpho borrow market. - Hands tests a typed `AddressBook` plus pre-built viem `publicClient` / `walletClient` / `testClient`. ## Foundry artifacts @@ -27,12 +27,14 @@ bun run fixtures:check `fixtures:check` always validates the bundled artifacts' integrity (file exists, parses, carries abi/bytecode/deployedBytecode/sourceCommitHash, and `INDEX.json` matches the stamps byte-for-byte) and only performs the sibling-drift comparison for repos whose forge output is actually present — it prints a `[fixtures] NOTICE: skipped sibling-drift verification` line for each absent repo and exits 0 on a fresh clone or CI runner without sibling checkouts. -`OwnableMockFund` and the vendored `Multicall3` are the only contracts whose source lives in this repo (`contracts/`); `fixtures:extract` always runs `forge build` on that directory (foundry's incremental build is near-instant when nothing changed), so editing a local `.sol` cannot silently re-stamp stale bytecode — `forge` must be on `PATH`. For these `local` artifacts the recorded `sourceCommitHash` is the monorepo's own HEAD and is provenance metadata only: `fixtures:check` compares their abi/bytecode/deployedBytecode but does not gate on the hash. +`OwnableMockFund`, `MockRetargetter` and the vendored `Multicall3` are the only contracts whose source lives in this repo (`contracts/`); `fixtures:extract` always runs `forge build` on that directory (foundry's incremental build is near-instant when nothing changed), so editing a local `.sol` cannot silently re-stamp stale bytecode — `forge` must be on `PATH`. For these `local` artifacts the recorded `sourceCommitHash` is the monorepo's own HEAD and is provenance metadata only: `fixtures:check` compares their abi/bytecode/deployedBytecode but does not gate on the hash. ## Why MockFund isn't reused The grunt `MockFund` (`test/mock/facility/MockFund.sol`) doesn't expose `Ownable.owner()`, which the §A.2 `intent-fund-binding` check reads. Spinning up a real `ParetoFund` would require a `WrappedAsset` proxy + `MockIdleCDOEpochVariant` + `MockIdleCreditVault` — too much yak-shaving for a domain-binding test. `OwnableMockFund` is the smallest contract that covers the surface the Guardian reads. +Likewise a real `Retargetter` needs a position manager, quoter and flash-loan module behind it; `MockRetargetter` exposes only `operation()` — with the production return tuple, so the bundled `retargetterAbi` decodes it exactly as it would the real contract — and an unauthenticated `setOperation` for attaching / detaching a Request. + ## Licensing `grunt` is BUSL-1.1; `3f-request-whitelist` is MIT. The bytecode bundled in `artifacts/` is derived from those repos. This package is `private: true` and never published, so no redistribution occurs through npm. If you remove the `private` flag in the future, audit the artifacts' source licenses first. diff --git a/packages/guardian-test-fixtures/artifacts/INDEX.json b/packages/guardian-test-fixtures/artifacts/INDEX.json index d712e7d..b29edbc 100644 --- a/packages/guardian-test-fixtures/artifacts/INDEX.json +++ b/packages/guardian-test-fixtures/artifacts/INDEX.json @@ -53,6 +53,12 @@ "sourcePath": "OwnableMockFund.sol", "sourceCommitHash": "95904f2cc82e6b8946d9706108eafc66192c172e" }, + { + "name": "MockRetargetter", + "sourceRepo": "local", + "sourcePath": "MockRetargetter.sol", + "sourceCommitHash": "96856e5b206cb7186cc81a91571765fad5d90fad" + }, { "name": "Multicall3", "sourceRepo": "local", diff --git a/packages/guardian-test-fixtures/artifacts/MockRetargetter.json b/packages/guardian-test-fixtures/artifacts/MockRetargetter.json new file mode 100644 index 0000000..e69586b --- /dev/null +++ b/packages/guardian-test-fixtures/artifacts/MockRetargetter.json @@ -0,0 +1,149 @@ +{ + "name": "MockRetargetter", + "abi": [ + { + "type": "function", + "name": "attachedRepaymentDeadline", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint40", + "internalType": "uint40" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "attachedRequest", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "operation", + "inputs": [], + "outputs": [ + { + "name": "positionManager", + "type": "address", + "internalType": "address" + }, + { + "name": "request", + "type": "address", + "internalType": "address" + }, + { + "name": "fund", + "type": "address", + "internalType": "address" + }, + { + "name": "startedAt", + "type": "uint40", + "internalType": "uint40" + }, + { + "name": "repaymentDeadline", + "type": "uint40", + "internalType": "uint40" + }, + { + "name": "operationMaxYieldBps", + "type": "uint16", + "internalType": "uint16" + }, + { + "name": "horizon", + "type": "uint32", + "internalType": "uint32" + }, + { + "name": "tickDuration", + "type": "uint24", + "internalType": "uint24" + }, + { + "name": "tickThreshold", + "type": "uint24", + "internalType": "uint24" + }, + { + "name": "order", + "type": "tuple", + "internalType": "struct MockRetargetter.Order", + "components": [ + { + "name": "mode", + "type": "uint8", + "internalType": "uint8" + }, + { + "name": "owner", + "type": "address", + "internalType": "address" + }, + { + "name": "receiver", + "type": "address", + "internalType": "address" + }, + { + "name": "input", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "output", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "salt", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "name": "orderLive", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "setOperation", + "inputs": [ + { + "name": "request", + "type": "address", + "internalType": "address" + }, + { + "name": "repaymentDeadline", + "type": "uint40", + "internalType": "uint40" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + } + ], + "bytecode": "0x6080604052348015600e575f5ffd5b506102c98061001c5f395ff3fe608060405234801561000f575f5ffd5b506004361061004a575f3560e01c806354163ee01461004e578063775fc12714610080578063ab53fdc314610150578063e97289c614610192575b5f5ffd5b5f5461006590600160a01b900464ffffffffff1681565b60405164ffffffffff90911681526020015b60405180910390f35b6100886101bc565b604080516001600160a01b039c8d1681529a8c166020808d0191909152998c168b82015264ffffffffff9889166060808d0191909152989097166080808c019190915261ffff90961660a0808c019190915263ffffffff90951660c08b015262ffffff93841660e08b015292909116610100890152805160ff166101208901529586015188166101408801529285015190961661016086015291830151610180850152908201516101a08401529201516101c08201529015156101e082015261020001610077565b61019061015e366004610248565b5f805464ffffffffff909216600160a01b026001600160c81b03199092166001600160a01b0390931692909217179055565b005b5f546101a4906001600160a01b031681565b6040516001600160a01b039091168152602001610077565b5f5f5f5f5f5f5f5f5f61020d6040518060c001604052805f60ff1681526020015f6001600160a01b031681526020015f6001600160a01b031681526020015f81526020015f81526020015f81525090565b5f8054909b6001600160a01b0382169b508c9a508a9950600160a01b90910464ffffffffff1697508896508695508594508493509091508290565b5f5f60408385031215610259575f5ffd5b82356001600160a01b038116811461026f575f5ffd5b9150602083013564ffffffffff81168114610288575f5ffd5b80915050925092905056fea264697066735822122020f932f5097c9b4aa5519b60f7ab933e9301335f3d88cd41893905eacf51eb7864736f6c634300081b0033", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b506004361061004a575f3560e01c806354163ee01461004e578063775fc12714610080578063ab53fdc314610150578063e97289c614610192575b5f5ffd5b5f5461006590600160a01b900464ffffffffff1681565b60405164ffffffffff90911681526020015b60405180910390f35b6100886101bc565b604080516001600160a01b039c8d1681529a8c166020808d0191909152998c168b82015264ffffffffff9889166060808d0191909152989097166080808c019190915261ffff90961660a0808c019190915263ffffffff90951660c08b015262ffffff93841660e08b015292909116610100890152805160ff166101208901529586015188166101408801529285015190961661016086015291830151610180850152908201516101a08401529201516101c08201529015156101e082015261020001610077565b61019061015e366004610248565b5f805464ffffffffff909216600160a01b026001600160c81b03199092166001600160a01b0390931692909217179055565b005b5f546101a4906001600160a01b031681565b6040516001600160a01b039091168152602001610077565b5f5f5f5f5f5f5f5f5f61020d6040518060c001604052805f60ff1681526020015f6001600160a01b031681526020015f6001600160a01b031681526020015f81526020015f81526020015f81525090565b5f8054909b6001600160a01b0382169b508c9a508a9950600160a01b90910464ffffffffff1697508896508695508594508493509091508290565b5f5f60408385031215610259575f5ffd5b82356001600160a01b038116811461026f575f5ffd5b9150602083013564ffffffffff81168114610288575f5ffd5b80915050925092905056fea264697066735822122020f932f5097c9b4aa5519b60f7ab933e9301335f3d88cd41893905eacf51eb7864736f6c634300081b0033", + "sourceRepo": "local", + "sourcePath": "MockRetargetter.sol", + "sourceCommitHash": "96856e5b206cb7186cc81a91571765fad5d90fad" +} diff --git a/packages/guardian-test-fixtures/contracts/MockRetargetter.sol b/packages/guardian-test-fixtures/contracts/MockRetargetter.sol new file mode 100644 index 0000000..58629c6 --- /dev/null +++ b/packages/guardian-test-fixtures/contracts/MockRetargetter.sol @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +/// @title MockRetargetter +/// @notice Bare-minimum stand-in for a 3F Retargetter +/// (`grunt/src/manager/rebalancer/Retargetter.sol`) used by the +/// Guardian §A.1 retargetter-path integration tests. +/// +/// Exposes exactly the surface the Guardian's `retargetterAbi` +/// reads — `operation()`, with the production return tuple — and +/// populates only the two members the Guardian consumes +/// (`request`, `repaymentDeadline`). The real contract deploys its +/// Request in `startRetargetting` and mirrors the deadline into +/// the operation; here `setOperation` is unauthenticated on +/// purpose so tests can attach / detach a Request directly. +contract MockRetargetter { + struct Order { + uint8 mode; + address owner; + address receiver; + uint256 input; + uint256 output; + bytes32 salt; + } + + address public attachedRequest; + uint40 public attachedRepaymentDeadline; + + function operation() + external + view + returns ( + address positionManager, + address request, + address fund, + uint40 startedAt, + uint40 repaymentDeadline, + uint16 operationMaxYieldBps, + uint32 horizon, + uint24 tickDuration, + uint24 tickThreshold, + Order memory order, + bool orderLive + ) + { + return ( + address(0), + attachedRequest, + address(0), + 0, + attachedRepaymentDeadline, + 0, + 0, + 0, + 0, + order, + false + ); + } + + // ── test setter (unauthenticated by design) ───────────────────────── + + function setOperation(address request, uint40 repaymentDeadline) external { + attachedRequest = request; + attachedRepaymentDeadline = repaymentDeadline; + } +} diff --git a/packages/guardian-test-fixtures/package.json b/packages/guardian-test-fixtures/package.json index 8bc07b8..42d3d1a 100644 --- a/packages/guardian-test-fixtures/package.json +++ b/packages/guardian-test-fixtures/package.json @@ -15,12 +15,12 @@ "typecheck": "tsc --noEmit" }, "dependencies": { - "prool": "^0.2.4", - "viem": "^2.52.2" + "prool": "^0.2.15", + "viem": "^2.56.3" }, "devDependencies": { "typescript": "^5.9.3", - "vitest": "^4.1.8" + "vitest": "^5.0.0" }, "license": "MIT" } diff --git a/packages/guardian-test-fixtures/src/artifacts.ts b/packages/guardian-test-fixtures/src/artifacts.ts index 6a26766..f514a4e 100644 --- a/packages/guardian-test-fixtures/src/artifacts.ts +++ b/packages/guardian-test-fixtures/src/artifacts.ts @@ -15,6 +15,7 @@ import erc1967Factory from "../artifacts/ERC1967Factory.json" with { type: "json import facility from "../artifacts/Facility.json" with { type: "json" }; import intentDescriptor from "../artifacts/IntentDescriptor.json" with { type: "json" }; import mockErc20 from "../artifacts/MockERC20.json" with { type: "json" }; +import mockRetargetter from "../artifacts/MockRetargetter.json" with { type: "json" }; import multicall3 from "../artifacts/Multicall3.json" with { type: "json" }; import ownableMockFund from "../artifacts/OwnableMockFund.json" with { type: "json" }; import positionManagerFactory from "../artifacts/PositionManagerFactory.json" with { type: "json" }; @@ -44,6 +45,7 @@ export const artifacts = { RequestWhitelist: cast(requestWhitelist), ERC1967Factory: cast(erc1967Factory), OwnableMockFund: cast(ownableMockFund), + MockRetargetter: cast(mockRetargetter), Multicall3: cast(multicall3), } as const; diff --git a/packages/guardian-test-fixtures/src/deploy.ts b/packages/guardian-test-fixtures/src/deploy.ts index 357dc94..3140c16 100644 --- a/packages/guardian-test-fixtures/src/deploy.ts +++ b/packages/guardian-test-fixtures/src/deploy.ts @@ -53,6 +53,15 @@ export type AddressBook = { readonly whitelistBookImpl: Address; readonly erc1967Factory: Address; readonly mockFund: Address; + /** `MockRetargetter` — owner, puller and consumer of `retargetterRequest`. */ + readonly mockRetargetter: Address; + /** + * A real Request minted by `requestFactory` with `mockRetargetter` as + * owner / puller / consumer and a 90-day repayment deadline, attached + * to `mockRetargetter.operation()` — the shape `startRetargetting` + * produces on chain. + */ + readonly retargetterRequest: Address; readonly tokens: { readonly collateral: Address; readonly debt: Address; @@ -316,6 +325,50 @@ export async function deployGuardianStack( "address,address,address", ); + /* 8b. MockRetargetter + its own Request --------------------------- */ + const mockRetargetter = await deployArtifact(client, "MockRetargetter", [], ""); + const retargetterBlock = await client.publicClient.getBlock(); + const retargetterDeadline = BigInt(retargetterBlock.timestamp) + 90n * 24n * 3600n; + const retargetterReqHash = await client.walletClient.sendTransaction({ + account: owner.account, + chain: client.walletClient.chain, + to: requestFactory, + data: encodeFunctionData({ + abi: artifacts.RequestFactory.abi, + functionName: "createRequest", + args: [ + mockRetargetter, + mockRetargetter, + mockRetargetter, + debt, + "Retargetter Test", + "RTR", + retargetterDeadline, + 0, + ], + }), + }); + const retargetterReqReceipt = await client.publicClient.waitForTransactionReceipt({ + hash: retargetterReqHash, + }); + const retargetterReqCreated = parseEventLogs({ + abi: artifacts.RequestFactory.abi, + logs: retargetterReqReceipt.logs, + eventName: "RequestCreated", + }); + if (retargetterReqCreated.length === 0) throw new Error("RequestCreated event missing"); + const retargetterRequest = (retargetterReqCreated[0] as unknown as { args: { request: Address } }) + .args.request; + await sendOwnerTx( + client, + mockRetargetter, + encodeFunctionData({ + abi: artifacts.MockRetargetter.abi, + functionName: "setOperation", + args: [retargetterRequest, retargetterDeadline], + }), + ); + /* 9. Create an Intent on the Facility ----------------------------- */ // Several §A checks (notably §A.2 fund-binding) read // `facility.getIntent(id)` and revert if no intent exists. We @@ -352,6 +405,8 @@ export async function deployGuardianStack( whitelistBookImpl, erc1967Factory, mockFund, + mockRetargetter, + retargetterRequest, tokens: { collateral, debt }, accounts: { deployer: testAccounts.deployer, diff --git a/packages/guardian/package.json b/packages/guardian/package.json index a531a98..d3159e7 100644 --- a/packages/guardian/package.json +++ b/packages/guardian/package.json @@ -30,17 +30,17 @@ "test:integration": "vitest run --config vitest.integration.config.ts" }, "dependencies": { - "@elysiajs/openapi": "^1.4.15", - "@noble/hashes": "^2.2.0", - "better-result": "^2.9.2", - "elysia": "^1.4.28", - "viem": "^2.52.2", - "zod": "^4.0.0" + "@elysiajs/openapi": "^1.4.16", + "@noble/hashes": "^2.4.0", + "better-result": "^3.0.1", + "elysia": "^1.4.30", + "viem": "^2.56.3", + "zod": "^4.6.2" }, "devDependencies": { "@3flabs/guardian-test-fixtures": "workspace:*", "typescript": "^5.9.3", - "vitest": "^4.1.8" + "vitest": "^5.0.0" }, "repository": { "type": "git", diff --git a/packages/guardian/src/errors/tagged.ts b/packages/guardian/src/errors/tagged.ts index 807c55e..4b99185 100644 --- a/packages/guardian/src/errors/tagged.ts +++ b/packages/guardian/src/errors/tagged.ts @@ -38,23 +38,23 @@ export function isGuardianErrorTag(value: unknown): value is GuardianError { */ export class UnauthenticatedError extends TaggedError("Unauthenticated")<{ message: string; -}>() {} +}> {} /** Token lacks scope. Maps to 403 forbidden. */ export class ForbiddenError extends TaggedError("Forbidden")<{ message: string; -}>() {} +}> {} /** Malformed body or headers, or sentinel values rejected up-front. */ export class BadRequestError extends TaggedError("BadRequest")<{ message: string; details?: Record; -}>() {} +}> {} /** §6.1 — Content-Type other than application/json on a body-bearing request. */ export class UnsupportedMediaTypeError extends TaggedError("UnsupportedMediaType")<{ message: string; -}>() {} +}> {} /** * Request body exceeds the shell's `maxBodyBytes` cap. Maps to 413; the @@ -63,19 +63,19 @@ export class UnsupportedMediaTypeError extends TaggedError("UnsupportedMediaType */ export class PayloadTooLargeError extends TaggedError("PayloadTooLarge")<{ message: string; -}>() {} +}> {} /** chainId not in supportedChains. Maps to 400 unsupported_chain. */ export class UnsupportedChainError extends TaggedError("UnsupportedChain")<{ message: string; chainId: number; -}>() {} +}> {} /** Unknown route or unresolvable on-chain reference. Maps to 404. */ export class NotFoundError extends TaggedError("NotFound")<{ message: string; details?: Record; -}>() {} +}> {} /** * On-chain state incompatible in a transient way. Maps to 409. @@ -85,24 +85,24 @@ export class NotFoundError extends TaggedError("NotFound")<{ export class StateConflictError extends TaggedError("StateConflict")<{ message: string; checks: CheckEntry[]; -}>() {} +}> {} /** Policy check failed. Maps to 422 validation_failed. */ export class ValidationFailedError extends TaggedError("ValidationFailed")<{ message: string; checks: CheckEntry[]; -}>() {} +}> {} /** Maps to 429 rate_limited. */ export class RateLimitedError extends TaggedError("RateLimited")<{ message: string; retryAfterSeconds: number; -}>() {} +}> {} /** Unexpected Guardian-side failure. Maps to 500. */ export class InternalError extends TaggedError("InternalError")<{ message: string; -}>() {} +}> {} /** * RPC or other dependency unavailable. Maps to 502 / 503. When @@ -113,7 +113,7 @@ export class UpstreamUnavailableError extends TaggedError("UpstreamUnavailable") message: string; status: 502 | 503; retryAfterSeconds?: number; -}>() {} +}> {} /** * Discriminated union of every error a route can produce. diff --git a/scripts/extract-contract-fixtures.ts b/scripts/extract-contract-fixtures.ts index 92eeaff..b85453b 100644 --- a/scripts/extract-contract-fixtures.ts +++ b/scripts/extract-contract-fixtures.ts @@ -115,6 +115,13 @@ const SOURCES: readonly Source[] = [ sourcePath: "OwnableMockFund.sol", repo: "local", }, + // Local — Retargetter stand-in exposing only `operation()` + { + name: "MockRetargetter", + artifactPath: "out/MockRetargetter.sol/MockRetargetter.json", + sourcePath: "MockRetargetter.sol", + repo: "local", + }, // Local — Multicall3 vendored from mds1/multicall3 (MIT). Anvil doesn't // deploy multicall3 by default; we need it for `client.multicall(...)`. {