From 8b4f875c1ca469835fef6cac465d7bc473ad6892 Mon Sep 17 00:00:00 2001 From: donghyeon-ka Date: Sun, 26 Jul 2026 17:37:51 +0900 Subject: [PATCH] feat: verify frontend supply chain --- config/ci/gates.json | 35 +- .../dependency-baseline.approval.json | 7 + config/security/dependency-baseline.json | 6669 +++++++++++++++++ .../security/dependency-change-evidence.json | 4 + config/security/dependency-policy.json | 24 + config/security/secret-scan-policy.json | 30 + config/security/vulnerability-exceptions.json | 4 + config/security/vulnerability-policy.json | 8 + .../decisions/VD-09-supply-chain-evidence.md | 103 + .../frontend-platform-capability-review.md | 13 +- ...rontend-platform-implementation-roadmap.md | 25 + docs/security/supply-chain.md | 55 +- package.json | 8 + .../dependency-inventory.schema.json | 60 + .../supply-chain-verification.schema.json | 55 + scripts/check-frozen-lockfile-fixture.mjs | 39 + scripts/check-supply-chain-fixtures.mjs | 148 + .../check-supply-chain-provider-fixtures.mjs | 105 + scripts/generate-build-manifest.mjs | 8 +- scripts/generate-supply-chain.mjs | 461 +- scripts/lib/supply-chain.mjs | 547 ++ scripts/security-scan.mjs | 193 +- scripts/test-sample-removal.mjs | 1 + scripts/update-dependency-baseline.mjs | 47 + scripts/verify-reproducible-build.mjs | 76 + scripts/verify-supply-chain-artifacts.mjs | 121 + scripts/verify-supply-chain-promotion.mjs | 30 + tests/e2e/app-shell.spec.js | 35 - tests/e2e/reference-route.spec.js | 36 + .../allowed/test-credentials.ts | 1 + .../secret-detection/forbidden-policy.json | 9 + .../secret-detection/forbidden/config.json | 3 + .../secret-detection/forbidden/dist.js | 1 + .../secret-detection/forbidden/source.ts | 1 + tests/unit/supply-chain.test.ts | 89 + 35 files changed, 8910 insertions(+), 141 deletions(-) create mode 100644 config/security/dependency-baseline.approval.json create mode 100644 config/security/dependency-baseline.json create mode 100644 config/security/dependency-change-evidence.json create mode 100644 config/security/dependency-policy.json create mode 100644 config/security/secret-scan-policy.json create mode 100644 config/security/vulnerability-exceptions.json create mode 100644 config/security/vulnerability-policy.json create mode 100644 docs/architecture/decisions/VD-09-supply-chain-evidence.md create mode 100644 schemas/artifacts/dependency-inventory.schema.json create mode 100644 schemas/artifacts/supply-chain-verification.schema.json create mode 100644 scripts/check-frozen-lockfile-fixture.mjs create mode 100644 scripts/check-supply-chain-fixtures.mjs create mode 100644 scripts/check-supply-chain-provider-fixtures.mjs create mode 100644 scripts/lib/supply-chain.mjs create mode 100644 scripts/update-dependency-baseline.mjs create mode 100644 scripts/verify-reproducible-build.mjs create mode 100644 scripts/verify-supply-chain-artifacts.mjs create mode 100644 scripts/verify-supply-chain-promotion.mjs create mode 100644 tests/e2e/reference-route.spec.js create mode 100644 tests/fixtures/security/secret-detection/allowed/test-credentials.ts create mode 100644 tests/fixtures/security/secret-detection/forbidden-policy.json create mode 100644 tests/fixtures/security/secret-detection/forbidden/config.json create mode 100644 tests/fixtures/security/secret-detection/forbidden/dist.js create mode 100644 tests/fixtures/security/secret-detection/forbidden/source.ts create mode 100644 tests/unit/supply-chain.test.ts diff --git a/config/ci/gates.json b/config/ci/gates.json index 4664a75..1970fa9 100644 --- a/config/ci/gates.json +++ b/config/ci/gates.json @@ -58,7 +58,10 @@ "gates": { "FE-GATE-001": { "name": "manifest-lockfile", - "steps": [{ "script": "verify:lockfile", "expect": "pass" }], + "steps": [ + { "script": "verify:lockfile", "expect": "pass" }, + { "script": "check:frozen-lockfile:fixture", "expect": "pass" } + ], "logPath": "artifacts/quality/install.txt", "evidence": ["artifacts/quality/install.txt"], "retentionClass": "merge-cycle" @@ -239,14 +242,32 @@ "FE-GATE-013": { "name": "security", "steps": [ + { "script": "verify:reproducible-build", "expect": "pass" }, { "script": "build:release", "expect": "pass" }, + { "script": "verify:supply-chain", "expect": "pass" }, + { "script": "check:supply-chain:fixtures", "expect": "pass" }, + { + "script": "check:supply-chain:provider-fixtures", + "expect": "pass" + }, + { "script": "scan:security:fixture", "expect": "fail" }, { "script": "check:browser-security", "expect": "pass" } ], "logPath": "artifacts/quality/gates/FE-GATE-013.txt", "evidence": [ "artifacts/security/scan.sarif", + "artifacts/security/scan-fixture.sarif", "artifacts/release/dependency-inventory.json", - "artifacts/security/dependency-diff.json" + "artifacts/release/sbom.cdx.json", + "artifacts/release/provenance.json", + "artifacts/release/reproducible-build.json", + "artifacts/security/dependency-diff.json", + "artifacts/security/license-report.json", + "artifacts/security/vulnerability-report.json", + "artifacts/security/supply-chain-verification.json", + "artifacts/security/supply-chain-coherence.json", + "artifacts/security/supply-chain-fixtures.json", + "artifacts/security/supply-chain-provider-fixtures.json" ], "retentionClass": "release-coherence" }, @@ -260,11 +281,15 @@ "FE-GATE-015": { "name": "release-coherence", "steps": [ - { "script": "build", "expect": "pass" }, - { "script": "verify:release", "expect": "pass" } + { "script": "build:release", "expect": "pass" }, + { "script": "verify:release", "expect": "pass" }, + { "script": "verify:supply-chain:promotion", "expect": "pass" } ], "logPath": "artifacts/quality/gates/FE-GATE-015.txt", - "evidence": ["artifacts/release/verification.json"], + "evidence": [ + "artifacts/release/verification.json", + "artifacts/security/promotion-verification.json" + ], "retentionClass": "release-coherence" }, "FE-GATE-016": { diff --git a/config/security/dependency-baseline.approval.json b/config/security/dependency-baseline.approval.json new file mode 100644 index 0000000..9ee247b --- /dev/null +++ b/config/security/dependency-baseline.approval.json @@ -0,0 +1,7 @@ +{ + "schemaVersion": 1, + "snapshotDigest": "ce4fa9b7944f27553067228bd6c9e73e7dc05875c283255b50d7eb3ad2923f6d", + "owner": "frontend-platform", + "reason": "RP-11-initial-transitive-inventory", + "approvedAt": "2026-07-26T08:27:17.874Z" +} diff --git a/config/security/dependency-baseline.json b/config/security/dependency-baseline.json new file mode 100644 index 0000000..fe77550 --- /dev/null +++ b/config/security/dependency-baseline.json @@ -0,0 +1,6669 @@ +{ + "schemaVersion": 2, + "packageManager": "pnpm@11.17.0", + "lockfileSha256": "bedf1bbc1007a7cf0dbc6d29b1f4da0a3296717d5969c7fabc4a2844d949ae21", + "dependencyCount": 561, + "directDependencyCount": 35, + "dependencies": [ + { + "name": "@adobe/css-tools", + "version": "4.5.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-6OzddxPio9UiWTCemp4N8cYLV2ZN1ncRnV1cVGtve7dhPOtRkleRyx32GQCYSwDYgaHU3USMm84tNsvKzRCa1Q==" + }, + { + "name": "@asamuzakjp/css-color", + "version": "5.1.11", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@asamuzakjp/generational-cache@1.0.1", + "@csstools/css-calc@3.3.0", + "@csstools/css-color-parser@4.1.10", + "@csstools/css-parser-algorithms@4.0.0", + "@csstools/css-tokenizer@4.0.0" + ], + "integrity": "sha512-KVw6qIiCTUQhByfTd78h2yD1/00waTmm9uy/R7Ck/ctUyAPj+AEDLkQIdJW0T8+qGgj3j5bpNKK7Q3G+LedJWg==" + }, + { + "name": "@asamuzakjp/dom-selector", + "version": "7.1.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@asamuzakjp/generational-cache@1.0.1", + "@asamuzakjp/nwsapi@2.3.9", + "bidi-js@1.0.3", + "css-tree@3.2.1", + "is-potential-custom-element-name@1.0.1" + ], + "integrity": "sha512-67RZDnYRc8H/8MLDgQCDE//zoqVFwajkepHZgmXrbwybzXOEwOWGPYGmALYl9J2DOLfFPPs6kKCqmbzV895hTQ==" + }, + { + "name": "@asamuzakjp/generational-cache", + "version": "1.0.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-wajfB8KqzMCN2KGNFdLkReeHncd0AslUSrvHVvvYWuU8ghncRJoA50kT3zP9MVL0+9g4/67H+cdvBskj9THPzg==" + }, + { + "name": "@asamuzakjp/nwsapi", + "version": "2.3.9", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==" + }, + { + "name": "@axe-core/playwright", + "version": "4.12.1", + "direct": true, + "scope": "development", + "optional": false, + "license": "MPL-2.0", + "dependencies": [ + "axe-core@4.12.1", + "playwright-core@1.62.0" + ], + "integrity": "sha512-rMd7xriptqKpP+w5265i4Hdkv2X5kbu6uiBi/B2I7uf3hieRBM3qDCfaKPtxfiYb2mKXfF+yLODJwIx+Jv1GDw==" + }, + { + "name": "@babel/code-frame", + "version": "7.29.7", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@babel/helper-validator-identifier@7.29.7", + "js-tokens@4.0.0", + "picocolors@1.1.1" + ], + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==" + }, + { + "name": "@babel/code-frame", + "version": "8.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@babel/helper-validator-identifier@8.0.4", + "js-tokens@10.0.0" + ], + "integrity": "sha512-dYYg153EyN2Ekbqw2zAsbd6/JR+9N2SEoC7YV2GyyqMM7x9bLDTjBD6XBhSMLH0wtIVyJj03jWNriQhaN+eoCw==" + }, + { + "name": "@babel/compat-data", + "version": "7.29.7", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==" + }, + { + "name": "@babel/compat-data", + "version": "8.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-DOjnob/cXOUgDOozCDeq/aK2p5y8dUIVdf6tNhEV1HQRd6I8aQ4f4fbtHRVEvb6lP3BGomrKHiS8ICAASSVQSw==" + }, + { + "name": "@babel/core", + "version": "7.29.7", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@babel/code-frame@7.29.7", + "@babel/generator@7.29.7", + "@babel/helper-compilation-targets@7.29.7", + "@babel/helper-module-transforms@7.29.7", + "@babel/helpers@7.29.7", + "@babel/parser@7.29.7", + "@babel/template@7.29.7", + "@babel/traverse@7.29.7", + "@babel/types@7.29.7", + "@jridgewell/remapping@2.3.5", + "convert-source-map@2.0.0", + "debug@4.4.3", + "gensync@1.0.0-beta.2", + "json5@2.2.3", + "semver@6.3.1" + ], + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==" + }, + { + "name": "@babel/core", + "version": "8.0.1", + "direct": true, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@babel/code-frame@8.0.0", + "@babel/generator@8.0.0", + "@babel/helper-compilation-targets@8.0.0", + "@babel/helpers@8.0.0", + "@babel/parser@8.0.4", + "@babel/template@8.0.0", + "@babel/traverse@8.0.4", + "@babel/types@8.0.4", + "@types/gensync@1.0.5", + "convert-source-map@2.0.0", + "empathic@2.0.1", + "gensync@1.0.0-beta.2", + "import-meta-resolve@4.2.0", + "json5@2.2.3", + "obug@2.1.4", + "semver@7.8.5" + ], + "integrity": "sha512-5FgxM4dLQpMJHSiVATk8foW263dVHQHBVpXYiimNECVWG01f4nFyEbQixeT6Mwvg7TayREJ2gpKl3o2RoMdnqw==" + }, + { + "name": "@babel/eslint-parser", + "version": "8.0.1", + "direct": true, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@babel/core@8.0.1", + "eslint-scope@9.1.2", + "eslint-visitor-keys@5.0.1", + "eslint@10.8.0", + "semver@7.8.5" + ], + "integrity": "sha512-2javO8pAQv/ld6sS6OcxoLAlzZEZy+xm99bnoAfMhzKSumKhdF5wylpbZB7XTorWr3KLPtx5K95eduJPOy1mzA==" + }, + { + "name": "@babel/generator", + "version": "7.29.7", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@babel/parser@7.29.7", + "@babel/types@7.29.7", + "@jridgewell/gen-mapping@0.3.13", + "@jridgewell/trace-mapping@0.3.31", + "jsesc@3.1.0" + ], + "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==" + }, + { + "name": "@babel/generator", + "version": "8.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@babel/parser@8.0.4", + "@babel/types@8.0.4", + "@jridgewell/gen-mapping@0.3.13", + "@jridgewell/trace-mapping@0.3.31", + "@types/jsesc@2.5.1", + "jsesc@3.1.0" + ], + "integrity": "sha512-NT9NrVwJsbSV6Y2FSstWa71EETOnzrjkL5/wX3D2mYHtKM+qvqB1DvR4D0Setb/gDBsHzRICifwEWMO8CnTF6g==" + }, + { + "name": "@babel/helper-compilation-targets", + "version": "7.29.7", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@babel/compat-data@7.29.7", + "@babel/helper-validator-option@7.29.7", + "browserslist@4.28.7", + "lru-cache@5.1.1", + "semver@6.3.1" + ], + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==" + }, + { + "name": "@babel/helper-compilation-targets", + "version": "8.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@babel/compat-data@8.0.0", + "@babel/helper-validator-option@8.0.0", + "browserslist@4.28.7", + "lru-cache@11.5.2", + "semver@7.8.5" + ], + "integrity": "sha512-JwculLABZvyPvyLBpwU/E/IbH2uM3mnxNtIJpxnIfb24y1PrdVxK5Dqjle4DpgqpGRnwgC7G8IkzPdSXZrO1Ew==" + }, + { + "name": "@babel/helper-globals", + "version": "7.29.7", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==" + }, + { + "name": "@babel/helper-globals", + "version": "8.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-lLozHOM6sWWlxNo8CYqHy4MBZeTvHXNgVPBfPOGsjPKUzHC2Az9QwB6gxdQmpwHl6GlQtbGgS+lj5887guDiLw==" + }, + { + "name": "@babel/helper-module-imports", + "version": "7.29.7", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@babel/traverse@7.29.7", + "@babel/types@7.29.7" + ], + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==" + }, + { + "name": "@babel/helper-module-transforms", + "version": "7.29.7", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@babel/core@7.29.7", + "@babel/helper-module-imports@7.29.7", + "@babel/helper-validator-identifier@7.29.7", + "@babel/traverse@7.29.7" + ], + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==" + }, + { + "name": "@babel/helper-plugin-utils", + "version": "8.0.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@babel/core@8.0.1" + ], + "integrity": "sha512-3PKFgjTyPlhFhorfP+SjKQxLViIL++zWjFOO4hGriYU+Bsm983DxEM1JmDRJVWXV0O9npu+xXRqz7Pbd3mh70g==" + }, + { + "name": "@babel/helper-string-parser", + "version": "7.29.7", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==" + }, + { + "name": "@babel/helper-string-parser", + "version": "8.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-6mJgmFFFIIO82vvoLt9XtRC7/TkzXfts1t/SpRX4IHSzMgqoPYCWesVu1udUPUWioAE/2fcG6WuI8zrkE1gwrg==" + }, + { + "name": "@babel/helper-validator-identifier", + "version": "7.29.7", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==" + }, + { + "name": "@babel/helper-validator-identifier", + "version": "8.0.4", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-4wFaiLd0bVo4cIoTXI3zKI038NIWE/cr3jvBjejOVYVxV/m8Ltav1USiGzG1fmS5J2RhgEOgXNNK46cRPnRsrg==" + }, + { + "name": "@babel/helper-validator-option", + "version": "7.29.7", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==" + }, + { + "name": "@babel/helper-validator-option", + "version": "8.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-U4Dybxh4WESWHt5XhBeExi4DrY0/DNK1aHpQbsrQXCUbFHuMweT0TpLEWKvaraV2Y6fS+ZXunsZ8zIuZIgvF2Q==" + }, + { + "name": "@babel/helpers", + "version": "7.29.7", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@babel/template@7.29.7", + "@babel/types@7.29.7" + ], + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==" + }, + { + "name": "@babel/helpers", + "version": "8.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@babel/template@8.0.0", + "@babel/types@8.0.4" + ], + "integrity": "sha512-wfbi91pM3py96oIiJEz7qIpyXDytgr9zQC1HEWwlGNVRAEmItuU/0a41ZUKu1sJGyhhOIpc4t5vk4PYzt8wpsg==" + }, + { + "name": "@babel/parser", + "version": "7.29.7", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@babel/types@7.29.7" + ], + "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==" + }, + { + "name": "@babel/parser", + "version": "8.0.4", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@babel/types@8.0.4" + ], + "integrity": "sha512-srpptsAkEbbNIC/q8nT7o+m6CQe8CJUTV/t7MYc9NnWlgYVtHOb7JH6SorxMhN0kuRJjVqXbKClG6xSbPtzz+g==" + }, + { + "name": "@babel/plugin-syntax-jsx", + "version": "8.0.1", + "direct": true, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@babel/core@8.0.1", + "@babel/helper-plugin-utils@8.0.1" + ], + "integrity": "sha512-n0jtCOxEovhU7METqSQjcZO9pX53nu9uNIjMS+hEt+Nt9jA7oOZoBIgbCxhhASmF6T6rPDGge5UAvh6Z4eFz/g==" + }, + { + "name": "@babel/plugin-syntax-typescript", + "version": "8.0.3", + "direct": true, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@babel/core@8.0.1", + "@babel/helper-plugin-utils@8.0.1" + ], + "integrity": "sha512-jmTPwps7oSQSZaV1SxkQ3C12UWyufGysGc5OzDpZzvPAIX4mO7dJT3hoqkWVrSImvkcMiknir1iLN1SNV/CZzg==" + }, + { + "name": "@babel/runtime", + "version": "7.29.7", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==" + }, + { + "name": "@babel/template", + "version": "7.29.7", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@babel/code-frame@7.29.7", + "@babel/parser@7.29.7", + "@babel/types@7.29.7" + ], + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==" + }, + { + "name": "@babel/template", + "version": "8.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@babel/code-frame@8.0.0", + "@babel/parser@8.0.4", + "@babel/types@8.0.4" + ], + "integrity": "sha512-eAD0QW/AlbamBbw0FeGiwasbCVPq5ncW0HNVyLP3B9czqLyh4gvw+5JTSNt6le9+ziAU7mqDZsKTHf3jTb4chQ==" + }, + { + "name": "@babel/traverse", + "version": "7.29.7", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@babel/code-frame@7.29.7", + "@babel/generator@7.29.7", + "@babel/helper-globals@7.29.7", + "@babel/parser@7.29.7", + "@babel/template@7.29.7", + "@babel/types@7.29.7", + "debug@4.4.3" + ], + "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==" + }, + { + "name": "@babel/traverse", + "version": "8.0.4", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@babel/code-frame@8.0.0", + "@babel/generator@8.0.0", + "@babel/helper-globals@8.0.0", + "@babel/parser@8.0.4", + "@babel/template@8.0.0", + "@babel/types@8.0.4", + "obug@2.1.4" + ], + "integrity": "sha512-bZnmqzGG8UZneG1lLxBoWIH0G6Gr1D846Yu4/3XnY6FhCndMR49u26nTY08u/dAxWmLWF9vGQOuC+84FfIUoeg==" + }, + { + "name": "@babel/types", + "version": "7.29.7", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@babel/helper-string-parser@7.29.7", + "@babel/helper-validator-identifier@7.29.7" + ], + "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==" + }, + { + "name": "@babel/types", + "version": "8.0.4", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@babel/helper-string-parser@8.0.0", + "@babel/helper-validator-identifier@8.0.4" + ], + "integrity": "sha512-eY+Yn3dCqTGmyiq2QRU66lA5FL8lqqqvecHt0fF3uHONIa7ToYsaCiWV8lOKqAs0Rb2SjixiKFROngnulPtt2g==" + }, + { + "name": "@bcoe/v8-coverage", + "version": "1.0.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==" + }, + { + "name": "@bramus/specificity", + "version": "2.4.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "css-tree@3.2.1" + ], + "integrity": "sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==" + }, + { + "name": "@csstools/color-helpers", + "version": "6.1.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT-0", + "dependencies": [], + "integrity": "sha512-064IFJdjTfUqnjpCVpMOdbr8FLQBhinbZj6yRv2An2E41O/pLEXqfFRWqGq/SxlE5PEUYTlvWsG2r8MswAVvkg==" + }, + { + "name": "@csstools/css-calc", + "version": "3.3.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@csstools/css-parser-algorithms@4.0.0", + "@csstools/css-tokenizer@4.0.0" + ], + "integrity": "sha512-c5ihYsPkdG6JCkU2zTMm4+k6r7RXuGxtWYhu5DHMIiF1FHzrfmHL5so11AoFpUv/tu61xfcmT4AmKoFfMPoqdQ==" + }, + { + "name": "@csstools/css-color-parser", + "version": "4.1.10", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@csstools/color-helpers@6.1.0", + "@csstools/css-calc@3.3.0", + "@csstools/css-parser-algorithms@4.0.0", + "@csstools/css-tokenizer@4.0.0" + ], + "integrity": "sha512-UZhQLIUyJaaMepqehrCODwCg2KW25vFvLWBmqYFaPclYvvxzj/sG8LBOhBFCp11i9uE7t1EyS+RAoV9tztPFyw==" + }, + { + "name": "@csstools/css-parser-algorithms", + "version": "4.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@csstools/css-tokenizer@4.0.0" + ], + "integrity": "sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==" + }, + { + "name": "@csstools/css-syntax-patches-for-csstree", + "version": "1.1.7", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT-0", + "dependencies": [ + "css-tree@3.2.1" + ], + "integrity": "sha512-fQ+05118eQS1cofO3aJpB5efgpBZMvIzwr/sbC8kDLVA5XLG8q1kJV5yzrUAI1f7lvhPnm8fgIjzFB8/O/5Dig==" + }, + { + "name": "@csstools/css-tokenizer", + "version": "4.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==" + }, + { + "name": "@emnapi/core", + "version": "1.11.1", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [ + "@emnapi/wasi-threads@1.2.2", + "tslib@2.8.1" + ], + "integrity": "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==" + }, + { + "name": "@emnapi/core", + "version": "1.11.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [ + "@emnapi/wasi-threads@1.2.2", + "tslib@2.8.1" + ], + "integrity": "sha512-TC8MkTuZUtcTSiFeuC0ksCh9QIJ5+F21MvZ4Wn4ORfYaFJ/0dsiudv5tVkejgwZlwQ39jL9WWDe2lz8x0WglOA==" + }, + { + "name": "@emnapi/core", + "version": "1.9.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [ + "@emnapi/wasi-threads@1.2.1", + "tslib@2.8.1" + ], + "integrity": "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==" + }, + { + "name": "@emnapi/runtime", + "version": "1.11.1", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [ + "tslib@2.8.1" + ], + "integrity": "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==" + }, + { + "name": "@emnapi/runtime", + "version": "1.11.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [ + "tslib@2.8.1" + ], + "integrity": "sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA==" + }, + { + "name": "@emnapi/runtime", + "version": "1.9.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [ + "tslib@2.8.1" + ], + "integrity": "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==" + }, + { + "name": "@emnapi/wasi-threads", + "version": "1.2.1", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [ + "tslib@2.8.1" + ], + "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==" + }, + { + "name": "@emnapi/wasi-threads", + "version": "1.2.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [ + "tslib@2.8.1" + ], + "integrity": "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==" + }, + { + "name": "@esbuild/aix-ppc64", + "version": "0.28.1", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==" + }, + { + "name": "@esbuild/android-arm", + "version": "0.28.1", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==" + }, + { + "name": "@esbuild/android-arm64", + "version": "0.28.1", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==" + }, + { + "name": "@esbuild/android-x64", + "version": "0.28.1", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==" + }, + { + "name": "@esbuild/darwin-arm64", + "version": "0.28.1", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==" + }, + { + "name": "@esbuild/darwin-x64", + "version": "0.28.1", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==" + }, + { + "name": "@esbuild/freebsd-arm64", + "version": "0.28.1", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==" + }, + { + "name": "@esbuild/freebsd-x64", + "version": "0.28.1", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==" + }, + { + "name": "@esbuild/linux-arm", + "version": "0.28.1", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==" + }, + { + "name": "@esbuild/linux-arm64", + "version": "0.28.1", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==" + }, + { + "name": "@esbuild/linux-ia32", + "version": "0.28.1", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==" + }, + { + "name": "@esbuild/linux-loong64", + "version": "0.28.1", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==" + }, + { + "name": "@esbuild/linux-mips64el", + "version": "0.28.1", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==" + }, + { + "name": "@esbuild/linux-ppc64", + "version": "0.28.1", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==" + }, + { + "name": "@esbuild/linux-riscv64", + "version": "0.28.1", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==" + }, + { + "name": "@esbuild/linux-s390x", + "version": "0.28.1", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==" + }, + { + "name": "@esbuild/linux-x64", + "version": "0.28.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==" + }, + { + "name": "@esbuild/netbsd-arm64", + "version": "0.28.1", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==" + }, + { + "name": "@esbuild/netbsd-x64", + "version": "0.28.1", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==" + }, + { + "name": "@esbuild/openbsd-arm64", + "version": "0.28.1", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==" + }, + { + "name": "@esbuild/openbsd-x64", + "version": "0.28.1", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==" + }, + { + "name": "@esbuild/openharmony-arm64", + "version": "0.28.1", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==" + }, + { + "name": "@esbuild/sunos-x64", + "version": "0.28.1", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==" + }, + { + "name": "@esbuild/win32-arm64", + "version": "0.28.1", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==" + }, + { + "name": "@esbuild/win32-ia32", + "version": "0.28.1", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==" + }, + { + "name": "@esbuild/win32-x64", + "version": "0.28.1", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==" + }, + { + "name": "@eslint-community/eslint-utils", + "version": "4.10.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "eslint-visitor-keys@3.4.3", + "eslint@10.8.0" + ], + "integrity": "sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==" + }, + { + "name": "@eslint-community/regexpp", + "version": "4.12.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==" + }, + { + "name": "@eslint/config-array", + "version": "0.23.5", + "direct": false, + "scope": "development", + "optional": false, + "license": "Apache-2.0", + "dependencies": [ + "@eslint/object-schema@3.0.5", + "debug@4.4.3", + "minimatch@10.2.5" + ], + "integrity": "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==" + }, + { + "name": "@eslint/config-helpers", + "version": "0.7.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "Apache-2.0", + "dependencies": [ + "@eslint/core@1.2.1" + ], + "integrity": "sha512-DObd/KKUsU+FaFv4PLxSRenpXfQWmPXXP3pPZ6/K1PCrMu2vQpMDMuQe/BqYeoLcz8ro0bVDF1RxOJgfVEdhUw==" + }, + { + "name": "@eslint/core", + "version": "1.2.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "Apache-2.0", + "dependencies": [ + "@types/json-schema@7.0.15" + ], + "integrity": "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==" + }, + { + "name": "@eslint/js", + "version": "10.0.1", + "direct": true, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "eslint@10.8.0" + ], + "integrity": "sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==" + }, + { + "name": "@eslint/object-schema", + "version": "3.0.5", + "direct": false, + "scope": "development", + "optional": false, + "license": "Apache-2.0", + "dependencies": [], + "integrity": "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==" + }, + { + "name": "@eslint/plugin-kit", + "version": "0.7.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "Apache-2.0", + "dependencies": [ + "@eslint/core@1.2.1", + "levn@0.4.1" + ], + "integrity": "sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A==" + }, + { + "name": "@exodus/bytes", + "version": "1.15.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-S6mL0yNB/Abt9Ei4tq8gDhcczc4S3+vQ4ra7vxnAf+YHC02srtqxKKZghx2Dq6p0e66THKwR6r8N6P95wEty7Q==" + }, + { + "name": "@humanfs/core", + "version": "0.19.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "Apache-2.0", + "dependencies": [ + "@humanfs/types@0.15.0" + ], + "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==" + }, + { + "name": "@humanfs/node", + "version": "0.16.8", + "direct": false, + "scope": "development", + "optional": false, + "license": "Apache-2.0", + "dependencies": [ + "@humanfs/core@0.19.2", + "@humanfs/types@0.15.0", + "@humanwhocodes/retry@0.4.3" + ], + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==" + }, + { + "name": "@humanfs/types", + "version": "0.15.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "Apache-2.0", + "dependencies": [], + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==" + }, + { + "name": "@humanwhocodes/module-importer", + "version": "1.0.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "Apache-2.0", + "dependencies": [], + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==" + }, + { + "name": "@humanwhocodes/retry", + "version": "0.4.3", + "direct": false, + "scope": "development", + "optional": false, + "license": "Apache-2.0", + "dependencies": [], + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==" + }, + { + "name": "@inquirer/ansi", + "version": "2.0.7", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-3eTuUO1vH2cZm2ZKHeQxnOqlTi9EfZDGgIe3BL3I4u+rJHocr9Fz86M4fjYABPvFnQG/gGK551HqDiIcETwU6Q==" + }, + { + "name": "@inquirer/confirm", + "version": "6.1.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@inquirer/core@11.2.1", + "@inquirer/type@4.0.7", + "@types/node@24.13.3" + ], + "integrity": "sha512-eb8DBZcz/2qHWQda4rk2JiQk5h9QV/cVHi1yjt0f69WFZMRFn0sJTye3EAP8icut8UDMjQPsaH5KbcOogefrFQ==" + }, + { + "name": "@inquirer/core", + "version": "11.2.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@inquirer/ansi@2.0.7", + "@inquirer/figures@2.0.7", + "@inquirer/type@4.0.7", + "@types/node@24.13.3", + "cli-width@4.1.0", + "fast-wrap-ansi@0.2.2", + "mute-stream@3.0.0", + "signal-exit@4.1.0" + ], + "integrity": "sha512-Qd6GJT1yVyrZZCfN8W2qKF5ApmqryXRhRKCuip8h01x2w/esJQ2XIYc6f9abMIHgKQdBfFTSOdbHRLAhuM09UA==" + }, + { + "name": "@inquirer/figures", + "version": "2.0.7", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-aJ8TBPOGB6f/2qziPfElISTCEd5XOYTFckA2SGjhNmiKzfK/u4ot3v0DUzGVdUnKjN10EqnnEPck36BkyfLnJw==" + }, + { + "name": "@inquirer/type", + "version": "4.0.7", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@types/node@24.13.3" + ], + "integrity": "sha512-t28inv14nMQ1PhKpsJPY+kEs/c00qzeCOS2gTNRyTjG5d6qsVA2fItxW4hkvGZ5lvanGLdtCzVIx5dwdRpN1+g==" + }, + { + "name": "@joshwooding/vite-plugin-react-docgen-typescript", + "version": "0.7.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "glob@13.0.6", + "react-docgen-typescript@2.4.0", + "typescript@7.0.2", + "vite@8.1.5" + ], + "integrity": "sha512-qvsTEwEFefhdirGOPnu9Wp6ChfIwy2dBCRuETU3uE+4cC+PFoxMSiiEhxk4lOluA34eARHA0OxqsEUYDqRMgeQ==" + }, + { + "name": "@jridgewell/gen-mapping", + "version": "0.3.13", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@jridgewell/sourcemap-codec@1.5.5", + "@jridgewell/trace-mapping@0.3.31" + ], + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==" + }, + { + "name": "@jridgewell/remapping", + "version": "2.3.5", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@jridgewell/gen-mapping@0.3.13", + "@jridgewell/trace-mapping@0.3.31" + ], + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==" + }, + { + "name": "@jridgewell/resolve-uri", + "version": "3.1.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==" + }, + { + "name": "@jridgewell/sourcemap-codec", + "version": "1.5.5", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==" + }, + { + "name": "@jridgewell/trace-mapping", + "version": "0.3.31", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@jridgewell/resolve-uri@3.1.2", + "@jridgewell/sourcemap-codec@1.5.5" + ], + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==" + }, + { + "name": "@mswjs/interceptors", + "version": "0.41.9", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@open-draft/deferred-promise@2.2.0", + "@open-draft/logger@0.3.0", + "@open-draft/until@2.1.0", + "is-node-process@1.2.0", + "outvariant@1.4.3", + "strict-event-emitter@0.5.1" + ], + "integrity": "sha512-VVPPgHyQ6ShqnrmDWuxjmUIsO9gWyOZFmuOfLd9LfBGQJwZfy0gvv9pbHSJuoFNIYC7ZDX9aoFwowjcdSC4E8w==" + }, + { + "name": "@napi-rs/wasm-runtime", + "version": "1.1.6", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [ + "@emnapi/core@1.11.1", + "@emnapi/core@1.11.2", + "@emnapi/core@1.9.2", + "@emnapi/runtime@1.11.1", + "@emnapi/runtime@1.11.2", + "@emnapi/runtime@1.9.2", + "@tybys/wasm-util@0.10.3" + ], + "integrity": "sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==" + }, + { + "name": "@open-draft/deferred-promise", + "version": "2.2.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==" + }, + { + "name": "@open-draft/deferred-promise", + "version": "3.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-XW375UK8/9SqUVNVa6M0yEy8+iTi4QN5VZ7aZuRFQmy76LRwI9wy5F4YIBU6T+eTe2/DNDo8tqu8RHlwLHM6RA==" + }, + { + "name": "@open-draft/logger", + "version": "0.3.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "is-node-process@1.2.0", + "outvariant@1.4.3" + ], + "integrity": "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==" + }, + { + "name": "@open-draft/until", + "version": "2.1.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==" + }, + { + "name": "@oxc-parser/binding-android-arm-eabi", + "version": "0.127.0", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-0LC7ye4hvqbIKxAzThzvswgHLFu2AURKzYLeSVvLdu2TBOYWQDmHnTqPLeA597BcUCxiLqLsS4CJ5uoI5WYWCQ==" + }, + { + "name": "@oxc-parser/binding-android-arm64", + "version": "0.127.0", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-b5jtVTH6AU5CJXHNdj7Jj9IEiR9yVjjnwHzPJhGyHGPdcsZSzBCkS9GBbV33niRMvKthDwQRFRJfI4a+k4PvYg==" + }, + { + "name": "@oxc-parser/binding-darwin-arm64", + "version": "0.127.0", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-obCE8B7ISKkJidjlhv9xRGJPOSDG2Yu6PRga9Ruaz35uintHxbp1Ki/Yc71wx4rj3Edrm0a1kzG1TAwit0wFpg==" + }, + { + "name": "@oxc-parser/binding-darwin-x64", + "version": "0.127.0", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-JL6Xb5IwPQT8rUzlpsX7E+AgfcdNklXNPFp8pjCQQ5MQOQo5rtEB2ui+3Hgg9Sn7Y9Egj6YOLLiHhLpdAe12Aw==" + }, + { + "name": "@oxc-parser/binding-freebsd-x64", + "version": "0.127.0", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-SDQ/3MQFw58fqQz3Z1PhSKFF3JoCF4gmlNjziDm8X02tTahCw0qJbd7FGPDKw1i4VTBZene9JPyC3mHtSvi+wA==" + }, + { + "name": "@oxc-parser/binding-linux-arm-gnueabihf", + "version": "0.127.0", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-Av+D1MIqzV0YMGPT9we2SIZaMKD7Cxs4CvXSx/yxaWHewZjYEjScpOf5igc8IILASViw4WTnjlwUdI1KzVtDHQ==" + }, + { + "name": "@oxc-parser/binding-linux-arm-musleabihf", + "version": "0.127.0", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-Cs2fdJ8cPpFdeebj6p4dag8A4+56hPvZ0AhQQzlaLswGz1tz7bXt1nETLeorrM9+AMcWFFkqxcXwDGfTVidY8g==" + }, + { + "name": "@oxc-parser/binding-linux-arm64-gnu", + "version": "0.127.0", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-qdOfTcT6SY8gsJrrV92uyEUyjqMGPpIB5JZUG6QN5dukYd+7/j0kX6MwK1DgQj39jtUYixxPiaRUiEN1+0CXgQ==" + }, + { + "name": "@oxc-parser/binding-linux-arm64-musl", + "version": "0.127.0", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-EoTCZneNFU/P2qrpEM+RHmQwt+CvDkyGESG6qhr7KaegXLZwePfbrkCDfAk8/rhxbDUVGsZILX+2tqPzFtoFWA==" + }, + { + "name": "@oxc-parser/binding-linux-ppc64-gnu", + "version": "0.127.0", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-zALjmZYgxFLHjXeudcDF0xFGNydTAtkAeXAr2EuC17ywCyFxcmQra4w0BMde0Yi/re4Bi4iwEoEXtYN7l6eBLQ==" + }, + { + "name": "@oxc-parser/binding-linux-riscv64-gnu", + "version": "0.127.0", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-fPP8M6zQLS7Jz7o9d5ArUSuAuSK3e+WCYVrCpdzeCOejidtZExJ9tjhDrAd3HEPqARBCPmdpqxESPFqy44vkBQ==" + }, + { + "name": "@oxc-parser/binding-linux-riscv64-musl", + "version": "0.127.0", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-7IcC4Ao02oGpfnjt+X/oF4U2mllo2qoSkw5xxiXNKL9MCTsTiAC6616beOuehdxGcnz1bRoPC1RQ2f1GQDdN+g==" + }, + { + "name": "@oxc-parser/binding-linux-s390x-gnu", + "version": "0.127.0", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-pbXIhiNFHoqWeqDNLiJ9JkpHz1IM9k4DXa66x+1GTWMG7iLxtkXgE53iiuKSXwmk3zIYmaPVfBvgcAhS583K4Q==" + }, + { + "name": "@oxc-parser/binding-linux-x64-gnu", + "version": "0.127.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-MYCguB9RvBvlSd6gbuNI7QwiLoCCAlGnlRJFPrzLI6U1/9wkC/WK6LtBAUln55H1Ctqw45PWmqrobKoMhsYQzQ==" + }, + { + "name": "@oxc-parser/binding-linux-x64-musl", + "version": "0.127.0", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-5eY0B/bxf1xIUxb4NOTvOI3KWtBQfPWYyKAzgcrCt0mDibSZygVpO1Pz8bkeiSZ5Jj9+M09dkggG3H8I5d0Uyg==" + }, + { + "name": "@oxc-parser/binding-openharmony-arm64", + "version": "0.127.0", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-Gld0ajrFTUXNtdw20fVBuTQx66FA75nIVg+//pPfR3sXkuABB4mTBhl3r9JNzrJpgW//qiwxf0nWXUWGJSL3UQ==" + }, + { + "name": "@oxc-parser/binding-wasm32-wasi", + "version": "0.127.0", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [ + "@emnapi/core@1.9.2", + "@emnapi/runtime@1.9.2", + "@napi-rs/wasm-runtime@1.1.6" + ], + "integrity": "sha512-T6KVD7rhLzFlwGRXMnxUFfkCZD8FHnb968wVXW1mXzgRFc5RNXOBY2mPPDZ77x5Ln76ltLMgtPg0cOkU1NSrEQ==" + }, + { + "name": "@oxc-parser/binding-win32-arm64-msvc", + "version": "0.127.0", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-Ujvw4X+LD1CCGULcsQcvb4YNVoBGqt+JHgNNzGGaCImELiZLk477ifUH53gIbE7EKd933NdTi25JWEr9K2HwXw==" + }, + { + "name": "@oxc-parser/binding-win32-ia32-msvc", + "version": "0.127.0", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-0cwxKO7KHQQQfo4Uf4B2SQrhgm+cJaP9OvFFhx52Tkg4bezsacu83GB2/In5bC415Ueeym+kXdnge/57rbSfTw==" + }, + { + "name": "@oxc-parser/binding-win32-x64-msvc", + "version": "0.127.0", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-rOrnSQSCbhI2kowr9XxE7m9a8oQXnBHjnS6j95LxxAnEZ0+Fz20WlRXG4ondQb+ejjt2KOsa65sE6++L6kUd+w==" + }, + { + "name": "@oxc-project/types", + "version": "0.127.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-aIYXQBo4lCbO4z0R3FHeucQHpF46l2LbMdxRvqvuRuW2OxdnSkcng5B8+K12spgLDj93rtN3+J2Vac/TIO+ciQ==" + }, + { + "name": "@oxc-project/types", + "version": "0.139.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==" + }, + { + "name": "@oxc-resolver/binding-android-arm-eabi", + "version": "11.24.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-y09e0L0SRI2OA2tUIrjBgoV3eH5hvUKXNkJqXmNo5V2WxIjyC7I7aJfRLMEVpA8yi95f90gFDvO0VMgrDw+vwA==" + }, + { + "name": "@oxc-resolver/binding-android-arm64", + "version": "11.24.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-cl4icWaZFnLdg8m6qtnh5rBMuGbxc/ptStFHLeCNwr+2cZjkjNwQu/jYRS0CHlnPecOJMpuS5M6/BH+0J/YkEg==" + }, + { + "name": "@oxc-resolver/binding-darwin-arm64", + "version": "11.24.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-At29QEMF6HajbQvgY8K6OXnHD1x9rad74xBEfmCB6ZqCGsdq75aK7tOYcTbOanMy8qdIBrfL3SMr3p/lfSlb9w==" + }, + { + "name": "@oxc-resolver/binding-darwin-x64", + "version": "11.24.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-A5Kqr1EUj4oIL5CF4WRssq/o5P0Y11cwoFouMRmQ7YnC/A8V93nv1nb7aSU8HwcgmXropjLNkVTl4MN87cu28Q==" + }, + { + "name": "@oxc-resolver/binding-freebsd-x64", + "version": "11.24.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-R5xkRBRRz7ceH/P5Jrc6G7FmdUdgpLYyESFAUDVTNQ9K0sGPxcp4ljiwEwEqsvNcQ4sYbMRrWcHHBCu7ksAJVw==" + }, + { + "name": "@oxc-resolver/binding-linux-arm-gnueabihf", + "version": "11.24.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-k/RuYL4L/R58IBn3wT5ma3Wh4k62bp1eYCFRWCmMsasUOqL+H6sW0VGFadEzKWXFFlz+2uIMoeMk9ySSZJHgbg==" + }, + { + "name": "@oxc-resolver/binding-linux-arm-musleabihf", + "version": "11.24.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-bnHAak3ujYfH5pKk4NieFNbvYvernfoQDgwLddbZ3OtMYrem87/qjlA+u+aKG0oZcqSLGCful/6/CEA+aeAgaA==" + }, + { + "name": "@oxc-resolver/binding-linux-arm64-gnu", + "version": "11.24.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-vDT3KHgzYp47gmtNOqL2VNhCyl5Zv643eyxm//A68J8DeUGXrvD1pZFiaT4jSfe+RInfnn1R2yVHye4enx6RnA==" + }, + { + "name": "@oxc-resolver/binding-linux-arm64-musl", + "version": "11.24.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-+kMlQvbzfyEYtu5FcjE4p+ttBLpKW4d/AsAsuE69BxV6V4twZJeIQZFfD8gh/wqglY0MkPSezWXQH0jBV13MUw==" + }, + { + "name": "@oxc-resolver/binding-linux-ppc64-gnu", + "version": "11.24.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-shjfMhmZ3gq9fv/w7bi3PnZlgOPG+2QAOFf0BJF0EgBSIGZ6PMLN2zbGEblTUYB/NKVDRyYhE2ff3dJ1QqNPkA==" + }, + { + "name": "@oxc-resolver/binding-linux-riscv64-gnu", + "version": "11.24.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-zGelwFR5oRo+b69k8Lrzun86DyUHzfKN6cnjbR9l7Z7NIRznOE/2ZvPa1IUKqAL2PzAXOdwkfVqNvO1H2RlpAw==" + }, + { + "name": "@oxc-resolver/binding-linux-riscv64-musl", + "version": "11.24.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-qxZ1SWCXJY0eyhAlP6Lmo9F2Nrtx7EkYj9oCgL8apDPCwXwCEDA2U697bbT81JIc2IrVjxO4KX6WU2N+oN9Z4w==" + }, + { + "name": "@oxc-resolver/binding-linux-s390x-gnu", + "version": "11.24.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-sGCecF3cx2DFlH4t/z7ApnOnXqN48p5p5mlHDEnHTAukQa2P+qMVE4CwyWE9W+q/m3QJ7kKfGrIjax31f44oFQ==" + }, + { + "name": "@oxc-resolver/binding-linux-x64-gnu", + "version": "11.24.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-k/VlMMcSzMlahb3/fENM4rTlsJ0s3fFROA0KXPBmKggqmTSaE383sl8F3KCOXPLmVsYfW6hCitMhXCEtNeZxxg==" + }, + { + "name": "@oxc-resolver/binding-linux-x64-musl", + "version": "11.24.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-8hbnZyNi97b/8wapYaIF9+t9GmZKBW2vunaOc3h9HGJptH7b7XpvZqOTBSm/MpTjr7H497BlgOaSfLUdhmy2bw==" + }, + { + "name": "@oxc-resolver/binding-openharmony-arm64", + "version": "11.24.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-MvyGik3a6pVgZ0t/kWlbmFxFLmXQJwgLsY2eYFHLpy0wGwRbfzeIGgDwQ3kXqE30z+kSXennRkCrT7TUvkptNg==" + }, + { + "name": "@oxc-resolver/binding-wasm32-wasi", + "version": "11.24.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [ + "@emnapi/core@1.11.2", + "@emnapi/runtime@1.11.2", + "@napi-rs/wasm-runtime@1.1.6" + ], + "integrity": "sha512-vHcssMPwO08RTvj/c0iOBz90attxyG3wQJ0dTcyEQK43LRpcdLWZlV5feBhv6Isn6ahbQIzHbCgfa81+RiML0Q==" + }, + { + "name": "@oxc-resolver/binding-win32-arm64-msvc", + "version": "11.24.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-uokJqro2iBqkFvJdKQLP7d8/BUmFwESQFVmIJUQKj1Xn1a/LysJoe1vmeECLF5b3jsV8CAL5sEMJXX6SdK9Nhg==" + }, + { + "name": "@oxc-resolver/binding-win32-x64-msvc", + "version": "11.24.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-UqGPmo56KDfLlfXFAFIrNflHT8tFxWGEivWg3Zeyp4Uy2NlKN1FGPr6/BxcLGG3+kZ6Wp14g5Uj+n71boqZfiw==" + }, + { + "name": "@playwright/test", + "version": "1.62.0", + "direct": true, + "scope": "development", + "optional": false, + "license": "Apache-2.0", + "dependencies": [ + "playwright@1.62.0" + ], + "integrity": "sha512-9zOJ6ZQRAena31MpOH9VSzIz8Ou3YJ/wtY/eQm5T2uhfhG7/U3COrMS8xOtUrZrp9OgdmzEnIYODye3nY1VqzA==" + }, + { + "name": "@rolldown/binding-android-arm64", + "version": "1.1.5", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ==" + }, + { + "name": "@rolldown/binding-darwin-arm64", + "version": "1.1.5", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw==" + }, + { + "name": "@rolldown/binding-darwin-x64", + "version": "1.1.5", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-Tm+gbfC0aHu1tBA/JvKQh32S0K6YgCHkiAF4/W6xX0K0RmNuc94VeK419dJoE65R5aRxmo+noZQSWrAMF6yb6g==" + }, + { + "name": "@rolldown/binding-freebsd-x64", + "version": "1.1.5", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-JMzDKCCXq93YccG5gz3hvOs1oXRKAf0XYpfOS88e+wZrC8Iugj6j68867vrYZkvpDDpKn/KoKORThmchMpF6TA==" + }, + { + "name": "@rolldown/binding-linux-arm-gnueabihf", + "version": "1.1.5", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-uML21j2K5TfPGutKxub+M+nLjZIrWjXQ5Grx4lCe/nimTj9B4L63zHpjXLl4y0L3mcm2htEQIb06oCG/szerNw==" + }, + { + "name": "@rolldown/binding-linux-arm64-gnu", + "version": "1.1.5", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-navSiuTMogvnQoZoM/v+l3ZWo50/NTwSHSzheABx/RCnmUPaKwq9qSo4Br2OYRs21+Fz8uFqITZM3H4opOB0/Q==" + }, + { + "name": "@rolldown/binding-linux-arm64-musl", + "version": "1.1.5", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-lAryqH7IteztmCXQXk0etKj4wBQ7Gx5S6LjKhsgp9zb8I5bsuvU/2llH1hDQcjsFeqIsovMVN339/8pUDDBXxA==" + }, + { + "name": "@rolldown/binding-linux-ppc64-gnu", + "version": "1.1.5", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-fsK/sNBnxzBlL4O1JNrZakVQxPspqpED5dLtNsZS9oOKmtSpdNIzxH2kkol5HYTWJN47sE20ztMJPxfZ89qGOg==" + }, + { + "name": "@rolldown/binding-linux-s390x-gnu", + "version": "1.1.5", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-gLYb4BIadlfTOYT5gO503n8zQjXflgzpD0FcyKh0Mzx3rqCZKnHoJWV9xe1KXUJ5lx2JfcSHr/mhzS0PC/McAA==" + }, + { + "name": "@rolldown/binding-linux-x64-gnu", + "version": "1.1.5", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-FjcpEKUyJygHgs1o50VYNvkt5+7Le/VEdYt0AkRpkL33MnyQfwr8l5mXwMmfmTbyMPr5vJLC+8/Gd9gXnwU1QQ==" + }, + { + "name": "@rolldown/binding-linux-x64-musl", + "version": "1.1.5", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-Me+PfPI2TMeOQk0gYWfLQZtTktrmzbr8cDboqX83XKc7UrgAi55gF+2dUkWdxd19n55Essp2yeca+O9N5rBxHg==" + }, + { + "name": "@rolldown/binding-openharmony-arm64", + "version": "1.1.5", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-yc5WrLzXks6zCQfn9Oxr8pORKyl/pF+QjHmW/Qx3qu0oyrrNC+y2JLTU1E2rcWYAmzlnqngWXHQjy51VzW70Vw==" + }, + { + "name": "@rolldown/binding-wasm32-wasi", + "version": "1.1.5", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [ + "@emnapi/core@1.11.1", + "@emnapi/runtime@1.11.1", + "@napi-rs/wasm-runtime@1.1.6" + ], + "integrity": "sha512-VbQGPX2b4r48TAMIM2cjgluIM1HYutm4pcTEJsle7iEP7sB1dFqtPLBVbdLAZCxy1txCcPxf4QFf4v8uvltPqA==" + }, + { + "name": "@rolldown/binding-win32-arm64-msvc", + "version": "1.1.5", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-gHv82k63z4qpV5+Q1y/12KrK0ltWBukVDI8nZcbT7Tt/ZlOIVwppazneq0F93oDxTo3IgAMEDIoQh3E2n6mVsw==" + }, + { + "name": "@rolldown/binding-win32-x64-msvc", + "version": "1.1.5", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-tTZuDBPw85tEN5PQi1pnEBzDy0Z49HtScLAbD5t6hyeU92A95pRWaSMw1GZZi/RwgSgUIl0xrSlXIT/9QzvYSA==" + }, + { + "name": "@rolldown/pluginutils", + "version": "1.0.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==" + }, + { + "name": "@rollup/pluginutils", + "version": "5.4.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@types/estree@1.0.9", + "estree-walker@2.0.2", + "picomatch@4.0.5" + ], + "integrity": "sha512-MfPp06CjRLfXQ3wY0R8vJDYBy/MvVcc9OulEfR0B8Iv9ko+GCNaRZ+EpJYFl27LhKsZK0o420sYCRHCjfCgeUg==" + }, + { + "name": "@standard-schema/spec", + "version": "1.1.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==" + }, + { + "name": "@storybook/addon-a11y", + "version": "10.5.4", + "direct": true, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@storybook/global@5.0.0", + "axe-core@4.12.1", + "storybook@10.5.4" + ], + "integrity": "sha512-UWdZtB7Dh1GjqxTPOrisUNDhDGF5pKGzZdzW9DSSHMBcAOx2dsTmXGzLSFprAz4LTT0OHCtKhxNqKK0JZJ0Y8g==" + }, + { + "name": "@storybook/builder-vite", + "version": "10.5.4", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@storybook/csf-plugin@10.5.4", + "storybook@10.5.4", + "ts-dedent@2.3.0", + "vite@8.1.5" + ], + "integrity": "sha512-eXdgow+brSzZrG3CnG18YwxZwEYNAZIh2G5qKwNoZf0uk2ZCPgLRQwtVAcd7BiiEDGnXUHm9pycAS+UiF4F4Mg==" + }, + { + "name": "@storybook/csf-plugin", + "version": "10.5.4", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "esbuild@0.28.1", + "storybook@10.5.4", + "unplugin@2.3.11", + "vite@8.1.5" + ], + "integrity": "sha512-DSp5Z/eZlRnKq0KrKLJE6uoYf/Ysc+FP0Z5DVTGnOrie+z3tC0lNi9I4RB++EXkJeUDS9/4dxvJZVSWjhLlXxw==" + }, + { + "name": "@storybook/global", + "version": "5.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==" + }, + { + "name": "@storybook/icons", + "version": "2.1.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "react@19.2.8" + ], + "integrity": "sha512-Fxh9vYpX9bQqFeHRiY8h2ApeRGDzRSMLwJwNZ/AIRqnyOKHxRKL+yFe+ctEkVJmuptRE9u1Hrn8ZZNHyfDKKNg==" + }, + { + "name": "@storybook/react-dom-shim", + "version": "10.5.4", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@types/react-dom@19.2.3", + "@types/react@19.2.8", + "react-dom@19.2.8", + "react@19.2.8", + "storybook@10.5.4" + ], + "integrity": "sha512-YdlppEOReg8MvTECRNuf79gu2zL83JqKDHIR/65eS0M6y+ue9pkpfjYo7hZVIcyOcRd9npBDXMdt2kC92bCuaA==" + }, + { + "name": "@storybook/react-vite", + "version": "10.5.4", + "direct": true, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@joshwooding/vite-plugin-react-docgen-typescript@0.7.0", + "@rollup/pluginutils@5.4.0", + "@storybook/builder-vite@10.5.4", + "@storybook/react@10.5.4", + "empathic@2.0.1", + "magic-string@0.30.21", + "react-docgen@8.0.3", + "react-dom@19.2.8", + "react@19.2.8", + "resolve@1.22.12", + "storybook@10.5.4", + "tsconfig-paths@4.2.0", + "typescript@7.0.2", + "vite@8.1.5" + ], + "integrity": "sha512-iw7EAA98n30vpf+ZSy2Ll4Ne7oyZ/lS6W22u5Sp5UOI2oAkYuklxIWjRIKGqpY0BHP+GqaGYtUGMZQnBqgul2g==" + }, + { + "name": "@storybook/react", + "version": "10.5.4", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@storybook/global@5.0.0", + "@storybook/react-dom-shim@10.5.4", + "@types/react-dom@19.2.3", + "@types/react@19.2.8", + "react-docgen-typescript@2.4.0", + "react-docgen@8.0.3", + "react-dom@19.2.8", + "react@19.2.8", + "storybook@10.5.4", + "typescript@7.0.2" + ], + "integrity": "sha512-tOxfVgbYcaVsArN8XTDkJfdsnsnHh1LxjRHVpJ/N+VEkz4FveK/XH3jOLV0YqgrG8yXza7+CteDP4FfPVQY/mw==" + }, + { + "name": "@tailwindcss/node", + "version": "4.3.3", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@jridgewell/remapping@2.3.5", + "enhanced-resolve@5.24.2", + "jiti@2.7.0", + "lightningcss@1.32.0", + "magic-string@0.30.21", + "source-map-js@1.2.1", + "tailwindcss@4.3.3" + ], + "integrity": "sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==" + }, + { + "name": "@tailwindcss/oxide-android-arm64", + "version": "4.3.3", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==" + }, + { + "name": "@tailwindcss/oxide-darwin-arm64", + "version": "4.3.3", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==" + }, + { + "name": "@tailwindcss/oxide-darwin-x64", + "version": "4.3.3", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==" + }, + { + "name": "@tailwindcss/oxide-freebsd-x64", + "version": "4.3.3", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==" + }, + { + "name": "@tailwindcss/oxide-linux-arm-gnueabihf", + "version": "4.3.3", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==" + }, + { + "name": "@tailwindcss/oxide-linux-arm64-gnu", + "version": "4.3.3", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==" + }, + { + "name": "@tailwindcss/oxide-linux-arm64-musl", + "version": "4.3.3", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==" + }, + { + "name": "@tailwindcss/oxide-linux-x64-gnu", + "version": "4.3.3", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==" + }, + { + "name": "@tailwindcss/oxide-linux-x64-musl", + "version": "4.3.3", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==" + }, + { + "name": "@tailwindcss/oxide-wasm32-wasi", + "version": "4.3.3", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==" + }, + { + "name": "@tailwindcss/oxide-win32-arm64-msvc", + "version": "4.3.3", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==" + }, + { + "name": "@tailwindcss/oxide-win32-x64-msvc", + "version": "4.3.3", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==" + }, + { + "name": "@tailwindcss/oxide", + "version": "4.3.3", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@tailwindcss/oxide-android-arm64@4.3.3", + "@tailwindcss/oxide-darwin-arm64@4.3.3", + "@tailwindcss/oxide-darwin-x64@4.3.3", + "@tailwindcss/oxide-freebsd-x64@4.3.3", + "@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3", + "@tailwindcss/oxide-linux-arm64-gnu@4.3.3", + "@tailwindcss/oxide-linux-arm64-musl@4.3.3", + "@tailwindcss/oxide-linux-x64-gnu@4.3.3", + "@tailwindcss/oxide-linux-x64-musl@4.3.3", + "@tailwindcss/oxide-wasm32-wasi@4.3.3", + "@tailwindcss/oxide-win32-arm64-msvc@4.3.3", + "@tailwindcss/oxide-win32-x64-msvc@4.3.3" + ], + "integrity": "sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA==" + }, + { + "name": "@tailwindcss/vite", + "version": "4.3.3", + "direct": true, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@tailwindcss/node@4.3.3", + "@tailwindcss/oxide@4.3.3", + "tailwindcss@4.3.3", + "vite@8.1.5" + ], + "integrity": "sha512-yYU8cogLeSh/ms2jh8Fj7jaba/EWa7Ja6GoUqYZaraEuCI5YS6ms6ObZgjjedm+jm6XZjdNRWBpPP6Z86oOxcw==" + }, + { + "name": "@tanstack/query-core", + "version": "5.101.4", + "direct": false, + "scope": "production", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-gNwcvOJcRbLWPOLG/2OBm+zM+Yv+MKsXKEOWC57USuZDEsI71hEErQsiEGx5wX9rzWWkfwM0fVSPoiIFSsxfiw==" + }, + { + "name": "@tanstack/react-query", + "version": "5.101.4", + "direct": true, + "scope": "production", + "optional": false, + "license": "MIT", + "dependencies": [ + "@tanstack/query-core@5.101.4", + "react@19.2.8" + ], + "integrity": "sha512-yRg2pfOCxIs4ZJW3XYYHU/WgtD04FHSnfHlpRT7h7pR77hwkdRG4wxbKe4aq6P0RvXUTBSQpQeadS1SUYUe+KA==" + }, + { + "name": "@testing-library/dom", + "version": "10.4.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@babel/code-frame@7.29.7", + "@babel/runtime@7.29.7", + "@types/aria-query@5.0.4", + "aria-query@5.3.0", + "dom-accessibility-api@0.5.16", + "lz-string@1.5.0", + "picocolors@1.1.1", + "pretty-format@27.5.1" + ], + "integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==" + }, + { + "name": "@testing-library/jest-dom", + "version": "6.10.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@adobe/css-tools@4.5.0", + "@testing-library/dom@10.4.1", + "aria-query@5.3.2", + "css.escape@1.5.1", + "dom-accessibility-api@0.6.3", + "picocolors@1.1.1", + "redent@3.0.0" + ], + "integrity": "sha512-HQwu0KaB2zyT0iLzBL+8CLyZDL3KlZlZJ+2iyc9uCUnlJVskJU/UlPuVCyIPhtukjPQdT2QNoR5nCP5FqTmmDQ==" + }, + { + "name": "@testing-library/jest-dom", + "version": "7.0.0", + "direct": true, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@adobe/css-tools@4.5.0", + "@testing-library/dom@10.4.1", + "aria-query@5.3.2", + "css.escape@1.5.1", + "dom-accessibility-api@0.6.3", + "picocolors@1.1.1", + "redent@3.0.0" + ], + "integrity": "sha512-HKAH9C6mBo5yBG6yRO5i43L2iisencAo5z+o5P/saHUoY+miC5ivXRxHBJcFyB5ypPNxHJdK3BoF/3O4DIptMg==" + }, + { + "name": "@testing-library/react", + "version": "16.3.2", + "direct": true, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@babel/runtime@7.29.7", + "@testing-library/dom@10.4.1", + "@types/react-dom@19.2.3", + "@types/react@19.2.8", + "react-dom@19.2.8", + "react@19.2.8" + ], + "integrity": "sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g==" + }, + { + "name": "@testing-library/user-event", + "version": "14.6.1", + "direct": true, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@testing-library/dom@10.4.1" + ], + "integrity": "sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==" + }, + { + "name": "@tybys/wasm-util", + "version": "0.10.3", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [ + "tslib@2.8.1" + ], + "integrity": "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==" + }, + { + "name": "@types/aria-query", + "version": "5.0.4", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==" + }, + { + "name": "@types/babel__core", + "version": "7.20.5", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@babel/parser@7.29.7", + "@babel/types@7.29.7", + "@types/babel__generator@7.27.0", + "@types/babel__template@7.4.4", + "@types/babel__traverse@7.28.0" + ], + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==" + }, + { + "name": "@types/babel__generator", + "version": "7.27.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@babel/types@7.29.7" + ], + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==" + }, + { + "name": "@types/babel__template", + "version": "7.4.4", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@babel/parser@7.29.7", + "@babel/types@7.29.7" + ], + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==" + }, + { + "name": "@types/babel__traverse", + "version": "7.28.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@babel/types@7.29.7" + ], + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==" + }, + { + "name": "@types/chai", + "version": "5.2.3", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@types/deep-eql@4.0.2", + "assertion-error@2.0.1" + ], + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==" + }, + { + "name": "@types/deep-eql", + "version": "4.0.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==" + }, + { + "name": "@types/doctrine", + "version": "0.0.9", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-eOIHzCUSH7SMfonMG1LsC2f8vxBFtho6NGBznK41R84YzPuvSBzrhEps33IsQiOW9+VL6NQ9DbjQJznk/S4uRA==" + }, + { + "name": "@types/esrecurse", + "version": "4.3.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==" + }, + { + "name": "@types/estree", + "version": "1.0.9", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==" + }, + { + "name": "@types/gensync", + "version": "1.0.5", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-MbsRCT7mTikHwKZ0X+LVUTLRrZZRLipTuXEO9qOYO+zmjMVk81axyClMROf6uoPD9MRVu46bx8zoR0Ad9q3NAg==" + }, + { + "name": "@types/jsesc", + "version": "2.5.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-9VN+6yxLOPLOav+7PwjZbxiID2bVaeq0ED4qSQmdQTdjnXJSaCVKTR58t15oqH1H5t8Ng2ZX1SabJVoN9Q34bw==" + }, + { + "name": "@types/json-schema", + "version": "7.0.15", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" + }, + { + "name": "@types/node", + "version": "24.13.3", + "direct": true, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "undici-types@7.18.2" + ], + "integrity": "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q==" + }, + { + "name": "@types/react-dom", + "version": "19.2.3", + "direct": true, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@types/react@19.2.8" + ], + "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==" + }, + { + "name": "@types/react", + "version": "19.2.8", + "direct": true, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "csstype@3.2.3" + ], + "integrity": "sha512-3MbSL37jEchWZz2p2mjntRZtPt837ij10ApxKfgmXCTuHWagYg7iA5bqPw6C8BMPfwidlvfPI/fxOc42HLhcyg==" + }, + { + "name": "@types/resolve", + "version": "1.20.6", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-A4STmOXPhMUtHH+S6ymgE2GiBSMqf4oTvcQZMcHzokuTLVYzXTB8ttjcgxOVaAp2lGwEdzZ0J+cRbbeevQj1UQ==" + }, + { + "name": "@types/set-cookie-parser", + "version": "2.4.10", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@types/node@24.13.3" + ], + "integrity": "sha512-GGmQVGpQWUe5qglJozEjZV/5dyxbOOZ0LHe/lqyWssB88Y4svNfst0uqBVscdDeIKl5Jy5+aPSvy7mI9tYRguw==" + }, + { + "name": "@types/statuses", + "version": "2.0.6", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-xMAgYwceFhRA2zY+XbEA7mxYbA093wdiW8Vu6gZPGWy9cmOyU9XesH1tNcEWsKFd5Vzrqx5T3D38PWx1FIIXkA==" + }, + { + "name": "@typescript/typescript-aix-ppc64", + "version": "7.0.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ==" + }, + { + "name": "@typescript/typescript-darwin-arm64", + "version": "7.0.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA==" + }, + { + "name": "@typescript/typescript-darwin-x64", + "version": "7.0.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-SZ9xZInqApNlNGc9s0W1VSsktYSOe9cFqNOIqmN1Gs8SmkjKZYFt017G4VwPxASInODuAdbTW7sXiFUf893RgA==" + }, + { + "name": "@typescript/typescript-freebsd-arm64", + "version": "7.0.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-W5NH4y/J0plIIS5b2xvTEkU7JFxyqdMAOgf+Ilhl0vHQXKO5dZoxd+C/jEtq56c4F3wk71RB4BMRQ2XdI+bwYQ==" + }, + { + "name": "@typescript/typescript-freebsd-x64", + "version": "7.0.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-UMGDx5sTpzNw3WiPebH7l90IWfJggEd+egHt/q6p7/Cm3zqoV7VxkGXt+3DxPIw8CcmvAB0j3sVVfbhX+M4Tpw==" + }, + { + "name": "@typescript/typescript-linux-arm", + "version": "7.0.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-gffT3xPz9sR7j/YJExkyPntrI0P2EP9XbOyWzth2/Gs0RstK+90RBcO0ncXoXy/beYll1SXw846Nf2zdnEz0QQ==" + }, + { + "name": "@typescript/typescript-linux-arm64", + "version": "7.0.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-Qh4eU4/y3yDjnfjjyPYihMj5/ODIlmt+Bzu17OI+fiSRDW57QmU5SiN63exPRNJPKUzcc1INa1NXdrJ+MqHjUQ==" + }, + { + "name": "@typescript/typescript-linux-loong64", + "version": "7.0.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-uEHck9i8hoAzXPiYRib1O7miOnz23SxIeVl6F4LXox+qov1K35jHcEW6VHKvZI+pyvl7fZEP4MCU5LYvIq1GuQ==" + }, + { + "name": "@typescript/typescript-linux-mips64el", + "version": "7.0.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-R4KvAMnE43W5Qeqb0Ly56O3mWMWIAgsMyz36DCaycd5nbg/9kzm0liw3JocfRqyJY0KPmzFjbswozXyW0DnIYA==" + }, + { + "name": "@typescript/typescript-linux-ppc64", + "version": "7.0.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-DORx5b3sd/4S7eayxm4FQv+A7CrkUIGRaHiwI8oiHTAI1fAPWhF4J0vAlkC8biAlHSVVwxMQ3tjZ2/DVbnQiiA==" + }, + { + "name": "@typescript/typescript-linux-riscv64", + "version": "7.0.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-wf0jqEDOjrPRnKwYRyyJDRo11KMbvMFrU+q4zqKyChODBzvlkbhNQfKvLxQCcwTpdDaXSHZTVuh0JoCrKCUMHQ==" + }, + { + "name": "@typescript/typescript-linux-s390x", + "version": "7.0.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-IkwJc3L7yhytWd/ewjyxNDfOmswCm9GWMJT/ue/dU4aZNbwZeYAetq42VyLmsmSjvoX7z74X6ZaYCtzAr0EuGw==" + }, + { + "name": "@typescript/typescript-linux-x64", + "version": "7.0.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "Apache-2.0", + "dependencies": [], + "integrity": "sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A==" + }, + { + "name": "@typescript/typescript-netbsd-arm64", + "version": "7.0.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-+polYF4MF04aPpO5FTkHran9yUQDSXqy5GiSDKpsll5jy3l3+g9QLhpf39T+ePtefhXLOGrLl0QIjkQP6VnelA==" + }, + { + "name": "@typescript/typescript-netbsd-x64", + "version": "7.0.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-8YIT0EHM/3dq10ZOVF/A7pc/YSMtbcecct4rWtexrnSCHOPcpC2KTLXfTCR6vDpnSiY12heNb1GiN/wu+T/FyA==" + }, + { + "name": "@typescript/typescript-openbsd-arm64", + "version": "7.0.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-APT8+ClYnuYm1u9+kgGXoMj2VzWzcymwh2gNSQVySHfkRDGOTVkoWLjCmOQSaO+PoqQ57B0flRp9SA+7GnnkzQ==" + }, + { + "name": "@typescript/typescript-openbsd-x64", + "version": "7.0.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-yX7s+Q0Dln0Dt9tEzZsAjXXR/+ytBM7AlglaqyeMPxQszJ1JhlJdZ6jLA+IzldHtflX81em7lDao1xXu+aRRkg==" + }, + { + "name": "@typescript/typescript-sunos-x64", + "version": "7.0.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-dLJDGaLZ1D4HPQn62u1n8mBDkJREwMsAkCdkwd4Ieqw+x3TUyTsqY0YiBCtE6H6OzzgGk3iuZ3vFWRS+E8/d1g==" + }, + { + "name": "@typescript/typescript-win32-arm64", + "version": "7.0.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-Gyl1Vy6OsWesLzmq+EP0Fb7b4Nid5232AvcA2SFcdYreldpNtYFFofPjnt62y9hQy7VTaZp65ICJjuAQRaVcIQ==" + }, + { + "name": "@typescript/typescript-win32-x64", + "version": "7.0.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g==" + }, + { + "name": "@vitejs/plugin-react", + "version": "6.0.4", + "direct": true, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@rolldown/pluginutils@1.0.1", + "vite@8.1.5" + ], + "integrity": "sha512-XcCQz0TBpBgljhj0gMuuDj49i6Ytqh5q1osT/Gp5uAVJUCTWxyskk/l1jwYYiu2xcNHHipdMz40EGfM1VdamVg==" + }, + { + "name": "@vitest/coverage-v8", + "version": "4.1.10", + "direct": true, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@bcoe/v8-coverage@1.0.2", + "@vitest/utils@4.1.10", + "ast-v8-to-istanbul@1.0.5", + "istanbul-lib-coverage@3.2.2", + "istanbul-lib-report@3.0.1", + "istanbul-reports@3.2.0", + "magicast@0.5.3", + "obug@2.1.4", + "std-env@4.2.0", + "tinyrainbow@3.1.0", + "vitest@4.1.10" + ], + "integrity": "sha512-IM49HmthevbgAO4anp1hwtoT9wYe59w0LR00gr+eagHE+ZJ5lK4sLPeO0ubgoJcwLk6dehU3R24N+FbEEKDc8g==" + }, + { + "name": "@vitest/expect", + "version": "3.2.4", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@types/chai@5.2.3", + "@vitest/spy@3.2.4", + "@vitest/utils@3.2.4", + "chai@5.3.3", + "tinyrainbow@2.0.0" + ], + "integrity": "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==" + }, + { + "name": "@vitest/expect", + "version": "4.1.10", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@standard-schema/spec@1.1.0", + "@types/chai@5.2.3", + "@vitest/spy@4.1.10", + "@vitest/utils@4.1.10", + "chai@6.2.2", + "tinyrainbow@3.1.0" + ], + "integrity": "sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==" + }, + { + "name": "@vitest/mocker", + "version": "4.1.10", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@vitest/spy@4.1.10", + "estree-walker@3.0.3", + "magic-string@0.30.21", + "msw@2.15.0", + "vite@8.1.5" + ], + "integrity": "sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow==" + }, + { + "name": "@vitest/pretty-format", + "version": "3.2.4", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "tinyrainbow@2.0.0" + ], + "integrity": "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==" + }, + { + "name": "@vitest/pretty-format", + "version": "4.1.10", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "tinyrainbow@3.1.0" + ], + "integrity": "sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q==" + }, + { + "name": "@vitest/runner", + "version": "4.1.10", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@vitest/utils@4.1.10", + "pathe@2.0.3" + ], + "integrity": "sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg==" + }, + { + "name": "@vitest/snapshot", + "version": "4.1.10", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@vitest/pretty-format@4.1.10", + "@vitest/utils@4.1.10", + "magic-string@0.30.21", + "pathe@2.0.3" + ], + "integrity": "sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw==" + }, + { + "name": "@vitest/spy", + "version": "3.2.4", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "tinyspy@4.0.4" + ], + "integrity": "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==" + }, + { + "name": "@vitest/spy", + "version": "4.1.10", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw==" + }, + { + "name": "@vitest/utils", + "version": "3.2.4", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@vitest/pretty-format@3.2.4", + "loupe@3.2.1", + "tinyrainbow@2.0.0" + ], + "integrity": "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==" + }, + { + "name": "@vitest/utils", + "version": "4.1.10", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@vitest/pretty-format@4.1.10", + "convert-source-map@2.0.0", + "tinyrainbow@3.1.0" + ], + "integrity": "sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==" + }, + { + "name": "@webcontainer/env", + "version": "1.1.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-6aN99yL695Hi9SuIk1oC88l9o0gmxL1nGWWQ/kNy81HigJ0FoaoTXpytCj6ItzgyCEwA9kF1wixsTuv5cjsgng==" + }, + { + "name": "acorn-jsx-walk", + "version": "2.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-uuo6iJj4D4ygkdzd6jPtcxs8vZgDX9YFIkqczGImoypX2fQ4dVImmu3UzA4ynixCIMTrEOWW+95M2HuBaCEOVA==" + }, + { + "name": "acorn-jsx", + "version": "5.3.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "acorn@8.17.0" + ], + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==" + }, + { + "name": "acorn-loose", + "version": "8.5.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "acorn@8.17.0" + ], + "integrity": "sha512-PPvV6g8UGMGgjrMu+n/f9E/tCSkNQ2Y97eFvuVdJfG11+xdIeDcLyNdC8SHcrHbRqkfwLASdplyR6B6sKM1U4A==" + }, + { + "name": "acorn-walk", + "version": "8.3.5", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "acorn@8.17.0" + ], + "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==" + }, + { + "name": "acorn", + "version": "8.17.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==" + }, + { + "name": "ajv", + "version": "6.15.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "fast-deep-equal@3.1.3", + "fast-json-stable-stringify@2.1.0", + "json-schema-traverse@0.4.1", + "uri-js@4.4.1" + ], + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==" + }, + { + "name": "ansi-regex", + "version": "5.0.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + { + "name": "ansi-styles", + "version": "4.3.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "color-convert@2.0.1" + ], + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==" + }, + { + "name": "ansi-styles", + "version": "5.2.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + }, + { + "name": "aria-query", + "version": "5.3.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "Apache-2.0", + "dependencies": [ + "dequal@2.0.3" + ], + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==" + }, + { + "name": "aria-query", + "version": "5.3.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "Apache-2.0", + "dependencies": [], + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==" + }, + { + "name": "assertion-error", + "version": "2.0.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==" + }, + { + "name": "ast-types", + "version": "0.16.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "tslib@2.8.1" + ], + "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==" + }, + { + "name": "ast-v8-to-istanbul", + "version": "1.0.5", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@jridgewell/trace-mapping@0.3.31", + "estree-walker@3.0.3", + "js-tokens@10.0.0" + ], + "integrity": "sha512-UPAgKJFSEGMWSDr3LX4tqnAb4f7KGT8O40Tyx8wbYmmZ/yn58lNCm8h3svs3eXgiGd5AXxz8NDOvXWvicq+rJA==" + }, + { + "name": "axe-core", + "version": "4.12.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MPL-2.0", + "dependencies": [], + "integrity": "sha512-s7iGf5GaVMxEG0ENN9x+xTr7GFZCb1ZP/1uATUpCEK2X78nDB3RwbtFCo9pGAf9ru+VwoQ464DkaLEeRM08wJA==" + }, + { + "name": "balanced-match", + "version": "4.0.4", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==" + }, + { + "name": "baseline-browser-mapping", + "version": "2.11.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "Apache-2.0", + "dependencies": [], + "integrity": "sha512-HYXq73DDpCtNzOmrFsm9eSwCvWCql0RzqjpDzXN9EadiLJ4DNat0nsZ/Bzmy+Ud12mb4/zKDY0cQ805ZzN+i0A==" + }, + { + "name": "bidi-js", + "version": "1.0.3", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "require-from-string@2.0.2" + ], + "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==" + }, + { + "name": "brace-expansion", + "version": "5.0.8", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "balanced-match@4.0.4" + ], + "integrity": "sha512-JZyDyq3D4AUifKTPOB7DELf6XsB3WdPuNxCtob1vFXPsSXhdAiHBWJ/tJ8HAc9aH84BK+5JFZLNkJKx3G9kzQg==" + }, + { + "name": "browserslist", + "version": "4.28.7", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "baseline-browser-mapping@2.11.1", + "caniuse-lite@1.0.30001806", + "electron-to-chromium@1.5.396", + "node-releases@2.0.51", + "update-browserslist-db@1.2.3" + ], + "integrity": "sha512-JxV13hNrFxqjOc8alRbq9dK1MM79NEXYpma2B2J4wAtpWS5zIEIKqWPGCl7N4o7Uc7B7itylh7SuDujATRyyTw==" + }, + { + "name": "bundle-name", + "version": "4.1.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "run-applescript@7.1.0" + ], + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==" + }, + { + "name": "caniuse-lite", + "version": "1.0.30001806", + "direct": false, + "scope": "development", + "optional": false, + "license": "CC-BY-4.0", + "dependencies": [], + "integrity": "sha512-72Cuvd95zbSYPKq6Fhg8eDJRlzgWDf7/mtoZv6Qe/DYNCEBdNxoA3+rZAU2ZhGCpZlns3EssFavaZomckT5Uuw==" + }, + { + "name": "chai", + "version": "5.3.3", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "assertion-error@2.0.1", + "check-error@2.1.3", + "deep-eql@5.0.2", + "loupe@3.2.1", + "pathval@2.0.1" + ], + "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==" + }, + { + "name": "chai", + "version": "6.2.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==" + }, + { + "name": "chalk", + "version": "4.1.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "ansi-styles@4.3.0", + "supports-color@7.2.0" + ], + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==" + }, + { + "name": "check-error", + "version": "2.1.3", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==" + }, + { + "name": "cli-width", + "version": "4.1.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "ISC", + "dependencies": [], + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==" + }, + { + "name": "cliui", + "version": "8.0.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "ISC", + "dependencies": [ + "string-width@4.2.3", + "strip-ansi@6.0.1", + "wrap-ansi@7.0.0" + ], + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==" + }, + { + "name": "color-convert", + "version": "2.0.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "color-name@1.1.4" + ], + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==" + }, + { + "name": "color-name", + "version": "1.1.4", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + { + "name": "commander", + "version": "15.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-z67u4ZhzCL/Tydu1lJARtEZYWbWaN7oYLHbsuzocr6y4N6WZAagG3RQ4FW61V1/0+jImpj293XfrcYnd1qxtPg==" + }, + { + "name": "convert-source-map", + "version": "2.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + }, + { + "name": "cookie", + "version": "1.1.1", + "direct": false, + "scope": "production", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==" + }, + { + "name": "cross-spawn", + "version": "7.0.6", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "path-key@3.1.1", + "shebang-command@2.0.0", + "which@2.0.2" + ], + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==" + }, + { + "name": "css-tree", + "version": "3.2.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "mdn-data@2.27.1", + "source-map-js@1.2.1" + ], + "integrity": "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==" + }, + { + "name": "css.escape", + "version": "1.5.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==" + }, + { + "name": "csstype", + "version": "3.2.3", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==" + }, + { + "name": "data-urls", + "version": "7.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "whatwg-mimetype@5.0.0", + "whatwg-url@16.0.1" + ], + "integrity": "sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==" + }, + { + "name": "debug", + "version": "4.4.3", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "ms@2.1.3", + "supports-color@7.2.0" + ], + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==" + }, + { + "name": "decimal.js", + "version": "10.6.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==" + }, + { + "name": "deep-eql", + "version": "5.0.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==" + }, + { + "name": "deep-is", + "version": "0.1.4", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" + }, + { + "name": "default-browser-id", + "version": "5.0.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==" + }, + { + "name": "default-browser", + "version": "5.5.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "bundle-name@4.1.0", + "default-browser-id@5.0.1" + ], + "integrity": "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==" + }, + { + "name": "define-lazy-prop", + "version": "3.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==" + }, + { + "name": "dependency-cruiser", + "version": "18.1.0", + "direct": true, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "acorn-jsx-walk@2.0.0", + "acorn-jsx@5.3.2", + "acorn-loose@8.5.2", + "acorn-walk@8.3.5", + "acorn@8.17.0", + "commander@15.0.0", + "enhanced-resolve@5.24.2", + "ignore@7.0.6", + "interpret@3.1.1", + "is-installed-globally@1.0.0", + "json5@2.2.3", + "picomatch@4.0.5", + "prompts@2.4.2", + "rechoir@0.8.0", + "safe-regex@2.1.1", + "semver@7.8.5", + "tsconfig-paths-webpack-plugin@4.2.0", + "watskeburt@6.0.0" + ], + "integrity": "sha512-pbsH0gQ15BxXi97SCuMeVgsh8VzYpziGIVaMdnALbVu+TYjSZrW9/nOvsPU+NjHLmJSF9R1UijjoACq6Ne/ybQ==" + }, + { + "name": "dequal", + "version": "2.0.3", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==" + }, + { + "name": "detect-libc", + "version": "2.1.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "Apache-2.0", + "dependencies": [], + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==" + }, + { + "name": "doctrine", + "version": "3.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "Apache-2.0", + "dependencies": [ + "esutils@2.0.3" + ], + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==" + }, + { + "name": "dom-accessibility-api", + "version": "0.5.16", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==" + }, + { + "name": "dom-accessibility-api", + "version": "0.6.3", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==" + }, + { + "name": "electron-to-chromium", + "version": "1.5.396", + "direct": false, + "scope": "development", + "optional": false, + "license": "ISC", + "dependencies": [], + "integrity": "sha512-yHiw2Y3C3H9U6TMbOfoWK/BPreiOPXRfTWPBwQBoZG6/8TB6eOPnsy5oaRYuatR7Fw2SJ4kKforgufeo7fq0EQ==" + }, + { + "name": "emoji-regex", + "version": "8.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + { + "name": "empathic", + "version": "2.0.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-YGRs8knHhKHVShLkFET/rWAU8kmHbOV5LwN938RHI0pljAJ1Gf6SzXsSmRaEzcXTtOOmVqJ5+WtQPL5uigY50Q==" + }, + { + "name": "enhanced-resolve", + "version": "5.24.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "graceful-fs@4.2.11", + "tapable@2.3.3" + ], + "integrity": "sha512-rpsZEGT1jFuve6QlpyRp9ckQ+kN61hvF9BzCPyMdaKTm8UJce96KBn3sorXOFXlzjPrs3Vc4T1NsSroZ3PxlFw==" + }, + { + "name": "entities", + "version": "8.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "BSD-2-Clause", + "dependencies": [], + "integrity": "sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==" + }, + { + "name": "es-errors", + "version": "1.3.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" + }, + { + "name": "es-module-lexer", + "version": "2.3.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==" + }, + { + "name": "esbuild", + "version": "0.28.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@esbuild/aix-ppc64@0.28.1", + "@esbuild/android-arm64@0.28.1", + "@esbuild/android-arm@0.28.1", + "@esbuild/android-x64@0.28.1", + "@esbuild/darwin-arm64@0.28.1", + "@esbuild/darwin-x64@0.28.1", + "@esbuild/freebsd-arm64@0.28.1", + "@esbuild/freebsd-x64@0.28.1", + "@esbuild/linux-arm64@0.28.1", + "@esbuild/linux-arm@0.28.1", + "@esbuild/linux-ia32@0.28.1", + "@esbuild/linux-loong64@0.28.1", + "@esbuild/linux-mips64el@0.28.1", + "@esbuild/linux-ppc64@0.28.1", + "@esbuild/linux-riscv64@0.28.1", + "@esbuild/linux-s390x@0.28.1", + "@esbuild/linux-x64@0.28.1", + "@esbuild/netbsd-arm64@0.28.1", + "@esbuild/netbsd-x64@0.28.1", + "@esbuild/openbsd-arm64@0.28.1", + "@esbuild/openbsd-x64@0.28.1", + "@esbuild/openharmony-arm64@0.28.1", + "@esbuild/sunos-x64@0.28.1", + "@esbuild/win32-arm64@0.28.1", + "@esbuild/win32-ia32@0.28.1", + "@esbuild/win32-x64@0.28.1" + ], + "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==" + }, + { + "name": "escalade", + "version": "3.2.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==" + }, + { + "name": "escape-string-regexp", + "version": "4.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" + }, + { + "name": "eslint-plugin-react-hooks", + "version": "7.1.1", + "direct": true, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@babel/core@7.29.7", + "@babel/parser@7.29.7", + "eslint@10.8.0", + "hermes-parser@0.25.1", + "zod-validation-error@4.0.2", + "zod@4.4.3" + ], + "integrity": "sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==" + }, + { + "name": "eslint-scope", + "version": "9.1.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "BSD-2-Clause", + "dependencies": [ + "@types/esrecurse@4.3.1", + "@types/estree@1.0.9", + "esrecurse@4.3.0", + "estraverse@5.3.0" + ], + "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==" + }, + { + "name": "eslint-visitor-keys", + "version": "3.4.3", + "direct": false, + "scope": "development", + "optional": false, + "license": "Apache-2.0", + "dependencies": [], + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==" + }, + { + "name": "eslint-visitor-keys", + "version": "5.0.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "Apache-2.0", + "dependencies": [], + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==" + }, + { + "name": "eslint", + "version": "10.8.0", + "direct": true, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@eslint-community/eslint-utils@4.10.1", + "@eslint-community/regexpp@4.12.2", + "@eslint/config-array@0.23.5", + "@eslint/config-helpers@0.7.0", + "@eslint/core@1.2.1", + "@eslint/plugin-kit@0.7.2", + "@humanfs/node@0.16.8", + "@humanwhocodes/module-importer@1.0.1", + "@humanwhocodes/retry@0.4.3", + "@types/estree@1.0.9", + "ajv@6.15.0", + "cross-spawn@7.0.6", + "debug@4.4.3", + "escape-string-regexp@4.0.0", + "eslint-scope@9.1.2", + "eslint-visitor-keys@5.0.1", + "espree@11.2.0", + "esquery@1.7.0", + "esutils@2.0.3", + "fast-deep-equal@3.1.3", + "file-entry-cache@8.0.0", + "find-up@5.0.0", + "glob-parent@6.0.2", + "ignore@5.3.2", + "imurmurhash@0.1.4", + "is-glob@4.0.3", + "jiti@2.7.0", + "json-stable-stringify-without-jsonify@1.0.1", + "minimatch@10.2.5", + "natural-compare@1.4.0", + "optionator@0.9.4" + ], + "integrity": "sha512-nuKKvN+oIBO0koN7Tm7dlkmnkc21mtt0QJLwAKzjLq14y6lRTdVG36MZHJ8eQHwdJMwZbQNMlPOYedMq/oVJvQ==" + }, + { + "name": "espree", + "version": "11.2.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "BSD-2-Clause", + "dependencies": [ + "acorn-jsx@5.3.2", + "acorn@8.17.0", + "eslint-visitor-keys@5.0.1" + ], + "integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==" + }, + { + "name": "esprima", + "version": "4.0.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "BSD-2-Clause", + "dependencies": [], + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + }, + { + "name": "esquery", + "version": "1.7.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "BSD-3-Clause", + "dependencies": [ + "estraverse@5.3.0" + ], + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==" + }, + { + "name": "esrecurse", + "version": "4.3.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "BSD-2-Clause", + "dependencies": [ + "estraverse@5.3.0" + ], + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==" + }, + { + "name": "estraverse", + "version": "5.3.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "BSD-2-Clause", + "dependencies": [], + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" + }, + { + "name": "estree-walker", + "version": "2.0.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + }, + { + "name": "estree-walker", + "version": "3.0.3", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@types/estree@1.0.9" + ], + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==" + }, + { + "name": "esutils", + "version": "2.0.3", + "direct": false, + "scope": "development", + "optional": false, + "license": "BSD-2-Clause", + "dependencies": [], + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" + }, + { + "name": "expect-type", + "version": "1.4.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "Apache-2.0", + "dependencies": [], + "integrity": "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==" + }, + { + "name": "fast-deep-equal", + "version": "3.1.3", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + { + "name": "fast-json-stable-stringify", + "version": "2.1.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + { + "name": "fast-levenshtein", + "version": "2.0.6", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" + }, + { + "name": "fast-string-truncated-width", + "version": "3.0.3", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-0jjjIEL6+0jag3l2XWWizO64/aZVtpiGE3t0Zgqxv0DPuxiMjvB3M24fCyhZUO4KomJQPj3LTSUnDP3GpdwC0g==" + }, + { + "name": "fast-string-width", + "version": "3.0.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "fast-string-truncated-width@3.0.3" + ], + "integrity": "sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg==" + }, + { + "name": "fast-wrap-ansi", + "version": "0.2.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "fast-string-width@3.0.2" + ], + "integrity": "sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q==" + }, + { + "name": "fdir", + "version": "6.5.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "picomatch@4.0.5" + ], + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==" + }, + { + "name": "file-entry-cache", + "version": "8.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "flat-cache@4.0.1" + ], + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==" + }, + { + "name": "find-up", + "version": "5.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "locate-path@6.0.0", + "path-exists@4.0.0" + ], + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==" + }, + { + "name": "flat-cache", + "version": "4.0.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "flatted@3.4.3", + "keyv@4.5.4" + ], + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==" + }, + { + "name": "flatted", + "version": "3.4.3", + "direct": false, + "scope": "development", + "optional": false, + "license": "ISC", + "dependencies": [], + "integrity": "sha512-/zipXxyO6rGvuNGDiULY9MvEGSkb2gaG4GGH4ygMi0ZZzyMHdUZBmntJmx5x1G2VuPytCwGN4xsJP6cw+sK+vQ==" + }, + { + "name": "fsevents", + "version": "2.3.2", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==" + }, + { + "name": "fsevents", + "version": "2.3.3", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==" + }, + { + "name": "function-bind", + "version": "1.1.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" + }, + { + "name": "gensync", + "version": "1.0.0-beta.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" + }, + { + "name": "get-caller-file", + "version": "2.0.5", + "direct": false, + "scope": "development", + "optional": false, + "license": "ISC", + "dependencies": [], + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + }, + { + "name": "glob-parent", + "version": "6.0.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "ISC", + "dependencies": [ + "is-glob@4.0.3" + ], + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==" + }, + { + "name": "glob", + "version": "13.0.6", + "direct": false, + "scope": "development", + "optional": false, + "license": "BlueOak-1.0.0", + "dependencies": [ + "minimatch@10.2.5", + "minipass@7.1.3", + "path-scurry@2.0.2" + ], + "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==" + }, + { + "name": "global-directory", + "version": "4.0.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "ini@4.1.1" + ], + "integrity": "sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==" + }, + { + "name": "globals", + "version": "17.7.0", + "direct": true, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-Czmyns5dUsq4seFBR/Kdydhmo8y9kC79hiSkPn0YcGtNnYWnrgt0vjrSjx9tspoDGWm2CMarffRuLjM4xUz8xg==" + }, + { + "name": "graceful-fs", + "version": "4.2.11", + "direct": false, + "scope": "development", + "optional": false, + "license": "ISC", + "dependencies": [], + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + { + "name": "graphql", + "version": "16.14.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-Chq1s4CY7jmh8gO2qvLIJyfCDIN+EHLFW/9iShnp1z8FjBQMoodWP1kDC36VAMXXIvAjj4ARa7ntfAV2BrjsbA==" + }, + { + "name": "has-flag", + "version": "4.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + { + "name": "hasown", + "version": "2.0.4", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "function-bind@1.1.2" + ], + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==" + }, + { + "name": "headers-polyfill", + "version": "5.0.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@types/set-cookie-parser@2.4.10", + "set-cookie-parser@3.1.2" + ], + "integrity": "sha512-1TJ6Fih/b8h5TIcv+1+Hw0PDQWJTKDKzFZzcKOiW1wJza3XoAQlkCuXLbymPYB8+ZQyw8mHvdw560e8zVFIWyA==" + }, + { + "name": "hermes-estree", + "version": "0.25.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==" + }, + { + "name": "hermes-parser", + "version": "0.25.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "hermes-estree@0.25.1" + ], + "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==" + }, + { + "name": "html-encoding-sniffer", + "version": "6.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@exodus/bytes@1.15.1" + ], + "integrity": "sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==" + }, + { + "name": "html-escaper", + "version": "2.0.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==" + }, + { + "name": "ignore", + "version": "5.3.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==" + }, + { + "name": "ignore", + "version": "7.0.6", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==" + }, + { + "name": "import-meta-resolve", + "version": "4.2.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==" + }, + { + "name": "imurmurhash", + "version": "0.1.4", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==" + }, + { + "name": "indent-string", + "version": "4.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==" + }, + { + "name": "ini", + "version": "4.1.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "ISC", + "dependencies": [], + "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==" + }, + { + "name": "interpret", + "version": "3.1.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==" + }, + { + "name": "is-core-module", + "version": "2.16.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "hasown@2.0.4" + ], + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==" + }, + { + "name": "is-docker", + "version": "3.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==" + }, + { + "name": "is-extglob", + "version": "2.1.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" + }, + { + "name": "is-fullwidth-code-point", + "version": "3.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + { + "name": "is-glob", + "version": "4.0.3", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "is-extglob@2.1.1" + ], + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==" + }, + { + "name": "is-inside-container", + "version": "1.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "is-docker@3.0.0" + ], + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==" + }, + { + "name": "is-installed-globally", + "version": "1.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "global-directory@4.0.1", + "is-path-inside@4.0.0" + ], + "integrity": "sha512-K55T22lfpQ63N4KEN57jZUAaAYqYHEe8veb/TycJRk9DdSCLLcovXz/mL6mOnhQaZsQGwPhuFopdQIlqGSEjiQ==" + }, + { + "name": "is-node-process", + "version": "1.2.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==" + }, + { + "name": "is-path-inside", + "version": "4.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==" + }, + { + "name": "is-potential-custom-element-name", + "version": "1.0.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==" + }, + { + "name": "is-wsl", + "version": "3.1.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "is-inside-container@1.0.0" + ], + "integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==" + }, + { + "name": "isexe", + "version": "2.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "ISC", + "dependencies": [], + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + { + "name": "istanbul-lib-coverage", + "version": "3.2.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "BSD-3-Clause", + "dependencies": [], + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==" + }, + { + "name": "istanbul-lib-report", + "version": "3.0.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "BSD-3-Clause", + "dependencies": [ + "istanbul-lib-coverage@3.2.2", + "make-dir@4.0.0", + "supports-color@7.2.0" + ], + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==" + }, + { + "name": "istanbul-reports", + "version": "3.2.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "BSD-3-Clause", + "dependencies": [ + "html-escaper@2.0.2", + "istanbul-lib-report@3.0.1" + ], + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==" + }, + { + "name": "jiti", + "version": "2.7.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==" + }, + { + "name": "js-tokens", + "version": "10.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==" + }, + { + "name": "js-tokens", + "version": "4.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + { + "name": "jsdom", + "version": "29.1.1", + "direct": true, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@asamuzakjp/css-color@5.1.11", + "@asamuzakjp/dom-selector@7.1.1", + "@bramus/specificity@2.4.2", + "@csstools/css-syntax-patches-for-csstree@1.1.7", + "@exodus/bytes@1.15.1", + "css-tree@3.2.1", + "data-urls@7.0.0", + "decimal.js@10.6.0", + "html-encoding-sniffer@6.0.0", + "is-potential-custom-element-name@1.0.1", + "lru-cache@11.5.2", + "parse5@8.0.1", + "saxes@6.0.0", + "symbol-tree@3.2.4", + "tough-cookie@6.0.2", + "undici@7.28.0", + "w3c-xmlserializer@5.0.0", + "webidl-conversions@8.0.1", + "whatwg-mimetype@5.0.0", + "whatwg-url@16.0.1", + "xml-name-validator@5.0.0" + ], + "integrity": "sha512-ECi4Fi2f7BdJtUKTflYRTiaMxIB0O6zfR1fX0GXpUrf6flp8QIYn1UT20YQqdSOfk2dfkCwS8LAFoJDEppNK5Q==" + }, + { + "name": "jsesc", + "version": "3.1.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==" + }, + { + "name": "json-buffer", + "version": "3.0.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" + }, + { + "name": "json-schema-traverse", + "version": "0.4.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + { + "name": "json-stable-stringify-without-jsonify", + "version": "1.0.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" + }, + { + "name": "json5", + "version": "2.2.3", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" + }, + { + "name": "jsonc-parser", + "version": "3.3.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==" + }, + { + "name": "keyv", + "version": "4.5.4", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "json-buffer@3.0.1" + ], + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==" + }, + { + "name": "kleur", + "version": "3.0.3", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==" + }, + { + "name": "levn", + "version": "0.4.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "prelude-ls@1.2.1", + "type-check@0.4.0" + ], + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==" + }, + { + "name": "lightningcss-android-arm64", + "version": "1.32.0", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==" + }, + { + "name": "lightningcss-android-arm64", + "version": "1.33.0", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==" + }, + { + "name": "lightningcss-darwin-arm64", + "version": "1.32.0", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==" + }, + { + "name": "lightningcss-darwin-arm64", + "version": "1.33.0", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==" + }, + { + "name": "lightningcss-darwin-x64", + "version": "1.32.0", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==" + }, + { + "name": "lightningcss-darwin-x64", + "version": "1.33.0", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==" + }, + { + "name": "lightningcss-freebsd-x64", + "version": "1.32.0", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==" + }, + { + "name": "lightningcss-freebsd-x64", + "version": "1.33.0", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==" + }, + { + "name": "lightningcss-linux-arm-gnueabihf", + "version": "1.32.0", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==" + }, + { + "name": "lightningcss-linux-arm-gnueabihf", + "version": "1.33.0", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==" + }, + { + "name": "lightningcss-linux-arm64-gnu", + "version": "1.32.0", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==" + }, + { + "name": "lightningcss-linux-arm64-gnu", + "version": "1.33.0", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==" + }, + { + "name": "lightningcss-linux-arm64-musl", + "version": "1.32.0", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==" + }, + { + "name": "lightningcss-linux-arm64-musl", + "version": "1.33.0", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==" + }, + { + "name": "lightningcss-linux-x64-gnu", + "version": "1.32.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MPL-2.0", + "dependencies": [], + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==" + }, + { + "name": "lightningcss-linux-x64-gnu", + "version": "1.33.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MPL-2.0", + "dependencies": [], + "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==" + }, + { + "name": "lightningcss-linux-x64-musl", + "version": "1.32.0", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==" + }, + { + "name": "lightningcss-linux-x64-musl", + "version": "1.33.0", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==" + }, + { + "name": "lightningcss-win32-arm64-msvc", + "version": "1.32.0", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==" + }, + { + "name": "lightningcss-win32-arm64-msvc", + "version": "1.33.0", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==" + }, + { + "name": "lightningcss-win32-x64-msvc", + "version": "1.32.0", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==" + }, + { + "name": "lightningcss-win32-x64-msvc", + "version": "1.33.0", + "direct": false, + "scope": "development", + "optional": true, + "license": "NOASSERTION", + "dependencies": [], + "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==" + }, + { + "name": "lightningcss", + "version": "1.32.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MPL-2.0", + "dependencies": [ + "detect-libc@2.1.2", + "lightningcss-android-arm64@1.32.0", + "lightningcss-darwin-arm64@1.32.0", + "lightningcss-darwin-x64@1.32.0", + "lightningcss-freebsd-x64@1.32.0", + "lightningcss-linux-arm-gnueabihf@1.32.0", + "lightningcss-linux-arm64-gnu@1.32.0", + "lightningcss-linux-arm64-musl@1.32.0", + "lightningcss-linux-x64-gnu@1.32.0", + "lightningcss-linux-x64-musl@1.32.0", + "lightningcss-win32-arm64-msvc@1.32.0", + "lightningcss-win32-x64-msvc@1.32.0" + ], + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==" + }, + { + "name": "lightningcss", + "version": "1.33.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MPL-2.0", + "dependencies": [ + "detect-libc@2.1.2", + "lightningcss-android-arm64@1.33.0", + "lightningcss-darwin-arm64@1.33.0", + "lightningcss-darwin-x64@1.33.0", + "lightningcss-freebsd-x64@1.33.0", + "lightningcss-linux-arm-gnueabihf@1.33.0", + "lightningcss-linux-arm64-gnu@1.33.0", + "lightningcss-linux-arm64-musl@1.33.0", + "lightningcss-linux-x64-gnu@1.33.0", + "lightningcss-linux-x64-musl@1.33.0", + "lightningcss-win32-arm64-msvc@1.33.0", + "lightningcss-win32-x64-msvc@1.33.0" + ], + "integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==" + }, + { + "name": "locate-path", + "version": "6.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "p-locate@5.0.0" + ], + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==" + }, + { + "name": "loupe", + "version": "3.2.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==" + }, + { + "name": "lru-cache", + "version": "11.5.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "BlueOak-1.0.0", + "dependencies": [], + "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==" + }, + { + "name": "lru-cache", + "version": "5.1.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "ISC", + "dependencies": [ + "yallist@3.1.1" + ], + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==" + }, + { + "name": "lucide-react", + "version": "1.25.0", + "direct": true, + "scope": "production", + "optional": false, + "license": "ISC", + "dependencies": [ + "react@19.2.8" + ], + "integrity": "sha512-/mdJTRbiwcLOQ1NZZK1amZF9rIZyvO18D6r9TngE6TG1NmqHgFuT4eE7Xrkm9UsXMbBJD1NlfwHVltCDWHrOTw==" + }, + { + "name": "lz-string", + "version": "1.5.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==" + }, + { + "name": "magic-string", + "version": "0.30.21", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@jridgewell/sourcemap-codec@1.5.5" + ], + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==" + }, + { + "name": "magicast", + "version": "0.5.3", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@babel/parser@7.29.7", + "@babel/types@7.29.7", + "source-map-js@1.2.1" + ], + "integrity": "sha512-pVKE4UdSQ7DvHzivsCIFx2BJn1mHG6KsyrFcaxFx6tONdneEuThrDx0Cj3AMg58KyN4pzYT+LHOotxDQDjNvkw==" + }, + { + "name": "make-dir", + "version": "4.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "semver@7.8.5" + ], + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==" + }, + { + "name": "mdn-data", + "version": "2.27.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "CC0-1.0", + "dependencies": [], + "integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==" + }, + { + "name": "min-indent", + "version": "1.0.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==" + }, + { + "name": "minimatch", + "version": "10.2.5", + "direct": false, + "scope": "development", + "optional": false, + "license": "BlueOak-1.0.0", + "dependencies": [ + "brace-expansion@5.0.8" + ], + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==" + }, + { + "name": "minimist", + "version": "1.2.8", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + { + "name": "minipass", + "version": "7.1.3", + "direct": false, + "scope": "development", + "optional": false, + "license": "BlueOak-1.0.0", + "dependencies": [], + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==" + }, + { + "name": "ms", + "version": "2.1.3", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + { + "name": "msw", + "version": "2.15.0", + "direct": true, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@inquirer/confirm@6.1.1", + "@mswjs/interceptors@0.41.9", + "@open-draft/deferred-promise@3.0.0", + "@types/statuses@2.0.6", + "cookie@1.1.1", + "graphql@16.14.2", + "headers-polyfill@5.0.1", + "is-node-process@1.2.0", + "outvariant@1.4.3", + "path-to-regexp@6.3.0", + "picocolors@1.1.1", + "rettime@0.11.11", + "statuses@2.0.2", + "strict-event-emitter@0.5.1", + "tough-cookie@6.0.2", + "type-fest@5.8.0", + "typescript@7.0.2", + "until-async@3.0.2", + "yargs@17.7.3" + ], + "integrity": "sha512-2wQAmKkQKxRuXvYJxVhPGG0wZNBQyD06oJvxqw90XqLvptdqxdlHrFUfEteKkpaNORX3Xzc+HtEl/q0nfmN2wQ==" + }, + { + "name": "mute-stream", + "version": "3.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "ISC", + "dependencies": [], + "integrity": "sha512-dkEJPVvun4FryqBmZ5KhDo0K9iDXAwn08tMLDinNdRBNPcYEDiWYysLcc6k3mjTMlbP9KyylvRpd4wFtwrT9rw==" + }, + { + "name": "nanoid", + "version": "3.3.16", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==" + }, + { + "name": "natural-compare", + "version": "1.4.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" + }, + { + "name": "node-releases", + "version": "2.0.51", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-wRNIrw4DmVLKQlbgOMdkMx27Wrpzes2hh5Jtbi2bjPd+4wJstWIqP5A+lscnqbm0xxmT5Bpg8Lec5ItEBwx6BQ==" + }, + { + "name": "obug", + "version": "2.1.4", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==" + }, + { + "name": "open", + "version": "10.2.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "default-browser@5.5.0", + "define-lazy-prop@3.0.0", + "is-inside-container@1.0.0", + "wsl-utils@0.1.0" + ], + "integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==" + }, + { + "name": "optionator", + "version": "0.9.4", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "deep-is@0.1.4", + "fast-levenshtein@2.0.6", + "levn@0.4.1", + "prelude-ls@1.2.1", + "type-check@0.4.0", + "word-wrap@1.2.5" + ], + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==" + }, + { + "name": "outvariant", + "version": "1.4.3", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==" + }, + { + "name": "oxc-parser", + "version": "0.127.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@oxc-parser/binding-android-arm-eabi@0.127.0", + "@oxc-parser/binding-android-arm64@0.127.0", + "@oxc-parser/binding-darwin-arm64@0.127.0", + "@oxc-parser/binding-darwin-x64@0.127.0", + "@oxc-parser/binding-freebsd-x64@0.127.0", + "@oxc-parser/binding-linux-arm-gnueabihf@0.127.0", + "@oxc-parser/binding-linux-arm-musleabihf@0.127.0", + "@oxc-parser/binding-linux-arm64-gnu@0.127.0", + "@oxc-parser/binding-linux-arm64-musl@0.127.0", + "@oxc-parser/binding-linux-ppc64-gnu@0.127.0", + "@oxc-parser/binding-linux-riscv64-gnu@0.127.0", + "@oxc-parser/binding-linux-riscv64-musl@0.127.0", + "@oxc-parser/binding-linux-s390x-gnu@0.127.0", + "@oxc-parser/binding-linux-x64-gnu@0.127.0", + "@oxc-parser/binding-linux-x64-musl@0.127.0", + "@oxc-parser/binding-openharmony-arm64@0.127.0", + "@oxc-parser/binding-wasm32-wasi@0.127.0", + "@oxc-parser/binding-win32-arm64-msvc@0.127.0", + "@oxc-parser/binding-win32-ia32-msvc@0.127.0", + "@oxc-parser/binding-win32-x64-msvc@0.127.0", + "@oxc-project/types@0.127.0" + ], + "integrity": "sha512-bkgD4qHlN7WxLdX8bLXdaU54TtQtAIg/ZBAfm0aje/mo3MRDo3P0hZSgr4U7O3xfX+fQmR5AP04JS/TGcZLcFA==" + }, + { + "name": "oxc-resolver", + "version": "11.24.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@oxc-resolver/binding-android-arm-eabi@11.24.2", + "@oxc-resolver/binding-android-arm64@11.24.2", + "@oxc-resolver/binding-darwin-arm64@11.24.2", + "@oxc-resolver/binding-darwin-x64@11.24.2", + "@oxc-resolver/binding-freebsd-x64@11.24.2", + "@oxc-resolver/binding-linux-arm-gnueabihf@11.24.2", + "@oxc-resolver/binding-linux-arm-musleabihf@11.24.2", + "@oxc-resolver/binding-linux-arm64-gnu@11.24.2", + "@oxc-resolver/binding-linux-arm64-musl@11.24.2", + "@oxc-resolver/binding-linux-ppc64-gnu@11.24.2", + "@oxc-resolver/binding-linux-riscv64-gnu@11.24.2", + "@oxc-resolver/binding-linux-riscv64-musl@11.24.2", + "@oxc-resolver/binding-linux-s390x-gnu@11.24.2", + "@oxc-resolver/binding-linux-x64-gnu@11.24.2", + "@oxc-resolver/binding-linux-x64-musl@11.24.2", + "@oxc-resolver/binding-openharmony-arm64@11.24.2", + "@oxc-resolver/binding-wasm32-wasi@11.24.2", + "@oxc-resolver/binding-win32-arm64-msvc@11.24.2", + "@oxc-resolver/binding-win32-x64-msvc@11.24.2" + ], + "integrity": "sha512-FY91FiDBj7ls5MsFS9jN3tjz2o0/zsdSsymlakySaBwVJZorHhkWyICLZMKxlu1R9vYo+sd3z1jwb4J8x7bNDw==" + }, + { + "name": "p-limit", + "version": "3.1.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "yocto-queue@0.1.0" + ], + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==" + }, + { + "name": "p-locate", + "version": "5.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "p-limit@3.1.0" + ], + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==" + }, + { + "name": "parse5", + "version": "8.0.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "entities@8.0.0" + ], + "integrity": "sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==" + }, + { + "name": "path-exists", + "version": "4.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" + }, + { + "name": "path-key", + "version": "3.1.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + }, + { + "name": "path-parse", + "version": "1.0.7", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + { + "name": "path-scurry", + "version": "2.0.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "BlueOak-1.0.0", + "dependencies": [ + "lru-cache@11.5.2", + "minipass@7.1.3" + ], + "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==" + }, + { + "name": "path-to-regexp", + "version": "6.3.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==" + }, + { + "name": "pathe", + "version": "2.0.3", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==" + }, + { + "name": "pathval", + "version": "2.0.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==" + }, + { + "name": "picocolors", + "version": "1.1.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "ISC", + "dependencies": [], + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + }, + { + "name": "picomatch", + "version": "4.0.5", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==" + }, + { + "name": "playwright-core", + "version": "1.62.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "Apache-2.0", + "dependencies": [], + "integrity": "sha512-nsNRyq0r2zsG8AcRHWknc9QRA5XCueC7gWMrs+Gx2tlZn9hcl8zudfh00lhJPY1DE7NmZ6bDsT9g2yey8mXljA==" + }, + { + "name": "playwright", + "version": "1.62.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "Apache-2.0", + "dependencies": [ + "fsevents@2.3.2", + "playwright-core@1.62.0" + ], + "integrity": "sha512-Z14dG305dgaLu6foB1TXQagFiW8JfSUIUaUuPaKQ6NtBPKF1P/qXcqfh6c6K/icPqdy37JmjbiBXf6JNg6Sylw==" + }, + { + "name": "postcss", + "version": "8.5.22", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "nanoid@3.3.16", + "picocolors@1.1.1", + "source-map-js@1.2.1" + ], + "integrity": "sha512-KBDEIpLrvpv16pp3K0Fw+UCoZfopFjjgeB+0tA/aaThfEE74kKDLrgg603YvOWJyg3+WYtyq3xYsQWsIyZlPqQ==" + }, + { + "name": "prelude-ls", + "version": "1.2.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==" + }, + { + "name": "pretty-format", + "version": "27.5.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "ansi-regex@5.0.1", + "ansi-styles@5.2.0", + "react-is@17.0.2" + ], + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==" + }, + { + "name": "prompts", + "version": "2.4.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "kleur@3.0.3", + "sisteransi@1.0.5" + ], + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==" + }, + { + "name": "punycode", + "version": "2.3.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==" + }, + { + "name": "react-docgen-typescript", + "version": "2.4.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "typescript@7.0.2" + ], + "integrity": "sha512-ZtAp5XTO5HRzQctjPU0ybY0RRCQO19X/8fxn3w7y2VVTUbGHDKULPTL4ky3vB05euSgG5NpALhEhDPvQ56wvXg==" + }, + { + "name": "react-docgen", + "version": "8.0.3", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@babel/core@7.29.7", + "@babel/traverse@7.29.7", + "@babel/types@7.29.7", + "@types/babel__core@7.20.5", + "@types/babel__traverse@7.28.0", + "@types/doctrine@0.0.9", + "@types/resolve@1.20.6", + "doctrine@3.0.0", + "resolve@1.22.12", + "strip-indent@4.1.1" + ], + "integrity": "sha512-aEZ9qP+/M+58x2qgfSFEWH1BxLyHe5+qkLNJOZQb5iGS017jpbRnoKhNRrXPeA6RfBrZO5wZrT9DMC1UqE1f1w==" + }, + { + "name": "react-dom", + "version": "19.2.8", + "direct": true, + "scope": "production", + "optional": false, + "license": "MIT", + "dependencies": [ + "react@19.2.8", + "scheduler@0.27.0" + ], + "integrity": "sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==" + }, + { + "name": "react-is", + "version": "17.0.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + { + "name": "react-router-dom", + "version": "7.18.1", + "direct": true, + "scope": "production", + "optional": false, + "license": "MIT", + "dependencies": [ + "react-dom@19.2.8", + "react-router@7.18.1", + "react@19.2.8" + ], + "integrity": "sha512-KaZh+X/6UtEp28x51AUYZDMg9NGoz2ja3dNHa+ta/tk40vCzKhQ/RypCWBMLbmDr6//E24Vv5uPsrqXFozdkAg==" + }, + { + "name": "react-router", + "version": "7.18.1", + "direct": false, + "scope": "production", + "optional": false, + "license": "MIT", + "dependencies": [ + "cookie@1.1.1", + "react-dom@19.2.8", + "react@19.2.8", + "set-cookie-parser@2.7.2" + ], + "integrity": "sha512-GDLgg3i3uM0aeJO3Fm+TCS+sDQ7gu12T6x0qdTEzcwqEfleci7JwugVNIF3U//0FWKnJT7ptG+20B2jfDqnZAg==" + }, + { + "name": "react", + "version": "19.2.8", + "direct": true, + "scope": "production", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==" + }, + { + "name": "recast", + "version": "0.23.12", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "ast-types@0.16.1", + "esprima@4.0.1", + "source-map@0.6.1", + "tiny-invariant@1.3.3", + "tslib@2.8.1" + ], + "integrity": "sha512-dEWRjcINDu/F4l2dYx57ugBtD7HV9KXESyxhzw/MqWLeglJrsjJKqACPyUPg+6AF8mIgm+Zi0dZ3ACoIg+QtpA==" + }, + { + "name": "rechoir", + "version": "0.8.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "resolve@1.22.12" + ], + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==" + }, + { + "name": "redent", + "version": "3.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "indent-string@4.0.0", + "strip-indent@3.0.0" + ], + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==" + }, + { + "name": "regexp-tree", + "version": "0.1.27", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==" + }, + { + "name": "require-directory", + "version": "2.1.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" + }, + { + "name": "require-from-string", + "version": "2.0.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" + }, + { + "name": "resolve", + "version": "1.22.12", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "es-errors@1.3.0", + "is-core-module@2.16.2", + "path-parse@1.0.7", + "supports-preserve-symlinks-flag@1.0.0" + ], + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==" + }, + { + "name": "rettime", + "version": "0.11.11", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-ILJRqVWBCTlg9r42fFgwVZx1gnFAcQF8mRoMkbgQfIrjEDf9nbBFDFx00oloOa+Q869FUtaYDXZvEfnecQSCoQ==" + }, + { + "name": "rolldown", + "version": "1.1.5", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@oxc-project/types@0.139.0", + "@rolldown/binding-android-arm64@1.1.5", + "@rolldown/binding-darwin-arm64@1.1.5", + "@rolldown/binding-darwin-x64@1.1.5", + "@rolldown/binding-freebsd-x64@1.1.5", + "@rolldown/binding-linux-arm-gnueabihf@1.1.5", + "@rolldown/binding-linux-arm64-gnu@1.1.5", + "@rolldown/binding-linux-arm64-musl@1.1.5", + "@rolldown/binding-linux-ppc64-gnu@1.1.5", + "@rolldown/binding-linux-s390x-gnu@1.1.5", + "@rolldown/binding-linux-x64-gnu@1.1.5", + "@rolldown/binding-linux-x64-musl@1.1.5", + "@rolldown/binding-openharmony-arm64@1.1.5", + "@rolldown/binding-wasm32-wasi@1.1.5", + "@rolldown/binding-win32-arm64-msvc@1.1.5", + "@rolldown/binding-win32-x64-msvc@1.1.5", + "@rolldown/pluginutils@1.0.1" + ], + "integrity": "sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA==" + }, + { + "name": "run-applescript", + "version": "7.1.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==" + }, + { + "name": "safe-regex", + "version": "2.1.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "regexp-tree@0.1.27" + ], + "integrity": "sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A==" + }, + { + "name": "saxes", + "version": "6.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "ISC", + "dependencies": [ + "xmlchars@2.2.0" + ], + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==" + }, + { + "name": "scheduler", + "version": "0.27.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==" + }, + { + "name": "semver", + "version": "6.3.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "ISC", + "dependencies": [], + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + }, + { + "name": "semver", + "version": "7.8.5", + "direct": false, + "scope": "development", + "optional": false, + "license": "ISC", + "dependencies": [], + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==" + }, + { + "name": "set-cookie-parser", + "version": "2.7.2", + "direct": false, + "scope": "production", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==" + }, + { + "name": "set-cookie-parser", + "version": "3.1.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-5/r/lTwbJ3zQ+qwdUFZYeRNqda7P5HD8zQKqlSjdGt1/S0cjLAphHusj4Y58ahDtWn/g32xrIS58/ikOvwl0Lw==" + }, + { + "name": "shebang-command", + "version": "2.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "shebang-regex@3.0.0" + ], + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==" + }, + { + "name": "shebang-regex", + "version": "3.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + }, + { + "name": "siginfo", + "version": "2.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "ISC", + "dependencies": [], + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==" + }, + { + "name": "signal-exit", + "version": "4.1.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "ISC", + "dependencies": [], + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==" + }, + { + "name": "sisteransi", + "version": "1.0.5", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" + }, + { + "name": "source-map-js", + "version": "1.2.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "BSD-3-Clause", + "dependencies": [], + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==" + }, + { + "name": "source-map", + "version": "0.6.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "BSD-3-Clause", + "dependencies": [], + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + { + "name": "stackback", + "version": "0.0.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==" + }, + { + "name": "statuses", + "version": "2.0.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==" + }, + { + "name": "std-env", + "version": "4.2.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==" + }, + { + "name": "storybook", + "version": "10.5.4", + "direct": true, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@storybook/global@5.0.0", + "@storybook/icons@2.1.0", + "@testing-library/dom@10.4.1", + "@testing-library/jest-dom@6.10.0", + "@testing-library/user-event@14.6.1", + "@types/react@19.2.8", + "@vitest/expect@3.2.4", + "@vitest/spy@3.2.4", + "@webcontainer/env@1.1.1", + "esbuild@0.28.1", + "jsonc-parser@3.3.1", + "open@10.2.0", + "oxc-parser@0.127.0", + "oxc-resolver@11.24.2", + "recast@0.23.12", + "semver@7.8.5", + "use-sync-external-store@1.6.0", + "ws@8.21.1" + ], + "integrity": "sha512-bmLxPsxVSPnbeiZqYQpozyNOiJXfk+pf7WfHZflvPkwT6Y+rvYz3Cj/D6H4Kf2jHpuDNiMXBKO3yawLN2OWirg==" + }, + { + "name": "strict-event-emitter", + "version": "0.5.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==" + }, + { + "name": "string-width", + "version": "4.2.3", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "emoji-regex@8.0.0", + "is-fullwidth-code-point@3.0.0", + "strip-ansi@6.0.1" + ], + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==" + }, + { + "name": "strip-ansi", + "version": "6.0.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "ansi-regex@5.0.1" + ], + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==" + }, + { + "name": "strip-bom", + "version": "3.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==" + }, + { + "name": "strip-indent", + "version": "3.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "min-indent@1.0.1" + ], + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==" + }, + { + "name": "strip-indent", + "version": "4.1.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-SlyRoSkdh1dYP0PzclLE7r0M9sgbFKKMFXpFRUMNuKhQSbC6VQIGzq3E0qsfvGJaUFJPGv6Ws1NZ/haTAjfbMA==" + }, + { + "name": "supports-color", + "version": "7.2.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "has-flag@4.0.0" + ], + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==" + }, + { + "name": "supports-preserve-symlinks-flag", + "version": "1.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" + }, + { + "name": "symbol-tree", + "version": "3.2.4", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" + }, + { + "name": "tagged-tag", + "version": "1.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==" + }, + { + "name": "tailwindcss", + "version": "4.3.3", + "direct": true, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==" + }, + { + "name": "tapable", + "version": "2.3.3", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==" + }, + { + "name": "tiny-invariant", + "version": "1.3.3", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==" + }, + { + "name": "tinybench", + "version": "2.9.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==" + }, + { + "name": "tinyexec", + "version": "1.2.4", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==" + }, + { + "name": "tinyglobby", + "version": "0.2.17", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "fdir@6.5.0", + "picomatch@4.0.5" + ], + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==" + }, + { + "name": "tinyrainbow", + "version": "2.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==" + }, + { + "name": "tinyrainbow", + "version": "3.1.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==" + }, + { + "name": "tinyspy", + "version": "4.0.4", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==" + }, + { + "name": "tldts-core", + "version": "7.4.9", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-DxKfPBI52p2msTEu7MPhdpdDTBhhVQg1a/8PjQckeyAvO13eMYElX545grIp6nnTGIMZlRvFZPvFhvI/WIz2Vg==" + }, + { + "name": "tldts", + "version": "7.4.9", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "tldts-core@7.4.9" + ], + "integrity": "sha512-3kZ8wQQ/k5DrChD4X4FVvr2D7E5uoRgAqkPyLpSCGUvqOvqu+JEdr3mwMUaVWb+vMHZaKhF5fp2PBigKsui7hA==" + }, + { + "name": "tough-cookie", + "version": "6.0.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "BSD-3-Clause", + "dependencies": [ + "tldts@7.4.9" + ], + "integrity": "sha512-exgYmnmL/sJpR3upZfXG5PoatXQii55xAiXGXzY+sROLZ/Y+SLcp9PgJNI9Vz37HpQ74WvDcLT8eqm+kV3FzrA==" + }, + { + "name": "tr46", + "version": "6.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "punycode@2.3.1" + ], + "integrity": "sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==" + }, + { + "name": "ts-dedent", + "version": "2.3.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-JfJeIHke7y2egdGGgRAvpCwYFUsHlM2gPcrVOxFkznt/4uzQ7HFmvE63iFHVLBJNDuyDOQgijDK/tXH/f6Msjg==" + }, + { + "name": "tsconfig-paths-webpack-plugin", + "version": "4.2.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "chalk@4.1.2", + "enhanced-resolve@5.24.2", + "tapable@2.3.3", + "tsconfig-paths@4.2.0" + ], + "integrity": "sha512-zbem3rfRS8BgeNK50Zz5SIQgXzLafiHjOwUAvk/38/o1jHn/V5QAgVUcz884or7WYcPaH3N2CIfUc2u0ul7UcA==" + }, + { + "name": "tsconfig-paths", + "version": "4.2.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "json5@2.2.3", + "minimist@1.2.8", + "strip-bom@3.0.0" + ], + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==" + }, + { + "name": "tslib", + "version": "2.8.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "0BSD", + "dependencies": [], + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + }, + { + "name": "type-check", + "version": "0.4.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "prelude-ls@1.2.1" + ], + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==" + }, + { + "name": "type-fest", + "version": "5.8.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "(MIT OR CC0-1.0)", + "dependencies": [ + "tagged-tag@1.0.0" + ], + "integrity": "sha512-YGYEVz3Fm5iy/AybuA0oyNFq7H4CgQNfRp/qfe8nurE1kuCeNm3/vfm9X4Mtl+qLyaKJUh5xrFZwogr41SMjYA==" + }, + { + "name": "typescript", + "version": "7.0.2", + "direct": true, + "scope": "development", + "optional": false, + "license": "Apache-2.0", + "dependencies": [ + "@typescript/typescript-aix-ppc64@7.0.2", + "@typescript/typescript-darwin-arm64@7.0.2", + "@typescript/typescript-darwin-x64@7.0.2", + "@typescript/typescript-freebsd-arm64@7.0.2", + "@typescript/typescript-freebsd-x64@7.0.2", + "@typescript/typescript-linux-arm64@7.0.2", + "@typescript/typescript-linux-arm@7.0.2", + "@typescript/typescript-linux-loong64@7.0.2", + "@typescript/typescript-linux-mips64el@7.0.2", + "@typescript/typescript-linux-ppc64@7.0.2", + "@typescript/typescript-linux-riscv64@7.0.2", + "@typescript/typescript-linux-s390x@7.0.2", + "@typescript/typescript-linux-x64@7.0.2", + "@typescript/typescript-netbsd-arm64@7.0.2", + "@typescript/typescript-netbsd-x64@7.0.2", + "@typescript/typescript-openbsd-arm64@7.0.2", + "@typescript/typescript-openbsd-x64@7.0.2", + "@typescript/typescript-sunos-x64@7.0.2", + "@typescript/typescript-win32-arm64@7.0.2", + "@typescript/typescript-win32-x64@7.0.2" + ], + "integrity": "sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==" + }, + { + "name": "undici-types", + "version": "7.18.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==" + }, + { + "name": "undici", + "version": "7.28.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==" + }, + { + "name": "unplugin", + "version": "2.3.11", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@jridgewell/remapping@2.3.5", + "acorn@8.17.0", + "picomatch@4.0.5", + "webpack-virtual-modules@0.6.2" + ], + "integrity": "sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww==" + }, + { + "name": "until-async", + "version": "3.0.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-IiSk4HlzAMqTUseHHe3VhIGyuFmN90zMTpD3Z3y8jeQbzLIq500MVM7Jq2vUAnTKAFPJrqwkzr6PoTcPhGcOiw==" + }, + { + "name": "update-browserslist-db", + "version": "1.2.3", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "browserslist@4.28.7", + "escalade@3.2.0", + "picocolors@1.1.1" + ], + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==" + }, + { + "name": "uri-js", + "version": "4.4.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "BSD-2-Clause", + "dependencies": [ + "punycode@2.3.1" + ], + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==" + }, + { + "name": "use-sync-external-store", + "version": "1.6.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "react@19.2.8" + ], + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==" + }, + { + "name": "vite", + "version": "8.1.5", + "direct": true, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@types/node@24.13.3", + "esbuild@0.28.1", + "fsevents@2.3.3", + "jiti@2.7.0", + "lightningcss@1.33.0", + "picomatch@4.0.5", + "postcss@8.5.22", + "rolldown@1.1.5", + "tinyglobby@0.2.17" + ], + "integrity": "sha512-7ULLwsCdYx/nRyrpiEwvqb5TFHrMVZyBt+rg/OAXT7rgj/z+DtTDyKFeLAdDkubDVDKD8jOsndmy7m55XcfUsw==" + }, + { + "name": "vitest", + "version": "4.1.10", + "direct": true, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@types/node@24.13.3", + "@vitest/coverage-v8@4.1.10", + "@vitest/expect@4.1.10", + "@vitest/mocker@4.1.10", + "@vitest/pretty-format@4.1.10", + "@vitest/runner@4.1.10", + "@vitest/snapshot@4.1.10", + "@vitest/spy@4.1.10", + "@vitest/utils@4.1.10", + "es-module-lexer@2.3.1", + "expect-type@1.4.0", + "jsdom@29.1.1", + "magic-string@0.30.21", + "obug@2.1.4", + "pathe@2.0.3", + "picomatch@4.0.5", + "std-env@4.2.0", + "tinybench@2.9.0", + "tinyexec@1.2.4", + "tinyglobby@0.2.17", + "tinyrainbow@3.1.0", + "vite@8.1.5", + "why-is-node-running@2.3.0" + ], + "integrity": "sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==" + }, + { + "name": "w3c-xmlserializer", + "version": "5.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "xml-name-validator@5.0.0" + ], + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==" + }, + { + "name": "watskeburt", + "version": "6.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-jfiuDABaxSkC71T6oZ3vCS99roYkSHm/+As+G0Dz8taAHQb+SJBvLEm5RlsgG71XdfAj3rv7eudUBTgwcQUPlQ==" + }, + { + "name": "webidl-conversions", + "version": "8.0.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "BSD-2-Clause", + "dependencies": [], + "integrity": "sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==" + }, + { + "name": "webpack-virtual-modules", + "version": "0.6.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==" + }, + { + "name": "whatwg-mimetype", + "version": "5.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==" + }, + { + "name": "whatwg-url", + "version": "16.0.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "@exodus/bytes@1.15.1", + "tr46@6.0.0", + "webidl-conversions@8.0.1" + ], + "integrity": "sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==" + }, + { + "name": "which", + "version": "2.0.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "ISC", + "dependencies": [ + "isexe@2.0.0" + ], + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==" + }, + { + "name": "why-is-node-running", + "version": "2.3.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "siginfo@2.0.0", + "stackback@0.0.2" + ], + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==" + }, + { + "name": "word-wrap", + "version": "1.2.5", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==" + }, + { + "name": "wrap-ansi", + "version": "7.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "ansi-styles@4.3.0", + "string-width@4.2.3", + "strip-ansi@6.0.1" + ], + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==" + }, + { + "name": "ws", + "version": "8.21.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw==" + }, + { + "name": "wsl-utils", + "version": "0.1.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "is-wsl@3.1.1" + ], + "integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==" + }, + { + "name": "xml-name-validator", + "version": "5.0.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "Apache-2.0", + "dependencies": [], + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==" + }, + { + "name": "xmlchars", + "version": "2.2.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" + }, + { + "name": "y18n", + "version": "5.0.8", + "direct": false, + "scope": "development", + "optional": false, + "license": "ISC", + "dependencies": [], + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" + }, + { + "name": "yallist", + "version": "3.1.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "ISC", + "dependencies": [], + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + { + "name": "yargs-parser", + "version": "21.1.1", + "direct": false, + "scope": "development", + "optional": false, + "license": "ISC", + "dependencies": [], + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==" + }, + { + "name": "yargs", + "version": "17.7.3", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "cliui@8.0.1", + "escalade@3.2.0", + "get-caller-file@2.0.5", + "require-directory@2.1.1", + "string-width@4.2.3", + "y18n@5.0.8", + "yargs-parser@21.1.1" + ], + "integrity": "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==" + }, + { + "name": "yocto-queue", + "version": "0.1.0", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" + }, + { + "name": "zod-validation-error", + "version": "4.0.2", + "direct": false, + "scope": "development", + "optional": false, + "license": "MIT", + "dependencies": [ + "zod@4.4.3" + ], + "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==" + }, + { + "name": "zod", + "version": "4.4.3", + "direct": true, + "scope": "production", + "optional": false, + "license": "MIT", + "dependencies": [], + "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==" + } + ] +} diff --git a/config/security/dependency-change-evidence.json b/config/security/dependency-change-evidence.json new file mode 100644 index 0000000..62d2c3c --- /dev/null +++ b/config/security/dependency-change-evidence.json @@ -0,0 +1,4 @@ +{ + "schemaVersion": 1, + "changes": [] +} diff --git a/config/security/dependency-policy.json b/config/security/dependency-policy.json new file mode 100644 index 0000000..acd24e4 --- /dev/null +++ b/config/security/dependency-policy.json @@ -0,0 +1,24 @@ +{ + "schemaVersion": 1, + "allowedLicenses": [ + "(MIT OR CC0-1.0)", + "0BSD", + "Apache-2.0", + "BSD-2-Clause", + "BSD-3-Clause", + "BlueOak-1.0.0", + "CC-BY-4.0", + "CC0-1.0", + "ISC", + "MIT", + "MIT-0", + "MPL-2.0" + ], + "deniedLicensePatterns": [ + "(^|\\s)AGPL", + "(^|\\s)GPL", + "SSPL", + "BUSL" + ], + "unknownLicensePolicy": "allow-only-unmaterialized-platform-optional" +} diff --git a/config/security/secret-scan-policy.json b/config/security/secret-scan-policy.json new file mode 100644 index 0000000..d680326 --- /dev/null +++ b/config/security/secret-scan-policy.json @@ -0,0 +1,30 @@ +{ + "schemaVersion": 1, + "trackedRoots": [ + "src", + "scripts", + "tests", + "config", + "public", + "schemas", + ".storybook", + "package.json", + "pnpm-lock.yaml", + "vite.config.js", + "vitest.config.js", + "playwright.config.js" + ], + "generatedRoots": ["dist", "artifacts/release"], + "excludedPaths": [ + "tests/fixtures/security/secret-detection/forbidden" + ], + "allowlist": [ + { + "path": "tests/fixtures/security/secret-detection/allowed/test-credentials.ts", + "ruleId": "assigned-secret", + "owner": "frontend-platform", + "reason": "Synthetic credential verifies the scoped test-only allowlist.", + "expiresAt": "2027-07-26T00:00:00.000Z" + } + ] +} diff --git a/config/security/vulnerability-exceptions.json b/config/security/vulnerability-exceptions.json new file mode 100644 index 0000000..f226765 --- /dev/null +++ b/config/security/vulnerability-exceptions.json @@ -0,0 +1,4 @@ +{ + "schemaVersion": 1, + "exceptions": [] +} diff --git a/config/security/vulnerability-policy.json b/config/security/vulnerability-policy.json new file mode 100644 index 0000000..6a6a4c7 --- /dev/null +++ b/config/security/vulnerability-policy.json @@ -0,0 +1,8 @@ +{ + "schemaVersion": 1, + "providerMode": "external-file", + "inputEnvironment": "VULNERABILITY_REPORT_PATH", + "blockAtSeverity": "high", + "allowedSeverities": ["unknown", "low", "moderate", "high", "critical"], + "missingProviderStatus": "FAIL_UNVERIFIED" +} diff --git a/docs/architecture/decisions/VD-09-supply-chain-evidence.md b/docs/architecture/decisions/VD-09-supply-chain-evidence.md new file mode 100644 index 0000000..f609ee2 --- /dev/null +++ b/docs/architecture/decisions/VD-09-supply-chain-evidence.md @@ -0,0 +1,103 @@ +# VD-09: 공급망 inventory, license, vulnerability, SBOM과 provenance + +- 상태: Accepted +- 결정일: 2026-07-26 +- 적용 브랜치: `feature-frontend-supply-chain-verification` +- 재검토: 조직 vulnerability scanner, signing/attestation provider와 dependency + exception 승인 체계가 선정될 때 + +## 배경 + +기존 release script는 `package.json`의 직접 dependency 이름과 버전, lockfile +전체 digest, `dist` checksum만 기록했다. 전이 dependency, 패키지별 integrity와 +license, 실제 baseline diff가 없었고 `highRiskUnreviewed: []`는 계산 결과가 아닌 +고정값이었다. secret scan도 `src`와 `dist`만 검사해 config, scripts, test와 +generated release metadata를 놓쳤다. + +반면 저장소에는 조직이 선택한 vulnerability source, severity exception 승인자, +signing identity와 attestation 저장소가 없다. 외부 provider가 없는 상태를 빈 +finding과 서명 성공으로 표현하면 local 검증과 release promotion을 혼동한다. + +## 결정 + +1. `pnpm-lock.yaml`의 모든 `packages` row와 `pnpm list --depth Infinity`의 실제 + graph를 결합해 직접/전이, production/development, required/platform-optional, + version, SHA-512 SRI, license와 dependency edge를 기록한다. +2. inventory row 수는 lockfile package row 수와 같아야 한다. 누락된 전이 + dependency, malformed integrity와 non-optional `NOASSERTION`은 local gate를 + 실패시킨다. +3. license는 설치된 package manifest에서 읽고 closed allow/deny policy로 + 검사한다. 현재 OS에 materialize되지 않은 platform optional만 + `NOASSERTION`과 그 이유를 명시적으로 허용한다. +4. 승인 dependency baseline과 approval digest를 보존하고 현재 lock inventory와 + actual add/remove/change/upgrade diff를 계산한다. 새 direct production + dependency는 owner와 서로 다른 reviewer, reason과 rollback evidence가 + 필요하다. +5. inventory를 CycloneDX 1.6 SBOM으로 투영한다. component 수, lockfile digest, + SRI, license와 dependency edge가 inventory와 일치해야 한다. +6. local in-toto/SLSA 형태 provenance statement는 source set, lockfile, SBOM과 + `dist` digest를 연결하되 `LOCAL_UNSIGNED`로 표시한다. 외부 attestation은 + provider, signer와 동일 dist subject digest가 있어야 한다. +7. vulnerability adapter는 `VULNERABILITY_REPORT_PATH`가 가리키는 + machine-readable provider report를 검증한다. report의 lock digest, provider, + severity와 exception owner/reviewer/reason/expiry가 유효해야 한다. +8. provider report가 없으면 local inventory/license/SBOM/coherence는 `PASS`, + promotion은 `FAIL_UNVERIFIED`다. 빈 finding을 만들어 vulnerability PASS로 + 표시하지 않는다. +9. secret scan은 source, scripts, tests, tracked config/schema, public, `dist`와 + generated release metadata를 검사한다. allowlist는 test path에만 허용하며 + owner, reason과 expiry가 필요하다. 발견한 secret 원문은 artifact에 쓰지 않고 + rule, path, line과 fingerprint만 남긴다. +10. `SOURCE_DATE_EPOCH`를 지원하고 같은 source/lock/config의 production build를 + 두 번 실행해 전체 dist digest 일치를 검증한 뒤 일반 build를 복원한다. + +## 실행 경계와 증적 + +```text +package.json + frozen pnpm-lock.yaml + installed graph + -> deterministic dependency inventory + -> license policy + approved actual baseline diff + -> CycloneDX SBOM + +source/config/lock + production dist + -> local provenance statement + -> optional vulnerability/attestation provider inputs + -> LOCAL PASS | promotion PASS/FAIL_UNVERIFIED +``` + +- policy: `config/security/` +- generator: `scripts/generate-supply-chain.mjs` +- coherence: `scripts/verify-supply-chain-artifacts.mjs` +- secret scan: `scripts/security-scan.mjs` +- reproducibility: `scripts/verify-reproducible-build.mjs` +- inventory: `artifacts/release/dependency-inventory.json` +- SBOM/provenance: `artifacts/release/sbom.cdx.json`, + `artifacts/release/provenance.json` +- local/promotion status: + `artifacts/security/supply-chain-verification.json` + +## 검증 + +- 현재 lockfile의 561개 package row와 inventory row가 양방향 일치한다. +- ordering-only digest, removal, integrity tamper, baseline tamper, high-risk + self approval, denied license, critical vulnerability와 만료 exception, + provider/digest 오류, SBOM/provenance 불일치 fixture를 검사한다. +- synthetic provider/attestation fixture는 promotion `PASS`를 증명한 후 기본 + `FAIL_UNVERIFIED` 상태를 복원한다. +- frozen install은 manifest/lock mismatch fixture를 실제 pnpm으로 거절한다. +- source/config/dist 각각의 synthetic secret fixture가 실제 scan을 실패시키고 + scoped test allowlist만 통과한다. + +## 한계와 재검토 조건 + +로컬 manifest license는 법률 검토가 아니며 vulnerability report도 외부 scanner가 +제공한 데이터의 최신성 자체를 보증하지 않는다. 실제 프로젝트는 provider 버전, +database freshness, network outage, exception 승인 조직, signing identity, +attestation transparency/retention과 비밀 관리를 결정해야 한다. + +## Rollback + +외부 scanner/attestor adapter는 환경 입력을 제거하면 즉시 +`FAIL_UNVERIFIED`로 돌아간다. local inventory, lock integrity, license, SBOM, +secret, reproducibility와 actual diff gate는 유지한다. scanner 장애를 이유로 +promotion을 PASS로 변경하지 않는다. diff --git a/docs/architecture/frontend-platform-capability-review.md b/docs/architecture/frontend-platform-capability-review.md index c9ff0a1..3b0250e 100644 --- a/docs/architecture/frontend-platform-capability-review.md +++ b/docs/architecture/frontend-platform-capability-review.md @@ -39,16 +39,15 @@ recovery 계약, 제거 가능한 reference 수직 슬라이스, form/page, desi i18n 실행 경계와 diagnostics/telemetry production wiring은 구현됐다. 현재 선행 해결 대상은 다음과 같다. -1. 공급망의 transitive inventory/license/vulnerability/SBOM/provenance 검증 -2. optional adapter의 opt-in 경계와 제거 가능한 recipe +1. optional adapter의 opt-in 경계와 제거 가능한 recipe 따라서 현재 상태를 “프론트 공통부가 모두 구현됐다”고 표현하면 범위가 과장된다. 더 정확한 표현은 다음과 같다. -> application API, 서버 상태, 폼, 라우팅, 페이지, 디자인 시스템과 테스트 증적의 -> 표준 수직 경로는 갖춰졌다. 현재 남은 저장소 내부 범위는 공급망 검증과 -> opt-in adapter recipe이며 실제 hosting·IdP·운영 provider는 프로젝트 통합 -> 범위다. +> application API, 서버 상태, 폼, 라우팅, 페이지, 디자인 시스템, 테스트와 +> local 공급망 증적의 표준 수직 경로는 갖춰졌다. 현재 남은 저장소 내부 범위는 +> opt-in adapter recipe이며 실제 hosting·IdP·취약점/서명/운영 provider는 +> 프로젝트 통합 범위다. ## 3. 판정 기준 @@ -89,7 +88,7 @@ i18n 실행 경계와 diagnostics/telemetry production wiring은 구현됐다. | UI 회귀 검증 | 준비됨 | dev-only Storybook interaction/axe와 pinned Chromium visual baseline 4종 | cloud review와 다중 OS/device는 프로젝트 선택 | | 샘플 제거 | 준비됨 | feature/catalog/test 제거 후 type/architecture/registry/test/home/build 9단계 검증 | 새 contribution도 같은 제거 gate에 포함 | | registry·compatibility 집행 | 준비됨 | 10개 registry type/reference/consumer/orphan, 승인 digest와 actual semantic diff, breaking evidence | public 계약 변경 시 baseline review 유지 | -| 공급망 검사 | 부분 준비 | lockfile·문서·gate는 있으나 실제 transitive 취약점/license/SBOM 깊이가 부족 | pinned scanner와 policy exception/증적 연결 | +| 공급망 검사 | 준비됨/프로젝트 선택 | 561개 transitive inventory/integrity/license, actual diff, CycloneDX, local provenance, secret/reproducible build gate | 실제 vulnerability scanner와 signed attestation 없이는 promotion `FAIL_UNVERIFIED` | | realtime·offline·file 등 | 프로젝트 선택 | 현재 없음 | port/adapter recipe와 선택 기준 제공 | ## 5. 우선순위별 발견 사항 diff --git a/docs/architecture/frontend-platform-implementation-roadmap.md b/docs/architecture/frontend-platform-implementation-roadmap.md index 6a6c979..28aa17c 100644 --- a/docs/architecture/frontend-platform-implementation-roadmap.md +++ b/docs/architecture/frontend-platform-implementation-roadmap.md @@ -892,6 +892,31 @@ owner와 만료 시한이 있는 quarantine만 허용한다. RP-11은 P1 최종 저장소 기준선이다. scanner outage를 무검증 승인으로 우회하지 않고 promotion을 보류한다. +**구현 증거 (2026-07-26)** + +- VD-09에서 frozen pnpm graph와 lockfile을 local SSOT로, package manifest + license policy와 CycloneDX 1.6을 local evidence로 채택했다. 외부 vulnerability + report와 signed attestation이 없으면 promotion은 `FAIL_UNVERIFIED`다. +- 현재 직접 35개, 전체 전이 561개 dependency의 name/version, direct/scope/ + optional, SHA-512 integrity, license와 dependency edge를 deterministic + inventory로 생성한다. lockfile row와 inventory가 양방향 일치하지 않으면 + 실패한다. +- 승인 baseline digest와 actual add/remove/change/upgrade diff를 계산하고 새 + direct production dependency에는 owner와 다른 reviewer, reason과 rollback을 + 요구한다. +- CycloneDX SBOM component/edge와 local in-toto/SLSA 형태 provenance의 + source/lock/SBOM/dist digest를 coherence gate로 다시 계산한다. +- license allow/deny, vulnerability severity와 독립·만료 exception 정책, + provider lock digest와 attestation subject를 machine-readable하게 검증한다. + provider fixture는 promotion PASS를 증명한 뒤 unconfigured + `FAIL_UNVERIFIED`를 복원한다. +- secret scan을 source/scripts/tests/config/schema/public/dist/generated release + metadata로 확장하고 원문 대신 rule/path/line/fingerprint만 SARIF에 남긴다. + test-only allowlist도 owner/reason/expiry를 강제한다. +- `SOURCE_DATE_EPOCH` 기반 동일 build 2회 digest, 실제 frozen install mismatch, + transitive omission/integrity/baseline/self-review/license/vulnerability/ + provider/SBOM/provenance/secret negative fixture를 blocking gate에 연결했다. + ## 9. P1 exit gate - 현실적인 form의 validation/dirty/pending/422/conflict가 작동한다. diff --git a/docs/security/supply-chain.md b/docs/security/supply-chain.md index f8eba98..3c38f63 100644 --- a/docs/security/supply-chain.md +++ b/docs/security/supply-chain.md @@ -1,18 +1,47 @@ # Build and supply-chain gate -Merge and release controls: +## Local blocking controls -- frozen `pnpm-lock.yaml` installation; drift is blocking -- clean production build with hashed assets and build manifest -- machine-readable bundle sizes and checksums -- source plus built-asset credential-pattern scan -- direct dependency inventory and lockfile digest -- base/head dependency diff review record +- `pnpm install --frozen-lockfile` and a real manifest/lock mismatch fixture +- all direct and transitive lockfile rows with package SHA-512 integrity +- production/development, direct/transitive and platform-optional classification +- package-manifest license allow/deny policy +- approved inventory baseline digest and actual add/remove/change/upgrade diff +- independent review for new direct production dependencies +- CycloneDX 1.6 SBOM and inventory component/edge coherence +- source/lock/SBOM/dist-linked local provenance statement +- source, scripts, tests, tracked config/schema, public, built asset and generated + release metadata secret scan +- two-build `SOURCE_DATE_EPOCH` reproducibility check -Organization-specific vulnerability severity, denied-license list, SBOM format, -and scanner selection remain policy inputs. An approved suppression must record -reason, owner, expiry, affected package, and compensating control. Expired -suppressions are blocking. +The canonical commands are: -`artifacts/security/dependency-diff.json` is a local baseline. CI replaces it -with the actual base/head direct and transitive lockfile diff before release. +```bash +corepack pnpm verify:lockfile +corepack pnpm verify:reproducible-build +corepack pnpm build:release +corepack pnpm verify:supply-chain +corepack pnpm check:supply-chain:fixtures +``` + +`config/security/dependency-baseline.json` is the approved local baseline. +Changing it requires `DEPENDENCY_BASELINE_OWNER` and +`DEPENDENCY_BASELINE_REASON`; editing the digest or hardcoding an empty diff is +rejected. + +## External promotion controls + +The vulnerability adapter reads the file named by +`VULNERABILITY_REPORT_PATH`. It requires a provider, the exact lockfile digest, +severity findings and valid independent, unexpired exception evidence. +`PROVENANCE_ATTESTATION_PATH` must name a provider, signer and the exact built +dist subject digest. + +If either provider input is absent, local verification remains meaningful but +`artifacts/security/supply-chain-verification.json` records +`promotionStatus: FAIL_UNVERIFIED`. `verify:supply-chain:promotion` then exits +non-zero. Scanner or signing outages are not converted to an empty PASS. + +Approved vulnerability exceptions require vulnerability/package identity, +owner, a different reviewer, reason and expiry. Expired or self-approved +exceptions are blocking. diff --git a/package.json b/package.json index e5c758a..7ee68cd 100644 --- a/package.json +++ b/package.json @@ -58,8 +58,16 @@ "check:coverage:fixture": "node scripts/check-risk-coverage.mjs --summary tests/fixtures/coverage/below-threshold.json --artifact artifacts/quality/risk-coverage-fixture.json", "test:all": "corepack pnpm test:runtime-schema && corepack pnpm test:unit && corepack pnpm test:component && corepack pnpm test:integration && corepack pnpm test:reference-feature", "verify:lockfile": "corepack pnpm install --frozen-lockfile", + "check:frozen-lockfile:fixture": "node scripts/check-frozen-lockfile-fixture.mjs", "generate:supply-chain": "node scripts/generate-supply-chain.mjs", + "verify:supply-chain": "node scripts/verify-supply-chain-artifacts.mjs", + "update:dependency-baseline": "node scripts/update-dependency-baseline.mjs", + "check:supply-chain:fixtures": "node scripts/check-supply-chain-fixtures.mjs", + "check:supply-chain:provider-fixtures": "node scripts/check-supply-chain-provider-fixtures.mjs", + "verify:supply-chain:promotion": "node scripts/verify-supply-chain-promotion.mjs", + "verify:reproducible-build": "node scripts/verify-reproducible-build.mjs", "scan:security": "node scripts/security-scan.mjs", + "scan:security:fixture": "node scripts/security-scan.mjs --policy tests/fixtures/security/secret-detection/forbidden-policy.json --artifact artifacts/security/scan-fixture.sarif", "check:browser-security": "node scripts/check-browser-security.mjs", "check:registries": "node scripts/check-registries.mjs", "check:registries:structure": "node scripts/check-registries.mjs --no-baseline", diff --git a/schemas/artifacts/dependency-inventory.schema.json b/schemas/artifacts/dependency-inventory.schema.json new file mode 100644 index 0000000..a55d6ef --- /dev/null +++ b/schemas/artifacts/dependency-inventory.schema.json @@ -0,0 +1,60 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://clean-architecture-frontend.local/schemas/dependency-inventory.schema.json", + "type": "object", + "additionalProperties": false, + "required": [ + "schemaVersion", + "packageManager", + "lockfileSha256", + "dependencyCount", + "directDependencyCount", + "dependencies" + ], + "properties": { + "schemaVersion": { "const": 2 }, + "packageManager": { "type": "string", "minLength": 1 }, + "lockfileSha256": { + "type": "string", + "pattern": "^[a-f0-9]{64}$" + }, + "dependencyCount": { "type": "integer", "minimum": 1 }, + "directDependencyCount": { "type": "integer", "minimum": 1 }, + "dependencies": { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "additionalProperties": false, + "required": [ + "name", + "version", + "direct", + "scope", + "optional", + "license", + "integrity", + "dependencies" + ], + "properties": { + "name": { "type": "string", "minLength": 1 }, + "version": { "type": "string", "minLength": 1 }, + "direct": { "type": "boolean" }, + "scope": { + "enum": ["production", "development"] + }, + "optional": { "type": "boolean" }, + "license": { "type": "string", "minLength": 1 }, + "integrity": { + "type": "string", + "pattern": "^sha512-" + }, + "dependencies": { + "type": "array", + "items": { "type": "string", "minLength": 1 } + } + } + } + } + } +} diff --git a/schemas/artifacts/supply-chain-verification.schema.json b/schemas/artifacts/supply-chain-verification.schema.json new file mode 100644 index 0000000..08e0402 --- /dev/null +++ b/schemas/artifacts/supply-chain-verification.schema.json @@ -0,0 +1,55 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://clean-architecture-frontend.local/schemas/supply-chain-verification.schema.json", + "type": "object", + "additionalProperties": false, + "required": [ + "schemaVersion", + "localStatus", + "promotionStatus", + "lockfileSha256", + "sourceSetSha256", + "distSha256", + "sbomSha256", + "dependencyDiff", + "highRiskReview", + "vulnerabilityStatus", + "provenanceAttestationStatus", + "failures" + ], + "properties": { + "schemaVersion": { "const": 1 }, + "localStatus": { "enum": ["PASS", "FAIL"] }, + "promotionStatus": { + "enum": ["PASS", "FAIL_UNVERIFIED"] + }, + "lockfileSha256": { + "type": "string", + "pattern": "^[a-f0-9]{64}$" + }, + "sourceSetSha256": { + "type": "string", + "pattern": "^[a-f0-9]{64}$" + }, + "distSha256": { + "type": "string", + "pattern": "^[a-f0-9]{64}$" + }, + "sbomSha256": { + "type": "string", + "pattern": "^[a-f0-9]{64}$" + }, + "dependencyDiff": { "type": "object" }, + "highRiskReview": { "type": "array" }, + "vulnerabilityStatus": { + "enum": ["PASS", "FAIL", "FAIL_UNVERIFIED"] + }, + "provenanceAttestationStatus": { + "enum": ["PASS", "FAIL_UNVERIFIED"] + }, + "failures": { + "type": "array", + "items": { "type": "string" } + } + } +} diff --git a/scripts/check-frozen-lockfile-fixture.mjs b/scripts/check-frozen-lockfile-fixture.mjs new file mode 100644 index 0000000..8cdc0b7 --- /dev/null +++ b/scripts/check-frozen-lockfile-fixture.mjs @@ -0,0 +1,39 @@ +import { spawnSync } from "node:child_process"; +import { cp, mkdtemp, readFile, rm, writeFile } from "node:fs/promises"; +import { tmpdir } from "node:os"; +import path from "node:path"; + +const fixtureRoot = await mkdtemp( + path.join(tmpdir(), "ca-frontend-frozen-lockfile-"), +); +try { + await cp("pnpm-lock.yaml", path.join(fixtureRoot, "pnpm-lock.yaml")); + const manifest = JSON.parse(await readFile("package.json", "utf8")); + manifest.dependencies.react = "0.0.0-invalid-fixture"; + await writeFile( + path.join(fixtureRoot, "package.json"), + `${JSON.stringify(manifest, null, 2)}\n`, + ); + const result = spawnSync( + "corepack", + [ + "pnpm", + "install", + "--frozen-lockfile", + "--lockfile-only", + "--ignore-scripts", + ], + { + cwd: fixtureRoot, + encoding: "utf8", + }, + ); + if (result.status === 0) { + process.stderr.write("Tampered manifest unexpectedly passed frozen install.\n"); + process.exitCode = 1; + } else { + process.stdout.write("Frozen lockfile mismatch fixture: rejected PASS\n"); + } +} finally { + await rm(fixtureRoot, { recursive: true, force: true }); +} diff --git a/scripts/check-supply-chain-fixtures.mjs b/scripts/check-supply-chain-fixtures.mjs new file mode 100644 index 0000000..2cc1b2a --- /dev/null +++ b/scripts/check-supply-chain-fixtures.mjs @@ -0,0 +1,148 @@ +import { mkdir, writeFile } from "node:fs/promises"; + +import { + diffDependencyInventories, + isValidSha512Integrity, + supplyChainDigest, + validateDependencyReview, + validateLicensePolicy, + validateVulnerabilityReport, + verifySupplyChainCoherence, +} from "./lib/supply-chain.mjs"; + +const integrity = `sha512-${Buffer.alloc(64, 1).toString("base64")}`; +const baseDependency = { + name: "base", + version: "1.0.0", + direct: false, + scope: "production", + optional: false, + license: "MIT", + integrity, + dependencies: [], +}; +const directDependency = { + ...baseDependency, + name: "new-direct", + direct: true, +}; +const before = { dependencies: [baseDependency] }; +const after = { dependencies: [baseDependency, directDependency] }; +const diff = diffDependencyInventories(before, after); +const selfReview = validateDependencyReview(diff, after, { + changes: [ + { + changeId: "add:new-direct@1.0.0", + owner: "same-person", + reviewer: "same-person", + reason: "fixture", + rollback: "remove", + }, + ], +}); +const deniedLicense = validateLicensePolicy( + { + dependencies: [{ ...baseDependency, license: "AGPL-3.0" }], + }, + { + allowedLicenses: ["MIT"], + deniedLicensePatterns: ["AGPL"], + }, +); +const vulnerable = validateVulnerabilityReport( + { + provider: "fixture", + scannedLockfileSha256: "lock", + findings: [ + { + id: "CVE-FIXTURE", + packageName: "base", + version: "1.0.0", + severity: "critical", + }, + ], + }, + { blockAtSeverity: "high" }, + { + exceptions: [ + { + vulnerabilityId: "CVE-FIXTURE", + packageName: "base", + owner: "owner", + reviewer: "reviewer", + reason: "expired fixture", + expiresAt: "2000-01-01T00:00:00.000Z", + }, + ], + }, + "lock", + new Date("2026-07-26T00:00:00.000Z"), +); +const mismatchedCoherence = verifySupplyChainCoherence( + { + components: [], + metadata: { + properties: [{ name: "ca:lockfileSha256", value: "wrong" }], + }, + }, + { dependencies: [baseDependency], lockfileSha256: "lock" }, + { + subject: [{ digest: { sha256: "wrong" } }], + predicate: { materials: { lockfileSha256: "wrong" } }, + }, + "dist", +); +const orderingStable = + supplyChainDigest({ dependencies: [baseDependency, directDependency] }) === + supplyChainDigest({ dependencies: [directDependency, baseDependency] }); +const approvedDigest = supplyChainDigest(before); +const tamperedBaselineRejected = + approvedDigest !== + supplyChainDigest({ + dependencies: [{ ...baseDependency, version: "9.9.9-tampered" }], + }); +const providerFailure = validateVulnerabilityReport( + { + provider: "", + scannedLockfileSha256: "wrong", + findings: [], + }, + { blockAtSeverity: "high" }, + { exceptions: [] }, + "lock", +); +const results = [ + { + id: "transitive-removal-is-real-diff", + passed: + diffDependencyInventories(after, before).removed[0] === + "new-direct@1.0.0", + }, + { + id: "tampered-integrity-rejected", + passed: !isValidSha512Integrity("sha512-dGFtcGVyZWQ="), + }, + { id: "high-risk-self-approval-rejected", passed: !selfReview.passed }, + { id: "denied-license-rejected", passed: !deniedLicense.passed }, + { + id: "critical-vulnerability-expired-exception-rejected", + passed: !vulnerable.passed, + }, + { id: "sbom-provenance-mismatch-rejected", passed: !mismatchedCoherence.passed }, + { id: "dependency-ordering-deterministic", passed: orderingStable }, + { id: "baseline-digest-tamper-rejected", passed: tamperedBaselineRejected }, + { + id: "vulnerability-provider-evidence-invalid", + passed: !providerFailure.passed, + }, +]; +await mkdir("artifacts/security", { recursive: true }); +await writeFile( + "artifacts/security/supply-chain-fixtures.json", + `${JSON.stringify({ schemaVersion: 1, results }, null, 2)}\n`, +); +if (results.some((result) => !result.passed)) { + process.stderr.write("Supply-chain negative fixture failed.\n"); + process.exit(1); +} +process.stdout.write(`Supply-chain fixtures: ${results.length} PASS\n`); diff --git a/scripts/check-supply-chain-provider-fixtures.mjs b/scripts/check-supply-chain-provider-fixtures.mjs new file mode 100644 index 0000000..b052a3e --- /dev/null +++ b/scripts/check-supply-chain-provider-fixtures.mjs @@ -0,0 +1,105 @@ +import { spawnSync } from "node:child_process"; +import { mkdir, readFile, rm, writeFile } from "node:fs/promises"; +import path from "node:path"; + +const fixtureDirectory = path.resolve(".tmp/supply-chain-provider-fixture"); +await rm(fixtureDirectory, { recursive: true, force: true }); +await mkdir(fixtureDirectory, { recursive: true }); +const inventory = JSON.parse( + await readFile("artifacts/release/dependency-inventory.json", "utf8"), +); +const verification = JSON.parse( + await readFile( + "artifacts/security/supply-chain-verification.json", + "utf8", + ), +); +const vulnerabilityPath = path.join( + fixtureDirectory, + "vulnerability-report.json", +); +const attestationPath = path.join(fixtureDirectory, "attestation.json"); +await writeFile( + vulnerabilityPath, + `${JSON.stringify( + { + schemaVersion: 1, + provider: "fixture-scanner", + scannedLockfileSha256: inventory.lockfileSha256, + generatedAt: "2026-07-26T00:00:00.000Z", + findings: [], + }, + null, + 2, + )}\n`, +); +await writeFile( + attestationPath, + `${JSON.stringify( + { + schemaVersion: 1, + provider: "fixture-attestor", + signer: "fixture-workload-identity", + subject: { + name: "dist", + digest: { sha256: verification.distSha256 }, + }, + }, + null, + 2, + )}\n`, +); +const providerRun = spawnSync( + "node", + ["scripts/generate-supply-chain.mjs"], + { + env: { + ...process.env, + VULNERABILITY_REPORT_PATH: vulnerabilityPath, + PROVENANCE_ATTESTATION_PATH: attestationPath, + }, + encoding: "utf8", + }, +); +let promotionStatus = "MISSING"; +if (providerRun.status === 0) { + promotionStatus = JSON.parse( + await readFile( + "artifacts/security/supply-chain-verification.json", + "utf8", + ), + ).promotionStatus; +} +const restore = spawnSync( + "node", + ["scripts/generate-supply-chain.mjs"], + { encoding: "utf8" }, +); +await rm(fixtureDirectory, { recursive: true, force: true }); +const passed = + providerRun.status === 0 && + promotionStatus === "PASS" && + restore.status === 0; +await writeFile( + "artifacts/security/supply-chain-provider-fixtures.json", + `${JSON.stringify( + { + schemaVersion: 1, + providerAccepted: providerRun.status === 0, + promotionStatus, + unverifiedDefaultRestored: restore.status === 0, + status: passed ? "PASS" : "FAIL", + }, + null, + 2, + )}\n`, +); +if (!passed) { + process.stderr.write( + `Supply-chain provider fixture failed: ${providerRun.stderr || restore.stderr}\n`, + ); + process.exit(1); +} +process.stdout.write( + "Supply-chain provider fixture: verified PASS and unconfigured default restored\n", +); diff --git a/scripts/generate-build-manifest.mjs b/scripts/generate-build-manifest.mjs index f89337f..0fd01e8 100644 --- a/scripts/generate-build-manifest.mjs +++ b/scripts/generate-build-manifest.mjs @@ -15,7 +15,13 @@ const buildId = process.env.VITE_BUILD_ID ?? "local-build"; const commitSha = process.env.VITE_COMMIT_SHA ?? "local"; const releaseId = process.env.RELEASE_ID ?? "local-release"; const runnerImage = process.env.CI_RUNNER_IMAGE ?? `${process.platform}-${process.arch}`; -const builtAt = new Date().toISOString(); +const buildTime = process.env.SOURCE_DATE_EPOCH + ? new Date(Number(process.env.SOURCE_DATE_EPOCH) * 1_000) + : new Date(); +if (!Number.isFinite(buildTime.getTime())) { + throw new Error("SOURCE_DATE_EPOCH must be epoch seconds"); +} +const builtAt = buildTime.toISOString(); const viteManifest = await readFile("dist/.vite/manifest.json", "utf8"); const viteManifestObject = /** @type {Record} */ ( diff --git a/scripts/generate-supply-chain.mjs b/scripts/generate-supply-chain.mjs index d5f978e..e701968 100644 --- a/scripts/generate-supply-chain.mjs +++ b/scripts/generate-supply-chain.mjs @@ -1,3 +1,4 @@ +import { spawnSync } from "node:child_process"; import { createHash } from "node:crypto"; import { gzipSync } from "node:zlib"; import { @@ -9,47 +10,404 @@ import { } from "node:fs/promises"; import path from "node:path"; +import { + diffDependencyInventories, + flattenPnpmDependencyTree, + isValidSha512Integrity, + parsePnpmLockfilePackages, + supplyChainDigest, + validateDependencyReview, + validateLicensePolicy, + validateVulnerabilityReport, + verifySupplyChainCoherence, +} from "./lib/supply-chain.mjs"; + /** @param {string} directory @returns {Promise} */ async function filesWithin(directory) { - const entries = await readdir(directory, { withFileTypes: true }); - const nested = /** @type {string[][]} */ (await Promise.all( - entries.map((entry) => { - const target = path.join(directory, entry.name); - return entry.isDirectory() ? filesWithin(target) : [target]; - }), - )); - return nested.flat().sort(); + try { + const entries = await readdir(directory, { withFileTypes: true }); + const nested = /** @type {string[][]} */ (await Promise.all( + entries.map((entry) => { + const target = path.join(directory, entry.name); + return entry.isDirectory() ? filesWithin(target) : [target]; + }), + )); + return nested.flat().sort(); + } catch { + return []; + } +} + +/** @param {string} file */ +async function sha256File(file) { + return createHash("sha256").update(await readFile(file)).digest("hex"); +} + +/** @param {string[]} files */ +async function digestFileSet(files) { + const rows = await Promise.all( + files.sort().map(async (file) => ({ + path: file.replaceAll("\\", "/"), + sha256: await sha256File(file), + })), + ); + return supplyChainDigest(rows); +} + +/** @param {string} file @returns {Promise | null>} */ +async function optionalJson(file) { + try { + return JSON.parse(await readFile(file, "utf8")); + } catch { + return null; + } +} + +export async function buildDependencyInventory() { + const packageJson = JSON.parse(await readFile("package.json", "utf8")); + const lockfileText = await readFile("pnpm-lock.yaml", "utf8"); + const lockfileSha256 = createHash("sha256") + .update(lockfileText) + .digest("hex"); + const listed = spawnSync( + "corepack", + ["pnpm", "list", "--json", "--depth", "Infinity"], + { + encoding: "utf8", + maxBuffer: 32 * 1024 * 1024, + }, + ); + if (listed.status !== 0) { + throw new Error(`pnpm dependency graph failed: ${listed.stderr}`); + } + const roots = JSON.parse(listed.stdout); + const root = roots[0]; + const flattened = await flattenPnpmDependencyTree( + root, + packageJson.dependencies ?? {}, + packageJson.devDependencies ?? {}, + ); + const lockRows = parsePnpmLockfilePackages(lockfileText); + const lockByIdentity = new Map( + lockRows.map((row) => [`${row.name}@${row.version}`, row]), + ); + const failures = []; + const dependencies = flattened.map((dependency) => { + const identity = `${dependency.name}@${dependency.version}`; + const lockRow = lockByIdentity.get(identity); + if (!lockRow) failures.push(`dependency missing from lockfile: ${identity}`); + if (lockRow && !isValidSha512Integrity(lockRow.integrity)) { + failures.push(`dependency has invalid sha512 integrity: ${identity}`); + } + return { + ...dependency, + integrity: lockRow?.integrity ?? "missing", + }; + }); + const inventoryIds = new Set( + dependencies.map((dependency) => `${dependency.name}@${dependency.version}`), + ); + for (const lockRow of lockRows) { + const identity = `${lockRow.name}@${lockRow.version}`; + if (!inventoryIds.has(identity)) { + failures.push(`transitive lockfile dependency omitted: ${identity}`); + } + } + if (failures.length > 0) { + throw new Error(failures.join("\n")); + } + return { + schemaVersion: 2, + packageManager: packageJson.packageManager, + lockfileSha256, + dependencyCount: dependencies.length, + directDependencyCount: dependencies.filter((entry) => entry.direct).length, + dependencies, + }; } const packageJson = JSON.parse(await readFile("package.json", "utf8")); -const lockfile = await readFile("pnpm-lock.yaml"); const outputFiles = await filesWithin("dist"); - +if (outputFiles.length === 0) { + throw new Error("dist is missing; run the production build first"); +} const outputs = await Promise.all( outputFiles.map(async (outputFile) => { const content = await readFile(outputFile); const metadata = await stat(outputFile); return { - path: outputFile, + path: outputFile.replaceAll("\\", "/"), bytes: metadata.size, gzipBytes: gzipSync(content).byteLength, sha256: createHash("sha256").update(content).digest("hex"), }; }), ); +const distDigest = supplyChainDigest( + outputs.map(({ path: outputPath, bytes, sha256 }) => ({ + path: outputPath, + bytes, + sha256, + })), +); +const inventory = await buildDependencyInventory(); +const licensePolicy = JSON.parse( + await readFile("config/security/dependency-policy.json", "utf8"), +); +const licenseResult = validateLicensePolicy(inventory, licensePolicy); -const dependencies = { - ...packageJson.dependencies, - ...packageJson.devDependencies, +const baseline = await optionalJson( + "config/security/dependency-baseline.json", +); +const baselineApproval = await optionalJson( + "config/security/dependency-baseline.approval.json", +); +const dependencyEvidence = JSON.parse( + await readFile( + "config/security/dependency-change-evidence.json", + "utf8", + ), +); +const skipsBaseline = process.argv.includes("--no-baseline"); +const baselineFailures = []; +let dependencyDiff = + /** @type {ReturnType} */ ({ + added: [], + removed: [], + changed: [], + upgrades: [], +}); +let reviewResult = + /** @type {ReturnType} */ ({ + passed: skipsBaseline, + highRisk: [], + failures: skipsBaseline ? [] : ["dependency baseline unavailable"], +}); +if (baseline && baselineApproval) { + const actualBaselineDigest = supplyChainDigest(baseline); + if ( + baselineApproval.schemaVersion !== 1 || + baselineApproval.snapshotDigest !== actualBaselineDigest || + typeof baselineApproval.owner !== "string" || + !baselineApproval.owner + ) { + baselineFailures.push("dependency baseline approval digest mismatch"); + } + dependencyDiff = diffDependencyInventories(baseline, inventory); + reviewResult = validateDependencyReview( + dependencyDiff, + inventory, + dependencyEvidence, + ); +} else if (!skipsBaseline) { + baselineFailures.push("dependency baseline and approval are required"); +} + +const vulnerabilityPolicy = JSON.parse( + await readFile("config/security/vulnerability-policy.json", "utf8"), +); +const vulnerabilityExceptions = JSON.parse( + await readFile("config/security/vulnerability-exceptions.json", "utf8"), +); +const vulnerabilityInput = process.env.VULNERABILITY_REPORT_PATH + ? await optionalJson(process.env.VULNERABILITY_REPORT_PATH) + : null; +const vulnerabilityResult = vulnerabilityInput + ? validateVulnerabilityReport( + vulnerabilityInput, + vulnerabilityPolicy, + vulnerabilityExceptions, + inventory.lockfileSha256, + ) + : { + passed: false, + failures: ["external vulnerability provider report is missing"], + blocking: [], + }; +const vulnerabilityReport = { + schemaVersion: 1, + provider: vulnerabilityInput?.provider ?? "UNCONFIGURED", + scannedLockfileSha256: + vulnerabilityInput?.scannedLockfileSha256 ?? inventory.lockfileSha256, + status: vulnerabilityInput + ? vulnerabilityResult.passed + ? "PASS" + : "FAIL" + : "FAIL_UNVERIFIED", + findings: vulnerabilityInput?.findings ?? [], + exceptionsApplied: + vulnerabilityInput && vulnerabilityResult.passed + ? vulnerabilityExceptions.exceptions + : [], + failures: vulnerabilityResult.failures, + blocking: vulnerabilityResult.blocking, +}; + +const sourceFiles = ( + await Promise.all( + [ + "src", + "scripts", + "config", + "public", + "schemas", + "package.json", + "pnpm-lock.yaml", + "vite.config.js", + ].map(async (target) => { + try { + const metadata = await stat(target); + return metadata.isDirectory() ? filesWithin(target) : [target]; + } catch { + return []; + } + }), + ) +).flat(); +const sourceSetSha256 = await digestFileSet(sourceFiles); + +const components = inventory.dependencies.map((dependency) => ({ + type: "library", + "bom-ref": `pkg:npm/${encodeURIComponent(dependency.name)}@${dependency.version}`, + name: dependency.name, + version: dependency.version, + scope: dependency.optional ? "optional" : "required", + hashes: [ + { + alg: "SHA-512", + content: dependency.integrity.slice("sha512-".length), + }, + ], + licenses: + dependency.license === "NOASSERTION" + ? [{ expression: "NOASSERTION" }] + : [{ expression: dependency.license }], + properties: [ + { name: "ca:direct", value: String(dependency.direct) }, + { name: "ca:scope", value: dependency.scope }, + ], +})); +const serialSeed = supplyChainDigest({ + lockfileSha256: inventory.lockfileSha256, + components: components.map((component) => component["bom-ref"]), +}); +const sbom = { + bomFormat: "CycloneDX", + specVersion: "1.6", + serialNumber: `urn:uuid:${serialSeed.slice(0, 8)}-${serialSeed.slice(8, 12)}-${serialSeed.slice(12, 16)}-${serialSeed.slice(16, 20)}-${serialSeed.slice(20, 32)}`, + version: 1, + metadata: { + component: { + type: "application", + name: packageJson.name, + version: packageJson.version, + }, + properties: [ + { + name: "ca:lockfileSha256", + value: inventory.lockfileSha256, + }, + ], + }, + components, + dependencies: inventory.dependencies.map((dependency) => ({ + ref: `pkg:npm/${encodeURIComponent(dependency.name)}@${dependency.version}`, + dependsOn: dependency.dependencies.map((identity) => { + const separator = identity.lastIndexOf("@"); + return `pkg:npm/${encodeURIComponent(identity.slice(0, separator))}@${identity.slice(separator + 1)}`; + }), + })), +}; + +const provenance = { + _type: "https://in-toto.io/Statement/v1", + subject: [{ name: "dist", digest: { sha256: distDigest } }], + predicateType: "https://slsa.dev/provenance/v1", + predicate: { + buildDefinition: { + buildType: "https://vite.dev/build/v1", + externalParameters: { + nodeVersion: process.version, + packageManager: packageJson.packageManager, + }, + internalParameters: { + sourceSetSha256, + }, + resolvedDependencies: [ + { + uri: "pnpm-lock.yaml", + digest: { sha256: inventory.lockfileSha256 }, + }, + ], + }, + runDetails: { + builder: { id: "local:clean-architecture-frontend-template" }, + metadata: { invocationId: "LOCAL_UNSIGNED" }, + }, + materials: { + lockfileSha256: inventory.lockfileSha256, + sourceSetSha256, + sbomSha256: supplyChainDigest(sbom), + }, + }, +}; +const coherence = verifySupplyChainCoherence( + sbom, + inventory, + provenance, + distDigest, +); + +const attestationInput = process.env.PROVENANCE_ATTESTATION_PATH + ? await optionalJson(process.env.PROVENANCE_ATTESTATION_PATH) + : null; +const attestationSubject = + /** @type {Record} */ ( + /** @type {Record} */ ( + attestationInput?.subject ?? {} + ).digest ?? {} + ); +const attestationPassed = + attestationSubject.sha256 === distDigest && + typeof attestationInput?.provider === "string" && + Boolean(attestationInput.provider) && + typeof attestationInput?.signer === "string" && + Boolean(attestationInput.signer); +const localFailures = [ + ...licenseResult.failures, + ...baselineFailures, + ...reviewResult.failures, + ...coherence.failures, +]; +if (vulnerabilityInput && !vulnerabilityResult.passed) { + localFailures.push( + ...vulnerabilityResult.failures, + ...vulnerabilityResult.blocking, + ); +} +const localPassed = localFailures.length === 0; +const promotionPassed = + localPassed && vulnerabilityResult.passed && attestationPassed; +const verification = { + schemaVersion: 1, + localStatus: localPassed ? "PASS" : "FAIL", + promotionStatus: promotionPassed ? "PASS" : "FAIL_UNVERIFIED", + lockfileSha256: inventory.lockfileSha256, + sourceSetSha256, + distSha256: distDigest, + sbomSha256: supplyChainDigest(sbom), + dependencyDiff, + highRiskReview: reviewResult.highRisk, + vulnerabilityStatus: vulnerabilityReport.status, + provenanceAttestationStatus: attestationPassed + ? "PASS" + : "FAIL_UNVERIFIED", + failures: localFailures, }; -const inventory = Object.entries(dependencies) - .sort(([left], [right]) => left.localeCompare(right)) - .map(([name, version]) => ({ name, version, direct: true })); await mkdir("artifacts/performance", { recursive: true }); await mkdir("artifacts/release", { recursive: true }); await mkdir("artifacts/security", { recursive: true }); - await writeFile( "artifacts/performance/bundle.json", `${JSON.stringify( @@ -59,7 +417,8 @@ await writeFile( context: { nodeVersion: process.version, packageManager: packageJson.packageManager, - runnerImage: process.env.CI_RUNNER_IMAGE ?? `${process.platform}-${process.arch}`, + runnerImage: + process.env.CI_RUNNER_IMAGE ?? `${process.platform}-${process.arch}`, }, outputs, }, @@ -67,36 +426,66 @@ await writeFile( 2, )}\n`, ); - await writeFile( "artifacts/release/dependency-inventory.json", - `${JSON.stringify( - { - schemaVersion: 1, - lockfileSha256: createHash("sha256").update(lockfile).digest("hex"), - dependencies: inventory, - }, - null, - 2, - )}\n`, + `${JSON.stringify(inventory, null, 2)}\n`, +); +await writeFile( + "artifacts/release/sbom.cdx.json", + `${JSON.stringify(sbom, null, 2)}\n`, +); +await writeFile( + "artifacts/release/provenance.json", + `${JSON.stringify(provenance, null, 2)}\n`, ); - await writeFile( "artifacts/release/checksums.txt", `${outputs.map((output) => `${output.sha256} ${output.path}`).join("\n")}\n`, ); - await writeFile( "artifacts/security/dependency-diff.json", `${JSON.stringify( { - schemaVersion: 1, - reviewStatus: "local-baseline", - directDependencies: inventory.length, - highRiskUnreviewed: [], - lockfileSha256: createHash("sha256").update(lockfile).digest("hex"), + schemaVersion: 2, + baselineDigest: baseline ? supplyChainDigest(baseline) : null, + currentDigest: supplyChainDigest(inventory), + ...dependencyDiff, + highRisk: reviewResult.highRisk, + reviewFailures: reviewResult.failures, }, null, 2, )}\n`, ); +await writeFile( + "artifacts/security/license-report.json", + `${JSON.stringify( + { + schemaVersion: 1, + status: licenseResult.passed ? "PASS" : "FAIL", + dependencyCount: inventory.dependencyCount, + results: licenseResult.results, + failures: licenseResult.failures, + }, + null, + 2, + )}\n`, +); +await writeFile( + "artifacts/security/vulnerability-report.json", + `${JSON.stringify(vulnerabilityReport, null, 2)}\n`, +); +await writeFile( + "artifacts/security/supply-chain-verification.json", + `${JSON.stringify(verification, null, 2)}\n`, +); + +if (!localPassed) { + process.stderr.write( + `Local supply-chain verification failed:\n- ${localFailures.join("\n- ")}\n`, + ); + process.exit(1); +} +process.stdout.write( + `Supply chain: LOCAL PASS (${inventory.dependencyCount} dependencies); promotion=${verification.promotionStatus}\n`, +); diff --git a/scripts/lib/supply-chain.mjs b/scripts/lib/supply-chain.mjs new file mode 100644 index 0000000..8201612 --- /dev/null +++ b/scripts/lib/supply-chain.mjs @@ -0,0 +1,547 @@ +import { createHash } from "node:crypto"; +import { readFile } from "node:fs/promises"; + +/** @param {unknown} value @returns {unknown} */ +export function canonicalizeSupplyChainValue(value) { + if (Array.isArray(value)) { + return value + .map(canonicalizeSupplyChainValue) + .sort((left, right) => + JSON.stringify(left).localeCompare(JSON.stringify(right)), + ); + } + if (value && typeof value === "object") { + return Object.fromEntries( + Object.entries(value) + .sort(([left], [right]) => left.localeCompare(right)) + .map(([key, item]) => [key, canonicalizeSupplyChainValue(item)]), + ); + } + return value; +} + +/** @param {unknown} value */ +export function supplyChainDigest(value) { + return createHash("sha256") + .update(JSON.stringify(canonicalizeSupplyChainValue(value))) + .digest("hex"); +} + +/** @param {string} lockfile */ +export function parsePnpmLockfilePackages(lockfile) { + const entries = + /** @type {Array<{name: string, version: string, integrity: string}>} */ ( + [] + ); + let inPackages = false; + /** @type {{name: string, version: string, integrity: string} | null} */ + let current = null; + + for (const line of lockfile.split(/\r?\n/)) { + if (line === "packages:") { + inPackages = true; + continue; + } + if (line === "snapshots:") { + if (current) entries.push(current); + break; + } + if (!inPackages) continue; + const packageMatch = line.match(/^ {2}(\S.*):$/); + if (packageMatch) { + if (current) entries.push(current); + const key = packageMatch[1].replace(/^['"]|['"]$/g, ""); + const separator = key.lastIndexOf("@"); + current = { + name: key.slice(0, separator), + version: key.slice(separator + 1), + integrity: "", + }; + continue; + } + const integrityMatch = line.match(/\bintegrity:\s*([^,}\s]+)/); + if (current && integrityMatch) { + current.integrity = integrityMatch[1]; + } + } + return entries.sort((left, right) => + `${left.name}@${left.version}`.localeCompare( + `${right.name}@${right.version}`, + ), + ); +} + +/** @param {string} integrity */ +export function isValidSha512Integrity(integrity) { + if (!integrity.startsWith("sha512-")) return false; + try { + return Buffer.from(integrity.slice("sha512-".length), "base64").length === 64; + } catch { + return false; + } +} + +/** + * @param {unknown} raw + * @returns {string} + */ +export function normalizeLicense(raw) { + if (typeof raw === "string" && raw.trim()) return raw.trim(); + if ( + raw && + typeof raw === "object" && + "type" in raw && + typeof raw.type === "string" + ) { + return raw.type; + } + if (Array.isArray(raw)) { + const licenses = raw.map(normalizeLicense).filter( + (license) => license !== "NOASSERTION", + ); + return licenses.length > 0 ? licenses.join(" OR ") : "NOASSERTION"; + } + return "NOASSERTION"; +} + +/** + * @param {Record} root + * @param {Readonly>} directProduction + * @param {Readonly>} directDevelopment + */ +export async function flattenPnpmDependencyTree( + root, + directProduction, + directDevelopment, +) { + const records = + /** @type {Map + * }>} */ (new Map()); + const directIds = new Set(); + for (const [name, rawDependency] of Object.entries( + /** @type {Record} */ (root.dependencies ?? {}), + )) { + if ( + Object.hasOwn(directProduction, name) && + rawDependency && + typeof rawDependency === "object" && + !Array.isArray(rawDependency) + ) { + directIds.add( + `${name}@${String( + /** @type {Record} */ (rawDependency).version ?? "", + )}`, + ); + } + } + for (const [name, rawDependency] of Object.entries( + /** @type {Record} */ (root.devDependencies ?? {}), + )) { + if ( + Object.hasOwn(directDevelopment, name) && + rawDependency && + typeof rawDependency === "object" && + !Array.isArray(rawDependency) + ) { + directIds.add( + `${name}@${String( + /** @type {Record} */ (rawDependency).version ?? "", + )}`, + ); + } + } + + /** + * @param {Record} node + * @param {"production" | "development"} scope + * @param {boolean} optionalPath + */ + function visit(node, scope, optionalPath) { + for (const [groupName, group] of Object.entries({ + dependencies: node.dependencies, + devDependencies: node.devDependencies, + optionalDependencies: node.optionalDependencies, + })) { + if (!group || typeof group !== "object" || Array.isArray(group)) continue; + for (const [name, rawDependency] of Object.entries(group)) { + if ( + !rawDependency || + typeof rawDependency !== "object" || + Array.isArray(rawDependency) + ) { + continue; + } + const dependency = + /** @type {Record} */ (rawDependency); + const version = String(dependency.version ?? ""); + const packagePath = String(dependency.path ?? ""); + const identity = `${name}@${version}`; + const childScope = + scope === "production" && groupName !== "devDependencies" + ? "production" + : "development"; + const childOptional = + optionalPath || groupName === "optionalDependencies"; + const previous = records.get(identity); + const dependencies = previous?.dependencies ?? new Set(); + for (const childGroup of [ + dependency.dependencies, + dependency.optionalDependencies, + ]) { + if ( + !childGroup || + typeof childGroup !== "object" || + Array.isArray(childGroup) + ) { + continue; + } + for (const [childName, rawChild] of Object.entries(childGroup)) { + if ( + rawChild && + typeof rawChild === "object" && + !Array.isArray(rawChild) + ) { + dependencies.add( + `${childName}@${String(rawChild.version ?? "")}`, + ); + } + } + } + records.set(identity, { + name, + version, + direct: directIds.has(identity), + scope: + previous?.scope === "production" || childScope === "production" + ? "production" + : "development", + optional: previous ? previous.optional && childOptional : childOptional, + packagePath: previous?.packagePath || packagePath, + dependencies, + }); + visit(dependency, childScope, childOptional); + } + } + } + + const productionRoot = { + dependencies: Object.fromEntries( + Object.entries( + /** @type {Record} */ (root.dependencies ?? {}), + ).filter(([name]) => Object.hasOwn(directProduction, name)), + ), + }; + const developmentRoot = { + devDependencies: Object.fromEntries( + Object.entries( + /** @type {Record} */ (root.devDependencies ?? {}), + ).filter(([name]) => Object.hasOwn(directDevelopment, name)), + ), + }; + visit(productionRoot, "production", false); + visit(developmentRoot, "development", false); + + const result = []; + for (const record of records.values()) { + let license = "NOASSERTION"; + let optional = record.optional; + if (record.packagePath) { + try { + const manifest = JSON.parse( + await readFile(`${record.packagePath}/package.json`, "utf8"), + ); + license = normalizeLicense(manifest.license ?? manifest.licenses); + } catch { + // Platform-specific optional packages may not be materialized locally. + optional = true; + } + } + result.push({ + name: record.name, + version: record.version, + direct: record.direct, + scope: record.scope, + optional, + license, + dependencies: [...record.dependencies].sort(), + }); + } + return result.sort((left, right) => + `${left.name}@${left.version}`.localeCompare( + `${right.name}@${right.version}`, + ), + ); +} + +/** + * @param {Readonly>} before + * @param {Readonly>} after + */ +export function diffDependencyInventories(before, after) { + const beforeRows = + /** @type {Array>} */ (before.dependencies ?? []); + const afterRows = + /** @type {Array>} */ (after.dependencies ?? []); + const beforeMap = new Map( + beforeRows.map((row) => [`${row.name}@${row.version}`, row]), + ); + const afterMap = new Map( + afterRows.map((row) => [`${row.name}@${row.version}`, row]), + ); + const added = [...afterMap.keys()].filter((key) => !beforeMap.has(key)); + const removed = [...beforeMap.keys()].filter((key) => !afterMap.has(key)); + const changed = []; + for (const key of [...beforeMap.keys()].filter((item) => afterMap.has(item))) { + if ( + supplyChainDigest(beforeMap.get(key)) !== + supplyChainDigest(afterMap.get(key)) + ) { + changed.push(key); + } + } + const upgrades = []; + for (const removedKey of removed) { + const previous = beforeMap.get(removedKey); + const replacement = added.find( + (addedKey) => afterMap.get(addedKey)?.name === previous?.name, + ); + if (replacement) { + upgrades.push({ + name: previous?.name, + from: previous?.version, + to: afterMap.get(replacement)?.version, + }); + } + } + return Object.freeze({ + added: Object.freeze(added.sort()), + removed: Object.freeze(removed.sort()), + changed: Object.freeze(changed.sort()), + upgrades: Object.freeze( + upgrades.sort((left, right) => + String(left.name).localeCompare(String(right.name)), + ), + ), + }); +} + +/** + * @param {Readonly>} inventory + * @param {Readonly>} policy + */ +export function validateLicensePolicy(inventory, policy) { + const allowed = new Set( + /** @type {string[]} */ (policy.allowedLicenses ?? []), + ); + const denied = /** @type {string[]} */ (policy.deniedLicensePatterns ?? []); + const failures = []; + const results = []; + for (const dependency of /** @type {Array>} */ ( + inventory.dependencies ?? [] + )) { + const license = String(dependency.license ?? "NOASSERTION"); + const explicitlyDenied = denied.some((pattern) => + new RegExp(pattern, "i").test(license), + ); + const unknownAccepted = + license === "NOASSERTION" && dependency.optional === true; + const passed = + !explicitlyDenied && (allowed.has(license) || unknownAccepted); + results.push({ + package: `${dependency.name}@${dependency.version}`, + license, + passed, + reason: unknownAccepted ? "platform-optional-not-materialized" : null, + }); + if (!passed) { + failures.push( + `${dependency.name}@${dependency.version} has disallowed license ${license}`, + ); + } + } + return Object.freeze({ + passed: failures.length === 0, + failures: Object.freeze(failures), + results: Object.freeze(results), + }); +} + +/** + * @param {ReturnType} diff + * @param {Readonly>} inventory + * @param {Readonly>} evidenceFile + */ +export function validateDependencyReview(diff, inventory, evidenceFile) { + const rows = + /** @type {Array>} */ (inventory.dependencies ?? []); + const byIdentity = new Map( + rows.map((row) => [`${row.name}@${row.version}`, row]), + ); + const evidence = new Map( + /** @type {Array>} */ ( + evidenceFile.changes ?? [] + ).map((entry) => [entry.changeId, entry]), + ); + const highRisk = diff.added.filter((identity) => { + const row = byIdentity.get(identity); + return row?.direct === true && row.scope === "production"; + }); + const failures = []; + for (const identity of highRisk) { + const changeId = `add:${identity}`; + const entry = evidence.get(changeId); + if (!entry) { + failures.push(`high-risk dependency missing review: ${changeId}`); + continue; + } + for (const field of ["owner", "reviewer", "reason", "rollback"]) { + if (typeof entry[field] !== "string" || !entry[field].trim()) { + failures.push(`${changeId} missing ${field}`); + } + } + if (entry.owner === entry.reviewer) { + failures.push(`${changeId} may not be self-approved`); + } + } + return Object.freeze({ + passed: failures.length === 0, + highRisk: Object.freeze(highRisk), + failures: Object.freeze(failures), + }); +} + +const severityRank = new Map([ + ["unknown", 0], + ["low", 1], + ["moderate", 2], + ["high", 3], + ["critical", 4], +]); + +/** + * @param {Readonly>} report + * @param {Readonly>} policy + * @param {Readonly>} exceptionFile + * @param {string} lockfileSha256 + * @param {Date} [now] + */ +export function validateVulnerabilityReport( + report, + policy, + exceptionFile, + lockfileSha256, + now = new Date(), +) { + const failures = []; + if (report.scannedLockfileSha256 !== lockfileSha256) { + failures.push("vulnerability report lockfile digest mismatch"); + } + if (typeof report.provider !== "string" || !report.provider.trim()) { + failures.push("vulnerability report provider missing"); + } + const threshold = severityRank.get(String(policy.blockAtSeverity)) ?? 3; + const exceptions = + /** @type {Array>} */ ( + exceptionFile.exceptions ?? [] + ); + const blocking = []; + for (const finding of /** @type {Array>} */ ( + report.findings ?? [] + )) { + const severity = String(finding.severity ?? "unknown").toLowerCase(); + if ((severityRank.get(severity) ?? 0) < threshold) continue; + const exception = exceptions.find( + (entry) => + entry.vulnerabilityId === finding.id && + entry.packageName === finding.packageName, + ); + const expiry = + typeof exception?.expiresAt === "string" + ? Date.parse(exception.expiresAt) + : Number.NaN; + const validException = + exception && + typeof exception.owner === "string" && + exception.owner.trim() && + typeof exception.reviewer === "string" && + exception.reviewer.trim() && + exception.owner !== exception.reviewer && + typeof exception.reason === "string" && + exception.reason.trim() && + Number.isFinite(expiry) && + expiry > now.getTime(); + if (!validException) { + blocking.push( + `${finding.id}:${finding.packageName}@${finding.version}:${severity}`, + ); + } + } + return Object.freeze({ + passed: failures.length === 0 && blocking.length === 0, + failures: Object.freeze(failures), + blocking: Object.freeze(blocking), + }); +} + +/** + * @param {Readonly>} sbom + * @param {Readonly>} inventory + * @param {Readonly>} provenance + * @param {string} distDigest + */ +export function verifySupplyChainCoherence( + sbom, + inventory, + provenance, + distDigest, +) { + const failures = []; + const componentCount = Array.isArray(sbom.components) + ? sbom.components.length + : -1; + const dependencyCount = Array.isArray(inventory.dependencies) + ? inventory.dependencies.length + : -2; + if (componentCount !== dependencyCount) { + failures.push("SBOM component count does not match inventory"); + } + const metadata = + /** @type {Record} */ (sbom.metadata ?? {}); + const properties = + /** @type {Array<{name?: string, value?: string}>} */ ( + metadata.properties ?? [] + ); + if (properties.find( + /** @param {{name?: string, value?: string}} property */ + (property) => + property.name === "ca:lockfileSha256" && + property.value === inventory.lockfileSha256, + ) === undefined) { + failures.push("SBOM lockfile digest does not match inventory"); + } + const subject = + /** @type {Array>} */ (provenance.subject ?? [])[0]; + const subjectDigest = + /** @type {Record} */ (subject?.digest ?? {}); + if (subjectDigest.sha256 !== distDigest) { + failures.push("provenance subject does not match built dist digest"); + } + const predicate = + /** @type {Record} */ (provenance.predicate ?? {}); + const materials = + /** @type {Record} */ (predicate.materials ?? {}); + if (materials.lockfileSha256 !== inventory.lockfileSha256) { + failures.push("provenance lockfile material does not match inventory"); + } + return Object.freeze({ + passed: failures.length === 0, + failures: Object.freeze(failures), + }); +} diff --git a/scripts/security-scan.mjs b/scripts/security-scan.mjs index 684ee77..15b1338 100644 --- a/scripts/security-scan.mjs +++ b/scripts/security-scan.mjs @@ -1,10 +1,37 @@ -import { mkdir, readFile, readdir, writeFile } from "node:fs/promises"; +import { createHash } from "node:crypto"; +import { mkdir, readFile, readdir, stat, writeFile } from "node:fs/promises"; import path from "node:path"; -const scanRoots = ["src", "dist"]; -const findings = /** @type {Array<{ruleId: string, file: string}>} */ ([]); +/** @param {string} name @param {string} fallback */ +function argumentValue(name, fallback) { + const index = process.argv.indexOf(name); + return index >= 0 && process.argv[index + 1] + ? process.argv[index + 1] + : fallback; +} + +const policyPath = argumentValue( + "--policy", + "config/security/secret-scan-policy.json", +); +const artifactPath = argumentValue( + "--artifact", + "artifacts/security/scan.sarif", +); +const policy = JSON.parse(await readFile(policyPath, "utf8")); +const findings = + /** @type {Array<{ + * ruleId: string, + * file: string, + * line: number, + * fingerprint: string + * }>} */ ([]); +const policyFailures = []; const patterns = [ - { id: "private-key", expression: /-----BEGIN (?:RSA |EC )?PRIVATE KEY-----/g }, + { + id: "private-key", + expression: /-----BEGIN (?:RSA |EC )?PRIVATE KEY-----/g, + }, { id: "aws-access-key", expression: /\bAKIA[0-9A-Z]{16}\b/g }, { id: "github-token", expression: /\bgh[pousr]_[A-Za-z0-9_]{30,}\b/g }, { @@ -14,35 +41,101 @@ const patterns = [ }, ]; -/** @param {string} directory @returns {Promise} */ -async function filesWithin(directory) { - const entries = await readdir(directory, { withFileTypes: true }); - const nested = /** @type {string[][]} */ (await Promise.all( - entries.map((entry) => { - const target = path.join(directory, entry.name); - return entry.isDirectory() ? filesWithin(target) : [target]; - }), - )); - return nested.flat(); +/** @param {string} target @returns {Promise} */ +async function filesWithin(target) { + try { + const metadata = await stat(target); + if (metadata.isFile()) return [target]; + const entries = await readdir(target, { withFileTypes: true }); + const nested = /** @type {string[][]} */ (await Promise.all( + entries.map((entry) => { + const child = path.join(target, entry.name); + return entry.isDirectory() ? filesWithin(child) : [child]; + }), + )); + return nested.flat(); + } catch { + return []; + } } -for (const root of scanRoots) { - for (const scanFile of await filesWithin(root)) { - if (/\.(png|jpg|jpeg|gif|woff2?|zip)$/i.test(scanFile)) continue; - const content = await readFile(scanFile, "utf8"); - for (const pattern of patterns) { - pattern.expression.lastIndex = 0; - if (pattern.expression.test(content)) { - findings.push({ ruleId: pattern.id, file: scanFile }); - } +const excluded = new Set( + /** @type {string[]} */ (policy.excludedPaths ?? []).map((entry) => + entry.replaceAll("\\", "/"), + ), +); +const allowlist = + /** @type {Array<{ + * path: string, + * ruleId: string, + * owner: string, + * reason: string, + * expiresAt: string + * }>} */ (policy.allowlist ?? []); +for (const entry of allowlist) { + const expiry = Date.parse(entry.expiresAt); + if ( + !entry.path.startsWith("tests/") || + !entry.owner?.trim() || + !entry.reason?.trim() || + !Number.isFinite(expiry) || + expiry <= Date.now() + ) { + policyFailures.push( + `invalid or expired secret allowlist entry: ${entry.path}:${entry.ruleId}`, + ); + } +} + +const roots = [ + ...(/** @type {string[]} */ (policy.trackedRoots ?? [])), + ...(/** @type {string[]} */ (policy.generatedRoots ?? [])), +]; +const scanFiles = ( + await Promise.all(roots.map((root) => filesWithin(root))) +).flat(); +for (const scanFile of [...new Set(scanFiles)].sort()) { + const normalized = scanFile.replaceAll("\\", "/"); + if ( + [...excluded].some( + (entry) => normalized === entry || normalized.startsWith(`${entry}/`), + ) || + /\.(?:png|jpe?g|gif|webp|woff2?|zip|gz|sarif)$/i.test(normalized) + ) { + continue; + } + let content; + try { + content = await readFile(scanFile, "utf8"); + } catch { + continue; + } + for (const pattern of patterns) { + pattern.expression.lastIndex = 0; + for (const match of content.matchAll(pattern.expression)) { + const isAllowed = allowlist.some( + (entry) => + entry.path === normalized && + entry.ruleId === pattern.id && + Date.parse(entry.expiresAt) > Date.now(), + ); + if (isAllowed) continue; + const prefix = content.slice(0, match.index); + findings.push({ + ruleId: pattern.id, + file: normalized, + line: prefix.split(/\r?\n/).length, + fingerprint: createHash("sha256") + .update(`${pattern.id}:${normalized}:${String(match.index)}`) + .digest("hex"), + }); } } } const sarif = { version: "2.1.0", - $schema: - "https://json.schemastore.org/sarif-2.1.0.json", + $schema: "https://json.schemastore.org/sarif-2.1.0.json", runs: [ { tool: { @@ -54,29 +147,41 @@ const sarif = { })), }, }, - results: findings.map((finding) => ({ - ruleId: finding.ruleId, - message: { text: "Potential secret material must be removed." }, - locations: [ - { - physicalLocation: { - artifactLocation: { uri: finding.file }, - }, + results: [ + ...findings.map((finding) => ({ + ruleId: finding.ruleId, + message: { + text: "Potential secret material must be removed.", }, - ], - })), + partialFingerprints: { + primaryLocationLineHash: finding.fingerprint, + }, + locations: [ + { + physicalLocation: { + artifactLocation: { uri: finding.file }, + region: { startLine: finding.line }, + }, + }, + ], + })), + ...policyFailures.map((failure) => ({ + ruleId: "invalid-allowlist", + message: { text: failure }, + })), + ], }, ], }; -await mkdir("artifacts/security", { recursive: true }); -await writeFile( - "artifacts/security/scan.sarif", - `${JSON.stringify(sarif, null, 2)}\n`, -); - -if (findings.length > 0) { - process.stderr.write(`Security scan found ${findings.length} blocking result(s).\n`); +await mkdir(path.dirname(artifactPath), { recursive: true }); +await writeFile(artifactPath, `${JSON.stringify(sarif, null, 2)}\n`); +if (findings.length > 0 || policyFailures.length > 0) { + process.stderr.write( + `Security scan found ${findings.length + policyFailures.length} blocking result(s).\n`, + ); process.exit(1); } -process.stdout.write("Source and built-asset secret scan: PASS\n"); +process.stdout.write( + `Tracked source, config, built asset and artifact secret scan: PASS (${scanFiles.length} files)\n`, +); diff --git a/scripts/test-sample-removal.mjs b/scripts/test-sample-removal.mjs index 4899823..9d9e46d 100644 --- a/scripts/test-sample-removal.mjs +++ b/scripts/test-sample-removal.mjs @@ -18,6 +18,7 @@ const featureOwnedPaths = [ featureSource, featureTests, "tests/e2e/reference-form.spec.js", + "tests/e2e/reference-route.spec.js", "tests/mocks", ]; const copyTargets = [ diff --git a/scripts/update-dependency-baseline.mjs b/scripts/update-dependency-baseline.mjs new file mode 100644 index 0000000..5f14fe8 --- /dev/null +++ b/scripts/update-dependency-baseline.mjs @@ -0,0 +1,47 @@ +import { spawnSync } from "node:child_process"; +import { readFile, writeFile } from "node:fs/promises"; + +import { supplyChainDigest } from "./lib/supply-chain.mjs"; + +const owner = process.env.DEPENDENCY_BASELINE_OWNER; +const reason = process.env.DEPENDENCY_BASELINE_REASON; +if (!owner?.trim() || !reason?.trim()) { + process.stderr.write( + "DEPENDENCY_BASELINE_OWNER and DEPENDENCY_BASELINE_REASON are required.\n", + ); + process.exit(2); +} + +const commands = /** @type {Array<[string, string[]]>} */ ([ + ["corepack", ["pnpm", "build"]], + ["node", ["scripts/generate-supply-chain.mjs", "--no-baseline"]], +]); +for (const [command, args] of commands) { + const result = spawnSync(command, args, { stdio: "inherit" }); + if (result.status !== 0) process.exit(result.status ?? 1); +} + +const inventory = JSON.parse( + await readFile("artifacts/release/dependency-inventory.json", "utf8"), +); +await writeFile( + "config/security/dependency-baseline.json", + `${JSON.stringify(inventory, null, 2)}\n`, +); +await writeFile( + "config/security/dependency-baseline.approval.json", + `${JSON.stringify( + { + schemaVersion: 1, + snapshotDigest: supplyChainDigest(inventory), + owner, + reason, + approvedAt: new Date().toISOString(), + }, + null, + 2, + )}\n`, +); +process.stdout.write( + `Dependency baseline approved: ${inventory.dependencyCount} packages\n`, +); diff --git a/scripts/verify-reproducible-build.mjs b/scripts/verify-reproducible-build.mjs new file mode 100644 index 0000000..74543d4 --- /dev/null +++ b/scripts/verify-reproducible-build.mjs @@ -0,0 +1,76 @@ +import { spawnSync } from "node:child_process"; +import { mkdir, readFile, readdir, writeFile } from "node:fs/promises"; +import path from "node:path"; + +import { supplyChainDigest } from "./lib/supply-chain.mjs"; + +/** @param {string} directory @returns {Promise} */ +async function filesWithin(directory) { + const entries = await readdir(directory, { withFileTypes: true }); + const nested = /** @type {string[][]} */ (await Promise.all( + entries.map((entry) => { + const target = path.join(directory, entry.name); + return entry.isDirectory() ? filesWithin(target) : [target]; + }), + )); + return nested.flat().sort(); +} + +async function distDigest() { + const rows = await Promise.all( + (await filesWithin("dist")).map(async (file) => ({ + path: path.relative("dist", file).replaceAll("\\", "/"), + bytes: (await readFile(file)).byteLength, + content: supplyChainDigest(await readFile(file)), + })), + ); + return supplyChainDigest(rows); +} + +function build(environment = process.env) { + return spawnSync("corepack", ["pnpm", "build"], { + env: environment, + encoding: "utf8", + maxBuffer: 16 * 1024 * 1024, + }); +} + +const deterministicEnvironment = { + ...process.env, + SOURCE_DATE_EPOCH: "946684800", +}; +const firstBuild = build(deterministicEnvironment); +const firstDigest = firstBuild.status === 0 ? await distDigest() : "BUILD_FAILED"; +const secondBuild = build(deterministicEnvironment); +const secondDigest = + secondBuild.status === 0 ? await distDigest() : "BUILD_FAILED"; +const restoreBuild = build(); +const passed = + firstBuild.status === 0 && + secondBuild.status === 0 && + restoreBuild.status === 0 && + firstDigest === secondDigest; + +await mkdir("artifacts/release", { recursive: true }); +await writeFile( + "artifacts/release/reproducible-build.json", + `${JSON.stringify( + { + schemaVersion: 1, + sourceDateEpoch: deterministicEnvironment.SOURCE_DATE_EPOCH, + firstDigest, + secondDigest, + restored: restoreBuild.status === 0, + status: passed ? "PASS" : "FAIL", + }, + null, + 2, + )}\n`, +); +if (!passed) { + process.stderr.write( + `Reproducible build failed: first=${firstDigest} second=${secondDigest}\n`, + ); + process.exit(1); +} +process.stdout.write(`Reproducible build: PASS (${firstDigest})\n`); diff --git a/scripts/verify-supply-chain-artifacts.mjs b/scripts/verify-supply-chain-artifacts.mjs new file mode 100644 index 0000000..6fcf41a --- /dev/null +++ b/scripts/verify-supply-chain-artifacts.mjs @@ -0,0 +1,121 @@ +import { createHash } from "node:crypto"; +import { mkdir, readFile, readdir, stat, writeFile } from "node:fs/promises"; +import path from "node:path"; + +import { + isValidSha512Integrity, + parsePnpmLockfilePackages, + supplyChainDigest, + verifySupplyChainCoherence, +} from "./lib/supply-chain.mjs"; + +/** @param {string} directory @returns {Promise} */ +async function filesWithin(directory) { + const entries = await readdir(directory, { withFileTypes: true }); + const nested = /** @type {string[][]} */ (await Promise.all( + entries.map((entry) => { + const target = path.join(directory, entry.name); + return entry.isDirectory() ? filesWithin(target) : [target]; + }), + )); + return nested.flat().sort(); +} + +const inventory = JSON.parse( + await readFile("artifacts/release/dependency-inventory.json", "utf8"), +); +const sbom = JSON.parse( + await readFile("artifacts/release/sbom.cdx.json", "utf8"), +); +const provenance = JSON.parse( + await readFile("artifacts/release/provenance.json", "utf8"), +); +const verification = JSON.parse( + await readFile( + "artifacts/security/supply-chain-verification.json", + "utf8", + ), +); +const lockfileText = await readFile("pnpm-lock.yaml", "utf8"); +const lockfileSha256 = createHash("sha256") + .update(lockfileText) + .digest("hex"); +const outputs = await Promise.all( + (await filesWithin("dist")).map(async (file) => { + const content = await readFile(file); + return { + path: file.replaceAll("\\", "/"), + bytes: (await stat(file)).size, + sha256: createHash("sha256").update(content).digest("hex"), + }; + }), +); +const distDigest = supplyChainDigest(outputs); +const coherence = verifySupplyChainCoherence( + sbom, + inventory, + provenance, + distDigest, +); +const failures = [...coherence.failures]; +if ( + inventory.lockfileSha256 !== lockfileSha256 || + verification.lockfileSha256 !== lockfileSha256 +) { + failures.push("inventory/verification lockfile digest mismatch"); +} +if ( + verification.distSha256 !== distDigest || + verification.sbomSha256 !== supplyChainDigest(sbom) +) { + failures.push("verification digest set is incoherent"); +} +const lockRows = parsePnpmLockfilePackages(lockfileText); +const inventoryRows = + /** @type {Array>} */ ( + inventory.dependencies ?? [] + ); +const inventoryByIdentity = new Map( + inventoryRows.map((entry) => [ + `${entry.name}@${entry.version}`, + entry, + ]), +); +if (lockRows.length !== inventoryRows.length) { + failures.push("transitive dependency count differs from lockfile"); +} +for (const lockRow of lockRows) { + const identity = `${lockRow.name}@${lockRow.version}`; + const dependency = inventoryByIdentity.get(identity); + if ( + !dependency || + dependency.integrity !== lockRow.integrity || + !isValidSha512Integrity(lockRow.integrity) + ) { + failures.push(`lockfile inventory integrity mismatch: ${identity}`); + } +} + +const report = { + schemaVersion: 1, + status: failures.length === 0 ? "PASS" : "FAIL", + dependencyCount: inventoryRows.length, + lockfileSha256, + distSha256: distDigest, + sbomSha256: supplyChainDigest(sbom), + failures, +}; +await mkdir("artifacts/security", { recursive: true }); +await writeFile( + "artifacts/security/supply-chain-coherence.json", + `${JSON.stringify(report, null, 2)}\n`, +); +if (failures.length > 0) { + process.stderr.write( + `Supply-chain artifact coherence failed:\n- ${failures.join("\n- ")}\n`, + ); + process.exit(1); +} +process.stdout.write( + `Supply-chain artifact coherence: PASS (${inventoryRows.length} dependencies)\n`, +); diff --git a/scripts/verify-supply-chain-promotion.mjs b/scripts/verify-supply-chain-promotion.mjs new file mode 100644 index 0000000..a9a6951 --- /dev/null +++ b/scripts/verify-supply-chain-promotion.mjs @@ -0,0 +1,30 @@ +import { mkdir, readFile, writeFile } from "node:fs/promises"; + +const verification = JSON.parse( + await readFile( + "artifacts/security/supply-chain-verification.json", + "utf8", + ), +); +const passed = verification.promotionStatus === "PASS"; +const report = { + schemaVersion: 1, + status: passed ? "PASS" : "FAIL_UNVERIFIED", + vulnerabilityStatus: verification.vulnerabilityStatus, + provenanceAttestationStatus: + verification.provenanceAttestationStatus, + lockfileSha256: verification.lockfileSha256, + distSha256: verification.distSha256, +}; +await mkdir("artifacts/security", { recursive: true }); +await writeFile( + "artifacts/security/promotion-verification.json", + `${JSON.stringify(report, null, 2)}\n`, +); +if (!passed) { + process.stderr.write( + "Supply-chain promotion is FAIL_UNVERIFIED: external vulnerability and signed provenance evidence are required.\n", + ); + process.exit(1); +} +process.stdout.write("Supply-chain promotion evidence: PASS\n"); diff --git a/tests/e2e/app-shell.spec.js b/tests/e2e/app-shell.spec.js index 097cbf4..32e4b40 100644 --- a/tests/e2e/app-shell.spec.js +++ b/tests/e2e/app-shell.spec.js @@ -1,6 +1,4 @@ import { expect, test } from "../support/browser/strict-browser-test.js"; -import { successEnvelope } from "../mocks/contracts/envelopes.js"; -import { ROUTE_REGISTRY } from "../../src/features/installed-feature-contracts.js"; test("boots the public app shell", async ({ page }) => { await page.goto("/"); @@ -26,39 +24,6 @@ test("navigates to a registry-backed example without a page reload", async ({ ).toBeFocused(); }); -test("opens the protected integration route through the local demo seam", async ({ - page, -}) => { - const protectedRoute = Object.values(ROUTE_REGISTRY).find( - (definition) => definition.access === "integration-defined", - ); - if (!protectedRoute) throw new Error("An integration route is required"); - await page.route( - "http://localhost:8080/api/reference-resources?*", - (route) => - route.fulfill({ - json: successEnvelope([ - { - id: "browser-reference", - name: "Browser reference", - createdAt: "2026-07-26T00:00:00.000Z", - }, - ]), - }), - ); - await page.goto(protectedRoute.path); - await expect( - page.getByRole("heading", { name: "세션이 필요합니다." }), - ).toBeVisible(); - - await page.getByRole("button", { name: "로그인 시작" }).click(); - - await expect( - page.getByRole("heading", { name: protectedRoute.title }), - ).toBeVisible(); - await expect(page.getByText("인증됨")).toBeVisible(); -}); - test("provides an escape-dismissible mobile navigation", async ({ page }) => { await page.setViewportSize({ width: 390, height: 844 }); await page.goto("/"); diff --git a/tests/e2e/reference-route.spec.js b/tests/e2e/reference-route.spec.js new file mode 100644 index 0000000..8f205a7 --- /dev/null +++ b/tests/e2e/reference-route.spec.js @@ -0,0 +1,36 @@ +import { expect, test } from "../support/browser/strict-browser-test.js"; +import { successEnvelope } from "../mocks/contracts/envelopes.js"; +import { ROUTE_REGISTRY } from "../../src/features/installed-feature-contracts.js"; + +test("opens the protected integration route through the local demo seam", async ({ + page, +}) => { + const protectedRoute = Object.values(ROUTE_REGISTRY).find( + (definition) => definition.access === "integration-defined", + ); + if (!protectedRoute) throw new Error("An integration route is required"); + await page.route( + "http://localhost:8080/api/reference-resources?*", + (route) => + route.fulfill({ + json: successEnvelope([ + { + id: "browser-reference", + name: "Browser reference", + createdAt: "2026-07-26T00:00:00.000Z", + }, + ]), + }), + ); + await page.goto(protectedRoute.path); + await expect( + page.getByRole("heading", { name: "세션이 필요합니다." }), + ).toBeVisible(); + + await page.getByRole("button", { name: "로그인 시작" }).click(); + + await expect( + page.getByRole("heading", { name: protectedRoute.title }), + ).toBeVisible(); + await expect(page.getByText("인증됨")).toBeVisible(); +}); diff --git a/tests/fixtures/security/secret-detection/allowed/test-credentials.ts b/tests/fixtures/security/secret-detection/allowed/test-credentials.ts new file mode 100644 index 0000000..19f40aa --- /dev/null +++ b/tests/fixtures/security/secret-detection/allowed/test-credentials.ts @@ -0,0 +1 @@ +export const client_secret = "fixture-only-secret-value"; diff --git a/tests/fixtures/security/secret-detection/forbidden-policy.json b/tests/fixtures/security/secret-detection/forbidden-policy.json new file mode 100644 index 0000000..434e141 --- /dev/null +++ b/tests/fixtures/security/secret-detection/forbidden-policy.json @@ -0,0 +1,9 @@ +{ + "schemaVersion": 1, + "trackedRoots": [ + "tests/fixtures/security/secret-detection/forbidden" + ], + "generatedRoots": [], + "excludedPaths": [], + "allowlist": [] +} diff --git a/tests/fixtures/security/secret-detection/forbidden/config.json b/tests/fixtures/security/secret-detection/forbidden/config.json new file mode 100644 index 0000000..f4de431 --- /dev/null +++ b/tests/fixtures/security/secret-detection/forbidden/config.json @@ -0,0 +1,3 @@ +{ + "client_secret": "synthetic-forbidden-secret" +} diff --git a/tests/fixtures/security/secret-detection/forbidden/dist.js b/tests/fixtures/security/secret-detection/forbidden/dist.js new file mode 100644 index 0000000..eeb6d80 --- /dev/null +++ b/tests/fixtures/security/secret-detection/forbidden/dist.js @@ -0,0 +1 @@ +globalThis.password = "synthetic-built-secret"; diff --git a/tests/fixtures/security/secret-detection/forbidden/source.ts b/tests/fixtures/security/secret-detection/forbidden/source.ts new file mode 100644 index 0000000..f8ec340 --- /dev/null +++ b/tests/fixtures/security/secret-detection/forbidden/source.ts @@ -0,0 +1 @@ +export const leaked = "AKIAABCDEFGHIJKLMNOP"; diff --git a/tests/unit/supply-chain.test.ts b/tests/unit/supply-chain.test.ts new file mode 100644 index 0000000..e5446bb --- /dev/null +++ b/tests/unit/supply-chain.test.ts @@ -0,0 +1,89 @@ +import { describe, expect, it } from "vitest"; + +import { + diffDependencyInventories, + isValidSha512Integrity, + parsePnpmLockfilePackages, + supplyChainDigest, + validateDependencyReview, + validateLicensePolicy, +} from "../../scripts/lib/supply-chain.mjs"; + +const integrity = `sha512-${Buffer.alloc(64, 7).toString("base64")}`; +const dependency = { + name: "fixture", + version: "1.0.0", + direct: true, + scope: "production", + optional: false, + license: "MIT", + integrity, + dependencies: [], +}; + +describe("supply-chain policy", () => { + it("parses every top-level lockfile package and validates SRI", () => { + const parsed = parsePnpmLockfilePackages(` +packages: + + '@scope/one@1.0.0': + resolution: {integrity: ${integrity}} + + two@2.0.0: + resolution: {integrity: ${integrity}} + +snapshots: +`); + expect(parsed).toEqual([ + { name: "@scope/one", version: "1.0.0", integrity }, + { name: "two", version: "2.0.0", integrity }, + ]); + expect(parsed.every((entry) => isValidSha512Integrity(entry.integrity))).toBe( + true, + ); + }); + + it("keeps inventory digests stable when dependency ordering changes", () => { + const other = { ...dependency, name: "other" }; + expect(supplyChainDigest([dependency, other])).toBe( + supplyChainDigest([other, dependency]), + ); + }); + + it("calculates actual additions and requires independent high-risk review", () => { + const before = { dependencies: [] }; + const after = { dependencies: [dependency] }; + const diff = diffDependencyInventories(before, after); + expect(diff.added).toEqual(["fixture@1.0.0"]); + expect( + validateDependencyReview(diff, after, { + changes: [ + { + changeId: "add:fixture@1.0.0", + owner: "one", + reviewer: "one", + reason: "fixture", + rollback: "remove", + }, + ], + }).passed, + ).toBe(false); + }); + + it("allows explicit policy licenses and rejects denied licenses", () => { + expect( + validateLicensePolicy( + { dependencies: [dependency] }, + { allowedLicenses: ["MIT"], deniedLicensePatterns: ["AGPL"] }, + ).passed, + ).toBe(true); + expect( + validateLicensePolicy( + { + dependencies: [{ ...dependency, license: "AGPL-3.0" }], + }, + { allowedLicenses: ["MIT"], deniedLicensePatterns: ["AGPL"] }, + ).passed, + ).toBe(false); + }); +});