diff --git a/NuGet.Config b/NuGet.Config
new file mode 100644
index 0000000..c848225
--- /dev/null
+++ b/NuGet.Config
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/apps/api/package.json b/apps/api/package.json
new file mode 100644
index 0000000..e9121d1
--- /dev/null
+++ b/apps/api/package.json
@@ -0,0 +1,23 @@
+{
+ "name": "@dada/api",
+ "version": "0.0.0",
+ "private": true,
+ "type": "module",
+ "scripts": {
+ "build": "tsc -p tsconfig.json",
+ "start": "node dist/main.js",
+ "typecheck": "tsc --noEmit -p tsconfig.json"
+ },
+ "dependencies": {
+ "@fastify/swagger": "9.8.1",
+ "@sinclair/typebox": "0.34.52",
+ "better-sqlite3": "13.0.1",
+ "drizzle-orm": "0.45.2",
+ "fastify": "5.10.0"
+ },
+ "devDependencies": {
+ "@types/better-sqlite3": "7.6.13",
+ "@types/node": "24.13.3",
+ "typescript": "7.0.2"
+ }
+}
diff --git a/apps/api/src/app.ts b/apps/api/src/app.ts
new file mode 100644
index 0000000..d183983
--- /dev/null
+++ b/apps/api/src/app.ts
@@ -0,0 +1,17 @@
+import swagger from "@fastify/swagger";
+import Fastify from "fastify";
+
+export function createApp() {
+ const app = Fastify({ logger: false });
+
+ void app.register(swagger, {
+ openapi: {
+ info: {
+ title: "Dada P0-A",
+ version: "0.0.0",
+ },
+ },
+ });
+
+ return app;
+}
diff --git a/apps/api/src/main.ts b/apps/api/src/main.ts
new file mode 100644
index 0000000..0e1f657
--- /dev/null
+++ b/apps/api/src/main.ts
@@ -0,0 +1,8 @@
+import { createApp } from "./app.js";
+
+const app = createApp();
+
+await app.listen({
+ host: "127.0.0.1",
+ port: 43121,
+});
diff --git a/apps/api/tsconfig.json b/apps/api/tsconfig.json
new file mode 100644
index 0000000..5425508
--- /dev/null
+++ b/apps/api/tsconfig.json
@@ -0,0 +1,12 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "module": "NodeNext",
+ "moduleResolution": "NodeNext",
+ "lib": ["ES2024"],
+ "types": ["node"],
+ "outDir": "dist",
+ "rootDir": "src"
+ },
+ "include": ["src"]
+}
diff --git a/apps/web/index.html b/apps/web/index.html
new file mode 100644
index 0000000..940c05e
--- /dev/null
+++ b/apps/web/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+ Dada
+
+
+
+
+
+
diff --git a/apps/web/package.json b/apps/web/package.json
new file mode 100644
index 0000000..069680e
--- /dev/null
+++ b/apps/web/package.json
@@ -0,0 +1,24 @@
+{
+ "name": "@dada/web",
+ "version": "0.0.0",
+ "private": true,
+ "type": "module",
+ "scripts": {
+ "build": "vite build",
+ "typecheck": "tsc --noEmit -p tsconfig.json"
+ },
+ "dependencies": {
+ "@vibrant/core": "4.0.4",
+ "@vibrant/quantizer-mmcq": "4.0.4",
+ "fabric": "7.4.0",
+ "react": "19.2.8",
+ "react-dom": "19.2.8"
+ },
+ "devDependencies": {
+ "@types/react": "19.2.17",
+ "@types/react-dom": "19.2.3",
+ "@vitejs/plugin-react": "6.0.4",
+ "typescript": "7.0.2",
+ "vite": "8.1.5"
+ }
+}
diff --git a/apps/web/src/main.tsx b/apps/web/src/main.tsx
new file mode 100644
index 0000000..c43edd8
--- /dev/null
+++ b/apps/web/src/main.tsx
@@ -0,0 +1,16 @@
+import { StrictMode } from "react";
+import { createRoot } from "react-dom/client";
+
+import { ToolchainProbe } from "./toolchain-probe.js";
+
+const root = document.getElementById("root");
+
+if (!root) {
+ throw new Error("Dada web root element is missing.");
+}
+
+createRoot(root).render(
+
+
+ ,
+);
diff --git a/apps/web/src/toolchain-probe.tsx b/apps/web/src/toolchain-probe.tsx
new file mode 100644
index 0000000..830aa4d
--- /dev/null
+++ b/apps/web/src/toolchain-probe.tsx
@@ -0,0 +1,21 @@
+import { Rect, version as fabricVersion } from "fabric";
+import { renderToStaticMarkup } from "react-dom/server";
+
+export function ToolchainProbe() {
+ return ;
+}
+
+export function renderToolchainProbe() {
+ const reactMarkup = renderToStaticMarkup();
+ const fabricSvg = new Rect({
+ fill: "#111111",
+ height: 16,
+ width: 16,
+ }).toSVG();
+
+ return {
+ fabricSvg,
+ fabricVersion,
+ reactMarkup,
+ };
+}
diff --git a/apps/web/tsconfig.json b/apps/web/tsconfig.json
new file mode 100644
index 0000000..35f22c6
--- /dev/null
+++ b/apps/web/tsconfig.json
@@ -0,0 +1,11 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "module": "ESNext",
+ "moduleResolution": "Bundler",
+ "jsx": "react-jsx",
+ "lib": ["ES2024", "DOM", "DOM.Iterable"],
+ "types": ["vite/client"]
+ },
+ "include": ["src", "vite.config.ts"]
+}
diff --git a/apps/web/vite.config.ts b/apps/web/vite.config.ts
new file mode 100644
index 0000000..58676f7
--- /dev/null
+++ b/apps/web/vite.config.ts
@@ -0,0 +1,6 @@
+import react from "@vitejs/plugin-react";
+import { defineConfig } from "vite";
+
+export default defineConfig({
+ plugins: [react()],
+});
diff --git a/apps/worker/package.json b/apps/worker/package.json
new file mode 100644
index 0000000..9281266
--- /dev/null
+++ b/apps/worker/package.json
@@ -0,0 +1,19 @@
+{
+ "name": "@dada/worker",
+ "version": "0.0.0",
+ "private": true,
+ "type": "module",
+ "scripts": {
+ "build": "tsc -p tsconfig.json",
+ "typecheck": "tsc --noEmit -p tsconfig.json"
+ },
+ "dependencies": {
+ "better-sqlite3": "13.0.1",
+ "drizzle-orm": "0.45.2"
+ },
+ "devDependencies": {
+ "@types/better-sqlite3": "7.6.13",
+ "@types/node": "24.13.3",
+ "typescript": "7.0.2"
+ }
+}
diff --git a/apps/worker/src/worker.ts b/apps/worker/src/worker.ts
new file mode 100644
index 0000000..7088a88
--- /dev/null
+++ b/apps/worker/src/worker.ts
@@ -0,0 +1,13 @@
+import { parentPort } from "node:worker_threads";
+
+export function handleWorkerProbe(message: unknown) {
+ return message === "ping" ? "pong" : null;
+}
+
+const workerPort = parentPort;
+
+if (workerPort) {
+ workerPort.on("message", (message: unknown) => {
+ workerPort.postMessage(handleWorkerProbe(message));
+ });
+}
diff --git a/apps/worker/tsconfig.json b/apps/worker/tsconfig.json
new file mode 100644
index 0000000..5425508
--- /dev/null
+++ b/apps/worker/tsconfig.json
@@ -0,0 +1,12 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "module": "NodeNext",
+ "moduleResolution": "NodeNext",
+ "lib": ["ES2024"],
+ "types": ["node"],
+ "outDir": "dist",
+ "rootDir": "src"
+ },
+ "include": ["src"]
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..8995e5b
--- /dev/null
+++ b/package.json
@@ -0,0 +1,37 @@
+{
+ "name": "dada-p0a",
+ "version": "0.0.0",
+ "private": true,
+ "packageManager": "pnpm@10.28.2",
+ "engines": {
+ "node": "24.13.0"
+ },
+ "scripts": {
+ "build": "pnpm -r --if-present build && dotnet build supervisor/Dada.Supervisor/Dada.Supervisor.csproj --configuration Release",
+ "typecheck": "pnpm -r --if-present typecheck",
+ "test:unit:contract": "node --test tests/toolchain/frozen-toolchain.test.mjs",
+ "test:unit": "pnpm run test:unit:contract && vitest run tests/unit",
+ "test:integration": "vitest run tests/integration",
+ "test:api": "vitest run tests/api",
+ "test:worker": "pnpm --filter @dada/worker build && node scripts/worker-smoke.mjs",
+ "test:e2e": "node scripts/validate-layer-scope.mjs E2E",
+ "test:visual": "node scripts/validate-layer-scope.mjs VISUAL",
+ "test:performance": "node scripts/validate-layer-scope.mjs PERFORMANCE",
+ "test:security": "node scripts/verify-frozen-dependencies.mjs && node scripts/redaction-scan.mjs",
+ "test:package": "pnpm run typecheck && pnpm --filter @dada/web build && pnpm --filter @dada/api build && pnpm --filter @dada/worker build && node scripts/package-smoke.mjs",
+ "validate:tdd-trace": "node scripts/validate-tdd-trace.mjs",
+ "validate:external": "node scripts/validate-external.mjs",
+ "test:all": "pnpm test:unit && pnpm test:integration && pnpm test:api && pnpm test:worker && pnpm test:e2e && pnpm test:visual && pnpm test:performance && pnpm test:security && pnpm test:package && pnpm validate:tdd-trace",
+ "test:wp0-01": "node scripts/run-wp0-01-validation.mjs"
+ },
+ "devDependencies": {
+ "@playwright/test": "1.62.0",
+ "@types/better-sqlite3": "7.6.13",
+ "@types/node": "24.13.3",
+ "@types/react": "19.2.17",
+ "@types/react-dom": "19.2.3",
+ "typescript": "7.0.2",
+ "vite": "8.1.5",
+ "vitest": "4.1.10"
+ }
+}
diff --git a/packages/shared-contracts/package.json b/packages/shared-contracts/package.json
new file mode 100644
index 0000000..5688fb4
--- /dev/null
+++ b/packages/shared-contracts/package.json
@@ -0,0 +1,20 @@
+{
+ "name": "@dada/shared-contracts",
+ "version": "0.0.0",
+ "private": true,
+ "type": "module",
+ "exports": {
+ ".": "./dist/index.js"
+ },
+ "types": "./dist/index.d.ts",
+ "scripts": {
+ "build": "tsc -p tsconfig.json",
+ "typecheck": "tsc --noEmit -p tsconfig.json"
+ },
+ "dependencies": {
+ "@sinclair/typebox": "0.34.52"
+ },
+ "devDependencies": {
+ "typescript": "7.0.2"
+ }
+}
diff --git a/packages/shared-contracts/src/index.ts b/packages/shared-contracts/src/index.ts
new file mode 100644
index 0000000..14a9f90
--- /dev/null
+++ b/packages/shared-contracts/src/index.ts
@@ -0,0 +1 @@
+export { Type } from "@sinclair/typebox";
diff --git a/packages/shared-contracts/tsconfig.json b/packages/shared-contracts/tsconfig.json
new file mode 100644
index 0000000..5bb4903
--- /dev/null
+++ b/packages/shared-contracts/tsconfig.json
@@ -0,0 +1,12 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "module": "NodeNext",
+ "moduleResolution": "NodeNext",
+ "lib": ["ES2024"],
+ "declaration": true,
+ "outDir": "dist",
+ "rootDir": "src"
+ },
+ "include": ["src"]
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
new file mode 100644
index 0000000..e1cd060
--- /dev/null
+++ b/pnpm-lock.yaml
@@ -0,0 +1,2424 @@
+lockfileVersion: '9.0'
+
+settings:
+ autoInstallPeers: true
+ excludeLinksFromLockfile: false
+
+importers:
+
+ .:
+ devDependencies:
+ '@playwright/test':
+ specifier: 1.62.0
+ version: 1.62.0
+ '@types/better-sqlite3':
+ specifier: 7.6.13
+ version: 7.6.13
+ '@types/node':
+ specifier: 24.13.3
+ version: 24.13.3
+ '@types/react':
+ specifier: 19.2.17
+ version: 19.2.17
+ '@types/react-dom':
+ specifier: 19.2.3
+ version: 19.2.3(@types/react@19.2.17)
+ typescript:
+ specifier: 7.0.2
+ version: 7.0.2
+ vite:
+ specifier: 8.1.5
+ version: 8.1.5(@types/node@24.13.3)(yaml@2.9.0)
+ vitest:
+ specifier: 4.1.10
+ version: 4.1.10(@types/node@24.13.3)(jsdom@26.1.0(canvas@3.2.3))(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0))
+
+ apps/api:
+ dependencies:
+ '@fastify/swagger':
+ specifier: 9.8.1
+ version: 9.8.1
+ '@sinclair/typebox':
+ specifier: 0.34.52
+ version: 0.34.52
+ better-sqlite3:
+ specifier: 13.0.1
+ version: 13.0.1
+ drizzle-orm:
+ specifier: 0.45.2
+ version: 0.45.2(@types/better-sqlite3@7.6.13)(better-sqlite3@13.0.1)
+ fastify:
+ specifier: 5.10.0
+ version: 5.10.0
+ devDependencies:
+ '@types/better-sqlite3':
+ specifier: 7.6.13
+ version: 7.6.13
+ '@types/node':
+ specifier: 24.13.3
+ version: 24.13.3
+ typescript:
+ specifier: 7.0.2
+ version: 7.0.2
+
+ apps/web:
+ dependencies:
+ '@vibrant/core':
+ specifier: 4.0.4
+ version: 4.0.4
+ '@vibrant/quantizer-mmcq':
+ specifier: 4.0.4
+ version: 4.0.4
+ fabric:
+ specifier: 7.4.0
+ version: 7.4.0
+ react:
+ specifier: 19.2.8
+ version: 19.2.8
+ react-dom:
+ specifier: 19.2.8
+ version: 19.2.8(react@19.2.8)
+ devDependencies:
+ '@types/react':
+ specifier: 19.2.17
+ version: 19.2.17
+ '@types/react-dom':
+ specifier: 19.2.3
+ version: 19.2.3(@types/react@19.2.17)
+ '@vitejs/plugin-react':
+ specifier: 6.0.4
+ version: 6.0.4(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0))
+ typescript:
+ specifier: 7.0.2
+ version: 7.0.2
+ vite:
+ specifier: 8.1.5
+ version: 8.1.5(@types/node@24.13.3)(yaml@2.9.0)
+
+ apps/worker:
+ dependencies:
+ better-sqlite3:
+ specifier: 13.0.1
+ version: 13.0.1
+ drizzle-orm:
+ specifier: 0.45.2
+ version: 0.45.2(@types/better-sqlite3@7.6.13)(better-sqlite3@13.0.1)
+ devDependencies:
+ '@types/better-sqlite3':
+ specifier: 7.6.13
+ version: 7.6.13
+ '@types/node':
+ specifier: 24.13.3
+ version: 24.13.3
+ typescript:
+ specifier: 7.0.2
+ version: 7.0.2
+
+ packages/shared-contracts:
+ dependencies:
+ '@sinclair/typebox':
+ specifier: 0.34.52
+ version: 0.34.52
+ devDependencies:
+ typescript:
+ specifier: 7.0.2
+ version: 7.0.2
+
+packages:
+
+ '@asamuzakjp/css-color@3.2.0':
+ resolution: {integrity: sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==}
+
+ '@csstools/color-helpers@5.1.0':
+ resolution: {integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==}
+ engines: {node: '>=18'}
+
+ '@csstools/css-calc@2.1.4':
+ resolution: {integrity: sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ '@csstools/css-parser-algorithms': ^3.0.5
+ '@csstools/css-tokenizer': ^3.0.4
+
+ '@csstools/css-color-parser@3.1.0':
+ resolution: {integrity: sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ '@csstools/css-parser-algorithms': ^3.0.5
+ '@csstools/css-tokenizer': ^3.0.4
+
+ '@csstools/css-parser-algorithms@3.0.5':
+ resolution: {integrity: sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ '@csstools/css-tokenizer': ^3.0.4
+
+ '@csstools/css-tokenizer@3.0.4':
+ resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==}
+ engines: {node: '>=18'}
+
+ '@emnapi/core@1.11.1':
+ resolution: {integrity: sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==}
+
+ '@emnapi/runtime@1.11.1':
+ resolution: {integrity: sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==}
+
+ '@emnapi/wasi-threads@1.2.2':
+ resolution: {integrity: sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==}
+
+ '@fastify/ajv-compiler@4.0.5':
+ resolution: {integrity: sha512-KoWKW+MhvfTRWL4qrhUwAAZoaChluo0m0vbiJlGMt2GXvL4LVPQEjt8kSpHI3IBq5Rez8fg+XeH3cneztq+C7A==}
+
+ '@fastify/error@4.2.0':
+ resolution: {integrity: sha512-RSo3sVDXfHskiBZKBPRgnQTtIqpi/7zhJOEmAxCiBcM7d0uwdGdxLlsCaLzGs8v8NnxIRlfG0N51p5yFaOentQ==}
+
+ '@fastify/fast-json-stringify-compiler@5.1.0':
+ resolution: {integrity: sha512-PxcYtKLbQ8Z+yApiqjK8FwxIwvEj38k2OiLc17u8dkJSlmfi2wHHPaSnaoqBPQqtvF8YVsDgDpP2snDCfFrpfw==}
+
+ '@fastify/forwarded@3.0.1':
+ resolution: {integrity: sha512-JqDochHFqXs3C3Ml3gOY58zM7OqO9ENqPo0UqAjAjH8L01fRZqwX9iLeX34//kiJubF7r2ZQHtBRU36vONbLlw==}
+
+ '@fastify/merge-json-schemas@0.2.1':
+ resolution: {integrity: sha512-OA3KGBCy6KtIvLf8DINC5880o5iBlDX4SxzLQS8HorJAbqluzLRn80UXU0bxZn7UOFhFgpRJDasfwn9nG4FG4A==}
+
+ '@fastify/proxy-addr@5.1.0':
+ resolution: {integrity: sha512-INS+6gh91cLUjB+PVHfu1UqcB76Sqtpyp7bnL+FYojhjygvOPA9ctiD/JDKsyD9Xgu4hUhCSJBPig/w7duNajw==}
+
+ '@fastify/swagger@9.8.1':
+ resolution: {integrity: sha512-VpHMnqZTY8iBZYJE8WWkbKPrXIYWy2rDfIf5qLr6DzZSpQYZ+KxQVcJFiq/AMlvNwI4gCBd66++iUlxXXGT0IQ==}
+
+ '@jridgewell/sourcemap-codec@1.5.5':
+ resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==}
+
+ '@napi-rs/wasm-runtime@1.1.6':
+ resolution: {integrity: sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==}
+ peerDependencies:
+ '@emnapi/core': ^1.7.1
+ '@emnapi/runtime': ^1.7.1
+
+ '@oxc-project/types@0.139.0':
+ resolution: {integrity: sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==}
+
+ '@pinojs/redact@0.4.0':
+ resolution: {integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==}
+
+ '@playwright/test@1.62.0':
+ resolution: {integrity: sha512-9zOJ6ZQRAena31MpOH9VSzIz8Ou3YJ/wtY/eQm5T2uhfhG7/U3COrMS8xOtUrZrp9OgdmzEnIYODye3nY1VqzA==}
+ engines: {node: '>=20'}
+ hasBin: true
+
+ '@rolldown/binding-android-arm64@1.1.5':
+ resolution: {integrity: sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [android]
+
+ '@rolldown/binding-darwin-arm64@1.1.5':
+ resolution: {integrity: sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@rolldown/binding-darwin-x64@1.1.5':
+ resolution: {integrity: sha512-Tm+gbfC0aHu1tBA/JvKQh32S0K6YgCHkiAF4/W6xX0K0RmNuc94VeK419dJoE65R5aRxmo+noZQSWrAMF6yb6g==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [darwin]
+
+ '@rolldown/binding-freebsd-x64@1.1.5':
+ resolution: {integrity: sha512-JMzDKCCXq93YccG5gz3hvOs1oXRKAf0XYpfOS88e+wZrC8Iugj6j68867vrYZkvpDDpKn/KoKORThmchMpF6TA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@rolldown/binding-linux-arm-gnueabihf@1.1.5':
+ resolution: {integrity: sha512-uML21j2K5TfPGutKxub+M+nLjZIrWjXQ5Grx4lCe/nimTj9B4L63zHpjXLl4y0L3mcm2htEQIb06oCG/szerNw==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm]
+ os: [linux]
+
+ '@rolldown/binding-linux-arm64-gnu@1.1.5':
+ resolution: {integrity: sha512-navSiuTMogvnQoZoM/v+l3ZWo50/NTwSHSzheABx/RCnmUPaKwq9qSo4Br2OYRs21+Fz8uFqITZM3H4opOB0/Q==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [linux]
+ libc: [glibc]
+
+ '@rolldown/binding-linux-arm64-musl@1.1.5':
+ resolution: {integrity: sha512-lAryqH7IteztmCXQXk0etKj4wBQ7Gx5S6LjKhsgp9zb8I5bsuvU/2llH1hDQcjsFeqIsovMVN339/8pUDDBXxA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [linux]
+ libc: [musl]
+
+ '@rolldown/binding-linux-ppc64-gnu@1.1.5':
+ resolution: {integrity: sha512-fsK/sNBnxzBlL4O1JNrZakVQxPspqpED5dLtNsZS9oOKmtSpdNIzxH2kkol5HYTWJN47sE20ztMJPxfZ89qGOg==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [ppc64]
+ os: [linux]
+ libc: [glibc]
+
+ '@rolldown/binding-linux-s390x-gnu@1.1.5':
+ resolution: {integrity: sha512-gLYb4BIadlfTOYT5gO503n8zQjXflgzpD0FcyKh0Mzx3rqCZKnHoJWV9xe1KXUJ5lx2JfcSHr/mhzS0PC/McAA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [s390x]
+ os: [linux]
+ libc: [glibc]
+
+ '@rolldown/binding-linux-x64-gnu@1.1.5':
+ resolution: {integrity: sha512-FjcpEKUyJygHgs1o50VYNvkt5+7Le/VEdYt0AkRpkL33MnyQfwr8l5mXwMmfmTbyMPr5vJLC+8/Gd9gXnwU1QQ==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [linux]
+ libc: [glibc]
+
+ '@rolldown/binding-linux-x64-musl@1.1.5':
+ resolution: {integrity: sha512-Me+PfPI2TMeOQk0gYWfLQZtTktrmzbr8cDboqX83XKc7UrgAi55gF+2dUkWdxd19n55Essp2yeca+O9N5rBxHg==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [linux]
+ libc: [musl]
+
+ '@rolldown/binding-openharmony-arm64@1.1.5':
+ resolution: {integrity: sha512-yc5WrLzXks6zCQfn9Oxr8pORKyl/pF+QjHmW/Qx3qu0oyrrNC+y2JLTU1E2rcWYAmzlnqngWXHQjy51VzW70Vw==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [openharmony]
+
+ '@rolldown/binding-wasm32-wasi@1.1.5':
+ resolution: {integrity: sha512-VbQGPX2b4r48TAMIM2cjgluIM1HYutm4pcTEJsle7iEP7sB1dFqtPLBVbdLAZCxy1txCcPxf4QFf4v8uvltPqA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [wasm32]
+
+ '@rolldown/binding-win32-arm64-msvc@1.1.5':
+ resolution: {integrity: sha512-gHv82k63z4qpV5+Q1y/12KrK0ltWBukVDI8nZcbT7Tt/ZlOIVwppazneq0F93oDxTo3IgAMEDIoQh3E2n6mVsw==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [win32]
+
+ '@rolldown/binding-win32-x64-msvc@1.1.5':
+ resolution: {integrity: sha512-tTZuDBPw85tEN5PQi1pnEBzDy0Z49HtScLAbD5t6hyeU92A95pRWaSMw1GZZi/RwgSgUIl0xrSlXIT/9QzvYSA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [win32]
+
+ '@rolldown/pluginutils@1.0.1':
+ resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==}
+
+ '@sinclair/typebox@0.34.52':
+ resolution: {integrity: sha512-XiMQh7qqVlxZzcVD+kkGMNGMzcTrDMLWI7S4x7z1MkCkbDPrekpZXEUK0eZqZFMuHQg2a2DZOcDIh9o5v3Gonw==}
+
+ '@standard-schema/spec@1.1.0':
+ resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==}
+
+ '@tybys/wasm-util@0.10.3':
+ resolution: {integrity: sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==}
+
+ '@types/better-sqlite3@7.6.13':
+ resolution: {integrity: sha512-NMv9ASNARoKksWtsq/SHakpYAYnhBrQgGD8zkLYk/jaK8jUGn08CfEdTRgYhMypUQAfzSP8W6gNLe0q19/t4VA==}
+
+ '@types/chai@5.2.3':
+ resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==}
+
+ '@types/deep-eql@4.0.2':
+ resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==}
+
+ '@types/estree@1.0.9':
+ resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==}
+
+ '@types/node@24.13.3':
+ resolution: {integrity: sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q==}
+
+ '@types/react-dom@19.2.3':
+ resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==}
+ peerDependencies:
+ '@types/react': ^19.2.0
+
+ '@types/react@19.2.17':
+ resolution: {integrity: sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==}
+
+ '@typescript/typescript-aix-ppc64@7.0.2':
+ resolution: {integrity: sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ==}
+ engines: {node: '>=16.20.0'}
+ cpu: [ppc64]
+ os: [aix]
+
+ '@typescript/typescript-darwin-arm64@7.0.2':
+ resolution: {integrity: sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA==}
+ engines: {node: '>=16.20.0'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@typescript/typescript-darwin-x64@7.0.2':
+ resolution: {integrity: sha512-SZ9xZInqApNlNGc9s0W1VSsktYSOe9cFqNOIqmN1Gs8SmkjKZYFt017G4VwPxASInODuAdbTW7sXiFUf893RgA==}
+ engines: {node: '>=16.20.0'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@typescript/typescript-freebsd-arm64@7.0.2':
+ resolution: {integrity: sha512-W5NH4y/J0plIIS5b2xvTEkU7JFxyqdMAOgf+Ilhl0vHQXKO5dZoxd+C/jEtq56c4F3wk71RB4BMRQ2XdI+bwYQ==}
+ engines: {node: '>=16.20.0'}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@typescript/typescript-freebsd-x64@7.0.2':
+ resolution: {integrity: sha512-UMGDx5sTpzNw3WiPebH7l90IWfJggEd+egHt/q6p7/Cm3zqoV7VxkGXt+3DxPIw8CcmvAB0j3sVVfbhX+M4Tpw==}
+ engines: {node: '>=16.20.0'}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@typescript/typescript-linux-arm64@7.0.2':
+ resolution: {integrity: sha512-Qh4eU4/y3yDjnfjjyPYihMj5/ODIlmt+Bzu17OI+fiSRDW57QmU5SiN63exPRNJPKUzcc1INa1NXdrJ+MqHjUQ==}
+ engines: {node: '>=16.20.0'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@typescript/typescript-linux-arm@7.0.2':
+ resolution: {integrity: sha512-gffT3xPz9sR7j/YJExkyPntrI0P2EP9XbOyWzth2/Gs0RstK+90RBcO0ncXoXy/beYll1SXw846Nf2zdnEz0QQ==}
+ engines: {node: '>=16.20.0'}
+ cpu: [arm]
+ os: [linux]
+
+ '@typescript/typescript-linux-loong64@7.0.2':
+ resolution: {integrity: sha512-uEHck9i8hoAzXPiYRib1O7miOnz23SxIeVl6F4LXox+qov1K35jHcEW6VHKvZI+pyvl7fZEP4MCU5LYvIq1GuQ==}
+ engines: {node: '>=16.20.0'}
+ cpu: [loong64]
+ os: [linux]
+
+ '@typescript/typescript-linux-mips64el@7.0.2':
+ resolution: {integrity: sha512-R4KvAMnE43W5Qeqb0Ly56O3mWMWIAgsMyz36DCaycd5nbg/9kzm0liw3JocfRqyJY0KPmzFjbswozXyW0DnIYA==}
+ engines: {node: '>=16.20.0'}
+ cpu: [mips64el]
+ os: [linux]
+
+ '@typescript/typescript-linux-ppc64@7.0.2':
+ resolution: {integrity: sha512-DORx5b3sd/4S7eayxm4FQv+A7CrkUIGRaHiwI8oiHTAI1fAPWhF4J0vAlkC8biAlHSVVwxMQ3tjZ2/DVbnQiiA==}
+ engines: {node: '>=16.20.0'}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@typescript/typescript-linux-riscv64@7.0.2':
+ resolution: {integrity: sha512-wf0jqEDOjrPRnKwYRyyJDRo11KMbvMFrU+q4zqKyChODBzvlkbhNQfKvLxQCcwTpdDaXSHZTVuh0JoCrKCUMHQ==}
+ engines: {node: '>=16.20.0'}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@typescript/typescript-linux-s390x@7.0.2':
+ resolution: {integrity: sha512-IkwJc3L7yhytWd/ewjyxNDfOmswCm9GWMJT/ue/dU4aZNbwZeYAetq42VyLmsmSjvoX7z74X6ZaYCtzAr0EuGw==}
+ engines: {node: '>=16.20.0'}
+ cpu: [s390x]
+ os: [linux]
+
+ '@typescript/typescript-linux-x64@7.0.2':
+ resolution: {integrity: sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A==}
+ engines: {node: '>=16.20.0'}
+ cpu: [x64]
+ os: [linux]
+
+ '@typescript/typescript-netbsd-arm64@7.0.2':
+ resolution: {integrity: sha512-+polYF4MF04aPpO5FTkHran9yUQDSXqy5GiSDKpsll5jy3l3+g9QLhpf39T+ePtefhXLOGrLl0QIjkQP6VnelA==}
+ engines: {node: '>=16.20.0'}
+ cpu: [arm64]
+ os: [netbsd]
+
+ '@typescript/typescript-netbsd-x64@7.0.2':
+ resolution: {integrity: sha512-8YIT0EHM/3dq10ZOVF/A7pc/YSMtbcecct4rWtexrnSCHOPcpC2KTLXfTCR6vDpnSiY12heNb1GiN/wu+T/FyA==}
+ engines: {node: '>=16.20.0'}
+ cpu: [x64]
+ os: [netbsd]
+
+ '@typescript/typescript-openbsd-arm64@7.0.2':
+ resolution: {integrity: sha512-APT8+ClYnuYm1u9+kgGXoMj2VzWzcymwh2gNSQVySHfkRDGOTVkoWLjCmOQSaO+PoqQ57B0flRp9SA+7GnnkzQ==}
+ engines: {node: '>=16.20.0'}
+ cpu: [arm64]
+ os: [openbsd]
+
+ '@typescript/typescript-openbsd-x64@7.0.2':
+ resolution: {integrity: sha512-yX7s+Q0Dln0Dt9tEzZsAjXXR/+ytBM7AlglaqyeMPxQszJ1JhlJdZ6jLA+IzldHtflX81em7lDao1xXu+aRRkg==}
+ engines: {node: '>=16.20.0'}
+ cpu: [x64]
+ os: [openbsd]
+
+ '@typescript/typescript-sunos-x64@7.0.2':
+ resolution: {integrity: sha512-dLJDGaLZ1D4HPQn62u1n8mBDkJREwMsAkCdkwd4Ieqw+x3TUyTsqY0YiBCtE6H6OzzgGk3iuZ3vFWRS+E8/d1g==}
+ engines: {node: '>=16.20.0'}
+ cpu: [x64]
+ os: [sunos]
+
+ '@typescript/typescript-win32-arm64@7.0.2':
+ resolution: {integrity: sha512-Gyl1Vy6OsWesLzmq+EP0Fb7b4Nid5232AvcA2SFcdYreldpNtYFFofPjnt62y9hQy7VTaZp65ICJjuAQRaVcIQ==}
+ engines: {node: '>=16.20.0'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@typescript/typescript-win32-x64@7.0.2':
+ resolution: {integrity: sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g==}
+ engines: {node: '>=16.20.0'}
+ cpu: [x64]
+ os: [win32]
+
+ '@vibrant/color@4.0.4':
+ resolution: {integrity: sha512-Fq2tAszz4QOPWfHZ+KuEAchXUD8i594BM2fOJt8dI/fvYbiVoBycBF/BlNH6F4IWBubxXoPqD4JmmAHvFYbNew==}
+
+ '@vibrant/core@4.0.4':
+ resolution: {integrity: sha512-yZ0XSpW2biKyaJPpBC31AVYgn7NseKSO2q3KNMmDrkL2qC6TEWsBMnSQ28n0m///chZELXpQLx1CCOsWg5pj8w==}
+
+ '@vibrant/generator@4.0.4':
+ resolution: {integrity: sha512-rwq8PnlpKdch4YqaA1FAwdm71gKE2cMrUsbu72TqRFGa8rpP1roaZlQCVXIIwElXVc3r9axZyAcqyTLaMjhrTg==}
+
+ '@vibrant/image@4.0.4':
+ resolution: {integrity: sha512-NBIJj7umfDRVpFjJHQo1AFSCWCzQyjfil+Yxu7W62PEL72GPCif0CDiglPkvVF8QhDLmnx/x1k3LIBb9jWF2sw==}
+
+ '@vibrant/quantizer-mmcq@4.0.4':
+ resolution: {integrity: sha512-/1CNnM96J8K+OBCWNUzywo6VdnmdFJyiKO+ty/nkfe8H0NseOEHIL7PrVtWGgtsb0rh2uTAq2rjXv65TfgPy8g==}
+
+ '@vibrant/quantizer@4.0.4':
+ resolution: {integrity: sha512-722CooC2W4mlBiv+zyAsIrIvARnMCN/P2Muo8bnWd0SQlVWFtQnFxJWGOUPOPS4DGe3pGoqmNfvS0let4dICZQ==}
+
+ '@vibrant/types@4.0.4':
+ resolution: {integrity: sha512-Qq3mVTJamn7yD4OBgBEUKaxfDlm3sxBK55N7dH3XzI9Ey7KR00R06uwtqOcEJMsziWTEXdYN3VUlYaj2Tkt7hw==}
+
+ '@vibrant/worker@4.0.4':
+ resolution: {integrity: sha512-Q/R6PYhSMWCXEk/IcXbWIzIu7Z4b58ABkGvcdF8Y+q/7g+KnpxKW5x/jfQ/6ciyYSby13wZZoEdNr3QQVgsdBQ==}
+
+ '@vitejs/plugin-react@6.0.4':
+ resolution: {integrity: sha512-XcCQz0TBpBgljhj0gMuuDj49i6Ytqh5q1osT/Gp5uAVJUCTWxyskk/l1jwYYiu2xcNHHipdMz40EGfM1VdamVg==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ peerDependencies:
+ '@rolldown/plugin-babel': ^0.1.7 || ^0.2.0
+ babel-plugin-react-compiler: ^1.0.0
+ vite: ^8.0.0
+ peerDependenciesMeta:
+ '@rolldown/plugin-babel':
+ optional: true
+ babel-plugin-react-compiler:
+ optional: true
+
+ '@vitest/expect@4.1.10':
+ resolution: {integrity: sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==}
+
+ '@vitest/mocker@4.1.10':
+ resolution: {integrity: sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow==}
+ peerDependencies:
+ msw: ^2.4.9
+ vite: ^6.0.0 || ^7.0.0 || ^8.0.0
+ peerDependenciesMeta:
+ msw:
+ optional: true
+ vite:
+ optional: true
+
+ '@vitest/pretty-format@4.1.10':
+ resolution: {integrity: sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q==}
+
+ '@vitest/runner@4.1.10':
+ resolution: {integrity: sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg==}
+
+ '@vitest/snapshot@4.1.10':
+ resolution: {integrity: sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw==}
+
+ '@vitest/spy@4.1.10':
+ resolution: {integrity: sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw==}
+
+ '@vitest/utils@4.1.10':
+ resolution: {integrity: sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==}
+
+ abstract-logging@2.0.1:
+ resolution: {integrity: sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==}
+
+ agent-base@7.1.4:
+ resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==}
+ engines: {node: '>= 14'}
+
+ ajv-formats@3.0.1:
+ resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==}
+ peerDependencies:
+ ajv: ^8.0.0
+ peerDependenciesMeta:
+ ajv:
+ optional: true
+
+ ajv@8.20.0:
+ resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==}
+
+ assertion-error@2.0.1:
+ resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==}
+ engines: {node: '>=12'}
+
+ atomic-sleep@1.0.0:
+ resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==}
+ engines: {node: '>=8.0.0'}
+
+ avvio@9.3.0:
+ resolution: {integrity: sha512-g2tQ7LE7oOSqDfwEm3M+ZCMTJc7KiZCdJ4UwyZJb5ckTKyYu50OYmvv0mCFXPuYXoM4zkSt8zM9XQ9KCvxA74A==}
+
+ base64-js@1.5.1:
+ resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
+
+ better-sqlite3@13.0.1:
+ resolution: {integrity: sha512-LYpmOXdkpQYf4wmlxkdzW01XGlOXNIbjLg45yNkh0FQ4814VbK9PdOFmhZpYbej+EZtR/i3FDdhEG98HqZdgnA==}
+ engines: {node: '>=22'}
+
+ bl@4.1.0:
+ resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==}
+
+ buffer@5.7.1:
+ resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
+
+ canvas@3.2.3:
+ resolution: {integrity: sha512-PzE5nJZPz72YUAfo8oTp0u3fqqY7IzlTubneAihqDYAUcBk7ryeCmBbdJBEdaH0bptSOe2VT2Zwcb3UaFyaSWw==}
+ engines: {node: ^18.12.0 || >= 20.9.0}
+
+ chai@6.2.2:
+ resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==}
+ engines: {node: '>=18'}
+
+ chownr@1.1.4:
+ resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==}
+
+ convert-source-map@2.0.0:
+ resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
+
+ cookie@1.1.1:
+ resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==}
+ engines: {node: '>=18'}
+
+ cssstyle@4.6.0:
+ resolution: {integrity: sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==}
+ engines: {node: '>=18'}
+
+ csstype@3.2.3:
+ resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
+
+ data-urls@5.0.0:
+ resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==}
+ engines: {node: '>=18'}
+
+ debug@4.4.3:
+ resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+
+ decimal.js@10.6.0:
+ resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==}
+
+ decompress-response@6.0.0:
+ resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==}
+ engines: {node: '>=10'}
+
+ deep-extend@0.6.0:
+ resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==}
+ engines: {node: '>=4.0.0'}
+
+ dequal@2.0.3:
+ resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
+ engines: {node: '>=6'}
+
+ detect-libc@2.1.2:
+ resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
+ engines: {node: '>=8'}
+
+ drizzle-orm@0.45.2:
+ resolution: {integrity: sha512-kY0BSaTNYWnoDMVoyY8uxmyHjpJW1geOmBMdSSicKo9CIIWkSxMIj2rkeSR51b8KAPB7m+qysjuHme5nKP+E5Q==}
+ peerDependencies:
+ '@aws-sdk/client-rds-data': '>=3'
+ '@cloudflare/workers-types': '>=4'
+ '@electric-sql/pglite': '>=0.2.0'
+ '@libsql/client': '>=0.10.0'
+ '@libsql/client-wasm': '>=0.10.0'
+ '@neondatabase/serverless': '>=0.10.0'
+ '@op-engineering/op-sqlite': '>=2'
+ '@opentelemetry/api': ^1.4.1
+ '@planetscale/database': '>=1.13'
+ '@prisma/client': '*'
+ '@tidbcloud/serverless': '*'
+ '@types/better-sqlite3': '*'
+ '@types/pg': '*'
+ '@types/sql.js': '*'
+ '@upstash/redis': '>=1.34.7'
+ '@vercel/postgres': '>=0.8.0'
+ '@xata.io/client': '*'
+ better-sqlite3: '>=7'
+ bun-types: '*'
+ expo-sqlite: '>=14.0.0'
+ gel: '>=2'
+ knex: '*'
+ kysely: '*'
+ mysql2: '>=2'
+ pg: '>=8'
+ postgres: '>=3'
+ prisma: '*'
+ sql.js: '>=1'
+ sqlite3: '>=5'
+ peerDependenciesMeta:
+ '@aws-sdk/client-rds-data':
+ optional: true
+ '@cloudflare/workers-types':
+ optional: true
+ '@electric-sql/pglite':
+ optional: true
+ '@libsql/client':
+ optional: true
+ '@libsql/client-wasm':
+ optional: true
+ '@neondatabase/serverless':
+ optional: true
+ '@op-engineering/op-sqlite':
+ optional: true
+ '@opentelemetry/api':
+ optional: true
+ '@planetscale/database':
+ optional: true
+ '@prisma/client':
+ optional: true
+ '@tidbcloud/serverless':
+ optional: true
+ '@types/better-sqlite3':
+ optional: true
+ '@types/pg':
+ optional: true
+ '@types/sql.js':
+ optional: true
+ '@upstash/redis':
+ optional: true
+ '@vercel/postgres':
+ optional: true
+ '@xata.io/client':
+ optional: true
+ better-sqlite3:
+ optional: true
+ bun-types:
+ optional: true
+ expo-sqlite:
+ optional: true
+ gel:
+ optional: true
+ knex:
+ optional: true
+ kysely:
+ optional: true
+ mysql2:
+ optional: true
+ pg:
+ optional: true
+ postgres:
+ optional: true
+ prisma:
+ optional: true
+ sql.js:
+ optional: true
+ sqlite3:
+ optional: true
+
+ end-of-stream@1.4.5:
+ resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==}
+
+ entities@6.0.1:
+ resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==}
+ engines: {node: '>=0.12'}
+
+ es-module-lexer@2.3.1:
+ resolution: {integrity: sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==}
+
+ estree-walker@3.0.3:
+ resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
+
+ expand-template@2.0.3:
+ resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==}
+ engines: {node: '>=6'}
+
+ expect-type@1.4.0:
+ resolution: {integrity: sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==}
+ engines: {node: '>=12.0.0'}
+
+ fabric@7.4.0:
+ resolution: {integrity: sha512-NalYDc3eifTl1C33zryQwpH6+XA/2ClxQrH9vkASkZw3tbkRmorpikhYMmxhUTmi7O3e9ODz0vOT8qfaCh9IVA==}
+ engines: {node: '>=20.0.0'}
+
+ fast-decode-uri-component@1.0.1:
+ resolution: {integrity: sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==}
+
+ fast-deep-equal@3.1.3:
+ resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
+
+ fast-json-stringify@7.0.1:
+ resolution: {integrity: sha512-eRSayARSbbwlBjpP4vnTTIRD5QPcIrmihPxDeN1DtKnHPg66UuJLx+8hlK1kaFdjvzyQ/dzALoi4vwAQ+T+iZA==}
+
+ fast-querystring@1.1.2:
+ resolution: {integrity: sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==}
+
+ fast-uri@3.1.4:
+ resolution: {integrity: sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==}
+
+ fast-uri@4.1.1:
+ resolution: {integrity: sha512-YPOs1zD5TG2+EZt+r88LwF6mclA7TPkpwMP7ZN3TO2HiHS8TXvq7QA/17iJsV9dubcLo/f8eEYqMBruyQV21hQ==}
+
+ fastify-plugin@6.0.0:
+ resolution: {integrity: sha512-fZOty7z3O7vOliF6d8bHE3wiEh1KcNnKEQensSgTk9C1DvN6nRLS++XVd86v33Hw/8u9Un8A1zDrQ8ujcQDHEg==}
+
+ fastify@5.10.0:
+ resolution: {integrity: sha512-A9L0ziuWGQHgEEVgF3davQ9vbD93IuX+lo2IsxapQmu5b/Y/ynn9m9K5JHt9dvyJXOFc5iN0Zk5GHEOqnzhWjg==}
+
+ fastq@1.20.1:
+ resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==}
+
+ fdir@6.5.0:
+ resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
+ engines: {node: '>=12.0.0'}
+ peerDependencies:
+ picomatch: ^3 || ^4
+ peerDependenciesMeta:
+ picomatch:
+ optional: true
+
+ find-my-way@9.7.0:
+ resolution: {integrity: sha512-f2JHn75x2JlwUwLenZypgczR7YWMb/uO9BvUXtus+JMgkbIkLADd38cI4EiV+OQqrGo1Zlq6V8wnqMJ8e62wUQ==}
+ engines: {node: '>=20'}
+
+ fs-constants@1.0.0:
+ resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==}
+
+ fsevents@2.3.2:
+ resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
+ engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+ os: [darwin]
+
+ fsevents@2.3.3:
+ resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
+ engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+ os: [darwin]
+
+ github-from-package@0.0.0:
+ resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==}
+
+ html-encoding-sniffer@4.0.0:
+ resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==}
+ engines: {node: '>=18'}
+
+ http-proxy-agent@7.0.2:
+ resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==}
+ engines: {node: '>= 14'}
+
+ https-proxy-agent@7.0.6:
+ resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==}
+ engines: {node: '>= 14'}
+
+ iconv-lite@0.6.3:
+ resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
+ engines: {node: '>=0.10.0'}
+
+ ieee754@1.2.1:
+ resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
+
+ inherits@2.0.4:
+ resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
+
+ ini@1.3.8:
+ resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==}
+
+ ipaddr.js@2.4.0:
+ resolution: {integrity: sha512-9VGk3HGanVE6JoZXHiCpnGy5X0jYDnN4EA4lntFPj+1vIWlFhIylq2CrrCOJH9EAhc5CYhq18F2Av2tgoAPsYQ==}
+ engines: {node: '>= 10'}
+
+ is-potential-custom-element-name@1.0.1:
+ resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==}
+
+ jsdom@26.1.0:
+ resolution: {integrity: sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ canvas: ^3.0.0
+ peerDependenciesMeta:
+ canvas:
+ optional: true
+
+ json-schema-ref-resolver@3.0.0:
+ resolution: {integrity: sha512-hOrZIVL5jyYFjzk7+y7n5JDzGlU8rfWDuYyHwGa2WA8/pcmMHezp2xsVwxrebD/Q9t8Nc5DboieySDpCp4WG4A==}
+
+ json-schema-resolver@3.0.0:
+ resolution: {integrity: sha512-HqMnbz0tz2DaEJ3ntsqtx3ezzZyDE7G56A/pPY/NGmrPu76UzsWquOpHFRAf5beTNXoH2LU5cQePVvRli1nchA==}
+ engines: {node: '>=20'}
+
+ json-schema-traverse@1.0.0:
+ resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==}
+
+ light-my-request@6.6.0:
+ resolution: {integrity: sha512-CHYbu8RtboSIoVsHZ6Ye4cj4Aw/yg2oAFimlF7mNvfDV192LR7nDiKtSIfCuLT7KokPSTn/9kfVLm5OGN0A28A==}
+
+ lightningcss-android-arm64@1.33.0:
+ resolution: {integrity: sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [android]
+
+ lightningcss-darwin-arm64@1.33.0:
+ resolution: {integrity: sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [darwin]
+
+ lightningcss-darwin-x64@1.33.0:
+ resolution: {integrity: sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [darwin]
+
+ lightningcss-freebsd-x64@1.33.0:
+ resolution: {integrity: sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [freebsd]
+
+ lightningcss-linux-arm-gnueabihf@1.33.0:
+ resolution: {integrity: sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm]
+ os: [linux]
+
+ lightningcss-linux-arm64-gnu@1.33.0:
+ resolution: {integrity: sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [linux]
+ libc: [glibc]
+
+ lightningcss-linux-arm64-musl@1.33.0:
+ resolution: {integrity: sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [linux]
+ libc: [musl]
+
+ lightningcss-linux-x64-gnu@1.33.0:
+ resolution: {integrity: sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [linux]
+ libc: [glibc]
+
+ lightningcss-linux-x64-musl@1.33.0:
+ resolution: {integrity: sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [linux]
+ libc: [musl]
+
+ lightningcss-win32-arm64-msvc@1.33.0:
+ resolution: {integrity: sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [win32]
+
+ lightningcss-win32-x64-msvc@1.33.0:
+ resolution: {integrity: sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [win32]
+
+ lightningcss@1.33.0:
+ resolution: {integrity: sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==}
+ engines: {node: '>= 12.0.0'}
+
+ lru-cache@10.4.3:
+ resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
+
+ magic-string@0.30.21:
+ resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
+
+ mimic-response@3.1.0:
+ resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==}
+ engines: {node: '>=10'}
+
+ minimist@1.2.8:
+ resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
+
+ mkdirp-classic@0.5.3:
+ resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==}
+
+ ms@2.1.3:
+ resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+
+ nanoid@3.3.16:
+ resolution: {integrity: sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==}
+ engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+ hasBin: true
+
+ napi-build-utils@2.0.0:
+ resolution: {integrity: sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==}
+
+ node-abi@3.94.0:
+ resolution: {integrity: sha512-W5ZNO5KRPB5TkYmGVD9F6YqhsglXJzE6etpbmT+f6EQElhiX/UTG551cnsRGvLG3fyZEg9HwaDmNmj5nwJ4z9g==}
+ engines: {node: '>=10'}
+
+ node-addon-api@7.1.1:
+ resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==}
+
+ node-addon-api@8.9.0:
+ resolution: {integrity: sha512-ekZMeaaIzSQTSpr7X2X3iJM7lTzgnx8ahAG9pJfT/7+14mlEM8ZYQ9cgCDvSSRbReFK0oHli3WrZdCiRsgAT9Q==}
+ engines: {node: ^18 || ^20 || >= 21}
+
+ nwsapi@2.2.24:
+ resolution: {integrity: sha512-7YRhZ3jS45LwmSCT4b2sVFHt/WuovaktDU07QrtOBY2PXskss5a9jfmR9jptyumwXST+rFjrmppMY1KT/yn35A==}
+
+ obug@2.1.4:
+ resolution: {integrity: sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==}
+ engines: {node: '>=12.20.0'}
+
+ on-exit-leak-free@2.1.2:
+ resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==}
+ engines: {node: '>=14.0.0'}
+
+ once@1.4.0:
+ resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
+
+ openapi-types@12.1.3:
+ resolution: {integrity: sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==}
+
+ parse5@7.3.0:
+ resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==}
+
+ pathe@2.0.3:
+ resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
+
+ picocolors@1.1.1:
+ resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
+
+ picomatch@4.0.5:
+ resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==}
+ engines: {node: '>=12'}
+
+ pino-abstract-transport@3.0.0:
+ resolution: {integrity: sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==}
+
+ pino-std-serializers@7.1.0:
+ resolution: {integrity: sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw==}
+
+ pino@10.3.1:
+ resolution: {integrity: sha512-r34yH/GlQpKZbU1BvFFqOjhISRo1MNx1tWYsYvmj6KIRHSPMT2+yHOEb1SG6NMvRoHRF0a07kCOox/9yakl1vg==}
+ hasBin: true
+
+ playwright-core@1.62.0:
+ resolution: {integrity: sha512-nsNRyq0r2zsG8AcRHWknc9QRA5XCueC7gWMrs+Gx2tlZn9hcl8zudfh00lhJPY1DE7NmZ6bDsT9g2yey8mXljA==}
+ engines: {node: '>=20'}
+ hasBin: true
+
+ playwright@1.62.0:
+ resolution: {integrity: sha512-Z14dG305dgaLu6foB1TXQagFiW8JfSUIUaUuPaKQ6NtBPKF1P/qXcqfh6c6K/icPqdy37JmjbiBXf6JNg6Sylw==}
+ engines: {node: '>=20'}
+ hasBin: true
+
+ postcss@8.5.23:
+ resolution: {integrity: sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==}
+ engines: {node: ^10 || ^12 || >=14}
+
+ prebuild-install@7.1.3:
+ resolution: {integrity: sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==}
+ engines: {node: '>=10'}
+ deprecated: No longer maintained. Please contact the author of the relevant native addon; alternatives are available.
+ hasBin: true
+
+ process-warning@4.0.1:
+ resolution: {integrity: sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q==}
+
+ process-warning@5.0.0:
+ resolution: {integrity: sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==}
+
+ pump@3.0.4:
+ resolution: {integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==}
+
+ punycode@2.3.1:
+ resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
+ engines: {node: '>=6'}
+
+ quick-format-unescaped@4.0.4:
+ resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==}
+
+ rc@1.2.8:
+ resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==}
+ hasBin: true
+
+ react-dom@19.2.8:
+ resolution: {integrity: sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==}
+ peerDependencies:
+ react: ^19.2.8
+
+ react@19.2.8:
+ resolution: {integrity: sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==}
+ engines: {node: '>=0.10.0'}
+
+ readable-stream@3.6.2:
+ resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
+ engines: {node: '>= 6'}
+
+ real-require@0.2.0:
+ resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==}
+ engines: {node: '>= 12.13.0'}
+
+ real-require@1.0.0:
+ resolution: {integrity: sha512-P4nbQYQfePJxRSmY+v/KINxVucm4NF3p3s7pJveMTtom52FR4YGltUQLB8idDXwDDWW+eYrWDFbuzUnjoWHF7g==}
+
+ require-from-string@2.0.2:
+ resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
+ engines: {node: '>=0.10.0'}
+
+ ret@0.5.0:
+ resolution: {integrity: sha512-I1XxrZSQ+oErkRR4jYbAyEEu2I0avBvvMM5JN+6EBprOGRCs63ENqZ3vjavq8fBw2+62G5LF5XelKwuJpcvcxw==}
+ engines: {node: '>=10'}
+
+ reusify@1.1.0:
+ resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==}
+ engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
+
+ rfdc@1.4.1:
+ resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==}
+
+ rolldown@1.1.5:
+ resolution: {integrity: sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ hasBin: true
+
+ rrweb-cssom@0.8.0:
+ resolution: {integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==}
+
+ safe-buffer@5.2.1:
+ resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
+
+ safe-regex2@5.1.1:
+ resolution: {integrity: sha512-mOSBvHGDZMuIEZMdOz/aCEYDCv0E7nfcNsIhUF+/P+xC7Hyf3FkvymqgPbg9D1EdSGu+uKbJgy09K/RKKc7kJA==}
+ hasBin: true
+
+ safe-stable-stringify@2.5.0:
+ resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==}
+ engines: {node: '>=10'}
+
+ safer-buffer@2.1.2:
+ resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
+
+ saxes@6.0.0:
+ resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==}
+ engines: {node: '>=v12.22.7'}
+
+ scheduler@0.27.0:
+ resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==}
+
+ secure-json-parse@4.1.0:
+ resolution: {integrity: sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA==}
+
+ semver@7.8.5:
+ resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==}
+ engines: {node: '>=10'}
+ hasBin: true
+
+ set-cookie-parser@2.7.2:
+ resolution: {integrity: sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==}
+
+ siginfo@2.0.0:
+ resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
+
+ simple-concat@1.0.1:
+ resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==}
+
+ simple-get@4.0.1:
+ resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==}
+
+ sonic-boom@4.2.1:
+ resolution: {integrity: sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==}
+
+ source-map-js@1.2.1:
+ resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
+ engines: {node: '>=0.10.0'}
+
+ split2@4.2.0:
+ resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==}
+ engines: {node: '>= 10.x'}
+
+ stackback@0.0.2:
+ resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
+
+ std-env@4.2.0:
+ resolution: {integrity: sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==}
+
+ string_decoder@1.3.0:
+ resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
+
+ strip-json-comments@2.0.1:
+ resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==}
+ engines: {node: '>=0.10.0'}
+
+ symbol-tree@3.2.4:
+ resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==}
+
+ tar-fs@2.1.5:
+ resolution: {integrity: sha512-OboTd8mmMhZDNPV+UjQcK9yKAatXu2aJ+r1w4im1Otd4M4fl2hwvdoXUxIYHFTHWK/3y3FarBP70v3vwmGlOxw==}
+
+ tar-stream@2.2.0:
+ resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==}
+ engines: {node: '>=6'}
+
+ thread-stream@4.2.0:
+ resolution: {integrity: sha512-e2zZ96wSChazBsbENf/Pcm/4swHt2cEKQ92rhUjkL9GCKiTDJIaTBenjE/m9DXi0QBmTMDkFDdOomUy20A1tDQ==}
+ engines: {node: '>=20'}
+
+ tinybench@2.9.0:
+ resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
+
+ tinyexec@1.2.4:
+ resolution: {integrity: sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==}
+ engines: {node: '>=18'}
+
+ tinyglobby@0.2.17:
+ resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==}
+ engines: {node: '>=12.0.0'}
+
+ tinyrainbow@3.1.0:
+ resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==}
+ engines: {node: '>=14.0.0'}
+
+ tldts-core@6.1.86:
+ resolution: {integrity: sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==}
+
+ tldts@6.1.86:
+ resolution: {integrity: sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==}
+ hasBin: true
+
+ toad-cache@3.7.4:
+ resolution: {integrity: sha512-m1TdR/rvT7kgGJZhspNtXdsdYk0fddFpJJFlG5s+UkPFo6lkLoZ3YLOaovPYjq1R75NP5JfeTlSHaOsE09peCg==}
+ engines: {node: '>=20'}
+
+ tough-cookie@5.1.2:
+ resolution: {integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==}
+ engines: {node: '>=16'}
+
+ tr46@5.1.1:
+ resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==}
+ engines: {node: '>=18'}
+
+ tslib@2.8.1:
+ resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
+
+ tunnel-agent@0.6.0:
+ resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==}
+
+ typescript@7.0.2:
+ resolution: {integrity: sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==}
+ engines: {node: '>=16.20.0'}
+ hasBin: true
+
+ undici-types@7.18.2:
+ resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==}
+
+ util-deprecate@1.0.2:
+ resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
+
+ vite@8.1.5:
+ resolution: {integrity: sha512-7ULLwsCdYx/nRyrpiEwvqb5TFHrMVZyBt+rg/OAXT7rgj/z+DtTDyKFeLAdDkubDVDKD8jOsndmy7m55XcfUsw==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ hasBin: true
+ peerDependencies:
+ '@types/node': ^20.19.0 || >=22.12.0
+ '@vitejs/devtools': ^0.3.0
+ esbuild: ^0.27.0 || ^0.28.0
+ jiti: '>=1.21.0'
+ less: ^4.0.0
+ sass: ^1.70.0
+ sass-embedded: ^1.70.0
+ stylus: '>=0.54.8'
+ sugarss: ^5.0.0
+ terser: ^5.16.0
+ tsx: ^4.8.1
+ yaml: ^2.4.2
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+ '@vitejs/devtools':
+ optional: true
+ esbuild:
+ optional: true
+ jiti:
+ optional: true
+ less:
+ optional: true
+ sass:
+ optional: true
+ sass-embedded:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ terser:
+ optional: true
+ tsx:
+ optional: true
+ yaml:
+ optional: true
+
+ vitest@4.1.10:
+ resolution: {integrity: sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==}
+ engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0}
+ hasBin: true
+ peerDependencies:
+ '@edge-runtime/vm': '*'
+ '@opentelemetry/api': ^1.9.0
+ '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0
+ '@vitest/browser-playwright': 4.1.10
+ '@vitest/browser-preview': 4.1.10
+ '@vitest/browser-webdriverio': 4.1.10
+ '@vitest/coverage-istanbul': 4.1.10
+ '@vitest/coverage-v8': 4.1.10
+ '@vitest/ui': 4.1.10
+ happy-dom: '*'
+ jsdom: '*'
+ vite: ^6.0.0 || ^7.0.0 || ^8.0.0
+ peerDependenciesMeta:
+ '@edge-runtime/vm':
+ optional: true
+ '@opentelemetry/api':
+ optional: true
+ '@types/node':
+ optional: true
+ '@vitest/browser-playwright':
+ optional: true
+ '@vitest/browser-preview':
+ optional: true
+ '@vitest/browser-webdriverio':
+ optional: true
+ '@vitest/coverage-istanbul':
+ optional: true
+ '@vitest/coverage-v8':
+ optional: true
+ '@vitest/ui':
+ optional: true
+ happy-dom:
+ optional: true
+ jsdom:
+ optional: true
+
+ w3c-xmlserializer@5.0.0:
+ resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==}
+ engines: {node: '>=18'}
+
+ webidl-conversions@7.0.0:
+ resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==}
+ engines: {node: '>=12'}
+
+ whatwg-encoding@3.1.1:
+ resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==}
+ engines: {node: '>=18'}
+ deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation
+
+ whatwg-mimetype@4.0.0:
+ resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==}
+ engines: {node: '>=18'}
+
+ whatwg-url@14.2.0:
+ resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==}
+ engines: {node: '>=18'}
+
+ why-is-node-running@2.3.0:
+ resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==}
+ engines: {node: '>=8'}
+ hasBin: true
+
+ wrappy@1.0.2:
+ resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
+
+ ws@8.21.1:
+ resolution: {integrity: sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw==}
+ engines: {node: '>=10.0.0'}
+ peerDependencies:
+ bufferutil: ^4.0.1
+ utf-8-validate: '>=5.0.2'
+ peerDependenciesMeta:
+ bufferutil:
+ optional: true
+ utf-8-validate:
+ optional: true
+
+ xml-name-validator@5.0.0:
+ resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==}
+ engines: {node: '>=18'}
+
+ xmlchars@2.2.0:
+ resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==}
+
+ yaml@2.9.0:
+ resolution: {integrity: sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==}
+ engines: {node: '>= 14.6'}
+ hasBin: true
+
+snapshots:
+
+ '@asamuzakjp/css-color@3.2.0':
+ dependencies:
+ '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
+ '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
+ '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4)
+ '@csstools/css-tokenizer': 3.0.4
+ lru-cache: 10.4.3
+ optional: true
+
+ '@csstools/color-helpers@5.1.0':
+ optional: true
+
+ '@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)':
+ dependencies:
+ '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4)
+ '@csstools/css-tokenizer': 3.0.4
+ optional: true
+
+ '@csstools/css-color-parser@3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)':
+ dependencies:
+ '@csstools/color-helpers': 5.1.0
+ '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
+ '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4)
+ '@csstools/css-tokenizer': 3.0.4
+ optional: true
+
+ '@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4)':
+ dependencies:
+ '@csstools/css-tokenizer': 3.0.4
+ optional: true
+
+ '@csstools/css-tokenizer@3.0.4':
+ optional: true
+
+ '@emnapi/core@1.11.1':
+ dependencies:
+ '@emnapi/wasi-threads': 1.2.2
+ tslib: 2.8.1
+ optional: true
+
+ '@emnapi/runtime@1.11.1':
+ dependencies:
+ tslib: 2.8.1
+ optional: true
+
+ '@emnapi/wasi-threads@1.2.2':
+ dependencies:
+ tslib: 2.8.1
+ optional: true
+
+ '@fastify/ajv-compiler@4.0.5':
+ dependencies:
+ ajv: 8.20.0
+ ajv-formats: 3.0.1(ajv@8.20.0)
+ fast-uri: 3.1.4
+
+ '@fastify/error@4.2.0': {}
+
+ '@fastify/fast-json-stringify-compiler@5.1.0':
+ dependencies:
+ fast-json-stringify: 7.0.1
+
+ '@fastify/forwarded@3.0.1': {}
+
+ '@fastify/merge-json-schemas@0.2.1':
+ dependencies:
+ dequal: 2.0.3
+
+ '@fastify/proxy-addr@5.1.0':
+ dependencies:
+ '@fastify/forwarded': 3.0.1
+ ipaddr.js: 2.4.0
+
+ '@fastify/swagger@9.8.1':
+ dependencies:
+ fastify-plugin: 6.0.0
+ json-schema-resolver: 3.0.0
+ openapi-types: 12.1.3
+ rfdc: 1.4.1
+ yaml: 2.9.0
+ transitivePeerDependencies:
+ - supports-color
+
+ '@jridgewell/sourcemap-codec@1.5.5': {}
+
+ '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)':
+ dependencies:
+ '@emnapi/core': 1.11.1
+ '@emnapi/runtime': 1.11.1
+ '@tybys/wasm-util': 0.10.3
+ optional: true
+
+ '@oxc-project/types@0.139.0': {}
+
+ '@pinojs/redact@0.4.0': {}
+
+ '@playwright/test@1.62.0':
+ dependencies:
+ playwright: 1.62.0
+
+ '@rolldown/binding-android-arm64@1.1.5':
+ optional: true
+
+ '@rolldown/binding-darwin-arm64@1.1.5':
+ optional: true
+
+ '@rolldown/binding-darwin-x64@1.1.5':
+ optional: true
+
+ '@rolldown/binding-freebsd-x64@1.1.5':
+ optional: true
+
+ '@rolldown/binding-linux-arm-gnueabihf@1.1.5':
+ optional: true
+
+ '@rolldown/binding-linux-arm64-gnu@1.1.5':
+ optional: true
+
+ '@rolldown/binding-linux-arm64-musl@1.1.5':
+ optional: true
+
+ '@rolldown/binding-linux-ppc64-gnu@1.1.5':
+ optional: true
+
+ '@rolldown/binding-linux-s390x-gnu@1.1.5':
+ optional: true
+
+ '@rolldown/binding-linux-x64-gnu@1.1.5':
+ optional: true
+
+ '@rolldown/binding-linux-x64-musl@1.1.5':
+ optional: true
+
+ '@rolldown/binding-openharmony-arm64@1.1.5':
+ optional: true
+
+ '@rolldown/binding-wasm32-wasi@1.1.5':
+ dependencies:
+ '@emnapi/core': 1.11.1
+ '@emnapi/runtime': 1.11.1
+ '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)
+ optional: true
+
+ '@rolldown/binding-win32-arm64-msvc@1.1.5':
+ optional: true
+
+ '@rolldown/binding-win32-x64-msvc@1.1.5':
+ optional: true
+
+ '@rolldown/pluginutils@1.0.1': {}
+
+ '@sinclair/typebox@0.34.52': {}
+
+ '@standard-schema/spec@1.1.0': {}
+
+ '@tybys/wasm-util@0.10.3':
+ dependencies:
+ tslib: 2.8.1
+ optional: true
+
+ '@types/better-sqlite3@7.6.13':
+ dependencies:
+ '@types/node': 24.13.3
+
+ '@types/chai@5.2.3':
+ dependencies:
+ '@types/deep-eql': 4.0.2
+ assertion-error: 2.0.1
+
+ '@types/deep-eql@4.0.2': {}
+
+ '@types/estree@1.0.9': {}
+
+ '@types/node@24.13.3':
+ dependencies:
+ undici-types: 7.18.2
+
+ '@types/react-dom@19.2.3(@types/react@19.2.17)':
+ dependencies:
+ '@types/react': 19.2.17
+
+ '@types/react@19.2.17':
+ dependencies:
+ csstype: 3.2.3
+
+ '@typescript/typescript-aix-ppc64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-darwin-arm64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-darwin-x64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-freebsd-arm64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-freebsd-x64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-linux-arm64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-linux-arm@7.0.2':
+ optional: true
+
+ '@typescript/typescript-linux-loong64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-linux-mips64el@7.0.2':
+ optional: true
+
+ '@typescript/typescript-linux-ppc64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-linux-riscv64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-linux-s390x@7.0.2':
+ optional: true
+
+ '@typescript/typescript-linux-x64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-netbsd-arm64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-netbsd-x64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-openbsd-arm64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-openbsd-x64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-sunos-x64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-win32-arm64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-win32-x64@7.0.2':
+ optional: true
+
+ '@vibrant/color@4.0.4': {}
+
+ '@vibrant/core@4.0.4':
+ dependencies:
+ '@vibrant/color': 4.0.4
+ '@vibrant/generator': 4.0.4
+ '@vibrant/image': 4.0.4
+ '@vibrant/quantizer': 4.0.4
+ '@vibrant/worker': 4.0.4
+
+ '@vibrant/generator@4.0.4':
+ dependencies:
+ '@vibrant/color': 4.0.4
+ '@vibrant/types': 4.0.4
+
+ '@vibrant/image@4.0.4':
+ dependencies:
+ '@vibrant/color': 4.0.4
+
+ '@vibrant/quantizer-mmcq@4.0.4':
+ dependencies:
+ '@vibrant/color': 4.0.4
+ '@vibrant/image': 4.0.4
+ '@vibrant/quantizer': 4.0.4
+
+ '@vibrant/quantizer@4.0.4':
+ dependencies:
+ '@vibrant/color': 4.0.4
+ '@vibrant/image': 4.0.4
+ '@vibrant/types': 4.0.4
+
+ '@vibrant/types@4.0.4': {}
+
+ '@vibrant/worker@4.0.4':
+ dependencies:
+ '@vibrant/types': 4.0.4
+
+ '@vitejs/plugin-react@6.0.4(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0))':
+ dependencies:
+ '@rolldown/pluginutils': 1.0.1
+ vite: 8.1.5(@types/node@24.13.3)(yaml@2.9.0)
+
+ '@vitest/expect@4.1.10':
+ 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
+
+ '@vitest/mocker@4.1.10(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0))':
+ dependencies:
+ '@vitest/spy': 4.1.10
+ estree-walker: 3.0.3
+ magic-string: 0.30.21
+ optionalDependencies:
+ vite: 8.1.5(@types/node@24.13.3)(yaml@2.9.0)
+
+ '@vitest/pretty-format@4.1.10':
+ dependencies:
+ tinyrainbow: 3.1.0
+
+ '@vitest/runner@4.1.10':
+ dependencies:
+ '@vitest/utils': 4.1.10
+ pathe: 2.0.3
+
+ '@vitest/snapshot@4.1.10':
+ dependencies:
+ '@vitest/pretty-format': 4.1.10
+ '@vitest/utils': 4.1.10
+ magic-string: 0.30.21
+ pathe: 2.0.3
+
+ '@vitest/spy@4.1.10': {}
+
+ '@vitest/utils@4.1.10':
+ dependencies:
+ '@vitest/pretty-format': 4.1.10
+ convert-source-map: 2.0.0
+ tinyrainbow: 3.1.0
+
+ abstract-logging@2.0.1: {}
+
+ agent-base@7.1.4:
+ optional: true
+
+ ajv-formats@3.0.1(ajv@8.20.0):
+ optionalDependencies:
+ ajv: 8.20.0
+
+ ajv@8.20.0:
+ dependencies:
+ fast-deep-equal: 3.1.3
+ fast-uri: 3.1.4
+ json-schema-traverse: 1.0.0
+ require-from-string: 2.0.2
+
+ assertion-error@2.0.1: {}
+
+ atomic-sleep@1.0.0: {}
+
+ avvio@9.3.0:
+ dependencies:
+ '@fastify/error': 4.2.0
+ fastq: 1.20.1
+
+ base64-js@1.5.1:
+ optional: true
+
+ better-sqlite3@13.0.1:
+ dependencies:
+ node-addon-api: 8.9.0
+
+ bl@4.1.0:
+ dependencies:
+ buffer: 5.7.1
+ inherits: 2.0.4
+ readable-stream: 3.6.2
+ optional: true
+
+ buffer@5.7.1:
+ dependencies:
+ base64-js: 1.5.1
+ ieee754: 1.2.1
+ optional: true
+
+ canvas@3.2.3:
+ dependencies:
+ node-addon-api: 7.1.1
+ prebuild-install: 7.1.3
+ optional: true
+
+ chai@6.2.2: {}
+
+ chownr@1.1.4:
+ optional: true
+
+ convert-source-map@2.0.0: {}
+
+ cookie@1.1.1: {}
+
+ cssstyle@4.6.0:
+ dependencies:
+ '@asamuzakjp/css-color': 3.2.0
+ rrweb-cssom: 0.8.0
+ optional: true
+
+ csstype@3.2.3: {}
+
+ data-urls@5.0.0:
+ dependencies:
+ whatwg-mimetype: 4.0.0
+ whatwg-url: 14.2.0
+ optional: true
+
+ debug@4.4.3:
+ dependencies:
+ ms: 2.1.3
+
+ decimal.js@10.6.0:
+ optional: true
+
+ decompress-response@6.0.0:
+ dependencies:
+ mimic-response: 3.1.0
+ optional: true
+
+ deep-extend@0.6.0:
+ optional: true
+
+ dequal@2.0.3: {}
+
+ detect-libc@2.1.2: {}
+
+ drizzle-orm@0.45.2(@types/better-sqlite3@7.6.13)(better-sqlite3@13.0.1):
+ optionalDependencies:
+ '@types/better-sqlite3': 7.6.13
+ better-sqlite3: 13.0.1
+
+ end-of-stream@1.4.5:
+ dependencies:
+ once: 1.4.0
+ optional: true
+
+ entities@6.0.1:
+ optional: true
+
+ es-module-lexer@2.3.1: {}
+
+ estree-walker@3.0.3:
+ dependencies:
+ '@types/estree': 1.0.9
+
+ expand-template@2.0.3:
+ optional: true
+
+ expect-type@1.4.0: {}
+
+ fabric@7.4.0:
+ optionalDependencies:
+ canvas: 3.2.3
+ jsdom: 26.1.0(canvas@3.2.3)
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+
+ fast-decode-uri-component@1.0.1: {}
+
+ fast-deep-equal@3.1.3: {}
+
+ fast-json-stringify@7.0.1:
+ dependencies:
+ '@fastify/merge-json-schemas': 0.2.1
+ ajv: 8.20.0
+ ajv-formats: 3.0.1(ajv@8.20.0)
+ fast-uri: 4.1.1
+ json-schema-ref-resolver: 3.0.0
+ rfdc: 1.4.1
+
+ fast-querystring@1.1.2:
+ dependencies:
+ fast-decode-uri-component: 1.0.1
+
+ fast-uri@3.1.4: {}
+
+ fast-uri@4.1.1: {}
+
+ fastify-plugin@6.0.0: {}
+
+ fastify@5.10.0:
+ dependencies:
+ '@fastify/ajv-compiler': 4.0.5
+ '@fastify/error': 4.2.0
+ '@fastify/fast-json-stringify-compiler': 5.1.0
+ '@fastify/proxy-addr': 5.1.0
+ abstract-logging: 2.0.1
+ avvio: 9.3.0
+ fast-json-stringify: 7.0.1
+ find-my-way: 9.7.0
+ light-my-request: 6.6.0
+ pino: 10.3.1
+ process-warning: 5.0.0
+ rfdc: 1.4.1
+ secure-json-parse: 4.1.0
+ semver: 7.8.5
+ toad-cache: 3.7.4
+
+ fastq@1.20.1:
+ dependencies:
+ reusify: 1.1.0
+
+ fdir@6.5.0(picomatch@4.0.5):
+ optionalDependencies:
+ picomatch: 4.0.5
+
+ find-my-way@9.7.0:
+ dependencies:
+ fast-deep-equal: 3.1.3
+ fast-querystring: 1.1.2
+ safe-regex2: 5.1.1
+
+ fs-constants@1.0.0:
+ optional: true
+
+ fsevents@2.3.2:
+ optional: true
+
+ fsevents@2.3.3:
+ optional: true
+
+ github-from-package@0.0.0:
+ optional: true
+
+ html-encoding-sniffer@4.0.0:
+ dependencies:
+ whatwg-encoding: 3.1.1
+ optional: true
+
+ http-proxy-agent@7.0.2:
+ dependencies:
+ agent-base: 7.1.4
+ debug: 4.4.3
+ transitivePeerDependencies:
+ - supports-color
+ optional: true
+
+ https-proxy-agent@7.0.6:
+ dependencies:
+ agent-base: 7.1.4
+ debug: 4.4.3
+ transitivePeerDependencies:
+ - supports-color
+ optional: true
+
+ iconv-lite@0.6.3:
+ dependencies:
+ safer-buffer: 2.1.2
+ optional: true
+
+ ieee754@1.2.1:
+ optional: true
+
+ inherits@2.0.4:
+ optional: true
+
+ ini@1.3.8:
+ optional: true
+
+ ipaddr.js@2.4.0: {}
+
+ is-potential-custom-element-name@1.0.1:
+ optional: true
+
+ jsdom@26.1.0(canvas@3.2.3):
+ dependencies:
+ cssstyle: 4.6.0
+ data-urls: 5.0.0
+ decimal.js: 10.6.0
+ html-encoding-sniffer: 4.0.0
+ http-proxy-agent: 7.0.2
+ https-proxy-agent: 7.0.6
+ is-potential-custom-element-name: 1.0.1
+ nwsapi: 2.2.24
+ parse5: 7.3.0
+ rrweb-cssom: 0.8.0
+ saxes: 6.0.0
+ symbol-tree: 3.2.4
+ tough-cookie: 5.1.2
+ w3c-xmlserializer: 5.0.0
+ webidl-conversions: 7.0.0
+ whatwg-encoding: 3.1.1
+ whatwg-mimetype: 4.0.0
+ whatwg-url: 14.2.0
+ ws: 8.21.1
+ xml-name-validator: 5.0.0
+ optionalDependencies:
+ canvas: 3.2.3
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+ optional: true
+
+ json-schema-ref-resolver@3.0.0:
+ dependencies:
+ dequal: 2.0.3
+
+ json-schema-resolver@3.0.0:
+ dependencies:
+ debug: 4.4.3
+ fast-uri: 3.1.4
+ rfdc: 1.4.1
+ transitivePeerDependencies:
+ - supports-color
+
+ json-schema-traverse@1.0.0: {}
+
+ light-my-request@6.6.0:
+ dependencies:
+ cookie: 1.1.1
+ process-warning: 4.0.1
+ set-cookie-parser: 2.7.2
+
+ lightningcss-android-arm64@1.33.0:
+ optional: true
+
+ lightningcss-darwin-arm64@1.33.0:
+ optional: true
+
+ lightningcss-darwin-x64@1.33.0:
+ optional: true
+
+ lightningcss-freebsd-x64@1.33.0:
+ optional: true
+
+ lightningcss-linux-arm-gnueabihf@1.33.0:
+ optional: true
+
+ lightningcss-linux-arm64-gnu@1.33.0:
+ optional: true
+
+ lightningcss-linux-arm64-musl@1.33.0:
+ optional: true
+
+ lightningcss-linux-x64-gnu@1.33.0:
+ optional: true
+
+ lightningcss-linux-x64-musl@1.33.0:
+ optional: true
+
+ lightningcss-win32-arm64-msvc@1.33.0:
+ optional: true
+
+ lightningcss-win32-x64-msvc@1.33.0:
+ optional: true
+
+ lightningcss@1.33.0:
+ dependencies:
+ detect-libc: 2.1.2
+ optionalDependencies:
+ 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
+
+ lru-cache@10.4.3:
+ optional: true
+
+ magic-string@0.30.21:
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.5.5
+
+ mimic-response@3.1.0:
+ optional: true
+
+ minimist@1.2.8:
+ optional: true
+
+ mkdirp-classic@0.5.3:
+ optional: true
+
+ ms@2.1.3: {}
+
+ nanoid@3.3.16: {}
+
+ napi-build-utils@2.0.0:
+ optional: true
+
+ node-abi@3.94.0:
+ dependencies:
+ semver: 7.8.5
+ optional: true
+
+ node-addon-api@7.1.1:
+ optional: true
+
+ node-addon-api@8.9.0: {}
+
+ nwsapi@2.2.24:
+ optional: true
+
+ obug@2.1.4: {}
+
+ on-exit-leak-free@2.1.2: {}
+
+ once@1.4.0:
+ dependencies:
+ wrappy: 1.0.2
+ optional: true
+
+ openapi-types@12.1.3: {}
+
+ parse5@7.3.0:
+ dependencies:
+ entities: 6.0.1
+ optional: true
+
+ pathe@2.0.3: {}
+
+ picocolors@1.1.1: {}
+
+ picomatch@4.0.5: {}
+
+ pino-abstract-transport@3.0.0:
+ dependencies:
+ split2: 4.2.0
+
+ pino-std-serializers@7.1.0: {}
+
+ pino@10.3.1:
+ dependencies:
+ '@pinojs/redact': 0.4.0
+ atomic-sleep: 1.0.0
+ on-exit-leak-free: 2.1.2
+ pino-abstract-transport: 3.0.0
+ pino-std-serializers: 7.1.0
+ process-warning: 5.0.0
+ quick-format-unescaped: 4.0.4
+ real-require: 0.2.0
+ safe-stable-stringify: 2.5.0
+ sonic-boom: 4.2.1
+ thread-stream: 4.2.0
+
+ playwright-core@1.62.0: {}
+
+ playwright@1.62.0:
+ dependencies:
+ playwright-core: 1.62.0
+ optionalDependencies:
+ fsevents: 2.3.2
+
+ postcss@8.5.23:
+ dependencies:
+ nanoid: 3.3.16
+ picocolors: 1.1.1
+ source-map-js: 1.2.1
+
+ prebuild-install@7.1.3:
+ dependencies:
+ detect-libc: 2.1.2
+ expand-template: 2.0.3
+ github-from-package: 0.0.0
+ minimist: 1.2.8
+ mkdirp-classic: 0.5.3
+ napi-build-utils: 2.0.0
+ node-abi: 3.94.0
+ pump: 3.0.4
+ rc: 1.2.8
+ simple-get: 4.0.1
+ tar-fs: 2.1.5
+ tunnel-agent: 0.6.0
+ optional: true
+
+ process-warning@4.0.1: {}
+
+ process-warning@5.0.0: {}
+
+ pump@3.0.4:
+ dependencies:
+ end-of-stream: 1.4.5
+ once: 1.4.0
+ optional: true
+
+ punycode@2.3.1:
+ optional: true
+
+ quick-format-unescaped@4.0.4: {}
+
+ rc@1.2.8:
+ dependencies:
+ deep-extend: 0.6.0
+ ini: 1.3.8
+ minimist: 1.2.8
+ strip-json-comments: 2.0.1
+ optional: true
+
+ react-dom@19.2.8(react@19.2.8):
+ dependencies:
+ react: 19.2.8
+ scheduler: 0.27.0
+
+ react@19.2.8: {}
+
+ readable-stream@3.6.2:
+ dependencies:
+ inherits: 2.0.4
+ string_decoder: 1.3.0
+ util-deprecate: 1.0.2
+ optional: true
+
+ real-require@0.2.0: {}
+
+ real-require@1.0.0: {}
+
+ require-from-string@2.0.2: {}
+
+ ret@0.5.0: {}
+
+ reusify@1.1.0: {}
+
+ rfdc@1.4.1: {}
+
+ rolldown@1.1.5:
+ dependencies:
+ '@oxc-project/types': 0.139.0
+ '@rolldown/pluginutils': 1.0.1
+ optionalDependencies:
+ '@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
+
+ rrweb-cssom@0.8.0:
+ optional: true
+
+ safe-buffer@5.2.1:
+ optional: true
+
+ safe-regex2@5.1.1:
+ dependencies:
+ ret: 0.5.0
+
+ safe-stable-stringify@2.5.0: {}
+
+ safer-buffer@2.1.2:
+ optional: true
+
+ saxes@6.0.0:
+ dependencies:
+ xmlchars: 2.2.0
+ optional: true
+
+ scheduler@0.27.0: {}
+
+ secure-json-parse@4.1.0: {}
+
+ semver@7.8.5: {}
+
+ set-cookie-parser@2.7.2: {}
+
+ siginfo@2.0.0: {}
+
+ simple-concat@1.0.1:
+ optional: true
+
+ simple-get@4.0.1:
+ dependencies:
+ decompress-response: 6.0.0
+ once: 1.4.0
+ simple-concat: 1.0.1
+ optional: true
+
+ sonic-boom@4.2.1:
+ dependencies:
+ atomic-sleep: 1.0.0
+
+ source-map-js@1.2.1: {}
+
+ split2@4.2.0: {}
+
+ stackback@0.0.2: {}
+
+ std-env@4.2.0: {}
+
+ string_decoder@1.3.0:
+ dependencies:
+ safe-buffer: 5.2.1
+ optional: true
+
+ strip-json-comments@2.0.1:
+ optional: true
+
+ symbol-tree@3.2.4:
+ optional: true
+
+ tar-fs@2.1.5:
+ dependencies:
+ chownr: 1.1.4
+ mkdirp-classic: 0.5.3
+ pump: 3.0.4
+ tar-stream: 2.2.0
+ optional: true
+
+ tar-stream@2.2.0:
+ dependencies:
+ bl: 4.1.0
+ end-of-stream: 1.4.5
+ fs-constants: 1.0.0
+ inherits: 2.0.4
+ readable-stream: 3.6.2
+ optional: true
+
+ thread-stream@4.2.0:
+ dependencies:
+ real-require: 1.0.0
+
+ tinybench@2.9.0: {}
+
+ tinyexec@1.2.4: {}
+
+ tinyglobby@0.2.17:
+ dependencies:
+ fdir: 6.5.0(picomatch@4.0.5)
+ picomatch: 4.0.5
+
+ tinyrainbow@3.1.0: {}
+
+ tldts-core@6.1.86:
+ optional: true
+
+ tldts@6.1.86:
+ dependencies:
+ tldts-core: 6.1.86
+ optional: true
+
+ toad-cache@3.7.4: {}
+
+ tough-cookie@5.1.2:
+ dependencies:
+ tldts: 6.1.86
+ optional: true
+
+ tr46@5.1.1:
+ dependencies:
+ punycode: 2.3.1
+ optional: true
+
+ tslib@2.8.1:
+ optional: true
+
+ tunnel-agent@0.6.0:
+ dependencies:
+ safe-buffer: 5.2.1
+ optional: true
+
+ typescript@7.0.2:
+ optionalDependencies:
+ '@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-arm': 7.0.2
+ '@typescript/typescript-linux-arm64': 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
+
+ undici-types@7.18.2: {}
+
+ util-deprecate@1.0.2:
+ optional: true
+
+ vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0):
+ dependencies:
+ lightningcss: 1.33.0
+ picomatch: 4.0.5
+ postcss: 8.5.23
+ rolldown: 1.1.5
+ tinyglobby: 0.2.17
+ optionalDependencies:
+ '@types/node': 24.13.3
+ fsevents: 2.3.3
+ yaml: 2.9.0
+
+ vitest@4.1.10(@types/node@24.13.3)(jsdom@26.1.0(canvas@3.2.3))(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0)):
+ dependencies:
+ '@vitest/expect': 4.1.10
+ '@vitest/mocker': 4.1.10(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0))
+ '@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
+ 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(@types/node@24.13.3)(yaml@2.9.0)
+ why-is-node-running: 2.3.0
+ optionalDependencies:
+ '@types/node': 24.13.3
+ jsdom: 26.1.0(canvas@3.2.3)
+ transitivePeerDependencies:
+ - msw
+
+ w3c-xmlserializer@5.0.0:
+ dependencies:
+ xml-name-validator: 5.0.0
+ optional: true
+
+ webidl-conversions@7.0.0:
+ optional: true
+
+ whatwg-encoding@3.1.1:
+ dependencies:
+ iconv-lite: 0.6.3
+ optional: true
+
+ whatwg-mimetype@4.0.0:
+ optional: true
+
+ whatwg-url@14.2.0:
+ dependencies:
+ tr46: 5.1.1
+ webidl-conversions: 7.0.0
+ optional: true
+
+ why-is-node-running@2.3.0:
+ dependencies:
+ siginfo: 2.0.0
+ stackback: 0.0.2
+
+ wrappy@1.0.2:
+ optional: true
+
+ ws@8.21.1:
+ optional: true
+
+ xml-name-validator@5.0.0:
+ optional: true
+
+ xmlchars@2.2.0:
+ optional: true
+
+ yaml@2.9.0: {}
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
new file mode 100644
index 0000000..bfe29af
--- /dev/null
+++ b/pnpm-workspace.yaml
@@ -0,0 +1,7 @@
+packages:
+ - apps/*
+ - packages/*
+
+onlyBuiltDependencies:
+ - better-sqlite3
+ - esbuild
diff --git a/scripts/frozen-versions.mjs b/scripts/frozen-versions.mjs
new file mode 100644
index 0000000..1f5cd20
--- /dev/null
+++ b/scripts/frozen-versions.mjs
@@ -0,0 +1,61 @@
+export const frozenPackages = {
+ "package.json": {
+ devDependencies: {
+ "@playwright/test": "1.62.0",
+ typescript: "7.0.2",
+ vite: "8.1.5",
+ vitest: "4.1.10",
+ },
+ },
+ "apps/web/package.json": {
+ dependencies: {
+ "@vibrant/core": "4.0.4",
+ "@vibrant/quantizer-mmcq": "4.0.4",
+ fabric: "7.4.0",
+ react: "19.2.8",
+ "react-dom": "19.2.8",
+ },
+ devDependencies: {
+ "@vitejs/plugin-react": "6.0.4",
+ typescript: "7.0.2",
+ vite: "8.1.5",
+ },
+ },
+ "apps/api/package.json": {
+ dependencies: {
+ "@fastify/swagger": "9.8.1",
+ "@sinclair/typebox": "0.34.52",
+ "better-sqlite3": "13.0.1",
+ "drizzle-orm": "0.45.2",
+ fastify: "5.10.0",
+ },
+ devDependencies: {
+ typescript: "7.0.2",
+ },
+ },
+ "apps/worker/package.json": {
+ dependencies: {
+ "better-sqlite3": "13.0.1",
+ "drizzle-orm": "0.45.2",
+ },
+ devDependencies: {
+ typescript: "7.0.2",
+ },
+ },
+ "packages/shared-contracts/package.json": {
+ dependencies: {
+ "@sinclair/typebox": "0.34.52",
+ },
+ devDependencies: {
+ typescript: "7.0.2",
+ },
+ },
+};
+
+export const frozenRuntime = {
+ arch: "x64",
+ dotnetTarget: "net8.0-windows",
+ node: "24.13.0",
+ os: "win32",
+ pnpm: "10.28.2",
+};
diff --git a/scripts/lib/tdd-trace.mjs b/scripts/lib/tdd-trace.mjs
new file mode 100644
index 0000000..7204723
--- /dev/null
+++ b/scripts/lib/tdd-trace.mjs
@@ -0,0 +1,259 @@
+import { createHash } from "node:crypto";
+import { readFileSync } from "node:fs";
+import { resolve } from "node:path";
+
+const expectedCounts = {
+ acceptanceCriteria: 52,
+ errorCategories: 9,
+ featureModules: 13,
+ parentFamilies: 89,
+ productContracts: 19,
+ requirements: 109,
+ tasks: 52,
+ testCases: 117,
+ uiPages: 22,
+};
+
+function readText(root, path) {
+ return readFileSync(resolve(root, path), "utf8");
+}
+
+function sha256(root, path) {
+ return createHash("sha256").update(readFileSync(resolve(root, path))).digest("hex").toUpperCase();
+}
+
+function duplicates(values) {
+ const counts = new Map();
+ for (const value of values) counts.set(value, (counts.get(value) ?? 0) + 1);
+ return [...counts.entries()].filter(([, count]) => count > 1).map(([value]) => value);
+}
+
+function markdownTable(markdown, headingPattern) {
+ const lines = markdown.split(/\r?\n/);
+ const headingIndex = lines.findIndex((line) => headingPattern.test(line));
+ if (headingIndex < 0) return [];
+
+ const tableIndex = lines.findIndex((line, index) => index > headingIndex && line.trim().startsWith("|"));
+ if (tableIndex < 0) return [];
+
+ const rows = [];
+ for (let index = tableIndex + 2; index < lines.length; index += 1) {
+ const line = lines[index].trim();
+ if (!line.startsWith("|")) break;
+ rows.push(line.split("|").slice(1, -1).map((cell) => cell.trim()));
+ }
+ return rows;
+}
+
+function collectPenIds(node, ids, duplicateIds) {
+ if (node.id) {
+ if (ids.has(node.id)) duplicateIds.push(node.id);
+ ids.add(node.id);
+ }
+ for (const child of node.children ?? []) collectPenIds(child, ids, duplicateIds);
+}
+
+function uiFrameIds(scope) {
+ if (!scope.frames) return [];
+ const frames = Array.isArray(scope.frames) ? scope.frames : [scope.frames];
+ return frames.map((frame) => frame.frame_id).filter((id) => id && id !== "UIDesign-only");
+}
+
+export function validateTddTrace({ root = process.cwd(), manifestOverride } = {}) {
+ const errors = [];
+ const manifest = manifestOverride ?? JSON.parse(readText(root, "tasks.manifest.json"));
+ const prd = readText(root, "PRD.md");
+ const featureSummary = readText(root, "FeatureSummary.md");
+ const tdd = readText(root, "tdd.md");
+ const tasksMarkdown = readText(root, "tasks.md");
+ const pen = JSON.parse(readText(root, "Dada-P0A-LowFi.pen"));
+
+ for (const [path, expectedHash] of Object.entries(manifest.source_hashes ?? {})) {
+ const actualHash = sha256(root, path);
+ if (actualHash !== expectedHash.toUpperCase()) {
+ errors.push(`${path} SHA-256 mismatch: ${actualHash}`);
+ }
+ }
+
+ if (manifest.tasks.length !== expectedCounts.tasks || manifest.task_count !== expectedCounts.tasks) {
+ errors.push(`task count must be ${expectedCounts.tasks}`);
+ }
+ if (
+ manifest.case_catalog.length !== expectedCounts.testCases ||
+ manifest.normative_case_count !== expectedCounts.testCases
+ ) {
+ errors.push(`normative case count must be ${expectedCounts.testCases}`);
+ }
+
+ const taskIds = manifest.tasks.map((task) => task.task_id);
+ const familyAssignments = manifest.tasks.flatMap((task) => task.parent_families);
+ const caseAssignments = manifest.tasks.flatMap((task) => task.case_ids);
+ const catalogCaseIds = manifest.case_catalog.map((testCase) => testCase.case_id);
+ const catalogFamilies = [...new Set(manifest.case_catalog.map((testCase) => testCase.parent_family))];
+
+ for (const [label, values] of [
+ ["task", taskIds],
+ ["family assignment", familyAssignments],
+ ["case assignment", caseAssignments],
+ ["case catalog", catalogCaseIds],
+ ]) {
+ const repeated = duplicates(values);
+ if (repeated.length > 0) errors.push(`duplicate ${label} IDs: ${repeated.join(", ")}`);
+ }
+
+ if (familyAssignments.length !== expectedCounts.parentFamilies || new Set(familyAssignments).size !== expectedCounts.parentFamilies) {
+ errors.push(`parent family assignments must be unique and total ${expectedCounts.parentFamilies}`);
+ }
+ if (manifest.parent_family_count !== expectedCounts.parentFamilies || catalogFamilies.length !== expectedCounts.parentFamilies) {
+ errors.push(`parent family catalog count must be ${expectedCounts.parentFamilies}`);
+ }
+ if (caseAssignments.length !== expectedCounts.testCases || new Set(caseAssignments).size !== expectedCounts.testCases) {
+ errors.push(`case assignments must be unique and total ${expectedCounts.testCases}`);
+ }
+
+ const assignedFamilySet = new Set(familyAssignments);
+ const assignedCaseSet = new Set(caseAssignments);
+ for (const family of catalogFamilies) {
+ if (!assignedFamilySet.has(family)) errors.push(`unassigned parent family: ${family}`);
+ if (!tdd.includes(family)) errors.push(`parent family missing from tdd.md: ${family}`);
+ }
+ for (const caseId of catalogCaseIds) {
+ if (!assignedCaseSet.has(caseId)) errors.push(`unassigned normative case: ${caseId}`);
+ if (!tdd.includes(caseId)) errors.push(`normative case missing from tdd.md: ${caseId}`);
+ }
+ for (const assignedCase of assignedCaseSet) {
+ if (!catalogCaseIds.includes(assignedCase)) errors.push(`assigned case missing from catalog: ${assignedCase}`);
+ }
+
+ const taskIndex = new Map(taskIds.map((id, index) => [id, index]));
+ const knownWorkPackages = new Set(manifest.tasks.map((task) => task.work_package));
+ manifest.tasks.forEach((task, index) => {
+ if (!/^TASK-(?:WP\d+|FINAL)-\d{2}$/.test(task.task_id)) {
+ errors.push(`invalid task ID: ${task.task_id}`);
+ }
+ if (!tasksMarkdown.includes(task.task_id)) errors.push(`task missing from tasks.md: ${task.task_id}`);
+
+ for (const dependency of task.dependencies.task_ids) {
+ const dependencyIndex = taskIndex.get(dependency);
+ if (dependencyIndex === undefined) errors.push(`${task.task_id} has unknown dependency ${dependency}`);
+ else if (dependencyIndex >= index) errors.push(`${task.task_id} dependency is not earlier: ${dependency}`);
+ }
+
+ for (const dependency of task.dependencies.work_packages) {
+ if (!knownWorkPackages.has(dependency)) errors.push(`${task.task_id} has unknown work-package dependency ${dependency}`);
+ }
+
+ if (task.validation_commands.length === 0) errors.push(`${task.task_id} has no validation command`);
+ if (task.evidence_directories.length === 0) errors.push(`${task.task_id} has no evidence directory`);
+ if (task.automation.length === 0) errors.push(`${task.task_id} has no automation classification`);
+ if (task.release_gate.length === 0) errors.push(`${task.task_id} has no release gate`);
+ });
+
+ for (const testCase of manifest.case_catalog) {
+ if (!/^TDD-[A-Z0-9-]+-[a-z0-9-]+$/.test(testCase.case_id)) {
+ errors.push(`invalid case ID: ${testCase.case_id}`);
+ }
+ if (!testCase.case_id.startsWith(`${testCase.parent_family}-`)) {
+ errors.push(`${testCase.case_id} does not belong to ${testCase.parent_family}`);
+ }
+ for (const field of [
+ "requirement_ac_source",
+ "fixture_and_preconditions",
+ "numbered_steps",
+ "expected_response_ui",
+ "expected_db_files",
+ "forbidden_side_effects",
+ "evidence_files",
+ ]) {
+ if (!testCase[field]?.trim()) errors.push(`${testCase.case_id} has an empty ${field}`);
+ }
+ }
+
+ const requirementIds = [...new Set(manifest.tasks.flatMap((task) => task.requirements))];
+ if (requirementIds.length !== expectedCounts.requirements) {
+ errors.push(`requirement coverage must total ${expectedCounts.requirements}`);
+ }
+ for (const id of requirementIds) {
+ if (!prd.includes(id)) errors.push(`requirement missing from PRD.md: ${id}`);
+ }
+
+ const acceptanceCriteria = [...new Set(manifest.tasks.flatMap((task) => task.acceptance_criteria))];
+ const expectedAcceptanceCriteria = Array.from({ length: 56 }, (_, index) => index + 1)
+ .filter((number) => ![8, 26, 37, 54].includes(number))
+ .map((number) => `AC-${String(number).padStart(2, "0")}`);
+ if (
+ acceptanceCriteria.length !== expectedCounts.acceptanceCriteria ||
+ expectedAcceptanceCriteria.some((id) => !acceptanceCriteria.includes(id))
+ ) {
+ errors.push(`current P0-A AC coverage must be the frozen ${expectedCounts.acceptanceCriteria}-item set`);
+ }
+
+ const featureModules = markdownTable(featureSummary, /^## 5\./);
+ const errorCategories = markdownTable(featureSummary, /^### 6\.1\b/);
+ const productContracts = markdownTable(featureSummary, /^## 7\./);
+ for (const [label, rows, count] of [
+ ["feature modules", featureModules, expectedCounts.featureModules],
+ ["error categories", errorCategories, expectedCounts.errorCategories],
+ ["product contracts", productContracts, expectedCounts.productContracts],
+ ]) {
+ if (rows.length !== count) errors.push(`${label} table must contain ${count} rows`);
+ if (duplicates(rows.map((row) => row[0])).length > 0) errors.push(`${label} table has duplicate keys`);
+ }
+
+ const uiScopes = manifest.tasks.flatMap((task) => task.ui_scope);
+ const pageIds = [...new Set(uiScopes.map((scope) => scope.page_id))];
+ if (pageIds.length !== expectedCounts.uiPages) errors.push(`UI page coverage must total ${expectedCounts.uiPages}`);
+ const uiRoleKeys = uiScopes.map((scope) => `${scope.page_id}:${scope.role}`);
+ for (const pageId of pageIds) {
+ for (const role of ["implementation", "final_evidence"]) {
+ if (!uiRoleKeys.includes(`${pageId}:${role}`)) errors.push(`${pageId} is missing UI role ${role}`);
+ }
+ }
+
+ const penIds = new Set();
+ const duplicatePenIds = [];
+ collectPenIds(pen, penIds, duplicatePenIds);
+ if (duplicatePenIds.length > 0) errors.push(`duplicate .pen IDs: ${duplicatePenIds.join(", ")}`);
+ if (pen.children.length !== 19 || pen.children.filter((frame) => frame.id !== "Z8p3I").length !== 18) {
+ errors.push("Dada-P0A-LowFi.pen must contain one index and 18 product frames");
+ }
+ for (const frameId of new Set(uiScopes.flatMap(uiFrameIds))) {
+ if (!penIds.has(frameId)) errors.push(`UI scope references an unknown .pen frame: ${frameId}`);
+ }
+
+ const requiredScripts = [
+ "test:unit",
+ "test:integration",
+ "test:api",
+ "test:worker",
+ "test:e2e",
+ "test:visual",
+ "test:performance",
+ "test:security",
+ "test:package",
+ "validate:tdd-trace",
+ "test:all",
+ "validate:external",
+ ];
+ const packageJson = JSON.parse(readText(root, "package.json"));
+ for (const script of requiredScripts) {
+ if (!packageJson.scripts?.[script]) errors.push(`package.json is missing script ${script}`);
+ }
+
+ return {
+ errors,
+ status: errors.length === 0 ? "passed" : "failed",
+ summary: {
+ acceptanceCriteria: acceptanceCriteria.length,
+ errorCategories: errorCategories.length,
+ featureModules: featureModules.length,
+ parentFamilies: catalogFamilies.length,
+ penProductFrames: pen.children.filter((frame) => frame.id !== "Z8p3I").length,
+ productContracts: productContracts.length,
+ requirements: requirementIds.length,
+ tasks: manifest.tasks.length,
+ testCases: manifest.case_catalog.length,
+ uiPages: pageIds.length,
+ },
+ };
+}
diff --git a/scripts/native-smoke.mjs b/scripts/native-smoke.mjs
new file mode 100644
index 0000000..e7b6bcb
--- /dev/null
+++ b/scripts/native-smoke.mjs
@@ -0,0 +1,23 @@
+import { createRequire } from "node:module";
+import { resolve } from "node:path";
+import { pathToFileURL } from "node:url";
+
+const requireFromApi = createRequire(pathToFileURL(resolve("apps/api/package.json")));
+const Database = requireFromApi("better-sqlite3");
+const sqlitePackage = requireFromApi("better-sqlite3/package.json");
+
+const database = new Database(":memory:");
+const row = database.prepare("select 1 as value").get();
+database.close();
+
+const result = {
+ arch: process.arch,
+ betterSqlite3: sqlitePackage.version,
+ node: process.version.slice(1),
+ os: process.platform,
+ selectValue: row.value,
+ status: row.value === 1 ? "passed" : "failed",
+};
+
+console.log(JSON.stringify(result));
+if (result.status !== "passed") process.exit(1);
diff --git a/scripts/package-smoke.mjs b/scripts/package-smoke.mjs
new file mode 100644
index 0000000..c060a80
--- /dev/null
+++ b/scripts/package-smoke.mjs
@@ -0,0 +1,77 @@
+import { execFileSync } from "node:child_process";
+import { copyFileSync, existsSync, mkdirSync, writeFileSync } from "node:fs";
+import { resolve } from "node:path";
+
+import { frozenRuntime } from "./frozen-versions.mjs";
+
+if (
+ process.platform !== frozenRuntime.os ||
+ process.arch !== frozenRuntime.arch ||
+ process.version.slice(1) !== frozenRuntime.node
+) {
+ throw new Error("The package smoke must run on the frozen win-x64 Node 24.13.0 runtime.");
+}
+
+const runtimeDirectory = resolve(".build/runtime");
+const runtimeNode = resolve(runtimeDirectory, "node.exe");
+mkdirSync(runtimeDirectory, { recursive: true });
+copyFileSync(process.execPath, runtimeNode);
+
+const nativeSmoke = JSON.parse(
+ execFileSync(runtimeNode, ["scripts/native-smoke.mjs"], { encoding: "utf8" }).trim(),
+);
+const workerSmoke = JSON.parse(
+ execFileSync(runtimeNode, ["scripts/worker-smoke.mjs"], { encoding: "utf8" }).trim(),
+);
+
+execFileSync(
+ "dotnet",
+ [
+ "restore",
+ "supervisor/Dada.Supervisor/Dada.Supervisor.csproj",
+ "--configfile",
+ "NuGet.Config",
+ ],
+ { stdio: "inherit" },
+);
+execFileSync(
+ "dotnet",
+ [
+ "build",
+ "supervisor/Dada.Supervisor/Dada.Supervisor.csproj",
+ "--configuration",
+ "Release",
+ "--no-restore",
+ ],
+ { stdio: "inherit" },
+);
+
+const supervisorExecutable = resolve(
+ "supervisor/Dada.Supervisor/bin/Release/net8.0-windows/Dada.Supervisor.exe",
+);
+if (!existsSync(supervisorExecutable)) {
+ throw new Error("The .NET 8 WinForms supervisor executable was not produced.");
+}
+
+const result = {
+ schema_version: "1.0",
+ native: nativeSmoke,
+ packagedNodeCandidate: {
+ path: ".build/runtime/node.exe",
+ version: frozenRuntime.node,
+ },
+ status: "passed",
+ supervisor: {
+ build: "passed",
+ target: frozenRuntime.dotnetTarget,
+ },
+ worker: workerSmoke,
+};
+
+const evidenceDirectory = process.env.DADA_EVIDENCE_DIR;
+if (evidenceDirectory) {
+ mkdirSync(evidenceDirectory, { recursive: true });
+ writeFileSync(resolve(evidenceDirectory, "native-smoke.json"), `${JSON.stringify(result, null, 2)}\n`);
+}
+
+console.log(JSON.stringify(result, null, 2));
diff --git a/scripts/redaction-scan.mjs b/scripts/redaction-scan.mjs
new file mode 100644
index 0000000..f2e9dc6
--- /dev/null
+++ b/scripts/redaction-scan.mjs
@@ -0,0 +1,32 @@
+import { readdirSync, readFileSync, statSync } from "node:fs";
+import { extname, join, relative } from "node:path";
+
+const scanRoots = ["apps", "packages", "scripts", "supervisor", "tests"];
+const textExtensions = new Set([".cs", ".json", ".mjs", ".ts", ".tsx", ".yaml", ".yml"]);
+const findings = [];
+
+function visit(path) {
+ for (const name of readdirSync(path)) {
+ const child = join(path, name);
+ const relativePath = relative(process.cwd(), child).replaceAll("\\", "/");
+ if (["bin", "dist", "node_modules", "obj"].includes(name)) continue;
+ if (statSync(child).isDirectory()) {
+ visit(child);
+ continue;
+ }
+ if (!textExtensions.has(extname(name)) || relativePath === "scripts/redaction-scan.mjs") continue;
+
+ const content = readFileSync(child, "utf8");
+ const prohibited = [
+ /-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/,
+ /[A-Za-z]:\\Users\\[^\\\s]+/,
+ /(?:api[_-]?key|password|secret)\s*[:=]\s*["'][^"']{8,}["']/i,
+ ];
+ if (prohibited.some((pattern) => pattern.test(content))) findings.push(relativePath);
+ }
+}
+
+for (const root of scanRoots) visit(root);
+
+console.log(JSON.stringify({ findings, status: findings.length === 0 ? "passed" : "failed" }, null, 2));
+if (findings.length > 0) process.exit(1);
diff --git a/scripts/run-wp0-01-validation.mjs b/scripts/run-wp0-01-validation.mjs
new file mode 100644
index 0000000..b6383d9
--- /dev/null
+++ b/scripts/run-wp0-01-validation.mjs
@@ -0,0 +1,79 @@
+import { createHash } from "node:crypto";
+import { spawnSync } from "node:child_process";
+import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
+import { resolve } from "node:path";
+
+const runId = process.env.DADA_TDD_RUN_ID ?? `wp0-01-green-${new Date().toISOString().replace(/[^0-9]/g, "")}`;
+const caseId = "TDD-WP0-DEP-001-frozen-toolchain";
+const evidenceDirectory = resolve("artifacts", "tdd", runId, "cases", caseId);
+
+if (existsSync(evidenceDirectory)) {
+ throw new Error(`Evidence run already exists: ${runId}`);
+}
+mkdirSync(evidenceDirectory, { recursive: true });
+
+const commandDefinitions = [
+ { command: "pnpm install --frozen-lockfile --offline", args: ["install", "--frozen-lockfile", "--offline"] },
+ { command: "pnpm test:unit", args: ["test:unit"] },
+ { command: "pnpm test:security", args: ["test:security"] },
+ { command: "pnpm test:package", args: ["test:package"] },
+ { command: "pnpm validate:tdd-trace", args: ["validate:tdd-trace"] },
+];
+
+const startedAt = new Date().toISOString();
+const commands = [];
+for (const definition of commandDefinitions) {
+ const commandStartedAt = new Date().toISOString();
+ const executable = process.platform === "win32" ? (process.env.ComSpec ?? "cmd.exe") : "pnpm";
+ const args = process.platform === "win32"
+ ? ["/d", "/s", "/c", `pnpm ${definition.args.join(" ")}`]
+ : definition.args;
+ const result = spawnSync(executable, args, {
+ env: { ...process.env, DADA_EVIDENCE_DIR: evidenceDirectory },
+ stdio: "inherit",
+ });
+ commands.push({
+ command: definition.command,
+ exit_code: result.status ?? 1,
+ finished_at: new Date().toISOString(),
+ started_at: commandStartedAt,
+ });
+}
+
+const allPassed = commands.every((command) => command.exit_code === 0);
+const requiredEvidence = ["dependency-tree.json", "native-smoke.json"];
+const missingEvidence = requiredEvidence.filter((path) => !existsSync(resolve(evidenceDirectory, path)));
+const passed = allPassed && missingEvidence.length === 0;
+
+writeFileSync(
+ resolve(evidenceDirectory, "commands.json"),
+ `${JSON.stringify({ schema_version: "1.0", run_id: runId, phase: "green", commands }, null, 2)}\n`,
+);
+
+const manifestBytes = readFileSync("tasks.manifest.json");
+const result = {
+ schema_version: "1.0",
+ run_id: runId,
+ task_id: "TASK-WP0-01",
+ case_id: caseId,
+ parent_family: "TDD-WP0-DEP-001",
+ phase: "green",
+ status: passed ? "passed" : "failed",
+ manifest: {
+ path: "tasks.manifest.json",
+ sha256: createHash("sha256").update(manifestBytes).digest("hex").toUpperCase(),
+ },
+ environment: {
+ arch: process.arch,
+ node: process.version.slice(1),
+ os: process.platform,
+ },
+ evidence_files: ["commands.json", ...requiredEvidence],
+ missing_evidence: missingEvidence,
+ started_at: startedAt,
+ finished_at: new Date().toISOString(),
+};
+writeFileSync(resolve(evidenceDirectory, "result.json"), `${JSON.stringify(result, null, 2)}\n`);
+
+console.log(JSON.stringify(result, null, 2));
+if (!passed) process.exit(1);
diff --git a/scripts/validate-external.mjs b/scripts/validate-external.mjs
new file mode 100644
index 0000000..e2b7444
--- /dev/null
+++ b/scripts/validate-external.mjs
@@ -0,0 +1,23 @@
+const allowedServices = new Set(["ai", "resend", "amap"]);
+
+function argument(name) {
+ const index = process.argv.indexOf(name);
+ return index >= 0 ? process.argv[index + 1] : undefined;
+}
+
+const service = argument("--service");
+const runId = argument("--run-id");
+
+if (!allowedServices.has(service) || !runId) {
+ console.error("Usage: pnpm validate:external -- --service --run-id ");
+ process.exit(2);
+}
+
+console.log(
+ JSON.stringify({
+ mode: "mock",
+ run_id: runId,
+ service,
+ status: "not_applicable_for_TASK-WP0-01",
+ }),
+);
diff --git a/scripts/validate-layer-scope.mjs b/scripts/validate-layer-scope.mjs
new file mode 100644
index 0000000..9f54c67
--- /dev/null
+++ b/scripts/validate-layer-scope.mjs
@@ -0,0 +1,24 @@
+import { readFileSync } from "node:fs";
+
+const layer = process.argv[2];
+if (!layer) {
+ console.error("A test layer is required.");
+ process.exit(2);
+}
+
+const manifest = JSON.parse(readFileSync("tasks.manifest.json", "utf8"));
+const task = manifest.tasks.find((item) => item.task_id === "TASK-WP0-01");
+const applicable = task.layers.includes(layer);
+
+if (applicable) {
+ console.error(`TASK-WP0-01 assigns ${layer}; a real layer runner is required.`);
+ process.exit(1);
+}
+
+console.log(
+ JSON.stringify({
+ layer,
+ status: "not_applicable",
+ task_id: task.task_id,
+ }),
+);
diff --git a/scripts/validate-tdd-trace.mjs b/scripts/validate-tdd-trace.mjs
new file mode 100644
index 0000000..924df64
--- /dev/null
+++ b/scripts/validate-tdd-trace.mjs
@@ -0,0 +1,5 @@
+import { validateTddTrace } from "./lib/tdd-trace.mjs";
+
+const result = validateTddTrace();
+console.log(JSON.stringify(result, null, 2));
+if (result.errors.length > 0) process.exit(1);
diff --git a/scripts/verify-frozen-dependencies.mjs b/scripts/verify-frozen-dependencies.mjs
new file mode 100644
index 0000000..88831d1
--- /dev/null
+++ b/scripts/verify-frozen-dependencies.mjs
@@ -0,0 +1,89 @@
+import { execFileSync } from "node:child_process";
+import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
+import { dirname, resolve } from "node:path";
+
+import { frozenPackages, frozenRuntime } from "./frozen-versions.mjs";
+
+function readJson(path) {
+ return JSON.parse(readFileSync(path, "utf8"));
+}
+
+function installedPackageVersion(manifestPath, packageName) {
+ const packagePath = resolve(
+ dirname(manifestPath),
+ "node_modules",
+ ...packageName.split("/"),
+ "package.json",
+ );
+ return readJson(packagePath).version;
+}
+
+export function verifyFrozenDependencies() {
+ const problems = [];
+ const packages = {};
+
+ for (const [manifestPath, sections] of Object.entries(frozenPackages)) {
+ const manifest = readJson(manifestPath);
+ packages[manifest.name] = {};
+
+ for (const [section, expected] of Object.entries(sections)) {
+ for (const [name, version] of Object.entries(expected)) {
+ const declared = manifest[section]?.[name];
+ if (declared !== version) {
+ problems.push(`${manifestPath} ${section}.${name}: declared ${declared ?? "missing"}, expected ${version}`);
+ continue;
+ }
+
+ const installed = installedPackageVersion(manifestPath, name);
+ packages[manifest.name][name] = installed;
+ if (installed !== version) {
+ problems.push(`${manifestPath} ${name}: installed ${installed}, expected ${version}`);
+ }
+ }
+ }
+ }
+
+ const packageManager = readJson("package.json").packageManager;
+ const pnpmVersion = process.platform === "win32"
+ ? execFileSync(process.env.ComSpec ?? "cmd.exe", ["/d", "/s", "/c", "pnpm --version"], {
+ encoding: "utf8",
+ }).trim()
+ : execFileSync("pnpm", ["--version"], { encoding: "utf8" }).trim();
+ const runtimeChecks = {
+ arch: process.arch,
+ node: process.version.slice(1),
+ os: process.platform,
+ packageManager,
+ pnpm: pnpmVersion,
+ };
+
+ for (const key of ["arch", "node", "os", "pnpm"]) {
+ if (runtimeChecks[key] !== frozenRuntime[key]) {
+ problems.push(`${key}: running ${runtimeChecks[key]}, expected ${frozenRuntime[key]}`);
+ }
+ }
+ if (packageManager !== `pnpm@${frozenRuntime.pnpm}`) {
+ problems.push(`packageManager: declared ${packageManager}, expected pnpm@${frozenRuntime.pnpm}`);
+ }
+
+ return {
+ packages,
+ problems,
+ runtime: runtimeChecks,
+ status: problems.length === 0 ? "passed" : "failed",
+ };
+}
+
+const snapshot = verifyFrozenDependencies();
+const evidenceDirectory = process.env.DADA_EVIDENCE_DIR;
+
+if (evidenceDirectory) {
+ mkdirSync(evidenceDirectory, { recursive: true });
+ writeFileSync(
+ resolve(evidenceDirectory, "dependency-tree.json"),
+ `${JSON.stringify({ schema_version: "1.0", ...snapshot }, null, 2)}\n`,
+ );
+}
+
+console.log(JSON.stringify(snapshot, null, 2));
+if (snapshot.problems.length > 0) process.exit(1);
diff --git a/scripts/worker-smoke.mjs b/scripts/worker-smoke.mjs
new file mode 100644
index 0000000..2f3cebb
--- /dev/null
+++ b/scripts/worker-smoke.mjs
@@ -0,0 +1,23 @@
+import { resolve } from "node:path";
+import { Worker } from "node:worker_threads";
+
+const worker = new Worker(resolve("apps/worker/dist/worker.js"));
+const timeout = setTimeout(() => {
+ void worker.terminate();
+ throw new Error("Worker probe timed out.");
+}, 5_000);
+
+const reply = await new Promise((resolveReply, reject) => {
+ worker.once("error", reject);
+ worker.once("message", resolveReply);
+ worker.postMessage("ping");
+});
+
+clearTimeout(timeout);
+await worker.terminate();
+
+if (reply !== "pong") {
+ throw new Error(`Unexpected Worker probe reply: ${String(reply)}`);
+}
+
+console.log(JSON.stringify({ reply, status: "passed" }));
diff --git a/supervisor/Dada.Supervisor/Dada.Supervisor.csproj b/supervisor/Dada.Supervisor/Dada.Supervisor.csproj
new file mode 100644
index 0000000..0590777
--- /dev/null
+++ b/supervisor/Dada.Supervisor/Dada.Supervisor.csproj
@@ -0,0 +1,9 @@
+
+
+ WinExe
+ net8.0-windows
+ true
+ enable
+ enable
+
+
diff --git a/supervisor/Dada.Supervisor/Program.cs b/supervisor/Dada.Supervisor/Program.cs
new file mode 100644
index 0000000..9e3e282
--- /dev/null
+++ b/supervisor/Dada.Supervisor/Program.cs
@@ -0,0 +1,11 @@
+namespace Dada.Supervisor;
+
+internal static class Program
+{
+ [STAThread]
+ private static void Main()
+ {
+ ApplicationConfiguration.Initialize();
+ Application.Run(new SupervisorForm());
+ }
+}
diff --git a/supervisor/Dada.Supervisor/SupervisorForm.cs b/supervisor/Dada.Supervisor/SupervisorForm.cs
new file mode 100644
index 0000000..609b155
--- /dev/null
+++ b/supervisor/Dada.Supervisor/SupervisorForm.cs
@@ -0,0 +1,13 @@
+namespace Dada.Supervisor;
+
+internal sealed class SupervisorForm : Form
+{
+ public SupervisorForm()
+ {
+ ClientSize = new Size(420, 160);
+ FormBorderStyle = FormBorderStyle.FixedDialog;
+ MaximizeBox = false;
+ StartPosition = FormStartPosition.CenterScreen;
+ Text = "Dada";
+ }
+}
diff --git a/tests/api/app.test.ts b/tests/api/app.test.ts
new file mode 100644
index 0000000..6d131de
--- /dev/null
+++ b/tests/api/app.test.ts
@@ -0,0 +1,12 @@
+import { describe, expect, it } from "vitest";
+
+import { createApp } from "../../apps/api/src/app.js";
+
+describe("Fastify skeleton", () => {
+ it("becomes ready without adding a product route", async () => {
+ const app = createApp();
+ await app.ready();
+ expect(app.printRoutes()).not.toContain("health");
+ await app.close();
+ });
+});
diff --git a/tests/integration/native-database.test.ts b/tests/integration/native-database.test.ts
new file mode 100644
index 0000000..c18713c
--- /dev/null
+++ b/tests/integration/native-database.test.ts
@@ -0,0 +1,15 @@
+import { createRequire } from "node:module";
+
+import { describe, expect, it } from "vitest";
+
+const requireFromApi = createRequire(new URL("../../apps/api/package.json", import.meta.url));
+const Database = requireFromApi("better-sqlite3");
+
+describe("better-sqlite3 native module", () => {
+ it("executes an in-memory query without creating business data", () => {
+ const database = new Database(":memory:");
+ const row = database.prepare("select 1 as value").get();
+ database.close();
+ expect(row.value).toBe(1);
+ });
+});
diff --git a/tests/toolchain/frozen-toolchain.test.mjs b/tests/toolchain/frozen-toolchain.test.mjs
new file mode 100644
index 0000000..74fc700
--- /dev/null
+++ b/tests/toolchain/frozen-toolchain.test.mjs
@@ -0,0 +1,59 @@
+import assert from "node:assert/strict";
+import { existsSync, readFileSync } from "node:fs";
+import test from "node:test";
+
+import { frozenPackages } from "../../scripts/frozen-versions.mjs";
+
+const expectedFiles = [
+ "NuGet.Config",
+ "pnpm-lock.yaml",
+ "pnpm-workspace.yaml",
+ "tsconfig.base.json",
+ "apps/web/package.json",
+ "apps/web/src/toolchain-probe.tsx",
+ "apps/api/package.json",
+ "apps/api/src/app.ts",
+ "apps/worker/package.json",
+ "apps/worker/src/worker.ts",
+ "packages/shared-contracts/package.json",
+ "packages/shared-contracts/src/index.ts",
+ "scripts/validate-tdd-trace.mjs",
+ "scripts/native-smoke.mjs",
+ "supervisor/Dada.Supervisor/Dada.Supervisor.csproj",
+];
+
+function readJson(path) {
+ return JSON.parse(readFileSync(path, "utf8"));
+}
+
+test("TASK-WP0-01 has no unresolved task dependency", () => {
+ const manifest = readJson("tasks.manifest.json");
+ const task = manifest.tasks.find((item) => item.task_id === "TASK-WP0-01");
+ assert.ok(task, "TASK-WP0-01 must exist in tasks.manifest.json");
+ assert.deepEqual(task.dependencies.task_ids, []);
+ assert.deepEqual(task.dependencies.work_packages, []);
+ assert.equal(task.dependencies.source_text, "无");
+});
+
+test("TDD-WP0-DEP-001 frozen toolchain contract is implemented", () => {
+ const problems = [];
+
+ for (const path of expectedFiles) {
+ if (!existsSync(path)) problems.push(`missing file: ${path}`);
+ }
+
+ for (const [path, sections] of Object.entries(frozenPackages)) {
+ if (!existsSync(path)) continue;
+ const packageJson = readJson(path);
+ for (const [section, packages] of Object.entries(sections)) {
+ for (const [name, version] of Object.entries(packages)) {
+ const actual = packageJson[section]?.[name];
+ if (actual !== version) {
+ problems.push(`${path} ${section}.${name}: expected ${version}, got ${actual ?? "missing"}`);
+ }
+ }
+ }
+ }
+
+ assert.deepEqual(problems, []);
+});
diff --git a/tests/unit/toolchain-smoke.test.ts b/tests/unit/toolchain-smoke.test.ts
new file mode 100644
index 0000000..59d55de
--- /dev/null
+++ b/tests/unit/toolchain-smoke.test.ts
@@ -0,0 +1,57 @@
+import { readFileSync } from "node:fs";
+
+import { describe, expect, it } from "vitest";
+
+import { createApp } from "../../apps/api/src/app.js";
+import { renderToolchainProbe } from "../../apps/web/src/toolchain-probe.js";
+import { validateTddTrace } from "../../scripts/lib/tdd-trace.mjs";
+
+function readManifest() {
+ return JSON.parse(readFileSync(new URL("../../tasks.manifest.json", import.meta.url), "utf8"));
+}
+
+describe("TASK-WP0-01 minimum toolchain", () => {
+ it("renders through React and Fabric at the frozen versions", () => {
+ const probe = renderToolchainProbe();
+
+ expect(probe.reactMarkup).toContain("Dada toolchain probe");
+ expect(probe.fabricSvg).toContain(" {
+ const app = createApp();
+ await app.ready();
+ expect(app.hasPlugin("@fastify/swagger")).toBe(true);
+ await app.close();
+ });
+
+ it("validates the frozen TDD trace", () => {
+ const result = validateTddTrace();
+ expect(result.errors).toEqual([]);
+ expect(result.summary).toMatchObject({
+ acceptanceCriteria: 52,
+ parentFamilies: 89,
+ requirements: 109,
+ tasks: 52,
+ testCases: 117,
+ uiPages: 22,
+ });
+ });
+
+ it("rejects a missing normative case", () => {
+ const manifest = readManifest();
+ manifest.case_catalog.pop();
+ const result = validateTddTrace({ manifestOverride: manifest });
+ expect(result.status).toBe("failed");
+ expect(result.errors.some((error) => error.includes("normative case count"))).toBe(true);
+ });
+
+ it("rejects a duplicated case assignment", () => {
+ const manifest = readManifest();
+ manifest.tasks[1].case_ids.push(manifest.tasks[0].case_ids[0]);
+ const result = validateTddTrace({ manifestOverride: manifest });
+ expect(result.status).toBe("failed");
+ expect(result.errors.some((error) => error.includes("duplicate case assignment"))).toBe(true);
+ });
+});
diff --git a/tsconfig.base.json b/tsconfig.base.json
new file mode 100644
index 0000000..9ee6ae1
--- /dev/null
+++ b/tsconfig.base.json
@@ -0,0 +1,13 @@
+{
+ "compilerOptions": {
+ "target": "ES2024",
+ "strict": true,
+ "noUncheckedIndexedAccess": true,
+ "exactOptionalPropertyTypes": true,
+ "forceConsistentCasingInFileNames": true,
+ "skipLibCheck": true,
+ "verbatimModuleSyntax": true,
+ "isolatedModules": true,
+ "resolveJsonModule": true
+ }
+}