) => (
+
+ ),
+ // A block element, not a : MDX parses multi-line children as a paragraph,
+ // and a
inside a
is invalid HTML that the browser reparents, which
+ // shows up as a hydration mismatch. The child overrides keep the lede
+ // typography whether the source is written inline or across lines.
+ Lede: (p: React.HTMLAttributes) => (
+
+ ),
+ Callout,
+ Card,
+ CardGroup,
+ Steps,
+ Step,
+ CodeGroup,
+ ArchitectureDiagram,
+ ...components,
+ };
+}
diff --git a/apps/console/next.config.ts b/apps/console/next.config.ts
index e9ffa30..d9d8ad3 100644
--- a/apps/console/next.config.ts
+++ b/apps/console/next.config.ts
@@ -1,7 +1,35 @@
+import createMDX from "@next/mdx";
import type { NextConfig } from "next";
+import rehypeSlug from "rehype-slug";
+import remarkGfm from "remark-gfm";
+import remarkCodeMeta from "./lib/remark-code-meta";
+// Connection URLs and service credentials are server-runtime configuration.
+// Do not copy them through `env`, which would make Next treat them as build-time
+// values and risks exposing future additions to client bundles.
+//
+// MDX itself is registered in vite.config.ts rather than through `@next/mdx`:
+// vinext runs on Vite/rolldown, and its own MDX delegate forwards remark and
+// rehype plugins but never sets `providerImportSource`, which is what binds
+// `mdx-components.tsx` to the compiled pages.
const nextConfig: NextConfig = {
- /* config options here */
+ // Documentation pages under app/docs/** are authored as MDX.
+ pageExtensions: ["ts", "tsx", "js", "jsx", "md", "mdx"],
+ ...(process.env.GLASSBOX_NEXT_STANDALONE_BUILD === "1"
+ ? { output: "standalone" as const }
+ : {}),
};
-export default nextConfig;
+const withMDX = createMDX({
+ options: {
+ remarkPlugins: [remarkGfm, remarkCodeMeta],
+ rehypePlugins: [rehypeSlug],
+ },
+});
+
+// Vinext owns MDX compilation in local/Sites builds. The deployment image uses
+// Next's standalone server so build-only Vite and Wrangler packages never enter
+// the production runtime.
+export default process.env.GLASSBOX_NEXT_STANDALONE_BUILD === "1"
+ ? withMDX(nextConfig)
+ : nextConfig;
diff --git a/apps/console/package-lock.json b/apps/console/package-lock.json
index 796313b..744e833 100644
--- a/apps/console/package-lock.json
+++ b/apps/console/package-lock.json
@@ -8,25 +8,34 @@
"name": "glassbox-forensics-console",
"version": "0.1.0",
"dependencies": {
- "next": "16.2.6",
- "react": "19.2.6",
- "react-dom": "19.2.6"
+ "@mdx-js/loader": "^3.1.1",
+ "@mdx-js/react": "^3.1.1",
+ "@next/mdx": "^16.3.0",
+ "next": "16.3.0",
+ "react": "19.2.8",
+ "react-dom": "19.2.8",
+ "rehype-slug": "^6.0.0",
+ "remark-gfm": "^4.0.1",
+ "unist-util-visit": "^5.1.0"
},
"devDependencies": {
"@cloudflare/vite-plugin": "1.37.1",
+ "@iconify-json/solar": "^1.2.5",
+ "@mdx-js/rollup": "^3.1.1",
"@tailwindcss/postcss": "4.2.1",
+ "@types/mdx": "^2.0.14",
"@types/node": "22.19.19",
"@types/react": "19.2.14",
"@types/react-dom": "19.2.3",
"@vitejs/plugin-react": "6.0.2",
"@vitejs/plugin-rsc": "0.5.26",
"eslint": "9.39.4",
- "eslint-config-next": "16.2.6",
- "react-server-dom-webpack": "19.2.6",
+ "eslint-config-next": "16.3.0",
+ "react-server-dom-webpack": "19.2.8",
"tailwindcss": "4.2.1",
"typescript": "5.9.3",
"vinext": "0.0.50",
- "vite": "8.0.13",
+ "vite": "8.2.1",
"wrangler": "4.92.0"
},
"engines": {
@@ -47,13 +56,13 @@
}
},
"node_modules/@babel/code-frame": {
- "version": "7.29.0",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz",
- "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==",
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz",
+ "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-validator-identifier": "^7.28.5",
+ "@babel/helper-validator-identifier": "^7.29.7",
"js-tokens": "^4.0.0",
"picocolors": "^1.1.1"
},
@@ -62,9 +71,9 @@
}
},
"node_modules/@babel/compat-data": {
- "version": "7.29.3",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.3.tgz",
- "integrity": "sha512-LIVqM46zQWZhj17qA8wb4nW/ixr2y1Nw+r1etiAWgRM6U1IqP+LNhL1yg440jYZR72jCWcWbLWzIosH+uP1fqg==",
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz",
+ "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -72,21 +81,21 @@
}
},
"node_modules/@babel/core": {
- "version": "7.29.0",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz",
- "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz",
+ "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/code-frame": "^7.29.0",
- "@babel/generator": "^7.29.0",
- "@babel/helper-compilation-targets": "^7.28.6",
- "@babel/helper-module-transforms": "^7.28.6",
- "@babel/helpers": "^7.28.6",
- "@babel/parser": "^7.29.0",
- "@babel/template": "^7.28.6",
- "@babel/traverse": "^7.29.0",
- "@babel/types": "^7.29.0",
+ "@babel/code-frame": "^7.29.7",
+ "@babel/generator": "^7.29.7",
+ "@babel/helper-compilation-targets": "^7.29.7",
+ "@babel/helper-module-transforms": "^7.29.7",
+ "@babel/helpers": "^7.29.7",
+ "@babel/parser": "^7.29.7",
+ "@babel/template": "^7.29.7",
+ "@babel/traverse": "^7.29.7",
+ "@babel/types": "^7.29.7",
"@jridgewell/remapping": "^2.3.5",
"convert-source-map": "^2.0.0",
"debug": "^4.1.0",
@@ -103,14 +112,14 @@
}
},
"node_modules/@babel/generator": {
- "version": "7.29.1",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz",
- "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==",
+ "version": "7.29.8",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.8.tgz",
+ "integrity": "sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/parser": "^7.29.0",
- "@babel/types": "^7.29.0",
+ "@babel/parser": "^7.29.8",
+ "@babel/types": "^7.29.8",
"@jridgewell/gen-mapping": "^0.3.12",
"@jridgewell/trace-mapping": "^0.3.28",
"jsesc": "^3.0.2"
@@ -120,14 +129,14 @@
}
},
"node_modules/@babel/helper-compilation-targets": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz",
- "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==",
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz",
+ "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/compat-data": "^7.28.6",
- "@babel/helper-validator-option": "^7.27.1",
+ "@babel/compat-data": "^7.29.7",
+ "@babel/helper-validator-option": "^7.29.7",
"browserslist": "^4.24.0",
"lru-cache": "^5.1.1",
"semver": "^6.3.1"
@@ -137,9 +146,9 @@
}
},
"node_modules/@babel/helper-globals": {
- "version": "7.28.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
- "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz",
+ "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -147,29 +156,29 @@
}
},
"node_modules/@babel/helper-module-imports": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz",
- "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==",
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz",
+ "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/traverse": "^7.28.6",
- "@babel/types": "^7.28.6"
+ "@babel/traverse": "^7.29.7",
+ "@babel/types": "^7.29.7"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-module-transforms": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz",
- "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==",
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz",
+ "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-module-imports": "^7.28.6",
- "@babel/helper-validator-identifier": "^7.28.5",
- "@babel/traverse": "^7.28.6"
+ "@babel/helper-module-imports": "^7.29.7",
+ "@babel/helper-validator-identifier": "^7.29.7",
+ "@babel/traverse": "^7.29.7"
},
"engines": {
"node": ">=6.9.0"
@@ -179,9 +188,9 @@
}
},
"node_modules/@babel/helper-string-parser": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
- "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz",
+ "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==",
"dev": true,
"license": "MIT",
"engines": {
@@ -189,9 +198,9 @@
}
},
"node_modules/@babel/helper-validator-identifier": {
- "version": "7.28.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
- "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz",
+ "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -199,9 +208,9 @@
}
},
"node_modules/@babel/helper-validator-option": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
- "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz",
+ "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==",
"dev": true,
"license": "MIT",
"engines": {
@@ -209,27 +218,27 @@
}
},
"node_modules/@babel/helpers": {
- "version": "7.29.2",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz",
- "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==",
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz",
+ "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/template": "^7.28.6",
- "@babel/types": "^7.29.0"
+ "@babel/template": "^7.29.7",
+ "@babel/types": "^7.29.7"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/parser": {
- "version": "7.29.3",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.3.tgz",
- "integrity": "sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==",
+ "version": "7.29.8",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.8.tgz",
+ "integrity": "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/types": "^7.29.0"
+ "@babel/types": "^7.29.8"
},
"bin": {
"parser": "bin/babel-parser.js"
@@ -239,33 +248,33 @@
}
},
"node_modules/@babel/template": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz",
- "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==",
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz",
+ "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/code-frame": "^7.28.6",
- "@babel/parser": "^7.28.6",
- "@babel/types": "^7.28.6"
+ "@babel/code-frame": "^7.29.7",
+ "@babel/parser": "^7.29.7",
+ "@babel/types": "^7.29.7"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/traverse": {
- "version": "7.29.0",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz",
- "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==",
+ "version": "7.29.8",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.8.tgz",
+ "integrity": "sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/code-frame": "^7.29.0",
- "@babel/generator": "^7.29.0",
- "@babel/helper-globals": "^7.28.0",
- "@babel/parser": "^7.29.0",
- "@babel/template": "^7.28.6",
- "@babel/types": "^7.29.0",
+ "@babel/code-frame": "^7.29.7",
+ "@babel/generator": "^7.29.8",
+ "@babel/helper-globals": "^7.29.7",
+ "@babel/parser": "^7.29.8",
+ "@babel/template": "^7.29.7",
+ "@babel/types": "^7.29.8",
"debug": "^4.3.1"
},
"engines": {
@@ -273,14 +282,14 @@
}
},
"node_modules/@babel/types": {
- "version": "7.29.0",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz",
- "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==",
+ "version": "7.29.8",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz",
+ "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-string-parser": "^7.27.1",
- "@babel/helper-validator-identifier": "^7.28.5"
+ "@babel/helper-string-parser": "^7.29.7",
+ "@babel/helper-validator-identifier": "^7.29.7"
},
"engines": {
"node": ">=6.9.0"
@@ -474,9 +483,9 @@
}
},
"node_modules/@esbuild/aix-ppc64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.0.tgz",
- "integrity": "sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz",
+ "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==",
"cpu": [
"ppc64"
],
@@ -492,9 +501,9 @@
}
},
"node_modules/@esbuild/android-arm": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.0.tgz",
- "integrity": "sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.2.tgz",
+ "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==",
"cpu": [
"arm"
],
@@ -510,9 +519,9 @@
}
},
"node_modules/@esbuild/android-arm64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.0.tgz",
- "integrity": "sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz",
+ "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==",
"cpu": [
"arm64"
],
@@ -528,9 +537,9 @@
}
},
"node_modules/@esbuild/android-x64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.0.tgz",
- "integrity": "sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.2.tgz",
+ "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==",
"cpu": [
"x64"
],
@@ -546,9 +555,9 @@
}
},
"node_modules/@esbuild/darwin-arm64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.0.tgz",
- "integrity": "sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz",
+ "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==",
"cpu": [
"arm64"
],
@@ -564,9 +573,9 @@
}
},
"node_modules/@esbuild/darwin-x64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.0.tgz",
- "integrity": "sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz",
+ "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==",
"cpu": [
"x64"
],
@@ -582,9 +591,9 @@
}
},
"node_modules/@esbuild/freebsd-arm64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.0.tgz",
- "integrity": "sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz",
+ "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==",
"cpu": [
"arm64"
],
@@ -600,9 +609,9 @@
}
},
"node_modules/@esbuild/freebsd-x64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.0.tgz",
- "integrity": "sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz",
+ "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==",
"cpu": [
"x64"
],
@@ -618,9 +627,9 @@
}
},
"node_modules/@esbuild/linux-arm": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.0.tgz",
- "integrity": "sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz",
+ "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==",
"cpu": [
"arm"
],
@@ -636,9 +645,9 @@
}
},
"node_modules/@esbuild/linux-arm64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.0.tgz",
- "integrity": "sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz",
+ "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==",
"cpu": [
"arm64"
],
@@ -654,9 +663,9 @@
}
},
"node_modules/@esbuild/linux-ia32": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.0.tgz",
- "integrity": "sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz",
+ "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==",
"cpu": [
"ia32"
],
@@ -672,9 +681,9 @@
}
},
"node_modules/@esbuild/linux-loong64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.0.tgz",
- "integrity": "sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz",
+ "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==",
"cpu": [
"loong64"
],
@@ -690,9 +699,9 @@
}
},
"node_modules/@esbuild/linux-mips64el": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.0.tgz",
- "integrity": "sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz",
+ "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==",
"cpu": [
"mips64el"
],
@@ -708,9 +717,9 @@
}
},
"node_modules/@esbuild/linux-ppc64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.0.tgz",
- "integrity": "sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz",
+ "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==",
"cpu": [
"ppc64"
],
@@ -726,9 +735,9 @@
}
},
"node_modules/@esbuild/linux-riscv64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.0.tgz",
- "integrity": "sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz",
+ "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==",
"cpu": [
"riscv64"
],
@@ -744,9 +753,9 @@
}
},
"node_modules/@esbuild/linux-s390x": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.0.tgz",
- "integrity": "sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz",
+ "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==",
"cpu": [
"s390x"
],
@@ -762,9 +771,9 @@
}
},
"node_modules/@esbuild/linux-x64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.0.tgz",
- "integrity": "sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz",
+ "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==",
"cpu": [
"x64"
],
@@ -780,9 +789,9 @@
}
},
"node_modules/@esbuild/netbsd-arm64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.0.tgz",
- "integrity": "sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz",
+ "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==",
"cpu": [
"arm64"
],
@@ -798,9 +807,9 @@
}
},
"node_modules/@esbuild/netbsd-x64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.0.tgz",
- "integrity": "sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz",
+ "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==",
"cpu": [
"x64"
],
@@ -816,9 +825,9 @@
}
},
"node_modules/@esbuild/openbsd-arm64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.0.tgz",
- "integrity": "sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz",
+ "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==",
"cpu": [
"arm64"
],
@@ -834,9 +843,9 @@
}
},
"node_modules/@esbuild/openbsd-x64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.0.tgz",
- "integrity": "sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz",
+ "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==",
"cpu": [
"x64"
],
@@ -852,9 +861,9 @@
}
},
"node_modules/@esbuild/openharmony-arm64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.0.tgz",
- "integrity": "sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz",
+ "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==",
"cpu": [
"arm64"
],
@@ -870,9 +879,9 @@
}
},
"node_modules/@esbuild/sunos-x64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.0.tgz",
- "integrity": "sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz",
+ "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==",
"cpu": [
"x64"
],
@@ -888,9 +897,9 @@
}
},
"node_modules/@esbuild/win32-arm64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.0.tgz",
- "integrity": "sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz",
+ "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==",
"cpu": [
"arm64"
],
@@ -906,9 +915,9 @@
}
},
"node_modules/@esbuild/win32-ia32": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.0.tgz",
- "integrity": "sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz",
+ "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==",
"cpu": [
"ia32"
],
@@ -924,9 +933,9 @@
}
},
"node_modules/@esbuild/win32-x64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.0.tgz",
- "integrity": "sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==",
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz",
+ "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==",
"cpu": [
"x64"
],
@@ -1151,6 +1160,23 @@
"url": "https://github.com/sponsors/nzakas"
}
},
+ "node_modules/@iconify-json/solar": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/@iconify-json/solar/-/solar-1.2.5.tgz",
+ "integrity": "sha512-WMAiNwchU8zhfrySww6KQBRIBbsQ6SvgIu2yA+CHGyMima/0KQwT5MXogrZPJGoQF+1Ye3Qj6K+1CiyNn3YkoA==",
+ "dev": true,
+ "license": "CC-BY-4.0",
+ "dependencies": {
+ "@iconify/types": "*"
+ }
+ },
+ "node_modules/@iconify/types": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz",
+ "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@img/colour": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz",
@@ -1207,6 +1233,51 @@
"@img/sharp-libvips-darwin-x64": "1.2.4"
}
},
+ "node_modules/@img/sharp-freebsd-wasm32": {
+ "version": "0.35.3",
+ "resolved": "https://registry.npmjs.org/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.3.tgz",
+ "integrity": "sha512-lUxcqWIj2wMQ9BrwNjngcr1gWUr5xgaGThBRqPPalIC2n67Cqj1uPh8NnA/ZhAg8hUbKl+kVHKwgUIwe6ZYPrg==",
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "dependencies": {
+ "@img/sharp-wasm32": "0.35.3"
+ },
+ "engines": {
+ "node": ">=20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-freebsd-wasm32/node_modules/@emnapi/runtime": {
+ "version": "1.11.3",
+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz",
+ "integrity": "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@img/sharp-freebsd-wasm32/node_modules/@img/sharp-wasm32": {
+ "version": "0.35.3",
+ "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.3.tgz",
+ "integrity": "sha512-cZ0XkcYGpHZkqW6iCkqTcmUC0CD9DhD5d/qeZlZkfRBn6GnHniZXLUo5+9xw8Iv76YE6LQFN9YNBlKREcCG76w==",
+ "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/runtime": "^1.11.1"
+ },
+ "engines": {
+ "node": ">=20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
"node_modules/@img/sharp-libvips-darwin-arm64": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz",
@@ -1581,6 +1652,51 @@
"url": "https://opencollective.com/libvips"
}
},
+ "node_modules/@img/sharp-webcontainers-wasm32": {
+ "version": "0.35.3",
+ "resolved": "https://registry.npmjs.org/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.3.tgz",
+ "integrity": "sha512-2rnq7bX3NzeR2T4YWgz8qiG4h3TSdMe+vN1iQXpJleSJ3SM5zQ8Fy2SyyXAWlbxpEZ2Y+Z4u1BePgJEYbSy80Q==",
+ "cpu": [
+ "wasm32"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "dependencies": {
+ "@img/sharp-wasm32": "0.35.3"
+ },
+ "engines": {
+ "node": ">=20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-webcontainers-wasm32/node_modules/@emnapi/runtime": {
+ "version": "1.11.3",
+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz",
+ "integrity": "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@img/sharp-webcontainers-wasm32/node_modules/@img/sharp-wasm32": {
+ "version": "0.35.3",
+ "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.3.tgz",
+ "integrity": "sha512-cZ0XkcYGpHZkqW6iCkqTcmUC0CD9DhD5d/qeZlZkfRBn6GnHniZXLUo5+9xw8Iv76YE6LQFN9YNBlKREcCG76w==",
+ "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/runtime": "^1.11.1"
+ },
+ "engines": {
+ "node": ">=20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
"node_modules/@img/sharp-win32-arm64": {
"version": "0.34.5",
"resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz",
@@ -1645,7 +1761,7 @@
"version": "0.3.13",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
"integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
- "dev": true,
+ "devOptional": true,
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.0",
@@ -1667,7 +1783,7 @@
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
- "dev": true,
+ "devOptional": true,
"license": "MIT",
"engines": {
"node": ">=6.0.0"
@@ -1677,7 +1793,7 @@
"version": "0.3.11",
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz",
"integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==",
- "dev": true,
+ "devOptional": true,
"license": "MIT",
"peer": true,
"dependencies": {
@@ -1689,20 +1805,162 @@
"version": "1.5.5",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
"integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
- "dev": true,
+ "devOptional": true,
"license": "MIT"
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.31",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
"integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
- "dev": true,
+ "devOptional": true,
"license": "MIT",
"dependencies": {
"@jridgewell/resolve-uri": "^3.1.0",
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
+ "node_modules/@mdx-js/loader": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/@mdx-js/loader/-/loader-3.1.1.tgz",
+ "integrity": "sha512-0TTacJyZ9mDmY+VefuthVshaNIyCGZHJG2fMnGaDttCt8HmjUF7SizlHJpaCDoGnN635nK1wpzfpx/Xx5S4WnQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@mdx-js/mdx": "^3.0.0",
+ "source-map": "^0.7.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ },
+ "peerDependencies": {
+ "webpack": ">=5"
+ },
+ "peerDependenciesMeta": {
+ "webpack": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@mdx-js/loader/node_modules/source-map": {
+ "version": "0.7.6",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz",
+ "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">= 12"
+ }
+ },
+ "node_modules/@mdx-js/mdx": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.1.1.tgz",
+ "integrity": "sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "@types/estree-jsx": "^1.0.0",
+ "@types/hast": "^3.0.0",
+ "@types/mdx": "^2.0.0",
+ "acorn": "^8.0.0",
+ "collapse-white-space": "^2.0.0",
+ "devlop": "^1.0.0",
+ "estree-util-is-identifier-name": "^3.0.0",
+ "estree-util-scope": "^1.0.0",
+ "estree-walker": "^3.0.0",
+ "hast-util-to-jsx-runtime": "^2.0.0",
+ "markdown-extensions": "^2.0.0",
+ "recma-build-jsx": "^1.0.0",
+ "recma-jsx": "^1.0.0",
+ "recma-stringify": "^1.0.0",
+ "rehype-recma": "^1.0.0",
+ "remark-mdx": "^3.0.0",
+ "remark-parse": "^11.0.0",
+ "remark-rehype": "^11.0.0",
+ "source-map": "^0.7.0",
+ "unified": "^11.0.0",
+ "unist-util-position-from-estree": "^2.0.0",
+ "unist-util-stringify-position": "^4.0.0",
+ "unist-util-visit": "^5.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/@mdx-js/mdx/node_modules/source-map": {
+ "version": "0.7.6",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz",
+ "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">= 12"
+ }
+ },
+ "node_modules/@mdx-js/react": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.1.1.tgz",
+ "integrity": "sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdx": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16",
+ "react": ">=16"
+ }
+ },
+ "node_modules/@mdx-js/rollup": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/@mdx-js/rollup/-/rollup-3.1.1.tgz",
+ "integrity": "sha512-v8satFmBB+DqDzYohnm1u2JOvxx6Hl3pUvqzJvfs2Zk/ngZ1aRUhsWpXvwPkNeGN9c2NCm/38H29ZqXQUjf8dw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@mdx-js/mdx": "^3.0.0",
+ "@rollup/pluginutils": "^5.0.0",
+ "source-map": "^0.7.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ },
+ "peerDependencies": {
+ "rollup": ">=2"
+ }
+ },
+ "node_modules/@mdx-js/rollup/node_modules/source-map": {
+ "version": "0.7.6",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz",
+ "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">= 12"
+ }
+ },
+ "node_modules/@napi-rs/lzma-linux-x64-gnu": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/@napi-rs/lzma-linux-x64-gnu/-/lzma-linux-x64-gnu-1.5.1.tgz",
+ "integrity": "sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": "^22.20 || ^24.12 || >=25"
+ }
+ },
"node_modules/@napi-rs/wasm-runtime": {
"version": "0.2.12",
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz",
@@ -1717,25 +1975,56 @@
}
},
"node_modules/@next/env": {
- "version": "16.2.6",
- "resolved": "https://registry.npmjs.org/@next/env/-/env-16.2.6.tgz",
- "integrity": "sha512-gd8HoHN4ufj73WmR3JmVolrpJR47ILK6LouP5xElPglaVxir6e1a7VzvTvDWkOoPXT9rkkTzyCxBu4yeZfZwcw==",
+ "version": "16.3.0",
+ "resolved": "https://registry.npmjs.org/@next/env/-/env-16.3.0.tgz",
+ "integrity": "sha512-o9r1S0BNiNreHP9Vs+Qnqd9kviDkJh8xIACY7UFZSmiGbbQRzPBBosvHzAU4TULHOIuOj/18RSsyz2qrREmIFw==",
"license": "MIT"
},
"node_modules/@next/eslint-plugin-next": {
- "version": "16.2.6",
- "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-16.2.6.tgz",
- "integrity": "sha512-Z8l6o4JWKUl755x4R+wogD86KPeU+Ckw4K+SYG4kHeOJtRenDeK+OSbGcqZpDtbwn9DsJVdir2UxmwXuinUbUw==",
+ "version": "16.3.0",
+ "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-16.3.0.tgz",
+ "integrity": "sha512-OqgJ8PN0d04KcPhDX/PTY5tJUJZxlbrt7O7FBsm4XE0XW2JDrKnDXsc9uo9WUimJGPoo2j+JRGhyXApC//mvbw==",
"dev": true,
"license": "MIT",
"dependencies": {
+ "@eslint-community/eslint-utils": "4.9.1",
"fast-glob": "3.3.1"
}
},
+ "node_modules/@next/mdx": {
+ "version": "16.3.0",
+ "resolved": "https://registry.npmjs.org/@next/mdx/-/mdx-16.3.0.tgz",
+ "integrity": "sha512-Vpfuf928ACvx4AOdDXWx/cj13Ak6xlvMn3QCkjvfQMmLnQWCesQTeY01CPDbIyZvjY+NOwP7bvbvJ2ghkj/3GA==",
+ "license": "MIT",
+ "dependencies": {
+ "source-map": "^0.7.0"
+ },
+ "peerDependencies": {
+ "@mdx-js/loader": ">=0.15.0",
+ "@mdx-js/react": ">=0.15.0"
+ },
+ "peerDependenciesMeta": {
+ "@mdx-js/loader": {
+ "optional": true
+ },
+ "@mdx-js/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@next/mdx/node_modules/source-map": {
+ "version": "0.7.6",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz",
+ "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">= 12"
+ }
+ },
"node_modules/@next/swc-darwin-arm64": {
- "version": "16.2.6",
- "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.2.6.tgz",
- "integrity": "sha512-ZJGkkcNfYgrrMkqOdZ7zoLa1TOy0qpcMfk/z4Mh/FKUz40gVO+HNQWqmLxf67Z5WB64DRp0dhEbyHfel+6sJUg==",
+ "version": "16.3.0",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.3.0.tgz",
+ "integrity": "sha512-55hpqq18bEVAlxedlTt3tFqZmKg2nUXT1kn1G/BGEy0R13h3LwtwHPVzzjG6P4LLeOHE32PFDQUVaJEWvBEZBw==",
"cpu": [
"arm64"
],
@@ -1749,9 +2038,9 @@
}
},
"node_modules/@next/swc-darwin-x64": {
- "version": "16.2.6",
- "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.2.6.tgz",
- "integrity": "sha512-v/YLBHIY132Ced3puBJ7YJKw1lqsCrgcNo2aRJlCEyQrrCeRJlvGlnmxhPxNQI3KE3N1DN5r9TPNPvka3nq5RQ==",
+ "version": "16.3.0",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.3.0.tgz",
+ "integrity": "sha512-SOi96kSaF5T+0wW4koiM1bWzSPwjzTesC1p3df+FjdOi5LIQkBK/blxh7HdoKnNuI4PURF1OO7TZqtfnbWDSgw==",
"cpu": [
"x64"
],
@@ -1765,9 +2054,9 @@
}
},
"node_modules/@next/swc-linux-arm64-gnu": {
- "version": "16.2.6",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.2.6.tgz",
- "integrity": "sha512-RPOvqlYBbcQjkz9VQQDZ2T2bARIjXZV1KFlt+V2Mr6SW/e4I9fcKsaA0hdyf2FHoTlsV2xnBd5Y912rP/1Ce6w==",
+ "version": "16.3.0",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.3.0.tgz",
+ "integrity": "sha512-P0gZAoPMF4dyTRzhmkV4PrqVzSOB6t4mC1oI3c4dqijJ+OVEVx5clIXAKR4/uQpsqw2KKM/0D5tVumcR2r5blg==",
"cpu": [
"arm64"
],
@@ -1781,9 +2070,9 @@
}
},
"node_modules/@next/swc-linux-arm64-musl": {
- "version": "16.2.6",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.2.6.tgz",
- "integrity": "sha512-URUTu1+dMkxJsPFgm+OeEvq9wf5sujw0EvgYy80TDGHTSLTnIHeqb0Eu8A3sC95IRgjejQL+kC4mw+4yPxiAXA==",
+ "version": "16.3.0",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.3.0.tgz",
+ "integrity": "sha512-tXXGKJw0m37O0eKJARVTX/TheKPhz0QFVtVVZXmOig+9YKLQOSP6hvf2pxv5DO7CLEJyTHx3Pg043CDQkv1G4Q==",
"cpu": [
"arm64"
],
@@ -1797,9 +2086,9 @@
}
},
"node_modules/@next/swc-linux-x64-gnu": {
- "version": "16.2.6",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.2.6.tgz",
- "integrity": "sha512-DOj182mPV8G3UkrayLoREM5YEYI+Dk5wv7Ox9xl1fFibAELEsFD0lDPfHIeILlutMMfdyhlzYPELG3peuKaurw==",
+ "version": "16.3.0",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.3.0.tgz",
+ "integrity": "sha512-pjGxK5EY7yWml78ALejFkWmgHsU7wbFQrISiugpH6FbUJhgEvw3xFZ/EBAtLl7QtL0WdQKiG9eWJ3mOKGTukHw==",
"cpu": [
"x64"
],
@@ -1813,9 +2102,9 @@
}
},
"node_modules/@next/swc-linux-x64-musl": {
- "version": "16.2.6",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.2.6.tgz",
- "integrity": "sha512-HKQ5SP/V/ub73UvF7n/zeJlxk2kLmtL7Wzrg4WfmkjmNos5onJ2tKu7yZOPdL18A6Svfn3max29ym+ry7NkK4g==",
+ "version": "16.3.0",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.3.0.tgz",
+ "integrity": "sha512-sjo++Xx+lomlPs3HRsHWhVDyGG6ms1kGW5EtHLERdII8AyG1i+f6aq68xHREO6AEMlhjTNEWBSmfJfqm9orf7g==",
"cpu": [
"x64"
],
@@ -1829,9 +2118,9 @@
}
},
"node_modules/@next/swc-win32-arm64-msvc": {
- "version": "16.2.6",
- "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.2.6.tgz",
- "integrity": "sha512-LZXpTlPyS5v7HhSmnvsLGP3iIYgYOBnc8r8ArlT55sGHV89bR2HlDdBjWQ+PY6SJMmk8TuVGFuxalnP3k/0Dwg==",
+ "version": "16.3.0",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.3.0.tgz",
+ "integrity": "sha512-C5JSgiO54wURdaxdEUIXqkz04uMqC9UmPX1gtDrV/5Tf1UowdWYI8uA5hfFbPolTlp0q4KZ60xlHePNibf0VIw==",
"cpu": [
"arm64"
],
@@ -1845,9 +2134,9 @@
}
},
"node_modules/@next/swc-win32-x64-msvc": {
- "version": "16.2.6",
- "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.2.6.tgz",
- "integrity": "sha512-F0+4i0h9J6C4eE3EAPWsoCk7UW/dbzOjyzxY0qnDUOYFu6FFmdZ6l97/XdV3/Nz3VYyO7UWjyEJUXkGqcoXfMA==",
+ "version": "16.3.0",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.3.0.tgz",
+ "integrity": "sha512-fDOggsweNb5SSw0ZKVk6U+gxSyGFFlIBY/LBc1r8GUj4u/6t6oArL+Pmkg0MBnsgR+KkdsURilVH4F3GXUGepA==",
"cpu": [
"x64"
],
@@ -1909,9 +2198,9 @@
}
},
"node_modules/@oxc-project/types": {
- "version": "0.130.0",
- "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.130.0.tgz",
- "integrity": "sha512-ibD2usx9JRu7f5pu2tMKMI4cpA4NgXJQoYRP4pQ7Pxmn1l6k/53qWtQWZayhYy3X4QZkt90Ot+mJEaeXouio6Q==",
+ "version": "0.143.0",
+ "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.143.0.tgz",
+ "integrity": "sha512-u6JZdLBTLotrNC9Vd6vPssINdzcCzleKAH6EJKImQb7GtYvX5keN2dxkoK44stCc4tffE6QQRtZTXVSzsLUlWA==",
"dev": true,
"license": "MIT",
"funding": {
@@ -1971,9 +2260,9 @@
}
},
"node_modules/@rolldown/binding-android-arm64": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.1.tgz",
- "integrity": "sha512-fJI3I0r3C3Oj/zdBCpaCmBRZYf07xpaq4yCfDDoSFm+beWNzbIl26puW8RraUdugoJw/95zerNOn6jasAhzSmg==",
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.3.tgz",
+ "integrity": "sha512-zrJtHDcaZJ1Fp7xf4hNl+7seH9Cn/N5TwLYkhgXREtBwAd/jaqW3uqeHxpDugJLVICWg4eW44kOQEGJ1r6jCGw==",
"cpu": [
"arm64"
],
@@ -1988,9 +2277,9 @@
}
},
"node_modules/@rolldown/binding-darwin-arm64": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.1.tgz",
- "integrity": "sha512-cKnAhWEsV7TPcA/5EAteDp6KcJZBQ2G+BqE7zayMMi7kMvwRsbv7WT9aOnn0WNl4SKEIf43vjS31iUPu80nzXg==",
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.3.tgz",
+ "integrity": "sha512-ieIiibVCp0tX7TLu2cafoNPv8wJyYi01ekXpbf8q2j7F4rGAhhXb/eQh7ge9DRBY78GwmRQtvjZDux7EDbA8kA==",
"cpu": [
"arm64"
],
@@ -2005,9 +2294,9 @@
}
},
"node_modules/@rolldown/binding-darwin-x64": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.1.tgz",
- "integrity": "sha512-YKrVwQjIRBPo+5G/u03wGjbdy4q7pyzCe93DK9VJ7zkVmeg8LJ7GbgsiHWdR4xSoe4CAXRD7Bcjgbtr64bkXNg==",
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.3.tgz",
+ "integrity": "sha512-Zh9tCon19eDXJoihx0rqKhMUlMYqzwj3aPsSuHmI4RWZh62dWUL+DJN4C5YQya5TcQBJU/Fe8+rY0jhXTQITqA==",
"cpu": [
"x64"
],
@@ -2022,9 +2311,9 @@
}
},
"node_modules/@rolldown/binding-freebsd-x64": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.1.tgz",
- "integrity": "sha512-z/oBsREo46SsFqBwYtFe0kpJeBijAT48O/WXLI4suiCLBkr03RTtTJMCzSdDd2znlh8VJizL09XVkQgk8IZonw==",
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.3.tgz",
+ "integrity": "sha512-nGbJWewA1wrXXZiQhjAT5rhibGfns5ZNkDVqxsO6zJ3f3YvpoDNNmGMSbbhLuXKjNScaBJVOAboztAWVespQMg==",
"cpu": [
"x64"
],
@@ -2039,9 +2328,9 @@
}
},
"node_modules/@rolldown/binding-linux-arm-gnueabihf": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.1.tgz",
- "integrity": "sha512-ik8q7GM11zxvYxFc2PeDcT6TBvhCQMaUxfph/M5l9sKuTs/Sjg3L+Byw0F7w0ZVLBZmx30P+gG0ECzzN+MFcmQ==",
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.3.tgz",
+ "integrity": "sha512-QNniJr5Kml0kDEB98jiDOJjXNroxIIi0IXIbdYzY26Xt1pVbeP62+KnoIZLwirOymX/0jDk/2gI/bNUv7A7OIw==",
"cpu": [
"arm"
],
@@ -2056,9 +2345,9 @@
}
},
"node_modules/@rolldown/binding-linux-arm64-gnu": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.1.tgz",
- "integrity": "sha512-QoSx2EkyrrdZ6kcyE8stqZ62t0Yra8Fs5ia9lOxJrh6TMQJK7gQKmscdTHf7pOXKREKrVwOtJcQG3qVSfc866A==",
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.3.tgz",
+ "integrity": "sha512-TkqEAcmmvH3I/q4114NB4RVt6241Dao48pF45uLcFGrwAaIn0iITgTAKP/dLjbN0R4buJjGb91+UHSoFmpgIWw==",
"cpu": [
"arm64"
],
@@ -2073,9 +2362,9 @@
}
},
"node_modules/@rolldown/binding-linux-arm64-musl": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.1.tgz",
- "integrity": "sha512-uwNwFpwKeNiZawfAWBgg0VIztPTV3ihhh1vV334h9ivnNLorxnQMU6Fz8wG1Zb4Qh9LC1/MkcyT3YlDXG3Rsgg==",
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.3.tgz",
+ "integrity": "sha512-NHqjnxpsndf4MPymxteFAWHHfkTL8HjWh1KB7z23ofZ6QO2euONuxDXjat69dKZRALnGypg8k8SsK8vZJoXv1Q==",
"cpu": [
"arm64"
],
@@ -2090,9 +2379,9 @@
}
},
"node_modules/@rolldown/binding-linux-ppc64-gnu": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.1.tgz",
- "integrity": "sha512-zY1bul7OWr7DFBiJ++wofXvnr8B45ce3QsQUhKrIhXsygAh7bTkwyeM1bi1a2g5C/yC/N8TZyGDEoMfm/l9mpg==",
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.3.tgz",
+ "integrity": "sha512-6tbrbwfz5GB9DQ4Jwo6hy9v+vR31xZlvzZ6n5Xut6Hhx5PvrA9q/HsK8KMaYQp063iqZGXwNvZtYNLD7EM/x0w==",
"cpu": [
"ppc64"
],
@@ -2107,9 +2396,9 @@
}
},
"node_modules/@rolldown/binding-linux-s390x-gnu": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.1.tgz",
- "integrity": "sha512-0frlsT/f4Ft6I7SMESTKnF3cZsdicQn1dCMkF/jT9wDLE+gGoiQfv1nmT9e+s7s/fekvvy6tZM2jHvI2tkbJDQ==",
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.3.tgz",
+ "integrity": "sha512-oyuXxXmoZHjXC917IAPFAAv4wWAa0cM9afk8nx1+9/jNNOX1uPf8yDA6p7G0RypOfw/X0PQt5IfoquY1um+zSg==",
"cpu": [
"s390x"
],
@@ -2124,9 +2413,9 @@
}
},
"node_modules/@rolldown/binding-linux-x64-gnu": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.1.tgz",
- "integrity": "sha512-XABVmGp9Tg0WspTVvwduTc4fpqy6JnAUrSQe6OuyqD/03nI7r0O9OWUkMIwFrjKAIqolvqoA4ZrJppgwE0Gxmw==",
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.3.tgz",
+ "integrity": "sha512-TytMwF2KVGqP2tgd0I1OY0PAv78dZRAYcF5ssDzjM34SUXCED3uXvSd5+lHoC0bTD6eEdFz7LdQNCO1y0oVk9w==",
"cpu": [
"x64"
],
@@ -2141,9 +2430,9 @@
}
},
"node_modules/@rolldown/binding-linux-x64-musl": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.1.tgz",
- "integrity": "sha512-bV4fzswuzVcKD90o/VM6QqKxnxlDq0g2BISDLNVmxrnhpv1DDbyPhCIjYfvzYLV+MvkKKnQt2Q6AO86SEBULUQ==",
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.3.tgz",
+ "integrity": "sha512-/E9m3qstrJFVPoULV25mVQblSNExY2+kBsYe4sy0Tn0yOOgJ8wZbZt3KnRbF/XeU2Gl1STKUQnDNTqhIE5MD4A==",
"cpu": [
"x64"
],
@@ -2158,9 +2447,9 @@
}
},
"node_modules/@rolldown/binding-openharmony-arm64": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.1.tgz",
- "integrity": "sha512-/Mh0Zhq3OP7fVs0kcQHZP6lZEthMGTaSf8UBQYSFEZDWGXXlEC+nJ6EqenaK2t4LBXMe3A+K/G2BVXXdtOr4PQ==",
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.3.tgz",
+ "integrity": "sha512-Kr0OcsoQI816i6HOl3vFHpd1K0eZyh76zgfj4c1nTyaTsd5r2Mj1lwM4R90y/qaCfmTn9eHy0SKwi98eitRxug==",
"cpu": [
"arm64"
],
@@ -2174,48 +2463,10 @@
"node": "^20.19.0 || >=22.12.0"
}
},
- "node_modules/@rolldown/binding-wasm32-wasi": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.1.tgz",
- "integrity": "sha512-+1xc9X45l8ufsBAm6Gjvx2qDRIY9lTVt0cgWNcJ+1gdhXvkbxePA60yRTwSTuXL09CMhyJmjpV7E3NoyxbqFQQ==",
- "cpu": [
- "wasm32"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@emnapi/core": "1.10.0",
- "@emnapi/runtime": "1.10.0",
- "@napi-rs/wasm-runtime": "^1.1.4"
- },
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz",
- "integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==",
- "dev": true,
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@tybys/wasm-util": "^0.10.1"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Brooooooklyn"
- },
- "peerDependencies": {
- "@emnapi/core": "^1.7.1",
- "@emnapi/runtime": "^1.7.1"
- }
- },
"node_modules/@rolldown/binding-win32-arm64-msvc": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.1.tgz",
- "integrity": "sha512-1D+UqZdfnuR+Jy1GgMJwi85bD40H21uNmOPRWQhw4oRSuolZ/B5rixZ45DK2KXOTCvmVCecauWgEhbw8bI7tOw==",
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.3.tgz",
+ "integrity": "sha512-hOtMwTqnME+/gJcH/PCZ0wn0zPUjiWOgkHpxbSJpfGKMezHltx1S7/k1SitzVa7Ww2cqrDDaFbZEhcJZO8o+Jw==",
"cpu": [
"arm64"
],
@@ -2230,9 +2481,9 @@
}
},
"node_modules/@rolldown/binding-win32-x64-msvc": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.1.tgz",
- "integrity": "sha512-INAycaWuhlOK3wk4mRHGsdgwYWmd9cChdPdE9bwWmy6rn9VqVNYNFGhOdXrofXUxwHIncSiPNb8tNm8knDVIeQ==",
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.3.tgz",
+ "integrity": "sha512-ekcqMMkI2PlhYnfzQnB/cEdYUVVJViWvoUyLrbzgDoi3Snfc1mVBwdnc306ufA5ejy8JSPjT2RlW1nQSjW7efg==",
"cpu": [
"x64"
],
@@ -2253,103 +2504,68 @@
"dev": true,
"license": "MIT"
},
- "node_modules/@rtsao/scc": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz",
- "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@shuding/opentype.js": {
- "version": "1.4.0-beta.0",
- "resolved": "https://registry.npmjs.org/@shuding/opentype.js/-/opentype.js-1.4.0-beta.0.tgz",
- "integrity": "sha512-3NgmNyH3l/Hv6EvsWJbsvpcpUba6R8IREQ83nH83cyakCw7uM1arZKNfHwv1Wz6jgqrF/j4x5ELvR6PnK9nTcA==",
+ "node_modules/@rollup/pluginutils": {
+ "version": "5.4.0",
+ "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.4.0.tgz",
+ "integrity": "sha512-MfPp06CjRLfXQ3wY0R8vJDYBy/MvVcc9OulEfR0B8Iv9ko+GCNaRZ+EpJYFl27LhKsZK0o420sYCRHCjfCgeUg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "fflate": "^0.7.3",
- "string.prototype.codepointat": "^0.2.1"
- },
- "bin": {
- "ot": "bin/ot"
+ "@types/estree": "^1.0.0",
+ "estree-walker": "^2.0.2",
+ "picomatch": "^4.0.2"
},
"engines": {
- "node": ">= 8.0.0"
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
+ },
+ "peerDependenciesMeta": {
+ "rollup": {
+ "optional": true
+ }
}
},
- "node_modules/@sindresorhus/is": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-7.2.0.tgz",
- "integrity": "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw==",
+ "node_modules/@rollup/pluginutils/node_modules/estree-walker": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
+ "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@rollup/pluginutils/node_modules/picomatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz",
+ "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">=18"
+ "node": ">=12"
},
"funding": {
- "url": "https://github.com/sindresorhus/is?sponsor=1"
+ "url": "https://github.com/sponsors/jonschlinkert"
}
},
- "node_modules/@speed-highlight/core": {
- "version": "1.2.15",
- "resolved": "https://registry.npmjs.org/@speed-highlight/core/-/core-1.2.15.tgz",
- "integrity": "sha512-BMq1K3DsElxDWawkX6eLg9+CKJrTVGCBAWVuHXVUV2u0s2711qiChLSId6ikYPfxhdYocLNt3wWwSvDiTvFabw==",
- "dev": true,
- "license": "CC0-1.0"
- },
- "node_modules/@swc/helpers": {
- "version": "0.5.15",
- "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz",
- "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==",
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.8.0"
- }
- },
- "node_modules/@tailwindcss/node": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.2.1.tgz",
- "integrity": "sha512-jlx6sLk4EOwO6hHe1oCGm1Q4AN/s0rSrTTPBGPM0/RQ6Uylwq17FuU8IeJJKEjtc6K6O07zsvP+gDO6MMWo7pg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jridgewell/remapping": "^2.3.5",
- "enhanced-resolve": "^5.19.0",
- "jiti": "^2.6.1",
- "lightningcss": "1.31.1",
- "magic-string": "^0.30.21",
- "source-map-js": "^1.2.1",
- "tailwindcss": "4.2.1"
- }
- },
- "node_modules/@tailwindcss/oxide": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.2.1.tgz",
- "integrity": "sha512-yv9jeEFWnjKCI6/T3Oq50yQEOqmpmpfzG1hcZsAOaXFQPfzWprWrlHSdGPEF3WQTi8zu8ohC9Mh9J470nT5pUw==",
+ "node_modules/@rollup/rollup-android-arm-eabi": {
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.4.tgz",
+ "integrity": "sha512-RrPokAb7dmbxFoeO3TloqHyOjgye8RkBhSqmp4aJMIex4c9r46ZstPnleDQOq1t46VOVjwIuwNogIqbodV1Vvg==",
+ "cpu": [
+ "arm"
+ ],
"dev": true,
"license": "MIT",
- "engines": {
- "node": ">= 20"
- },
- "optionalDependencies": {
- "@tailwindcss/oxide-android-arm64": "4.2.1",
- "@tailwindcss/oxide-darwin-arm64": "4.2.1",
- "@tailwindcss/oxide-darwin-x64": "4.2.1",
- "@tailwindcss/oxide-freebsd-x64": "4.2.1",
- "@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.1",
- "@tailwindcss/oxide-linux-arm64-gnu": "4.2.1",
- "@tailwindcss/oxide-linux-arm64-musl": "4.2.1",
- "@tailwindcss/oxide-linux-x64-gnu": "4.2.1",
- "@tailwindcss/oxide-linux-x64-musl": "4.2.1",
- "@tailwindcss/oxide-wasm32-wasi": "4.2.1",
- "@tailwindcss/oxide-win32-arm64-msvc": "4.2.1",
- "@tailwindcss/oxide-win32-x64-msvc": "4.2.1"
- }
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "peer": true
},
- "node_modules/@tailwindcss/oxide-android-arm64": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.2.1.tgz",
- "integrity": "sha512-eZ7G1Zm5EC8OOKaesIKuw77jw++QJ2lL9N+dDpdQiAB/c/B2wDh0QPFHbkBVrXnwNugvrbJFk1gK2SsVjwWReg==",
+ "node_modules/@rollup/rollup-android-arm64": {
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.4.tgz",
+ "integrity": "sha512-JKuJc+pnpks2pjy7L/N3v/cAkZxYlnmuZoD840ldbMI5KDbC4iO9NKwPKYdjYFCMAIIlBzYSFHxIJVYzRo2/8A==",
"cpu": [
"arm64"
],
@@ -2359,14 +2575,12 @@
"os": [
"android"
],
- "engines": {
- "node": ">= 20"
- }
+ "peer": true
},
- "node_modules/@tailwindcss/oxide-darwin-arm64": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.2.1.tgz",
- "integrity": "sha512-q/LHkOstoJ7pI1J0q6djesLzRvQSIfEto148ppAd+BVQK0JYjQIFSK3JgYZJa+Yzi0DDa52ZsQx2rqytBnf8Hw==",
+ "node_modules/@rollup/rollup-darwin-arm64": {
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.4.tgz",
+ "integrity": "sha512-krw5uS2STmvJ02x0uTXHbqQNuz+9eZ1iw+qXk9dmW2gvV4jV7O2hEoOnuhFrpOPiel1mBFtqbxYZZtC46hXLOw==",
"cpu": [
"arm64"
],
@@ -2376,14 +2590,12 @@
"os": [
"darwin"
],
- "engines": {
- "node": ">= 20"
- }
+ "peer": true
},
- "node_modules/@tailwindcss/oxide-darwin-x64": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.2.1.tgz",
- "integrity": "sha512-/f/ozlaXGY6QLbpvd/kFTro2l18f7dHKpB+ieXz+Cijl4Mt9AI2rTrpq7V+t04nK+j9XBQHnSMdeQRhbGyt6fw==",
+ "node_modules/@rollup/rollup-darwin-x64": {
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.4.tgz",
+ "integrity": "sha512-wsTxtgApb4PrOsNJIm0FZ1h3WvCC+k9uxLJ4ad75hgoS4NiRes2SoJFlDAyMwiUY8IssDqGcHbXuN0sx1tfF1A==",
"cpu": [
"x64"
],
@@ -2393,14 +2605,27 @@
"os": [
"darwin"
],
- "engines": {
- "node": ">= 20"
- }
+ "peer": true
},
- "node_modules/@tailwindcss/oxide-freebsd-x64": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.2.1.tgz",
- "integrity": "sha512-5e/AkgYJT/cpbkys/OU2Ei2jdETCLlifwm7ogMC7/hksI2fC3iiq6OcXwjibcIjPung0kRtR3TxEITkqgn0TcA==",
+ "node_modules/@rollup/rollup-freebsd-arm64": {
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.4.tgz",
+ "integrity": "sha512-GUOnQlyZe3yAXhWOtOMsn5Qkrv5E5mZXa0thbARWi5Ei2szlVXJFQhddZ4HbAzh8q92w5twp+CQvs/eFanz9YQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "peer": true
+ },
+ "node_modules/@rollup/rollup-freebsd-x64": {
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.4.tgz",
+ "integrity": "sha512-/Y7f3QuxjzPKsjA/rfEDa3+0vXqyjmJ50Ln8dPpCmWkKTrUoWHG1cWhTqaAMLob2m2nESWuC7yGrREz019Ztqg==",
"cpu": [
"x64"
],
@@ -2410,14 +2635,12 @@
"os": [
"freebsd"
],
- "engines": {
- "node": ">= 20"
- }
+ "peer": true
},
- "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.2.1.tgz",
- "integrity": "sha512-Uny1EcVTTmerCKt/1ZuKTkb0x8ZaiuYucg2/kImO5A5Y/kBz41/+j0gxUZl+hTF3xkWpDmHX+TaWhOtba2Fyuw==",
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.4.tgz",
+ "integrity": "sha512-81wiiX3v7aqy+T+bT61TJ78yJjRquqFFTTbAPt08imfQQzkPIW8t6aJbkTagtCCrXMNc9D66+geqlK7ydLPNqA==",
"cpu": [
"arm"
],
@@ -2427,16 +2650,14 @@
"os": [
"linux"
],
- "engines": {
- "node": ">= 20"
- }
+ "peer": true
},
- "node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.2.1.tgz",
- "integrity": "sha512-CTrwomI+c7n6aSSQlsPL0roRiNMDQ/YzMD9EjcR+H4f0I1SQ8QqIuPnsVp7QgMkC1Qi8rtkekLkOFjo7OlEFRQ==",
+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.4.tgz",
+ "integrity": "sha512-9kmDIvNZqdoHOBZgNtpTBeLWYO/LVipM3H/j62P8848/l/VPEQL6N3uxU9pvP1oZAsXyC2MEnFP3ovRjo7WYNQ==",
"cpu": [
- "arm64"
+ "arm"
],
"dev": true,
"license": "MIT",
@@ -2444,14 +2665,12 @@
"os": [
"linux"
],
- "engines": {
- "node": ">= 20"
- }
+ "peer": true
},
- "node_modules/@tailwindcss/oxide-linux-arm64-musl": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.2.1.tgz",
- "integrity": "sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ==",
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.4.tgz",
+ "integrity": "sha512-CcnXHWnXg69g+DX5VWL3FHts3qMRN2uVEHX+BZvGLdd07/gXkn3ePjYtO1LDJvxkGKVHMclKBRa1QUTH+6toYQ==",
"cpu": [
"arm64"
],
@@ -2461,16 +2680,14 @@
"os": [
"linux"
],
- "engines": {
- "node": ">= 20"
- }
+ "peer": true
},
- "node_modules/@tailwindcss/oxide-linux-x64-gnu": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.2.1.tgz",
- "integrity": "sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g==",
+ "node_modules/@rollup/rollup-linux-arm64-musl": {
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.4.tgz",
+ "integrity": "sha512-iFOibiHnTRuhrWLlRsOQFdZJJIa7S8OwkneJr4ocALP16u5yk6lWLINFwhHaEqBFMsKDUZofLkGos7+CPzGB3g==",
"cpu": [
- "x64"
+ "arm64"
],
"dev": true,
"license": "MIT",
@@ -2478,16 +2695,14 @@
"os": [
"linux"
],
- "engines": {
- "node": ">= 20"
- }
+ "peer": true
},
- "node_modules/@tailwindcss/oxide-linux-x64-musl": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.2.1.tgz",
- "integrity": "sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g==",
+ "node_modules/@rollup/rollup-linux-loong64-gnu": {
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.4.tgz",
+ "integrity": "sha512-XnWYMI7euHlb5a871xPja+Gm7DRCFU+FGRrtS2sMq9N8FvqtpagUy6gD4YOemC5MRk9xbh8+jYMEJbigFQwsgA==",
"cpu": [
- "x64"
+ "loong64"
],
"dev": true,
"license": "MIT",
@@ -2495,125 +2710,132 @@
"os": [
"linux"
],
- "engines": {
- "node": ">= 20"
- }
+ "peer": true
},
- "node_modules/@tailwindcss/oxide-wasm32-wasi": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.2.1.tgz",
- "integrity": "sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q==",
- "bundleDependencies": [
- "@napi-rs/wasm-runtime",
- "@emnapi/core",
- "@emnapi/runtime",
- "@tybys/wasm-util",
- "@emnapi/wasi-threads",
- "tslib"
- ],
+ "node_modules/@rollup/rollup-linux-loong64-musl": {
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.4.tgz",
+ "integrity": "sha512-qGDAlO0U8xedCcsdRm9oaoQY8DAx/QT7uIxJWhCdx0ceIWX783UC9QSYkdpzAe29wNiVfp24+bZdQmn49o45SQ==",
"cpu": [
- "wasm32"
+ "loong64"
],
"dev": true,
"license": "MIT",
"optional": true,
- "dependencies": {
- "@emnapi/core": "^1.8.1",
- "@emnapi/runtime": "^1.8.1",
- "@emnapi/wasi-threads": "^1.1.0",
- "@napi-rs/wasm-runtime": "^1.1.1",
- "@tybys/wasm-util": "^0.10.1",
- "tslib": "^2.8.1"
- },
- "engines": {
- "node": ">=14.0.0"
- }
+ "os": [
+ "linux"
+ ],
+ "peer": true
},
- "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": {
- "version": "1.8.1",
+ "node_modules/@rollup/rollup-linux-ppc64-gnu": {
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.4.tgz",
+ "integrity": "sha512-ru4H6ezD7ysA5EiEK6qkkaEb4modH8CTej6kUy/gQi20u3kB3G7Zn8snXXkeJSCOFKG/rbPPtM/+9Wgas1961w==",
+ "cpu": [
+ "ppc64"
+ ],
"dev": true,
- "inBundle": true,
"license": "MIT",
"optional": true,
- "dependencies": {
- "@emnapi/wasi-threads": "1.1.0",
- "tslib": "^2.4.0"
- }
+ "os": [
+ "linux"
+ ],
+ "peer": true
},
- "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": {
- "version": "1.8.1",
+ "node_modules/@rollup/rollup-linux-ppc64-musl": {
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.4.tgz",
+ "integrity": "sha512-2W4MO5WQVJnbJaZdvDb9rhBDuFU1nKIepPFpJUBsTh2k1YY2g+ODViaWuyOAjQ5cOP7NvrvLzt3wvHOoiAvc7w==",
+ "cpu": [
+ "ppc64"
+ ],
"dev": true,
- "inBundle": true,
"license": "MIT",
"optional": true,
- "dependencies": {
- "tslib": "^2.4.0"
- }
+ "os": [
+ "linux"
+ ],
+ "peer": true
},
- "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": {
- "version": "1.1.0",
+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.4.tgz",
+ "integrity": "sha512-+fxjfuoAmVMCYV5QyjoIpu0cp5DOiOTeqYFk1AVaxGr+/ravWLX89XfQmptsoWcaVy/TGf2hexzbUOrCQIL1CQ==",
+ "cpu": [
+ "riscv64"
+ ],
"dev": true,
- "inBundle": true,
"license": "MIT",
"optional": true,
- "dependencies": {
- "tslib": "^2.4.0"
- }
+ "os": [
+ "linux"
+ ],
+ "peer": true
},
- "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": {
- "version": "1.1.1",
+ "node_modules/@rollup/rollup-linux-riscv64-musl": {
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.4.tgz",
+ "integrity": "sha512-jTn8JfHGL4djjFxPuM06LmNUJDsst2jeVlsd9OmIH6zc5sC9K6rIuO4YajXatLUpBmBKl6b35ro1QZocLi+tcA==",
+ "cpu": [
+ "riscv64"
+ ],
"dev": true,
- "inBundle": true,
"license": "MIT",
"optional": true,
- "dependencies": {
- "@emnapi/core": "^1.7.1",
- "@emnapi/runtime": "^1.7.1",
- "@tybys/wasm-util": "^0.10.1"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Brooooooklyn"
- }
+ "os": [
+ "linux"
+ ],
+ "peer": true
},
- "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": {
- "version": "0.10.1",
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.4.tgz",
+ "integrity": "sha512-oCJCJL4pXsoDcP2QZ+JVlPTIRc6266zsIaeJJsWImmF7HO0W8nb6HuSgZlMWxJwaPf8ehbSw8yo0EUw925hKsA==",
+ "cpu": [
+ "s390x"
+ ],
"dev": true,
- "inBundle": true,
"license": "MIT",
"optional": true,
- "dependencies": {
- "tslib": "^2.4.0"
- }
+ "os": [
+ "linux"
+ ],
+ "peer": true
},
- "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": {
- "version": "2.8.1",
+ "node_modules/@rollup/rollup-linux-x64-gnu": {
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.4.tgz",
+ "integrity": "sha512-W69hukhZ3KKNRCaMIEzKvcFye42hh0FE1+YoYaf5+Ikacuftoco6yO/xouz0hc5d5W/s3yBro5jRiuEE/Q5vUw==",
+ "cpu": [
+ "x64"
+ ],
"dev": true,
- "inBundle": true,
- "license": "0BSD",
- "optional": true
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true
},
- "node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.2.1.tgz",
- "integrity": "sha512-YlUEHRHBGnCMh4Nj4GnqQyBtsshUPdiNroZj8VPkvTZSoHsilRCwXcVKnG9kyi0ZFAS/3u+qKHBdDc81SADTRA==",
+ "node_modules/@rollup/rollup-linux-x64-musl": {
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.4.tgz",
+ "integrity": "sha512-qiXbGG2jkjXhzXpsFZSR2Xpb8DN/UaxYsbb/STbuR/6fpaDgRmmaq1B/LmtF2wQFOFOSsK2jdE0RZ3a0zHn4QA==",
"cpu": [
- "arm64"
+ "x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
- "win32"
+ "linux"
],
- "engines": {
- "node": ">= 20"
- }
+ "peer": true
},
- "node_modules/@tailwindcss/oxide-win32-x64-msvc": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.2.1.tgz",
- "integrity": "sha512-rbO34G5sMWWyrN/idLeVxAZgAKWrn5LiR3/I90Q9MkA67s6T1oB0xtTe+0heoBvHSpbU9Mk7i6uwJnpo4u21XQ==",
+ "node_modules/@rollup/rollup-openbsd-x64": {
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.4.tgz",
+ "integrity": "sha512-nWeM//hxv8mIo6jD7Hu4o48DVmV9pbV6gsKaWU+4NFyqHoPKwrkRiZGLKUhOBk8qNmDmpwFtPKg80Bo/Tn4xiQ==",
"cpu": [
"x64"
],
@@ -2621,455 +2843,429 @@
"license": "MIT",
"optional": true,
"os": [
- "win32"
+ "openbsd"
],
- "engines": {
- "node": ">= 20"
- }
+ "peer": true
},
- "node_modules/@tailwindcss/postcss": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.2.1.tgz",
- "integrity": "sha512-OEwGIBnXnj7zJeonOh6ZG9woofIjGrd2BORfvE5p9USYKDCZoQmfqLcfNiRWoJlRWLdNPn2IgVZuWAOM4iTYMw==",
+ "node_modules/@rollup/rollup-openharmony-arm64": {
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.4.tgz",
+ "integrity": "sha512-s62SQ/vgsRSvMwDkOEfTqfgASF0f26ZNaQuTA6Aok5lrikf89yI2W0gFHvZb2Jpgc6N8JnOKZgCK2iciO3CsxQ==",
+ "cpu": [
+ "arm64"
+ ],
"dev": true,
"license": "MIT",
- "dependencies": {
- "@alloc/quick-lru": "^5.2.0",
- "@tailwindcss/node": "4.2.1",
- "@tailwindcss/oxide": "4.2.1",
- "postcss": "^8.5.6",
- "tailwindcss": "4.2.1"
- }
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "peer": true
},
- "node_modules/@tybys/wasm-util": {
- "version": "0.10.2",
- "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.2.tgz",
- "integrity": "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==",
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.4.tgz",
+ "integrity": "sha512-J6wGf8TVGbXJq+HH+ttTvrcfNKPbuZecV6KT1B8I18BC5IURUh5kl4Yl5OEP5eFIUoI5BWxCsyYMhFsDx8kekw==",
+ "cpu": [
+ "arm64"
+ ],
"dev": true,
"license": "MIT",
"optional": true,
- "dependencies": {
- "tslib": "^2.4.0"
- }
+ "os": [
+ "win32"
+ ],
+ "peer": true
},
- "node_modules/@types/eslint": {
- "version": "9.6.1",
- "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz",
- "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==",
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.4.tgz",
+ "integrity": "sha512-zmfrQd/0wu6oJs8Vq8KwY/YtsKSsLtKe/HwAP4Wqy8LhWjeT55fHRAkOhYQ12wI3ayS4Tt12d5CDRD7N96SAYQ==",
+ "cpu": [
+ "ia32"
+ ],
"dev": true,
"license": "MIT",
- "peer": true,
- "dependencies": {
- "@types/estree": "*",
- "@types/json-schema": "*"
- }
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "peer": true
},
- "node_modules/@types/eslint-scope": {
- "version": "3.7.7",
- "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz",
- "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==",
+ "node_modules/@rollup/rollup-win32-x64-gnu": {
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.4.tgz",
+ "integrity": "sha512-qPzHqdj9rfUD+w79dtE07zi/kFwKyCJqplp5K5ygeLTp7jLpAoc16OAH39HSmRC9UpozaecsleI8uAdEj6v2yw==",
+ "cpu": [
+ "x64"
+ ],
"dev": true,
"license": "MIT",
- "peer": true,
- "dependencies": {
- "@types/eslint": "*",
- "@types/estree": "*"
- }
- },
- "node_modules/@types/estree": {
- "version": "1.0.9",
- "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz",
- "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==",
- "dev": true,
- "license": "MIT"
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "peer": true
},
- "node_modules/@types/json-schema": {
- "version": "7.0.15",
- "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
- "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.4.tgz",
+ "integrity": "sha512-zD6NdeWEByGE9QF9vCrlJ5YQB4oq9q91kPZS37Jwj5hOkvR1lTBSpsKhKDw4IJtbQ35LsTS1HD9DZYGKIshU1Q==",
+ "cpu": [
+ "x64"
+ ],
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "peer": true
},
- "node_modules/@types/json5": {
- "version": "0.0.29",
- "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
- "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
+ "node_modules/@rtsao/scc": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz",
+ "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==",
"dev": true,
"license": "MIT"
},
- "node_modules/@types/node": {
- "version": "22.19.19",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.19.tgz",
- "integrity": "sha512-dyh/xO2Fh5bYrfWaaqGrRQQGkNdmYw6AmaAUvYeUMNTWQtvb796ikLdmTchRmOlOiIJ1TDXfWgVx1QkUlQ6Hew==",
+ "node_modules/@shuding/opentype.js": {
+ "version": "1.4.0-beta.0",
+ "resolved": "https://registry.npmjs.org/@shuding/opentype.js/-/opentype.js-1.4.0-beta.0.tgz",
+ "integrity": "sha512-3NgmNyH3l/Hv6EvsWJbsvpcpUba6R8IREQ83nH83cyakCw7uM1arZKNfHwv1Wz6jgqrF/j4x5ELvR6PnK9nTcA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "undici-types": "~6.21.0"
+ "fflate": "^0.7.3",
+ "string.prototype.codepointat": "^0.2.1"
+ },
+ "bin": {
+ "ot": "bin/ot"
+ },
+ "engines": {
+ "node": ">= 8.0.0"
}
},
- "node_modules/@types/react": {
- "version": "19.2.14",
- "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz",
- "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==",
+ "node_modules/@sindresorhus/is": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-7.2.0.tgz",
+ "integrity": "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw==",
"dev": true,
"license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/is?sponsor=1"
+ }
+ },
+ "node_modules/@speed-highlight/core": {
+ "version": "1.2.15",
+ "resolved": "https://registry.npmjs.org/@speed-highlight/core/-/core-1.2.15.tgz",
+ "integrity": "sha512-BMq1K3DsElxDWawkX6eLg9+CKJrTVGCBAWVuHXVUV2u0s2711qiChLSId6ikYPfxhdYocLNt3wWwSvDiTvFabw==",
+ "dev": true,
+ "license": "CC0-1.0"
+ },
+ "node_modules/@swc/helpers": {
+ "version": "0.5.15",
+ "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz",
+ "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==",
+ "license": "Apache-2.0",
"dependencies": {
- "csstype": "^3.2.2"
+ "tslib": "^2.8.0"
}
},
- "node_modules/@types/react-dom": {
- "version": "19.2.3",
- "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz",
- "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
+ "node_modules/@tailwindcss/node": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.2.1.tgz",
+ "integrity": "sha512-jlx6sLk4EOwO6hHe1oCGm1Q4AN/s0rSrTTPBGPM0/RQ6Uylwq17FuU8IeJJKEjtc6K6O07zsvP+gDO6MMWo7pg==",
"dev": true,
"license": "MIT",
- "peerDependencies": {
- "@types/react": "^19.2.0"
+ "dependencies": {
+ "@jridgewell/remapping": "^2.3.5",
+ "enhanced-resolve": "^5.19.0",
+ "jiti": "^2.6.1",
+ "lightningcss": "1.31.1",
+ "magic-string": "^0.30.21",
+ "source-map-js": "^1.2.1",
+ "tailwindcss": "4.2.1"
}
},
- "node_modules/@typescript-eslint/eslint-plugin": {
- "version": "8.59.3",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.59.3.tgz",
- "integrity": "sha512-PwFvSKsXGShKGW6n5bZOhGHEcCZXM8HofLK9fNsEwZXzFRjoY+XT1Vsf1zgyXdwTr0ZYz1/2tkZ0DBTT9jZjhw==",
+ "node_modules/@tailwindcss/oxide": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.2.1.tgz",
+ "integrity": "sha512-yv9jeEFWnjKCI6/T3Oq50yQEOqmpmpfzG1hcZsAOaXFQPfzWprWrlHSdGPEF3WQTi8zu8ohC9Mh9J470nT5pUw==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "@eslint-community/regexpp": "^4.12.2",
- "@typescript-eslint/scope-manager": "8.59.3",
- "@typescript-eslint/type-utils": "8.59.3",
- "@typescript-eslint/utils": "8.59.3",
- "@typescript-eslint/visitor-keys": "8.59.3",
- "ignore": "^7.0.5",
- "natural-compare": "^1.4.0",
- "ts-api-utils": "^2.5.0"
- },
"engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
+ "node": ">= 20"
},
- "peerDependencies": {
- "@typescript-eslint/parser": "^8.59.3",
- "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
- "typescript": ">=4.8.4 <6.1.0"
+ "optionalDependencies": {
+ "@tailwindcss/oxide-android-arm64": "4.2.1",
+ "@tailwindcss/oxide-darwin-arm64": "4.2.1",
+ "@tailwindcss/oxide-darwin-x64": "4.2.1",
+ "@tailwindcss/oxide-freebsd-x64": "4.2.1",
+ "@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.1",
+ "@tailwindcss/oxide-linux-arm64-gnu": "4.2.1",
+ "@tailwindcss/oxide-linux-arm64-musl": "4.2.1",
+ "@tailwindcss/oxide-linux-x64-gnu": "4.2.1",
+ "@tailwindcss/oxide-linux-x64-musl": "4.2.1",
+ "@tailwindcss/oxide-wasm32-wasi": "4.2.1",
+ "@tailwindcss/oxide-win32-arm64-msvc": "4.2.1",
+ "@tailwindcss/oxide-win32-x64-msvc": "4.2.1"
}
},
- "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
- "version": "7.0.5",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
- "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
+ "node_modules/@tailwindcss/oxide-android-arm64": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.2.1.tgz",
+ "integrity": "sha512-eZ7G1Zm5EC8OOKaesIKuw77jw++QJ2lL9N+dDpdQiAB/c/B2wDh0QPFHbkBVrXnwNugvrbJFk1gK2SsVjwWReg==",
+ "cpu": [
+ "arm64"
+ ],
"dev": true,
"license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
"engines": {
- "node": ">= 4"
+ "node": ">= 20"
}
},
- "node_modules/@typescript-eslint/parser": {
- "version": "8.59.3",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.59.3.tgz",
- "integrity": "sha512-HPwA+hVkfcriajbNvTmZv4VRauibay+cWArYUYq7u7W7PmGShMxbPxLvrwDme55a6d5alG3nrYfhyJ/G28XlLg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@typescript-eslint/scope-manager": "8.59.3",
- "@typescript-eslint/types": "8.59.3",
- "@typescript-eslint/typescript-estree": "8.59.3",
- "@typescript-eslint/visitor-keys": "8.59.3",
- "debug": "^4.4.3"
- },
+ "node_modules/@tailwindcss/oxide-darwin-arm64": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.2.1.tgz",
+ "integrity": "sha512-q/LHkOstoJ7pI1J0q6djesLzRvQSIfEto148ppAd+BVQK0JYjQIFSK3JgYZJa+Yzi0DDa52ZsQx2rqytBnf8Hw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
"engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
- "typescript": ">=4.8.4 <6.1.0"
+ "node": ">= 20"
}
},
- "node_modules/@typescript-eslint/project-service": {
- "version": "8.59.3",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.59.3.tgz",
- "integrity": "sha512-ECiUWa/KYRGDFUqTNehaRgzDshnJfkTABJxVemHk4ko22gcr0ukloKjWvyQ64g8YCV/UI47kN1dbmjf/GaQYng==",
+ "node_modules/@tailwindcss/oxide-darwin-x64": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.2.1.tgz",
+ "integrity": "sha512-/f/ozlaXGY6QLbpvd/kFTro2l18f7dHKpB+ieXz+Cijl4Mt9AI2rTrpq7V+t04nK+j9XBQHnSMdeQRhbGyt6fw==",
+ "cpu": [
+ "x64"
+ ],
"dev": true,
"license": "MIT",
- "dependencies": {
- "@typescript-eslint/tsconfig-utils": "^8.59.3",
- "@typescript-eslint/types": "^8.59.3",
- "debug": "^4.4.3"
- },
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
"engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "typescript": ">=4.8.4 <6.1.0"
+ "node": ">= 20"
}
},
- "node_modules/@typescript-eslint/scope-manager": {
- "version": "8.59.3",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.59.3.tgz",
- "integrity": "sha512-t2LvZnoEfzKtnPjgeEu41xw5gxq9mQVfYy4OoZ4Vlt0sk3JwxmhCca/AR7DwOiHrjWgjAj6as4AhRLKSDfvZIA==",
+ "node_modules/@tailwindcss/oxide-freebsd-x64": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.2.1.tgz",
+ "integrity": "sha512-5e/AkgYJT/cpbkys/OU2Ei2jdETCLlifwm7ogMC7/hksI2fC3iiq6OcXwjibcIjPung0kRtR3TxEITkqgn0TcA==",
+ "cpu": [
+ "x64"
+ ],
"dev": true,
"license": "MIT",
- "dependencies": {
- "@typescript-eslint/types": "8.59.3",
- "@typescript-eslint/visitor-keys": "8.59.3"
- },
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
"engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
+ "node": ">= 20"
}
},
- "node_modules/@typescript-eslint/tsconfig-utils": {
- "version": "8.59.3",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.59.3.tgz",
- "integrity": "sha512-PcIJHjmaREXLgIAIzLnSY9VucEzz8FKXsRgFa1DmdGCK/5tJpW03TKJF01Q6VZd1lLdz2sIKPWaDUZN9dp//dw==",
+ "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.2.1.tgz",
+ "integrity": "sha512-Uny1EcVTTmerCKt/1ZuKTkb0x8ZaiuYucg2/kImO5A5Y/kBz41/+j0gxUZl+hTF3xkWpDmHX+TaWhOtba2Fyuw==",
+ "cpu": [
+ "arm"
+ ],
"dev": true,
"license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
"engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "typescript": ">=4.8.4 <6.1.0"
+ "node": ">= 20"
}
},
- "node_modules/@typescript-eslint/type-utils": {
- "version": "8.59.3",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.59.3.tgz",
- "integrity": "sha512-g71d8QD8UaiHGvrJwyIS1hCX5r63w6Jll+4VEYhEAHXTDIqX1JgxhTAbEHtKntL9kuc4jRo7/GWw5xfCepSccQ==",
+ "node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.2.1.tgz",
+ "integrity": "sha512-CTrwomI+c7n6aSSQlsPL0roRiNMDQ/YzMD9EjcR+H4f0I1SQ8QqIuPnsVp7QgMkC1Qi8rtkekLkOFjo7OlEFRQ==",
+ "cpu": [
+ "arm64"
+ ],
"dev": true,
"license": "MIT",
- "dependencies": {
- "@typescript-eslint/types": "8.59.3",
- "@typescript-eslint/typescript-estree": "8.59.3",
- "@typescript-eslint/utils": "8.59.3",
- "debug": "^4.4.3",
- "ts-api-utils": "^2.5.0"
- },
+ "optional": true,
+ "os": [
+ "linux"
+ ],
"engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
- "typescript": ">=4.8.4 <6.1.0"
+ "node": ">= 20"
}
},
- "node_modules/@typescript-eslint/types": {
- "version": "8.59.3",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.59.3.tgz",
- "integrity": "sha512-ePFoH0g4ludssdRFqqDxQePCxU4WQyRa9+XVwjm7yLn0FKhMeoetC+qBEEI1Eyb1pGSDveTIT09Bvw2WhlGayg==",
+ "node_modules/@tailwindcss/oxide-linux-arm64-musl": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.2.1.tgz",
+ "integrity": "sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ==",
+ "cpu": [
+ "arm64"
+ ],
"dev": true,
"license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
"engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
+ "node": ">= 20"
}
},
- "node_modules/@typescript-eslint/typescript-estree": {
- "version": "8.59.3",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.59.3.tgz",
- "integrity": "sha512-CbRjVRAf7Lr9Kr8RopKcbY45p2VfmmHrm0ygOCYFi7oU8q19m0Fs/6iHS7kNOmwpp+ob07ZVcAqlxUod9lYdmg==",
+ "node_modules/@tailwindcss/oxide-linux-x64-gnu": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.2.1.tgz",
+ "integrity": "sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g==",
+ "cpu": [
+ "x64"
+ ],
"dev": true,
"license": "MIT",
- "dependencies": {
- "@typescript-eslint/project-service": "8.59.3",
- "@typescript-eslint/tsconfig-utils": "8.59.3",
- "@typescript-eslint/types": "8.59.3",
- "@typescript-eslint/visitor-keys": "8.59.3",
- "debug": "^4.4.3",
- "minimatch": "^10.2.2",
- "semver": "^7.7.3",
- "tinyglobby": "^0.2.15",
- "ts-api-utils": "^2.5.0"
- },
+ "optional": true,
+ "os": [
+ "linux"
+ ],
"engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "typescript": ">=4.8.4 <6.1.0"
+ "node": ">= 20"
}
},
- "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
- "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
+ "node_modules/@tailwindcss/oxide-linux-x64-musl": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.2.1.tgz",
+ "integrity": "sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g==",
+ "cpu": [
+ "x64"
+ ],
"dev": true,
"license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
"engines": {
- "node": "18 || 20 || >=22"
+ "node": ">= 20"
}
},
- "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
- "version": "5.0.6",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz",
- "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==",
+ "node_modules/@tailwindcss/oxide-wasm32-wasi": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.2.1.tgz",
+ "integrity": "sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q==",
+ "bundleDependencies": [
+ "@napi-rs/wasm-runtime",
+ "@emnapi/core",
+ "@emnapi/runtime",
+ "@tybys/wasm-util",
+ "@emnapi/wasi-threads",
+ "tslib"
+ ],
+ "cpu": [
+ "wasm32"
+ ],
"dev": true,
"license": "MIT",
+ "optional": true,
"dependencies": {
- "balanced-match": "^4.0.2"
+ "@emnapi/core": "^1.8.1",
+ "@emnapi/runtime": "^1.8.1",
+ "@emnapi/wasi-threads": "^1.1.0",
+ "@napi-rs/wasm-runtime": "^1.1.1",
+ "@tybys/wasm-util": "^0.10.1",
+ "tslib": "^2.8.1"
},
"engines": {
- "node": "18 || 20 || >=22"
+ "node": ">=14.0.0"
}
},
- "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
- "version": "10.2.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz",
- "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==",
+ "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": {
+ "version": "1.8.1",
"dev": true,
- "license": "BlueOak-1.0.0",
+ "inBundle": true,
+ "license": "MIT",
+ "optional": true,
"dependencies": {
- "brace-expansion": "^5.0.5"
- },
- "engines": {
- "node": "18 || 20 || >=22"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": {
- "version": "7.8.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.0.tgz",
- "integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
+ "@emnapi/wasi-threads": "1.1.0",
+ "tslib": "^2.4.0"
}
},
- "node_modules/@typescript-eslint/utils": {
- "version": "8.59.3",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.59.3.tgz",
- "integrity": "sha512-JAvT14goBzRzzzZyqq3P9BLArIxTtQURUtFgQ/V7FO+eU+Gg6ES+5ymOPP1wRxXcxAYeivCk4uS3jCKWI1K8Zg==",
+ "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": {
+ "version": "1.8.1",
"dev": true,
+ "inBundle": true,
"license": "MIT",
+ "optional": true,
"dependencies": {
- "@eslint-community/eslint-utils": "^4.9.1",
- "@typescript-eslint/scope-manager": "8.59.3",
- "@typescript-eslint/types": "8.59.3",
- "@typescript-eslint/typescript-estree": "8.59.3"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
- "typescript": ">=4.8.4 <6.1.0"
+ "tslib": "^2.4.0"
}
},
- "node_modules/@typescript-eslint/visitor-keys": {
- "version": "8.59.3",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.59.3.tgz",
- "integrity": "sha512-f1UQF7ggd42YiwI5wGrRaPsa+P0CINBlrkLPmGfpq/u/I/oVtecoEIfFR9ag/oa1sLOsRNZ6xehf6qMZhQGBDg==",
+ "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": {
+ "version": "1.1.0",
"dev": true,
+ "inBundle": true,
"license": "MIT",
+ "optional": true,
"dependencies": {
- "@typescript-eslint/types": "8.59.3",
- "eslint-visitor-keys": "^5.0.0"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz",
- "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": "^20.19.0 || ^22.13.0 || >=24"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
+ "tslib": "^2.4.0"
}
},
- "node_modules/@unpic/core": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/@unpic/core/-/core-1.0.3.tgz",
- "integrity": "sha512-aum9YNVUGso7MjGLD0Rp/08kywCGLqZ03/q6VQBFFakDBOXWEc8D4kPGcZ8v5wEnGRex3lE+++bOuucBp3KJ/w==",
+ "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": {
+ "version": "1.1.1",
"dev": true,
+ "inBundle": true,
"license": "MIT",
+ "optional": true,
"dependencies": {
- "unpic": "^4.2.2"
+ "@emnapi/core": "^1.7.1",
+ "@emnapi/runtime": "^1.7.1",
+ "@tybys/wasm-util": "^0.10.1"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/Brooooooklyn"
}
},
- "node_modules/@unpic/react": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/@unpic/react/-/react-1.0.2.tgz",
- "integrity": "sha512-5RmRfELwTF8w+4zjtQGqjpvX+RU2VLvis3xDCS1O2uWk0PZN2cvatL+3/KAR3mshAuRrkFGTX1XwyAezSXaoCA==",
+ "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": {
+ "version": "0.10.1",
"dev": true,
+ "inBundle": true,
"license": "MIT",
+ "optional": true,
"dependencies": {
- "@unpic/core": "^1.0.3"
- },
- "peerDependencies": {
- "next": "^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0",
- "react": "^17.0.0 || ^18.0.0 || ^19.0.0",
- "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
- },
- "peerDependenciesMeta": {
- "next": {
- "optional": true
- }
+ "tslib": "^2.4.0"
}
},
- "node_modules/@unrs/resolver-binding-android-arm-eabi": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz",
- "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==",
- "cpu": [
- "arm"
- ],
+ "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": {
+ "version": "2.8.1",
"dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ]
+ "inBundle": true,
+ "license": "0BSD",
+ "optional": true
},
- "node_modules/@unrs/resolver-binding-android-arm64": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz",
- "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==",
+ "node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.2.1.tgz",
+ "integrity": "sha512-YlUEHRHBGnCMh4Nj4GnqQyBtsshUPdiNroZj8VPkvTZSoHsilRCwXcVKnG9kyi0ZFAS/3u+qKHBdDc81SADTRA==",
"cpu": [
"arm64"
],
@@ -3077,27 +3273,16 @@
"license": "MIT",
"optional": true,
"os": [
- "android"
- ]
- },
- "node_modules/@unrs/resolver-binding-darwin-arm64": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz",
- "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==",
- "cpu": [
- "arm64"
+ "win32"
],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ]
+ "engines": {
+ "node": ">= 20"
+ }
},
- "node_modules/@unrs/resolver-binding-darwin-x64": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz",
- "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==",
+ "node_modules/@tailwindcss/oxide-win32-x64-msvc": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.2.1.tgz",
+ "integrity": "sha512-rbO34G5sMWWyrN/idLeVxAZgAKWrn5LiR3/I90Q9MkA67s6T1oB0xtTe+0heoBvHSpbU9Mk7i6uwJnpo4u21XQ==",
"cpu": [
"x64"
],
@@ -3105,960 +3290,3084 @@
"license": "MIT",
"optional": true,
"os": [
- "darwin"
- ]
- },
- "node_modules/@unrs/resolver-binding-freebsd-x64": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz",
- "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==",
- "cpu": [
- "x64"
+ "win32"
],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ]
+ "engines": {
+ "node": ">= 20"
+ }
},
- "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz",
- "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==",
- "cpu": [
- "arm"
- ],
+ "node_modules/@tailwindcss/postcss": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.2.1.tgz",
+ "integrity": "sha512-OEwGIBnXnj7zJeonOh6ZG9woofIjGrd2BORfvE5p9USYKDCZoQmfqLcfNiRWoJlRWLdNPn2IgVZuWAOM4iTYMw==",
"dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
+ "dependencies": {
+ "@alloc/quick-lru": "^5.2.0",
+ "@tailwindcss/node": "4.2.1",
+ "@tailwindcss/oxide": "4.2.1",
+ "postcss": "^8.5.6",
+ "tailwindcss": "4.2.1"
+ }
},
- "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz",
- "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==",
- "cpu": [
- "arm"
- ],
+ "node_modules/@tybys/wasm-util": {
+ "version": "0.10.2",
+ "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.2.tgz",
+ "integrity": "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==",
"dev": true,
"license": "MIT",
"optional": true,
- "os": [
- "linux"
- ]
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
},
- "node_modules/@unrs/resolver-binding-linux-arm64-gnu": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz",
- "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
+ "node_modules/@types/debug": {
+ "version": "4.1.13",
+ "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz",
+ "integrity": "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==",
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
+ "dependencies": {
+ "@types/ms": "*"
+ }
},
- "node_modules/@unrs/resolver-binding-linux-arm64-musl": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz",
- "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
+ "node_modules/@types/eslint": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz",
+ "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==",
+ "devOptional": true,
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
+ "peer": true,
+ "dependencies": {
+ "@types/estree": "*",
+ "@types/json-schema": "*"
+ }
},
- "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz",
- "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==",
- "cpu": [
- "ppc64"
- ],
- "dev": true,
+ "node_modules/@types/eslint-scope": {
+ "version": "3.7.7",
+ "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz",
+ "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==",
+ "devOptional": true,
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
+ "peer": true,
+ "dependencies": {
+ "@types/eslint": "*",
+ "@types/estree": "*"
+ }
},
- "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz",
- "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==",
- "cpu": [
- "riscv64"
- ],
- "dev": true,
+ "node_modules/@types/estree": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz",
+ "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==",
+ "license": "MIT"
+ },
+ "node_modules/@types/estree-jsx": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz",
+ "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==",
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
+ "dependencies": {
+ "@types/estree": "*"
+ }
},
- "node_modules/@unrs/resolver-binding-linux-riscv64-musl": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz",
- "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==",
- "cpu": [
- "riscv64"
- ],
- "dev": true,
+ "node_modules/@types/hast": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.5.tgz",
+ "integrity": "sha512-rp/ezSWaD1m44dPKICGhiskI13nVr7qTloFwDa/IYkhhf5nzwP+zIQcIJh3WIFSBOy/H1PzB40jPjMDksN4F+g==",
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
+ "dependencies": {
+ "@types/unist": "*"
+ }
},
- "node_modules/@unrs/resolver-binding-linux-s390x-gnu": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz",
- "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==",
- "cpu": [
- "s390x"
- ],
+ "node_modules/@types/json-schema": {
+ "version": "7.0.15",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/json5": {
+ "version": "0.0.29",
+ "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
+ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
"dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/mdast": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz",
+ "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==",
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
+ "dependencies": {
+ "@types/unist": "*"
+ }
},
- "node_modules/@unrs/resolver-binding-linux-x64-gnu": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz",
- "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==",
- "cpu": [
- "x64"
- ],
- "dev": true,
+ "node_modules/@types/mdx": {
+ "version": "2.0.14",
+ "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.14.tgz",
+ "integrity": "sha512-T48PeuJtvLosNTPVhfnIp3i/n3a4g4Bad7YCq5k64D4u7NwDrAotikQ+5+sjtUvBmxCMlbo3dVL+C2dP0rWHzg==",
+ "license": "MIT"
+ },
+ "node_modules/@types/ms": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz",
+ "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==",
+ "license": "MIT"
+ },
+ "node_modules/@types/node": {
+ "version": "22.19.19",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.19.tgz",
+ "integrity": "sha512-dyh/xO2Fh5bYrfWaaqGrRQQGkNdmYw6AmaAUvYeUMNTWQtvb796ikLdmTchRmOlOiIJ1TDXfWgVx1QkUlQ6Hew==",
+ "devOptional": true,
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
+ "dependencies": {
+ "undici-types": "~6.21.0"
+ }
},
- "node_modules/@unrs/resolver-binding-linux-x64-musl": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz",
- "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==",
- "cpu": [
- "x64"
- ],
+ "node_modules/@types/react": {
+ "version": "19.2.14",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz",
+ "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==",
+ "license": "MIT",
+ "dependencies": {
+ "csstype": "^3.2.2"
+ }
+ },
+ "node_modules/@types/react-dom": {
+ "version": "19.2.3",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz",
+ "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
"dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
+ "peerDependencies": {
+ "@types/react": "^19.2.0"
+ }
},
- "node_modules/@unrs/resolver-binding-wasm32-wasi": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz",
- "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==",
- "cpu": [
- "wasm32"
- ],
+ "node_modules/@types/unist": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
+ "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==",
+ "license": "MIT"
+ },
+ "node_modules/@typescript-eslint/eslint-plugin": {
+ "version": "8.59.3",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.59.3.tgz",
+ "integrity": "sha512-PwFvSKsXGShKGW6n5bZOhGHEcCZXM8HofLK9fNsEwZXzFRjoY+XT1Vsf1zgyXdwTr0ZYz1/2tkZ0DBTT9jZjhw==",
"dev": true,
"license": "MIT",
- "optional": true,
"dependencies": {
- "@napi-rs/wasm-runtime": "^0.2.11"
+ "@eslint-community/regexpp": "^4.12.2",
+ "@typescript-eslint/scope-manager": "8.59.3",
+ "@typescript-eslint/type-utils": "8.59.3",
+ "@typescript-eslint/utils": "8.59.3",
+ "@typescript-eslint/visitor-keys": "8.59.3",
+ "ignore": "^7.0.5",
+ "natural-compare": "^1.4.0",
+ "ts-api-utils": "^2.5.0"
},
"engines": {
- "node": ">=14.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/parser": "^8.59.3",
+ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
+ "typescript": ">=4.8.4 <6.1.0"
}
},
- "node_modules/@unrs/resolver-binding-win32-arm64-msvc": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz",
- "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==",
- "cpu": [
- "arm64"
- ],
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
+ "version": "7.0.5",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
+ "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
"dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
+ "engines": {
+ "node": ">= 4"
+ }
},
- "node_modules/@unrs/resolver-binding-win32-ia32-msvc": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz",
- "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==",
- "cpu": [
- "ia32"
- ],
+ "node_modules/@typescript-eslint/parser": {
+ "version": "8.59.3",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.59.3.tgz",
+ "integrity": "sha512-HPwA+hVkfcriajbNvTmZv4VRauibay+cWArYUYq7u7W7PmGShMxbPxLvrwDme55a6d5alG3nrYfhyJ/G28XlLg==",
"dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "8.59.3",
+ "@typescript-eslint/types": "8.59.3",
+ "@typescript-eslint/typescript-estree": "8.59.3",
+ "@typescript-eslint/visitor-keys": "8.59.3",
+ "debug": "^4.4.3"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
+ "typescript": ">=4.8.4 <6.1.0"
+ }
},
- "node_modules/@unrs/resolver-binding-win32-x64-msvc": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz",
- "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==",
- "cpu": [
- "x64"
- ],
+ "node_modules/@typescript-eslint/project-service": {
+ "version": "8.59.3",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.59.3.tgz",
+ "integrity": "sha512-ECiUWa/KYRGDFUqTNehaRgzDshnJfkTABJxVemHk4ko22gcr0ukloKjWvyQ64g8YCV/UI47kN1dbmjf/GaQYng==",
"dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
+ "dependencies": {
+ "@typescript-eslint/tsconfig-utils": "^8.59.3",
+ "@typescript-eslint/types": "^8.59.3",
+ "debug": "^4.4.3"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.1.0"
+ }
},
- "node_modules/@vercel/og": {
- "version": "0.8.6",
- "resolved": "https://registry.npmjs.org/@vercel/og/-/og-0.8.6.tgz",
- "integrity": "sha512-hBcWIOppZV14bi+eAmCZj8Elj8hVSUZJTpf1lgGBhVD85pervzQ1poM/qYfFUlPraYSZYP+ASg6To5BwYmUSGQ==",
+ "node_modules/@typescript-eslint/scope-manager": {
+ "version": "8.59.3",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.59.3.tgz",
+ "integrity": "sha512-t2LvZnoEfzKtnPjgeEu41xw5gxq9mQVfYy4OoZ4Vlt0sk3JwxmhCca/AR7DwOiHrjWgjAj6as4AhRLKSDfvZIA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.59.3",
+ "@typescript-eslint/visitor-keys": "8.59.3"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/tsconfig-utils": {
+ "version": "8.59.3",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.59.3.tgz",
+ "integrity": "sha512-PcIJHjmaREXLgIAIzLnSY9VucEzz8FKXsRgFa1DmdGCK/5tJpW03TKJF01Q6VZd1lLdz2sIKPWaDUZN9dp//dw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils": {
+ "version": "8.59.3",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.59.3.tgz",
+ "integrity": "sha512-g71d8QD8UaiHGvrJwyIS1hCX5r63w6Jll+4VEYhEAHXTDIqX1JgxhTAbEHtKntL9kuc4jRo7/GWw5xfCepSccQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.59.3",
+ "@typescript-eslint/typescript-estree": "8.59.3",
+ "@typescript-eslint/utils": "8.59.3",
+ "debug": "^4.4.3",
+ "ts-api-utils": "^2.5.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/@typescript-eslint/types": {
+ "version": "8.59.3",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.59.3.tgz",
+ "integrity": "sha512-ePFoH0g4ludssdRFqqDxQePCxU4WQyRa9+XVwjm7yLn0FKhMeoetC+qBEEI1Eyb1pGSDveTIT09Bvw2WhlGayg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree": {
+ "version": "8.59.3",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.59.3.tgz",
+ "integrity": "sha512-CbRjVRAf7Lr9Kr8RopKcbY45p2VfmmHrm0ygOCYFi7oU8q19m0Fs/6iHS7kNOmwpp+ob07ZVcAqlxUod9lYdmg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/project-service": "8.59.3",
+ "@typescript-eslint/tsconfig-utils": "8.59.3",
+ "@typescript-eslint/types": "8.59.3",
+ "@typescript-eslint/visitor-keys": "8.59.3",
+ "debug": "^4.4.3",
+ "minimatch": "^10.2.2",
+ "semver": "^7.7.3",
+ "tinyglobby": "^0.2.15",
+ "ts-api-utils": "^2.5.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
+ "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "18 || 20 || >=22"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
+ "version": "5.0.9",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz",
+ "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^4.0.2"
+ },
+ "engines": {
+ "node": "20 || >=22"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
+ "version": "10.2.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz",
+ "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "brace-expansion": "^5.0.5"
+ },
+ "engines": {
+ "node": "18 || 20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": {
+ "version": "7.8.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.0.tgz",
+ "integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@typescript-eslint/utils": {
+ "version": "8.59.3",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.59.3.tgz",
+ "integrity": "sha512-JAvT14goBzRzzzZyqq3P9BLArIxTtQURUtFgQ/V7FO+eU+Gg6ES+5ymOPP1wRxXcxAYeivCk4uS3jCKWI1K8Zg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.9.1",
+ "@typescript-eslint/scope-manager": "8.59.3",
+ "@typescript-eslint/types": "8.59.3",
+ "@typescript-eslint/typescript-estree": "8.59.3"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys": {
+ "version": "8.59.3",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.59.3.tgz",
+ "integrity": "sha512-f1UQF7ggd42YiwI5wGrRaPsa+P0CINBlrkLPmGfpq/u/I/oVtecoEIfFR9ag/oa1sLOsRNZ6xehf6qMZhQGBDg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.59.3",
+ "eslint-visitor-keys": "^5.0.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz",
+ "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^20.19.0 || ^22.13.0 || >=24"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@ungap/structured-clone": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.3.tgz",
+ "integrity": "sha512-60YRaenCQcVjYEKOcG824+DRGGIQ3VKErcBoAEDJZz5bKIs2ZG+X/H9Nk+Q6EVkwJk5QNApxbrc5QtBSwtrXAg==",
+ "license": "ISC"
+ },
+ "node_modules/@unpic/core": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@unpic/core/-/core-1.0.3.tgz",
+ "integrity": "sha512-aum9YNVUGso7MjGLD0Rp/08kywCGLqZ03/q6VQBFFakDBOXWEc8D4kPGcZ8v5wEnGRex3lE+++bOuucBp3KJ/w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "unpic": "^4.2.2"
+ }
+ },
+ "node_modules/@unpic/react": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@unpic/react/-/react-1.0.2.tgz",
+ "integrity": "sha512-5RmRfELwTF8w+4zjtQGqjpvX+RU2VLvis3xDCS1O2uWk0PZN2cvatL+3/KAR3mshAuRrkFGTX1XwyAezSXaoCA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@unpic/core": "^1.0.3"
+ },
+ "peerDependencies": {
+ "next": "^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0",
+ "react": "^17.0.0 || ^18.0.0 || ^19.0.0",
+ "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
+ },
+ "peerDependenciesMeta": {
+ "next": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@unrs/resolver-binding-android-arm-eabi": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz",
+ "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-android-arm64": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz",
+ "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-darwin-arm64": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz",
+ "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-darwin-x64": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz",
+ "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-freebsd-x64": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz",
+ "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz",
+ "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz",
+ "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-arm64-gnu": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz",
+ "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-arm64-musl": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz",
+ "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz",
+ "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz",
+ "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-riscv64-musl": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz",
+ "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-s390x-gnu": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz",
+ "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-x64-gnu": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz",
+ "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-x64-musl": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz",
+ "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-wasm32-wasi": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz",
+ "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==",
+ "cpu": [
+ "wasm32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@napi-rs/wasm-runtime": "^0.2.11"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@unrs/resolver-binding-win32-arm64-msvc": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz",
+ "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-win32-ia32-msvc": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz",
+ "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-win32-x64-msvc": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz",
+ "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@vercel/og": {
+ "version": "0.8.6",
+ "resolved": "https://registry.npmjs.org/@vercel/og/-/og-0.8.6.tgz",
+ "integrity": "sha512-hBcWIOppZV14bi+eAmCZj8Elj8hVSUZJTpf1lgGBhVD85pervzQ1poM/qYfFUlPraYSZYP+ASg6To5BwYmUSGQ==",
+ "dev": true,
+ "license": "MPL-2.0",
+ "dependencies": {
+ "@resvg/resvg-wasm": "2.4.0",
+ "satori": "0.16.0"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/@vitejs/plugin-react": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.0.2.tgz",
+ "integrity": "sha512-DlSMqo4WhThw4vB8Mpn0Woe9J+Jfq1geJ61AKW0QEgLzGMNwtIMdxbDUzLxcun8W7NbJO0e2Jg/Nxm3cCSVzzg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@rolldown/pluginutils": "^1.0.0"
+ },
+ "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
+ }
+ }
+ },
+ "node_modules/@vitejs/plugin-rsc": {
+ "version": "0.5.26",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-rsc/-/plugin-rsc-0.5.26.tgz",
+ "integrity": "sha512-T8W8ODEutblw9qXQB512LDPyv1tAbJRD/Gf0QEGsAoydl4nxEtIrghnhoI9oLY9R+7aw+cLk1ZEltxWHWf4aHw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@rolldown/pluginutils": "1.0.0-rc.18",
+ "es-module-lexer": "^2.1.0",
+ "estree-walker": "^3.0.3",
+ "magic-string": "^0.30.21",
+ "srvx": "^0.11.15",
+ "strip-literal": "^3.1.0",
+ "turbo-stream": "^3.2.0",
+ "vitefu": "^1.1.3"
+ },
+ "peerDependencies": {
+ "react": "*",
+ "react-dom": "*",
+ "react-server-dom-webpack": "*",
+ "vite": "*"
+ },
+ "peerDependenciesMeta": {
+ "react-server-dom-webpack": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@vitejs/plugin-rsc/node_modules/@rolldown/pluginutils": {
+ "version": "1.0.0-rc.18",
+ "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.18.tgz",
+ "integrity": "sha512-CUY5Mnhe64xQBGZEEXQ5WyZwsc1JU3vAZLIxtrsBt3LO6UOb+C8GunVKqe9sT8NeWb4lqSaoJtp2xo6GxT1MNw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@webassemblyjs/ast": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz",
+ "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==",
+ "devOptional": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@webassemblyjs/helper-numbers": "1.13.2",
+ "@webassemblyjs/helper-wasm-bytecode": "1.13.2"
+ }
+ },
+ "node_modules/@webassemblyjs/floating-point-hex-parser": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz",
+ "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==",
+ "devOptional": true,
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@webassemblyjs/helper-api-error": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz",
+ "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==",
+ "devOptional": true,
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@webassemblyjs/helper-buffer": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz",
+ "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==",
+ "devOptional": true,
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@webassemblyjs/helper-numbers": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz",
+ "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==",
+ "devOptional": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@webassemblyjs/floating-point-hex-parser": "1.13.2",
+ "@webassemblyjs/helper-api-error": "1.13.2",
+ "@xtuc/long": "4.2.2"
+ }
+ },
+ "node_modules/@webassemblyjs/helper-wasm-bytecode": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz",
+ "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==",
+ "devOptional": true,
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@webassemblyjs/helper-wasm-section": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz",
+ "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==",
+ "devOptional": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@webassemblyjs/ast": "1.14.1",
+ "@webassemblyjs/helper-buffer": "1.14.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
+ "@webassemblyjs/wasm-gen": "1.14.1"
+ }
+ },
+ "node_modules/@webassemblyjs/ieee754": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz",
+ "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==",
+ "devOptional": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@xtuc/ieee754": "^1.2.0"
+ }
+ },
+ "node_modules/@webassemblyjs/leb128": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz",
+ "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==",
+ "devOptional": true,
+ "license": "Apache-2.0",
+ "peer": true,
+ "dependencies": {
+ "@xtuc/long": "4.2.2"
+ }
+ },
+ "node_modules/@webassemblyjs/utf8": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz",
+ "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==",
+ "devOptional": true,
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@webassemblyjs/wasm-edit": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz",
+ "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==",
+ "devOptional": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@webassemblyjs/ast": "1.14.1",
+ "@webassemblyjs/helper-buffer": "1.14.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
+ "@webassemblyjs/helper-wasm-section": "1.14.1",
+ "@webassemblyjs/wasm-gen": "1.14.1",
+ "@webassemblyjs/wasm-opt": "1.14.1",
+ "@webassemblyjs/wasm-parser": "1.14.1",
+ "@webassemblyjs/wast-printer": "1.14.1"
+ }
+ },
+ "node_modules/@webassemblyjs/wasm-gen": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz",
+ "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==",
+ "devOptional": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@webassemblyjs/ast": "1.14.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
+ "@webassemblyjs/ieee754": "1.13.2",
+ "@webassemblyjs/leb128": "1.13.2",
+ "@webassemblyjs/utf8": "1.13.2"
+ }
+ },
+ "node_modules/@webassemblyjs/wasm-opt": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz",
+ "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==",
+ "devOptional": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@webassemblyjs/ast": "1.14.1",
+ "@webassemblyjs/helper-buffer": "1.14.1",
+ "@webassemblyjs/wasm-gen": "1.14.1",
+ "@webassemblyjs/wasm-parser": "1.14.1"
+ }
+ },
+ "node_modules/@webassemblyjs/wasm-parser": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz",
+ "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==",
+ "devOptional": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@webassemblyjs/ast": "1.14.1",
+ "@webassemblyjs/helper-api-error": "1.13.2",
+ "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
+ "@webassemblyjs/ieee754": "1.13.2",
+ "@webassemblyjs/leb128": "1.13.2",
+ "@webassemblyjs/utf8": "1.13.2"
+ }
+ },
+ "node_modules/@webassemblyjs/wast-printer": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz",
+ "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==",
+ "devOptional": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@webassemblyjs/ast": "1.14.1",
+ "@xtuc/long": "4.2.2"
+ }
+ },
+ "node_modules/@xtuc/ieee754": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
+ "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==",
+ "devOptional": true,
+ "license": "BSD-3-Clause",
+ "peer": true
+ },
+ "node_modules/@xtuc/long": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
+ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
+ "devOptional": true,
+ "license": "Apache-2.0",
+ "peer": true
+ },
+ "node_modules/acorn": {
+ "version": "8.16.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz",
+ "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
+ "license": "MIT",
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-import-phases": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz",
+ "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==",
+ "devOptional": true,
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=10.13.0"
+ },
+ "peerDependencies": {
+ "acorn": "^8.14.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/acorn-loose": {
+ "version": "8.5.2",
+ "resolved": "https://registry.npmjs.org/acorn-loose/-/acorn-loose-8.5.2.tgz",
+ "integrity": "sha512-PPvV6g8UGMGgjrMu+n/f9E/tCSkNQ2Y97eFvuVdJfG11+xdIeDcLyNdC8SHcrHbRqkfwLASdplyR6B6sKM1U4A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "acorn": "^8.15.0"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.15.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz",
+ "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ajv-formats": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz",
+ "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
+ "devOptional": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "ajv": "^8.0.0"
+ },
+ "peerDependencies": {
+ "ajv": "^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "ajv": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/ajv-formats/node_modules/ajv": {
+ "version": "8.20.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
+ "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
+ "devOptional": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3",
+ "fast-uri": "^3.0.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ajv-formats/node_modules/json-schema-traverse": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+ "devOptional": true,
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true,
+ "license": "Python-2.0"
+ },
+ "node_modules/aria-query": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz",
+ "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/array-buffer-byte-length": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz",
+ "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "is-array-buffer": "^3.0.5"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array-includes": {
+ "version": "3.1.9",
+ "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz",
+ "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.24.0",
+ "es-object-atoms": "^1.1.1",
+ "get-intrinsic": "^1.3.0",
+ "is-string": "^1.1.1",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.findlast": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz",
+ "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.findlastindex": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz",
+ "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.9",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "es-shim-unscopables": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.flat": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz",
+ "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.5",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.flatmap": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz",
+ "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.5",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.tosorted": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz",
+ "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.3",
+ "es-errors": "^1.3.0",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/arraybuffer.prototype.slice": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz",
+ "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-buffer-byte-length": "^1.0.1",
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.5",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "is-array-buffer": "^3.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/ast-types-flow": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz",
+ "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/astring": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/astring/-/astring-1.9.0.tgz",
+ "integrity": "sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==",
+ "license": "MIT",
+ "bin": {
+ "astring": "bin/astring"
+ }
+ },
+ "node_modules/async-function": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz",
+ "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/available-typed-arrays": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
+ "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "possible-typed-array-names": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/axe-core": {
+ "version": "4.11.4",
+ "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.11.4.tgz",
+ "integrity": "sha512-KunSNx+TVpkAw/6ULfhnx+HWRecjqZGTOyquAoWHYLRSdK1tB5Ihce1ZW+UY3fj33bYAFWPu7W/GRSmmrCGuxA==",
+ "dev": true,
+ "license": "MPL-2.0",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/axobject-query": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
+ "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/bail": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz",
+ "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/base64-js": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz",
+ "integrity": "sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/baseline-browser-mapping": {
+ "version": "2.10.30",
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.30.tgz",
+ "integrity": "sha512-xjOFN16Ha1+Rz4nFYKqHU/LSB+gx/Vi3yQLX7r7sAW+Wa+8hhF2h4pvqTrTMc8+WcDBEunnUurr46Jvv0jk3Vg==",
+ "license": "Apache-2.0",
+ "bin": {
+ "baseline-browser-mapping": "dist/cli.cjs"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/blake3-wasm": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz",
+ "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.18",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz",
+ "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fill-range": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.28.2",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz",
+ "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==",
+ "devOptional": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "baseline-browser-mapping": "^2.10.12",
+ "caniuse-lite": "^1.0.30001782",
+ "electron-to-chromium": "^1.5.328",
+ "node-releases": "^2.0.36",
+ "update-browserslist-db": "^1.2.3"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/buffer-from": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+ "devOptional": true,
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/call-bind": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz",
+ "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "es-define-property": "^1.0.1",
+ "get-intrinsic": "^1.3.0",
+ "set-function-length": "^1.2.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/call-bind-apply-helpers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+ "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/call-bound": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
+ "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "get-intrinsic": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/camelize": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz",
+ "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001793",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001793.tgz",
+ "integrity": "sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "CC-BY-4.0"
+ },
+ "node_modules/ccount": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz",
+ "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/character-entities": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz",
+ "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/character-entities-html4": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz",
+ "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/character-entities-legacy": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz",
+ "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/character-reference-invalid": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz",
+ "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/chrome-trace-event": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz",
+ "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==",
+ "devOptional": true,
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=6.0"
+ }
+ },
+ "node_modules/client-only": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
+ "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==",
+ "license": "MIT"
+ },
+ "node_modules/collapse-white-space": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-2.1.0.tgz",
+ "integrity": "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/comma-separated-tokens": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz",
+ "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/commander": {
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+ "devOptional": true,
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/cookie": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz",
+ "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/css-background-parser": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/css-background-parser/-/css-background-parser-0.1.0.tgz",
+ "integrity": "sha512-2EZLisiZQ+7m4wwur/qiYJRniHX4K5Tc9w93MT3AS0WS1u5kaZ4FKXlOTBhOjc+CgEgPiGY+fX1yWD8UwpEqUA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/css-box-shadow": {
+ "version": "1.0.0-3",
+ "resolved": "https://registry.npmjs.org/css-box-shadow/-/css-box-shadow-1.0.0-3.tgz",
+ "integrity": "sha512-9jaqR6e7Ohds+aWwmhe6wILJ99xYQbfmK9QQB9CcMjDbTxPZjwEmUQpU91OG05Xgm8BahT5fW+svbsQGjS/zPg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/css-color-keywords": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz",
+ "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/css-gradient-parser": {
+ "version": "0.0.16",
+ "resolved": "https://registry.npmjs.org/css-gradient-parser/-/css-gradient-parser-0.0.16.tgz",
+ "integrity": "sha512-3O5QdqgFRUbXvK1x5INf1YkBz1UKSWqrd63vWsum8MNHDBYD5urm3QtxZbKU259OrEXNM26lP/MPY3d1IGkBgA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/css-to-react-native": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz",
+ "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "camelize": "^1.0.0",
+ "css-color-keywords": "^1.0.0",
+ "postcss-value-parser": "^4.0.2"
+ }
+ },
+ "node_modules/csstype": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
+ "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
+ "license": "MIT"
+ },
+ "node_modules/damerau-levenshtein": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
+ "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==",
+ "dev": true,
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/data-view-buffer": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz",
+ "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/data-view-byte-length": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz",
+ "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/inspect-js"
+ }
+ },
+ "node_modules/data-view-byte-offset": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz",
+ "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/decode-named-character-reference": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.3.0.tgz",
+ "integrity": "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==",
+ "license": "MIT",
+ "dependencies": {
+ "character-entities": "^2.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/define-data-property": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
+ "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/define-properties": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
+ "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-data-property": "^1.0.1",
+ "has-property-descriptors": "^1.0.0",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/dequal": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
+ "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/detect-libc": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
+ "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
+ "devOptional": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/devlop": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz",
+ "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==",
+ "license": "MIT",
+ "dependencies": {
+ "dequal": "^2.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/dunder-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
+ "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.5.358",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.358.tgz",
+ "integrity": "sha512-EO7tKm3QxRqTs1lSuPXzl6yRAwznehp0AH9OoMOIC+4mQzTFday8FJCO5KU6J/TFSQXEOahNq4vTKpz1jmCVOA==",
+ "devOptional": true,
+ "license": "ISC"
+ },
+ "node_modules/emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/emoji-regex-xs": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/emoji-regex-xs/-/emoji-regex-xs-2.0.1.tgz",
+ "integrity": "sha512-1QFuh8l7LqUcKe24LsPUNzjrzJQ7pgRwp1QMcZ5MX6mFplk2zQ08NVCM84++1cveaUUYtcCYHmeFEuNg16sU4g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/enhanced-resolve": {
+ "version": "5.21.3",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.3.tgz",
+ "integrity": "sha512-QyL119InA+XXEkNLNTPCXPugSvOfhwv0JOlGNzvxs0hZaiHLNvXSpudUWsOlsXGWJh8G6ckCScEkVHfX3kw/2Q==",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.2.4",
+ "tapable": "^2.3.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/error-stack-parser-es": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/error-stack-parser-es/-/error-stack-parser-es-1.0.5.tgz",
+ "integrity": "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
+ "node_modules/es-abstract": {
+ "version": "1.24.2",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz",
+ "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-buffer-byte-length": "^1.0.2",
+ "arraybuffer.prototype.slice": "^1.0.4",
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "data-view-buffer": "^1.0.2",
+ "data-view-byte-length": "^1.0.2",
+ "data-view-byte-offset": "^1.0.1",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "es-set-tostringtag": "^2.1.0",
+ "es-to-primitive": "^1.3.0",
+ "function.prototype.name": "^1.1.8",
+ "get-intrinsic": "^1.3.0",
+ "get-proto": "^1.0.1",
+ "get-symbol-description": "^1.1.0",
+ "globalthis": "^1.0.4",
+ "gopd": "^1.2.0",
+ "has-property-descriptors": "^1.0.2",
+ "has-proto": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "internal-slot": "^1.1.0",
+ "is-array-buffer": "^3.0.5",
+ "is-callable": "^1.2.7",
+ "is-data-view": "^1.0.2",
+ "is-negative-zero": "^2.0.3",
+ "is-regex": "^1.2.1",
+ "is-set": "^2.0.3",
+ "is-shared-array-buffer": "^1.0.4",
+ "is-string": "^1.1.1",
+ "is-typed-array": "^1.1.15",
+ "is-weakref": "^1.1.1",
+ "math-intrinsics": "^1.1.0",
+ "object-inspect": "^1.13.4",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.7",
+ "own-keys": "^1.0.1",
+ "regexp.prototype.flags": "^1.5.4",
+ "safe-array-concat": "^1.1.3",
+ "safe-push-apply": "^1.0.0",
+ "safe-regex-test": "^1.1.0",
+ "set-proto": "^1.0.0",
+ "stop-iteration-iterator": "^1.1.0",
+ "string.prototype.trim": "^1.2.10",
+ "string.prototype.trimend": "^1.0.9",
+ "string.prototype.trimstart": "^1.0.8",
+ "typed-array-buffer": "^1.0.3",
+ "typed-array-byte-length": "^1.0.3",
+ "typed-array-byte-offset": "^1.0.4",
+ "typed-array-length": "^1.0.7",
+ "unbox-primitive": "^1.1.0",
+ "which-typed-array": "^1.1.19"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/es-define-property": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
+ "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-iterator-helpers": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.3.2.tgz",
+ "integrity": "sha512-HVLACW1TppGYjJ8H6/jqH/pqOtKRw6wMlrB23xfExmFWxFquAIWCmwoLsOyN96K4a5KbmOf5At9ZUO3GZbetAw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.9",
+ "call-bound": "^1.0.4",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.24.2",
+ "es-errors": "^1.3.0",
+ "es-set-tostringtag": "^2.1.0",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.3.0",
+ "globalthis": "^1.0.4",
+ "gopd": "^1.2.0",
+ "has-property-descriptors": "^1.0.2",
+ "has-proto": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "internal-slot": "^1.1.0",
+ "iterator.prototype": "^1.1.5",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-module-lexer": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz",
+ "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/es-object-atoms": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
+ "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-set-tostringtag": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+ "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-shim-unscopables": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz",
+ "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==",
"dev": true,
- "license": "MPL-2.0",
+ "license": "MIT",
"dependencies": {
- "@resvg/resvg-wasm": "2.4.0",
- "satori": "0.16.0"
+ "hasown": "^2.0.2"
},
"engines": {
- "node": ">=16"
+ "node": ">= 0.4"
}
},
- "node_modules/@vitejs/plugin-react": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.0.2.tgz",
- "integrity": "sha512-DlSMqo4WhThw4vB8Mpn0Woe9J+Jfq1geJ61AKW0QEgLzGMNwtIMdxbDUzLxcun8W7NbJO0e2Jg/Nxm3cCSVzzg==",
+ "node_modules/es-to-primitive": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz",
+ "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@rolldown/pluginutils": "^1.0.0"
+ "is-callable": "^1.2.7",
+ "is-date-object": "^1.0.5",
+ "is-symbol": "^1.0.4"
},
"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"
+ "node": ">= 0.4"
},
- "peerDependenciesMeta": {
- "@rolldown/plugin-babel": {
- "optional": true
- },
- "babel-plugin-react-compiler": {
- "optional": true
- }
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/@vitejs/plugin-rsc": {
- "version": "0.5.26",
- "resolved": "https://registry.npmjs.org/@vitejs/plugin-rsc/-/plugin-rsc-0.5.26.tgz",
- "integrity": "sha512-T8W8ODEutblw9qXQB512LDPyv1tAbJRD/Gf0QEGsAoydl4nxEtIrghnhoI9oLY9R+7aw+cLk1ZEltxWHWf4aHw==",
- "dev": true,
+ "node_modules/esast-util-from-estree": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/esast-util-from-estree/-/esast-util-from-estree-2.0.0.tgz",
+ "integrity": "sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==",
"license": "MIT",
"dependencies": {
- "@rolldown/pluginutils": "1.0.0-rc.18",
- "es-module-lexer": "^2.1.0",
- "estree-walker": "^3.0.3",
- "magic-string": "^0.30.21",
- "srvx": "^0.11.15",
- "strip-literal": "^3.1.0",
- "turbo-stream": "^3.2.0",
- "vitefu": "^1.1.3"
- },
- "peerDependencies": {
- "react": "*",
- "react-dom": "*",
- "react-server-dom-webpack": "*",
- "vite": "*"
+ "@types/estree-jsx": "^1.0.0",
+ "devlop": "^1.0.0",
+ "estree-util-visit": "^2.0.0",
+ "unist-util-position-from-estree": "^2.0.0"
},
- "peerDependenciesMeta": {
- "react-server-dom-webpack": {
- "optional": true
- }
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
- "node_modules/@vitejs/plugin-rsc/node_modules/@rolldown/pluginutils": {
- "version": "1.0.0-rc.18",
- "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.18.tgz",
- "integrity": "sha512-CUY5Mnhe64xQBGZEEXQ5WyZwsc1JU3vAZLIxtrsBt3LO6UOb+C8GunVKqe9sT8NeWb4lqSaoJtp2xo6GxT1MNw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@webassemblyjs/ast": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz",
- "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==",
- "dev": true,
+ "node_modules/esast-util-from-js": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/esast-util-from-js/-/esast-util-from-js-2.0.1.tgz",
+ "integrity": "sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==",
"license": "MIT",
- "peer": true,
"dependencies": {
- "@webassemblyjs/helper-numbers": "1.13.2",
- "@webassemblyjs/helper-wasm-bytecode": "1.13.2"
+ "@types/estree-jsx": "^1.0.0",
+ "acorn": "^8.0.0",
+ "esast-util-from-estree": "^2.0.0",
+ "vfile-message": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
- "node_modules/@webassemblyjs/floating-point-hex-parser": {
- "version": "1.13.2",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz",
- "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==",
+ "node_modules/esbuild": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz",
+ "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==",
"dev": true,
+ "hasInstallScript": true,
"license": "MIT",
- "peer": true
+ "optional": true,
+ "peer": true,
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.28.2",
+ "@esbuild/android-arm": "0.28.2",
+ "@esbuild/android-arm64": "0.28.2",
+ "@esbuild/android-x64": "0.28.2",
+ "@esbuild/darwin-arm64": "0.28.2",
+ "@esbuild/darwin-x64": "0.28.2",
+ "@esbuild/freebsd-arm64": "0.28.2",
+ "@esbuild/freebsd-x64": "0.28.2",
+ "@esbuild/linux-arm": "0.28.2",
+ "@esbuild/linux-arm64": "0.28.2",
+ "@esbuild/linux-ia32": "0.28.2",
+ "@esbuild/linux-loong64": "0.28.2",
+ "@esbuild/linux-mips64el": "0.28.2",
+ "@esbuild/linux-ppc64": "0.28.2",
+ "@esbuild/linux-riscv64": "0.28.2",
+ "@esbuild/linux-s390x": "0.28.2",
+ "@esbuild/linux-x64": "0.28.2",
+ "@esbuild/netbsd-arm64": "0.28.2",
+ "@esbuild/netbsd-x64": "0.28.2",
+ "@esbuild/openbsd-arm64": "0.28.2",
+ "@esbuild/openbsd-x64": "0.28.2",
+ "@esbuild/openharmony-arm64": "0.28.2",
+ "@esbuild/sunos-x64": "0.28.2",
+ "@esbuild/win32-arm64": "0.28.2",
+ "@esbuild/win32-ia32": "0.28.2",
+ "@esbuild/win32-x64": "0.28.2"
+ }
},
- "node_modules/@webassemblyjs/helper-api-error": {
- "version": "1.13.2",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz",
- "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==",
- "dev": true,
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "devOptional": true,
"license": "MIT",
- "peer": true
+ "engines": {
+ "node": ">=6"
+ }
},
- "node_modules/@webassemblyjs/helper-buffer": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz",
- "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==",
+ "node_modules/escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
"dev": true,
- "license": "MIT",
- "peer": true
+ "license": "MIT"
},
- "node_modules/@webassemblyjs/helper-numbers": {
- "version": "1.13.2",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz",
- "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==",
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
"dev": true,
"license": "MIT",
- "peer": true,
- "dependencies": {
- "@webassemblyjs/floating-point-hex-parser": "1.13.2",
- "@webassemblyjs/helper-api-error": "1.13.2",
- "@xtuc/long": "4.2.2"
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/@webassemblyjs/helper-wasm-bytecode": {
- "version": "1.13.2",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz",
- "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==",
+ "node_modules/eslint": {
+ "version": "9.39.4",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz",
+ "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==",
"dev": true,
"license": "MIT",
- "peer": true
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.8.0",
+ "@eslint-community/regexpp": "^4.12.1",
+ "@eslint/config-array": "^0.21.2",
+ "@eslint/config-helpers": "^0.4.2",
+ "@eslint/core": "^0.17.0",
+ "@eslint/eslintrc": "^3.3.5",
+ "@eslint/js": "9.39.4",
+ "@eslint/plugin-kit": "^0.4.1",
+ "@humanfs/node": "^0.16.6",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@humanwhocodes/retry": "^0.4.2",
+ "@types/estree": "^1.0.6",
+ "ajv": "^6.14.0",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.6",
+ "debug": "^4.3.2",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^8.4.0",
+ "eslint-visitor-keys": "^4.2.1",
+ "espree": "^10.4.0",
+ "esquery": "^1.5.0",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^8.0.0",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.5",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
+ },
+ "peerDependencies": {
+ "jiti": "*"
+ },
+ "peerDependenciesMeta": {
+ "jiti": {
+ "optional": true
+ }
+ }
},
- "node_modules/@webassemblyjs/helper-wasm-section": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz",
- "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==",
+ "node_modules/eslint-config-next": {
+ "version": "16.3.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-16.3.0.tgz",
+ "integrity": "sha512-lPrf1kHsMJEZqO0uXkNB400c5MGrhrTk3BNX7P0ol4gt61+iUlQfjy9TyIOEA9eOXrf+5+mYbT/JsY8+zqUByQ==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
- "@webassemblyjs/ast": "1.14.1",
- "@webassemblyjs/helper-buffer": "1.14.1",
- "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
- "@webassemblyjs/wasm-gen": "1.14.1"
+ "@next/eslint-plugin-next": "16.3.0",
+ "eslint-import-resolver-node": "^0.3.6",
+ "eslint-import-resolver-typescript": "^3.5.2",
+ "eslint-plugin-import": "^2.32.0",
+ "eslint-plugin-jsx-a11y": "^6.10.0",
+ "eslint-plugin-react": "^7.37.0",
+ "eslint-plugin-react-hooks": "^7.0.0",
+ "globals": "16.4.0",
+ "typescript-eslint": "^8.46.0"
+ },
+ "peerDependencies": {
+ "eslint": ">=9.0.0",
+ "typescript": ">=3.3.1"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
}
},
- "node_modules/@webassemblyjs/ieee754": {
- "version": "1.13.2",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz",
- "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==",
+ "node_modules/eslint-config-next/node_modules/globals": {
+ "version": "16.4.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-16.4.0.tgz",
+ "integrity": "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==",
"dev": true,
"license": "MIT",
- "peer": true,
- "dependencies": {
- "@xtuc/ieee754": "^1.2.0"
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/@webassemblyjs/leb128": {
- "version": "1.13.2",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz",
- "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==",
- "dev": true,
- "license": "Apache-2.0",
- "peer": true,
+ "node_modules/eslint-import-resolver-node": {
+ "version": "0.3.10",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.10.tgz",
+ "integrity": "sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@xtuc/long": "4.2.2"
+ "debug": "^3.2.7",
+ "is-core-module": "^2.16.1",
+ "resolve": "^2.0.0-next.6"
}
},
- "node_modules/@webassemblyjs/utf8": {
- "version": "1.13.2",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz",
- "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==",
+ "node_modules/eslint-import-resolver-node/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
"dev": true,
"license": "MIT",
- "peer": true
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
},
- "node_modules/@webassemblyjs/wasm-edit": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz",
- "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==",
+ "node_modules/eslint-import-resolver-typescript": {
+ "version": "3.10.1",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.10.1.tgz",
+ "integrity": "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==",
"dev": true,
- "license": "MIT",
- "peer": true,
+ "license": "ISC",
"dependencies": {
- "@webassemblyjs/ast": "1.14.1",
- "@webassemblyjs/helper-buffer": "1.14.1",
- "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
- "@webassemblyjs/helper-wasm-section": "1.14.1",
- "@webassemblyjs/wasm-gen": "1.14.1",
- "@webassemblyjs/wasm-opt": "1.14.1",
- "@webassemblyjs/wasm-parser": "1.14.1",
- "@webassemblyjs/wast-printer": "1.14.1"
+ "@nolyfill/is-core-module": "1.0.39",
+ "debug": "^4.4.0",
+ "get-tsconfig": "^4.10.0",
+ "is-bun-module": "^2.0.0",
+ "stable-hash": "^0.0.5",
+ "tinyglobby": "^0.2.13",
+ "unrs-resolver": "^1.6.2"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint-import-resolver-typescript"
+ },
+ "peerDependencies": {
+ "eslint": "*",
+ "eslint-plugin-import": "*",
+ "eslint-plugin-import-x": "*"
+ },
+ "peerDependenciesMeta": {
+ "eslint-plugin-import": {
+ "optional": true
+ },
+ "eslint-plugin-import-x": {
+ "optional": true
+ }
}
},
- "node_modules/@webassemblyjs/wasm-gen": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz",
- "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==",
+ "node_modules/eslint-module-utils": {
+ "version": "2.12.1",
+ "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz",
+ "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
- "@webassemblyjs/ast": "1.14.1",
- "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
- "@webassemblyjs/ieee754": "1.13.2",
- "@webassemblyjs/leb128": "1.13.2",
- "@webassemblyjs/utf8": "1.13.2"
+ "debug": "^3.2.7"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependenciesMeta": {
+ "eslint": {
+ "optional": true
+ }
}
},
- "node_modules/@webassemblyjs/wasm-opt": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz",
- "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==",
+ "node_modules/eslint-module-utils/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
- "@webassemblyjs/ast": "1.14.1",
- "@webassemblyjs/helper-buffer": "1.14.1",
- "@webassemblyjs/wasm-gen": "1.14.1",
- "@webassemblyjs/wasm-parser": "1.14.1"
+ "ms": "^2.1.1"
}
},
- "node_modules/@webassemblyjs/wasm-parser": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz",
- "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==",
+ "node_modules/eslint-plugin-import": {
+ "version": "2.32.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz",
+ "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
- "@webassemblyjs/ast": "1.14.1",
- "@webassemblyjs/helper-api-error": "1.13.2",
- "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
- "@webassemblyjs/ieee754": "1.13.2",
- "@webassemblyjs/leb128": "1.13.2",
- "@webassemblyjs/utf8": "1.13.2"
+ "@rtsao/scc": "^1.1.0",
+ "array-includes": "^3.1.9",
+ "array.prototype.findlastindex": "^1.2.6",
+ "array.prototype.flat": "^1.3.3",
+ "array.prototype.flatmap": "^1.3.3",
+ "debug": "^3.2.7",
+ "doctrine": "^2.1.0",
+ "eslint-import-resolver-node": "^0.3.9",
+ "eslint-module-utils": "^2.12.1",
+ "hasown": "^2.0.2",
+ "is-core-module": "^2.16.1",
+ "is-glob": "^4.0.3",
+ "minimatch": "^3.1.2",
+ "object.fromentries": "^2.0.8",
+ "object.groupby": "^1.0.3",
+ "object.values": "^1.2.1",
+ "semver": "^6.3.1",
+ "string.prototype.trimend": "^1.0.9",
+ "tsconfig-paths": "^3.15.0"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependencies": {
+ "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9"
}
},
- "node_modules/@webassemblyjs/wast-printer": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz",
- "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==",
+ "node_modules/eslint-plugin-import/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
- "@webassemblyjs/ast": "1.14.1",
- "@xtuc/long": "4.2.2"
+ "ms": "^2.1.1"
}
},
- "node_modules/@xtuc/ieee754": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
- "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==",
- "dev": true,
- "license": "BSD-3-Clause",
- "peer": true
- },
- "node_modules/@xtuc/long": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
- "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
- "dev": true,
- "license": "Apache-2.0",
- "peer": true
- },
- "node_modules/acorn": {
- "version": "8.16.0",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz",
- "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
+ "node_modules/eslint-plugin-jsx-a11y": {
+ "version": "6.10.2",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz",
+ "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==",
"dev": true,
"license": "MIT",
- "bin": {
- "acorn": "bin/acorn"
+ "dependencies": {
+ "aria-query": "^5.3.2",
+ "array-includes": "^3.1.8",
+ "array.prototype.flatmap": "^1.3.2",
+ "ast-types-flow": "^0.0.8",
+ "axe-core": "^4.10.0",
+ "axobject-query": "^4.1.0",
+ "damerau-levenshtein": "^1.0.8",
+ "emoji-regex": "^9.2.2",
+ "hasown": "^2.0.2",
+ "jsx-ast-utils": "^3.3.5",
+ "language-tags": "^1.0.9",
+ "minimatch": "^3.1.2",
+ "object.fromentries": "^2.0.8",
+ "safe-regex-test": "^1.0.3",
+ "string.prototype.includes": "^2.0.1"
},
"engines": {
- "node": ">=0.4.0"
+ "node": ">=4.0"
+ },
+ "peerDependencies": {
+ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9"
}
},
- "node_modules/acorn-import-phases": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz",
- "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==",
+ "node_modules/eslint-plugin-react": {
+ "version": "7.37.5",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz",
+ "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==",
"dev": true,
"license": "MIT",
- "peer": true,
+ "dependencies": {
+ "array-includes": "^3.1.8",
+ "array.prototype.findlast": "^1.2.5",
+ "array.prototype.flatmap": "^1.3.3",
+ "array.prototype.tosorted": "^1.1.4",
+ "doctrine": "^2.1.0",
+ "es-iterator-helpers": "^1.2.1",
+ "estraverse": "^5.3.0",
+ "hasown": "^2.0.2",
+ "jsx-ast-utils": "^2.4.1 || ^3.0.0",
+ "minimatch": "^3.1.2",
+ "object.entries": "^1.1.9",
+ "object.fromentries": "^2.0.8",
+ "object.values": "^1.2.1",
+ "prop-types": "^15.8.1",
+ "resolve": "^2.0.0-next.5",
+ "semver": "^6.3.1",
+ "string.prototype.matchall": "^4.0.12",
+ "string.prototype.repeat": "^1.0.0"
+ },
"engines": {
- "node": ">=10.13.0"
+ "node": ">=4"
},
"peerDependencies": {
- "acorn": "^8.14.0"
+ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7"
}
},
- "node_modules/acorn-jsx": {
- "version": "5.3.2",
- "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
- "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "node_modules/eslint-plugin-react-hooks": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.1.1.tgz",
+ "integrity": "sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==",
"dev": true,
"license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.24.4",
+ "@babel/parser": "^7.24.4",
+ "hermes-parser": "^0.25.1",
+ "zod": "^3.25.0 || ^4.0.0",
+ "zod-validation-error": "^3.5.0 || ^4.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
"peerDependencies": {
- "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0"
}
},
- "node_modules/acorn-loose": {
- "version": "8.5.2",
- "resolved": "https://registry.npmjs.org/acorn-loose/-/acorn-loose-8.5.2.tgz",
- "integrity": "sha512-PPvV6g8UGMGgjrMu+n/f9E/tCSkNQ2Y97eFvuVdJfG11+xdIeDcLyNdC8SHcrHbRqkfwLASdplyR6B6sKM1U4A==",
+ "node_modules/eslint-scope": {
+ "version": "8.4.0",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz",
+ "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
"dev": true,
- "license": "MIT",
+ "license": "BSD-2-Clause",
"dependencies": {
- "acorn": "^8.15.0"
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
},
"engines": {
- "node": ">=0.4.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
}
},
- "node_modules/ajv": {
- "version": "6.15.0",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz",
- "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==",
+ "node_modules/eslint-visitor-keys": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
+ "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
"dev": true,
- "license": "MIT",
- "dependencies": {
- "fast-deep-equal": "^3.1.1",
- "fast-json-stable-stringify": "^2.0.0",
- "json-schema-traverse": "^0.4.1",
- "uri-js": "^4.2.2"
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
- "type": "github",
- "url": "https://github.com/sponsors/epoberezkin"
+ "url": "https://opencollective.com/eslint"
}
},
- "node_modules/ajv-formats": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz",
- "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
+ "node_modules/espree": {
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
+ "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
"dev": true,
- "license": "MIT",
- "peer": true,
+ "license": "BSD-2-Clause",
"dependencies": {
- "ajv": "^8.0.0"
+ "acorn": "^8.15.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^4.2.1"
},
- "peerDependencies": {
- "ajv": "^8.0.0"
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
- "peerDependenciesMeta": {
- "ajv": {
- "optional": true
- }
+ "funding": {
+ "url": "https://opencollective.com/eslint"
}
},
- "node_modules/ajv-formats/node_modules/ajv": {
- "version": "8.20.0",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
- "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
+ "node_modules/esquery": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz",
+ "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==",
"dev": true,
- "license": "MIT",
- "peer": true,
+ "license": "BSD-3-Clause",
"dependencies": {
- "fast-deep-equal": "^3.1.3",
- "fast-uri": "^3.0.1",
- "json-schema-traverse": "^1.0.0",
- "require-from-string": "^2.0.2"
+ "estraverse": "^5.1.0"
},
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/epoberezkin"
+ "engines": {
+ "node": ">=0.10"
}
},
- "node_modules/ajv-formats/node_modules/json-schema-traverse": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
- "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
- "dev": true,
- "license": "MIT",
- "peer": true
- },
- "node_modules/ansi-styles": {
+ "node_modules/esrecurse": {
"version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "dev": true,
- "license": "MIT",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "devOptional": true,
+ "license": "BSD-2-Clause",
"dependencies": {
- "color-convert": "^2.0.1"
+ "estraverse": "^5.2.0"
},
"engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ "node": ">=4.0"
}
},
- "node_modules/argparse": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
- "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
- "dev": true,
- "license": "Python-2.0"
- },
- "node_modules/aria-query": {
- "version": "5.3.2",
- "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz",
- "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==",
- "dev": true,
- "license": "Apache-2.0",
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "devOptional": true,
+ "license": "BSD-2-Clause",
"engines": {
- "node": ">= 0.4"
+ "node": ">=4.0"
}
},
- "node_modules/array-buffer-byte-length": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz",
- "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==",
- "dev": true,
+ "node_modules/estree-util-attach-comments": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/estree-util-attach-comments/-/estree-util-attach-comments-3.0.0.tgz",
+ "integrity": "sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw==",
"license": "MIT",
"dependencies": {
- "call-bound": "^1.0.3",
- "is-array-buffer": "^3.0.5"
- },
- "engines": {
- "node": ">= 0.4"
+ "@types/estree": "^1.0.0"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
- "node_modules/array-includes": {
- "version": "3.1.9",
- "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz",
- "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==",
- "dev": true,
+ "node_modules/estree-util-build-jsx": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/estree-util-build-jsx/-/estree-util-build-jsx-3.0.1.tgz",
+ "integrity": "sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ==",
"license": "MIT",
"dependencies": {
- "call-bind": "^1.0.8",
- "call-bound": "^1.0.4",
- "define-properties": "^1.2.1",
- "es-abstract": "^1.24.0",
- "es-object-atoms": "^1.1.1",
- "get-intrinsic": "^1.3.0",
- "is-string": "^1.1.1",
- "math-intrinsics": "^1.1.0"
- },
- "engines": {
- "node": ">= 0.4"
+ "@types/estree-jsx": "^1.0.0",
+ "devlop": "^1.0.0",
+ "estree-util-is-identifier-name": "^3.0.0",
+ "estree-walker": "^3.0.0"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
- "node_modules/array.prototype.findlast": {
- "version": "1.2.5",
- "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz",
- "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==",
- "dev": true,
+ "node_modules/estree-util-is-identifier-name": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz",
+ "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==",
"license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.7",
- "define-properties": "^1.2.1",
- "es-abstract": "^1.23.2",
- "es-errors": "^1.3.0",
- "es-object-atoms": "^1.0.0",
- "es-shim-unscopables": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
- "node_modules/array.prototype.findlastindex": {
- "version": "1.2.6",
- "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz",
- "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==",
- "dev": true,
+ "node_modules/estree-util-scope": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/estree-util-scope/-/estree-util-scope-1.0.0.tgz",
+ "integrity": "sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ==",
"license": "MIT",
"dependencies": {
- "call-bind": "^1.0.8",
- "call-bound": "^1.0.4",
- "define-properties": "^1.2.1",
- "es-abstract": "^1.23.9",
- "es-errors": "^1.3.0",
- "es-object-atoms": "^1.1.1",
- "es-shim-unscopables": "^1.1.0"
- },
- "engines": {
- "node": ">= 0.4"
+ "@types/estree": "^1.0.0",
+ "devlop": "^1.0.0"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
- "node_modules/array.prototype.flat": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz",
- "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==",
- "dev": true,
+ "node_modules/estree-util-to-js": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/estree-util-to-js/-/estree-util-to-js-2.0.0.tgz",
+ "integrity": "sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==",
"license": "MIT",
"dependencies": {
- "call-bind": "^1.0.8",
- "define-properties": "^1.2.1",
- "es-abstract": "^1.23.5",
- "es-shim-unscopables": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
+ "@types/estree-jsx": "^1.0.0",
+ "astring": "^1.8.0",
+ "source-map": "^0.7.0"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
- "node_modules/array.prototype.flatmap": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz",
- "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==",
- "dev": true,
+ "node_modules/estree-util-to-js/node_modules/source-map": {
+ "version": "0.7.6",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz",
+ "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">= 12"
+ }
+ },
+ "node_modules/estree-util-visit": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/estree-util-visit/-/estree-util-visit-2.0.0.tgz",
+ "integrity": "sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==",
"license": "MIT",
"dependencies": {
- "call-bind": "^1.0.8",
- "define-properties": "^1.2.1",
- "es-abstract": "^1.23.5",
- "es-shim-unscopables": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
+ "@types/estree-jsx": "^1.0.0",
+ "@types/unist": "^3.0.0"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
- "node_modules/array.prototype.tosorted": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz",
- "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==",
- "dev": true,
+ "node_modules/estree-walker": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
+ "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
"license": "MIT",
"dependencies": {
- "call-bind": "^1.0.7",
- "define-properties": "^1.2.1",
- "es-abstract": "^1.23.3",
- "es-errors": "^1.3.0",
- "es-shim-unscopables": "^1.0.2"
- },
+ "@types/estree": "^1.0.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "license": "BSD-2-Clause",
"engines": {
- "node": ">= 0.4"
+ "node": ">=0.10.0"
}
},
- "node_modules/arraybuffer.prototype.slice": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz",
- "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==",
- "dev": true,
+ "node_modules/events": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
+ "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
+ "devOptional": true,
"license": "MIT",
- "dependencies": {
- "array-buffer-byte-length": "^1.0.1",
- "call-bind": "^1.0.8",
- "define-properties": "^1.2.1",
- "es-abstract": "^1.23.5",
- "es-errors": "^1.3.0",
- "get-intrinsic": "^1.2.6",
- "is-array-buffer": "^3.0.4"
- },
+ "peer": true,
"engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "node": ">=0.8.x"
}
},
- "node_modules/ast-types-flow": {
- "version": "0.0.8",
- "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz",
- "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==",
- "dev": true,
+ "node_modules/extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
"license": "MIT"
},
- "node_modules/async-function": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz",
- "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==",
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-glob": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz",
+ "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==",
"dev": true,
"license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ },
"engines": {
- "node": ">= 0.4"
+ "node": ">=8.6.0"
}
},
- "node_modules/available-typed-arrays": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
- "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
+ "node_modules/fast-glob/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"dev": true,
- "license": "MIT",
+ "license": "ISC",
"dependencies": {
- "possible-typed-array-names": "^1.0.0"
+ "is-glob": "^4.0.1"
},
"engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "node": ">= 6"
}
},
- "node_modules/axe-core": {
- "version": "4.11.4",
- "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.11.4.tgz",
- "integrity": "sha512-KunSNx+TVpkAw/6ULfhnx+HWRecjqZGTOyquAoWHYLRSdK1tB5Ihce1ZW+UY3fj33bYAFWPu7W/GRSmmrCGuxA==",
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
"dev": true,
- "license": "MPL-2.0",
- "engines": {
- "node": ">=4"
- }
+ "license": "MIT"
},
- "node_modules/axobject-query": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
- "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==",
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
"dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": ">= 0.4"
+ "license": "MIT"
+ },
+ "node_modules/fast-uri": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.5.tgz",
+ "integrity": "sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==",
+ "devOptional": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fastify"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fastify"
+ }
+ ],
+ "license": "BSD-3-Clause",
+ "peer": true
+ },
+ "node_modules/fastq": {
+ "version": "1.20.1",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz",
+ "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "reusify": "^1.0.4"
}
},
- "node_modules/balanced-match": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "node_modules/fflate": {
+ "version": "0.7.4",
+ "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.7.4.tgz",
+ "integrity": "sha512-5u2V/CDW15QM1XbbgS+0DfPxVB+jUKhWEKuuFuHncbk3tEEqzmoXL+2KyOFuKGqOnmdIy0/davWF1CkuwtibCw==",
"dev": true,
"license": "MIT"
},
- "node_modules/base64-js": {
- "version": "0.0.8",
- "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz",
- "integrity": "sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw==",
+ "node_modules/file-entry-cache": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
+ "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
"dev": true,
"license": "MIT",
+ "dependencies": {
+ "flat-cache": "^4.0.0"
+ },
"engines": {
- "node": ">= 0.4"
+ "node": ">=16.0.0"
}
},
- "node_modules/baseline-browser-mapping": {
- "version": "2.10.30",
- "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.30.tgz",
- "integrity": "sha512-xjOFN16Ha1+Rz4nFYKqHU/LSB+gx/Vi3yQLX7r7sAW+Wa+8hhF2h4pvqTrTMc8+WcDBEunnUurr46Jvv0jk3Vg==",
- "license": "Apache-2.0",
- "bin": {
- "baseline-browser-mapping": "dist/cli.cjs"
+ "node_modules/fill-range": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
},
"engines": {
- "node": ">=6.0.0"
+ "node": ">=8"
}
},
- "node_modules/blake3-wasm": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz",
- "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/brace-expansion": {
- "version": "1.1.14",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz",
- "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==",
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
"dev": true,
"license": "MIT",
"dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/braces": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
- "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "node_modules/flat-cache": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
+ "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "fill-range": "^7.1.1"
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.4"
},
"engines": {
- "node": ">=8"
+ "node": ">=16"
}
},
- "node_modules/browserslist": {
- "version": "4.28.2",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz",
- "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==",
+ "node_modules/flatted": {
+ "version": "3.4.2",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz",
+ "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/for-each": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
+ "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
"dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/browserslist"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
"license": "MIT",
"dependencies": {
- "baseline-browser-mapping": "^2.10.12",
- "caniuse-lite": "^1.0.30001782",
- "electron-to-chromium": "^1.5.328",
- "node-releases": "^2.0.36",
- "update-browserslist-db": "^1.2.3"
+ "is-callable": "^1.2.7"
},
- "bin": {
- "browserslist": "cli.js"
+ "engines": {
+ "node": ">= 0.4"
},
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
"engines": {
- "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
- "node_modules/buffer-from": {
+ "node_modules/function-bind": {
"version": "1.1.2",
- "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
- "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"dev": true,
"license": "MIT",
- "peer": true
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
},
- "node_modules/call-bind": {
- "version": "1.0.9",
- "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz",
- "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==",
+ "node_modules/function.prototype.name": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz",
+ "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==",
"dev": true,
"license": "MIT",
"dependencies": {
- "call-bind-apply-helpers": "^1.0.2",
- "es-define-property": "^1.0.1",
- "get-intrinsic": "^1.3.0",
- "set-function-length": "^1.2.2"
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "define-properties": "^1.2.1",
+ "functions-have-names": "^1.2.3",
+ "hasown": "^2.0.2",
+ "is-callable": "^1.2.7"
},
"engines": {
"node": ">= 0.4"
@@ -4067,29 +6376,53 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/call-bind-apply-helpers": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
- "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+ "node_modules/functions-have-names": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
+ "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/generator-function": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz",
+ "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "function-bind": "^1.1.2"
- },
"engines": {
"node": ">= 0.4"
}
},
- "node_modules/call-bound": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
- "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
+ "node_modules/gensync": {
+ "version": "1.0.0-beta.2",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+ "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.2",
- "get-intrinsic": "^1.3.0"
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "function-bind": "^1.1.2",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "math-intrinsics": "^1.1.0"
},
"engines": {
"node": ">= 0.4"
@@ -4098,221 +6431,179 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/callsites": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
- "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/camelize": {
+ "node_modules/get-proto": {
"version": "1.0.1",
- "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz",
- "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==",
+ "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
+ "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
"dev": true,
"license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "dependencies": {
+ "dunder-proto": "^1.0.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
}
},
- "node_modules/caniuse-lite": {
- "version": "1.0.30001793",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001793.tgz",
- "integrity": "sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA==",
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "CC-BY-4.0"
- },
- "node_modules/chalk": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
- "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "node_modules/get-symbol-description": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz",
+ "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6"
},
"engines": {
- "node": ">=10"
+ "node": ">= 0.4"
},
"funding": {
- "url": "https://github.com/chalk/chalk?sponsor=1"
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/chrome-trace-event": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz",
- "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==",
+ "node_modules/get-tsconfig": {
+ "version": "4.14.0",
+ "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.0.tgz",
+ "integrity": "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==",
"dev": true,
"license": "MIT",
- "peer": true,
- "engines": {
- "node": ">=6.0"
+ "dependencies": {
+ "resolve-pkg-maps": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
}
},
- "node_modules/client-only": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
- "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==",
- "license": "MIT"
+ "node_modules/github-slugger": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz",
+ "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==",
+ "license": "ISC"
},
- "node_modules/color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
"dev": true,
- "license": "MIT",
+ "license": "ISC",
"dependencies": {
- "color-name": "~1.1.4"
+ "is-glob": "^4.0.3"
},
"engines": {
- "node": ">=7.0.0"
+ "node": ">=10.13.0"
}
},
- "node_modules/color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/commander": {
- "version": "2.20.3",
- "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
- "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
- "dev": true,
- "license": "MIT",
+ "node_modules/glob-to-regexp": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
+ "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==",
+ "devOptional": true,
+ "license": "BSD-2-Clause",
"peer": true
},
- "node_modules/concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/convert-source-map": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
- "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/cookie": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz",
- "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==",
+ "node_modules/globals": {
+ "version": "14.0.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
+ "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=18"
},
"funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/cross-spawn": {
- "version": "7.0.6",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
- "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "node_modules/globalthis": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz",
+ "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "path-key": "^3.1.0",
- "shebang-command": "^2.0.0",
- "which": "^2.0.1"
+ "define-properties": "^1.2.1",
+ "gopd": "^1.0.1"
},
"engines": {
- "node": ">= 8"
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/css-background-parser": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/css-background-parser/-/css-background-parser-0.1.0.tgz",
- "integrity": "sha512-2EZLisiZQ+7m4wwur/qiYJRniHX4K5Tc9w93MT3AS0WS1u5kaZ4FKXlOTBhOjc+CgEgPiGY+fX1yWD8UwpEqUA==",
+ "node_modules/globrex": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz",
+ "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==",
"dev": true,
"license": "MIT"
},
- "node_modules/css-box-shadow": {
- "version": "1.0.0-3",
- "resolved": "https://registry.npmjs.org/css-box-shadow/-/css-box-shadow-1.0.0-3.tgz",
- "integrity": "sha512-9jaqR6e7Ohds+aWwmhe6wILJ99xYQbfmK9QQB9CcMjDbTxPZjwEmUQpU91OG05Xgm8BahT5fW+svbsQGjS/zPg==",
+ "node_modules/gopd": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
+ "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
},
- "node_modules/css-color-keywords": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz",
- "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==",
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+ "devOptional": true,
+ "license": "ISC"
+ },
+ "node_modules/has-bigints": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz",
+ "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==",
"dev": true,
- "license": "ISC",
+ "license": "MIT",
"engines": {
- "node": ">=4"
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/css-gradient-parser": {
- "version": "0.0.16",
- "resolved": "https://registry.npmjs.org/css-gradient-parser/-/css-gradient-parser-0.0.16.tgz",
- "integrity": "sha512-3O5QdqgFRUbXvK1x5INf1YkBz1UKSWqrd63vWsum8MNHDBYD5urm3QtxZbKU259OrEXNM26lP/MPY3d1IGkBgA==",
- "dev": true,
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "devOptional": true,
"license": "MIT",
"engines": {
- "node": ">=16"
+ "node": ">=8"
}
},
- "node_modules/css-to-react-native": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz",
- "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==",
+ "node_modules/has-property-descriptors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
+ "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "camelize": "^1.0.0",
- "css-color-keywords": "^1.0.0",
- "postcss-value-parser": "^4.0.2"
+ "es-define-property": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/csstype": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
- "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/damerau-levenshtein": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
- "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==",
- "dev": true,
- "license": "BSD-2-Clause"
- },
- "node_modules/data-view-buffer": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz",
- "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==",
+ "node_modules/has-proto": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz",
+ "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "call-bound": "^1.0.3",
- "es-errors": "^1.3.0",
- "is-data-view": "^1.0.2"
+ "dunder-proto": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
@@ -4321,34 +6612,27 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/data-view-byte-length": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz",
- "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==",
+ "node_modules/has-symbols": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
+ "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.3",
- "es-errors": "^1.3.0",
- "is-data-view": "^1.0.2"
- },
"engines": {
"node": ">= 0.4"
},
"funding": {
- "url": "https://github.com/sponsors/inspect-js"
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/data-view-byte-offset": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz",
- "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==",
+ "node_modules/has-tostringtag": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+ "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "call-bound": "^1.0.2",
- "es-errors": "^1.3.0",
- "is-data-view": "^1.0.1"
+ "has-symbols": "^1.0.3"
},
"engines": {
"node": ">= 0.4"
@@ -4357,214 +6641,278 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/debug": {
- "version": "4.4.3",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
- "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "node_modules/hasown": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz",
+ "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "ms": "^2.1.3"
+ "function-bind": "^1.1.2"
},
"engines": {
- "node": ">=6.0"
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/hast-util-heading-rank": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/hast-util-heading-rank/-/hast-util-heading-rank-3.0.0.tgz",
+ "integrity": "sha512-EJKb8oMUXVHcWZTDepnr+WNbfnXKFNf9duMesmr4S8SXTJBJ9M4Yok08pu9vxdJwdlGRhVumk9mEhkEvKGifwA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0"
},
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
- "node_modules/deep-is": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
- "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
- "dev": true,
- "license": "MIT"
+ "node_modules/hast-util-to-estree": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-3.1.3.tgz",
+ "integrity": "sha512-48+B/rJWAp0jamNbAAf9M7Uf//UVqAoMmgXhBdxTDJLGKY+LRnZ99qcG+Qjl5HfMpYNzS5v4EAwVEF34LeAj7w==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "@types/estree-jsx": "^1.0.0",
+ "@types/hast": "^3.0.0",
+ "comma-separated-tokens": "^2.0.0",
+ "devlop": "^1.0.0",
+ "estree-util-attach-comments": "^3.0.0",
+ "estree-util-is-identifier-name": "^3.0.0",
+ "hast-util-whitespace": "^3.0.0",
+ "mdast-util-mdx-expression": "^2.0.0",
+ "mdast-util-mdx-jsx": "^3.0.0",
+ "mdast-util-mdxjs-esm": "^2.0.0",
+ "property-information": "^7.0.0",
+ "space-separated-tokens": "^2.0.0",
+ "style-to-js": "^1.0.0",
+ "unist-util-position": "^5.0.0",
+ "zwitch": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
},
- "node_modules/define-data-property": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
- "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
- "dev": true,
+ "node_modules/hast-util-to-jsx-runtime": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz",
+ "integrity": "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==",
"license": "MIT",
"dependencies": {
- "es-define-property": "^1.0.0",
- "es-errors": "^1.3.0",
- "gopd": "^1.0.1"
+ "@types/estree": "^1.0.0",
+ "@types/hast": "^3.0.0",
+ "@types/unist": "^3.0.0",
+ "comma-separated-tokens": "^2.0.0",
+ "devlop": "^1.0.0",
+ "estree-util-is-identifier-name": "^3.0.0",
+ "hast-util-whitespace": "^3.0.0",
+ "mdast-util-mdx-expression": "^2.0.0",
+ "mdast-util-mdx-jsx": "^3.0.0",
+ "mdast-util-mdxjs-esm": "^2.0.0",
+ "property-information": "^7.0.0",
+ "space-separated-tokens": "^2.0.0",
+ "style-to-js": "^1.0.0",
+ "unist-util-position": "^5.0.0",
+ "vfile-message": "^4.0.0"
},
- "engines": {
- "node": ">= 0.4"
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-to-string": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-3.0.1.tgz",
+ "integrity": "sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
- "node_modules/define-properties": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
- "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
- "dev": true,
+ "node_modules/hast-util-whitespace": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz",
+ "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==",
"license": "MIT",
"dependencies": {
- "define-data-property": "^1.0.1",
- "has-property-descriptors": "^1.0.0",
- "object-keys": "^1.1.1"
+ "@types/hast": "^3.0.0"
},
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hermes-estree": {
+ "version": "0.25.1",
+ "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz",
+ "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/hermes-parser": {
+ "version": "0.25.1",
+ "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz",
+ "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hermes-estree": "0.25.1"
+ }
+ },
+ "node_modules/hex-rgb": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/hex-rgb/-/hex-rgb-4.3.0.tgz",
+ "integrity": "sha512-Ox1pJVrDCyGHMG9CFg1tmrRUMRPRsAWYc/PinY0XzJU4K7y7vjNoLKIQ7BR5UJMCxNN8EM1MNDmHWA/B3aZUuw==",
+ "dev": true,
+ "license": "MIT",
"engines": {
- "node": ">= 0.4"
+ "node": ">=6"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/detect-libc": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
- "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
- "devOptional": true,
- "license": "Apache-2.0",
+ "node_modules/ignore": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+ "dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=8"
+ "node": ">= 4"
}
},
- "node_modules/doctrine": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
- "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "node_modules/image-size": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/image-size/-/image-size-2.0.2.tgz",
+ "integrity": "sha512-IRqXKlaXwgSMAMtpNzZa1ZAe8m+Sa1770Dhk8VkSsP9LS+iHD62Zd8FQKs8fbPiagBE7BzoFX23cxFnwshpV6w==",
"dev": true,
- "license": "Apache-2.0",
+ "license": "MIT",
+ "bin": {
+ "image-size": "bin/image-size.js"
+ },
+ "engines": {
+ "node": ">=16.x"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
+ "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "esutils": "^2.0.2"
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
},
"engines": {
- "node": ">=0.10.0"
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/dunder-proto": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
- "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/inline-style-parser": {
+ "version": "0.2.7",
+ "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz",
+ "integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==",
+ "license": "MIT"
+ },
+ "node_modules/internal-slot": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz",
+ "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "call-bind-apply-helpers": "^1.0.1",
"es-errors": "^1.3.0",
- "gopd": "^1.2.0"
+ "hasown": "^2.0.2",
+ "side-channel": "^1.1.0"
},
"engines": {
"node": ">= 0.4"
}
},
- "node_modules/electron-to-chromium": {
- "version": "1.5.358",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.358.tgz",
- "integrity": "sha512-EO7tKm3QxRqTs1lSuPXzl6yRAwznehp0AH9OoMOIC+4mQzTFday8FJCO5KU6J/TFSQXEOahNq4vTKpz1jmCVOA==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/emoji-regex": {
- "version": "9.2.2",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
- "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+ "node_modules/ipaddr.js": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.4.0.tgz",
+ "integrity": "sha512-9VGk3HGanVE6JoZXHiCpnGy5X0jYDnN4EA4lntFPj+1vIWlFhIylq2CrrCOJH9EAhc5CYhq18F2Av2tgoAPsYQ==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10"
+ }
},
- "node_modules/emoji-regex-xs": {
+ "node_modules/is-alphabetical": {
"version": "2.0.1",
- "resolved": "https://registry.npmjs.org/emoji-regex-xs/-/emoji-regex-xs-2.0.1.tgz",
- "integrity": "sha512-1QFuh8l7LqUcKe24LsPUNzjrzJQ7pgRwp1QMcZ5MX6mFplk2zQ08NVCM84++1cveaUUYtcCYHmeFEuNg16sU4g==",
- "dev": true,
+ "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz",
+ "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==",
"license": "MIT",
- "engines": {
- "node": ">=10.0.0"
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
}
},
- "node_modules/enhanced-resolve": {
- "version": "5.21.3",
- "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.3.tgz",
- "integrity": "sha512-QyL119InA+XXEkNLNTPCXPugSvOfhwv0JOlGNzvxs0hZaiHLNvXSpudUWsOlsXGWJh8G6ckCScEkVHfX3kw/2Q==",
- "dev": true,
+ "node_modules/is-alphanumerical": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz",
+ "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==",
"license": "MIT",
"dependencies": {
- "graceful-fs": "^4.2.4",
- "tapable": "^2.3.3"
+ "is-alphabetical": "^2.0.0",
+ "is-decimal": "^2.0.0"
},
- "engines": {
- "node": ">=10.13.0"
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
}
},
- "node_modules/error-stack-parser-es": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/error-stack-parser-es/-/error-stack-parser-es-1.0.5.tgz",
- "integrity": "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==",
+ "node_modules/is-array-buffer": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
+ "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==",
"dev": true,
"license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "get-intrinsic": "^1.2.6"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
"funding": {
- "url": "https://github.com/sponsors/antfu"
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/es-abstract": {
- "version": "1.24.2",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz",
- "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==",
+ "node_modules/is-async-function": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz",
+ "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "array-buffer-byte-length": "^1.0.2",
- "arraybuffer.prototype.slice": "^1.0.4",
- "available-typed-arrays": "^1.0.7",
- "call-bind": "^1.0.8",
- "call-bound": "^1.0.4",
- "data-view-buffer": "^1.0.2",
- "data-view-byte-length": "^1.0.2",
- "data-view-byte-offset": "^1.0.1",
- "es-define-property": "^1.0.1",
- "es-errors": "^1.3.0",
- "es-object-atoms": "^1.1.1",
- "es-set-tostringtag": "^2.1.0",
- "es-to-primitive": "^1.3.0",
- "function.prototype.name": "^1.1.8",
- "get-intrinsic": "^1.3.0",
+ "async-function": "^1.0.0",
+ "call-bound": "^1.0.3",
"get-proto": "^1.0.1",
- "get-symbol-description": "^1.1.0",
- "globalthis": "^1.0.4",
- "gopd": "^1.2.0",
- "has-property-descriptors": "^1.0.2",
- "has-proto": "^1.2.0",
- "has-symbols": "^1.1.0",
- "hasown": "^2.0.2",
- "internal-slot": "^1.1.0",
- "is-array-buffer": "^3.0.5",
- "is-callable": "^1.2.7",
- "is-data-view": "^1.0.2",
- "is-negative-zero": "^2.0.3",
- "is-regex": "^1.2.1",
- "is-set": "^2.0.3",
- "is-shared-array-buffer": "^1.0.4",
- "is-string": "^1.1.1",
- "is-typed-array": "^1.1.15",
- "is-weakref": "^1.1.1",
- "math-intrinsics": "^1.1.0",
- "object-inspect": "^1.13.4",
- "object-keys": "^1.1.1",
- "object.assign": "^4.1.7",
- "own-keys": "^1.0.1",
- "regexp.prototype.flags": "^1.5.4",
- "safe-array-concat": "^1.1.3",
- "safe-push-apply": "^1.0.0",
- "safe-regex-test": "^1.1.0",
- "set-proto": "^1.0.0",
- "stop-iteration-iterator": "^1.1.0",
- "string.prototype.trim": "^1.2.10",
- "string.prototype.trimend": "^1.0.9",
- "string.prototype.trimstart": "^1.0.8",
- "typed-array-buffer": "^1.0.3",
- "typed-array-byte-length": "^1.0.3",
- "typed-array-byte-offset": "^1.0.4",
- "typed-array-length": "^1.0.7",
- "unbox-primitive": "^1.1.0",
- "which-typed-array": "^1.1.19"
+ "has-tostringtag": "^1.0.2",
+ "safe-regex-test": "^1.1.0"
},
"engines": {
"node": ">= 0.4"
@@ -4573,113 +6921,118 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/es-define-property": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
- "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+ "node_modules/is-bigint": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz",
+ "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==",
"dev": true,
"license": "MIT",
+ "dependencies": {
+ "has-bigints": "^1.0.2"
+ },
"engines": {
"node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/es-errors": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
- "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "node_modules/is-boolean-object": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz",
+ "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==",
"dev": true,
"license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "has-tostringtag": "^1.0.2"
+ },
"engines": {
"node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/es-iterator-helpers": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.3.2.tgz",
- "integrity": "sha512-HVLACW1TppGYjJ8H6/jqH/pqOtKRw6wMlrB23xfExmFWxFquAIWCmwoLsOyN96K4a5KbmOf5At9ZUO3GZbetAw==",
+ "node_modules/is-bun-module": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz",
+ "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "call-bind": "^1.0.9",
- "call-bound": "^1.0.4",
- "define-properties": "^1.2.1",
- "es-abstract": "^1.24.2",
- "es-errors": "^1.3.0",
- "es-set-tostringtag": "^2.1.0",
- "function-bind": "^1.1.2",
- "get-intrinsic": "^1.3.0",
- "globalthis": "^1.0.4",
- "gopd": "^1.2.0",
- "has-property-descriptors": "^1.0.2",
- "has-proto": "^1.2.0",
- "has-symbols": "^1.1.0",
- "internal-slot": "^1.1.0",
- "iterator.prototype": "^1.1.5",
- "math-intrinsics": "^1.1.0"
- },
- "engines": {
- "node": ">= 0.4"
+ "semver": "^7.7.1"
}
},
- "node_modules/es-module-lexer": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz",
- "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==",
+ "node_modules/is-bun-module/node_modules/semver": {
+ "version": "7.8.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.0.tgz",
+ "integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==",
"dev": true,
- "license": "MIT"
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
},
- "node_modules/es-object-atoms": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
- "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+ "node_modules/is-callable": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
+ "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0"
- },
"engines": {
"node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/es-set-tostringtag": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
- "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+ "node_modules/is-core-module": {
+ "version": "2.16.2",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz",
+ "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "es-errors": "^1.3.0",
- "get-intrinsic": "^1.2.6",
- "has-tostringtag": "^1.0.2",
- "hasown": "^2.0.2"
+ "hasown": "^2.0.3"
},
"engines": {
"node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/es-shim-unscopables": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz",
- "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==",
+ "node_modules/is-data-view": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz",
+ "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "hasown": "^2.0.2"
+ "call-bound": "^1.0.2",
+ "get-intrinsic": "^1.2.6",
+ "is-typed-array": "^1.1.13"
},
"engines": {
"node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/es-to-primitive": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz",
- "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==",
+ "node_modules/is-date-object": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz",
+ "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "is-callable": "^1.2.7",
- "is-date-object": "^1.0.5",
- "is-symbol": "^1.0.4"
+ "call-bound": "^1.0.2",
+ "has-tostringtag": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
@@ -4688,2299 +7041,2612 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/esbuild": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.0.tgz",
- "integrity": "sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==",
- "dev": true,
- "hasInstallScript": true,
+ "node_modules/is-decimal": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz",
+ "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==",
"license": "MIT",
- "optional": true,
- "peer": true,
- "bin": {
- "esbuild": "bin/esbuild"
- },
- "engines": {
- "node": ">=18"
- },
- "optionalDependencies": {
- "@esbuild/aix-ppc64": "0.28.0",
- "@esbuild/android-arm": "0.28.0",
- "@esbuild/android-arm64": "0.28.0",
- "@esbuild/android-x64": "0.28.0",
- "@esbuild/darwin-arm64": "0.28.0",
- "@esbuild/darwin-x64": "0.28.0",
- "@esbuild/freebsd-arm64": "0.28.0",
- "@esbuild/freebsd-x64": "0.28.0",
- "@esbuild/linux-arm": "0.28.0",
- "@esbuild/linux-arm64": "0.28.0",
- "@esbuild/linux-ia32": "0.28.0",
- "@esbuild/linux-loong64": "0.28.0",
- "@esbuild/linux-mips64el": "0.28.0",
- "@esbuild/linux-ppc64": "0.28.0",
- "@esbuild/linux-riscv64": "0.28.0",
- "@esbuild/linux-s390x": "0.28.0",
- "@esbuild/linux-x64": "0.28.0",
- "@esbuild/netbsd-arm64": "0.28.0",
- "@esbuild/netbsd-x64": "0.28.0",
- "@esbuild/openbsd-arm64": "0.28.0",
- "@esbuild/openbsd-x64": "0.28.0",
- "@esbuild/openharmony-arm64": "0.28.0",
- "@esbuild/sunos-x64": "0.28.0",
- "@esbuild/win32-arm64": "0.28.0",
- "@esbuild/win32-ia32": "0.28.0",
- "@esbuild/win32-x64": "0.28.0"
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
}
},
- "node_modules/escalade": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
- "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">=6"
+ "node": ">=0.10.0"
}
},
- "node_modules/escape-html": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
- "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/escape-string-regexp": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
- "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "node_modules/is-finalizationregistry": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz",
+ "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==",
"dev": true,
"license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3"
+ },
"engines": {
- "node": ">=10"
+ "node": ">= 0.4"
},
"funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/eslint": {
- "version": "9.39.4",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz",
- "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==",
+ "node_modules/is-generator-function": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz",
+ "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@eslint-community/eslint-utils": "^4.8.0",
- "@eslint-community/regexpp": "^4.12.1",
- "@eslint/config-array": "^0.21.2",
- "@eslint/config-helpers": "^0.4.2",
- "@eslint/core": "^0.17.0",
- "@eslint/eslintrc": "^3.3.5",
- "@eslint/js": "9.39.4",
- "@eslint/plugin-kit": "^0.4.1",
- "@humanfs/node": "^0.16.6",
- "@humanwhocodes/module-importer": "^1.0.1",
- "@humanwhocodes/retry": "^0.4.2",
- "@types/estree": "^1.0.6",
- "ajv": "^6.14.0",
- "chalk": "^4.0.0",
- "cross-spawn": "^7.0.6",
- "debug": "^4.3.2",
- "escape-string-regexp": "^4.0.0",
- "eslint-scope": "^8.4.0",
- "eslint-visitor-keys": "^4.2.1",
- "espree": "^10.4.0",
- "esquery": "^1.5.0",
- "esutils": "^2.0.2",
- "fast-deep-equal": "^3.1.3",
- "file-entry-cache": "^8.0.0",
- "find-up": "^5.0.0",
- "glob-parent": "^6.0.2",
- "ignore": "^5.2.0",
- "imurmurhash": "^0.1.4",
- "is-glob": "^4.0.0",
- "json-stable-stringify-without-jsonify": "^1.0.1",
- "lodash.merge": "^4.6.2",
- "minimatch": "^3.1.5",
- "natural-compare": "^1.4.0",
- "optionator": "^0.9.3"
- },
- "bin": {
- "eslint": "bin/eslint.js"
+ "call-bound": "^1.0.4",
+ "generator-function": "^2.0.0",
+ "get-proto": "^1.0.1",
+ "has-tostringtag": "^1.0.2",
+ "safe-regex-test": "^1.1.0"
},
"engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ "node": ">= 0.4"
},
"funding": {
- "url": "https://eslint.org/donate"
- },
- "peerDependencies": {
- "jiti": "*"
- },
- "peerDependenciesMeta": {
- "jiti": {
- "optional": true
- }
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/eslint-config-next": {
- "version": "16.2.6",
- "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-16.2.6.tgz",
- "integrity": "sha512-z2ELYSkyrrJ6cuunTU8vhsT/RpouPkjaSah06nVW6Rg2Hpg0Vs8s497/e5s8G8qtdp4ccsiovz5P1rv+5VSW2Q==",
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@next/eslint-plugin-next": "16.2.6",
- "eslint-import-resolver-node": "^0.3.6",
- "eslint-import-resolver-typescript": "^3.5.2",
- "eslint-plugin-import": "^2.32.0",
- "eslint-plugin-jsx-a11y": "^6.10.0",
- "eslint-plugin-react": "^7.37.0",
- "eslint-plugin-react-hooks": "^7.0.0",
- "globals": "16.4.0",
- "typescript-eslint": "^8.46.0"
- },
- "peerDependencies": {
- "eslint": ">=9.0.0",
- "typescript": ">=3.3.1"
+ "is-extglob": "^2.1.1"
},
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "node_modules/eslint-config-next/node_modules/globals": {
- "version": "16.4.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-16.4.0.tgz",
- "integrity": "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==",
+ "node_modules/is-hexadecimal": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz",
+ "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/is-map": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz",
+ "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">=18"
+ "node": ">= 0.4"
},
"funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/eslint-import-resolver-node": {
- "version": "0.3.10",
- "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.10.tgz",
- "integrity": "sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ==",
+ "node_modules/is-negative-zero": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz",
+ "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "debug": "^3.2.7",
- "is-core-module": "^2.16.1",
- "resolve": "^2.0.0-next.6"
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/eslint-import-resolver-node/node_modules/debug": {
- "version": "3.2.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
- "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "ms": "^2.1.1"
+ "engines": {
+ "node": ">=0.12.0"
}
},
- "node_modules/eslint-import-resolver-typescript": {
- "version": "3.10.1",
- "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.10.1.tgz",
- "integrity": "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==",
+ "node_modules/is-number-object": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz",
+ "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==",
"dev": true,
- "license": "ISC",
+ "license": "MIT",
"dependencies": {
- "@nolyfill/is-core-module": "1.0.39",
- "debug": "^4.4.0",
- "get-tsconfig": "^4.10.0",
- "is-bun-module": "^2.0.0",
- "stable-hash": "^0.0.5",
- "tinyglobby": "^0.2.13",
- "unrs-resolver": "^1.6.2"
+ "call-bound": "^1.0.3",
+ "has-tostringtag": "^1.0.2"
},
"engines": {
- "node": "^14.18.0 || >=16.0.0"
+ "node": ">= 0.4"
},
"funding": {
- "url": "https://opencollective.com/eslint-import-resolver-typescript"
- },
- "peerDependencies": {
- "eslint": "*",
- "eslint-plugin-import": "*",
- "eslint-plugin-import-x": "*"
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-plain-obj": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz",
+ "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
},
- "peerDependenciesMeta": {
- "eslint-plugin-import": {
- "optional": true
- },
- "eslint-plugin-import-x": {
- "optional": true
- }
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/eslint-module-utils": {
- "version": "2.12.1",
- "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz",
- "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==",
+ "node_modules/is-regex": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
+ "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "debug": "^3.2.7"
+ "call-bound": "^1.0.2",
+ "gopd": "^1.2.0",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
},
"engines": {
- "node": ">=4"
+ "node": ">= 0.4"
},
- "peerDependenciesMeta": {
- "eslint": {
- "optional": true
- }
- }
- },
- "node_modules/eslint-module-utils/node_modules/debug": {
- "version": "3.2.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
- "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-set": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz",
+ "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "ms": "^2.1.1"
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/eslint-plugin-import": {
- "version": "2.32.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz",
- "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==",
+ "node_modules/is-shared-array-buffer": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz",
+ "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@rtsao/scc": "^1.1.0",
- "array-includes": "^3.1.9",
- "array.prototype.findlastindex": "^1.2.6",
- "array.prototype.flat": "^1.3.3",
- "array.prototype.flatmap": "^1.3.3",
- "debug": "^3.2.7",
- "doctrine": "^2.1.0",
- "eslint-import-resolver-node": "^0.3.9",
- "eslint-module-utils": "^2.12.1",
- "hasown": "^2.0.2",
- "is-core-module": "^2.16.1",
- "is-glob": "^4.0.3",
- "minimatch": "^3.1.2",
- "object.fromentries": "^2.0.8",
- "object.groupby": "^1.0.3",
- "object.values": "^1.2.1",
- "semver": "^6.3.1",
- "string.prototype.trimend": "^1.0.9",
- "tsconfig-paths": "^3.15.0"
+ "call-bound": "^1.0.3"
},
"engines": {
- "node": ">=4"
+ "node": ">= 0.4"
},
- "peerDependencies": {
- "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9"
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/eslint-plugin-import/node_modules/debug": {
- "version": "3.2.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
- "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "node_modules/is-string": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz",
+ "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "ms": "^2.1.1"
+ "call-bound": "^1.0.3",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/eslint-plugin-jsx-a11y": {
- "version": "6.10.2",
- "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz",
- "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==",
+ "node_modules/is-symbol": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz",
+ "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==",
"dev": true,
"license": "MIT",
"dependencies": {
- "aria-query": "^5.3.2",
- "array-includes": "^3.1.8",
- "array.prototype.flatmap": "^1.3.2",
- "ast-types-flow": "^0.0.8",
- "axe-core": "^4.10.0",
- "axobject-query": "^4.1.0",
- "damerau-levenshtein": "^1.0.8",
- "emoji-regex": "^9.2.2",
- "hasown": "^2.0.2",
- "jsx-ast-utils": "^3.3.5",
- "language-tags": "^1.0.9",
- "minimatch": "^3.1.2",
- "object.fromentries": "^2.0.8",
- "safe-regex-test": "^1.0.3",
- "string.prototype.includes": "^2.0.1"
+ "call-bound": "^1.0.2",
+ "has-symbols": "^1.1.0",
+ "safe-regex-test": "^1.1.0"
},
"engines": {
- "node": ">=4.0"
+ "node": ">= 0.4"
},
- "peerDependencies": {
- "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9"
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/eslint-plugin-react": {
- "version": "7.37.5",
- "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz",
- "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==",
+ "node_modules/is-typed-array": {
+ "version": "1.1.15",
+ "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz",
+ "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "array-includes": "^3.1.8",
- "array.prototype.findlast": "^1.2.5",
- "array.prototype.flatmap": "^1.3.3",
- "array.prototype.tosorted": "^1.1.4",
- "doctrine": "^2.1.0",
- "es-iterator-helpers": "^1.2.1",
- "estraverse": "^5.3.0",
- "hasown": "^2.0.2",
- "jsx-ast-utils": "^2.4.1 || ^3.0.0",
- "minimatch": "^3.1.2",
- "object.entries": "^1.1.9",
- "object.fromentries": "^2.0.8",
- "object.values": "^1.2.1",
- "prop-types": "^15.8.1",
- "resolve": "^2.0.0-next.5",
- "semver": "^6.3.1",
- "string.prototype.matchall": "^4.0.12",
- "string.prototype.repeat": "^1.0.0"
+ "which-typed-array": "^1.1.16"
},
"engines": {
- "node": ">=4"
+ "node": ">= 0.4"
},
- "peerDependencies": {
- "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7"
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/eslint-plugin-react-hooks": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.1.1.tgz",
- "integrity": "sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==",
+ "node_modules/is-weakmap": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz",
+ "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "@babel/core": "^7.24.4",
- "@babel/parser": "^7.24.4",
- "hermes-parser": "^0.25.1",
- "zod": "^3.25.0 || ^4.0.0",
- "zod-validation-error": "^3.5.0 || ^4.0.0"
- },
"engines": {
- "node": ">=18"
+ "node": ">= 0.4"
},
- "peerDependencies": {
- "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0"
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/eslint-scope": {
- "version": "8.4.0",
- "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz",
- "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
+ "node_modules/is-weakref": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz",
+ "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==",
"dev": true,
- "license": "BSD-2-Clause",
+ "license": "MIT",
"dependencies": {
- "esrecurse": "^4.3.0",
- "estraverse": "^5.2.0"
+ "call-bound": "^1.0.3"
},
"engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ "node": ">= 0.4"
},
"funding": {
- "url": "https://opencollective.com/eslint"
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/eslint-visitor-keys": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
- "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
+ "node_modules/is-weakset": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz",
+ "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==",
"dev": true,
- "license": "Apache-2.0",
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "get-intrinsic": "^1.2.6"
+ },
"engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ "node": ">= 0.4"
},
"funding": {
- "url": "https://opencollective.com/eslint"
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/espree": {
- "version": "10.4.0",
- "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
- "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
+ "node_modules/isarray": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
+ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
"dev": true,
- "license": "BSD-2-Clause",
+ "license": "MIT"
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/iterator.prototype": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz",
+ "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "acorn": "^8.15.0",
- "acorn-jsx": "^5.3.2",
- "eslint-visitor-keys": "^4.2.1"
+ "define-data-property": "^1.1.4",
+ "es-object-atoms": "^1.0.0",
+ "get-intrinsic": "^1.2.6",
+ "get-proto": "^1.0.0",
+ "has-symbols": "^1.1.0",
+ "set-function-name": "^2.0.2"
},
"engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
+ "node": ">= 0.4"
}
},
- "node_modules/esquery": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz",
- "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==",
- "dev": true,
- "license": "BSD-3-Clause",
+ "node_modules/jest-worker": {
+ "version": "27.5.1",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz",
+ "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==",
+ "devOptional": true,
+ "license": "MIT",
+ "peer": true,
"dependencies": {
- "estraverse": "^5.1.0"
+ "@types/node": "*",
+ "merge-stream": "^2.0.0",
+ "supports-color": "^8.0.0"
},
"engines": {
- "node": ">=0.10"
+ "node": ">= 10.13.0"
}
},
- "node_modules/esrecurse": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
- "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
- "dev": true,
- "license": "BSD-2-Clause",
+ "node_modules/jest-worker/node_modules/supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "devOptional": true,
+ "license": "MIT",
+ "peer": true,
"dependencies": {
- "estraverse": "^5.2.0"
+ "has-flag": "^4.0.0"
},
"engines": {
- "node": ">=4.0"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
}
},
- "node_modules/estraverse": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
- "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "node_modules/jiti": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz",
+ "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==",
"dev": true,
- "license": "BSD-2-Clause",
- "engines": {
- "node": ">=4.0"
+ "license": "MIT",
+ "bin": {
+ "jiti": "lib/jiti-cli.mjs"
}
},
- "node_modules/estree-walker": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
- "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/js-yaml": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz",
+ "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==",
"dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/puzrin"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/nodeca"
+ }
+ ],
"license": "MIT",
"dependencies": {
- "@types/estree": "^1.0.0"
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
}
},
- "node_modules/esutils": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
- "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "node_modules/jsesc": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
+ "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
"dev": true,
- "license": "BSD-2-Clause",
+ "license": "MIT",
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
"engines": {
- "node": ">=0.10.0"
+ "node": ">=6"
}
},
- "node_modules/events": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
- "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
"dev": true,
- "license": "MIT",
- "peer": true,
- "engines": {
- "node": ">=0.8.x"
- }
+ "license": "MIT"
},
- "node_modules/fast-deep-equal": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
- "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
"dev": true,
"license": "MIT"
},
- "node_modules/fast-glob": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz",
- "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==",
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json5": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "@nodelib/fs.stat": "^2.0.2",
- "@nodelib/fs.walk": "^1.2.3",
- "glob-parent": "^5.1.2",
- "merge2": "^1.3.0",
- "micromatch": "^4.0.4"
+ "bin": {
+ "json5": "lib/cli.js"
},
"engines": {
- "node": ">=8.6.0"
+ "node": ">=6"
}
},
- "node_modules/fast-glob/node_modules/glob-parent": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "node_modules/jsx-ast-utils": {
+ "version": "3.3.5",
+ "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
+ "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==",
"dev": true,
- "license": "ISC",
+ "license": "MIT",
"dependencies": {
- "is-glob": "^4.0.1"
+ "array-includes": "^3.1.6",
+ "array.prototype.flat": "^1.3.1",
+ "object.assign": "^4.1.4",
+ "object.values": "^1.1.6"
},
"engines": {
- "node": ">= 6"
+ "node": ">=4.0"
}
},
- "node_modules/fast-json-stable-stringify": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
- "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/fast-levenshtein": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
- "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/fast-uri": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz",
- "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==",
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
"dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/fastify"
- },
- {
- "type": "opencollective",
- "url": "https://opencollective.com/fastify"
- }
- ],
- "license": "BSD-3-Clause",
- "peer": true
+ "license": "MIT",
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
},
- "node_modules/fastq": {
- "version": "1.20.1",
- "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz",
- "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==",
+ "node_modules/kleur": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
+ "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==",
"dev": true,
- "license": "ISC",
- "dependencies": {
- "reusify": "^1.0.4"
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
}
},
- "node_modules/fflate": {
- "version": "0.7.4",
- "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.7.4.tgz",
- "integrity": "sha512-5u2V/CDW15QM1XbbgS+0DfPxVB+jUKhWEKuuFuHncbk3tEEqzmoXL+2KyOFuKGqOnmdIy0/davWF1CkuwtibCw==",
+ "node_modules/language-subtag-registry": {
+ "version": "0.3.23",
+ "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz",
+ "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==",
"dev": true,
- "license": "MIT"
+ "license": "CC0-1.0"
},
- "node_modules/file-entry-cache": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
- "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
+ "node_modules/language-tags": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz",
+ "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "flat-cache": "^4.0.0"
+ "language-subtag-registry": "^0.3.20"
},
"engines": {
- "node": ">=16.0.0"
+ "node": ">=0.10"
}
},
- "node_modules/fill-range": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
- "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "to-regex-range": "^5.0.1"
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
},
"engines": {
- "node": ">=8"
+ "node": ">= 0.8.0"
}
},
- "node_modules/find-up": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
- "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "node_modules/lightningcss": {
+ "version": "1.31.1",
+ "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.31.1.tgz",
+ "integrity": "sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ==",
"dev": true,
- "license": "MIT",
+ "license": "MPL-2.0",
"dependencies": {
- "locate-path": "^6.0.0",
- "path-exists": "^4.0.0"
+ "detect-libc": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
},
+ "optionalDependencies": {
+ "lightningcss-android-arm64": "1.31.1",
+ "lightningcss-darwin-arm64": "1.31.1",
+ "lightningcss-darwin-x64": "1.31.1",
+ "lightningcss-freebsd-x64": "1.31.1",
+ "lightningcss-linux-arm-gnueabihf": "1.31.1",
+ "lightningcss-linux-arm64-gnu": "1.31.1",
+ "lightningcss-linux-arm64-musl": "1.31.1",
+ "lightningcss-linux-x64-gnu": "1.31.1",
+ "lightningcss-linux-x64-musl": "1.31.1",
+ "lightningcss-win32-arm64-msvc": "1.31.1",
+ "lightningcss-win32-x64-msvc": "1.31.1"
+ }
+ },
+ "node_modules/lightningcss-android-arm64": {
+ "version": "1.31.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.31.1.tgz",
+ "integrity": "sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "android"
+ ],
"engines": {
- "node": ">=10"
+ "node": ">= 12.0.0"
},
"funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
}
},
- "node_modules/flat-cache": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
- "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
+ "node_modules/lightningcss-darwin-arm64": {
+ "version": "1.31.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.31.1.tgz",
+ "integrity": "sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg==",
+ "cpu": [
+ "arm64"
+ ],
"dev": true,
- "license": "MIT",
- "dependencies": {
- "flatted": "^3.2.9",
- "keyv": "^4.5.4"
- },
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
"engines": {
- "node": ">=16"
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
}
},
- "node_modules/flatted": {
- "version": "3.4.2",
- "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz",
- "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==",
+ "node_modules/lightningcss-darwin-x64": {
+ "version": "1.31.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.31.1.tgz",
+ "integrity": "sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA==",
+ "cpu": [
+ "x64"
+ ],
"dev": true,
- "license": "ISC"
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
},
- "node_modules/for-each": {
- "version": "0.3.5",
- "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
- "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
+ "node_modules/lightningcss-freebsd-x64": {
+ "version": "1.31.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.31.1.tgz",
+ "integrity": "sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A==",
+ "cpu": [
+ "x64"
+ ],
"dev": true,
- "license": "MIT",
- "dependencies": {
- "is-callable": "^1.2.7"
- },
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
"engines": {
- "node": ">= 0.4"
+ "node": ">= 12.0.0"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
}
},
- "node_modules/fsevents": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
- "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "node_modules/lightningcss-linux-arm-gnueabihf": {
+ "version": "1.31.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.31.1.tgz",
+ "integrity": "sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g==",
+ "cpu": [
+ "arm"
+ ],
"dev": true,
- "hasInstallScript": true,
- "license": "MIT",
+ "license": "MPL-2.0",
"optional": true,
"os": [
- "darwin"
+ "linux"
],
"engines": {
- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
}
},
- "node_modules/function-bind": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
- "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "node_modules/lightningcss-linux-arm64-gnu": {
+ "version": "1.31.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.31.1.tgz",
+ "integrity": "sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==",
+ "cpu": [
+ "arm64"
+ ],
"dev": true,
- "license": "MIT",
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
}
},
- "node_modules/function.prototype.name": {
- "version": "1.1.8",
- "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz",
- "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==",
+ "node_modules/lightningcss-linux-arm64-musl": {
+ "version": "1.31.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.31.1.tgz",
+ "integrity": "sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==",
+ "cpu": [
+ "arm64"
+ ],
"dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.8",
- "call-bound": "^1.0.3",
- "define-properties": "^1.2.1",
- "functions-have-names": "^1.2.3",
- "hasown": "^2.0.2",
- "is-callable": "^1.2.7"
- },
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
"engines": {
- "node": ">= 0.4"
+ "node": ">= 12.0.0"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
}
},
- "node_modules/functions-have-names": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
- "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
+ "node_modules/lightningcss-linux-x64-gnu": {
+ "version": "1.31.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.31.1.tgz",
+ "integrity": "sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==",
+ "cpu": [
+ "x64"
+ ],
"dev": true,
- "license": "MIT",
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
}
},
- "node_modules/generator-function": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz",
- "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==",
+ "node_modules/lightningcss-linux-x64-musl": {
+ "version": "1.31.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.31.1.tgz",
+ "integrity": "sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==",
+ "cpu": [
+ "x64"
+ ],
"dev": true,
- "license": "MIT",
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
"engines": {
- "node": ">= 0.4"
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
}
},
- "node_modules/gensync": {
- "version": "1.0.0-beta.2",
- "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
- "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "node_modules/lightningcss-win32-arm64-msvc": {
+ "version": "1.31.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.31.1.tgz",
+ "integrity": "sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==",
+ "cpu": [
+ "arm64"
+ ],
"dev": true,
- "license": "MIT",
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
"engines": {
- "node": ">=6.9.0"
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
}
},
- "node_modules/get-intrinsic": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
- "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+ "node_modules/lightningcss-win32-x64-msvc": {
+ "version": "1.31.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.31.1.tgz",
+ "integrity": "sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw==",
+ "cpu": [
+ "x64"
+ ],
"dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bind-apply-helpers": "^1.0.2",
- "es-define-property": "^1.0.1",
- "es-errors": "^1.3.0",
- "es-object-atoms": "^1.1.1",
- "function-bind": "^1.1.2",
- "get-proto": "^1.0.1",
- "gopd": "^1.2.0",
- "has-symbols": "^1.1.0",
- "hasown": "^2.0.2",
- "math-intrinsics": "^1.1.0"
- },
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
"engines": {
- "node": ">= 0.4"
+ "node": ">= 12.0.0"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
}
},
- "node_modules/get-proto": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
- "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+ "node_modules/linebreak": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/linebreak/-/linebreak-1.1.0.tgz",
+ "integrity": "sha512-MHp03UImeVhB7XZtjd0E4n6+3xr5Dq/9xI/5FptGk5FrbDR3zagPa2DS6U8ks/3HjbKWG9Q1M2ufOzxV2qLYSQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "dunder-proto": "^1.0.1",
- "es-object-atoms": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
+ "base64-js": "0.0.8",
+ "unicode-trie": "^2.0.0"
}
},
- "node_modules/get-symbol-description": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz",
- "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==",
- "dev": true,
+ "node_modules/loader-runner": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.2.tgz",
+ "integrity": "sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w==",
+ "devOptional": true,
"license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.3",
- "es-errors": "^1.3.0",
- "get-intrinsic": "^1.2.6"
- },
+ "peer": true,
"engines": {
- "node": ">= 0.4"
+ "node": ">=6.11.5"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
}
},
- "node_modules/get-tsconfig": {
- "version": "4.14.0",
- "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.0.tgz",
- "integrity": "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==",
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "resolve-pkg-maps": "^1.0.0"
- },
- "funding": {
- "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
- }
- },
- "node_modules/glob-parent": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
- "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "is-glob": "^4.0.3"
+ "p-locate": "^5.0.0"
},
"engines": {
- "node": ">=10.13.0"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/glob-to-regexp": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
- "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==",
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
"dev": true,
- "license": "BSD-2-Clause",
- "peer": true
+ "license": "MIT"
},
- "node_modules/globals": {
- "version": "14.0.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
- "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
- "dev": true,
+ "node_modules/longest-streak": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz",
+ "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==",
"license": "MIT",
- "engines": {
- "node": ">=18"
- },
"funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
}
},
- "node_modules/globalthis": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz",
- "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==",
+ "node_modules/loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
"dev": true,
"license": "MIT",
"dependencies": {
- "define-properties": "^1.2.1",
- "gopd": "^1.0.1"
- },
- "engines": {
- "node": ">= 0.4"
+ "js-tokens": "^3.0.0 || ^4.0.0"
},
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "bin": {
+ "loose-envify": "cli.js"
}
},
- "node_modules/globrex": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz",
- "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==",
+ "node_modules/lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
"dev": true,
- "license": "MIT"
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^3.0.2"
+ }
},
- "node_modules/gopd": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
- "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+ "node_modules/magic-string": {
+ "version": "0.30.21",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
+ "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
"dev": true,
"license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.5"
+ }
+ },
+ "node_modules/markdown-extensions": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/markdown-extensions/-/markdown-extensions-2.0.0.tgz",
+ "integrity": "sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==",
+ "license": "MIT",
"engines": {
- "node": ">= 0.4"
+ "node": ">=16"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/graceful-fs": {
- "version": "4.2.11",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
- "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/has-bigints": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz",
- "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==",
- "dev": true,
+ "node_modules/markdown-table": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz",
+ "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==",
"license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
}
},
- "node_modules/has-flag": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
- "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "node_modules/math-intrinsics": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+ "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">=8"
+ "node": ">= 0.4"
}
},
- "node_modules/has-property-descriptors": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
- "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
- "dev": true,
+ "node_modules/mdast-util-find-and-replace": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz",
+ "integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==",
"license": "MIT",
"dependencies": {
- "es-define-property": "^1.0.0"
+ "@types/mdast": "^4.0.0",
+ "escape-string-regexp": "^5.0.0",
+ "unist-util-is": "^6.0.0",
+ "unist-util-visit-parents": "^6.0.0"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
- "node_modules/has-proto": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz",
- "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==",
- "dev": true,
+ "node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
+ "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==",
"license": "MIT",
- "dependencies": {
- "dunder-proto": "^1.0.0"
- },
"engines": {
- "node": ">= 0.4"
+ "node": ">=12"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/has-symbols": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
- "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
- "dev": true,
+ "node_modules/mdast-util-from-markdown": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.3.tgz",
+ "integrity": "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==",
"license": "MIT",
- "engines": {
- "node": ">= 0.4"
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "@types/unist": "^3.0.0",
+ "decode-named-character-reference": "^1.0.0",
+ "devlop": "^1.0.0",
+ "mdast-util-to-string": "^4.0.0",
+ "micromark": "^4.0.0",
+ "micromark-util-decode-numeric-character-reference": "^2.0.0",
+ "micromark-util-decode-string": "^2.0.0",
+ "micromark-util-normalize-identifier": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0",
+ "unist-util-stringify-position": "^4.0.0"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
- "node_modules/has-tostringtag": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
- "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
- "dev": true,
+ "node_modules/mdast-util-gfm": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz",
+ "integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==",
"license": "MIT",
"dependencies": {
- "has-symbols": "^1.0.3"
- },
- "engines": {
- "node": ">= 0.4"
+ "mdast-util-from-markdown": "^2.0.0",
+ "mdast-util-gfm-autolink-literal": "^2.0.0",
+ "mdast-util-gfm-footnote": "^2.0.0",
+ "mdast-util-gfm-strikethrough": "^2.0.0",
+ "mdast-util-gfm-table": "^2.0.0",
+ "mdast-util-gfm-task-list-item": "^2.0.0",
+ "mdast-util-to-markdown": "^2.0.0"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
- "node_modules/hasown": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz",
- "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==",
- "dev": true,
+ "node_modules/mdast-util-gfm-autolink-literal": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz",
+ "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==",
"license": "MIT",
"dependencies": {
- "function-bind": "^1.1.2"
+ "@types/mdast": "^4.0.0",
+ "ccount": "^2.0.0",
+ "devlop": "^1.0.0",
+ "mdast-util-find-and-replace": "^3.0.0",
+ "micromark-util-character": "^2.0.0"
},
- "engines": {
- "node": ">= 0.4"
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
- "node_modules/hermes-estree": {
- "version": "0.25.1",
- "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz",
- "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/hermes-parser": {
- "version": "0.25.1",
- "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz",
- "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==",
- "dev": true,
+ "node_modules/mdast-util-gfm-footnote": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz",
+ "integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==",
"license": "MIT",
"dependencies": {
- "hermes-estree": "0.25.1"
+ "@types/mdast": "^4.0.0",
+ "devlop": "^1.1.0",
+ "mdast-util-from-markdown": "^2.0.0",
+ "mdast-util-to-markdown": "^2.0.0",
+ "micromark-util-normalize-identifier": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
- "node_modules/hex-rgb": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/hex-rgb/-/hex-rgb-4.3.0.tgz",
- "integrity": "sha512-Ox1pJVrDCyGHMG9CFg1tmrRUMRPRsAWYc/PinY0XzJU4K7y7vjNoLKIQ7BR5UJMCxNN8EM1MNDmHWA/B3aZUuw==",
- "dev": true,
+ "node_modules/mdast-util-gfm-strikethrough": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz",
+ "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==",
"license": "MIT",
- "engines": {
- "node": ">=6"
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "mdast-util-from-markdown": "^2.0.0",
+ "mdast-util-to-markdown": "^2.0.0"
},
"funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
- "node_modules/ignore": {
- "version": "5.3.2",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
- "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
- "dev": true,
+ "node_modules/mdast-util-gfm-table": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz",
+ "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==",
"license": "MIT",
- "engines": {
- "node": ">= 4"
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "devlop": "^1.0.0",
+ "markdown-table": "^3.0.0",
+ "mdast-util-from-markdown": "^2.0.0",
+ "mdast-util-to-markdown": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
- "node_modules/image-size": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/image-size/-/image-size-2.0.2.tgz",
- "integrity": "sha512-IRqXKlaXwgSMAMtpNzZa1ZAe8m+Sa1770Dhk8VkSsP9LS+iHD62Zd8FQKs8fbPiagBE7BzoFX23cxFnwshpV6w==",
- "dev": true,
+ "node_modules/mdast-util-gfm-task-list-item": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz",
+ "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==",
"license": "MIT",
- "bin": {
- "image-size": "bin/image-size.js"
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "devlop": "^1.0.0",
+ "mdast-util-from-markdown": "^2.0.0",
+ "mdast-util-to-markdown": "^2.0.0"
},
- "engines": {
- "node": ">=16.x"
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
- "node_modules/import-fresh": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
- "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
- "dev": true,
+ "node_modules/mdast-util-mdx": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz",
+ "integrity": "sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==",
"license": "MIT",
"dependencies": {
- "parent-module": "^1.0.0",
- "resolve-from": "^4.0.0"
- },
- "engines": {
- "node": ">=6"
+ "mdast-util-from-markdown": "^2.0.0",
+ "mdast-util-mdx-expression": "^2.0.0",
+ "mdast-util-mdx-jsx": "^3.0.0",
+ "mdast-util-mdxjs-esm": "^2.0.0",
+ "mdast-util-to-markdown": "^2.0.0"
},
"funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
- "node_modules/imurmurhash": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
- "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
- "dev": true,
+ "node_modules/mdast-util-mdx-expression": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz",
+ "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==",
"license": "MIT",
- "engines": {
- "node": ">=0.8.19"
+ "dependencies": {
+ "@types/estree-jsx": "^1.0.0",
+ "@types/hast": "^3.0.0",
+ "@types/mdast": "^4.0.0",
+ "devlop": "^1.0.0",
+ "mdast-util-from-markdown": "^2.0.0",
+ "mdast-util-to-markdown": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
- "node_modules/internal-slot": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz",
- "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==",
- "dev": true,
+ "node_modules/mdast-util-mdx-jsx": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz",
+ "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==",
"license": "MIT",
"dependencies": {
- "es-errors": "^1.3.0",
- "hasown": "^2.0.2",
- "side-channel": "^1.1.0"
+ "@types/estree-jsx": "^1.0.0",
+ "@types/hast": "^3.0.0",
+ "@types/mdast": "^4.0.0",
+ "@types/unist": "^3.0.0",
+ "ccount": "^2.0.0",
+ "devlop": "^1.1.0",
+ "mdast-util-from-markdown": "^2.0.0",
+ "mdast-util-to-markdown": "^2.0.0",
+ "parse-entities": "^4.0.0",
+ "stringify-entities": "^4.0.0",
+ "unist-util-stringify-position": "^4.0.0",
+ "vfile-message": "^4.0.0"
},
- "engines": {
- "node": ">= 0.4"
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
- "node_modules/ipaddr.js": {
- "version": "2.4.0",
- "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.4.0.tgz",
- "integrity": "sha512-9VGk3HGanVE6JoZXHiCpnGy5X0jYDnN4EA4lntFPj+1vIWlFhIylq2CrrCOJH9EAhc5CYhq18F2Av2tgoAPsYQ==",
- "dev": true,
+ "node_modules/mdast-util-mdxjs-esm": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz",
+ "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==",
"license": "MIT",
- "engines": {
- "node": ">= 10"
+ "dependencies": {
+ "@types/estree-jsx": "^1.0.0",
+ "@types/hast": "^3.0.0",
+ "@types/mdast": "^4.0.0",
+ "devlop": "^1.0.0",
+ "mdast-util-from-markdown": "^2.0.0",
+ "mdast-util-to-markdown": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
- "node_modules/is-array-buffer": {
- "version": "3.0.5",
- "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
- "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==",
- "dev": true,
+ "node_modules/mdast-util-phrasing": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz",
+ "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==",
"license": "MIT",
"dependencies": {
- "call-bind": "^1.0.8",
- "call-bound": "^1.0.3",
- "get-intrinsic": "^1.2.6"
- },
- "engines": {
- "node": ">= 0.4"
+ "@types/mdast": "^4.0.0",
+ "unist-util-is": "^6.0.0"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
- "node_modules/is-async-function": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz",
- "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==",
- "dev": true,
+ "node_modules/mdast-util-to-hast": {
+ "version": "13.2.1",
+ "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz",
+ "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==",
"license": "MIT",
"dependencies": {
- "async-function": "^1.0.0",
- "call-bound": "^1.0.3",
- "get-proto": "^1.0.1",
- "has-tostringtag": "^1.0.2",
- "safe-regex-test": "^1.1.0"
- },
- "engines": {
- "node": ">= 0.4"
+ "@types/hast": "^3.0.0",
+ "@types/mdast": "^4.0.0",
+ "@ungap/structured-clone": "^1.0.0",
+ "devlop": "^1.0.0",
+ "micromark-util-sanitize-uri": "^2.0.0",
+ "trim-lines": "^3.0.0",
+ "unist-util-position": "^5.0.0",
+ "unist-util-visit": "^5.0.0",
+ "vfile": "^6.0.0"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
- "node_modules/is-bigint": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz",
- "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==",
- "dev": true,
+ "node_modules/mdast-util-to-markdown": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz",
+ "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==",
"license": "MIT",
"dependencies": {
- "has-bigints": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
+ "@types/mdast": "^4.0.0",
+ "@types/unist": "^3.0.0",
+ "longest-streak": "^3.0.0",
+ "mdast-util-phrasing": "^4.0.0",
+ "mdast-util-to-string": "^4.0.0",
+ "micromark-util-classify-character": "^2.0.0",
+ "micromark-util-decode-string": "^2.0.0",
+ "unist-util-visit": "^5.0.0",
+ "zwitch": "^2.0.0"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
- "node_modules/is-boolean-object": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz",
- "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==",
- "dev": true,
+ "node_modules/mdast-util-to-string": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz",
+ "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==",
"license": "MIT",
"dependencies": {
- "call-bound": "^1.0.3",
- "has-tostringtag": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
+ "@types/mdast": "^4.0.0"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
- "node_modules/is-bun-module": {
+ "node_modules/merge-stream": {
"version": "2.0.0",
- "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz",
- "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+ "devOptional": true,
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
"dev": true,
"license": "MIT",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/micromark": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz",
+ "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
"dependencies": {
- "semver": "^7.7.1"
+ "@types/debug": "^4.0.0",
+ "debug": "^4.0.0",
+ "decode-named-character-reference": "^1.0.0",
+ "devlop": "^1.0.0",
+ "micromark-core-commonmark": "^2.0.0",
+ "micromark-factory-space": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-chunked": "^2.0.0",
+ "micromark-util-combine-extensions": "^2.0.0",
+ "micromark-util-decode-numeric-character-reference": "^2.0.0",
+ "micromark-util-encode": "^2.0.0",
+ "micromark-util-normalize-identifier": "^2.0.0",
+ "micromark-util-resolve-all": "^2.0.0",
+ "micromark-util-sanitize-uri": "^2.0.0",
+ "micromark-util-subtokenize": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
}
},
- "node_modules/is-bun-module/node_modules/semver": {
- "version": "7.8.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.0.tgz",
- "integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
+ "node_modules/micromark-core-commonmark": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz",
+ "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "decode-named-character-reference": "^1.0.0",
+ "devlop": "^1.0.0",
+ "micromark-factory-destination": "^2.0.0",
+ "micromark-factory-label": "^2.0.0",
+ "micromark-factory-space": "^2.0.0",
+ "micromark-factory-title": "^2.0.0",
+ "micromark-factory-whitespace": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-chunked": "^2.0.0",
+ "micromark-util-classify-character": "^2.0.0",
+ "micromark-util-html-tag-name": "^2.0.0",
+ "micromark-util-normalize-identifier": "^2.0.0",
+ "micromark-util-resolve-all": "^2.0.0",
+ "micromark-util-subtokenize": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
}
},
- "node_modules/is-callable": {
- "version": "1.2.7",
- "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
- "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
- "dev": true,
+ "node_modules/micromark-extension-gfm": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz",
+ "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==",
"license": "MIT",
- "engines": {
- "node": ">= 0.4"
+ "dependencies": {
+ "micromark-extension-gfm-autolink-literal": "^2.0.0",
+ "micromark-extension-gfm-footnote": "^2.0.0",
+ "micromark-extension-gfm-strikethrough": "^2.0.0",
+ "micromark-extension-gfm-table": "^2.0.0",
+ "micromark-extension-gfm-tagfilter": "^2.0.0",
+ "micromark-extension-gfm-task-list-item": "^2.0.0",
+ "micromark-util-combine-extensions": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
- "node_modules/is-core-module": {
- "version": "2.16.2",
- "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz",
- "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==",
- "dev": true,
+ "node_modules/micromark-extension-gfm-autolink-literal": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz",
+ "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==",
"license": "MIT",
"dependencies": {
- "hasown": "^2.0.3"
- },
- "engines": {
- "node": ">= 0.4"
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-sanitize-uri": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
- "node_modules/is-data-view": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz",
- "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==",
- "dev": true,
+ "node_modules/micromark-extension-gfm-footnote": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz",
+ "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==",
"license": "MIT",
"dependencies": {
- "call-bound": "^1.0.2",
- "get-intrinsic": "^1.2.6",
- "is-typed-array": "^1.1.13"
- },
- "engines": {
- "node": ">= 0.4"
+ "devlop": "^1.0.0",
+ "micromark-core-commonmark": "^2.0.0",
+ "micromark-factory-space": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-normalize-identifier": "^2.0.0",
+ "micromark-util-sanitize-uri": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
- "node_modules/is-date-object": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz",
- "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==",
- "dev": true,
+ "node_modules/micromark-extension-gfm-strikethrough": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz",
+ "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==",
"license": "MIT",
"dependencies": {
- "call-bound": "^1.0.2",
- "has-tostringtag": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
+ "devlop": "^1.0.0",
+ "micromark-util-chunked": "^2.0.0",
+ "micromark-util-classify-character": "^2.0.0",
+ "micromark-util-resolve-all": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
- "node_modules/is-extglob": {
+ "node_modules/micromark-extension-gfm-table": {
"version": "2.1.1",
- "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
- "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
- "dev": true,
+ "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz",
+ "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==",
"license": "MIT",
- "engines": {
- "node": ">=0.10.0"
+ "dependencies": {
+ "devlop": "^1.0.0",
+ "micromark-factory-space": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
- "node_modules/is-finalizationregistry": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz",
- "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==",
- "dev": true,
+ "node_modules/micromark-extension-gfm-tagfilter": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz",
+ "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==",
"license": "MIT",
"dependencies": {
- "call-bound": "^1.0.3"
+ "micromark-util-types": "^2.0.0"
},
- "engines": {
- "node": ">= 0.4"
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-extension-gfm-task-list-item": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz",
+ "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==",
+ "license": "MIT",
+ "dependencies": {
+ "devlop": "^1.0.0",
+ "micromark-factory-space": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-extension-mdx-expression": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.1.tgz",
+ "integrity": "sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "devlop": "^1.0.0",
+ "micromark-factory-mdx-expression": "^2.0.0",
+ "micromark-factory-space": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-events-to-acorn": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
}
},
- "node_modules/is-generator-function": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz",
- "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==",
- "dev": true,
+ "node_modules/micromark-extension-mdx-jsx": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-3.0.2.tgz",
+ "integrity": "sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ==",
"license": "MIT",
"dependencies": {
- "call-bound": "^1.0.4",
- "generator-function": "^2.0.0",
- "get-proto": "^1.0.1",
- "has-tostringtag": "^1.0.2",
- "safe-regex-test": "^1.1.0"
- },
- "engines": {
- "node": ">= 0.4"
+ "@types/estree": "^1.0.0",
+ "devlop": "^1.0.0",
+ "estree-util-is-identifier-name": "^3.0.0",
+ "micromark-factory-mdx-expression": "^2.0.0",
+ "micromark-factory-space": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-events-to-acorn": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0",
+ "vfile-message": "^4.0.0"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
- "node_modules/is-glob": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
- "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
- "dev": true,
+ "node_modules/micromark-extension-mdx-md": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/micromark-extension-mdx-md/-/micromark-extension-mdx-md-2.0.0.tgz",
+ "integrity": "sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==",
"license": "MIT",
"dependencies": {
- "is-extglob": "^2.1.1"
+ "micromark-util-types": "^2.0.0"
},
- "engines": {
- "node": ">=0.10.0"
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
- "node_modules/is-map": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz",
- "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==",
- "dev": true,
+ "node_modules/micromark-extension-mdxjs": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs/-/micromark-extension-mdxjs-3.0.0.tgz",
+ "integrity": "sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==",
"license": "MIT",
- "engines": {
- "node": ">= 0.4"
+ "dependencies": {
+ "acorn": "^8.0.0",
+ "acorn-jsx": "^5.0.0",
+ "micromark-extension-mdx-expression": "^3.0.0",
+ "micromark-extension-mdx-jsx": "^3.0.0",
+ "micromark-extension-mdx-md": "^2.0.0",
+ "micromark-extension-mdxjs-esm": "^3.0.0",
+ "micromark-util-combine-extensions": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
- "node_modules/is-negative-zero": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz",
- "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==",
- "dev": true,
+ "node_modules/micromark-extension-mdxjs-esm": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-3.0.0.tgz",
+ "integrity": "sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==",
"license": "MIT",
- "engines": {
- "node": ">= 0.4"
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "devlop": "^1.0.0",
+ "micromark-core-commonmark": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-events-to-acorn": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0",
+ "unist-util-position-from-estree": "^2.0.0",
+ "vfile-message": "^4.0.0"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
- "node_modules/is-number": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
- "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
- "dev": true,
+ "node_modules/micromark-factory-destination": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz",
+ "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
"license": "MIT",
- "engines": {
- "node": ">=0.12.0"
+ "dependencies": {
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
}
},
- "node_modules/is-number-object": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz",
- "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==",
- "dev": true,
+ "node_modules/micromark-factory-label": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz",
+ "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
"license": "MIT",
"dependencies": {
- "call-bound": "^1.0.3",
- "has-tostringtag": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "devlop": "^1.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
}
},
- "node_modules/is-regex": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
- "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==",
- "dev": true,
+ "node_modules/micromark-factory-mdx-expression": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-2.0.3.tgz",
+ "integrity": "sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
"license": "MIT",
"dependencies": {
- "call-bound": "^1.0.2",
- "gopd": "^1.2.0",
- "has-tostringtag": "^1.0.2",
- "hasown": "^2.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "@types/estree": "^1.0.0",
+ "devlop": "^1.0.0",
+ "micromark-factory-space": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-events-to-acorn": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0",
+ "unist-util-position-from-estree": "^2.0.0",
+ "vfile-message": "^4.0.0"
}
},
- "node_modules/is-set": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz",
- "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==",
- "dev": true,
+ "node_modules/micromark-factory-space": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz",
+ "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
"license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "dependencies": {
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
}
},
- "node_modules/is-shared-array-buffer": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz",
- "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==",
- "dev": true,
+ "node_modules/micromark-factory-title": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz",
+ "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
"license": "MIT",
"dependencies": {
- "call-bound": "^1.0.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "micromark-factory-space": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
}
},
- "node_modules/is-string": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz",
- "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==",
- "dev": true,
+ "node_modules/micromark-factory-whitespace": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz",
+ "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
"license": "MIT",
"dependencies": {
- "call-bound": "^1.0.3",
- "has-tostringtag": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "micromark-factory-space": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
}
},
- "node_modules/is-symbol": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz",
- "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==",
- "dev": true,
+ "node_modules/micromark-util-character": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz",
+ "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
"license": "MIT",
"dependencies": {
- "call-bound": "^1.0.2",
- "has-symbols": "^1.1.0",
- "safe-regex-test": "^1.1.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
}
},
- "node_modules/is-typed-array": {
- "version": "1.1.15",
- "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz",
- "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==",
- "dev": true,
+ "node_modules/micromark-util-chunked": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz",
+ "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
"license": "MIT",
"dependencies": {
- "which-typed-array": "^1.1.16"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "micromark-util-symbol": "^2.0.0"
}
},
- "node_modules/is-weakmap": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz",
- "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==",
- "dev": true,
+ "node_modules/micromark-util-classify-character": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz",
+ "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
"license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "dependencies": {
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
}
},
- "node_modules/is-weakref": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz",
- "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==",
- "dev": true,
+ "node_modules/micromark-util-combine-extensions": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz",
+ "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
"license": "MIT",
"dependencies": {
- "call-bound": "^1.0.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "micromark-util-chunked": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-decode-numeric-character-reference": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz",
+ "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-symbol": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-decode-string": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz",
+ "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "decode-named-character-reference": "^1.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-decode-numeric-character-reference": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0"
}
},
- "node_modules/is-weakset": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz",
- "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==",
- "dev": true,
+ "node_modules/micromark-util-encode": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz",
+ "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/micromark-util-events-to-acorn": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-2.0.3.tgz",
+ "integrity": "sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
"license": "MIT",
"dependencies": {
- "call-bound": "^1.0.3",
- "get-intrinsic": "^1.2.6"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "@types/estree": "^1.0.0",
+ "@types/unist": "^3.0.0",
+ "devlop": "^1.0.0",
+ "estree-util-visit": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0",
+ "vfile-message": "^4.0.0"
}
},
- "node_modules/isarray": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
- "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
- "dev": true,
+ "node_modules/micromark-util-html-tag-name": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz",
+ "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
"license": "MIT"
},
- "node_modules/isexe": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
- "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/iterator.prototype": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz",
- "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==",
- "dev": true,
+ "node_modules/micromark-util-normalize-identifier": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz",
+ "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
"license": "MIT",
"dependencies": {
- "define-data-property": "^1.1.4",
- "es-object-atoms": "^1.0.0",
- "get-intrinsic": "^1.2.6",
- "get-proto": "^1.0.0",
- "has-symbols": "^1.1.0",
- "set-function-name": "^2.0.2"
- },
- "engines": {
- "node": ">= 0.4"
+ "micromark-util-symbol": "^2.0.0"
}
},
- "node_modules/jest-worker": {
- "version": "27.5.1",
- "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz",
- "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==",
- "dev": true,
+ "node_modules/micromark-util-resolve-all": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz",
+ "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
"license": "MIT",
- "peer": true,
"dependencies": {
- "@types/node": "*",
- "merge-stream": "^2.0.0",
- "supports-color": "^8.0.0"
- },
- "engines": {
- "node": ">= 10.13.0"
+ "micromark-util-types": "^2.0.0"
}
},
- "node_modules/jest-worker/node_modules/supports-color": {
- "version": "8.1.1",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
- "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
- "dev": true,
+ "node_modules/micromark-util-sanitize-uri": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz",
+ "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
"license": "MIT",
- "peer": true,
"dependencies": {
- "has-flag": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/supports-color?sponsor=1"
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-encode": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0"
}
},
- "node_modules/jiti": {
- "version": "2.7.0",
- "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz",
- "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==",
- "dev": true,
+ "node_modules/micromark-util-subtokenize": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz",
+ "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
"license": "MIT",
- "bin": {
- "jiti": "lib/jiti-cli.mjs"
+ "dependencies": {
+ "devlop": "^1.0.0",
+ "micromark-util-chunked": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
}
},
- "node_modules/js-tokens": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
- "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
- "dev": true,
+ "node_modules/micromark-util-symbol": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz",
+ "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
"license": "MIT"
},
- "node_modules/js-yaml": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
- "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
+ "node_modules/micromark-util-types": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz",
+ "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
+ "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "argparse": "^2.0.1"
+ "braces": "^3.0.3",
+ "picomatch": "^2.3.1"
},
- "bin": {
- "js-yaml": "bin/js-yaml.js"
+ "engines": {
+ "node": ">=8.6"
}
},
- "node_modules/jsesc": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
- "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
- "dev": true,
+ "node_modules/mime-db": {
+ "version": "1.54.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
+ "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
+ "devOptional": true,
"license": "MIT",
- "bin": {
- "jsesc": "bin/jsesc"
- },
+ "peer": true,
"engines": {
- "node": ">=6"
+ "node": ">= 0.6"
}
},
- "node_modules/json-buffer": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
- "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/json-schema-traverse": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
- "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/json-stable-stringify-without-jsonify": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
- "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/json5": {
- "version": "2.2.3",
- "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
- "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "node_modules/miniflare": {
+ "version": "4.20260515.0",
+ "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-4.20260515.0.tgz",
+ "integrity": "sha512-2j0oQWizk1Eu4Cm8tDX7Z+Nsjd0nebIj1TQcQ+Oy1QKeo0Ay9+bdn8wfLAtOj9znDCybDCUlnS1+nYvKXEdfNg==",
"dev": true,
"license": "MIT",
+ "dependencies": {
+ "@cspotcode/source-map-support": "0.8.1",
+ "sharp": "^0.34.5",
+ "undici": "7.24.8",
+ "workerd": "1.20260515.1",
+ "ws": "8.18.0",
+ "youch": "4.1.0-beta.10"
+ },
"bin": {
- "json5": "lib/cli.js"
+ "miniflare": "bootstrap.js"
},
"engines": {
- "node": ">=6"
+ "node": ">=22.0.0"
}
},
- "node_modules/jsx-ast-utils": {
- "version": "3.3.5",
- "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
- "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==",
+ "node_modules/minimatch": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
+ "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
"dev": true,
- "license": "MIT",
+ "license": "ISC",
"dependencies": {
- "array-includes": "^3.1.6",
- "array.prototype.flat": "^1.3.1",
- "object.assign": "^4.1.4",
- "object.values": "^1.1.6"
+ "brace-expansion": "^1.1.7"
},
"engines": {
- "node": ">=4.0"
+ "node": "*"
}
},
- "node_modules/keyv": {
- "version": "4.5.4",
- "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
- "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "node_modules/minimist": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+ "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "json-buffer": "3.0.1"
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/kleur": {
- "version": "4.1.5",
- "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
- "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==",
- "dev": true,
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.18",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz",
+ "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
"license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
"engines": {
- "node": ">=6"
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
- "node_modules/language-subtag-registry": {
- "version": "0.3.23",
- "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz",
- "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==",
- "dev": true,
- "license": "CC0-1.0"
- },
- "node_modules/language-tags": {
- "version": "1.0.9",
- "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz",
- "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==",
+ "node_modules/napi-postinstall": {
+ "version": "0.3.4",
+ "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz",
+ "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "language-subtag-registry": "^0.3.20"
+ "bin": {
+ "napi-postinstall": "lib/cli.js"
},
"engines": {
- "node": ">=0.10"
+ "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/napi-postinstall"
}
},
- "node_modules/levn": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
- "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
"dev": true,
+ "license": "MIT"
+ },
+ "node_modules/neo-async": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
+ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/next": {
+ "version": "16.3.0",
+ "resolved": "https://registry.npmjs.org/next/-/next-16.3.0.tgz",
+ "integrity": "sha512-NEdGOzH+08eTXMUp9UYkA99Nhi5N6Thrhc1jgFOQgfgnGK/dA2hRwBpXep+exdFQrnwlRf/3Wixyp8lLBUpE2A==",
"license": "MIT",
"dependencies": {
- "prelude-ls": "^1.2.1",
- "type-check": "~0.4.0"
+ "@next/env": "16.3.0",
+ "@swc/helpers": "0.5.15",
+ "baseline-browser-mapping": "^2.9.19",
+ "caniuse-lite": "^1.0.30001579",
+ "postcss": "8.5.23",
+ "styled-jsx": "5.1.6"
+ },
+ "bin": {
+ "next": "dist/bin/next"
},
"engines": {
- "node": ">= 0.8.0"
+ "node": ">=20.9.0"
+ },
+ "optionalDependencies": {
+ "@next/swc-darwin-arm64": "16.3.0",
+ "@next/swc-darwin-x64": "16.3.0",
+ "@next/swc-linux-arm64-gnu": "16.3.0",
+ "@next/swc-linux-arm64-musl": "16.3.0",
+ "@next/swc-linux-x64-gnu": "16.3.0",
+ "@next/swc-linux-x64-musl": "16.3.0",
+ "@next/swc-win32-arm64-msvc": "16.3.0",
+ "@next/swc-win32-x64-msvc": "16.3.0",
+ "sharp": "^0.35.3"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.1.0",
+ "@playwright/test": "^1.51.1",
+ "babel-plugin-react-compiler": "*",
+ "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0",
+ "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0",
+ "sass": "^1.3.0"
+ },
+ "peerDependenciesMeta": {
+ "@opentelemetry/api": {
+ "optional": true
+ },
+ "@playwright/test": {
+ "optional": true
+ },
+ "babel-plugin-react-compiler": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ }
}
},
- "node_modules/lightningcss": {
- "version": "1.31.1",
- "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.31.1.tgz",
- "integrity": "sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ==",
- "dev": true,
- "license": "MPL-2.0",
- "dependencies": {
- "detect-libc": "^2.0.3"
- },
+ "node_modules/next/node_modules/@img/sharp-darwin-arm64": {
+ "version": "0.35.3",
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.3.tgz",
+ "integrity": "sha512-RMnFX7YQsMoh7lWfcM4NEHHymBX/rLuKNPVM84XE9ONPcaSCDgE7CHIHpSgPcO2xcRthgBy1HfNO319mwhIAkg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
"engines": {
- "node": ">= 12.0.0"
+ "node": ">=20.9.0"
},
"funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
+ "url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "lightningcss-android-arm64": "1.31.1",
- "lightningcss-darwin-arm64": "1.31.1",
- "lightningcss-darwin-x64": "1.31.1",
- "lightningcss-freebsd-x64": "1.31.1",
- "lightningcss-linux-arm-gnueabihf": "1.31.1",
- "lightningcss-linux-arm64-gnu": "1.31.1",
- "lightningcss-linux-arm64-musl": "1.31.1",
- "lightningcss-linux-x64-gnu": "1.31.1",
- "lightningcss-linux-x64-musl": "1.31.1",
- "lightningcss-win32-arm64-msvc": "1.31.1",
- "lightningcss-win32-x64-msvc": "1.31.1"
+ "@img/sharp-libvips-darwin-arm64": "1.3.2"
}
},
- "node_modules/lightningcss-android-arm64": {
- "version": "1.31.1",
- "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.31.1.tgz",
- "integrity": "sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg==",
+ "node_modules/next/node_modules/@img/sharp-darwin-x64": {
+ "version": "0.35.3",
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.3.tgz",
+ "integrity": "sha512-Xo+5uFBtLN0BKqieTxiFzFPQAUlBbbH5iBKyRX/z1JrbnYsHTfKJnUfL8+p2TPXr1pXqao4eeL4Rl144uDpK9w==",
"cpu": [
- "arm64"
+ "x64"
],
- "dev": true,
- "license": "MPL-2.0",
+ "license": "Apache-2.0",
"optional": true,
"os": [
- "android"
+ "darwin"
],
"engines": {
- "node": ">= 12.0.0"
+ "node": ">=20.9.0"
},
"funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-darwin-x64": "1.3.2"
}
},
- "node_modules/lightningcss-darwin-arm64": {
- "version": "1.31.1",
- "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.31.1.tgz",
- "integrity": "sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg==",
+ "node_modules/next/node_modules/@img/sharp-libvips-darwin-arm64": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.2.tgz",
+ "integrity": "sha512-9J6ypZFpQBj4YnePGoq/S38w6nz+vqg5WZLrLGY4YuSemdMq47GMLBPO42MzwdGwpg/agZ7xzZcFHa48xlywfg==",
"cpu": [
"arm64"
],
- "dev": true,
- "license": "MPL-2.0",
+ "license": "LGPL-3.0-or-later",
"optional": true,
"os": [
"darwin"
],
- "engines": {
- "node": ">= 12.0.0"
- },
"funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
+ "url": "https://opencollective.com/libvips"
}
},
- "node_modules/lightningcss-darwin-x64": {
- "version": "1.31.1",
- "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.31.1.tgz",
- "integrity": "sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA==",
+ "node_modules/next/node_modules/@img/sharp-libvips-darwin-x64": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.2.tgz",
+ "integrity": "sha512-m2pW1n6cns9VaubNwsZ+c3CRYjxNQWgJ5gPlnL1nbBcpkBvFm6SCFN5o0psFHI8w9n11NKhFkeEDns98tiqbEw==",
"cpu": [
"x64"
],
- "dev": true,
- "license": "MPL-2.0",
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/next/node_modules/@img/sharp-libvips-linux-arm": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.2.tgz",
+ "integrity": "sha512-1eMLzy92I4J6rmi4mAT8yC3HxOtniyGELlzGbNMLLeqe052ahFQ0h6LFq+lh5DsDIdYViIDst08abvSbcEdLXQ==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/next/node_modules/@img/sharp-libvips-linux-arm64": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.2.tgz",
+ "integrity": "sha512-dqVSFynCox4C/J8kT16V7SIFAns0IjgLwkvYT7p8LQVmJ5OS5b6tI9IGflxTeuBS//zXeFIUbwt5dwxyZ17cnA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/next/node_modules/@img/sharp-libvips-linux-ppc64": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.2.tgz",
+ "integrity": "sha512-3z0NHDxD6n5I9gc05U1eW1AyRm+Gznzq3naMrthPNqE6oYykcogW0l/jfpJdjYnuNl8R7yI9pNbE1XiUeyq0Aw==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/next/node_modules/@img/sharp-libvips-linux-riscv64": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.2.tgz",
+ "integrity": "sha512-bsb4rI+NldGOsXuej2r8OdSS8+zXDVaCWxyWrcv6kneTOlgAHtZABRzBBCwdsPiD90J4myNJuHpg6kA20ImW/w==",
+ "cpu": [
+ "riscv64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/next/node_modules/@img/sharp-libvips-linux-s390x": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.2.tgz",
+ "integrity": "sha512-/ABshyj8gCpyIrNXnHn4LorDJ0HHm1VhXPBlxZ8zAtfVPAaSafXPGn+sUSIRiwaSBy0mmFjSjiXI5mkcwdChKQ==",
+ "cpu": [
+ "s390x"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/next/node_modules/@img/sharp-libvips-linux-x64": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.2.tgz",
+ "integrity": "sha512-ITPEtgffGJ0S6G9dRyw/366tJQqFRcHWPHhC+Stpg3Z8AEMrDrTr2lhdz4f/Y/HMbRh//7Z5mBzEpVdi62Oc3w==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/next/node_modules/@img/sharp-libvips-linuxmusl-arm64": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.2.tgz",
+ "integrity": "sha512-zE9EdiUzUmg5mDT5a1rk5fYJ6GWPloTwWBYDS14naqHsL+EaMpDj1AWnpLgh3u0YCORv2Tt50wrcrpYqkP97Kw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "LGPL-3.0-or-later",
"optional": true,
"os": [
- "darwin"
+ "linux"
],
- "engines": {
- "node": ">= 12.0.0"
- },
"funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
+ "url": "https://opencollective.com/libvips"
}
},
- "node_modules/lightningcss-freebsd-x64": {
- "version": "1.31.1",
- "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.31.1.tgz",
- "integrity": "sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A==",
+ "node_modules/next/node_modules/@img/sharp-libvips-linuxmusl-x64": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.2.tgz",
+ "integrity": "sha512-m0lrLiUt+lBYnCFr8qV/65yMR4E/c7/wf78I5eKTdkEakFAlZ9QlzEM3QIhhAwVeUhLAHLcCq7a7Vszq/oFNZQ==",
"cpu": [
"x64"
],
- "dev": true,
- "license": "MPL-2.0",
+ "license": "LGPL-3.0-or-later",
"optional": true,
"os": [
- "freebsd"
+ "linux"
],
- "engines": {
- "node": ">= 12.0.0"
- },
"funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
+ "url": "https://opencollective.com/libvips"
}
},
- "node_modules/lightningcss-linux-arm-gnueabihf": {
- "version": "1.31.1",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.31.1.tgz",
- "integrity": "sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g==",
+ "node_modules/next/node_modules/@img/sharp-linux-arm": {
+ "version": "0.35.3",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.3.tgz",
+ "integrity": "sha512-affVWCTLooy8TSxbDx2qkzuDeaWLNVBA+P//FNBirHsXpP2fuBhk5AuboYUnrDnzoXes8GFjpTx0SBFOCRg+FA==",
"cpu": [
"arm"
],
- "dev": true,
- "license": "MPL-2.0",
+ "license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
- "node": ">= 12.0.0"
+ "node": ">=20.9.0"
},
"funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-arm": "1.3.2"
}
},
- "node_modules/lightningcss-linux-arm64-gnu": {
- "version": "1.31.1",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.31.1.tgz",
- "integrity": "sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==",
+ "node_modules/next/node_modules/@img/sharp-linux-arm64": {
+ "version": "0.35.3",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.3.tgz",
+ "integrity": "sha512-QgKDspHPnrU+GQ55XPhGwyhC8acLVOOSyAvo1oVfFmrIXLkDNmGWzAfDZ4xK8oSA1qBQrALcHX0G5UZni/SuFQ==",
"cpu": [
"arm64"
],
- "dev": true,
- "license": "MPL-2.0",
+ "license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
- "node": ">= 12.0.0"
+ "node": ">=20.9.0"
},
"funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-arm64": "1.3.2"
}
},
- "node_modules/lightningcss-linux-arm64-musl": {
- "version": "1.31.1",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.31.1.tgz",
- "integrity": "sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==",
+ "node_modules/next/node_modules/@img/sharp-linux-ppc64": {
+ "version": "0.35.3",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.3.tgz",
+ "integrity": "sha512-sMd8rDxmpLOwv/7N44klFjOD5DUO7FLdjiXDI0hoxYaf7Ar262dQIEkosE98bps+5HPLtp/EvNqeqQtOycP/IA==",
"cpu": [
- "arm64"
+ "ppc64"
],
- "dev": true,
- "license": "MPL-2.0",
+ "license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
- "node": ">= 12.0.0"
+ "node": ">=20.9.0"
},
"funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-ppc64": "1.3.2"
}
},
- "node_modules/lightningcss-linux-x64-gnu": {
- "version": "1.31.1",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.31.1.tgz",
- "integrity": "sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==",
+ "node_modules/next/node_modules/@img/sharp-linux-riscv64": {
+ "version": "0.35.3",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.3.tgz",
+ "integrity": "sha512-0Eob78yjlYPfL5vMNWAW55l3R9Y6BQS/gOfe0ZcP9mEz9ohhKSt4im1hayiknXgf8AWrFqMvJcKIdmLmEe7yeQ==",
"cpu": [
- "x64"
+ "riscv64"
],
- "dev": true,
- "license": "MPL-2.0",
+ "license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
- "node": ">= 12.0.0"
+ "node": ">=20.9.0"
},
"funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-riscv64": "1.3.2"
}
},
- "node_modules/lightningcss-linux-x64-musl": {
- "version": "1.31.1",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.31.1.tgz",
- "integrity": "sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==",
+ "node_modules/next/node_modules/@img/sharp-linux-s390x": {
+ "version": "0.35.3",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.3.tgz",
+ "integrity": "sha512-KgAxQ0DxpNOq1rG2t5cgTgShJFGSuU7XO45cqC+1NVOuZnP6tlgZRuSYOfNupGkHID0o3cJOsw4DVeJpMovcGw==",
"cpu": [
- "x64"
+ "s390x"
],
- "dev": true,
- "license": "MPL-2.0",
+ "license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
- "node": ">= 12.0.0"
+ "node": ">=20.9.0"
},
"funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-s390x": "1.3.2"
}
},
- "node_modules/lightningcss-win32-arm64-msvc": {
- "version": "1.31.1",
- "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.31.1.tgz",
- "integrity": "sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==",
+ "node_modules/next/node_modules/@img/sharp-linux-x64": {
+ "version": "0.35.3",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.3.tgz",
+ "integrity": "sha512-8pqvxubL2PGdhlPy6GLqzDYMUjyRmKAwKHYKixpdJYBUK7PJ0C029XdsnpFIdgRZG68fZiGdHVWcKPvtiPB4cA==",
"cpu": [
- "arm64"
+ "x64"
],
- "dev": true,
- "license": "MPL-2.0",
+ "license": "Apache-2.0",
"optional": true,
"os": [
- "win32"
+ "linux"
],
"engines": {
- "node": ">= 12.0.0"
+ "node": ">=20.9.0"
},
"funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-x64": "1.3.2"
}
},
- "node_modules/lightningcss-win32-x64-msvc": {
- "version": "1.31.1",
- "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.31.1.tgz",
- "integrity": "sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw==",
+ "node_modules/next/node_modules/@img/sharp-linuxmusl-arm64": {
+ "version": "0.35.3",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.3.tgz",
+ "integrity": "sha512-Vz0iQjzzcSX3HCbfwFfCSG/9SCIqyO0mH2sXyiHaAYfBk0cRsCWXRyQYX0ovCK/PAQBbTzQ0dsPQHh5MAFL59w==",
"cpu": [
- "x64"
+ "arm64"
],
- "dev": true,
- "license": "MPL-2.0",
+ "license": "Apache-2.0",
"optional": true,
"os": [
- "win32"
+ "linux"
],
"engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/linebreak": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/linebreak/-/linebreak-1.1.0.tgz",
- "integrity": "sha512-MHp03UImeVhB7XZtjd0E4n6+3xr5Dq/9xI/5FptGk5FrbDR3zagPa2DS6U8ks/3HjbKWG9Q1M2ufOzxV2qLYSQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "base64-js": "0.0.8",
- "unicode-trie": "^2.0.0"
- }
- },
- "node_modules/loader-runner": {
- "version": "4.3.2",
- "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.2.tgz",
- "integrity": "sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w==",
- "dev": true,
- "license": "MIT",
- "peer": true,
- "engines": {
- "node": ">=6.11.5"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/webpack"
- }
- },
- "node_modules/locate-path": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
- "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "p-locate": "^5.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/lodash.merge": {
- "version": "4.6.2",
- "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
- "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/loose-envify": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
- "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "js-tokens": "^3.0.0 || ^4.0.0"
+ "node": ">=20.9.0"
},
- "bin": {
- "loose-envify": "cli.js"
- }
- },
- "node_modules/lru-cache": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
- "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "yallist": "^3.0.2"
- }
- },
- "node_modules/magic-string": {
- "version": "0.30.21",
- "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
- "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jridgewell/sourcemap-codec": "^1.5.5"
- }
- },
- "node_modules/math-intrinsics": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
- "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/merge-stream": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
- "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
- "dev": true,
- "license": "MIT",
- "peer": true
- },
- "node_modules/merge2": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
- "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/micromatch": {
- "version": "4.0.8",
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
- "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "braces": "^3.0.3",
- "picomatch": "^2.3.1"
+ "funding": {
+ "url": "https://opencollective.com/libvips"
},
- "engines": {
- "node": ">=8.6"
+ "optionalDependencies": {
+ "@img/sharp-libvips-linuxmusl-arm64": "1.3.2"
}
},
- "node_modules/mime-db": {
- "version": "1.54.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
- "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
- "dev": true,
- "license": "MIT",
- "peer": true,
+ "node_modules/next/node_modules/@img/sharp-linuxmusl-x64": {
+ "version": "0.35.3",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.3.tgz",
+ "integrity": "sha512-6O1NPKcDVj9QEdg7Hx549EX8U0rp6yXQERqru6yRN7fGBn32UvIRJUlWnk+8xDCiG76hXVBbX82NZ/ZKr0euIg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
"engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/miniflare": {
- "version": "4.20260515.0",
- "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-4.20260515.0.tgz",
- "integrity": "sha512-2j0oQWizk1Eu4Cm8tDX7Z+Nsjd0nebIj1TQcQ+Oy1QKeo0Ay9+bdn8wfLAtOj9znDCybDCUlnS1+nYvKXEdfNg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@cspotcode/source-map-support": "0.8.1",
- "sharp": "^0.34.5",
- "undici": "7.24.8",
- "workerd": "1.20260515.1",
- "ws": "8.18.0",
- "youch": "4.1.0-beta.10"
+ "node": ">=20.9.0"
},
- "bin": {
- "miniflare": "bootstrap.js"
+ "funding": {
+ "url": "https://opencollective.com/libvips"
},
- "engines": {
- "node": ">=22.0.0"
+ "optionalDependencies": {
+ "@img/sharp-libvips-linuxmusl-x64": "1.3.2"
}
},
- "node_modules/minimatch": {
- "version": "3.1.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
- "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
+ "node_modules/next/node_modules/@img/sharp-win32-arm64": {
+ "version": "0.35.3",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.3.tgz",
+ "integrity": "sha512-4bPwFdMbeC4JQ8L8LOyWp6nsHcboP5fxkp6iPOXz2Vg49R42TuMs2whkJ5OAP4/Ul035qOzy0AecOF9VOscn4w==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "Apache-2.0 AND LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
"engines": {
- "node": "*"
+ "node": ">=20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
}
},
- "node_modules/minimist": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
- "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
- "dev": true,
- "license": "MIT",
+ "node_modules/next/node_modules/@img/sharp-win32-ia32": {
+ "version": "0.35.3",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.3.tgz",
+ "integrity": "sha512-r53mXsBN6lFUDiST764SvgwUdHAqM4rPAiDzAmf4fLoB6X/rkfyTrLCg6+g17wJJiCmB3JYgHuUldCWUIRFSXw==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "Apache-2.0 AND LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^20.9.0"
+ },
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "url": "https://opencollective.com/libvips"
}
},
- "node_modules/ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/nanoid": {
- "version": "3.3.12",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz",
- "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
+ "node_modules/next/node_modules/@img/sharp-win32-x64": {
+ "version": "0.35.3",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.3.tgz",
+ "integrity": "sha512-D4y1vNeZrIIJCN+uHaWVtH86B+aCrdMYYjicy9pXHvbGZeGYLLSd3wdVuC37FxVXlU1ARsk84eKWfWMXGYEqvA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0 AND LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "win32"
],
- "license": "MIT",
- "bin": {
- "nanoid": "bin/nanoid.cjs"
- },
"engines": {
- "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ "node": ">=20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
}
},
- "node_modules/napi-postinstall": {
- "version": "0.3.4",
- "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz",
- "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==",
- "dev": true,
- "license": "MIT",
+ "node_modules/next/node_modules/semver": {
+ "version": "7.8.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
+ "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
+ "license": "ISC",
+ "optional": true,
"bin": {
- "napi-postinstall": "lib/cli.js"
+ "semver": "bin/semver.js"
},
"engines": {
- "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/napi-postinstall"
+ "node": ">=10"
}
},
- "node_modules/natural-compare": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
- "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/neo-async": {
- "version": "2.6.2",
- "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
- "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/next": {
- "version": "16.2.6",
- "resolved": "https://registry.npmjs.org/next/-/next-16.2.6.tgz",
- "integrity": "sha512-qOVgKJg1+At15NpeUP+eJgCHvTCgXsogweq87Ri/Ix7PkqQHg4sdaXmSFqKlgaIXE4kW0g25LE68W87UANlHtw==",
- "license": "MIT",
+ "node_modules/next/node_modules/sharp": {
+ "version": "0.35.3",
+ "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.3.tgz",
+ "integrity": "sha512-ej0zVHuZGHCiABXcNxeYhpRnPNPAcvbG8RMdBAhDAxLKkCRVSpK3Iyu7qbqw3JMzoj0REeM6f3tJLtVwl0023Q==",
+ "license": "Apache-2.0",
+ "optional": true,
"dependencies": {
- "@next/env": "16.2.6",
- "@swc/helpers": "0.5.15",
- "baseline-browser-mapping": "^2.9.19",
- "caniuse-lite": "^1.0.30001579",
- "postcss": "8.4.31",
- "styled-jsx": "5.1.6"
- },
- "bin": {
- "next": "dist/bin/next"
+ "@img/colour": "^1.1.0",
+ "detect-libc": "^2.1.2",
+ "semver": "^7.8.5"
},
"engines": {
"node": ">=20.9.0"
},
- "optionalDependencies": {
- "@next/swc-darwin-arm64": "16.2.6",
- "@next/swc-darwin-x64": "16.2.6",
- "@next/swc-linux-arm64-gnu": "16.2.6",
- "@next/swc-linux-arm64-musl": "16.2.6",
- "@next/swc-linux-x64-gnu": "16.2.6",
- "@next/swc-linux-x64-musl": "16.2.6",
- "@next/swc-win32-arm64-msvc": "16.2.6",
- "@next/swc-win32-x64-msvc": "16.2.6",
- "sharp": "^0.34.5"
+ "funding": {
+ "url": "https://opencollective.com/libvips"
},
- "peerDependencies": {
- "@opentelemetry/api": "^1.1.0",
- "@playwright/test": "^1.51.1",
- "babel-plugin-react-compiler": "*",
- "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0",
- "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0",
- "sass": "^1.3.0"
+ "optionalDependencies": {
+ "@img/sharp-darwin-arm64": "0.35.3",
+ "@img/sharp-darwin-x64": "0.35.3",
+ "@img/sharp-freebsd-wasm32": "0.35.3",
+ "@img/sharp-libvips-darwin-arm64": "1.3.2",
+ "@img/sharp-libvips-darwin-x64": "1.3.2",
+ "@img/sharp-libvips-linux-arm": "1.3.2",
+ "@img/sharp-libvips-linux-arm64": "1.3.2",
+ "@img/sharp-libvips-linux-ppc64": "1.3.2",
+ "@img/sharp-libvips-linux-riscv64": "1.3.2",
+ "@img/sharp-libvips-linux-s390x": "1.3.2",
+ "@img/sharp-libvips-linux-x64": "1.3.2",
+ "@img/sharp-libvips-linuxmusl-arm64": "1.3.2",
+ "@img/sharp-libvips-linuxmusl-x64": "1.3.2",
+ "@img/sharp-linux-arm": "0.35.3",
+ "@img/sharp-linux-arm64": "0.35.3",
+ "@img/sharp-linux-ppc64": "0.35.3",
+ "@img/sharp-linux-riscv64": "0.35.3",
+ "@img/sharp-linux-s390x": "0.35.3",
+ "@img/sharp-linux-x64": "0.35.3",
+ "@img/sharp-linuxmusl-arm64": "0.35.3",
+ "@img/sharp-linuxmusl-x64": "0.35.3",
+ "@img/sharp-webcontainers-wasm32": "0.35.3",
+ "@img/sharp-win32-arm64": "0.35.3",
+ "@img/sharp-win32-ia32": "0.35.3",
+ "@img/sharp-win32-x64": "0.35.3"
},
"peerDependenciesMeta": {
- "@opentelemetry/api": {
- "optional": true
- },
- "@playwright/test": {
- "optional": true
- },
- "babel-plugin-react-compiler": {
- "optional": true
- },
- "sass": {
+ "@types/node": {
"optional": true
}
}
},
- "node_modules/next/node_modules/postcss": {
- "version": "8.4.31",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
- "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/postcss"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "nanoid": "^3.3.6",
- "picocolors": "^1.0.0",
- "source-map-js": "^1.0.2"
- },
- "engines": {
- "node": "^10 || ^12 || >=14"
- }
- },
"node_modules/node-exports-info": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/node-exports-info/-/node-exports-info-1.6.0.tgz",
@@ -7004,7 +9670,7 @@
"version": "2.0.44",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.44.tgz",
"integrity": "sha512-5WUyunoPMsvvEhS8AxHtRzP+oA8UCkJ7YRxatWKjngndhDGLiqEVAQKWjFAiAiuL8zMRGzGSJxFnLetoa43qGQ==",
- "dev": true,
+ "devOptional": true,
"license": "MIT"
},
"node_modules/object-assign": {
@@ -7229,6 +9895,31 @@
"hex-rgb": "^4.1.0"
}
},
+ "node_modules/parse-entities": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz",
+ "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "character-entities-legacy": "^3.0.0",
+ "character-reference-invalid": "^2.0.0",
+ "decode-named-character-reference": "^1.0.0",
+ "is-alphanumerical": "^2.0.0",
+ "is-decimal": "^2.0.0",
+ "is-hexadecimal": "^2.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/parse-entities/node_modules/@types/unist": {
+ "version": "2.0.11",
+ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz",
+ "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==",
+ "license": "MIT"
+ },
"node_modules/path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@@ -7300,10 +9991,9 @@
}
},
"node_modules/postcss": {
- "version": "8.5.14",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz",
- "integrity": "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==",
- "dev": true,
+ "version": "8.5.23",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.23.tgz",
+ "integrity": "sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==",
"funding": [
{
"type": "opencollective",
@@ -7320,7 +10010,7 @@
],
"license": "MIT",
"dependencies": {
- "nanoid": "^3.3.11",
+ "nanoid": "^3.3.16",
"picocolors": "^1.1.1",
"source-map-js": "^1.2.1"
},
@@ -7357,6 +10047,16 @@
"react-is": "^16.13.1"
}
},
+ "node_modules/property-information": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.2.0.tgz",
+ "integrity": "sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/punycode": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
@@ -7389,24 +10089,24 @@
"license": "MIT"
},
"node_modules/react": {
- "version": "19.2.6",
- "resolved": "https://registry.npmjs.org/react/-/react-19.2.6.tgz",
- "integrity": "sha512-sfWGGfavi0xr8Pg0sVsyHMAOziVYKgPLNrS7ig+ivMNb3wbCBw3KxtflsGBAwD3gYQlE/AEZsTLgToRrSCjb0Q==",
+ "version": "19.2.8",
+ "resolved": "https://registry.npmjs.org/react/-/react-19.2.8.tgz",
+ "integrity": "sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/react-dom": {
- "version": "19.2.6",
- "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.6.tgz",
- "integrity": "sha512-0prMI+hvBbPjsWnxDLxlCGyM8PN6UuWjEUCYmZhO67xIV9Xasa/r/vDnq+Xyq4Lo27g8QSbO5YzARu0D1Sps3g==",
+ "version": "19.2.8",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.8.tgz",
+ "integrity": "sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==",
"license": "MIT",
"dependencies": {
"scheduler": "^0.27.0"
},
"peerDependencies": {
- "react": "^19.2.6"
+ "react": "^19.2.8"
}
},
"node_modules/react-is": {
@@ -7416,24 +10116,91 @@
"dev": true,
"license": "MIT"
},
- "node_modules/react-server-dom-webpack": {
- "version": "19.2.6",
- "resolved": "https://registry.npmjs.org/react-server-dom-webpack/-/react-server-dom-webpack-19.2.6.tgz",
- "integrity": "sha512-762YXjBPc6hw2V16k4x1sdnw0mxghcSPzoiOhefGYjiTguJLCImGBUz6EjznPIfqKhWgLtpaQMlBhp66N8dKrw==",
- "dev": true,
+ "node_modules/react-server-dom-webpack": {
+ "version": "19.2.8",
+ "resolved": "https://registry.npmjs.org/react-server-dom-webpack/-/react-server-dom-webpack-19.2.8.tgz",
+ "integrity": "sha512-rFO1VJZ+cH9ZH6hGy9+qmIsmZHZpCMKJZXhWHqT71UnSfg+w+W+gwrwp58MVzMqdFquG8GF1c6C8q0OGphkEdg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "acorn-loose": "^8.3.0",
+ "neo-async": "^2.6.1",
+ "webpack-sources": "^3.2.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ },
+ "peerDependencies": {
+ "react": "^19.2.8",
+ "react-dom": "^19.2.8",
+ "webpack": "^5.59.0"
+ }
+ },
+ "node_modules/recma-build-jsx": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/recma-build-jsx/-/recma-build-jsx-1.0.0.tgz",
+ "integrity": "sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "estree-util-build-jsx": "^3.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/recma-jsx": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/recma-jsx/-/recma-jsx-1.0.1.tgz",
+ "integrity": "sha512-huSIy7VU2Z5OLv6oFLosQGGDqPqdO1iq6bWNAdhzMxSJP7RAso4fCZ1cKu8j9YHCZf3TPrq4dw3okhrylgcd7w==",
+ "license": "MIT",
+ "dependencies": {
+ "acorn-jsx": "^5.0.0",
+ "estree-util-to-js": "^2.0.0",
+ "recma-parse": "^1.0.0",
+ "recma-stringify": "^1.0.0",
+ "unified": "^11.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ },
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/recma-parse": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/recma-parse/-/recma-parse-1.0.0.tgz",
+ "integrity": "sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "esast-util-from-js": "^2.0.0",
+ "unified": "^11.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/recma-stringify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/recma-stringify/-/recma-stringify-1.0.0.tgz",
+ "integrity": "sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==",
"license": "MIT",
"dependencies": {
- "acorn-loose": "^8.3.0",
- "neo-async": "^2.6.1",
- "webpack-sources": "^3.2.0"
+ "@types/estree": "^1.0.0",
+ "estree-util-to-js": "^2.0.0",
+ "unified": "^11.0.0",
+ "vfile": "^6.0.0"
},
- "engines": {
- "node": ">=0.10.0"
- },
- "peerDependencies": {
- "react": "^19.2.6",
- "react-dom": "^19.2.6",
- "webpack": "^5.59.0"
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
"node_modules/reflect.getprototypeof": {
@@ -7480,11 +10247,123 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/rehype-recma": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/rehype-recma/-/rehype-recma-1.0.0.tgz",
+ "integrity": "sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "@types/hast": "^3.0.0",
+ "hast-util-to-estree": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/rehype-slug": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/rehype-slug/-/rehype-slug-6.0.0.tgz",
+ "integrity": "sha512-lWyvf/jwu+oS5+hL5eClVd3hNdmwM1kAC0BUvEGD19pajQMIzcNUd/k9GsfQ+FfECvX+JE+e9/btsKH0EjJT6A==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "github-slugger": "^2.0.0",
+ "hast-util-heading-rank": "^3.0.0",
+ "hast-util-to-string": "^3.0.0",
+ "unist-util-visit": "^5.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/remark-gfm": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz",
+ "integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "mdast-util-gfm": "^3.0.0",
+ "micromark-extension-gfm": "^3.0.0",
+ "remark-parse": "^11.0.0",
+ "remark-stringify": "^11.0.0",
+ "unified": "^11.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/remark-mdx": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.1.tgz",
+ "integrity": "sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg==",
+ "license": "MIT",
+ "dependencies": {
+ "mdast-util-mdx": "^3.0.0",
+ "micromark-extension-mdxjs": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/remark-parse": {
+ "version": "11.0.0",
+ "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz",
+ "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "mdast-util-from-markdown": "^2.0.0",
+ "micromark-util-types": "^2.0.0",
+ "unified": "^11.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/remark-rehype": {
+ "version": "11.1.2",
+ "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz",
+ "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "@types/mdast": "^4.0.0",
+ "mdast-util-to-hast": "^13.0.0",
+ "unified": "^11.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/remark-stringify": {
+ "version": "11.0.0",
+ "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz",
+ "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "mdast-util-to-markdown": "^2.0.0",
+ "unified": "^11.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"node_modules/require-from-string": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
- "dev": true,
+ "devOptional": true,
"license": "MIT",
"peer": true,
"engines": {
@@ -7547,13 +10426,13 @@
}
},
"node_modules/rolldown": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.1.tgz",
- "integrity": "sha512-X0KQHljNnEkWNqqiz9zJrGunh1B0HgOxLXvnFpCOcadzcy5qohZ3tqMEUg00vncoRovXuK3ZqCT9KnnKzoInFQ==",
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.3.tgz",
+ "integrity": "sha512-rn9wpmxplLf7NLNyCk9FyWh3FM43DbY8jOzCdEPzH7uflhTftRbCEpqi6Ly2osgoU8OwObtmavMbWLaWy4LX7A==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@oxc-project/types": "=0.130.0",
+ "@oxc-project/types": "=0.143.0",
"@rolldown/pluginutils": "^1.0.0"
},
"bin": {
@@ -7563,21 +10442,67 @@
"node": "^20.19.0 || >=22.12.0"
},
"optionalDependencies": {
- "@rolldown/binding-android-arm64": "1.0.1",
- "@rolldown/binding-darwin-arm64": "1.0.1",
- "@rolldown/binding-darwin-x64": "1.0.1",
- "@rolldown/binding-freebsd-x64": "1.0.1",
- "@rolldown/binding-linux-arm-gnueabihf": "1.0.1",
- "@rolldown/binding-linux-arm64-gnu": "1.0.1",
- "@rolldown/binding-linux-arm64-musl": "1.0.1",
- "@rolldown/binding-linux-ppc64-gnu": "1.0.1",
- "@rolldown/binding-linux-s390x-gnu": "1.0.1",
- "@rolldown/binding-linux-x64-gnu": "1.0.1",
- "@rolldown/binding-linux-x64-musl": "1.0.1",
- "@rolldown/binding-openharmony-arm64": "1.0.1",
- "@rolldown/binding-wasm32-wasi": "1.0.1",
- "@rolldown/binding-win32-arm64-msvc": "1.0.1",
- "@rolldown/binding-win32-x64-msvc": "1.0.1"
+ "@rolldown/binding-android-arm64": "1.2.3",
+ "@rolldown/binding-darwin-arm64": "1.2.3",
+ "@rolldown/binding-darwin-x64": "1.2.3",
+ "@rolldown/binding-freebsd-x64": "1.2.3",
+ "@rolldown/binding-linux-arm-gnueabihf": "1.2.3",
+ "@rolldown/binding-linux-arm64-gnu": "1.2.3",
+ "@rolldown/binding-linux-arm64-musl": "1.2.3",
+ "@rolldown/binding-linux-ppc64-gnu": "1.2.3",
+ "@rolldown/binding-linux-s390x-gnu": "1.2.3",
+ "@rolldown/binding-linux-x64-gnu": "1.2.3",
+ "@rolldown/binding-linux-x64-musl": "1.2.3",
+ "@rolldown/binding-openharmony-arm64": "1.2.3",
+ "@rolldown/binding-win32-arm64-msvc": "1.2.3",
+ "@rolldown/binding-win32-x64-msvc": "1.2.3"
+ }
+ },
+ "node_modules/rollup": {
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.4.tgz",
+ "integrity": "sha512-RXOqwaPsBGjMNMa4sQjDjHieHEZDFoj/Rdr46l2MU5DfEs16wHJPC2RPTPHWhNl+M3aI472LLqFkFKut4SblOg==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@types/estree": "1.0.9"
+ },
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=18.0.0",
+ "npm": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "@napi-rs/lzma-linux-x64-gnu": "1.5.1",
+ "@rollup/rollup-android-arm-eabi": "4.62.4",
+ "@rollup/rollup-android-arm64": "4.62.4",
+ "@rollup/rollup-darwin-arm64": "4.62.4",
+ "@rollup/rollup-darwin-x64": "4.62.4",
+ "@rollup/rollup-freebsd-arm64": "4.62.4",
+ "@rollup/rollup-freebsd-x64": "4.62.4",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.62.4",
+ "@rollup/rollup-linux-arm-musleabihf": "4.62.4",
+ "@rollup/rollup-linux-arm64-gnu": "4.62.4",
+ "@rollup/rollup-linux-arm64-musl": "4.62.4",
+ "@rollup/rollup-linux-loong64-gnu": "4.62.4",
+ "@rollup/rollup-linux-loong64-musl": "4.62.4",
+ "@rollup/rollup-linux-ppc64-gnu": "4.62.4",
+ "@rollup/rollup-linux-ppc64-musl": "4.62.4",
+ "@rollup/rollup-linux-riscv64-gnu": "4.62.4",
+ "@rollup/rollup-linux-riscv64-musl": "4.62.4",
+ "@rollup/rollup-linux-s390x-gnu": "4.62.4",
+ "@rollup/rollup-linux-x64-gnu": "4.62.4",
+ "@rollup/rollup-linux-x64-musl": "4.62.4",
+ "@rollup/rollup-openbsd-x64": "4.62.4",
+ "@rollup/rollup-openharmony-arm64": "4.62.4",
+ "@rollup/rollup-win32-arm64-msvc": "4.62.4",
+ "@rollup/rollup-win32-ia32-msvc": "4.62.4",
+ "@rollup/rollup-win32-x64-gnu": "4.62.4",
+ "@rollup/rollup-win32-x64-msvc": "4.62.4",
+ "fsevents": "~2.3.2"
}
},
"node_modules/run-parallel": {
@@ -7692,7 +10617,7 @@
"version": "4.3.3",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz",
"integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==",
- "dev": true,
+ "devOptional": true,
"license": "MIT",
"peer": true,
"dependencies": {
@@ -7713,7 +10638,7 @@
"version": "8.20.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
"integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
- "dev": true,
+ "devOptional": true,
"license": "MIT",
"peer": true,
"dependencies": {
@@ -7731,7 +10656,7 @@
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
"integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
- "dev": true,
+ "devOptional": true,
"license": "MIT",
"peer": true,
"dependencies": {
@@ -7745,7 +10670,7 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
- "dev": true,
+ "devOptional": true,
"license": "MIT",
"peer": true
},
@@ -7812,7 +10737,7 @@
"version": "0.34.5",
"resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz",
"integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==",
- "devOptional": true,
+ "dev": true,
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
@@ -7857,7 +10782,7 @@
"version": "7.8.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.8.0.tgz",
"integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==",
- "devOptional": true,
+ "dev": true,
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
@@ -7969,7 +10894,7 @@
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true,
+ "devOptional": true,
"license": "BSD-3-Clause",
"peer": true,
"engines": {
@@ -7989,7 +10914,7 @@
"version": "0.5.21",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
- "dev": true,
+ "devOptional": true,
"license": "MIT",
"peer": true,
"dependencies": {
@@ -7997,6 +10922,16 @@
"source-map": "^0.6.0"
}
},
+ "node_modules/space-separated-tokens": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz",
+ "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/srvx": {
"version": "0.11.15",
"resolved": "https://registry.npmjs.org/srvx/-/srvx-0.11.15.tgz",
@@ -8151,6 +11086,20 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/stringify-entities": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz",
+ "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==",
+ "license": "MIT",
+ "dependencies": {
+ "character-entities-html4": "^2.0.0",
+ "character-entities-legacy": "^3.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/strip-bom": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
@@ -8194,6 +11143,24 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/style-to-js": {
+ "version": "1.1.21",
+ "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.21.tgz",
+ "integrity": "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==",
+ "license": "MIT",
+ "dependencies": {
+ "style-to-object": "1.0.14"
+ }
+ },
+ "node_modules/style-to-object": {
+ "version": "1.0.14",
+ "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.14.tgz",
+ "integrity": "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==",
+ "license": "MIT",
+ "dependencies": {
+ "inline-style-parser": "0.2.7"
+ }
+ },
"node_modules/styled-jsx": {
"version": "5.1.6",
"resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz",
@@ -8254,7 +11221,7 @@
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz",
"integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==",
- "dev": true,
+ "devOptional": true,
"license": "MIT",
"engines": {
"node": ">=6"
@@ -8268,7 +11235,7 @@
"version": "5.47.1",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.47.1.tgz",
"integrity": "sha512-tPbLXTI6ohPASb/1YViL428oEHu6/qv1OxqYnfaonVCFHqx4+wCd95pHrQWsL5X4pl90CTyW9piSAsS2L0VoMw==",
- "dev": true,
+ "devOptional": true,
"license": "BSD-2-Clause",
"peer": true,
"dependencies": {
@@ -8288,7 +11255,7 @@
"version": "5.6.0",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.6.0.tgz",
"integrity": "sha512-Eum+5ajkaOhf5KbM26osvv21kLD7BaGqQ1UA4Ami4arYwylmGUQTgHFpHDdmJod1q4QXa66p0to/FBKID+J1vA==",
- "dev": true,
+ "devOptional": true,
"license": "MIT",
"peer": true,
"dependencies": {
@@ -8354,9 +11321,9 @@
"license": "MIT"
},
"node_modules/tinyglobby": {
- "version": "0.2.16",
- "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz",
- "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==",
+ "version": "0.2.17",
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz",
+ "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -8414,6 +11381,26 @@
"node": ">=8.0"
}
},
+ "node_modules/trim-lines": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz",
+ "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/trough": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz",
+ "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/ts-api-utils": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz",
@@ -8670,7 +11657,7 @@
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
- "dev": true,
+ "devOptional": true,
"license": "MIT"
},
"node_modules/unenv": {
@@ -8694,6 +11681,106 @@
"tiny-inflate": "^1.0.0"
}
},
+ "node_modules/unified": {
+ "version": "11.0.5",
+ "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz",
+ "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "bail": "^2.0.0",
+ "devlop": "^1.0.0",
+ "extend": "^3.0.0",
+ "is-plain-obj": "^4.0.0",
+ "trough": "^2.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-is": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz",
+ "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-position": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz",
+ "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-position-from-estree": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-position-from-estree/-/unist-util-position-from-estree-2.0.0.tgz",
+ "integrity": "sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-stringify-position": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz",
+ "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-visit": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz",
+ "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "unist-util-is": "^6.0.0",
+ "unist-util-visit-parents": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-visit-parents": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz",
+ "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "unist-util-is": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"node_modules/unpic": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/unpic/-/unpic-4.2.2.tgz",
@@ -8740,7 +11827,7 @@
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
"integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==",
- "dev": true,
+ "devOptional": true,
"funding": [
{
"type": "opencollective",
@@ -8777,6 +11864,34 @@
"punycode": "^2.1.0"
}
},
+ "node_modules/vfile": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz",
+ "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "vfile-message": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vfile-message": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz",
+ "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "unist-util-stringify-position": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"node_modules/vinext": {
"version": "0.0.50",
"resolved": "https://registry.npmjs.org/vinext/-/vinext-0.0.50.tgz",
@@ -8821,17 +11936,17 @@
}
},
"node_modules/vite": {
- "version": "8.0.13",
- "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.13.tgz",
- "integrity": "sha512-MFtjBYgzmSxmgA4RAfjIyXWpGe1oALnjgUTzzV7QLx/TKxCzjtMH6Fd9/eVK+5Fg1qNoz5VAwsmMs/NofrmJvw==",
+ "version": "8.2.1",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-8.2.1.tgz",
+ "integrity": "sha512-EU/eS7BH3XROHh2YnBefjM6DBKA6ZeMZEYQbj7NLWg5wHYlhB8B/Mayd5XsgWq+NFYccDOTemRpdETWR6Ka/lw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "lightningcss": "^1.32.0",
- "picomatch": "^4.0.4",
- "postcss": "^8.5.14",
- "rolldown": "1.0.1",
- "tinyglobby": "^0.2.16"
+ "lightningcss": "^1.33.0",
+ "picomatch": "^4.0.5",
+ "postcss": "^8.5.25",
+ "rolldown": "~1.2.1",
+ "tinyglobby": "^0.2.17"
},
"bin": {
"vite": "bin/vite.js"
@@ -8847,7 +11962,7 @@
},
"peerDependencies": {
"@types/node": "^20.19.0 || >=22.12.0",
- "@vitejs/devtools": "^0.1.18",
+ "@vitejs/devtools": "^0.4.0",
"esbuild": "^0.27.0 || ^0.28.0",
"jiti": ">=1.21.0",
"less": "^4.0.0",
@@ -8976,9 +12091,9 @@
}
},
"node_modules/vite/node_modules/lightningcss": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz",
- "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==",
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz",
+ "integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==",
"dev": true,
"license": "MPL-2.0",
"dependencies": {
@@ -8992,23 +12107,23 @@
"url": "https://opencollective.com/parcel"
},
"optionalDependencies": {
- "lightningcss-android-arm64": "1.32.0",
- "lightningcss-darwin-arm64": "1.32.0",
- "lightningcss-darwin-x64": "1.32.0",
- "lightningcss-freebsd-x64": "1.32.0",
- "lightningcss-linux-arm-gnueabihf": "1.32.0",
- "lightningcss-linux-arm64-gnu": "1.32.0",
- "lightningcss-linux-arm64-musl": "1.32.0",
- "lightningcss-linux-x64-gnu": "1.32.0",
- "lightningcss-linux-x64-musl": "1.32.0",
- "lightningcss-win32-arm64-msvc": "1.32.0",
- "lightningcss-win32-x64-msvc": "1.32.0"
+ "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"
}
},
"node_modules/vite/node_modules/lightningcss-android-arm64": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz",
- "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==",
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz",
+ "integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==",
"cpu": [
"arm64"
],
@@ -9027,9 +12142,9 @@
}
},
"node_modules/vite/node_modules/lightningcss-darwin-arm64": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz",
- "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==",
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz",
+ "integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==",
"cpu": [
"arm64"
],
@@ -9048,9 +12163,9 @@
}
},
"node_modules/vite/node_modules/lightningcss-darwin-x64": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz",
- "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==",
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz",
+ "integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==",
"cpu": [
"x64"
],
@@ -9069,9 +12184,9 @@
}
},
"node_modules/vite/node_modules/lightningcss-freebsd-x64": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz",
- "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==",
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz",
+ "integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==",
"cpu": [
"x64"
],
@@ -9090,9 +12205,9 @@
}
},
"node_modules/vite/node_modules/lightningcss-linux-arm-gnueabihf": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz",
- "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==",
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz",
+ "integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==",
"cpu": [
"arm"
],
@@ -9111,9 +12226,9 @@
}
},
"node_modules/vite/node_modules/lightningcss-linux-arm64-gnu": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz",
- "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==",
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz",
+ "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==",
"cpu": [
"arm64"
],
@@ -9132,9 +12247,9 @@
}
},
"node_modules/vite/node_modules/lightningcss-linux-arm64-musl": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz",
- "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==",
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz",
+ "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==",
"cpu": [
"arm64"
],
@@ -9153,9 +12268,9 @@
}
},
"node_modules/vite/node_modules/lightningcss-linux-x64-gnu": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz",
- "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==",
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz",
+ "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==",
"cpu": [
"x64"
],
@@ -9174,9 +12289,9 @@
}
},
"node_modules/vite/node_modules/lightningcss-linux-x64-musl": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz",
- "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==",
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz",
+ "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==",
"cpu": [
"x64"
],
@@ -9195,9 +12310,9 @@
}
},
"node_modules/vite/node_modules/lightningcss-win32-arm64-msvc": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz",
- "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==",
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz",
+ "integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==",
"cpu": [
"arm64"
],
@@ -9216,9 +12331,9 @@
}
},
"node_modules/vite/node_modules/lightningcss-win32-x64-msvc": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz",
- "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==",
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz",
+ "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==",
"cpu": [
"x64"
],
@@ -9237,9 +12352,9 @@
}
},
"node_modules/vite/node_modules/picomatch": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
- "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz",
+ "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==",
"dev": true,
"license": "MIT",
"engines": {
@@ -9249,6 +12364,35 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
+ "node_modules/vite/node_modules/postcss": {
+ "version": "8.5.26",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz",
+ "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "nanoid": "^3.3.17",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
"node_modules/vitefu": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.1.3.tgz",
@@ -9273,7 +12417,7 @@
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz",
"integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==",
- "dev": true,
+ "devOptional": true,
"license": "MIT",
"peer": true,
"dependencies": {
@@ -9295,7 +12439,7 @@
"version": "5.106.2",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.106.2.tgz",
"integrity": "sha512-wGN3qcrBQIFmQ/c0AiOAQBvrZ5lmY8vbbMv4Mxfgzqd/B6+9pXtLo73WuS1dSGXM5QYY3hZnIbvx+K1xxe6FyA==",
- "dev": true,
+ "devOptional": true,
"license": "MIT",
"peer": true,
"dependencies": {
@@ -9344,7 +12488,7 @@
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.4.1.tgz",
"integrity": "sha512-eACpxRN02yaawnt+uUNIF7Qje6A9zArxBbcAJjK1PK3S9Ycg5jIuJ8pW4q8EMnwNZCEGltcjkRx1QzOxOkKD8A==",
- "dev": true,
+ "devOptional": true,
"license": "MIT",
"engines": {
"node": ">=10.13.0"
@@ -9354,7 +12498,7 @@
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
"integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
- "dev": true,
+ "devOptional": true,
"license": "BSD-2-Clause",
"peer": true,
"dependencies": {
@@ -9369,7 +12513,7 @@
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
"integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
- "dev": true,
+ "devOptional": true,
"license": "BSD-2-Clause",
"peer": true,
"engines": {
@@ -10127,6 +13271,16 @@
"peerDependencies": {
"zod": "^3.25.0 || ^4.0.0"
}
+ },
+ "node_modules/zwitch": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz",
+ "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
}
}
}
diff --git a/apps/console/package.json b/apps/console/package.json
index 936f4b6..0c03568 100644
--- a/apps/console/package.json
+++ b/apps/console/package.json
@@ -14,26 +14,38 @@
"typecheck": "tsc --noEmit"
},
"dependencies": {
- "next": "16.2.6",
- "react": "19.2.6",
- "react-dom": "19.2.6"
+ "@mdx-js/loader": "^3.1.1",
+ "@mdx-js/react": "^3.1.1",
+ "@next/mdx": "^16.3.0",
+ "next": "16.3.0",
+ "react": "19.2.8",
+ "react-dom": "19.2.8",
+ "rehype-slug": "^6.0.0",
+ "remark-gfm": "^4.0.1",
+ "unist-util-visit": "^5.1.0"
},
"devDependencies": {
"@cloudflare/vite-plugin": "1.37.1",
+ "@iconify-json/solar": "^1.2.5",
+ "@mdx-js/rollup": "^3.1.1",
"@tailwindcss/postcss": "4.2.1",
+ "@types/mdx": "^2.0.14",
"@types/node": "22.19.19",
"@types/react": "19.2.14",
"@types/react-dom": "19.2.3",
"@vitejs/plugin-react": "6.0.2",
"@vitejs/plugin-rsc": "0.5.26",
"eslint": "9.39.4",
- "eslint-config-next": "16.2.6",
- "react-server-dom-webpack": "19.2.6",
+ "eslint-config-next": "16.3.0",
+ "react-server-dom-webpack": "19.2.8",
"tailwindcss": "4.2.1",
"typescript": "5.9.3",
"vinext": "0.0.50",
- "vite": "8.0.13",
+ "vite": "8.2.1",
"wrangler": "4.92.0"
},
+ "overrides": {
+ "fast-uri": "3.1.5"
+ },
"type": "module"
}
diff --git a/apps/console/proxy.ts b/apps/console/proxy.ts
new file mode 100644
index 0000000..c05a3dc
--- /dev/null
+++ b/apps/console/proxy.ts
@@ -0,0 +1,69 @@
+import type { NextRequest } from "next/server";
+import { NextResponse } from "next/server";
+
+/**
+ * One build, two faces.
+ *
+ * Next 16 renamed the middleware entry point to `proxy.ts`; vinext honours the
+ * old filename but warns, and does not run it.
+ *
+ * GlassBox ships self-hosted and organization-owned (ADR-0027), so the console
+ * is the default at `/`: a customer running this inside their own network gets
+ * the operator surface with no configuration, and never serves our marketing
+ * page from their cluster.
+ *
+ * Marketing mode is opt-in per host. Set `GLASSBOX_PUBLIC_HOSTS` to a
+ * comma-separated list on the public deployment only:
+ *
+ * GLASSBOX_PUBLIC_HOSTS=glassbox.dev,www.glassbox.dev
+ *
+ * On those hosts `/` renders the landing page and the operator routes are not
+ * served, because there is no evidence plane behind them.
+ */
+const OPERATOR_ROUTES = [
+ "/investigations",
+ "/receipts",
+ "/campaigns",
+ "/recovery",
+ "/trust",
+ "/settings",
+];
+
+function publicHosts(): string[] {
+ return (process.env.GLASSBOX_PUBLIC_HOSTS ?? "")
+ .split(",")
+ .map((entry) => entry.trim().toLowerCase())
+ .filter(Boolean);
+}
+
+export function proxy(request: NextRequest) {
+ const hosts = publicHosts();
+ if (hosts.length === 0) return NextResponse.next();
+
+ const host = request.headers.get("host")?.split(":")[0].toLowerCase();
+ if (!host || !hosts.includes(host)) return NextResponse.next();
+
+ const { pathname } = request.nextUrl;
+
+ // `/home` is an implementation detail of the rewrite. Keep it out of the
+ // public URL space so the landing page has exactly one address.
+ if (pathname === "/home") {
+ return NextResponse.redirect(new URL("/", request.url));
+ }
+
+ if (pathname === "/") {
+ const landing = request.nextUrl.clone();
+ landing.pathname = "/home";
+ return NextResponse.rewrite(landing);
+ }
+
+ if (OPERATOR_ROUTES.some((route) => pathname === route || pathname.startsWith(`${route}/`))) {
+ return NextResponse.redirect(new URL("/", request.url));
+ }
+
+ return NextResponse.next();
+}
+
+export const config = {
+ matcher: ["/((?!api|_next/static|_next/image|favicon.svg|fonts/|media/).*)"],
+};
diff --git a/apps/console/public/fonts/plex-mono-400.woff2 b/apps/console/public/fonts/plex-mono-400.woff2
new file mode 100644
index 0000000..52b6c75
Binary files /dev/null and b/apps/console/public/fonts/plex-mono-400.woff2 differ
diff --git a/apps/console/public/fonts/plex-mono-600.woff2 b/apps/console/public/fonts/plex-mono-600.woff2
new file mode 100644
index 0000000..c6759ef
Binary files /dev/null and b/apps/console/public/fonts/plex-mono-600.woff2 differ
diff --git a/apps/console/public/fonts/plex-sans-var.woff2 b/apps/console/public/fonts/plex-sans-var.woff2
new file mode 100644
index 0000000..e5ebabb
Binary files /dev/null and b/apps/console/public/fonts/plex-sans-var.woff2 differ
diff --git a/apps/console/public/media/glassbox-architecture-diagram.svg b/apps/console/public/media/glassbox-architecture-diagram.svg
new file mode 100644
index 0000000..4b244e7
--- /dev/null
+++ b/apps/console/public/media/glassbox-architecture-diagram.svg
@@ -0,0 +1,452 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GlassBox
+ DataHub-native execution provenance and control for AI agents
+
+
+
+
+
+ DataHub
+ Core 1.6.0 Β· governed graph
+
+
+ Recorded at the boundary. Signed by policy. Invalidated by evidence.
+
+
+
+ HOW GLASSBOX WORKS
+
+ 1
+ Capture
+ 2
+ Sign
+ 3
+ Project
+ 4
+ Assess
+ 5
+ Recover
+
+
+
+
+
+
+
+
+ AGENTS
+ Instrumented runs emit OTLP
+ spans as they read and write.
+
+ glassbox.runtime Β· nested runs
+
+ LangGraph Β· Google ADK Β· MCP
+
+
+
+
+
+
+ OPERATORS
+ Review decisions and
+ authorize recovery explicitly.
+
+ glassbox-dbom verify-policy
+
+
+
+
+
+
+ PLATFORM
+ Run the control plane and
+ provision the estate as code.
+
+ glassbox-otlp-receiver serve
+
+ glassbox-datahub-action
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ localhost:3002/investigations
+
+
+
+
+ Decision receipts
+ signed index Β· newest first
+
+ 2 receipts
+
+
+
+
+
+ dab8881a9aβ¦b5872bcb
+ postgres Β· commerce.orders Β· PROD
+
+ STALE
+
+
+
+ e18291381bβ¦cc217baa
+ postgres Β· commerce.orders Β· PROD
+
+ NO FINDINGS
+
+
+
+ SCHEMA_FIELD_TYPE_CHANGED
+ average_order_value Β· decimal β double
+
+
+
+
+
+ DBOM 0.1 canonical form
+ canonicalised Β· Ed25519 Β· append-only
+
+
+ dbom.version = "0.1"
+ influence.dependencies[1]
+ urn:li:schemaField:(β¦,PROD)
+ signature.alg = Ed25519
+
+
+ canonical state readback verified
+
+ every URN resolved before publish
+
+ field-lineage coverage COMPLETE
+
+
+ raw content withheld
+
+
+
+
+
+ Impact assessment
+ deterministic Β· rule pack, not a model
+
+
+
+ OBSERVED_MATERIAL_DEPENDENCY_CHANGED
+
+ policy v1
+
+ dependency timeline
+
+
+
+
+
+
+
+
+ a3f1c8 β 9c4e02
+
+ campaign Β· pinned
+
+
+
+
+
+ 1/1
+ dependencies resolved
+
+
+ unrelated-field control
+
+ UNAFFECTED Β· proven unused
+
+
+
+
+
+ Recovery & closure
+ authorized Β· sandboxed Β· append-only
+
+
+
+
+ Receipt quarantined
+
+ enforced
+
+
+ Replay authorized by fingerprint
+
+ bound
+
+
+ Replayed in digest-pinned OCI
+
+ no network
+
+
+ Supersession written
+
+ both unchanged
+
+
+
+
+ origin = datahub-action
+ change caused this quarantine
+
+ incident closed after direct DataHub readback
+
+
+
+
+
+
+
+
+
+
+
+
+ Signed baseline
+ A DBOM turns first sight into a signed
+ assertion about what the run depended on.
+
+
+
+
+ Correlated evidence
+ Findings reach DataHub carrying governed
+ URNs, campaign IDs, and reason codes.
+
+
+
+
+ Closed loop
+ A metadata change quarantines the next
+ decision before anyone reads it again.
+
+
+
+
+
+
+
+ DataHub estate
+ governed metadata graph
+
+ receipt Documents + aspects
+
+ metadata change events
+
+ native ownership routing
+
+ direct entity readback
+
+ incident writeback + closure
+
+
+
+
+
+
+ Assessment engine
+ deterministic, then durable
+
+ content-addressed rule packs
+
+ campaign per change event
+
+ leases Β· expiry Β· recovery
+
+ raw-free durable assessments
+
+ append-only audit trail
+
+
+
+
+
+
+ Recovery plane
+ authorized, sandboxed, reversible
+
+ digest-bound expiring approval
+
+ digest-pinned OCI profile
+
+ network denied Β· read-only root
+
+ supersession, never edit
+
+ verified idempotent closure
+
+ postgres Β· server-clock leases
+
+
+
+
+
+
+
+
+
+
+
+ Receipt
+ in DataHub
+
+
+
+
+ Findings
+ reason-coded
+
+
+
+
+ Superseded
+ history intact
+
+
+
+
+
+ GlassBox capabilities
+ Full contract set Β· DataHub-native
+
+
+
+
+ DBOM signing
+
+ URN resolution
+
+ Field lineage
+
+ Materiality rules
+
+ Campaigns
+
+ Leases & outbox
+
+ Kafka Β· pgQueue
+
+ Replay bundles
+
+ OCI sandbox
+
+ Supersession
+
+ Incident closure
+
+ MCP tools
+
+
+
+
+
+
+ Evidence β OTLP spans, signed receipts
+
+ Metadata β DataHub aspects and change events
+
+ Control β campaign β quarantine β recovery
+
+
+ GlassBox never returns raw content: only digests, governed URNs, reason codes, and verification results.
+ Enforcement is explicit, reversible, and always leaves both receipt Documents unchanged.
+
diff --git a/apps/console/tests/rendered-html.test.mjs b/apps/console/tests/rendered-html.test.mjs
index ce91fb9..287c04b 100644
--- a/apps/console/tests/rendered-html.test.mjs
+++ b/apps/console/tests/rendered-html.test.mjs
@@ -2,53 +2,120 @@ import assert from "node:assert/strict";
import { access, readFile } from "node:fs/promises";
import test from "node:test";
-async function render() {
+async function render(path = "/") {
const workerUrl = new URL("../dist/server/index.js", import.meta.url);
- workerUrl.searchParams.set("test", `${process.pid}-${Date.now()}`);
+ workerUrl.searchParams.set("test", `${process.pid}-${Date.now()}-${path}`);
const { default: worker } = await import(workerUrl.href);
-
return worker.fetch(
- new Request("http://localhost/", {
- headers: { accept: "text/html" },
- }),
- {
- ASSETS: {
- fetch: async () => new Response("Not found", { status: 404 }),
- },
- },
- {
- waitUntil() {},
- passThroughOnException() {},
- },
+ new Request(`http://localhost${path}`, { headers: { accept: "text/html" } }),
+ { ASSETS: { fetch: async () => new Response("Not found", { status: 404 }) } },
+ { waitUntil() {}, passThroughOnException() {} },
);
}
-test("server-renders the GlassBox forensic investigation", async () => {
+test("server-renders a real disconnected application state", async () => {
const response = await render();
assert.equal(response.status, 200);
- assert.match(response.headers.get("content-type") ?? "", /^text\/html\b/i);
-
const html = await response.text();
- assert.match(html, /GlassBox Forensics β Agent Decision Evidence<\/title>/i);
- assert.match(html, /og:image[^>]+og\.png|og\.png[^>]+og:image/i);
- assert.match(html, /Pricing recommendation/);
- assert.match(html, /OBSERVED_MATERIAL_DEPENDENCY_CHANGED/);
- assert.match(html, /PROJECTION_ONLY/);
- assert.match(html, /Integrity is not truth/);
+
+ assert.match(html, /GlassBox Forensics β Decision Control Center<\/title>/i);
+ assert.match(html, />Overview);
+ assert.match(html, /Connect your evidence plane/);
+ assert.match(html, /href="\/investigations"/);
+ assert.match(html, /href="\/receipts"/);
+ assert.match(html, /href="\/campaigns"/);
+ assert.match(html, /href="\/recovery"/);
+ assert.match(html, /href="\/trust"/);
+ assert.doesNotMatch(html, /Pricing recommendation|OBSERVED_MATERIAL_DEPENDENCY_CHANGED/);
assert.doesNotMatch(html, /codex-preview|react-loading-skeleton|SECRET/i);
});
-test("removes starter-only assets and dependency", async () => {
- const [page, layout, packageJson] = await Promise.all([
- readFile(new URL("../app/page.tsx", import.meta.url), "utf8"),
+test("renders the public product, documentation, and architecture surfaces", async () => {
+ const landing = await render("/home");
+ assert.equal(landing.status, 200);
+ const landingHtml = await landing.text();
+ assert.match(landingHtml, /GlassBox tells you what your agents did because of it/);
+ assert.match(landingHtml, /href="\/docs"/);
+ assert.match(landingHtml, /href="\/docs\/architecture"/);
+ assert.doesNotMatch(landingHtml, /Service-account token|Create ingestion key/);
+
+ const docs = await render("/docs");
+ assert.equal(docs.status, 200);
+ assert.match(await docs.text(), /Documentation/);
+
+ const architecture = await render("/docs/architecture");
+ assert.equal(architecture.status, 200);
+ assert.match(await architecture.text(), /Architecture/);
+});
+
+test("every primary navigation destination is independently rendered", async () => {
+ for (const [path, heading] of [
+ ["/investigations", "Investigations"],
+ ["/receipts", "Receipts"],
+ ["/campaigns", "Campaigns"],
+ ["/recovery", "Recovery"],
+ ["/trust", "Trust & privacy"],
+ ["/settings", "Connections"],
+ ]) {
+ const response = await render(path);
+ assert.equal(response.status, 200, path);
+ assert.match(await response.text(), new RegExp(`>${heading}<`), path);
+ }
+});
+
+test("removes starter and bundled-success implementation paths", async () => {
+ const [layout, operatorLayout, packageJson, api] = await Promise.all([
readFile(new URL("../app/layout.tsx", import.meta.url), "utf8"),
+ readFile(new URL("../app/(console)/layout.tsx", import.meta.url), "utf8"),
readFile(new URL("../package.json", import.meta.url), "utf8"),
+ readFile(new URL("../app/lib/forensics-api.ts", import.meta.url), "utf8"),
]);
- assert.match(page, /datahub-agent-forensics/);
- assert.match(page, /safe_for_deterministic_policy|All gates pass/);
- assert.match(layout, /GlassBox Forensics/);
- assert.match(layout, /\/og\.png/);
+ assert.match(layout, /Root layout owns only the document/);
+ assert.match(operatorLayout, /ConsoleShell/);
+ assert.match(operatorLayout, /dynamic\s*=\s*["']force-dynamic["']/);
+ assert.match(api, /GLASSBOX_FORENSICS_API_URL/);
+ assert.doesNotMatch(api, /one-command-flagship|Pricing recommendation/);
assert.doesNotMatch(packageJson, /react-loading-skeleton/);
await assert.rejects(access(new URL("../app/_sites-preview", import.meta.url)));
+ await assert.rejects(access(new URL("../app/flagship-evidence.ts", import.meta.url)));
+});
+
+test("keeps the operator-facing repairs wired into the product", async () => {
+ const [shell, investigation, campaign, receipts, recovery, overview] = await Promise.all([
+ readFile(new URL("../app/components/console-shell.tsx", import.meta.url), "utf8"),
+ readFile(new URL("../app/(console)/investigations/[receiptId]/page.tsx", import.meta.url), "utf8"),
+ readFile(new URL("../app/(console)/campaigns/[campaignId]/page.tsx", import.meta.url), "utf8"),
+ readFile(new URL("../app/(console)/receipts/page.tsx", import.meta.url), "utf8"),
+ readFile(new URL("../app/(console)/recovery/page.tsx", import.meta.url), "utf8"),
+ readFile(new URL("../app/(console)/page.tsx", import.meta.url), "utf8"),
+ ]);
+
+ assert.match(shell, /EXACT_RECEIPT_ID/);
+ assert.match(shell, /global-search-submit/);
+ assert.match(investigation, /IdentifierControl/);
+ assert.match(investigation, /DateValue/);
+ assert.match(campaign, /IdentifierControl/);
+ assert.match(campaign, /DateValue/);
+ assert.match(receipts, /DateValue/);
+ assert.match(recovery, /AWAITING_AUTHORIZATION/);
+ assert.match(overview, /compactChangeLabel/);
+ assert.match(overview, /compactUrn/);
+});
+
+test("renders the real connection center without exposing deployment secrets", async () => {
+ const response = await render("/settings");
+ const html = await response.text();
+ const [controlApi, proxy] = await Promise.all([
+ readFile(new URL("../app/lib/control-api.ts", import.meta.url), "utf8"),
+ readFile(new URL("../app/api/control/[...path]/route.ts", import.meta.url), "utf8"),
+ ]);
+
+ assert.match(html, /Connect DataHub/);
+ assert.match(html, /Service-account token/);
+ assert.match(html, /Prove write permission/);
+ assert.match(html, /Agent keys/);
+ assert.match(controlApi, /GLASSBOX_CONTROL_API_TOKEN/);
+ assert.match(proxy, /proxyControlRequest/);
+ assert.doesNotMatch(html, /GLASSBOX_CONTROL_MASTER_KEY|DATAHUB_GMS_TOKEN/);
});
diff --git a/apps/console/tsconfig.json b/apps/console/tsconfig.json
index 3a13f90..e6d6ed7 100644
--- a/apps/console/tsconfig.json
+++ b/apps/console/tsconfig.json
@@ -11,6 +11,7 @@
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
+ "allowImportingTsExtensions": true,
"jsx": "react-jsx",
"incremental": true,
"plugins": [
diff --git a/apps/console/vite.config.ts b/apps/console/vite.config.ts
index ae08f93..2dc03c3 100644
--- a/apps/console/vite.config.ts
+++ b/apps/console/vite.config.ts
@@ -1,7 +1,21 @@
+import mdx from "@mdx-js/rollup";
+import rehypeSlug from "rehype-slug";
+import remarkGfm from "remark-gfm";
import vinext from "vinext";
import { defineConfig } from "vite";
-import hostingConfig from "./.openai/hosting.json";
-import { sites } from "./build/sites-vite-plugin";
+import hostingConfig from "./.openai/hosting.json" with { type: "json" };
+import remarkCodeMeta from "./lib/remark-code-meta.ts";
+import { sites } from "./lib/sites-vite-plugin.ts";
+
+// Points the compiled MDX at the root `mdx-components.tsx`. That module exports
+// a plain `useMDXComponents` function rather than a React context provider, so
+// documentation pages keep rendering as server components.
+//
+// Resolved through the `@/` alias rather than an absolute filesystem path: an
+// absolute specifier produces a second module instance outside the normal graph,
+// which breaks the "use client" boundaries on CodeBlock and friends and leaves
+// them calling hooks against a null dispatcher.
+const mdxProvider = "@/mdx-components";
const SITE_CREATOR_PLACEHOLDER_DATABASE_ID =
"00000000-0000-4000-8000-000000000000";
@@ -14,6 +28,12 @@ const isCodexSeatbeltSandbox = process.env.CODEX_SANDBOX === "seatbelt";
const localBindingConfig = {
main: "./worker/index.ts",
compatibility_flags: ["nodejs_compat"],
+ // The Workers runtime does not inherit the shell environment, so anything the
+ // app reads from `process.env` on this path has to be handed over as a var.
+ // Production sets the same key in wrangler config; this bridges local dev.
+ vars: {
+ GLASSBOX_PUBLIC_HOSTS: process.env.GLASSBOX_PUBLIC_HOSTS ?? "",
+ },
d1_databases: d1
? [
{
@@ -43,11 +63,32 @@ export default defineConfig(async () => {
// Wrangler snapshots its log path while the Cloudflare plugin is imported.
const { cloudflare } = await import("@cloudflare/vite-plugin");
+ // The dev server rejects unknown Host headers. Marketing mode is selected by
+ // host in middleware, so developing or testing it locally needs those exact
+ // hostnames allowed here too. Production runs on Workers, where this check
+ // does not apply.
+ const marketingHosts = (process.env.GLASSBOX_PUBLIC_HOSTS ?? "")
+ .split(",")
+ .map((entry) => entry.trim())
+ .filter(Boolean);
+
return {
- server: isCodexSeatbeltSandbox
- ? { watch: { useFsEvents: false, usePolling: true } }
- : undefined,
+ server: {
+ ...(isCodexSeatbeltSandbox ? { watch: { useFsEvents: false, usePolling: true } } : {}),
+ ...(marketingHosts.length > 0 ? { allowedHosts: marketingHosts } : {}),
+ },
plugins: [
+ // Must precede vinext: it defers to a user-registered MDX plugin and
+ // otherwise injects its own without a provider.
+ {
+ enforce: "pre" as const,
+ ...mdx({
+ remarkPlugins: [remarkGfm, remarkCodeMeta],
+ // Gives every heading an id, which is what the "On this page" rail reads.
+ rehypePlugins: [rehypeSlug],
+ providerImportSource: mdxProvider,
+ }),
+ },
vinext(),
sites(),
cloudflare({
diff --git a/benchmarks/__init__.py b/benchmarks/__init__.py
new file mode 100644
index 0000000..4c43ad3
--- /dev/null
+++ b/benchmarks/__init__.py
@@ -0,0 +1 @@
+"""Reproducible GlassBox evaluation harnesses."""
diff --git a/benchmarks/agent_invalidation/__init__.py b/benchmarks/agent_invalidation/__init__.py
new file mode 100644
index 0000000..6f951a7
--- /dev/null
+++ b/benchmarks/agent_invalidation/__init__.py
@@ -0,0 +1,5 @@
+"""Agent invalidation benchmark and evidence-capability ablations."""
+
+from benchmarks.agent_invalidation.runner import build_benchmark_report
+
+__all__ = ["build_benchmark_report"]
diff --git a/benchmarks/agent_invalidation/__main__.py b/benchmarks/agent_invalidation/__main__.py
new file mode 100644
index 0000000..6fff20d
--- /dev/null
+++ b/benchmarks/agent_invalidation/__main__.py
@@ -0,0 +1,5 @@
+"""Module entry point for the agent invalidation benchmark."""
+
+from benchmarks.agent_invalidation.runner import main
+
+raise SystemExit(main())
diff --git a/benchmarks/agent_invalidation/fixtures.v1.json b/benchmarks/agent_invalidation/fixtures.v1.json
new file mode 100644
index 0000000..d20d3e8
--- /dev/null
+++ b/benchmarks/agent_invalidation/fixtures.v1.json
@@ -0,0 +1,447 @@
+{
+ "schema_version": "0.1.0",
+ "benchmark": "glassbox.agent-invalidation-ablation.v1",
+ "cases": [
+ {
+ "case_id": "used-field-type-change",
+ "description": "A type change lands after an agent observed the exact revenue field.",
+ "truth": "CONTAMINATED",
+ "ground_truth": {
+ "assets": ["urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)"],
+ "fields": ["urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD),revenue)"]
+ },
+ "signals": {
+ "static_declared_assets": [
+ "urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.customers,PROD)",
+ "urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)"
+ ],
+ "raw_otel_assets": ["urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)"]
+ },
+ "dependency": {
+ "entity_urn": "urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)",
+ "schema_field_urn": "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD),revenue)",
+ "state": "OBSERVED",
+ "role": "INPUT",
+ "observed_at": "2026-08-06T12:00:00Z",
+ "snapshot_version": "orders-v1"
+ },
+ "lineage": {
+ "coverage": "COMPLETE",
+ "rule_id": "glassbox.benchmark.sql-column-lineage.v1",
+ "wildcard_query": false
+ },
+ "change": {
+ "event_id": "change-used-field-type",
+ "entity_urn": "urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)",
+ "aspect_name": "schemaMetadata",
+ "kind": "SCHEMA_FIELD_TYPE_CHANGED",
+ "occurred_at": "2026-08-07T12:00:00Z",
+ "schema_field_urn": "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD),revenue)",
+ "before_version": "orders-v1",
+ "after_version": "orders-v2"
+ }
+ },
+ {
+ "case_id": "unrelated-field-same-asset",
+ "description": "A different field changes on the same dataset under complete non-wildcard lineage.",
+ "truth": "CLEAN",
+ "ground_truth": {
+ "assets": ["urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)"],
+ "fields": ["urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD),revenue)"]
+ },
+ "signals": {
+ "static_declared_assets": ["urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)"],
+ "raw_otel_assets": ["urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)"]
+ },
+ "dependency": {
+ "entity_urn": "urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)",
+ "schema_field_urn": "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD),revenue)",
+ "state": "OBSERVED",
+ "role": "INPUT",
+ "observed_at": "2026-08-06T12:00:00Z",
+ "snapshot_version": "orders-v1"
+ },
+ "lineage": {
+ "coverage": "COMPLETE",
+ "rule_id": "glassbox.benchmark.sql-column-lineage.v1",
+ "wildcard_query": false
+ },
+ "change": {
+ "event_id": "change-unrelated-field",
+ "entity_urn": "urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)",
+ "aspect_name": "schemaMetadata",
+ "kind": "SCHEMA_FIELD_TYPE_CHANGED",
+ "occurred_at": "2026-08-07T12:00:00Z",
+ "schema_field_urn": "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD),internal_note)",
+ "before_version": "note-v1",
+ "after_version": "note-v2"
+ }
+ },
+ {
+ "case_id": "matching-post-change-snapshot",
+ "description": "The receipt observed the exact changed field after the new metadata version existed.",
+ "truth": "CLEAN",
+ "ground_truth": {
+ "assets": ["urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)"],
+ "fields": ["urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD),revenue)"]
+ },
+ "signals": {
+ "static_declared_assets": ["urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)"],
+ "raw_otel_assets": ["urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)"]
+ },
+ "dependency": {
+ "entity_urn": "urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)",
+ "schema_field_urn": "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD),revenue)",
+ "state": "OBSERVED",
+ "role": "INPUT",
+ "observed_at": "2026-08-08T12:00:00Z",
+ "snapshot_version": "orders-v2"
+ },
+ "lineage": {
+ "coverage": "COMPLETE",
+ "rule_id": "glassbox.benchmark.sql-column-lineage.v1",
+ "wildcard_query": false
+ },
+ "change": {
+ "event_id": "change-before-observation",
+ "entity_urn": "urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)",
+ "aspect_name": "schemaMetadata",
+ "kind": "SCHEMA_FIELD_TYPE_CHANGED",
+ "occurred_at": "2026-08-07T12:00:00Z",
+ "schema_field_urn": "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD),revenue)",
+ "before_version": "orders-v1",
+ "after_version": "orders-v2"
+ }
+ },
+ {
+ "case_id": "other-asset-change",
+ "description": "A field changes on a resolved asset outside the observed influence set.",
+ "truth": "CLEAN",
+ "ground_truth": {
+ "assets": ["urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)"],
+ "fields": ["urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD),revenue)"]
+ },
+ "signals": {
+ "static_declared_assets": [
+ "urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.customers,PROD)",
+ "urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)"
+ ],
+ "raw_otel_assets": ["urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)"]
+ },
+ "dependency": {
+ "entity_urn": "urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)",
+ "schema_field_urn": "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD),revenue)",
+ "state": "OBSERVED",
+ "role": "INPUT",
+ "observed_at": "2026-08-06T12:00:00Z",
+ "snapshot_version": "orders-v1"
+ },
+ "lineage": {
+ "coverage": "COMPLETE",
+ "rule_id": "glassbox.benchmark.sql-column-lineage.v1",
+ "wildcard_query": false
+ },
+ "change": {
+ "event_id": "change-other-asset",
+ "entity_urn": "urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.customers,PROD)",
+ "aspect_name": "schemaMetadata",
+ "kind": "SCHEMA_FIELD_TYPE_CHANGED",
+ "occurred_at": "2026-08-07T12:00:00Z",
+ "schema_field_urn": "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.customers,PROD),id)",
+ "before_version": "customers-v1",
+ "after_version": "customers-v2"
+ }
+ },
+ {
+ "case_id": "trace-alias-collision",
+ "description": "A raw trace alias points at a similarly named asset that the run did not use.",
+ "truth": "CLEAN",
+ "ground_truth": {
+ "assets": ["urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)"],
+ "fields": ["urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD),revenue)"]
+ },
+ "signals": {
+ "static_declared_assets": ["urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)"],
+ "raw_otel_assets": ["urn:li:dataset:(urn:li:dataPlatform:postgres,marketing.orders,PROD)"]
+ },
+ "dependency": {
+ "entity_urn": "urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)",
+ "schema_field_urn": "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD),revenue)",
+ "state": "OBSERVED",
+ "role": "INPUT",
+ "observed_at": "2026-08-06T12:00:00Z",
+ "snapshot_version": "orders-v1"
+ },
+ "lineage": {
+ "coverage": "COMPLETE",
+ "rule_id": "glassbox.benchmark.sql-column-lineage.v1",
+ "wildcard_query": false
+ },
+ "change": {
+ "event_id": "change-alias-collision",
+ "entity_urn": "urn:li:dataset:(urn:li:dataPlatform:postgres,marketing.orders,PROD)",
+ "aspect_name": "schemaMetadata",
+ "kind": "SCHEMA_FIELD_TYPE_CHANGED",
+ "occurred_at": "2026-08-07T12:00:00Z",
+ "schema_field_urn": "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:postgres,marketing.orders,PROD),revenue)",
+ "before_version": "marketing-orders-v1",
+ "after_version": "marketing-orders-v2"
+ }
+ },
+ {
+ "case_id": "semantic-constraint-change",
+ "description": "An observed glossary constraint used by the decision changes materially.",
+ "truth": "CONTAMINATED",
+ "ground_truth": {
+ "assets": ["urn:li:glossaryTerm:Revenue"],
+ "fields": []
+ },
+ "signals": {
+ "static_declared_assets": ["urn:li:glossaryTerm:Revenue"],
+ "raw_otel_assets": ["urn:li:glossaryTerm:Revenue"]
+ },
+ "dependency": {
+ "entity_urn": "urn:li:glossaryTerm:Revenue",
+ "schema_field_urn": null,
+ "state": "OBSERVED",
+ "role": "CONSTRAINT",
+ "observed_at": "2026-08-06T12:00:00Z",
+ "snapshot_version": "revenue-term-v1"
+ },
+ "lineage": {
+ "coverage": "NONE",
+ "rule_id": null,
+ "wildcard_query": null
+ },
+ "change": {
+ "event_id": "change-semantic-constraint",
+ "entity_urn": "urn:li:glossaryTerm:Revenue",
+ "aspect_name": "glossaryTermInfo",
+ "kind": "GLOSSARY_DEFINITION_CHANGED",
+ "occurred_at": "2026-08-07T12:00:00Z",
+ "schema_field_urn": null,
+ "before_version": "revenue-term-v1",
+ "after_version": "revenue-term-v2"
+ }
+ },
+ {
+ "case_id": "semantic-reference-unproven",
+ "description": "A glossary reference changes but the receipt does not prove it was a constraint.",
+ "truth": "INDETERMINATE",
+ "ground_truth": {
+ "assets": ["urn:li:glossaryTerm:Revenue"],
+ "fields": []
+ },
+ "signals": {
+ "static_declared_assets": ["urn:li:glossaryTerm:Revenue"],
+ "raw_otel_assets": ["urn:li:glossaryTerm:Revenue"]
+ },
+ "dependency": {
+ "entity_urn": "urn:li:glossaryTerm:Revenue",
+ "schema_field_urn": null,
+ "state": "OBSERVED",
+ "role": "REFERENCE",
+ "observed_at": "2026-08-06T12:00:00Z",
+ "snapshot_version": "revenue-term-v1"
+ },
+ "lineage": {
+ "coverage": "NONE",
+ "rule_id": null,
+ "wildcard_query": null
+ },
+ "change": {
+ "event_id": "change-semantic-reference",
+ "entity_urn": "urn:li:glossaryTerm:Revenue",
+ "aspect_name": "glossaryTermInfo",
+ "kind": "GLOSSARY_DEFINITION_CHANGED",
+ "occurred_at": "2026-08-07T12:00:00Z",
+ "schema_field_urn": null,
+ "before_version": "revenue-term-v1",
+ "after_version": "revenue-term-v2"
+ }
+ },
+ {
+ "case_id": "freshness-requirement-unrecorded",
+ "description": "A freshness incident lands without a recorded freshness constraint.",
+ "truth": "INDETERMINATE",
+ "ground_truth": {
+ "assets": ["urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)"],
+ "fields": []
+ },
+ "signals": {
+ "static_declared_assets": ["urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)"],
+ "raw_otel_assets": ["urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)"]
+ },
+ "dependency": {
+ "entity_urn": "urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)",
+ "schema_field_urn": null,
+ "state": "OBSERVED",
+ "role": "INPUT",
+ "observed_at": "2026-08-06T12:00:00Z",
+ "snapshot_version": "orders-v1"
+ },
+ "lineage": {
+ "coverage": "NONE",
+ "rule_id": null,
+ "wildcard_query": null
+ },
+ "change": {
+ "event_id": "change-freshness",
+ "entity_urn": "urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)",
+ "aspect_name": "assertionRunEvent",
+ "kind": "FRESHNESS_INCIDENT",
+ "occurred_at": "2026-08-07T12:00:00Z",
+ "schema_field_urn": null,
+ "before_version": null,
+ "after_version": null
+ }
+ },
+ {
+ "case_id": "wildcard-field-ambiguity",
+ "description": "An unrelated field changes but wildcard query behavior prevents a safe exclusion.",
+ "truth": "INDETERMINATE",
+ "ground_truth": {
+ "assets": ["urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)"],
+ "fields": ["urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD),revenue)"]
+ },
+ "signals": {
+ "static_declared_assets": ["urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)"],
+ "raw_otel_assets": ["urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)"]
+ },
+ "dependency": {
+ "entity_urn": "urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)",
+ "schema_field_urn": "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD),revenue)",
+ "state": "OBSERVED",
+ "role": "INPUT",
+ "observed_at": "2026-08-06T12:00:00Z",
+ "snapshot_version": "orders-v1"
+ },
+ "lineage": {
+ "coverage": "COMPLETE",
+ "rule_id": "glassbox.benchmark.sql-column-lineage.v1",
+ "wildcard_query": true
+ },
+ "change": {
+ "event_id": "change-wildcard-unrelated",
+ "entity_urn": "urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)",
+ "aspect_name": "schemaMetadata",
+ "kind": "SCHEMA_FIELD_TYPE_CHANGED",
+ "occurred_at": "2026-08-07T12:00:00Z",
+ "schema_field_urn": "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD),internal_note)",
+ "before_version": "note-v1",
+ "after_version": "note-v2"
+ }
+ },
+ {
+ "case_id": "unresolved-runtime-context",
+ "description": "The runtime dependency cannot be resolved to a DataHub URN after a material change.",
+ "truth": "CONTAMINATED",
+ "ground_truth": {
+ "assets": ["urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)"],
+ "fields": ["urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD),revenue)"]
+ },
+ "signals": {
+ "static_declared_assets": ["urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)"],
+ "raw_otel_assets": []
+ },
+ "dependency": {
+ "entity_urn": null,
+ "schema_field_urn": null,
+ "state": "UNKNOWN",
+ "role": "INPUT",
+ "observed_at": null,
+ "snapshot_version": null
+ },
+ "lineage": {
+ "coverage": "NONE",
+ "rule_id": null,
+ "wildcard_query": null
+ },
+ "change": {
+ "event_id": "change-unresolved-context",
+ "entity_urn": "urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)",
+ "aspect_name": "schemaMetadata",
+ "kind": "SCHEMA_FIELD_TYPE_CHANGED",
+ "occurred_at": "2026-08-07T12:00:00Z",
+ "schema_field_urn": "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD),revenue)",
+ "before_version": "orders-v1",
+ "after_version": "orders-v2"
+ }
+ },
+ {
+ "case_id": "declared-but-not-observed-asset",
+ "description": "Static configuration declares an asset that this execution did not observe.",
+ "truth": "CLEAN",
+ "ground_truth": {
+ "assets": ["urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)"],
+ "fields": ["urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD),revenue)"]
+ },
+ "signals": {
+ "static_declared_assets": [
+ "urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.customers,PROD)",
+ "urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)"
+ ],
+ "raw_otel_assets": ["urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)"]
+ },
+ "dependency": {
+ "entity_urn": "urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)",
+ "schema_field_urn": "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD),revenue)",
+ "state": "OBSERVED",
+ "role": "INPUT",
+ "observed_at": "2026-08-06T12:00:00Z",
+ "snapshot_version": "orders-v1"
+ },
+ "lineage": {
+ "coverage": "COMPLETE",
+ "rule_id": "glassbox.benchmark.sql-column-lineage.v1",
+ "wildcard_query": false
+ },
+ "change": {
+ "event_id": "change-declared-unused-asset",
+ "entity_urn": "urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.customers,PROD)",
+ "aspect_name": "schemaMetadata",
+ "kind": "SCHEMA_FIELD_TYPE_CHANGED",
+ "occurred_at": "2026-08-07T12:00:00Z",
+ "schema_field_urn": "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.customers,PROD),email)",
+ "before_version": "customers-v1",
+ "after_version": "customers-v2"
+ }
+ },
+ {
+ "case_id": "new-field-non-wildcard",
+ "description": "A new field is added to an asset with complete non-wildcard field lineage.",
+ "truth": "CLEAN",
+ "ground_truth": {
+ "assets": ["urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)"],
+ "fields": ["urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD),revenue)"]
+ },
+ "signals": {
+ "static_declared_assets": ["urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)"],
+ "raw_otel_assets": ["urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)"]
+ },
+ "dependency": {
+ "entity_urn": "urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)",
+ "schema_field_urn": "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD),revenue)",
+ "state": "OBSERVED",
+ "role": "INPUT",
+ "observed_at": "2026-08-06T12:00:00Z",
+ "snapshot_version": "orders-v1"
+ },
+ "lineage": {
+ "coverage": "COMPLETE",
+ "rule_id": "glassbox.benchmark.sql-column-lineage.v1",
+ "wildcard_query": false
+ },
+ "change": {
+ "event_id": "change-new-field",
+ "entity_urn": "urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)",
+ "aspect_name": "schemaMetadata",
+ "kind": "SCHEMA_FIELD_ADDED",
+ "occurred_at": "2026-08-07T12:00:00Z",
+ "schema_field_urn": "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD),new_note)",
+ "before_version": null,
+ "after_version": "new-note-v1"
+ }
+ }
+ ]
+}
diff --git a/benchmarks/agent_invalidation/runner.py b/benchmarks/agent_invalidation/runner.py
new file mode 100644
index 0000000..bddf052
--- /dev/null
+++ b/benchmarks/agent_invalidation/runner.py
@@ -0,0 +1,1019 @@
+"""Deterministic five-way evidence ablation over the production policy engine."""
+
+from __future__ import annotations
+
+import argparse
+import copy
+import hashlib
+import json
+import platform
+import sys
+import time
+from collections.abc import Mapping, Sequence
+from dataclasses import dataclass
+from enum import StrEnum
+from pathlib import Path
+from typing import Any
+
+from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
+from examples.deterministic_pricing_agent import (
+ _synthetic_order_aggregate,
+ build_replayable_pricing_agent,
+)
+from examples.end_to_end_invalidation import FIELD_URN
+from examples.end_to_end_receipt import build_signed_receipt
+from examples.pricing_policy import apply_replayable_pricing_policy
+from jsonschema import Draft202012Validator
+
+from glassbox import GlassBox, InMemorySink
+from glassbox.redaction import RedactionPolicy, digest_value
+from glassbox_dbom import SigningKey, seal_receipt
+from glassbox_dbom.canonical import canonicalize
+from glassbox_policy import (
+ ChangeKind,
+ EvidenceDependency,
+ EvidenceRole,
+ EvidenceState,
+ FieldCoverage,
+ FieldLineageProof,
+ ImpactState,
+ NormalizedChange,
+ ReceiptDependencyProfile,
+ classify_materiality,
+)
+from glassbox_replay import (
+ ReplayDecision,
+ ReplayMode,
+ ReplaySupplement,
+ ResourceAvailability,
+ ResourceInventory,
+ ResourceKind,
+ build_replay_bundle,
+ plan_replay,
+)
+
+BENCHMARK_NAME = "glassbox.agent-invalidation-ablation.v1"
+BENCHMARK_VERSION = "0.1.0"
+_BENCHMARK_DOMAIN = b"glassbox.benchmark.agent-invalidation.v1\0"
+_ROOT = Path(__file__).resolve().parents[2]
+DEFAULT_FIXTURES = Path(__file__).with_name("fixtures.v1.json")
+DEFAULT_SCHEMA = _ROOT / "schemas" / "benchmark-report" / BENCHMARK_VERSION / "schema.json"
+DEFAULT_LIVE_REPORT = (
+ _ROOT / "docs" / "compatibility" / "datahub-1.6.0-flagship-causal-recovery.live.json"
+)
+_UNCERTAIN_STATES = frozenset({ImpactState.AT_RISK, ImpactState.UNKNOWN})
+
+
+class FixtureError(ValueError):
+ """Raised when a benchmark fixture violates the closed evaluation contract."""
+
+
+class Truth(StrEnum):
+ """Ground-truth impact labels used only by the synthetic benchmark."""
+
+ CONTAMINATED = "CONTAMINATED"
+ CLEAN = "CLEAN"
+ INDETERMINATE = "INDETERMINATE"
+
+
+class Ablation(StrEnum):
+ """Required evidence-capability variants from the GlassBox evaluation plan."""
+
+ STATIC_DECLARED_LINEAGE = "STATIC_DECLARED_LINEAGE"
+ RAW_OTEL_TRACES = "RAW_OTEL_TRACES"
+ GLASSBOX_WITHOUT_FIELD_EVIDENCE = "GLASSBOX_WITHOUT_FIELD_EVIDENCE"
+ GLASSBOX_WITHOUT_METADATA_SNAPSHOTS = "GLASSBOX_WITHOUT_METADATA_SNAPSHOTS"
+ FULL_GLASSBOX = "FULL_GLASSBOX"
+
+
+_REMOVED_CAPABILITIES = {
+ Ablation.STATIC_DECLARED_LINEAGE: [
+ "runtime observation state",
+ "field identity",
+ "metadata snapshot binding",
+ ],
+ Ablation.RAW_OTEL_TRACES: [
+ "verified DataHub resolution authority",
+ "field identity",
+ "metadata snapshot binding",
+ ],
+ Ablation.GLASSBOX_WITHOUT_FIELD_EVIDENCE: ["field identity", "field-lineage proof"],
+ Ablation.GLASSBOX_WITHOUT_METADATA_SNAPSHOTS: [
+ "observation timestamp and representation digest"
+ ],
+ Ablation.FULL_GLASSBOX: [],
+}
+
+
+@dataclass(frozen=True)
+class BenchmarkCase:
+ """One normalized context-change case and its independent ground truth."""
+
+ case_id: str
+ description: str
+ truth: Truth
+ ground_truth_assets: tuple[str, ...]
+ ground_truth_fields: tuple[str, ...]
+ static_declared_assets: tuple[str, ...]
+ raw_otel_assets: tuple[str, ...]
+ dependency: Mapping[str, Any]
+ lineage: Mapping[str, Any]
+ change: Mapping[str, Any]
+
+
+def _required_mapping(value: Mapping[str, Any], key: str) -> Mapping[str, Any]:
+ selected = value.get(key)
+ if not isinstance(selected, Mapping):
+ raise FixtureError(f"{key} must be an object")
+ return selected
+
+
+def _required_list(value: Mapping[str, Any], key: str) -> list[Any]:
+ selected = value.get(key)
+ if not isinstance(selected, list):
+ raise FixtureError(f"{key} must be an array")
+ return selected
+
+
+def _required_string(value: Mapping[str, Any], key: str) -> str:
+ selected = value.get(key)
+ if not isinstance(selected, str) or not selected:
+ raise FixtureError(f"{key} must be a non-empty string")
+ return selected
+
+
+def _string_tuple(value: Mapping[str, Any], key: str) -> tuple[str, ...]:
+ selected = _required_list(value, key)
+ if any(not isinstance(item, str) or not item for item in selected):
+ raise FixtureError(f"{key} must contain only non-empty strings")
+ result = tuple(sorted(selected))
+ if len(result) != len(set(result)):
+ raise FixtureError(f"{key} must not contain duplicate values")
+ return result
+
+
+def load_cases(
+ path: Path = DEFAULT_FIXTURES,
+) -> tuple[Mapping[str, Any], tuple[BenchmarkCase, ...]]:
+ """Load and close-check the published benchmark fixture set."""
+
+ raw = json.loads(path.read_text(encoding="utf-8"))
+ if not isinstance(raw, Mapping):
+ raise FixtureError("benchmark fixture root must be an object")
+ if raw.get("schema_version") != BENCHMARK_VERSION or raw.get("benchmark") != BENCHMARK_NAME:
+ raise FixtureError("benchmark fixture identity or schema version drifted")
+ allowed_root = {"schema_version", "benchmark", "cases"}
+ if set(raw) != allowed_root:
+ raise FixtureError("benchmark fixture root has missing or unexpected properties")
+ raw_cases = _required_list(raw, "cases")
+ cases: list[BenchmarkCase] = []
+ case_ids: set[str] = set()
+ expected_case_keys = {
+ "case_id",
+ "description",
+ "truth",
+ "ground_truth",
+ "signals",
+ "dependency",
+ "lineage",
+ "change",
+ }
+ for item in raw_cases:
+ if not isinstance(item, Mapping) or set(item) != expected_case_keys:
+ raise FixtureError("every benchmark case must use the closed case contract")
+ case_id = _required_string(item, "case_id")
+ if case_id in case_ids:
+ raise FixtureError("benchmark case IDs must be unique")
+ case_ids.add(case_id)
+ truth = Truth(_required_string(item, "truth"))
+ ground_truth = _required_mapping(item, "ground_truth")
+ signals = _required_mapping(item, "signals")
+ if set(ground_truth) != {"assets", "fields"} or set(signals) != {
+ "static_declared_assets",
+ "raw_otel_assets",
+ }:
+ raise FixtureError("ground_truth or signals has an unexpected property")
+ dependency = _required_mapping(item, "dependency")
+ lineage = _required_mapping(item, "lineage")
+ change = _required_mapping(item, "change")
+ cases.append(
+ BenchmarkCase(
+ case_id=case_id,
+ description=_required_string(item, "description"),
+ truth=truth,
+ ground_truth_assets=_string_tuple(ground_truth, "assets"),
+ ground_truth_fields=_string_tuple(ground_truth, "fields"),
+ static_declared_assets=_string_tuple(signals, "static_declared_assets"),
+ raw_otel_assets=_string_tuple(signals, "raw_otel_assets"),
+ dependency=dependency,
+ lineage=lineage,
+ change=change,
+ )
+ )
+ if not cases or not {item.truth for item in cases} == set(Truth):
+ raise FixtureError("benchmark requires contaminated, clean, and indeterminate cases")
+ return raw, tuple(cases)
+
+
+def _sha256_label(value: object) -> str | None:
+ if value is None:
+ return None
+ if not isinstance(value, str) or not value:
+ raise FixtureError("snapshot version labels must be non-empty strings or null")
+ return hashlib.sha256(value.encode()).hexdigest()
+
+
+def _lineage(value: Mapping[str, Any], *, remove_field_proof: bool) -> FieldLineageProof:
+ if set(value) != {"coverage", "rule_id", "wildcard_query"}:
+ raise FixtureError("lineage fixture has an unexpected property")
+ if remove_field_proof:
+ return FieldLineageProof()
+ coverage = FieldCoverage(_required_string(value, "coverage"))
+ rule_id = value.get("rule_id")
+ wildcard = value.get("wildcard_query")
+ if rule_id is not None and not isinstance(rule_id, str):
+ raise FixtureError("lineage rule_id must be a string or null")
+ if wildcard is not None and not isinstance(wildcard, bool):
+ raise FixtureError("lineage wildcard_query must be a boolean or null")
+ return FieldLineageProof(coverage=coverage, rule_id=rule_id, wildcard_query=wildcard)
+
+
+def _base_dependency(case: BenchmarkCase) -> EvidenceDependency:
+ value = case.dependency
+ expected = {
+ "entity_urn",
+ "schema_field_urn",
+ "state",
+ "role",
+ "observed_at",
+ "snapshot_version",
+ }
+ if set(value) != expected:
+ raise FixtureError("dependency fixture has an unexpected property")
+ entity = value.get("entity_urn")
+ field = value.get("schema_field_urn")
+ observed_at = value.get("observed_at")
+ for selected, label in ((entity, "entity_urn"), (field, "schema_field_urn")):
+ if selected is not None and not isinstance(selected, str):
+ raise FixtureError(f"dependency {label} must be a string or null")
+ if observed_at is not None and not isinstance(observed_at, str):
+ raise FixtureError("dependency observed_at must be a string or null")
+ return EvidenceDependency(
+ evidence_id=f"evidence-{case.case_id}",
+ datahub_urn=entity,
+ schema_field_urn=field,
+ state=EvidenceState(_required_string(value, "state")),
+ role=EvidenceRole(_required_string(value, "role")),
+ observed_at=observed_at,
+ representation_digest=_sha256_label(value.get("snapshot_version")),
+ )
+
+
+def _change(case: BenchmarkCase) -> NormalizedChange:
+ value = case.change
+ expected = {
+ "event_id",
+ "entity_urn",
+ "aspect_name",
+ "kind",
+ "occurred_at",
+ "schema_field_urn",
+ "before_version",
+ "after_version",
+ }
+ if set(value) != expected:
+ raise FixtureError("change fixture has an unexpected property")
+ field = value.get("schema_field_urn")
+ if field is not None and not isinstance(field, str):
+ raise FixtureError("change schema_field_urn must be a string or null")
+ return NormalizedChange(
+ event_id=_required_string(value, "event_id"),
+ entity_urn=_required_string(value, "entity_urn"),
+ aspect_name=_required_string(value, "aspect_name"),
+ kind=ChangeKind(_required_string(value, "kind")),
+ occurred_at=_required_string(value, "occurred_at"),
+ schema_field_urn=field,
+ before_digest=_sha256_label(value.get("before_version")),
+ after_digest=_sha256_label(value.get("after_version")),
+ )
+
+
+def _receipt_identity(case: BenchmarkCase, ablation: Ablation) -> tuple[str, str]:
+ digest = hashlib.sha256(f"{case.case_id}:{ablation.value}".encode()).hexdigest()
+ return (
+ f"gbx:receipt:sha256:{digest}",
+ f"urn:li:document:glassbox.receipt.{digest}",
+ )
+
+
+def _signal_dependencies(
+ case: BenchmarkCase,
+ ablation: Ablation,
+ assets: tuple[str, ...],
+ state: EvidenceState,
+) -> tuple[EvidenceDependency, ...]:
+ role = EvidenceRole(_required_string(case.dependency, "role"))
+ if not assets:
+ return (
+ EvidenceDependency(
+ evidence_id=f"evidence-{case.case_id}-{ablation.value.lower()}-unresolved",
+ datahub_urn=None,
+ schema_field_urn=None,
+ state=EvidenceState.UNKNOWN,
+ role=role,
+ observed_at=None,
+ representation_digest=None,
+ ),
+ )
+ return tuple(
+ EvidenceDependency(
+ evidence_id=f"evidence-{case.case_id}-{ablation.value.lower()}-{index}",
+ datahub_urn=asset,
+ schema_field_urn=None,
+ state=state,
+ role=role,
+ observed_at=None,
+ representation_digest=None,
+ )
+ for index, asset in enumerate(assets)
+ )
+
+
+def project_profile(case: BenchmarkCase, ablation: Ablation) -> ReceiptDependencyProfile:
+ """Remove only the evidence capabilities named by one ablation."""
+
+ dependency = _base_dependency(case)
+ if ablation is Ablation.STATIC_DECLARED_LINEAGE:
+ dependencies = _signal_dependencies(
+ case,
+ ablation,
+ case.static_declared_assets,
+ EvidenceState.DECLARED,
+ )
+ lineage = FieldLineageProof()
+ elif ablation is Ablation.RAW_OTEL_TRACES:
+ dependencies = _signal_dependencies(
+ case,
+ ablation,
+ case.raw_otel_assets,
+ EvidenceState.INFERRED,
+ )
+ lineage = FieldLineageProof()
+ elif ablation is Ablation.GLASSBOX_WITHOUT_FIELD_EVIDENCE:
+ dependencies = (
+ EvidenceDependency(
+ evidence_id=dependency.evidence_id,
+ datahub_urn=dependency.datahub_urn,
+ schema_field_urn=None,
+ state=dependency.state,
+ role=dependency.role,
+ observed_at=dependency.observed_at,
+ representation_digest=dependency.representation_digest,
+ ),
+ )
+ lineage = _lineage(case.lineage, remove_field_proof=True)
+ elif ablation is Ablation.GLASSBOX_WITHOUT_METADATA_SNAPSHOTS:
+ dependencies = (
+ EvidenceDependency(
+ evidence_id=dependency.evidence_id,
+ datahub_urn=dependency.datahub_urn,
+ schema_field_urn=dependency.schema_field_urn,
+ state=dependency.state,
+ role=dependency.role,
+ observed_at=None,
+ representation_digest=None,
+ ),
+ )
+ lineage = _lineage(case.lineage, remove_field_proof=False)
+ else:
+ dependencies = (dependency,)
+ lineage = _lineage(case.lineage, remove_field_proof=False)
+ receipt_id, document_urn = _receipt_identity(case, ablation)
+ return ReceiptDependencyProfile(
+ receipt_id=receipt_id,
+ document_urn=document_urn,
+ ended_at="2026-08-08T12:00:01Z",
+ dependencies=dependencies,
+ field_lineage=lineage,
+ )
+
+
+def _ratio(numerator: int, denominator: int) -> dict[str, int | float | None]:
+ return {
+ "numerator": numerator,
+ "denominator": denominator,
+ "value": None if denominator == 0 else round(numerator / denominator, 6),
+ }
+
+
+def _resolution_metrics(
+ cases: Sequence[BenchmarkCase], profiles: Sequence[ReceiptDependencyProfile]
+) -> dict[str, Any]:
+ true_assets = predicted_assets = correct_assets = 0
+ true_fields = predicted_fields = correct_fields = 0
+ failed_assets: list[str] = []
+ failed_fields: list[str] = []
+ for case, profile in zip(cases, profiles, strict=True):
+ expected_assets = set(case.ground_truth_assets)
+ expected_fields = set(case.ground_truth_fields)
+ projected_assets = {
+ item.datahub_urn for item in profile.dependencies if item.datahub_urn is not None
+ }
+ projected_fields = {
+ item.schema_field_urn
+ for item in profile.dependencies
+ if item.schema_field_urn is not None
+ }
+ true_assets += len(expected_assets)
+ predicted_assets += len(projected_assets)
+ correct_assets += len(expected_assets & projected_assets)
+ true_fields += len(expected_fields)
+ predicted_fields += len(projected_fields)
+ correct_fields += len(expected_fields & projected_fields)
+ if projected_assets != expected_assets:
+ failed_assets.append(case.case_id)
+ if projected_fields != expected_fields:
+ failed_fields.append(case.case_id)
+ return {
+ "asset_precision": _ratio(correct_assets, predicted_assets),
+ "asset_recall": _ratio(correct_assets, true_assets),
+ "field_precision": _ratio(correct_fields, predicted_fields),
+ "field_recall": _ratio(correct_fields, true_fields),
+ "asset_resolution_failed_cases": sorted(failed_assets),
+ "field_resolution_failed_cases": sorted(failed_fields),
+ }
+
+
+def _impact_metrics(results: Sequence[tuple[BenchmarkCase, ImpactState]]) -> dict[str, Any]:
+ contaminated = [item for item in results if item[0].truth is Truth.CONTAMINATED]
+ clean = [item for item in results if item[0].truth is Truth.CLEAN]
+ indeterminate = [item for item in results if item[0].truth is Truth.INDETERMINATE]
+
+ def quarantined(state: ImpactState) -> bool:
+ return state in {
+ ImpactState.STALE,
+ ImpactState.AT_RISK,
+ ImpactState.UNKNOWN,
+ }
+
+ contamination_quarantined = sum(quarantined(state) for _, state in contaminated)
+ clean_quarantined = sum(quarantined(state) for _, state in clean)
+ confident_true = sum(state is ImpactState.STALE for _, state in contaminated)
+ confident_false = sum(state is ImpactState.STALE for _, state in clean)
+ honest_unknown = sum(state in _UNCERTAIN_STATES for _, state in indeterminate)
+ false_cases = sorted(case.case_id for case, state in clean if quarantined(state))
+ missed_cases = sorted(case.case_id for case, state in contaminated if not quarantined(state))
+ dishonest_cases = sorted(
+ case.case_id for case, state in indeterminate if state not in _UNCERTAIN_STATES
+ )
+ return {
+ "quarantine_precision": _ratio(
+ contamination_quarantined,
+ contamination_quarantined + clean_quarantined,
+ ),
+ "quarantine_recall": _ratio(contamination_quarantined, len(contaminated)),
+ "false_invalidation_rate": _ratio(clean_quarantined, len(clean)),
+ "missed_invalidation_rate": _ratio(
+ len(contaminated) - contamination_quarantined,
+ len(contaminated),
+ ),
+ "confident_stale_precision": _ratio(
+ confident_true,
+ confident_true + confident_false,
+ ),
+ "confident_stale_recall": _ratio(confident_true, len(contaminated)),
+ "unknown_at_risk_honesty_rate": _ratio(honest_unknown, len(indeterminate)),
+ "false_invalidation_cases": false_cases,
+ "missed_invalidation_cases": missed_cases,
+ "dishonest_indeterminate_cases": dishonest_cases,
+ }
+
+
+def _evaluate_variant(cases: Sequence[BenchmarkCase], ablation: Ablation) -> dict[str, Any]:
+ profiles = [project_profile(case, ablation) for case in cases]
+ case_results: list[dict[str, Any]] = []
+ states: list[tuple[BenchmarkCase, ImpactState]] = []
+ for case, profile in zip(cases, profiles, strict=True):
+ assessment = classify_materiality(profile, _change(case))
+ states.append((case, assessment.state))
+ case_results.append(
+ {
+ "case_id": case.case_id,
+ "truth": case.truth.value,
+ "state": assessment.state.value,
+ "reason_code": assessment.reason_code,
+ "quarantine_required": assessment.quarantine_required,
+ "matched_evidence_count": len(assessment.matched_evidence_ids),
+ "resolved_asset_count": len(
+ {
+ item.datahub_urn
+ for item in profile.dependencies
+ if item.datahub_urn is not None
+ }
+ ),
+ "resolved_field_count": len(
+ {
+ item.schema_field_urn
+ for item in profile.dependencies
+ if item.schema_field_urn is not None
+ }
+ ),
+ }
+ )
+ return {
+ "variant": ablation.value,
+ "policy_version": "glassbox.materiality.v1",
+ "removed_capabilities": _REMOVED_CAPABILITIES[ablation],
+ "resolution": _resolution_metrics(cases, profiles),
+ "impact": _impact_metrics(states),
+ "cases": case_results,
+ }
+
+
+def _inventory(receipt: Mapping[str, Any]) -> ResourceInventory:
+ resources: list[ResourceAvailability] = []
+ singular = (
+ (ResourceKind.AGENT, receipt["agent"], True),
+ (ResourceKind.WORKFLOW, receipt["workflow"], False),
+ )
+ plural = (
+ (ResourceKind.MODEL, receipt["models"], True),
+ (ResourceKind.SKILL, receipt["skills"], True),
+ (ResourceKind.TOOL, receipt["tools"], True),
+ )
+ for kind, item, source_required in singular:
+ if not isinstance(item, Mapping):
+ raise RuntimeError("replay benchmark receipt resource is invalid")
+ resources.append(_availability(kind, item, source_required=source_required))
+ for kind, items, source_required in plural:
+ if not isinstance(items, list):
+ raise RuntimeError("replay benchmark receipt resource list is invalid")
+ for item in items:
+ if not isinstance(item, Mapping):
+ raise RuntimeError("replay benchmark receipt resource is invalid")
+ resources.append(_availability(kind, item, source_required=source_required))
+ return ResourceInventory(tuple(resources))
+
+
+def _availability(
+ kind: ResourceKind,
+ item: Mapping[str, Any],
+ *,
+ source_required: bool,
+) -> ResourceAvailability:
+ source = item.get("source_digest")
+ schema = item.get("schema_digest")
+ source_digest = source.get("value") if isinstance(source, Mapping) else None
+ schema_digest = schema.get("value") if isinstance(schema, Mapping) else None
+ if source_required and not isinstance(source_digest, str):
+ raise RuntimeError("replay benchmark resource lacks a source digest")
+ return ResourceAvailability(
+ kind=kind,
+ resource_id=str(item["id"]),
+ version=str(item["version"]),
+ source_digest=source_digest,
+ schema_digest=schema_digest if kind is ResourceKind.TOOL else None,
+ )
+
+
+def _reseal_receipt(
+ source: Mapping[str, Any],
+ *,
+ effect: str,
+ eligibility: str,
+) -> dict[str, Any]:
+ payload = copy.deepcopy(dict(source))
+ payload.pop("receipt_id")
+ payload.pop("integrity")
+ payload["actions"][0]["effect"] = effect
+ payload["replay"]["eligibility"] = eligibility
+ return seal_receipt(
+ payload,
+ signing_keys=(SigningKey("benchmark-source", Ed25519PrivateKey.generate()),),
+ )
+
+
+def _replay_case(
+ source: Mapping[str, Any],
+ *,
+ inventory: ResourceInventory,
+ supplement: ReplaySupplement,
+) -> ReplayDecision:
+ bundle = build_replay_bundle(
+ source,
+ mode=ReplayMode.PINNED,
+ supplement=supplement,
+ signing_keys=(SigningKey("benchmark-bundle", Ed25519PrivateKey.generate()),),
+ )
+ return plan_replay(
+ bundle,
+ source_receipt=source,
+ inventory=inventory,
+ evaluated_at="2026-08-08T12:30:00Z",
+ ).decision
+
+
+def _replay_policy_proof() -> dict[str, Any]:
+ source = build_signed_receipt(schema_field_urn=FIELD_URN, replay_ready=True)
+ safe_supplement = ReplaySupplement(
+ input_digest=digest_value({"benchmark": "authorized-input"}),
+ input_reference="artifact://glassbox-benchmark/replay-input",
+ feature_flags_digest=hashlib.sha256(b"benchmark-flags-v1").hexdigest(),
+ )
+ irreversible = _reseal_receipt(
+ source,
+ effect="IRREVERSIBLE",
+ eligibility="UNREPLAYABLE",
+ )
+ cases = (
+ (
+ "safe-read-only",
+ _replay_case(source, inventory=_inventory(source), supplement=safe_supplement),
+ ReplayDecision.ALLOW,
+ ),
+ (
+ "irreversible-refusal",
+ _replay_case(
+ irreversible,
+ inventory=_inventory(irreversible),
+ supplement=safe_supplement,
+ ),
+ ReplayDecision.BLOCK,
+ ),
+ (
+ "missing-resource-refusal",
+ _replay_case(
+ source,
+ inventory=ResourceInventory(()),
+ supplement=safe_supplement,
+ ),
+ ReplayDecision.BLOCK,
+ ),
+ (
+ "missing-execution-material-dry-only",
+ _replay_case(
+ source,
+ inventory=_inventory(source),
+ supplement=ReplaySupplement(),
+ ),
+ ReplayDecision.DRY_RUN_ONLY,
+ ),
+ )
+ correct = sum(actual is expected for _, actual, expected in cases)
+ return {
+ "policy_version": "glassbox.replay-policy.v1",
+ "correctness": _ratio(correct, len(cases)),
+ "cases": [
+ {
+ "case_id": case_id,
+ "actual": actual.value,
+ "expected": expected.value,
+ "correct": actual is expected,
+ }
+ for case_id, actual, expected in cases
+ ],
+ }
+
+
+def _redaction_proof() -> dict[str, Any]:
+ policy = RedactionPolicy(sensitive_paths=frozenset({"customer.ssn"}))
+ sensitive_keys = (
+ "authorization",
+ "api_key",
+ "cookie",
+ "password",
+ "refresh_token",
+ "secret",
+ "set-cookie",
+ "token",
+ "x-api-key",
+ )
+ sentinels = [f"benchmark-sensitive-value-{index}" for index in range(len(sensitive_keys) + 1)]
+ payload: dict[str, Any] = {key: sentinels[index] for index, key in enumerate(sensitive_keys)}
+ payload["customer"] = {"ssn": sentinels[-1], "segment": "synthetic"}
+ rendered = json.dumps(policy.sanitize(payload), sort_keys=True)
+ escapes = sum(sentinel in rendered for sentinel in sentinels)
+ return {
+ "policy_id": policy.policy_id,
+ "escape_rate": _ratio(escapes, len(sentinels)),
+ "plaintext_values_retained": escapes,
+ }
+
+
+def _percentiles(samples_ns: Sequence[int], *, unit_divisor: float) -> dict[str, float | int]:
+ if not samples_ns:
+ raise ValueError("performance measurement requires at least one sample")
+ ordered = sorted(samples_ns)
+
+ def selected(percentile: float) -> float:
+ index = max(0, min(len(ordered) - 1, round((len(ordered) - 1) * percentile)))
+ return round(ordered[index] / unit_divisor, 6)
+
+ return {
+ "samples": len(ordered),
+ "p50": selected(0.50),
+ "p95": selected(0.95),
+ "min": round(ordered[0] / unit_divisor, 6),
+ "max": round(ordered[-1] / unit_divisor, 6),
+ }
+
+
+def _measure_call(function: Any) -> int:
+ started = time.perf_counter_ns()
+ function()
+ return time.perf_counter_ns() - started
+
+
+def _performance_measurement(
+ cases: Sequence[BenchmarkCase],
+ *,
+ samples: int,
+ compilation_samples: int,
+) -> dict[str, Any]:
+ if samples == 0 and compilation_samples == 0:
+ return {"status": "NOT_MEASURED"}
+ if samples < 1 or compilation_samples < 1:
+ raise ValueError("both performance sample counts must be positive or both zero")
+ classification: dict[str, dict[str, float | int]] = {}
+ for ablation in Ablation:
+ prepared = [(project_profile(case, ablation), _change(case)) for case in cases]
+
+ suite_samples: list[int] = []
+ for _ in range(samples):
+ started = time.perf_counter_ns()
+ for profile, change in prepared:
+ classify_materiality(profile, change)
+ suite_samples.append(time.perf_counter_ns() - started)
+
+ classification[ablation.value] = _percentiles(
+ suite_samples,
+ unit_divisor=1_000.0,
+ )
+
+ def baseline_agent() -> None:
+ aggregate = _synthetic_order_aggregate("synthetic-benchmark-customer")
+ aggregate["average_order_value"] = str(aggregate["average_order_value"])
+ apply_replayable_pricing_policy(aggregate)
+
+ runtime = GlassBox(InMemorySink())
+ instrumented_agent = build_replayable_pricing_agent(runtime, schema_field_urn=FIELD_URN)
+
+ def observed_agent() -> None:
+ instrumented_agent("synthetic-benchmark-customer")
+
+ baseline_samples = [_measure_call(baseline_agent) for _ in range(samples)]
+ observed_samples = [_measure_call(observed_agent) for _ in range(samples)]
+ baseline_summary = _percentiles(baseline_samples, unit_divisor=1_000.0)
+ observed_summary = _percentiles(observed_samples, unit_divisor=1_000.0)
+ compilation = _percentiles(
+ [
+ _measure_call(
+ lambda: build_signed_receipt(schema_field_urn=FIELD_URN, replay_ready=True)
+ )
+ for _ in range(compilation_samples)
+ ],
+ unit_divisor=1_000_000.0,
+ )
+ baseline_p50 = float(baseline_summary["p50"])
+ observed_p50 = float(observed_summary["p50"])
+ baseline_p95 = float(baseline_summary["p95"])
+ observed_p95 = float(observed_summary["p95"])
+ return {
+ "status": "MEASURED_OFFLINE",
+ "clock": "time.perf_counter_ns",
+ "environment": {
+ "python": platform.python_version(),
+ "implementation": platform.python_implementation(),
+ "system": platform.system(),
+ "machine": platform.machine(),
+ },
+ "policy_suite_latency_microseconds": classification,
+ "agent_runtime_microseconds": {
+ "baseline": baseline_summary,
+ "glassbox_observed": observed_summary,
+ "overhead_p50": round(observed_p50 - baseline_p50, 6),
+ "overhead_p95": round(observed_p95 - baseline_p95, 6),
+ },
+ "receipt_compilation_milliseconds": compilation,
+ "scope": (
+ "Single-process deterministic microbenchmark; excludes network, DataHub, MCP, "
+ "PostgreSQL, container startup, and model-provider latency."
+ ),
+ }
+
+
+def _live_evidence(path: Path | None) -> dict[str, Any]:
+ if path is None:
+ return {"status": "NOT_REQUESTED"}
+ raw = path.read_bytes()
+ report = json.loads(raw)
+ if not isinstance(report, Mapping) or not report.get("valid"):
+ raise RuntimeError("live flagship evidence is not a valid report")
+ source = _required_mapping(report, "source_decision")
+ negative = _required_mapping(report, "negative_control")
+ invalidation = _required_mapping(report, "invalidation")
+ replay = _required_mapping(report, "corrected_replay")
+ supersession = _required_mapping(report, "supersession")
+ closure = _required_mapping(report, "incident_closure")
+ source_publication = _required_mapping(_required_mapping(source, "publication"), "datahub")
+ replay_publication = _required_mapping(_required_mapping(replay, "publication"), "datahub")
+ write_units = {
+ "source_receipt_emissions": int(source_publication["emissions"]),
+ "invalidation_emissions": int(invalidation["first_delivery_emissions"]),
+ "replay_receipt_emissions": int(replay_publication["emissions"]),
+ "supersession_emissions": int(supersession["emissions"]),
+ "incident_closure_aspect_writes": int(closure["aspect_writes"]),
+ }
+ idempotent = (
+ source.get("completed_redelivery_datahub_write_performed") is False,
+ invalidation.get("redelivery_emissions") == 0,
+ replay.get("completed_redelivery_datahub_write_performed") is False,
+ )
+ relative = path.name if path.parent.name == "compatibility" else path.as_posix()
+ return {
+ "status": "MEASURED_LIVE_REPORT",
+ "source_report": relative,
+ "source_report_sha256": hashlib.sha256(raw).hexdigest(),
+ "datahub_write_units": {
+ "measurement_unit": (
+ "adapter-reported proposal emissions or aspect writes; not storage rows"
+ ),
+ "breakdown": write_units,
+ "total": sum(write_units.values()),
+ },
+ "completed_redelivery_zero_write_rate": _ratio(sum(idempotent), len(idempotent)),
+ "negative_control_zero_write_rate": _ratio(
+ int(
+ negative.get("first_delivery_emissions") == 0
+ and negative.get("redelivery_emissions") == 0
+ ),
+ 1,
+ ),
+ "corrected_replay_success_rate": _ratio(
+ int(replay.get("execution_status") == "SUCCEEDED"),
+ 1,
+ ),
+ "verified_incident_closure_rate": _ratio(int(closure.get("valid") is True), 1),
+ }
+
+
+def _report_id(material: Mapping[str, Any]) -> str:
+ digest = hashlib.sha256(_BENCHMARK_DOMAIN + canonicalize(material)).hexdigest()
+ return f"gbx:benchmark:sha256:{digest}"
+
+
+def build_benchmark_report(
+ *,
+ fixture_path: Path = DEFAULT_FIXTURES,
+ live_report_path: Path | None = DEFAULT_LIVE_REPORT,
+ performance_samples: int = 0,
+ compilation_samples: int = 0,
+) -> dict[str, Any]:
+ """Build a raw-free benchmark report with exact denominators and failed cases."""
+
+ raw_fixtures, cases = load_cases(fixture_path)
+ variants = [_evaluate_variant(cases, ablation) for ablation in Ablation]
+ replay = _replay_policy_proof()
+ redaction = _redaction_proof()
+ correctness_material: dict[str, Any] = {
+ "benchmark": BENCHMARK_NAME,
+ "contract_version": BENCHMARK_VERSION,
+ "fixture_sha256": hashlib.sha256(canonicalize(raw_fixtures)).hexdigest(),
+ "case_count": len(cases),
+ "variants": variants,
+ "replay_policy": replay,
+ "redaction": redaction,
+ }
+ report: dict[str, Any] = {
+ "benchmark_id": _report_id(correctness_material),
+ **correctness_material,
+ "truth_distribution": {
+ truth.value: sum(case.truth is truth for case in cases) for truth in Truth
+ },
+ "primary_result": {
+ "selected_variant": Ablation.FULL_GLASSBOX.value,
+ "selection_rule": (
+ "Minimize missed invalidation, then false invalidation, while requiring "
+ "perfect indeterminate-case honesty."
+ ),
+ "selection_is_model_judged": False,
+ },
+ "performance": _performance_measurement(
+ cases,
+ samples=performance_samples,
+ compilation_samples=compilation_samples,
+ ),
+ "live_evidence": _live_evidence(live_report_path),
+ "metric_coverage": {
+ "asset_resolution_precision_recall": "MEASURED_SYNTHETIC_EXACT",
+ "field_resolution_precision_recall": "MEASURED_SYNTHETIC_EXACT",
+ "false_and_missed_invalidation": "MEASURED_SYNTHETIC_EXACT",
+ "unknown_at_risk_honesty": "MEASURED_SYNTHETIC_EXACT",
+ "receipt_compilation_latency": (
+ "MEASURED_OFFLINE" if performance_samples else "NOT_MEASURED"
+ ),
+ "agent_overhead_p50_p95": (
+ "MEASURED_OFFLINE" if performance_samples else "NOT_MEASURED"
+ ),
+ "datahub_write_amplification": (
+ "MEASURED_LIVE_REPORT" if live_report_path is not None else "NOT_MEASURED"
+ ),
+ "idempotent_event_handling": (
+ "MEASURED_LIVE_REPORT" if live_report_path is not None else "NOT_MEASURED"
+ ),
+ "replay_success_and_refusal": (
+ "MEASURED_DETERMINISTIC_AND_LIVE"
+ if live_report_path is not None
+ else "MEASURED_DETERMINISTIC"
+ ),
+ "secret_redaction_escape": "MEASURED_SYNTHETIC_EXACT",
+ "fresh_checkout_setup": "NOT_MEASURED_ON_A_FRESH_HOST",
+ },
+ "limitations": [
+ (
+ "Synthetic correctness fixtures measure a closed causal contract, not "
+ "production prevalence."
+ ),
+ (
+ "Raw OpenTelemetry means spans without GlassBox-qualified DataHub field "
+ "and snapshot attributes."
+ ),
+ (
+ "Offline latency excludes service, network, model-provider, and container "
+ "startup time."
+ ),
+ (
+ "The live write unit is an adapter emission/aspect write, not an underlying "
+ "database row."
+ ),
+ (
+ "A fresh-host success rate needs independent clean-host repetitions; this "
+ "report does not invent it."
+ ),
+ ],
+ "privacy": {
+ "synthetic_fixtures_only": True,
+ "raw_prompts_retained": False,
+ "raw_evidence_retained": False,
+ "raw_action_inputs_retained": False,
+ "raw_outputs_retained": False,
+ "credentials_retained": False,
+ },
+ }
+ return report
+
+
+def validate_benchmark_report(
+ report: Mapping[str, Any], schema_path: Path = DEFAULT_SCHEMA
+) -> None:
+ schema = json.loads(schema_path.read_text(encoding="utf-8"))
+ Draft202012Validator(schema, format_checker=Draft202012Validator.FORMAT_CHECKER).validate(
+ report
+ )
+ material = {
+ key: report[key]
+ for key in (
+ "benchmark",
+ "contract_version",
+ "fixture_sha256",
+ "case_count",
+ "variants",
+ "replay_policy",
+ "redaction",
+ )
+ }
+ if report.get("benchmark_id") != _report_id(material):
+ raise RuntimeError("benchmark report content address does not verify")
+
+
+def _parser() -> argparse.ArgumentParser:
+ parser = argparse.ArgumentParser(prog="glassbox-agent-invalidation-benchmark")
+ parser.add_argument("--fixtures", type=Path, default=DEFAULT_FIXTURES)
+ parser.add_argument("--live-report", type=Path, default=DEFAULT_LIVE_REPORT)
+ parser.add_argument("--without-live-report", action="store_true")
+ parser.add_argument("--performance-samples", type=int, default=200)
+ parser.add_argument("--compilation-samples", type=int, default=20)
+ parser.add_argument("--output", type=Path, default=None)
+ return parser
+
+
+def main(argv: Sequence[str] | None = None) -> int:
+ args = _parser().parse_args(argv)
+ report = build_benchmark_report(
+ fixture_path=args.fixtures,
+ live_report_path=None if args.without_live_report else args.live_report,
+ performance_samples=args.performance_samples,
+ compilation_samples=args.compilation_samples,
+ )
+ validate_benchmark_report(report)
+ rendered = json.dumps(report, indent=2, sort_keys=True) + "\n"
+ if args.output is not None:
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ args.output.write_text(rendered, encoding="utf-8")
+ else:
+ sys.stdout.write(rendered)
+ return 0
+
+
+if __name__ == "__main__":
+ raise SystemExit(main())
diff --git a/deploy/production/.env.production.example b/deploy/production/.env.production.example
new file mode 100644
index 0000000..87ec0bf
--- /dev/null
+++ b/deploy/production/.env.production.example
@@ -0,0 +1,33 @@
+# Public edge. TierHive HAProxy should forward both hosts to this port. The
+# apex serves only the public site/docs and OTLP; the console host requires OAuth.
+GLASSBOX_PUBLIC_DOMAIN=glassboxhq.xyz
+GLASSBOX_CONSOLE_DOMAIN=app.glassboxhq.xyz
+GLASSBOX_EDGE_PORT=8080
+GLASSBOX_IMAGE_TAG=rc1
+GLASSBOX_ORGANIZATION=glassbox-demo
+GLASSBOX_ADMIN_EMAILS=admin@example.com
+
+# GitHub OAuth App registered with callback:
+# https://app.glassboxhq.xyz/oauth2/callback
+GITHUB_OAUTH_CLIENT_ID=
+GITHUB_OAUTH_CLIENT_SECRET=
+GITHUB_ALLOWED_USERS=your-github-username
+
+# Generate with: openssl rand -base64 32 | tr -- '+/' '-_'
+OAUTH_COOKIE_SECRET=
+
+# Generate with: glassbox-control master-key
+GLASSBOX_CONTROL_MASTER_KEY=
+GLASSBOX_CONTROL_MASTER_KEY_ID=control-v1
+
+# Generate each value independently with at least 32 random bytes.
+GLASSBOX_CONTROL_API_TOKEN=
+GLASSBOX_FORENSICS_API_TOKEN=
+GLASSBOX_POSTGRES_PASSWORD=
+
+# Receipt authority. Generate the private key and matching trusted-signers file
+# through the GlassBox signer tooling; never commit either deployment artifact.
+GLASSBOX_RECEIPT_SIGNING_KEY_ID=
+GLASSBOX_RECEIPT_SIGNING_KEY=
+GLASSBOX_SIGNER_TRUST_POLICY_PATH=
+GLASSBOX_STATE_POSTGRES_SCHEMA=glassbox
diff --git a/deploy/production/Caddyfile b/deploy/production/Caddyfile
new file mode 100644
index 0000000..54c30f7
--- /dev/null
+++ b/deploy/production/Caddyfile
@@ -0,0 +1,96 @@
+{
+ auto_https off
+ admin off
+}
+
+:8080 {
+ request_body {
+ max_size 8MB
+ }
+
+ header {
+ -Server
+ Strict-Transport-Security "max-age=31536000; includeSubDomains"
+ X-Content-Type-Options "nosniff"
+ X-Frame-Options "DENY"
+ Referrer-Policy "strict-origin-when-cross-origin"
+ Permissions-Policy "camera=(), microphone=(), geolocation=()"
+ }
+
+ # Keep the infrastructure probe outside the human OAuth boundary. Using a
+ # path-matched handle also keeps it mutually exclusive with the fallback.
+ handle /healthz {
+ respond 200
+ }
+
+ @oauth {
+ host {$GLASSBOX_CONSOLE_DOMAIN}
+ path /oauth2/*
+ }
+ handle @oauth {
+ reverse_proxy oauth2-proxy:4180
+ }
+
+ # Agent traffic has its own individually revocable bearer credentials and
+ # never enters the human OAuth session boundary.
+ @otlp path /v1/traces
+ handle @otlp {
+ reverse_proxy receiver:4318
+ }
+
+ # The public product host serves only the landing page, documentation, and
+ # their static assets. The app itself also redirects operator routes, but the
+ # edge allowlist is the security boundary: /api and console routes never reach
+ # an unauthenticated server handler on this host.
+ @public_surface {
+ host {$GLASSBOX_PUBLIC_DOMAIN}
+ path / /home /docs /docs/* /architecture /_next/* /favicon.svg /og.png /fonts/* /media/*
+ }
+ handle @public_surface {
+ request_header -X-Auth-Request-User
+ request_header -X-Auth-Request-Email
+ request_header -X-GlassBox-Role
+ reverse_proxy console:3000
+ }
+
+ @public_unknown host {$GLASSBOX_PUBLIC_DOMAIN}
+ handle @public_unknown {
+ respond 404
+ }
+
+ @console_host host {$GLASSBOX_CONSOLE_DOMAIN}
+ handle @console_host {
+ # `route` preserves this security-sensitive order. Untrusted identity
+ # assertions are removed before OAuth, then only the identity copied
+ # from OAuth2 Proxy is forwarded to the console.
+ route {
+ request_header -X-Auth-Request-User
+ request_header -X-Auth-Request-Email
+ request_header -X-GlassBox-Role
+
+ forward_auth oauth2-proxy:4180 {
+ uri /oauth2/auth
+ header_up X-Real-IP {remote_host}
+ copy_headers X-Auth-Request-User X-Auth-Request-Email
+
+ # oauth2-proxy's auth endpoint correctly returns 401 for a missing
+ # session. Turn that browser-only failure into the start of the OAuth
+ # flow; agent traffic is handled above and never enters this branch.
+ @unauthorized status 401
+ handle_response @unauthorized {
+ # Keep the post-login destination same-origin and relative. This
+ # avoids relying on the backend HTTP scheme behind TLS termination.
+ redir * /oauth2/sign_in?rd={uri}
+ }
+ }
+
+ reverse_proxy console:3000
+ }
+ }
+
+ # Refuse unknown Host headers rather than routing them into the authenticated
+ # application by accident.
+ handle {
+ respond 421
+ }
+}
diff --git a/deploy/production/Dockerfile.console b/deploy/production/Dockerfile.console
new file mode 100644
index 0000000..9342e55
--- /dev/null
+++ b/deploy/production/Dockerfile.console
@@ -0,0 +1,25 @@
+FROM node:22.20.0-bookworm-slim AS build
+
+WORKDIR /opt/console
+COPY apps/console/package.json apps/console/package-lock.json ./
+RUN npm ci
+ENV NEXT_TELEMETRY_DISABLED=1
+COPY apps/console ./
+ENV GLASSBOX_NEXT_STANDALONE_BUILD=1
+RUN npx next build --webpack
+
+FROM node:22.20.0-bookworm-slim AS runtime
+
+ENV NODE_ENV=production \
+ NEXT_TELEMETRY_DISABLED=1 \
+ HOSTNAME=0.0.0.0 \
+ PORT=3000
+WORKDIR /opt/console
+
+COPY --from=build --chown=node:node /opt/console/.next/standalone ./
+COPY --from=build --chown=node:node /opt/console/.next/static ./.next/static
+COPY --from=build --chown=node:node /opt/console/public ./public
+
+USER node
+EXPOSE 3000
+CMD ["node", "server.js"]
diff --git a/deploy/production/Dockerfile.python b/deploy/production/Dockerfile.python
new file mode 100644
index 0000000..1197b8a
--- /dev/null
+++ b/deploy/production/Dockerfile.python
@@ -0,0 +1,30 @@
+FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim AS runtime
+
+ENV PYTHONDONTWRITEBYTECODE=1 \
+ PYTHONUNBUFFERED=1 \
+ UV_COMPILE_BYTECODE=1 \
+ UV_LINK_MODE=copy
+
+WORKDIR /opt/glassbox
+
+COPY pyproject.toml uv.lock README.md ./
+COPY packages ./packages
+COPY services ./services
+COPY schemas ./schemas
+
+RUN uv sync --frozen --no-dev \
+ --extra control \
+ --extra datahub \
+ --extra mcp \
+ --extra postgres
+
+ENV PATH="/opt/glassbox/.venv/bin:${PATH}"
+
+RUN addgroup --system --gid 10001 glassbox \
+ && adduser --system --uid 10001 --ingroup glassbox --home /nonexistent glassbox \
+ && mkdir -p /var/lib/glassbox-control \
+ && chown -R 10001:10001 /var/lib/glassbox-control
+
+USER 10001:10001
+
+ENTRYPOINT []
diff --git a/deploy/production/README.md b/deploy/production/README.md
new file mode 100644
index 0000000..de0077e
--- /dev/null
+++ b/deploy/production/README.md
@@ -0,0 +1,120 @@
+# Production release-candidate deployment
+
+This profile deploys an organization-owned GlassBox control and evidence plane.
+Only the edge port is published. The apex host serves the public product site and
+documentation, the console host requires GitHub OAuth, and OTLP ingestion uses
+individually issued GlassBox keys. PostgreSQL and internal service APIs stay on an
+isolated container network.
+
+The console image is a native Next.js standalone runtime. Vinext, Vite, Wrangler,
+and the rest of the local/Sites toolchain remain build-time dependencies and are
+absent from the production image. The release check requires a zero-finding
+`npm audit --omit=dev` result for the runtime graph.
+
+## Required operator inputs
+
+1. A VPS with Docker Compose, persistent storage, and enough headroom for GlassBox.
+ DataHub may be external; this stack does not install or pretend to own DataHub.
+2. A public hostname and a separate console hostname routed to the same edge. The
+ reference pair is `glassboxhq.xyz` and `app.glassboxhq.xyz`.
+3. A GitHub OAuth App whose callback is
+ `https://app.glassboxhq.xyz/oauth2/callback` (replace the host for another domain).
+ The reference proxy requests `user:email read:org`: email identifies the user,
+ while GitHub requires `read:org` for the organization list that OAuth2 Proxy
+ uses to populate its authenticated group set.
+4. A scoped DataHub service account that can read catalog entities and upsert the
+ GlassBox Document/Incident aspects used by the compiler and invalidation Action.
+5. A receipt signing key and matching operator trust policy.
+6. Independent random values for the control master key, internal API credentials,
+ OAuth session secret, and PostgreSQL password.
+
+Copy `.env.production.example` to an untracked `.env.production`, fill it through
+the VPS secret boundary, and restrict it to the deployment user. Generate the
+control master key with `glassbox-control master-key`; generate all other bearer
+values independently. Never reuse a DataHub token as a GlassBox credential.
+
+The hosted RC also runs a backend-only reference DataHub Core estate as a separate
+Compose project. It is not a dependency bundled into this profile: it publishes no
+DataHub port, exposes no DataHub UI, attaches GMS to the GlassBox private network
+through one explicit alias, and keeps MySQL, Kafka, and OpenSearch on its own
+project network. Customer deployments should normally connect GlassBox to the
+organization's existing DataHub estate.
+
+## Start and verify
+
+```bash
+docker compose --env-file .env.production -f compose.yml config --quiet
+docker compose --env-file .env.production -f compose.yml build
+docker compose --env-file .env.production -f compose.yml up -d
+curl --fail http://127.0.0.1:8080/healthz
+```
+
+Sign in through GitHub at the configured console hostname, open **Connections**, and enter the
+DataHub GMS origin, DataHub UI origin, and service-account token. **Verify & save**
+performs an actual SDK connection test, one deterministic synthetic Document upsert,
+and direct readback before the credential is encrypted. The receiver waits without
+accepting traffic until this proof exists, then activates automatically.
+
+Create a named ingestion key in the **Agent keys** tab and configure an exporter:
+
+```text
+OTEL_EXPORTER_OTLP_ENDPOINT=https://glassboxhq.xyz
+OTEL_EXPORTER_OTLP_HEADERS=Authorization=Bearer
+```
+
+## TierHive and DNS
+
+For the current infrastructure, configure TierHive HAProxy to terminate TLS for both
+the public and console domains and forward them to the selected VPS private address
+on `GLASSBOX_EDGE_PORT` while preserving the original Host header. Point both DNS
+records at the exact TierHive regional HAProxy address. Verify the origin health
+first, then the public landing page and docs, the console OAuth callback and
+authentication, a DataHub connection proof, key issuance/revocation, and an OTLP 200
+before calling the deployment live.
+
+Do not attach this stack to an occupied VPS until its CPU, memory, disk, port, and
+backup headroom have been inspected. Do not expose ports 3000, 4180, 4318, 5432,
+8788, or 8790 directly.
+
+## RC proof recorded on 2026-08-10
+
+The packaged control path was exercised against the retained, commit-pinned
+DataHub Core `v1.6.0` estate with DataHub SDK `1.6.0.15`. The verifier connected,
+upserted `urn:li:document:glassbox.connection.probe`, directly read it back, and
+saved only the AES-256-GCM encrypted service credential.
+
+On the isolated hosted VPS, the separate backend-only DataHub Core `v1.6.0` project
+runs with metadata and REST authorization enabled and no published DataHub ports.
+Anonymous GraphQL access is denied. A native GlassBox service account has no role
+assignment: custom policies grant Document-scoped create/update/read authority and
+dataset read/incident authority only. Its rotating token remains root-owned outside
+containers except for encrypted control-plane storage.
+
+The separate hosted edge proof provisioned an isolated TierHive VPS, routed
+`glassboxhq.xyz` through the regional HAProxy and Let's Encrypt certificate, and
+completed the allowlisted GitHub OAuth flow. The authenticated operator resolved as
+an administrator at request time; the live DataHub connection form and named agent-
+key controls are enabled. The control plane proved connection, authentication, SDK
+compatibility, Document write, and direct readback before activating the receiver.
+One named production ingestion key is active; an earlier key whose one-time secret
+was not recoverably escrowed is revoked.
+
+The real public `https://glassboxhq.xyz/v1/traces` path then received a two-span
+synthetic run produced by the deterministic pricing agent. Delivery one returned
+HTTP 200, registered and reread the signed receipt in PostgreSQL, performed the
+required idempotent double emission, and directly read back five persisted Document
+aspects. Identical redelivery returned HTTP 200 for the same receipt and Document
+with `datahub_write_performed=false`. The authenticated console shows the verified
+receipt and its resolved `commerce.orders` dependency. The sanitized evidence is
+`docs/compatibility/datahub-1.6.0-hosted-production-otlp.live.json`.
+
+The deployed stores also require a trusted signer to be active both at admission
+and at the receipt's claimed run time before any durable write. A live PostgreSQL
+regression rejected a receipt from before its signer's validity window with zero
+receipt, dependency, or publication-task rows. After that hardened image was rolled
+out, external identical redelivery again returned HTTP 200 with fresh PostgreSQL and
+DataHub readback and no DataHub write.
+
+This reference proof does not claim customer-owned DataHub tenancy, a public
+DataHub UI, multi-node high availability, or disaster-recovery readiness. Those
+remain deployment-specific operator responsibilities.
diff --git a/deploy/production/compose.yml b/deploy/production/compose.yml
new file mode 100644
index 0000000..3445b48
--- /dev/null
+++ b/deploy/production/compose.yml
@@ -0,0 +1,237 @@
+name: glassbox
+
+services:
+ edge:
+ image: caddy:2.10.0-alpine
+ restart: unless-stopped
+ environment:
+ GLASSBOX_PUBLIC_DOMAIN: ${GLASSBOX_PUBLIC_DOMAIN:?set GLASSBOX_PUBLIC_DOMAIN}
+ GLASSBOX_CONSOLE_DOMAIN: ${GLASSBOX_CONSOLE_DOMAIN:?set GLASSBOX_CONSOLE_DOMAIN}
+ ports:
+ - "${GLASSBOX_EDGE_PORT:-8080}:8080"
+ volumes:
+ - ./Caddyfile:/etc/caddy/Caddyfile:ro
+ depends_on:
+ console:
+ condition: service_started
+ oauth2-proxy:
+ condition: service_started
+ networks: [edge, private]
+ read_only: true
+ tmpfs: [/config, /data]
+ security_opt: [no-new-privileges:true]
+
+ oauth2-proxy:
+ image: quay.io/oauth2-proxy/oauth2-proxy:v7.12.0
+ restart: unless-stopped
+ command:
+ - --github-user=${GITHUB_ALLOWED_USERS:?set GITHUB_ALLOWED_USERS}
+ environment:
+ OAUTH2_PROXY_PROVIDER: github
+ OAUTH2_PROXY_CLIENT_ID: ${GITHUB_OAUTH_CLIENT_ID:?set GITHUB_OAUTH_CLIENT_ID}
+ OAUTH2_PROXY_CLIENT_SECRET: ${GITHUB_OAUTH_CLIENT_SECRET:?set GITHUB_OAUTH_CLIENT_SECRET}
+ OAUTH2_PROXY_COOKIE_SECRET: ${OAUTH_COOKIE_SECRET:?set OAUTH_COOKIE_SECRET}
+ OAUTH2_PROXY_COOKIE_NAME: __Host-glassbox_session
+ OAUTH2_PROXY_COOKIE_SECURE: "true"
+ OAUTH2_PROXY_COOKIE_SAMESITE: lax
+ OAUTH2_PROXY_COOKIE_REFRESH: 1h
+ OAUTH2_PROXY_COOKIE_EXPIRE: 8h
+ OAUTH2_PROXY_REDIRECT_URL: https://${GLASSBOX_CONSOLE_DOMAIN:?set GLASSBOX_CONSOLE_DOMAIN}/oauth2/callback
+ OAUTH2_PROXY_EMAIL_DOMAINS: "*"
+ # GitHub's organization-list endpoint requires read:org (or broader user)
+ # and oauth2-proxy uses it to populate the authenticated group set.
+ OAUTH2_PROXY_SCOPE: user:email read:org
+ OAUTH2_PROXY_REVERSE_PROXY: "true"
+ OAUTH2_PROXY_SET_XAUTHREQUEST: "true"
+ OAUTH2_PROXY_SKIP_PROVIDER_BUTTON: "true"
+ OAUTH2_PROXY_UPSTREAMS: static://202
+ OAUTH2_PROXY_HTTP_ADDRESS: 0.0.0.0:4180
+ expose: ["4180"]
+ networks: [private, egress]
+ read_only: true
+ tmpfs: [/tmp]
+ security_opt: [no-new-privileges:true]
+
+ console:
+ build:
+ context: ../..
+ dockerfile: deploy/production/Dockerfile.console
+ image: glassbox-console:${GLASSBOX_IMAGE_TAG:-rc1}
+ restart: unless-stopped
+ environment:
+ GLASSBOX_FORENSICS_API_URL: http://forensics:8788
+ GLASSBOX_FORENSICS_API_TOKEN: ${GLASSBOX_FORENSICS_API_TOKEN:?set GLASSBOX_FORENSICS_API_TOKEN}
+ GLASSBOX_CONTROL_API_URL: http://control:8790
+ GLASSBOX_CONTROL_API_TOKEN: ${GLASSBOX_CONTROL_API_TOKEN:?set GLASSBOX_CONTROL_API_TOKEN}
+ GLASSBOX_ADMIN_EMAILS: ${GLASSBOX_ADMIN_EMAILS:-}
+ GLASSBOX_ADMIN_USERS: ${GITHUB_ALLOWED_USERS:?set GITHUB_ALLOWED_USERS}
+ GLASSBOX_ALLOW_LOCAL_OPERATOR: "false"
+ GLASSBOX_PUBLIC_HOSTS: ${GLASSBOX_PUBLIC_DOMAIN:?set GLASSBOX_PUBLIC_DOMAIN}
+ expose: ["3000"]
+ networks: [private]
+ read_only: true
+ tmpfs: [/tmp, /opt/console/.wrangler]
+ security_opt: [no-new-privileges:true]
+
+ control-init:
+ build:
+ context: ../..
+ dockerfile: deploy/production/Dockerfile.python
+ image: glassbox-core:${GLASSBOX_IMAGE_TAG:-rc1}
+ command:
+ - glassbox-control
+ - init
+ - --if-needed
+ - --database
+ - /var/lib/glassbox-control/control.sqlite3
+ environment: &control_environment
+ GLASSBOX_CONTROL_MASTER_KEY: ${GLASSBOX_CONTROL_MASTER_KEY:?set GLASSBOX_CONTROL_MASTER_KEY}
+ GLASSBOX_CONTROL_MASTER_KEY_ID: ${GLASSBOX_CONTROL_MASTER_KEY_ID:-control-v1}
+ GLASSBOX_ORGANIZATION: ${GLASSBOX_ORGANIZATION:-default}
+ volumes:
+ - control-state:/var/lib/glassbox-control
+ networks: [private]
+ security_opt: [no-new-privileges:true]
+
+ control:
+ image: glassbox-core:${GLASSBOX_IMAGE_TAG:-rc1}
+ restart: unless-stopped
+ command:
+ - glassbox-control
+ - serve
+ - --bind
+ - 0.0.0.0
+ - --database
+ - /var/lib/glassbox-control/control.sqlite3
+ environment:
+ <<: *control_environment
+ GLASSBOX_CONTROL_API_TOKEN: ${GLASSBOX_CONTROL_API_TOKEN:?set GLASSBOX_CONTROL_API_TOKEN}
+ volumes:
+ - control-state:/var/lib/glassbox-control
+ expose: ["8790"]
+ depends_on:
+ control-init:
+ condition: service_completed_successfully
+ networks: [private, egress]
+ read_only: true
+ tmpfs: [/tmp]
+ security_opt: [no-new-privileges:true]
+
+ postgres:
+ image: postgres:16.10-alpine
+ restart: unless-stopped
+ environment:
+ POSTGRES_DB: glassbox
+ POSTGRES_USER: glassbox
+ POSTGRES_PASSWORD: ${GLASSBOX_POSTGRES_PASSWORD:?set GLASSBOX_POSTGRES_PASSWORD}
+ volumes:
+ - postgres-state:/var/lib/postgresql/data
+ expose: ["5432"]
+ networks: [private]
+ healthcheck:
+ test: ["CMD-SHELL", "pg_isready -U glassbox -d glassbox"]
+ interval: 5s
+ timeout: 3s
+ retries: 20
+ security_opt: [no-new-privileges:true]
+
+ state-init:
+ image: glassbox-core:${GLASSBOX_IMAGE_TAG:-rc1}
+ command:
+ - glassbox-invalidation-state
+ - postgres-init
+ - --schema
+ - ${GLASSBOX_STATE_POSTGRES_SCHEMA:-glassbox}
+ - --signer-trust-policy
+ - /etc/glassbox/trusted-signers.json
+ environment: &runtime_environment
+ GLASSBOX_STATE_POSTGRES_DSN: postgresql://glassbox:${GLASSBOX_POSTGRES_PASSWORD}@postgres:5432/glassbox
+ GLASSBOX_SIGNER_TRUST_POLICY_PATH: /etc/glassbox/trusted-signers.json
+ GLASSBOX_CONTROL_MASTER_KEY: ${GLASSBOX_CONTROL_MASTER_KEY}
+ volumes:
+ - ${GLASSBOX_SIGNER_TRUST_POLICY_PATH:?set GLASSBOX_SIGNER_TRUST_POLICY_PATH}:/etc/glassbox/trusted-signers.json:ro
+ depends_on:
+ postgres:
+ condition: service_healthy
+ networks: [private]
+ security_opt: [no-new-privileges:true]
+
+ forensics:
+ image: glassbox-core:${GLASSBOX_IMAGE_TAG:-rc1}
+ restart: unless-stopped
+ command:
+ - glassbox-forensics-mcp
+ - --transport
+ - streamable-http
+ - --http-host
+ - 0.0.0.0
+ - --state-postgres-dsn-env
+ - GLASSBOX_STATE_POSTGRES_DSN
+ - --state-postgres-schema
+ - ${GLASSBOX_STATE_POSTGRES_SCHEMA:-glassbox}
+ - --signer-trust-policy
+ - /etc/glassbox/trusted-signers.json
+ environment:
+ <<: *runtime_environment
+ GLASSBOX_FORENSICS_API_TOKEN: ${GLASSBOX_FORENSICS_API_TOKEN}
+ volumes:
+ - ${GLASSBOX_SIGNER_TRUST_POLICY_PATH}:/etc/glassbox/trusted-signers.json:ro
+ expose: ["8788"]
+ depends_on:
+ state-init:
+ condition: service_completed_successfully
+ networks: [private]
+ read_only: true
+ tmpfs: [/tmp]
+ security_opt: [no-new-privileges:true]
+
+ receiver:
+ image: glassbox-core:${GLASSBOX_IMAGE_TAG:-rc1}
+ restart: unless-stopped
+ command:
+ - glassbox-otlp-receiver
+ - serve
+ - --bind
+ - 0.0.0.0
+ - --control-database
+ - /var/lib/glassbox-control/control.sqlite3
+ - --control-organization
+ - ${GLASSBOX_ORGANIZATION:-default}
+ - --startup-retry-seconds
+ - "5"
+ - --state-schema
+ - ${GLASSBOX_STATE_POSTGRES_SCHEMA:-glassbox}
+ - --signing-key-id
+ - ${GLASSBOX_RECEIPT_SIGNING_KEY_ID:?set GLASSBOX_RECEIPT_SIGNING_KEY_ID}
+ - --environment
+ - PROD
+ - --output-kind
+ - agent-decision
+ - --output-mime-type
+ - application/json
+ environment:
+ <<: *runtime_environment
+ GLASSBOX_RECEIPT_SIGNING_KEY: ${GLASSBOX_RECEIPT_SIGNING_KEY:?set GLASSBOX_RECEIPT_SIGNING_KEY}
+ volumes:
+ - control-state:/var/lib/glassbox-control:ro
+ - ${GLASSBOX_SIGNER_TRUST_POLICY_PATH}:/etc/glassbox/trusted-signers.json:ro
+ expose: ["4318"]
+ depends_on:
+ control:
+ condition: service_started
+ state-init:
+ condition: service_completed_successfully
+ networks: [private, egress]
+ read_only: true
+ tmpfs: [/tmp]
+ security_opt: [no-new-privileges:true]
+
+networks:
+ edge: {}
+ egress: {}
+ private:
+ internal: true
+
+volumes:
+ control-state: {}
+ postgres-state: {}
diff --git a/docs/adr/0025-pinned-flagship-estate-and-evidence-ablation.md b/docs/adr/0025-pinned-flagship-estate-and-evidence-ablation.md
new file mode 100644
index 0000000..fb3b175
--- /dev/null
+++ b/docs/adr/0025-pinned-flagship-estate-and-evidence-ablation.md
@@ -0,0 +1,128 @@
+# ADR-0025: Pin the flagship estate and ablate evidence capabilities through one policy
+
+- **Status:** Accepted
+- **Date:** 2026-08-09
+- **Owners:** GlassBox maintainers
+- **Extends:** [ADR-0020](0020-signed-invalidation-to-recovery-handoff.md),
+ [ADR-0021](0021-oci-isolated-replay-and-verified-incident-closure.md), and
+ [ADR-0023](0023-content-addressed-domain-semantic-policies.md)
+
+## Context
+
+The causal flagship already proved the complete GlassBox recovery chain against
+DataHub Core, PostgreSQL, both MCP servers, and an OCI-isolated capability. It still
+required an operator to start DataHub and PostgreSQL, build the replay image, copy
+its digest, and invoke the scenario. That was reproducible by a maintainer, but not
+one command from a fresh checkout.
+
+The evaluation plan also required five ablations. Implementing five unrelated
+classifiers would make the result easy to game: a baseline could be weakened by
+code rather than by the evidence it lacks. Correctness, live integration evidence,
+and timing measurements also have different authorities and must not be blended
+into one flattering score.
+
+## Decision
+
+- `examples.flagship_demo` owns the entire reference estate after the user passes
+ the explicit `--allow-live` gate. It checks Docker and `uvx`, fetches DataHub's
+ official quickstart compose from exact upstream commit
+ `059a36c0b035a6057de00114ccac0ea9003d6bc2`, and records the downloaded bytes'
+ SHA-256 digest.
+- A committed Compose overlay replaces every upstream host port and every explicit
+ network or volume name. The project is always `glassbox-flagship`, adds a
+ PostgreSQL 16 state service, uses an isolated runtime home, and can coexist with a
+ normal DataHub quickstart.
+- The launcher validates the merged Compose model, waits for service health, builds
+ and inspects the source/schema-bound replay sandbox, invokes the existing real
+ causal flagship, and accepts success only when the report proves the exact Core
+ version and commit, both MCP planes, real DataHub writes/readback, PostgreSQL,
+ isolation, recovery, closure, privacy, and zero-write redelivery.
+- Cleanup targets only the exact Compose project and its disposable volumes. It is
+ the default even on failure. `--keep-estate` is an explicit inspection mode.
+- `--compose-file` is an explicit local-development override. Its bytes are still
+ validated and hashed, but its report is labeled `LOCAL_OVERRIDE` and cannot be
+ presented as the pinned fresh-checkout path.
+- The benchmark runs all five required variants through the same production
+ `glassbox.materiality.v1` classifier. Each variant is a deterministic projection
+ that removes named evidence capabilities: runtime observation authority, field
+ identity, or metadata snapshot time/digest. The full variant removes nothing.
+- Ground truth, declared assets, raw-trace asset hints, runtime dependencies,
+ field-lineage state, snapshots, and changes are public synthetic fixtures. The
+ report includes every per-case state and reason code, resolution failures, false
+ invalidations, missed invalidations, and dishonest uncertainty outcomes.
+- Selection is an exact rule, not a model judge: minimize missed invalidation, then
+ false invalidation, while requiring perfect honesty on indeterminate cases.
+- Deterministic fixture correctness, offline single-process timing, and metrics
+ derived from the committed live DataHub report remain separately labeled. A
+ mixed adapter write unit is described precisely and never called a storage row.
+- A fresh-host success rate remains `NOT_MEASURED_ON_A_FRESH_HOST` until independent
+ clean-host repetitions exist. The presence of a one-command launcher is not used
+ to invent that measurement.
+
+## Evidence
+
+Unit tests exercise the full launcher lifecycle through its process boundary,
+including compose validation, exact project scoping, sandbox/report acceptance,
+failure on Core drift, cleanup, and credential exclusion. The merged overlay also
+passes Docker Compose validation against an official quickstart file.
+
+A real one-command run started all eight isolated services, completed the causal
+proof in 56.728 seconds, directly received Core `v1.6.0` and commit
+`059a36c0b035a6057de00114ccac0ea9003d6bc2`, and removed every project container,
+network, and volume. The raw-free report is
+[`datahub-1.6.0-one-command-flagship.live.json`](../compatibility/datahub-1.6.0-one-command-flagship.live.json).
+The execution environment could not resolve GitHub, so this measured run used its
+locally cached official quickstart file and is correctly labeled `LOCAL_OVERRIDE`;
+it proves the orchestration and Core target, not the default download path on a
+fresh host.
+
+The benchmark has 12 public cases: exact used-field change, unrelated-field
+negative control, post-change snapshot, other-asset change, trace alias collision,
+semantic constraint and reference changes, absent freshness requirement, wildcard
+ambiguity, unresolved runtime context, declared-but-unobserved assets, and a safe
+new-field addition. Its schema-valid report is
+[`agent-invalidation-ablation.v1.json`](../benchmarks/agent-invalidation-ablation.v1.json).
+
+On those fixtures, full GlassBox records zero false invalidations across six clean
+cases, zero misses across three contaminated cases, and honest uncertainty across
+all three indeterminate cases. The unresolved case is published as a field- and
+asset-resolution failure and remains `UNKNOWN`; it is not rewritten as success.
+
+## Alternatives considered
+
+- Keep the four manual setup steps: rejected because they violate Gate 9's fresh
+ checkout and one-command exit criteria.
+- Depend on an already-running DataHub: rejected because hidden state, versions,
+ and port ownership make a flagship irreproducible.
+- Copy DataHub's generated compose into this repository: rejected because a
+ commit-addressed primary upstream artifact plus a small auditable overlay keeps
+ ownership and drift clearer.
+- Reimplement simplified baseline classifiers: rejected because implementation
+ differences would confound the evidence ablation.
+- Collapse `AT_RISK` into either correct or incorrect contamination: rejected
+ because uncertainty is a first-class product result and needs its own honesty
+ denominator.
+- Publish only an aggregate score: rejected because failed cases and exact
+ denominators are required for skeptical review.
+
+## Consequences and limits
+
+The pinned path requires Docker Compose with `!override` support, `uv`, internet
+access for missing official artifacts and images, available configured host ports,
+and enough memory for DataHub quickstart. It proves a disposable single-host estate,
+not production topology, failover, or organization-wide retention.
+
+The correctness fixture distribution is not an estimate of production prevalence.
+The timing section measures deterministic local Python work and deliberately
+excludes DataHub, MCP, PostgreSQL, Docker startup, model providers, and networks.
+Raw OpenTelemetry in this benchmark means spans without GlassBox-qualified,
+authority-verified DataHub field and snapshot attributes; instrumented OTel carrying
+those attributes is GlassBox evidence, not the raw-trace ablation.
+
+## Reversal conditions
+
+Replace the quickstart orchestration if DataHub publishes a content-addressed,
+project-isolated reference-estate contract with equivalent version, health, and
+cleanup guarantees. Add an ablation implementation only when it can be expressed as
+another explicit evidence-capability projection or a separately justified competing
+system; never silently change a baseline's decision rules.
diff --git a/docs/adr/0026-loopback-console-read-model.md b/docs/adr/0026-loopback-console-read-model.md
new file mode 100644
index 0000000..3fe8c14
--- /dev/null
+++ b/docs/adr/0026-loopback-console-read-model.md
@@ -0,0 +1,58 @@
+# ADR-0026: Loopback console read model
+
+## Context
+
+The first console rendered one committed flagship report directly inside a single
+page. That made a reproducible proof easy to inspect, but it was not an operational
+product: navigation did not create distinct workflows, successful content existed
+without a running evidence authority, and the UI could be mistaken for the source
+of decision state.
+
+The existing `ForensicsService` already owns a bounded, raw-free read boundary over
+verified receipt profiles and persisted invalidation campaigns. The console needs
+list and detail views without receiving PostgreSQL credentials, signing keys, raw
+DBOM bodies, or mutation authority.
+
+## Decision
+
+1. The console is a multi-route read-only application. Overview, investigations,
+ receipts, campaigns, recovery, trust, and settings are independent routes.
+2. Production UI code never imports the flagship compatibility report or a
+ hard-coded successful response.
+3. `ForensicsService` exposes bounded receipt-list, campaign-list, and overview
+ projections in addition to its existing detail operations.
+4. The MCP process may expose those projections as loopback-only HTTP routes when
+ started with `--transport streamable-http`. The default remains stdio MCP.
+5. The HTTP console surface refuses a non-loopback bind. Remote deployments must
+ add authenticated operator infrastructure before relaxing this boundary.
+6. The console server reads `GLASSBOX_FORENSICS_API_URL`. Missing, unreachable, or
+ unsupported services produce explicit states rather than populated fallback data.
+7. Policy classification, receipt verification, campaign processing, quarantine,
+ and recovery authorization remain outside the UI.
+
+## Alternatives
+
+- **Bundle the live flagship report:** rejected because proof evidence is not live
+ application state.
+- **Read PostgreSQL directly from the console:** rejected because it leaks the
+ persistence boundary and credentials into the presentation layer.
+- **Call DataHub only:** rejected because DataHub projections do not contain the
+ full cryptographic receipt and persisted Action authority.
+- **Expose unauthenticated remote HTTP:** rejected because the read model contains
+ governed operational metadata even though it is raw-free.
+
+## Consequences
+
+- The application is honest when disconnected and useful against any compatible
+ receipt/campaign store.
+- Each navigation destination can evolve independently without duplicating policy.
+- A connected deployment needs the forensics process plus an operator-controlled
+ API URL.
+- Recovery currently derives its queue from quarantined campaign findings; a
+ dedicated persisted recovery-history reader remains separate future work.
+
+## Reversal conditions
+
+Replace the loopback HTTP boundary when GlassBox has a reviewed authenticated API
+gateway or when DataHub provides an equivalent native operator read model with the
+same receipt-verification, provenance-state, and campaign-history guarantees.
diff --git a/docs/adr/0027-authenticated-control-plane-and-self-hosted-deployment.md b/docs/adr/0027-authenticated-control-plane-and-self-hosted-deployment.md
new file mode 100644
index 0000000..44e39c7
--- /dev/null
+++ b/docs/adr/0027-authenticated-control-plane-and-self-hosted-deployment.md
@@ -0,0 +1,135 @@
+# ADR-0027: Add an authenticated control plane and self-hosted deployment boundary
+
+- **Status:** Accepted
+- **Date:** 2026-08-10
+- **Owners:** GlassBox maintainers
+- **Extends:** [ADR-0013](0013-read-only-forensics-mcp.md),
+ [ADR-0016](0016-durable-receipt-publication-and-otlp-acknowledgement.md), and
+ [ADR-0026](0026-loopback-console-read-model.md)
+
+## Context
+
+GlassBox has production-shaped evidence, invalidation, recovery, and read-only
+forensics services, but the first console deliberately runs against a loopback-only
+unauthenticated API. That is an honest local boundary, not an internet deployment.
+Putting the console and its existing API directly behind a domain would expose
+governed operational metadata and would provide no safe way to configure DataHub,
+issue agent credentials, or identify operators.
+
+The product also needs one coherent installation model. A DataHub deployment is an
+organization-level system, so GlassBox should connect once with a scoped DataHub
+service account. Human operators and telemetry-producing agents are different
+principals and must not share that credential.
+
+## Decision
+
+1. Ship self-hosted, organization-owned GlassBox first. A future hosted control
+ plane is not implied by this deployment.
+2. Separate three credentials:
+ - humans authenticate at the edge through an operator-configured OAuth 2.0 or
+ OIDC provider;
+ - GlassBox uses one scoped DataHub service-account token;
+ - agents use individually named and revocable GlassBox ingestion keys.
+3. Add a control-plane service with an authenticated, role-checked HTTP API. The
+ service is reachable only on the private application network. Every request must
+ carry a high-entropy internal bearer credential added by the console server; it
+ never trusts browser-supplied identity headers on their own.
+4. The edge proxy removes incoming identity and role headers before authentication,
+ obtains identity from the identity proxy, and then injects the normalized subject
+ and role for the console. The route order is explicit so sanitization cannot erase
+ the trusted identity after it is created. The console forwards those claims to the
+ control plane only after authenticating itself with the internal bearer credential.
+5. Store control state in one explicitly initialized SQLite database for the
+ single-node release candidate. Encrypt the DataHub token with AES-256-GCM using
+ a 32-byte deployment master key that is never stored in the database. Bind the
+ ciphertext to its organization, connection ID, and format version through
+ authenticated additional data.
+6. Store agent ingestion credentials only as keyed HMAC-SHA-256 digests. Return the
+ clear credential once at creation. Revocation is durable and authorization reads
+ fail closed if the control database or master key is unavailable.
+7. A connection test performs a real DataHub SDK connection check. The optional
+ write proof emits one deterministic, clearly labelled synthetic Document and
+ directly reads it back. Reachability is never reported as write permission, and
+ mocks never produce a `PROVEN` compatibility state.
+8. The console remains a presentation layer. It may proxy bounded control requests,
+ but it never persists or logs a DataHub token and never receives the deployment
+ master key, signing key, PostgreSQL DSN, or raw receipt content.
+9. Keep the forensics service private. Container-to-container access requires a
+ separate bearer credential, and the console server sends that credential without
+ exposing it to the browser.
+10. The public deployment exposes only TLS at the edge. PostgreSQL, the control
+ database, forensics API, and service ports remain private. OAuth configuration is
+ mandatory for a production profile; an explicitly named local-development
+ operator bypass is allowed only outside production.
+11. A deployment may serve the static product site and documentation without human
+ authentication on an explicitly allowlisted public hostname. That hostname has
+ no route to the operator pages or control API. The authenticated console uses a
+ separate hostname, while `/v1/traces` remains protected by revocable agent
+ credentials. Unknown Host headers fail closed at the edge.
+
+## Role model
+
+- `viewer`: read connection status and evidence projections.
+- `operator`: viewer capabilities plus operational inspection.
+- `admin`: test or replace the DataHub connection and create or revoke ingestion
+ keys.
+
+Mutation responses and audit rows contain bounded identifiers and outcome codes,
+never credentials, tokens, exception messages, or request bodies.
+
+## Deployment profile
+
+The release candidate uses a private Compose network with an edge proxy, OAuth proxy,
+console, control plane, forensics service, compiler receiver, and PostgreSQL. The
+domain and TLS provider are deployment choices. The reference configuration supports
+an upstream TLS/HAProxy provider terminating at the VPS as well as direct Caddy TLS;
+exact DNS and certificate ownership must be selected before publication.
+
+The reference edge assigns `glassboxhq.xyz` to the unauthenticated landing page,
+documentation, and authenticated OTLP receiver, and `app.glassboxhq.xyz` to the
+GitHub-OAuth-protected operator console. Both hosts may terminate at the same edge,
+but their route allowlists and principal types remain distinct.
+
+SQLite is accepted here only for low-write control metadata on one VPS. Receipt,
+campaign, publication, and recovery authority remains PostgreSQL. A multi-replica
+control plane requires a new migration design and a shared transactional store.
+
+## Alternatives considered
+
+- **Put the unauthenticated forensics server on the public domain:** rejected because
+ read-only governed metadata still requires authenticated principals and rate
+ limits.
+- **Use each human's DataHub personal token:** rejected because runtime publication
+ would depend on a person's lifecycle and would blur human and workload authority.
+- **Store the DataHub token in console environment or browser storage:** rejected
+ because it would enter the presentation or client boundary.
+- **One shared agent bearer token:** retained only as a legacy environment profile;
+ named keys are required for accountable issuance and revocation.
+- **Claim permissions after a health check:** rejected. Permission is `UNVERIFIED`
+ until a real authorized operation and direct readback succeed.
+- **Run a new identity database inside GlassBox:** rejected. The configured OAuth or
+ OIDC provider remains the organization's identity authority. The reference
+ production profile uses a GitHub OAuth App with a deployment allowlist.
+
+## Consequences and limits
+
+- Operators must provide an OAuth client, a control-plane master key, and
+ internal service credentials before an internet deployment is production-safe.
+- Runtime consumers wait through initial onboarding and transient dependency
+ unavailability, then activate automatically after a verified DataHub connection
+ is saved.
+- The deterministic DataHub write proof leaves an intentionally labelled synthetic
+ Document. It is idempotent and contains no secret or customer data.
+- Edge RBAC mapping is initially deployment-wide. DataHub-side policies still govern
+ the service account, while tenant-specific policy and managed KMS/HSM custody are
+ future work.
+- The public and console DNS names must both preserve the original Host header when
+ an upstream TLS proxy forwards them to the reference edge.
+
+## Reversal conditions
+
+Replace the single-node control store with PostgreSQL or a managed secrets system
+when GlassBox needs multiple control replicas, tenant isolation, online key rotation,
+or externally managed encryption. Replace the proxy-header identity bridge if the
+control API terminates and validates OAuth/OIDC tokens directly with equivalent issuer,
+audience, expiry, role, and revocation guarantees.
diff --git a/docs/adr/README.md b/docs/adr/README.md
index 1c3544f..4bf7bc7 100644
--- a/docs/adr/README.md
+++ b/docs/adr/README.md
@@ -49,3 +49,10 @@ change coverage, and raw-free assessment evidence. Transport recovery is defined
[ADR-0024](0024-independent-transport-acknowledgement-recovery.md), which separately
proves Kafka commit-retry exhaustion and pgQueue visibility/ack recovery through
persisted source authority rather than in-process replay.
+[ADR-0025](0025-pinned-flagship-estate-and-evidence-ablation.md) pins the flagship
+estate and requires causal ablation rather than presentation-only success.
+[ADR-0026](0026-loopback-console-read-model.md) makes the operational console a
+bounded read model over verified live state and refuses unauthenticated remote
+exposure. [ADR-0027](0027-authenticated-control-plane-and-self-hosted-deployment.md)
+adds the OAuth-gated self-hosted boundary, encrypted organization-level DataHub
+connection, named revocable agent keys, and private production service network.
diff --git a/docs/architecture/glassbox-architecture-diagram.png b/docs/architecture/glassbox-architecture-diagram.png
new file mode 100644
index 0000000..f137aaf
Binary files /dev/null and b/docs/architecture/glassbox-architecture-diagram.png differ
diff --git a/docs/architecture/glassbox-architecture-diagram.svg b/docs/architecture/glassbox-architecture-diagram.svg
new file mode 100644
index 0000000..4b244e7
--- /dev/null
+++ b/docs/architecture/glassbox-architecture-diagram.svg
@@ -0,0 +1,452 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GlassBox
+ DataHub-native execution provenance and control for AI agents
+
+
+
+
+
+ DataHub
+ Core 1.6.0 Β· governed graph
+
+
+ Recorded at the boundary. Signed by policy. Invalidated by evidence.
+
+
+
+ HOW GLASSBOX WORKS
+
+ 1
+ Capture
+ 2
+ Sign
+ 3
+ Project
+ 4
+ Assess
+ 5
+ Recover
+
+
+
+
+
+
+
+
+ AGENTS
+ Instrumented runs emit OTLP
+ spans as they read and write.
+
+ glassbox.runtime Β· nested runs
+
+ LangGraph Β· Google ADK Β· MCP
+
+
+
+
+
+
+ OPERATORS
+ Review decisions and
+ authorize recovery explicitly.
+
+ glassbox-dbom verify-policy
+
+
+
+
+
+
+ PLATFORM
+ Run the control plane and
+ provision the estate as code.
+
+ glassbox-otlp-receiver serve
+
+ glassbox-datahub-action
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ localhost:3002/investigations
+
+
+
+
+ Decision receipts
+ signed index Β· newest first
+
+ 2 receipts
+
+
+
+
+
+ dab8881a9aβ¦b5872bcb
+ postgres Β· commerce.orders Β· PROD
+
+ STALE
+
+
+
+ e18291381bβ¦cc217baa
+ postgres Β· commerce.orders Β· PROD
+
+ NO FINDINGS
+
+
+
+ SCHEMA_FIELD_TYPE_CHANGED
+ average_order_value Β· decimal β double
+
+
+
+
+
+ DBOM 0.1 canonical form
+ canonicalised Β· Ed25519 Β· append-only
+
+
+ dbom.version = "0.1"
+ influence.dependencies[1]
+ urn:li:schemaField:(β¦,PROD)
+ signature.alg = Ed25519
+
+
+ canonical state readback verified
+
+ every URN resolved before publish
+
+ field-lineage coverage COMPLETE
+
+
+ raw content withheld
+
+
+
+
+
+ Impact assessment
+ deterministic Β· rule pack, not a model
+
+
+
+ OBSERVED_MATERIAL_DEPENDENCY_CHANGED
+
+ policy v1
+
+ dependency timeline
+
+
+
+
+
+
+
+
+ a3f1c8 β 9c4e02
+
+ campaign Β· pinned
+
+
+
+
+
+ 1/1
+ dependencies resolved
+
+
+ unrelated-field control
+
+ UNAFFECTED Β· proven unused
+
+
+
+
+
+ Recovery & closure
+ authorized Β· sandboxed Β· append-only
+
+
+
+
+ Receipt quarantined
+
+ enforced
+
+
+ Replay authorized by fingerprint
+
+ bound
+
+
+ Replayed in digest-pinned OCI
+
+ no network
+
+
+ Supersession written
+
+ both unchanged
+
+
+
+
+ origin = datahub-action
+ change caused this quarantine
+
+ incident closed after direct DataHub readback
+
+
+
+
+
+
+
+
+
+
+
+
+ Signed baseline
+ A DBOM turns first sight into a signed
+ assertion about what the run depended on.
+
+
+
+
+ Correlated evidence
+ Findings reach DataHub carrying governed
+ URNs, campaign IDs, and reason codes.
+
+
+
+
+ Closed loop
+ A metadata change quarantines the next
+ decision before anyone reads it again.
+
+
+
+
+
+
+
+ DataHub estate
+ governed metadata graph
+
+ receipt Documents + aspects
+
+ metadata change events
+
+ native ownership routing
+
+ direct entity readback
+
+ incident writeback + closure
+
+
+
+
+
+
+ Assessment engine
+ deterministic, then durable
+
+ content-addressed rule packs
+
+ campaign per change event
+
+ leases Β· expiry Β· recovery
+
+ raw-free durable assessments
+
+ append-only audit trail
+
+
+
+
+
+
+ Recovery plane
+ authorized, sandboxed, reversible
+
+ digest-bound expiring approval
+
+ digest-pinned OCI profile
+
+ network denied Β· read-only root
+
+ supersession, never edit
+
+ verified idempotent closure
+
+ postgres Β· server-clock leases
+
+
+
+
+
+
+
+
+
+
+
+ Receipt
+ in DataHub
+
+
+
+
+ Findings
+ reason-coded
+
+
+
+
+ Superseded
+ history intact
+
+
+
+
+
+ GlassBox capabilities
+ Full contract set Β· DataHub-native
+
+
+
+
+ DBOM signing
+
+ URN resolution
+
+ Field lineage
+
+ Materiality rules
+
+ Campaigns
+
+ Leases & outbox
+
+ Kafka Β· pgQueue
+
+ Replay bundles
+
+ OCI sandbox
+
+ Supersession
+
+ Incident closure
+
+ MCP tools
+
+
+
+
+
+
+ Evidence β OTLP spans, signed receipts
+
+ Metadata β DataHub aspects and change events
+
+ Control β campaign β quarantine β recovery
+
+
+ GlassBox never returns raw content: only digests, governed URNs, reason codes, and verification results.
+ Enforcement is explicit, reversible, and always leaves both receipt Documents unchanged.
+
diff --git a/docs/assets/glassbox-readme-banner.png b/docs/assets/glassbox-readme-banner.png
new file mode 100644
index 0000000..f4d8743
Binary files /dev/null and b/docs/assets/glassbox-readme-banner.png differ
diff --git a/docs/assets/glassbox-readme-banner.svg b/docs/assets/glassbox-readme-banner.svg
new file mode 100644
index 0000000..360c60e
--- /dev/null
+++ b/docs/assets/glassbox-readme-banner.svg
@@ -0,0 +1,110 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GlassBox
+
+ Know when an AI-agent decision is no longer safe to trust.
+
+ Data lineage tells you where data went.
+ GlassBox tells you what your agents did because of it.
+
+
+
+
+ Signed receipts
+
+
+ Deterministic impact
+
+
+ Governed replay
+
+
+ OPEN SOURCE Β· DATAHUB-NATIVE Β· APACHE-2.0
+
+
+
+
+
+
+
+ AGENT RUN
+ Signed decision receipt
+ gbx:receipt:sha256:dab8881a9aβ¦
+
+
+
+
+
+
+
+
+ DATAHUB CHANGE
+ A field it depended on moved
+ average_order_value Β· decimal β double
+
+
+
+
+
+
+
+
+ DETERMINISTIC VERDICT
+ Quarantined, with a reason
+
+ STALE
+
+ policy v1
+
+
+
+
+
+
diff --git a/docs/benchmarks/README.md b/docs/benchmarks/README.md
new file mode 100644
index 0000000..f9a3651
--- /dev/null
+++ b/docs/benchmarks/README.md
@@ -0,0 +1,82 @@
+# Agent invalidation benchmark
+
+This benchmark answers one narrow question with exact denominators:
+
+> Which previously emitted agent decisions can each evidence contract correctly
+> quarantine or release after governed context changes?
+
+It is not a model-judge leaderboard. All five required variants execute the same
+production `glassbox.materiality.v1` classifier. An ablation removes evidence from a
+normalized receipt profile; it does not replace the policy with hand-written
+baseline logic.
+
+## Run it
+
+From a fresh checkout with `uv` installed:
+
+```bash
+uv run --all-extras python -m benchmarks.agent_invalidation \
+ --performance-samples 500 \
+ --compilation-samples 50 \
+ --output .glassbox/agent-invalidation-ablation.json
+```
+
+The command validates the closed report schema and content address before writing.
+Use `--without-live-report` to exclude metrics derived from the committed DataHub
+Core flagship proof. Correctness output and `benchmark_id` remain deterministic;
+timings are environment-specific and are not part of that correctness identity.
+
+## Compared evidence contracts
+
+| Variant | Evidence deliberately removed |
+| --- | --- |
+| Static declared lineage | Runtime observation, fields, snapshots |
+| Raw OpenTelemetry traces | Verified DataHub resolution, fields, snapshots |
+| GlassBox without fields | Field identity and complete field-lineage proof |
+| GlassBox without snapshots | Observation time and representation digest |
+| Full GlassBox | Nothing |
+
+βRaw OpenTelemetryβ means ordinary spans without GlassBox-qualified DataHub field
+and snapshot attributes. Once an instrumented trace carries those authority-bound
+attributes, it is GlassBox evidence and belongs in the full path.
+
+## Current proof
+
+The committed [schema-valid report](agent-invalidation-ablation.v1.json) contains 12
+public synthetic cases and every per-case state/reason. Its primary exact results
+are:
+
+| Variant | False invalidations | Missed invalidations | Honest uncertain cases | Field recall |
+| --- | ---: | ---: | ---: | ---: |
+| Static declared lineage | 5/6 | 0/3 | 3/3 | 0/9 |
+| Raw OpenTelemetry traces | 4/6 | 0/3 | 3/3 | 0/9 |
+| GlassBox without fields | 3/6 | 0/3 | 3/3 | 0/9 |
+| GlassBox without snapshots | 1/6 | 0/3 | 3/3 | 8/9 |
+| Full GlassBox | 0/6 | 0/3 | 3/3 | 8/9 |
+
+The missing ninth field is deliberate: `unresolved-runtime-context` has ground truth
+known to the fixture author but cannot be resolved by the runtime contract. Full
+GlassBox returns `UNKNOWN` and quarantines it. The report publishes the resolution
+failure rather than promoting it to observed or safe.
+
+The same report records:
+
+- 4/4 deterministic replay allow/refusal decisions;
+- 0/10 secret-redaction escapes;
+- 3/3 zero-write completed redeliveries from the live DataHub report;
+- one successful corrected replay and one verified incident closure;
+- the exact DataHub adapter write breakdown, labeled as emissions/aspect writes,
+ not database rows;
+- local p50/p95 agent instrumentation, receipt compilation, and policy-suite
+ timings with environment and sample counts.
+
+## What is not claimed
+
+The 12 cases are a closed correctness corpus, not a claim about production incident
+frequency. Local microbenchmarks exclude service and model latency. The one-command
+estate is separately executable, but a statistically meaningful fresh-host setup
+success rate still requires repeated independent clean hosts; the report marks that
+metric unmeasured.
+
+See [ADR-0025](../adr/0025-pinned-flagship-estate-and-evidence-ablation.md) for the
+orchestration, baseline, and measurement decisions.
diff --git a/docs/benchmarks/agent-invalidation-ablation.v1.json b/docs/benchmarks/agent-invalidation-ablation.v1.json
new file mode 100644
index 0000000..0710554
--- /dev/null
+++ b/docs/benchmarks/agent-invalidation-ablation.v1.json
@@ -0,0 +1,1231 @@
+{
+ "benchmark": "glassbox.agent-invalidation-ablation.v1",
+ "benchmark_id": "gbx:benchmark:sha256:6042398f7b96bd5ae0595063bd049d5c7183a4a26a652b3b515dbee51b83689b",
+ "case_count": 12,
+ "contract_version": "0.1.0",
+ "fixture_sha256": "20b3132e80827072b6f40f21ad0110c706902478864ff04a8ba148fc9a0de349",
+ "limitations": [
+ "Synthetic correctness fixtures measure a closed causal contract, not production prevalence.",
+ "Raw OpenTelemetry means spans without GlassBox-qualified DataHub field and snapshot attributes.",
+ "Offline latency excludes service, network, model-provider, and container startup time.",
+ "The live write unit is an adapter emission/aspect write, not an underlying database row.",
+ "A fresh-host success rate needs independent clean-host repetitions; this report does not invent it."
+ ],
+ "live_evidence": {
+ "completed_redelivery_zero_write_rate": {
+ "denominator": 3,
+ "numerator": 3,
+ "value": 1.0
+ },
+ "corrected_replay_success_rate": {
+ "denominator": 1,
+ "numerator": 1,
+ "value": 1.0
+ },
+ "datahub_write_units": {
+ "breakdown": {
+ "incident_closure_aspect_writes": 4,
+ "invalidation_emissions": 2,
+ "replay_receipt_emissions": 2,
+ "source_receipt_emissions": 2,
+ "supersession_emissions": 2
+ },
+ "measurement_unit": "adapter-reported proposal emissions or aspect writes; not storage rows",
+ "total": 12
+ },
+ "negative_control_zero_write_rate": {
+ "denominator": 1,
+ "numerator": 1,
+ "value": 1.0
+ },
+ "source_report": "datahub-1.6.0-flagship-causal-recovery.live.json",
+ "source_report_sha256": "645a5f16afb29e8550b1802d2c989edf96cd4f38d2edac830cf48b567cd6145d",
+ "status": "MEASURED_LIVE_REPORT",
+ "verified_incident_closure_rate": {
+ "denominator": 1,
+ "numerator": 1,
+ "value": 1.0
+ }
+ },
+ "metric_coverage": {
+ "agent_overhead_p50_p95": "MEASURED_OFFLINE",
+ "asset_resolution_precision_recall": "MEASURED_SYNTHETIC_EXACT",
+ "datahub_write_amplification": "MEASURED_LIVE_REPORT",
+ "false_and_missed_invalidation": "MEASURED_SYNTHETIC_EXACT",
+ "field_resolution_precision_recall": "MEASURED_SYNTHETIC_EXACT",
+ "fresh_checkout_setup": "NOT_MEASURED_ON_A_FRESH_HOST",
+ "idempotent_event_handling": "MEASURED_LIVE_REPORT",
+ "receipt_compilation_latency": "MEASURED_OFFLINE",
+ "replay_success_and_refusal": "MEASURED_DETERMINISTIC_AND_LIVE",
+ "secret_redaction_escape": "MEASURED_SYNTHETIC_EXACT",
+ "unknown_at_risk_honesty": "MEASURED_SYNTHETIC_EXACT"
+ },
+ "performance": {
+ "agent_runtime_microseconds": {
+ "baseline": {
+ "max": 9.833,
+ "min": 0.375,
+ "p50": 0.458,
+ "p95": 0.5,
+ "samples": 500
+ },
+ "glassbox_observed": {
+ "max": 351.459,
+ "min": 44.75,
+ "p50": 48.833,
+ "p95": 57.458,
+ "samples": 500
+ },
+ "overhead_p50": 48.375,
+ "overhead_p95": 56.958
+ },
+ "clock": "time.perf_counter_ns",
+ "environment": {
+ "implementation": "CPython",
+ "machine": "arm64",
+ "python": "3.12.13",
+ "system": "Darwin"
+ },
+ "policy_suite_latency_microseconds": {
+ "FULL_GLASSBOX": {
+ "max": 33.167,
+ "min": 15.542,
+ "p50": 17.542,
+ "p95": 17.833,
+ "samples": 500
+ },
+ "GLASSBOX_WITHOUT_FIELD_EVIDENCE": {
+ "max": 26.625,
+ "min": 13.916,
+ "p50": 15.625,
+ "p95": 15.875,
+ "samples": 500
+ },
+ "GLASSBOX_WITHOUT_METADATA_SNAPSHOTS": {
+ "max": 129.375,
+ "min": 15.375,
+ "p50": 16.125,
+ "p95": 18.0,
+ "samples": 500
+ },
+ "RAW_OTEL_TRACES": {
+ "max": 28.125,
+ "min": 13.166,
+ "p50": 14.833,
+ "p95": 15.042,
+ "samples": 500
+ },
+ "STATIC_DECLARED_LINEAGE": {
+ "max": 26.791,
+ "min": 13.292,
+ "p50": 15.25,
+ "p95": 15.583,
+ "samples": 500
+ }
+ },
+ "receipt_compilation_milliseconds": {
+ "max": 1.344875,
+ "min": 1.013917,
+ "p50": 1.065875,
+ "p95": 1.181292,
+ "samples": 50
+ },
+ "scope": "Single-process deterministic microbenchmark; excludes network, DataHub, MCP, PostgreSQL, container startup, and model-provider latency.",
+ "status": "MEASURED_OFFLINE"
+ },
+ "primary_result": {
+ "selected_variant": "FULL_GLASSBOX",
+ "selection_is_model_judged": false,
+ "selection_rule": "Minimize missed invalidation, then false invalidation, while requiring perfect indeterminate-case honesty."
+ },
+ "privacy": {
+ "credentials_retained": false,
+ "raw_action_inputs_retained": false,
+ "raw_evidence_retained": false,
+ "raw_outputs_retained": false,
+ "raw_prompts_retained": false,
+ "synthetic_fixtures_only": true
+ },
+ "redaction": {
+ "escape_rate": {
+ "denominator": 10,
+ "numerator": 0,
+ "value": 0.0
+ },
+ "plaintext_values_retained": 0,
+ "policy_id": "glassbox.default-deny-v1"
+ },
+ "replay_policy": {
+ "cases": [
+ {
+ "actual": "ALLOW",
+ "case_id": "safe-read-only",
+ "correct": true,
+ "expected": "ALLOW"
+ },
+ {
+ "actual": "BLOCK",
+ "case_id": "irreversible-refusal",
+ "correct": true,
+ "expected": "BLOCK"
+ },
+ {
+ "actual": "BLOCK",
+ "case_id": "missing-resource-refusal",
+ "correct": true,
+ "expected": "BLOCK"
+ },
+ {
+ "actual": "DRY_RUN_ONLY",
+ "case_id": "missing-execution-material-dry-only",
+ "correct": true,
+ "expected": "DRY_RUN_ONLY"
+ }
+ ],
+ "correctness": {
+ "denominator": 4,
+ "numerator": 4,
+ "value": 1.0
+ },
+ "policy_version": "glassbox.replay-policy.v1"
+ },
+ "truth_distribution": {
+ "CLEAN": 6,
+ "CONTAMINATED": 3,
+ "INDETERMINATE": 3
+ },
+ "variants": [
+ {
+ "cases": [
+ {
+ "case_id": "used-field-type-change",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "FIELD_LINEAGE_INCOMPLETE_OR_WILDCARD_UNKNOWN",
+ "resolved_asset_count": 2,
+ "resolved_field_count": 0,
+ "state": "AT_RISK",
+ "truth": "CONTAMINATED"
+ },
+ {
+ "case_id": "unrelated-field-same-asset",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "FIELD_LINEAGE_INCOMPLETE_OR_WILDCARD_UNKNOWN",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 0,
+ "state": "AT_RISK",
+ "truth": "CLEAN"
+ },
+ {
+ "case_id": "matching-post-change-snapshot",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "FIELD_LINEAGE_INCOMPLETE_OR_WILDCARD_UNKNOWN",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 0,
+ "state": "AT_RISK",
+ "truth": "CLEAN"
+ },
+ {
+ "case_id": "other-asset-change",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "FIELD_LINEAGE_INCOMPLETE_OR_WILDCARD_UNKNOWN",
+ "resolved_asset_count": 2,
+ "resolved_field_count": 0,
+ "state": "AT_RISK",
+ "truth": "CLEAN"
+ },
+ {
+ "case_id": "trace-alias-collision",
+ "matched_evidence_count": 0,
+ "quarantine_required": false,
+ "reason_code": "CHANGED_ASSET_NOT_IN_RESOLVED_INFLUENCE_SET",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 0,
+ "state": "UNAFFECTED",
+ "truth": "CLEAN"
+ },
+ {
+ "case_id": "semantic-constraint-change",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "MATCHED_DEPENDENCY_NOT_OBSERVED",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 0,
+ "state": "AT_RISK",
+ "truth": "CONTAMINATED"
+ },
+ {
+ "case_id": "semantic-reference-unproven",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "MATCHED_DEPENDENCY_NOT_OBSERVED",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 0,
+ "state": "AT_RISK",
+ "truth": "INDETERMINATE"
+ },
+ {
+ "case_id": "freshness-requirement-unrecorded",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "MATCHED_DEPENDENCY_NOT_OBSERVED",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 0,
+ "state": "AT_RISK",
+ "truth": "INDETERMINATE"
+ },
+ {
+ "case_id": "wildcard-field-ambiguity",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "FIELD_LINEAGE_INCOMPLETE_OR_WILDCARD_UNKNOWN",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 0,
+ "state": "AT_RISK",
+ "truth": "INDETERMINATE"
+ },
+ {
+ "case_id": "unresolved-runtime-context",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "FIELD_LINEAGE_INCOMPLETE_OR_WILDCARD_UNKNOWN",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 0,
+ "state": "AT_RISK",
+ "truth": "CONTAMINATED"
+ },
+ {
+ "case_id": "declared-but-not-observed-asset",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "FIELD_LINEAGE_INCOMPLETE_OR_WILDCARD_UNKNOWN",
+ "resolved_asset_count": 2,
+ "resolved_field_count": 0,
+ "state": "AT_RISK",
+ "truth": "CLEAN"
+ },
+ {
+ "case_id": "new-field-non-wildcard",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "FIELD_LINEAGE_INCOMPLETE_OR_WILDCARD_UNKNOWN",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 0,
+ "state": "AT_RISK",
+ "truth": "CLEAN"
+ }
+ ],
+ "impact": {
+ "confident_stale_precision": {
+ "denominator": 0,
+ "numerator": 0,
+ "value": null
+ },
+ "confident_stale_recall": {
+ "denominator": 3,
+ "numerator": 0,
+ "value": 0.0
+ },
+ "dishonest_indeterminate_cases": [],
+ "false_invalidation_cases": [
+ "declared-but-not-observed-asset",
+ "matching-post-change-snapshot",
+ "new-field-non-wildcard",
+ "other-asset-change",
+ "unrelated-field-same-asset"
+ ],
+ "false_invalidation_rate": {
+ "denominator": 6,
+ "numerator": 5,
+ "value": 0.833333
+ },
+ "missed_invalidation_cases": [],
+ "missed_invalidation_rate": {
+ "denominator": 3,
+ "numerator": 0,
+ "value": 0.0
+ },
+ "quarantine_precision": {
+ "denominator": 8,
+ "numerator": 3,
+ "value": 0.375
+ },
+ "quarantine_recall": {
+ "denominator": 3,
+ "numerator": 3,
+ "value": 1.0
+ },
+ "unknown_at_risk_honesty_rate": {
+ "denominator": 3,
+ "numerator": 3,
+ "value": 1.0
+ }
+ },
+ "policy_version": "glassbox.materiality.v1",
+ "removed_capabilities": [
+ "runtime observation state",
+ "field identity",
+ "metadata snapshot binding"
+ ],
+ "resolution": {
+ "asset_precision": {
+ "denominator": 15,
+ "numerator": 12,
+ "value": 0.8
+ },
+ "asset_recall": {
+ "denominator": 12,
+ "numerator": 12,
+ "value": 1.0
+ },
+ "asset_resolution_failed_cases": [
+ "declared-but-not-observed-asset",
+ "other-asset-change",
+ "used-field-type-change"
+ ],
+ "field_precision": {
+ "denominator": 0,
+ "numerator": 0,
+ "value": null
+ },
+ "field_recall": {
+ "denominator": 9,
+ "numerator": 0,
+ "value": 0.0
+ },
+ "field_resolution_failed_cases": [
+ "declared-but-not-observed-asset",
+ "matching-post-change-snapshot",
+ "new-field-non-wildcard",
+ "other-asset-change",
+ "trace-alias-collision",
+ "unrelated-field-same-asset",
+ "unresolved-runtime-context",
+ "used-field-type-change",
+ "wildcard-field-ambiguity"
+ ]
+ },
+ "variant": "STATIC_DECLARED_LINEAGE"
+ },
+ {
+ "cases": [
+ {
+ "case_id": "used-field-type-change",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "FIELD_LINEAGE_INCOMPLETE_OR_WILDCARD_UNKNOWN",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 0,
+ "state": "AT_RISK",
+ "truth": "CONTAMINATED"
+ },
+ {
+ "case_id": "unrelated-field-same-asset",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "FIELD_LINEAGE_INCOMPLETE_OR_WILDCARD_UNKNOWN",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 0,
+ "state": "AT_RISK",
+ "truth": "CLEAN"
+ },
+ {
+ "case_id": "matching-post-change-snapshot",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "FIELD_LINEAGE_INCOMPLETE_OR_WILDCARD_UNKNOWN",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 0,
+ "state": "AT_RISK",
+ "truth": "CLEAN"
+ },
+ {
+ "case_id": "other-asset-change",
+ "matched_evidence_count": 0,
+ "quarantine_required": false,
+ "reason_code": "CHANGED_ASSET_NOT_IN_RESOLVED_INFLUENCE_SET",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 0,
+ "state": "UNAFFECTED",
+ "truth": "CLEAN"
+ },
+ {
+ "case_id": "trace-alias-collision",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "FIELD_LINEAGE_INCOMPLETE_OR_WILDCARD_UNKNOWN",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 0,
+ "state": "AT_RISK",
+ "truth": "CLEAN"
+ },
+ {
+ "case_id": "semantic-constraint-change",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "MATCHED_DEPENDENCY_NOT_OBSERVED",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 0,
+ "state": "AT_RISK",
+ "truth": "CONTAMINATED"
+ },
+ {
+ "case_id": "semantic-reference-unproven",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "MATCHED_DEPENDENCY_NOT_OBSERVED",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 0,
+ "state": "AT_RISK",
+ "truth": "INDETERMINATE"
+ },
+ {
+ "case_id": "freshness-requirement-unrecorded",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "MATCHED_DEPENDENCY_NOT_OBSERVED",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 0,
+ "state": "AT_RISK",
+ "truth": "INDETERMINATE"
+ },
+ {
+ "case_id": "wildcard-field-ambiguity",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "FIELD_LINEAGE_INCOMPLETE_OR_WILDCARD_UNKNOWN",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 0,
+ "state": "AT_RISK",
+ "truth": "INDETERMINATE"
+ },
+ {
+ "case_id": "unresolved-runtime-context",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "UNRESOLVED_DEPENDENCY_PREVENTS_ASSET_EXCLUSION",
+ "resolved_asset_count": 0,
+ "resolved_field_count": 0,
+ "state": "UNKNOWN",
+ "truth": "CONTAMINATED"
+ },
+ {
+ "case_id": "declared-but-not-observed-asset",
+ "matched_evidence_count": 0,
+ "quarantine_required": false,
+ "reason_code": "CHANGED_ASSET_NOT_IN_RESOLVED_INFLUENCE_SET",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 0,
+ "state": "UNAFFECTED",
+ "truth": "CLEAN"
+ },
+ {
+ "case_id": "new-field-non-wildcard",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "FIELD_LINEAGE_INCOMPLETE_OR_WILDCARD_UNKNOWN",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 0,
+ "state": "AT_RISK",
+ "truth": "CLEAN"
+ }
+ ],
+ "impact": {
+ "confident_stale_precision": {
+ "denominator": 0,
+ "numerator": 0,
+ "value": null
+ },
+ "confident_stale_recall": {
+ "denominator": 3,
+ "numerator": 0,
+ "value": 0.0
+ },
+ "dishonest_indeterminate_cases": [],
+ "false_invalidation_cases": [
+ "matching-post-change-snapshot",
+ "new-field-non-wildcard",
+ "trace-alias-collision",
+ "unrelated-field-same-asset"
+ ],
+ "false_invalidation_rate": {
+ "denominator": 6,
+ "numerator": 4,
+ "value": 0.666667
+ },
+ "missed_invalidation_cases": [],
+ "missed_invalidation_rate": {
+ "denominator": 3,
+ "numerator": 0,
+ "value": 0.0
+ },
+ "quarantine_precision": {
+ "denominator": 7,
+ "numerator": 3,
+ "value": 0.428571
+ },
+ "quarantine_recall": {
+ "denominator": 3,
+ "numerator": 3,
+ "value": 1.0
+ },
+ "unknown_at_risk_honesty_rate": {
+ "denominator": 3,
+ "numerator": 3,
+ "value": 1.0
+ }
+ },
+ "policy_version": "glassbox.materiality.v1",
+ "removed_capabilities": [
+ "verified DataHub resolution authority",
+ "field identity",
+ "metadata snapshot binding"
+ ],
+ "resolution": {
+ "asset_precision": {
+ "denominator": 11,
+ "numerator": 10,
+ "value": 0.909091
+ },
+ "asset_recall": {
+ "denominator": 12,
+ "numerator": 10,
+ "value": 0.833333
+ },
+ "asset_resolution_failed_cases": [
+ "trace-alias-collision",
+ "unresolved-runtime-context"
+ ],
+ "field_precision": {
+ "denominator": 0,
+ "numerator": 0,
+ "value": null
+ },
+ "field_recall": {
+ "denominator": 9,
+ "numerator": 0,
+ "value": 0.0
+ },
+ "field_resolution_failed_cases": [
+ "declared-but-not-observed-asset",
+ "matching-post-change-snapshot",
+ "new-field-non-wildcard",
+ "other-asset-change",
+ "trace-alias-collision",
+ "unrelated-field-same-asset",
+ "unresolved-runtime-context",
+ "used-field-type-change",
+ "wildcard-field-ambiguity"
+ ]
+ },
+ "variant": "RAW_OTEL_TRACES"
+ },
+ {
+ "cases": [
+ {
+ "case_id": "used-field-type-change",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "FIELD_LINEAGE_INCOMPLETE_OR_WILDCARD_UNKNOWN",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 0,
+ "state": "AT_RISK",
+ "truth": "CONTAMINATED"
+ },
+ {
+ "case_id": "unrelated-field-same-asset",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "FIELD_LINEAGE_INCOMPLETE_OR_WILDCARD_UNKNOWN",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 0,
+ "state": "AT_RISK",
+ "truth": "CLEAN"
+ },
+ {
+ "case_id": "matching-post-change-snapshot",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "FIELD_LINEAGE_INCOMPLETE_OR_WILDCARD_UNKNOWN",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 0,
+ "state": "AT_RISK",
+ "truth": "CLEAN"
+ },
+ {
+ "case_id": "other-asset-change",
+ "matched_evidence_count": 0,
+ "quarantine_required": false,
+ "reason_code": "CHANGED_ASSET_NOT_IN_RESOLVED_INFLUENCE_SET",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 0,
+ "state": "UNAFFECTED",
+ "truth": "CLEAN"
+ },
+ {
+ "case_id": "trace-alias-collision",
+ "matched_evidence_count": 0,
+ "quarantine_required": false,
+ "reason_code": "CHANGED_ASSET_NOT_IN_RESOLVED_INFLUENCE_SET",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 0,
+ "state": "UNAFFECTED",
+ "truth": "CLEAN"
+ },
+ {
+ "case_id": "semantic-constraint-change",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "OBSERVED_SEMANTIC_CONSTRAINT_CHANGED",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 0,
+ "state": "STALE",
+ "truth": "CONTAMINATED"
+ },
+ {
+ "case_id": "semantic-reference-unproven",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "SEMANTIC_REFERENCE_MATERIALITY_UNPROVEN",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 0,
+ "state": "AT_RISK",
+ "truth": "INDETERMINATE"
+ },
+ {
+ "case_id": "freshness-requirement-unrecorded",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "FRESHNESS_REQUIREMENT_NOT_RECORDED",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 0,
+ "state": "AT_RISK",
+ "truth": "INDETERMINATE"
+ },
+ {
+ "case_id": "wildcard-field-ambiguity",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "FIELD_LINEAGE_INCOMPLETE_OR_WILDCARD_UNKNOWN",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 0,
+ "state": "AT_RISK",
+ "truth": "INDETERMINATE"
+ },
+ {
+ "case_id": "unresolved-runtime-context",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "UNRESOLVED_DEPENDENCY_PREVENTS_ASSET_EXCLUSION",
+ "resolved_asset_count": 0,
+ "resolved_field_count": 0,
+ "state": "UNKNOWN",
+ "truth": "CONTAMINATED"
+ },
+ {
+ "case_id": "declared-but-not-observed-asset",
+ "matched_evidence_count": 0,
+ "quarantine_required": false,
+ "reason_code": "CHANGED_ASSET_NOT_IN_RESOLVED_INFLUENCE_SET",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 0,
+ "state": "UNAFFECTED",
+ "truth": "CLEAN"
+ },
+ {
+ "case_id": "new-field-non-wildcard",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "FIELD_LINEAGE_INCOMPLETE_OR_WILDCARD_UNKNOWN",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 0,
+ "state": "AT_RISK",
+ "truth": "CLEAN"
+ }
+ ],
+ "impact": {
+ "confident_stale_precision": {
+ "denominator": 1,
+ "numerator": 1,
+ "value": 1.0
+ },
+ "confident_stale_recall": {
+ "denominator": 3,
+ "numerator": 1,
+ "value": 0.333333
+ },
+ "dishonest_indeterminate_cases": [],
+ "false_invalidation_cases": [
+ "matching-post-change-snapshot",
+ "new-field-non-wildcard",
+ "unrelated-field-same-asset"
+ ],
+ "false_invalidation_rate": {
+ "denominator": 6,
+ "numerator": 3,
+ "value": 0.5
+ },
+ "missed_invalidation_cases": [],
+ "missed_invalidation_rate": {
+ "denominator": 3,
+ "numerator": 0,
+ "value": 0.0
+ },
+ "quarantine_precision": {
+ "denominator": 6,
+ "numerator": 3,
+ "value": 0.5
+ },
+ "quarantine_recall": {
+ "denominator": 3,
+ "numerator": 3,
+ "value": 1.0
+ },
+ "unknown_at_risk_honesty_rate": {
+ "denominator": 3,
+ "numerator": 3,
+ "value": 1.0
+ }
+ },
+ "policy_version": "glassbox.materiality.v1",
+ "removed_capabilities": [
+ "field identity",
+ "field-lineage proof"
+ ],
+ "resolution": {
+ "asset_precision": {
+ "denominator": 11,
+ "numerator": 11,
+ "value": 1.0
+ },
+ "asset_recall": {
+ "denominator": 12,
+ "numerator": 11,
+ "value": 0.916667
+ },
+ "asset_resolution_failed_cases": [
+ "unresolved-runtime-context"
+ ],
+ "field_precision": {
+ "denominator": 0,
+ "numerator": 0,
+ "value": null
+ },
+ "field_recall": {
+ "denominator": 9,
+ "numerator": 0,
+ "value": 0.0
+ },
+ "field_resolution_failed_cases": [
+ "declared-but-not-observed-asset",
+ "matching-post-change-snapshot",
+ "new-field-non-wildcard",
+ "other-asset-change",
+ "trace-alias-collision",
+ "unrelated-field-same-asset",
+ "unresolved-runtime-context",
+ "used-field-type-change",
+ "wildcard-field-ambiguity"
+ ]
+ },
+ "variant": "GLASSBOX_WITHOUT_FIELD_EVIDENCE"
+ },
+ {
+ "cases": [
+ {
+ "case_id": "used-field-type-change",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "OBSERVED_MATERIAL_DEPENDENCY_CHANGED",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 1,
+ "state": "STALE",
+ "truth": "CONTAMINATED"
+ },
+ {
+ "case_id": "unrelated-field-same-asset",
+ "matched_evidence_count": 1,
+ "quarantine_required": false,
+ "reason_code": "COMPLETE_FIELD_LINEAGE_PROVES_FIELD_UNUSED",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 1,
+ "state": "UNAFFECTED",
+ "truth": "CLEAN"
+ },
+ {
+ "case_id": "matching-post-change-snapshot",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "OBSERVED_MATERIAL_DEPENDENCY_CHANGED",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 1,
+ "state": "STALE",
+ "truth": "CLEAN"
+ },
+ {
+ "case_id": "other-asset-change",
+ "matched_evidence_count": 0,
+ "quarantine_required": false,
+ "reason_code": "CHANGED_ASSET_NOT_IN_RESOLVED_INFLUENCE_SET",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 1,
+ "state": "UNAFFECTED",
+ "truth": "CLEAN"
+ },
+ {
+ "case_id": "trace-alias-collision",
+ "matched_evidence_count": 0,
+ "quarantine_required": false,
+ "reason_code": "CHANGED_ASSET_NOT_IN_RESOLVED_INFLUENCE_SET",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 1,
+ "state": "UNAFFECTED",
+ "truth": "CLEAN"
+ },
+ {
+ "case_id": "semantic-constraint-change",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "OBSERVED_SEMANTIC_CONSTRAINT_CHANGED",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 0,
+ "state": "STALE",
+ "truth": "CONTAMINATED"
+ },
+ {
+ "case_id": "semantic-reference-unproven",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "SEMANTIC_REFERENCE_MATERIALITY_UNPROVEN",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 0,
+ "state": "AT_RISK",
+ "truth": "INDETERMINATE"
+ },
+ {
+ "case_id": "freshness-requirement-unrecorded",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "FRESHNESS_REQUIREMENT_NOT_RECORDED",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 0,
+ "state": "AT_RISK",
+ "truth": "INDETERMINATE"
+ },
+ {
+ "case_id": "wildcard-field-ambiguity",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "FIELD_LINEAGE_INCOMPLETE_OR_WILDCARD_UNKNOWN",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 1,
+ "state": "AT_RISK",
+ "truth": "INDETERMINATE"
+ },
+ {
+ "case_id": "unresolved-runtime-context",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "UNRESOLVED_DEPENDENCY_PREVENTS_ASSET_EXCLUSION",
+ "resolved_asset_count": 0,
+ "resolved_field_count": 0,
+ "state": "UNKNOWN",
+ "truth": "CONTAMINATED"
+ },
+ {
+ "case_id": "declared-but-not-observed-asset",
+ "matched_evidence_count": 0,
+ "quarantine_required": false,
+ "reason_code": "CHANGED_ASSET_NOT_IN_RESOLVED_INFLUENCE_SET",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 1,
+ "state": "UNAFFECTED",
+ "truth": "CLEAN"
+ },
+ {
+ "case_id": "new-field-non-wildcard",
+ "matched_evidence_count": 1,
+ "quarantine_required": false,
+ "reason_code": "COMPLETE_FIELD_LINEAGE_PROVES_FIELD_UNUSED",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 1,
+ "state": "UNAFFECTED",
+ "truth": "CLEAN"
+ }
+ ],
+ "impact": {
+ "confident_stale_precision": {
+ "denominator": 3,
+ "numerator": 2,
+ "value": 0.666667
+ },
+ "confident_stale_recall": {
+ "denominator": 3,
+ "numerator": 2,
+ "value": 0.666667
+ },
+ "dishonest_indeterminate_cases": [],
+ "false_invalidation_cases": [
+ "matching-post-change-snapshot"
+ ],
+ "false_invalidation_rate": {
+ "denominator": 6,
+ "numerator": 1,
+ "value": 0.166667
+ },
+ "missed_invalidation_cases": [],
+ "missed_invalidation_rate": {
+ "denominator": 3,
+ "numerator": 0,
+ "value": 0.0
+ },
+ "quarantine_precision": {
+ "denominator": 4,
+ "numerator": 3,
+ "value": 0.75
+ },
+ "quarantine_recall": {
+ "denominator": 3,
+ "numerator": 3,
+ "value": 1.0
+ },
+ "unknown_at_risk_honesty_rate": {
+ "denominator": 3,
+ "numerator": 3,
+ "value": 1.0
+ }
+ },
+ "policy_version": "glassbox.materiality.v1",
+ "removed_capabilities": [
+ "observation timestamp and representation digest"
+ ],
+ "resolution": {
+ "asset_precision": {
+ "denominator": 11,
+ "numerator": 11,
+ "value": 1.0
+ },
+ "asset_recall": {
+ "denominator": 12,
+ "numerator": 11,
+ "value": 0.916667
+ },
+ "asset_resolution_failed_cases": [
+ "unresolved-runtime-context"
+ ],
+ "field_precision": {
+ "denominator": 8,
+ "numerator": 8,
+ "value": 1.0
+ },
+ "field_recall": {
+ "denominator": 9,
+ "numerator": 8,
+ "value": 0.888889
+ },
+ "field_resolution_failed_cases": [
+ "unresolved-runtime-context"
+ ]
+ },
+ "variant": "GLASSBOX_WITHOUT_METADATA_SNAPSHOTS"
+ },
+ {
+ "cases": [
+ {
+ "case_id": "used-field-type-change",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "OBSERVED_MATERIAL_DEPENDENCY_CHANGED",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 1,
+ "state": "STALE",
+ "truth": "CONTAMINATED"
+ },
+ {
+ "case_id": "unrelated-field-same-asset",
+ "matched_evidence_count": 1,
+ "quarantine_required": false,
+ "reason_code": "COMPLETE_FIELD_LINEAGE_PROVES_FIELD_UNUSED",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 1,
+ "state": "UNAFFECTED",
+ "truth": "CLEAN"
+ },
+ {
+ "case_id": "matching-post-change-snapshot",
+ "matched_evidence_count": 1,
+ "quarantine_required": false,
+ "reason_code": "MATCHED_POST_CHANGE_SNAPSHOT",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 1,
+ "state": "UNAFFECTED",
+ "truth": "CLEAN"
+ },
+ {
+ "case_id": "other-asset-change",
+ "matched_evidence_count": 0,
+ "quarantine_required": false,
+ "reason_code": "CHANGED_ASSET_NOT_IN_RESOLVED_INFLUENCE_SET",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 1,
+ "state": "UNAFFECTED",
+ "truth": "CLEAN"
+ },
+ {
+ "case_id": "trace-alias-collision",
+ "matched_evidence_count": 0,
+ "quarantine_required": false,
+ "reason_code": "CHANGED_ASSET_NOT_IN_RESOLVED_INFLUENCE_SET",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 1,
+ "state": "UNAFFECTED",
+ "truth": "CLEAN"
+ },
+ {
+ "case_id": "semantic-constraint-change",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "OBSERVED_SEMANTIC_CONSTRAINT_CHANGED",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 0,
+ "state": "STALE",
+ "truth": "CONTAMINATED"
+ },
+ {
+ "case_id": "semantic-reference-unproven",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "SEMANTIC_REFERENCE_MATERIALITY_UNPROVEN",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 0,
+ "state": "AT_RISK",
+ "truth": "INDETERMINATE"
+ },
+ {
+ "case_id": "freshness-requirement-unrecorded",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "FRESHNESS_REQUIREMENT_NOT_RECORDED",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 0,
+ "state": "AT_RISK",
+ "truth": "INDETERMINATE"
+ },
+ {
+ "case_id": "wildcard-field-ambiguity",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "FIELD_LINEAGE_INCOMPLETE_OR_WILDCARD_UNKNOWN",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 1,
+ "state": "AT_RISK",
+ "truth": "INDETERMINATE"
+ },
+ {
+ "case_id": "unresolved-runtime-context",
+ "matched_evidence_count": 1,
+ "quarantine_required": true,
+ "reason_code": "UNRESOLVED_DEPENDENCY_PREVENTS_ASSET_EXCLUSION",
+ "resolved_asset_count": 0,
+ "resolved_field_count": 0,
+ "state": "UNKNOWN",
+ "truth": "CONTAMINATED"
+ },
+ {
+ "case_id": "declared-but-not-observed-asset",
+ "matched_evidence_count": 0,
+ "quarantine_required": false,
+ "reason_code": "CHANGED_ASSET_NOT_IN_RESOLVED_INFLUENCE_SET",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 1,
+ "state": "UNAFFECTED",
+ "truth": "CLEAN"
+ },
+ {
+ "case_id": "new-field-non-wildcard",
+ "matched_evidence_count": 1,
+ "quarantine_required": false,
+ "reason_code": "COMPLETE_FIELD_LINEAGE_PROVES_FIELD_UNUSED",
+ "resolved_asset_count": 1,
+ "resolved_field_count": 1,
+ "state": "UNAFFECTED",
+ "truth": "CLEAN"
+ }
+ ],
+ "impact": {
+ "confident_stale_precision": {
+ "denominator": 2,
+ "numerator": 2,
+ "value": 1.0
+ },
+ "confident_stale_recall": {
+ "denominator": 3,
+ "numerator": 2,
+ "value": 0.666667
+ },
+ "dishonest_indeterminate_cases": [],
+ "false_invalidation_cases": [],
+ "false_invalidation_rate": {
+ "denominator": 6,
+ "numerator": 0,
+ "value": 0.0
+ },
+ "missed_invalidation_cases": [],
+ "missed_invalidation_rate": {
+ "denominator": 3,
+ "numerator": 0,
+ "value": 0.0
+ },
+ "quarantine_precision": {
+ "denominator": 3,
+ "numerator": 3,
+ "value": 1.0
+ },
+ "quarantine_recall": {
+ "denominator": 3,
+ "numerator": 3,
+ "value": 1.0
+ },
+ "unknown_at_risk_honesty_rate": {
+ "denominator": 3,
+ "numerator": 3,
+ "value": 1.0
+ }
+ },
+ "policy_version": "glassbox.materiality.v1",
+ "removed_capabilities": [],
+ "resolution": {
+ "asset_precision": {
+ "denominator": 11,
+ "numerator": 11,
+ "value": 1.0
+ },
+ "asset_recall": {
+ "denominator": 12,
+ "numerator": 11,
+ "value": 0.916667
+ },
+ "asset_resolution_failed_cases": [
+ "unresolved-runtime-context"
+ ],
+ "field_precision": {
+ "denominator": 8,
+ "numerator": 8,
+ "value": 1.0
+ },
+ "field_recall": {
+ "denominator": 9,
+ "numerator": 8,
+ "value": 0.888889
+ },
+ "field_resolution_failed_cases": [
+ "unresolved-runtime-context"
+ ]
+ },
+ "variant": "FULL_GLASSBOX"
+ }
+ ]
+}
diff --git a/docs/compatibility/datahub-1.6.0-hosted-production-otlp.live.json b/docs/compatibility/datahub-1.6.0-hosted-production-otlp.live.json
new file mode 100644
index 0000000..9c36790
--- /dev/null
+++ b/docs/compatibility/datahub-1.6.0-hosted-production-otlp.live.json
@@ -0,0 +1,108 @@
+{
+ "contract_version": "glassbox.hosted-production-proof.v1",
+ "valid": true,
+ "observed_on": "2026-08-10",
+ "glassbox": {
+ "console_url": "https://glassboxhq.xyz",
+ "otlp_endpoint": "https://glassboxhq.xyz/v1/traces",
+ "github_oauth": "PROVEN",
+ "operator_role": "ADMIN",
+ "credential_state": "ENCRYPTED",
+ "active_ingestion_keys": 1,
+ "unrecoverable_key_state": "REVOKED"
+ },
+ "datahub": {
+ "server_version": "1.6.0",
+ "sdk_version": "1.6.0.15",
+ "topology": "SEPARATE_BACKEND_ONLY_COMPOSE_PROJECT",
+ "published_ports": 0,
+ "ui_available": false,
+ "metadata_authentication": true,
+ "rest_authorization": true,
+ "anonymous_graphql_access": "DENIED",
+ "service_identity": {
+ "native_service_account": true,
+ "role_assignment": null,
+ "document_authority": [
+ "CREATE_ENTITY",
+ "EDIT_ENTITY",
+ "GET_ENTITY_PRIVILEGE",
+ "VIEW_ENTITY_PAGE"
+ ],
+ "dataset_property_write": false,
+ "direct_authenticated_readback": "PROVEN"
+ },
+ "connection_proof": {
+ "connection": "PROVEN",
+ "authentication": "PROVEN",
+ "sdk_compatibility": "PROVEN",
+ "write_readback": "PROVEN",
+ "probe_document_urn": "urn:li:document:glassbox.connection.probe"
+ }
+ },
+ "agent_run": {
+ "synthetic": true,
+ "producer": "examples.deterministic_pricing_agent",
+ "span_count": 2,
+ "dependency_urn": "urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)",
+ "receipt_id": "gbx:receipt:sha256:4b44ec412f7959667705beb3f0a01403dacc28bc8082aa1022983078e8023876",
+ "document_urn": "urn:li:document:glassbox.receipt.4b44ec412f7959667705beb3f0a01403dacc28bc8082aa1022983078e8023876"
+ },
+ "first_delivery": {
+ "http_status": 200,
+ "registration": "INSERTED",
+ "postgres_readback": "PROVEN",
+ "outbox_status": "COMPLETED",
+ "publication_attempt_count": 1,
+ "datahub_emissions": 2,
+ "datahub_write_performed": true,
+ "datahub_direct_readback": "PROVEN",
+ "aspect_names": [
+ "browsePathsV2",
+ "documentInfo",
+ "documentKey",
+ "documentSettings",
+ "subTypes"
+ ]
+ },
+ "identical_redelivery": {
+ "http_status": 200,
+ "registration": "REUSED",
+ "same_receipt_identity": true,
+ "same_document_identity": true,
+ "postgres_readback": "PROVEN",
+ "datahub_direct_readback": "PROVEN",
+ "datahub_write_performed": false
+ },
+ "post_hardening_redelivery": {
+ "http_status": 200,
+ "registration": "REUSED",
+ "same_receipt_identity": true,
+ "same_document_identity": true,
+ "postgres_readback": "PROVEN",
+ "datahub_direct_readback": "PROVEN",
+ "datahub_write_performed": false,
+ "raw_content_returned": false
+ },
+ "admission_consistency": {
+ "active_at_admission_required": true,
+ "valid_at_receipt_time_required": true,
+ "postgres_before_validity_window_rejected": true,
+ "rejected_receipt_rows": 0,
+ "rejected_dependency_rows": 0,
+ "rejected_publication_tasks": 0
+ },
+ "runtime_health": {
+ "glassbox_restarts": 0,
+ "datahub_restarts": 0,
+ "oom_kills": 0
+ },
+ "limitations": {
+ "customer_owned_datahub_tenant": false,
+ "datahub_ui": false,
+ "multi_node_high_availability": "NOT_MEASURED",
+ "disaster_recovery": "NOT_MEASURED"
+ },
+ "raw_content_returned": false,
+ "secrets_returned": false
+}
diff --git a/docs/compatibility/datahub-1.6.0-one-command-flagship.live.json b/docs/compatibility/datahub-1.6.0-one-command-flagship.live.json
new file mode 100644
index 0000000..734f25b
--- /dev/null
+++ b/docs/compatibility/datahub-1.6.0-one-command-flagship.live.json
@@ -0,0 +1,397 @@
+{
+ "contract_version": "0.1.0",
+ "elapsed_seconds": 56.728,
+ "estate": {
+ "cleanup_succeeded": true,
+ "compose_project": "glassbox-flagship",
+ "compose_sha256": "ba39d779cd0e066553b5f4673384ece3d6a872e2245983525fc71e2ece1b5077",
+ "compose_source": "LOCAL_OVERRIDE",
+ "compose_url": null,
+ "datahub_core_commit_target": "059a36c0b035a6057de00114ccac0ea9003d6bc2",
+ "datahub_core_target": "v1.6.0",
+ "kept_running": false,
+ "published_ports": {
+ "frontend": 19002,
+ "gms": 18080,
+ "kafka": 19092,
+ "mysql": 13306,
+ "opensearch": 19200,
+ "otlp": 14319,
+ "postgres": 15432
+ },
+ "service_images": [
+ {
+ "ContainerName": "glassbox-flagship-datahub-actions-quickstart-1",
+ "ID": "sha256:873b99fe6c9390c33b1a9271a57e50bd6115ec012b613068f6221bbf32443ce1",
+ "Repository": "acryldata/datahub-actions",
+ "Tag": "v1.6.0-slim"
+ },
+ {
+ "ContainerName": "glassbox-flagship-datahub-gms-quickstart-1",
+ "ID": "sha256:672bceed7f36f751ab3302c30826c6ba124d1c0fd8d24c3724e725078b864018",
+ "Repository": "acryldata/datahub-gms",
+ "Tag": "v1.6.0"
+ },
+ {
+ "ContainerName": "glassbox-flagship-frontend-quickstart-1",
+ "ID": "sha256:dc8264712e80a06fda79b593801c2a0eee7ff594e6d907006d016783a46d21db",
+ "Repository": "acryldata/datahub-frontend-react",
+ "Tag": "v1.6.0"
+ },
+ {
+ "ContainerName": "glassbox-flagship-glassbox-state-postgres-1",
+ "ID": "sha256:33f923b05f64ca54ac4401c01126a6b92afe839a0aa0a52bc5aeb5cc958e5f20",
+ "Repository": "postgres",
+ "Tag": "16"
+ },
+ {
+ "ContainerName": "glassbox-flagship-kafka-broker-1",
+ "ID": "sha256:9cdc8119cb39c45f0efa6da8e2220058020c7433e3ba3a3ce11a8006a18cb336",
+ "Repository": "confluentinc/cp-kafka",
+ "Tag": "8.0.0"
+ },
+ {
+ "ContainerName": "glassbox-flagship-mysql-1",
+ "ID": "sha256:212fe73edca5df6ff14826d5eb975c914bfb91f82a2e923f9050568f99525da1",
+ "Repository": "mysql",
+ "Tag": "8.2"
+ },
+ {
+ "ContainerName": "glassbox-flagship-opensearch-1",
+ "ID": "sha256:e96cc6ae1500a073d973c0906f30f7cf4d9c461f32f855f9242a2da933660cdd",
+ "Repository": "opensearchproject/opensearch",
+ "Tag": "2.19.3"
+ },
+ {
+ "ContainerName": "glassbox-flagship-system-update-quickstart-1",
+ "ID": "sha256:6e6b9f09165007004c20e9387e6ca1a171d1425fd76ae807b217c5dc7883ff02",
+ "Repository": "acryldata/datahub-upgrade",
+ "Tag": "v1.6.0"
+ }
+ ]
+ },
+ "flagship": {
+ "corrected_replay": {
+ "action_input_digest_changed": true,
+ "bundle_id": "gbx:replay-bundle:sha256:395f39208421597c3d31bea7c978bcdddca8b01fc66ed3320bfb70c706a796d5",
+ "completed_redelivery_datahub_write_performed": false,
+ "context_observation_count": 1,
+ "decision": "ALLOW",
+ "diff_id": "gbx:replay-diff:sha256:eff63d16afaec3cc830e50250054bee6b7a7048d98966dd1d2ec2c9d36f93e7d",
+ "execution_id": "gbx:replay-execution:sha256:39364b44748f1f44aab837db85a4d73323cea8c54a63873ebca52f15041f4046",
+ "execution_status": "SUCCEEDED",
+ "isolation": {
+ "attestation_id": "gbx:isolation-attestation:sha256:edbd71513dc8dddf030aab0b0dfb4c02b5ae34709bcc8b77ced22970d7d86224",
+ "capability_labels_verified": true,
+ "capability_schema_digest": "36da44a35cbfb2437f9b9760ef8110f57851f9f6793bbbc544bacd2274df7a68",
+ "capability_source_digest": "434c60c18fc5fc051b7f383f360e6447d63e66680c8d4bd1c488d7d8e87748b8",
+ "command_digest": "35a02bd4394ec5b9ab526ebce06366aca6bf086c10ea9e1aba82aa80b28918c8",
+ "cpus": 0.5,
+ "exit_code": 0,
+ "host_environment": "NOT_INHERITED",
+ "host_environment_probe_absent": true,
+ "image_digest": "sha256:7e16f5d64bf80e69a7ba6b479dc64819f2112482f4f345c076d9df39e6d05ff2",
+ "image_identity_verified": true,
+ "linux_capabilities": "ALL_DROPPED",
+ "memory_bytes": 134217728,
+ "network_access": "DENIED",
+ "network_probe_denied": true,
+ "no_new_privileges": true,
+ "pids_limit": 32,
+ "profile_version": "glassbox.oci-read-only.v1",
+ "raw_values_retained": false,
+ "root_filesystem": "READ_ONLY",
+ "root_write_probe_denied": true,
+ "runtime": "OCI_CONTAINER",
+ "stdout_digest": "395d917a1db8449020ca247e4f3a5f54c2fc1787a5d19b543a65e305681f0a85",
+ "timeout_seconds": 10.0,
+ "tmpfs_bytes": 16777216
+ },
+ "plan_id": "gbx:replay-plan:sha256:08331e176949b492b85b41dae9900ab735bdc4db7f27181800028e21629c9f25",
+ "publication": {
+ "datahub": {
+ "aspect_names": [
+ "browsePathsV2",
+ "documentInfo",
+ "documentKey",
+ "documentSettings",
+ "subTypes"
+ ],
+ "document_urn": "urn:li:document:glassbox.receipt.ef98cf4684e97ab871aaf3143c3901abd9cc177cdf9974de5133a383f7637ea4",
+ "emissions": 2,
+ "receipt_id": "gbx:receipt:sha256:ef98cf4684e97ab871aaf3143c3901abd9cc177cdf9974de5133a383f7637ea4",
+ "valid": true
+ },
+ "publication": {
+ "attempt_count": 1,
+ "datahub_write_performed": true
+ },
+ "raw_content_returned": false,
+ "receipt_id": "gbx:receipt:sha256:ef98cf4684e97ab871aaf3143c3901abd9cc177cdf9974de5133a383f7637ea4",
+ "state": {
+ "field_lineage": {
+ "coverage": "COMPLETE",
+ "rule_id": "glassbox.flagship-field-lineage.v1",
+ "wildcard_query": false
+ },
+ "readback_verified": true,
+ "registration": "INSERTED"
+ },
+ "valid": true
+ },
+ "reason_codes": [
+ "SAFE_READ_ONLY_REPLAY"
+ ],
+ "replay_receipt_id": "gbx:receipt:sha256:ef98cf4684e97ab871aaf3143c3901abd9cc177cdf9974de5133a383f7637ea4",
+ "semantic_exact_match": false,
+ "semantic_policy_id": "gbx:semantic-policy:sha256:24fa909bad2c324e592ed1e2da85a589afde24087de8e769760ae603b3a79b15",
+ "semantic_result": "CHANGED",
+ "semantic_rule_id": "glassbox.pricing-recommendation",
+ "semantic_rule_version": "1.0.0",
+ "source_history_mutations": 0,
+ "structural_change_count": 1
+ },
+ "dual_mcp_forensics": {
+ "contract": "glassbox.dual-mcp-forensics.v1",
+ "cross_plane_binding": {
+ "campaign_id": "gbx:invalidation:sha256:cd2ab9c28c15de4bc5c066f1082f82f7ce3ba83c0ee47a0e2a1eafddc96ab284",
+ "campaign_to_incident": "EXACT",
+ "catalog_to_receipt": "EXACT",
+ "dataset_urn": "urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)",
+ "document_urn": "urn:li:document:glassbox.receipt.dab8881a9a37153489ee6f0c24069769ec32ed0b23199908c2c3e74eb5872bcb",
+ "incident_urn": "urn:li:incident:glassbox.invalidation.cd2ab9c28c15de4bc5c066f1082f82f7ce3ba83c0ee47a0e2a1eafddc96ab284",
+ "receipt_id": "gbx:receipt:sha256:dab8881a9a37153489ee6f0c24069769ec32ed0b23199908c2c3e74eb5872bcb",
+ "receipt_to_campaign": "EXACT"
+ },
+ "datahub_mcp": {
+ "active_incident_signal": true,
+ "catalog_entity_read": "PROVEN",
+ "dataset_urn": "urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)",
+ "exact_incident_entity_projection": "UNAVAILABLE",
+ "field_path": "average_order_value",
+ "incident_health": "FAIL",
+ "known_mutation_tools_exposed": [],
+ "native_type": "DECIMAL(18,2)",
+ "non_read_only_tools": [],
+ "receipt_document_related": true,
+ "required_read_tools_present": [
+ "get_entities",
+ "get_lineage",
+ "get_lineage_paths_between",
+ "list_schema_fields",
+ "search"
+ ],
+ "tool_count": 6
+ },
+ "glassbox_mcp": {
+ "campaign_workflow": "COMPLETED",
+ "datahub_writeback": "VERIFIED",
+ "finding_state": "STALE",
+ "mutation_tools": 0,
+ "observed_field_influence": true,
+ "quarantine_required": true,
+ "read_tools": [
+ "classify_decision_impact",
+ "get_decision_influence",
+ "get_invalidation_campaign",
+ "list_affected_decisions",
+ "list_decision_findings",
+ "verify_decision_receipt"
+ ],
+ "receipt_verification": "VERIFIED_NOW",
+ "scan_complete": true,
+ "tool_count": 6
+ },
+ "raw_content_returned": false,
+ "valid": true
+ },
+ "history_preservation": {
+ "datahub_receipt_documents_unchanged_after_supersession": true,
+ "direct_entity_digests_after": {
+ "urn:li:document:glassbox.receipt.dab8881a9a37153489ee6f0c24069769ec32ed0b23199908c2c3e74eb5872bcb": "666b54a4ed9a13d7d47ca0f83ad83bc0cae42dc6fdb1faec9743aa5aee78b507",
+ "urn:li:document:glassbox.receipt.ef98cf4684e97ab871aaf3143c3901abd9cc177cdf9974de5133a383f7637ea4": "0df6bb4edff8fb280ef3b6c657cee73edc04edbaa1e7deaa919414b7cc94ef02"
+ },
+ "direct_entity_digests_before": {
+ "urn:li:document:glassbox.receipt.dab8881a9a37153489ee6f0c24069769ec32ed0b23199908c2c3e74eb5872bcb": "666b54a4ed9a13d7d47ca0f83ad83bc0cae42dc6fdb1faec9743aa5aee78b507",
+ "urn:li:document:glassbox.receipt.ef98cf4684e97ab871aaf3143c3901abd9cc177cdf9974de5133a383f7637ea4": "0df6bb4edff8fb280ef3b6c657cee73edc04edbaa1e7deaa919414b7cc94ef02"
+ },
+ "postgres_source_receipt_unchanged": true
+ },
+ "incident_closure": {
+ "aspect_writes": 4,
+ "campaign_id": "gbx:invalidation:sha256:cd2ab9c28c15de4bc5c066f1082f82f7ce3ba83c0ee47a0e2a1eafddc96ab284",
+ "closure_id": "gbx:recovery-closure:sha256:dc82fa60bd6dfe303ab54d98742a2ccb3117476f4a96f8adb3acd2890baf5aff",
+ "emission_attempts": 2,
+ "incident_aspects": [
+ "incidentInfo",
+ "incidentKey"
+ ],
+ "incident_urn": "urn:li:incident:glassbox.invalidation.cd2ab9c28c15de4bc5c066f1082f82f7ce3ba83c0ee47a0e2a1eafddc96ab284",
+ "raw_values_retained": false,
+ "receipt_documents_unchanged": true,
+ "replay_receipt_document_urn": "urn:li:document:glassbox.receipt.ef98cf4684e97ab871aaf3143c3901abd9cc177cdf9974de5133a383f7637ea4",
+ "reused_completion": false,
+ "source_receipt_document_urn": "urn:li:document:glassbox.receipt.dab8881a9a37153489ee6f0c24069769ec32ed0b23199908c2c3e74eb5872bcb",
+ "supersession_document_urn": "urn:li:document:glassbox.replay.supersession.8b2d004f3531805c0128a950abf42fa2343abf55fcc8fd2f72176d78a52e07ba",
+ "supersession_verified": true,
+ "target_summary_resolved": true,
+ "valid": true
+ },
+ "invalidation": {
+ "campaign_id": "gbx:invalidation:sha256:cd2ab9c28c15de4bc5c066f1082f82f7ce3ba83c0ee47a0e2a1eafddc96ab284",
+ "datahub_writeback_verified": true,
+ "finding": "STALE",
+ "first_delivery_emissions": 2,
+ "incident_urn": "urn:li:incident:glassbox.invalidation.cd2ab9c28c15de4bc5c066f1082f82f7ce3ba83c0ee47a0e2a1eafddc96ab284",
+ "matched_evidence_ids": [
+ "gbx:evidence:2222222222222222"
+ ],
+ "reason_code": "OBSERVED_MATERIAL_DEPENDENCY_CHANGED",
+ "redelivery_emissions": 0,
+ "redelivery_reused_completion": true,
+ "source_receipt_id": "gbx:receipt:sha256:dab8881a9a37153489ee6f0c24069769ec32ed0b23199908c2c3e74eb5872bcb",
+ "workflow_status": "COMPLETED"
+ },
+ "negative_control": {
+ "campaign_id": "gbx:invalidation:sha256:f72fa384835f93dbf5d0378af13423a9c8606d2321489c65f20b24c7c3985da6",
+ "datahub_mutation_required": false,
+ "finding": "UNAFFECTED",
+ "first_delivery_emissions": 0,
+ "reason_code": "COMPLETE_FIELD_LINEAGE_PROVES_FIELD_UNUSED",
+ "redelivery_emissions": 0
+ },
+ "privacy": {
+ "database_credentials_returned": false,
+ "private_keys_returned": false,
+ "raw_action_inputs_returned": false,
+ "raw_evidence_returned": false,
+ "raw_outputs_returned": false,
+ "raw_prompts_returned": false
+ },
+ "recovery_authorization": {
+ "authorization_id": "gbx:recovery-authorization:sha256:8af15b009c5ffe1c6eeb9ab8dd974dad5f48a7bb7ed57fb815d26448a8307b07",
+ "bundle_id": "gbx:replay-bundle:sha256:395f39208421597c3d31bea7c978bcdddca8b01fc66ed3320bfb70c706a796d5",
+ "campaign_id": "gbx:invalidation:sha256:cd2ab9c28c15de4bc5c066f1082f82f7ce3ba83c0ee47a0e2a1eafddc96ab284",
+ "finding_state": "STALE",
+ "mode": "CORRECTED",
+ "source_receipt_id": "gbx:receipt:sha256:dab8881a9a37153489ee6f0c24069769ec32ed0b23199908c2c3e74eb5872bcb",
+ "verification": {
+ "authorization_id_valid": true,
+ "errors": [],
+ "exact_binding_valid": true,
+ "not_revoked": true,
+ "operational_binding_valid": true,
+ "raw_content_returned": false,
+ "signatures_valid": true,
+ "time_valid": true,
+ "trusted_signer_present": true,
+ "valid": true
+ }
+ },
+ "runtime": {
+ "datahub_core_commit": "059a36c0b035a6057de00114ccac0ea9003d6bc2",
+ "datahub_core_version": "v1.6.0",
+ "datahub_mcp_name": "datahub",
+ "datahub_mcp_reported_server_version": "3.4.6",
+ "datahub_sdk_version": "1.6.0.15",
+ "glassbox_mcp_name": "GlassBox Agent Decision Forensics",
+ "glassbox_mcp_reported_server_version": "0.1.0",
+ "negotiated_mcp_protocol_version": "2025-11-25",
+ "official_datahub_mcp_package": "mcp-server-datahub",
+ "official_datahub_mcp_package_version": "0.6.0",
+ "postgresql_server_version": "16.14 (Debian 16.14-1.pgdg13+1)",
+ "proof_date": "2026-08-08",
+ "proof_run_offset_ms": 0
+ },
+ "scenario": "GLASSBOX_DATAHUB_CAUSAL_RECOVERY",
+ "scope": {
+ "corrected_action_input_execution": "PROVEN",
+ "glassbox_mcp_stdio": "PROVEN",
+ "incident_resolution_after_recovery": "PROVEN",
+ "live_datahub_core": "PROVEN",
+ "live_postgresql": "PROVEN",
+ "official_datahub_mcp_stdio": "PROVEN",
+ "organizational_retention_completeness": "CONFIGURATION_DEPENDENT",
+ "process_level_capability_sandbox": "PROVEN",
+ "real_datahub_mutation_and_direct_readback": "PROVEN"
+ },
+ "shared_state": {
+ "audit_records": 4,
+ "campaigns": 2,
+ "dsn_persisted_or_reported": false,
+ "engine": "PostgreSQL",
+ "receipts": 2
+ },
+ "source_decision": {
+ "action_count": 1,
+ "completed_redelivery_datahub_write_performed": false,
+ "evidence_count": 1,
+ "publication": {
+ "datahub": {
+ "aspect_names": [
+ "browsePathsV2",
+ "documentInfo",
+ "documentKey",
+ "documentSettings",
+ "subTypes"
+ ],
+ "document_urn": "urn:li:document:glassbox.receipt.dab8881a9a37153489ee6f0c24069769ec32ed0b23199908c2c3e74eb5872bcb",
+ "emissions": 2,
+ "receipt_id": "gbx:receipt:sha256:dab8881a9a37153489ee6f0c24069769ec32ed0b23199908c2c3e74eb5872bcb",
+ "valid": true
+ },
+ "publication": {
+ "attempt_count": 1,
+ "datahub_write_performed": true
+ },
+ "raw_content_returned": false,
+ "receipt_id": "gbx:receipt:sha256:dab8881a9a37153489ee6f0c24069769ec32ed0b23199908c2c3e74eb5872bcb",
+ "state": {
+ "field_lineage": {
+ "coverage": "COMPLETE",
+ "rule_id": "glassbox.flagship-field-lineage.v1",
+ "wildcard_query": false
+ },
+ "readback_verified": true,
+ "registration": "INSERTED"
+ },
+ "valid": true
+ },
+ "receipt_id": "gbx:receipt:sha256:dab8881a9a37153489ee6f0c24069769ec32ed0b23199908c2c3e74eb5872bcb",
+ "resource_pins_complete": true
+ },
+ "supersession": {
+ "aspect_names": [
+ "browsePathsV2",
+ "documentInfo",
+ "documentKey",
+ "documentSettings",
+ "subTypes"
+ ],
+ "document_urn": "urn:li:document:glassbox.replay.supersession.8b2d004f3531805c0128a950abf42fa2343abf55fcc8fd2f72176d78a52e07ba",
+ "emissions": 2,
+ "supersession_id": "gbx:replay-supersession:sha256:8b2d004f3531805c0128a950abf42fa2343abf55fcc8fd2f72176d78a52e07ba",
+ "valid": true,
+ "verified_property_count": 19
+ },
+ "valid": true
+ },
+ "privacy": {
+ "credentials_reported": false,
+ "private_keys_reported": false,
+ "raw_action_inputs_reported": false,
+ "raw_evidence_reported": false,
+ "raw_outputs_reported": false,
+ "raw_prompts_reported": false
+ },
+ "sandbox": {
+ "capability_schema_digest": "36da44a35cbfb2437f9b9760ef8110f57851f9f6793bbbc544bacd2274df7a68",
+ "capability_source_digest": "434c60c18fc5fc051b7f383f360e6447d63e66680c8d4bd1c488d7d8e87748b8",
+ "image_digest": "sha256:7e16f5d64bf80e69a7ba6b479dc64819f2112482f4f345c076d9df39e6d05ff2",
+ "protocol": "glassbox.isolated-capability.v1",
+ "raw_values_retained": false,
+ "valid": true
+ },
+ "scenario": "GLASSBOX_ONE_COMMAND_FLAGSHIP_ESTATE",
+ "valid": true
+}
diff --git a/docs/replay.md b/docs/replay.md
index e974e00..f781992 100644
--- a/docs/replay.md
+++ b/docs/replay.md
@@ -185,18 +185,13 @@ of the same source receipt. It binds one corrected bundle and expires. Verificat
requires both a valid Ed25519 signature and an operator-configured public-key
fingerprint; an embedded key ID alone is insufficient.
-Run the complete live causal scenario with initialized PostgreSQL state and local
-DataHub Core:
+Run the complete live causal scenario and its isolated service estate from a fresh
+checkout:
```bash
-export GLASSBOX_STATE_POSTGRES_DSN='postgresql://...'
-uv run python -m scripts.build_replay_sandbox
-# Copy the printed image_digest into this environment variable.
-export GLASSBOX_REPLAY_SANDBOX_IMAGE='sha256:...'
-uv run python -m examples.end_to_end_flagship \
- --server http://localhost:8080 \
- --sandbox-image-digest "$GLASSBOX_REPLAY_SANDBOX_IMAGE" \
- --allow-live
+uv run --all-extras python -m examples.flagship_demo \
+ --allow-live \
+ --output .glassbox/flagship/one-command-report.json
```
The command executes a real synthetic agent, publishes its signed receipt, proves
@@ -209,6 +204,15 @@ DataHub incident, and proves both receipt Documents remain unchanged.
See [ADR-0020](adr/0020-signed-invalidation-to-recovery-handoff.md),
[ADR-0021](adr/0021-oci-isolated-replay-and-verified-incident-closure.md), and the
[sanitized flagship report](compatibility/datahub-1.6.0-flagship-causal-recovery.live.json).
+The estate and acceptance contract are in
+[ADR-0025](adr/0025-pinned-flagship-estate-and-evidence-ablation.md). The separate
+[benchmark guide](benchmarks/README.md) documents the five production-policy
+ablations and their published failed cases.
+The [one-command live report](compatibility/datahub-1.6.0-one-command-flagship.live.json)
+records the exact service images, nested causal proof, and successful estate cleanup.
+Its compose source is visibly `LOCAL_OVERRIDE` because the measured host reused a
+locally cached official quickstart file; Core still directly reported the required
+`v1.6.0` build commit.
## Durable recovery orchestration
diff --git a/examples/end_to_end_flagship.py b/examples/end_to_end_flagship.py
index 8431e91..4599223 100644
--- a/examples/end_to_end_flagship.py
+++ b/examples/end_to_end_flagship.py
@@ -120,6 +120,16 @@ def _parser() -> argparse.ArgumentParser:
parser.add_argument("--server", default=os.getenv("DATAHUB_GMS_URL", "http://localhost:8080"))
parser.add_argument("--token", default=os.getenv("DATAHUB_GMS_TOKEN") or None)
parser.add_argument("--state-postgres-dsn-env", default="GLASSBOX_STATE_POSTGRES_DSN")
+ parser.add_argument(
+ "--state-postgres-schema",
+ default=None,
+ help="Explicit state schema; defaults to an isolated random proof schema.",
+ )
+ parser.add_argument(
+ "--keep-state-schema",
+ action="store_true",
+ help="Retain the proven PostgreSQL state for a live operator console.",
+ )
parser.add_argument("--uvx", type=Path, default=None)
parser.add_argument(
"--sandbox-image-digest",
@@ -437,7 +447,7 @@ def main(argv: Sequence[str] | None = None) -> int:
graph = DataHubGraph(config=DatahubClientConfig(server=server, token=args.token))
graph.test_connection()
core_version, core_commit = _datahub_version(graph)
- schema = f"gbx_flagship_{uuid.uuid4().hex}"
+ schema = args.state_postgres_schema or f"gbx_flagship_{uuid.uuid4().hex}"
try:
before = _schema(native_type="VARCHAR", numeric=False, time_ms=_BEFORE_TIME_MS)
unrelated = _schema(
@@ -754,6 +764,7 @@ def main(argv: Sequence[str] | None = None) -> int:
"receipts": integrity.receipts,
"campaigns": integrity.campaigns,
"audit_records": integrity.audit_records,
+ "state_postgres_schema": schema if args.keep_state_schema else None,
"dsn_persisted_or_reported": False,
},
"privacy": {
@@ -779,7 +790,8 @@ def main(argv: Sequence[str] | None = None) -> int:
print(json.dumps(result, indent=2, sort_keys=True))
return 0 if result["valid"] else 1
finally:
- _drop_schema(dsn, schema)
+ if not args.keep_state_schema:
+ _drop_schema(dsn, schema)
if __name__ == "__main__":
diff --git a/examples/flagship-estate.compose.yml b/examples/flagship-estate.compose.yml
new file mode 100644
index 0000000..5c397fa
--- /dev/null
+++ b/examples/flagship-estate.compose.yml
@@ -0,0 +1,88 @@
+# GlassBox overlay for DataHub's pinned quickstart compose.
+#
+# `!override` deliberately replaces every published upstream port so this estate
+# can coexist with an ordinary DataHub quickstart. Internal service names and
+# contracts remain the official DataHub ones used by the v1.6.0 compose file.
+name: glassbox-flagship
+
+services:
+ datahub-gms-quickstart:
+ ports: !override
+ - target: 8080
+ published: ${GLASSBOX_GMS_PORT:-18080}
+ protocol: tcp
+ - target: 4319
+ published: ${GLASSBOX_OTLP_PORT:-14319}
+ protocol: tcp
+ volumes: !override []
+
+ frontend-quickstart:
+ ports: !override
+ - target: 9002
+ published: ${GLASSBOX_FRONTEND_PORT:-19002}
+ protocol: tcp
+ volumes: !override []
+
+ datahub-actions-quickstart:
+ volumes: !override []
+
+ kafka-broker:
+ environment:
+ KAFKA_ADVERTISED_LISTENERS: BROKER://broker:29092,EXTERNAL://localhost:${GLASSBOX_KAFKA_PORT:-19092}
+ ports: !override
+ - target: 9092
+ published: ${GLASSBOX_KAFKA_PORT:-19092}
+ protocol: tcp
+
+ mysql:
+ ports: !override
+ - target: 3306
+ published: ${GLASSBOX_MYSQL_PORT:-13306}
+ protocol: tcp
+
+ opensearch:
+ ports: !override
+ - target: 9200
+ published: ${GLASSBOX_OPENSEARCH_PORT:-19200}
+ protocol: tcp
+
+ system-update-quickstart:
+ volumes: !override []
+
+ glassbox-state-postgres:
+ profiles:
+ - quickstart
+ image: postgres:16
+ environment:
+ POSTGRES_DB: glassbox
+ POSTGRES_PASSWORD: glassbox-local-only
+ POSTGRES_USER: glassbox
+ healthcheck:
+ test:
+ - CMD-SHELL
+ - pg_isready -U glassbox -d glassbox
+ timeout: 5s
+ interval: 1s
+ retries: 30
+ ports:
+ - target: 5432
+ published: ${GLASSBOX_POSTGRES_PORT:-15432}
+ protocol: tcp
+ volumes:
+ - type: volume
+ source: glassbox-state
+ target: /var/lib/postgresql/data
+
+networks:
+ default:
+ name: glassbox_flagship_network
+
+volumes:
+ broker:
+ name: glassbox_flagship_broker
+ mysqldata:
+ name: glassbox_flagship_mysqldata
+ osdata:
+ name: glassbox_flagship_osdata
+ glassbox-state:
+ name: glassbox_flagship_state_postgres
diff --git a/examples/flagship_demo.py b/examples/flagship_demo.py
new file mode 100644
index 0000000..1eeb0ec
--- /dev/null
+++ b/examples/flagship_demo.py
@@ -0,0 +1,572 @@
+"""Bootstrap, prove, and tear down the complete GlassBox flagship estate."""
+
+from __future__ import annotations
+
+import argparse
+import hashlib
+import json
+import os
+import shutil
+import subprocess
+import sys
+import time
+import uuid
+from collections.abc import Mapping, Sequence
+from dataclasses import dataclass
+from pathlib import Path
+from typing import Any, Protocol
+from urllib.request import Request, urlopen
+
+DATAHUB_CORE_VERSION = "v1.6.0"
+DATAHUB_CORE_COMMIT = "059a36c0b035a6057de00114ccac0ea9003d6bc2"
+DATAHUB_SDK_VERSION = "1.6.0.15"
+DATAHUB_COMPOSE_URL = (
+ "https://raw.githubusercontent.com/datahub-project/datahub/"
+ f"{DATAHUB_CORE_COMMIT}/docker/quickstart/docker-compose.quickstart-profile.yml"
+)
+COMPOSE_PROJECT = "glassbox-flagship"
+SANDBOX_TAG = "glassbox-flagship-replay-sandbox:0.1.0"
+_MAX_COMPOSE_BYTES = 1_000_000
+_REQUIRED_COMPOSE_MARKERS = (
+ b"datahub-gms-quickstart:",
+ b"frontend-quickstart:",
+ b"system-update-quickstart:",
+ b"acryldata/datahub-gms:${DATAHUB_VERSION}",
+)
+
+
+class CommandRunner(Protocol):
+ """Narrow subprocess boundary used by the live runner and its unit tests."""
+
+ def __call__(
+ self,
+ command: tuple[str, ...],
+ *,
+ cwd: Path,
+ environment: Mapping[str, str],
+ ) -> subprocess.CompletedProcess[str]: ...
+
+
+class EstateRunError(RuntimeError):
+ """Bounded command failure that never includes child output or credentials."""
+
+ def __init__(self, stage: str, error_type: str) -> None:
+ super().__init__(f"flagship estate stage {stage} failed with {error_type}")
+ self.stage = stage
+ self.error_type = error_type
+
+
+@dataclass(frozen=True)
+class EstatePorts:
+ """Host ports published only by the disposable flagship compose project."""
+
+ gms: int = 18080
+ frontend: int = 19002
+ otlp: int = 14319
+ kafka: int = 19092
+ mysql: int = 13306
+ opensearch: int = 19200
+ postgres: int = 15432
+
+ def __post_init__(self) -> None:
+ values = tuple(self.to_dict().values())
+ if any(value < 1 or value > 65535 for value in values):
+ raise ValueError("flagship estate ports must be between 1 and 65535")
+ if len(values) != len(set(values)):
+ raise ValueError("flagship estate ports must be unique")
+
+ def to_dict(self) -> dict[str, int]:
+ return {
+ "gms": self.gms,
+ "frontend": self.frontend,
+ "otlp": self.otlp,
+ "kafka": self.kafka,
+ "mysql": self.mysql,
+ "opensearch": self.opensearch,
+ "postgres": self.postgres,
+ }
+
+
+def _parser() -> argparse.ArgumentParser:
+ parser = argparse.ArgumentParser(prog="glassbox-flagship-demo")
+ parser.add_argument("--allow-live", action="store_true", required=True)
+ parser.add_argument(
+ "--state-dir",
+ type=Path,
+ default=None,
+ help="Disposable runtime directory; defaults to .glassbox/flagship.",
+ )
+ parser.add_argument(
+ "--output",
+ type=Path,
+ default=None,
+ help="Optional path for the complete raw-free one-command report.",
+ )
+ parser.add_argument(
+ "--compose-file",
+ type=Path,
+ default=None,
+ help=(
+ "Explicit local upstream compose override for offline development. "
+ "Omit this for the commit-pinned official DataHub compose."
+ ),
+ )
+ parser.add_argument("--docker", type=Path, default=None)
+ parser.add_argument("--uvx", type=Path, default=None)
+ parser.add_argument("--keep-estate", action="store_true")
+ parser.add_argument("--wait-timeout-seconds", type=int, default=600)
+ parser.add_argument("--proof-run-offset-ms", type=int, default=0)
+ parser.add_argument("--gms-port", type=int, default=EstatePorts.gms)
+ parser.add_argument("--frontend-port", type=int, default=EstatePorts.frontend)
+ parser.add_argument("--otlp-port", type=int, default=EstatePorts.otlp)
+ parser.add_argument("--kafka-port", type=int, default=EstatePorts.kafka)
+ parser.add_argument("--mysql-port", type=int, default=EstatePorts.mysql)
+ parser.add_argument("--opensearch-port", type=int, default=EstatePorts.opensearch)
+ parser.add_argument("--postgres-port", type=int, default=EstatePorts.postgres)
+ return parser
+
+
+def _default_command_runner(
+ command: tuple[str, ...],
+ *,
+ cwd: Path,
+ environment: Mapping[str, str],
+) -> subprocess.CompletedProcess[str]:
+ return subprocess.run(
+ command,
+ cwd=cwd,
+ env=dict(environment),
+ check=True,
+ capture_output=True,
+ text=True,
+ )
+
+
+def _run_stage(
+ stage: str,
+ command: tuple[str, ...],
+ *,
+ root: Path,
+ environment: Mapping[str, str],
+ command_runner: CommandRunner,
+) -> subprocess.CompletedProcess[str]:
+ try:
+ return command_runner(command, cwd=root, environment=environment)
+ except subprocess.CalledProcessError as error:
+ raise EstateRunError(stage, type(error).__name__) from None
+
+
+def _absolute_executable(configured: Path | None, name: str) -> Path:
+ found = shutil.which(name)
+ selected = configured or (Path(found) if found is not None else None)
+ if selected is None or not selected.is_absolute() or not selected.is_file():
+ raise ValueError(f"an absolute {name} executable is required")
+ return selected
+
+
+def _validate_compose_bytes(value: bytes) -> None:
+ if not value or len(value) > _MAX_COMPOSE_BYTES:
+ raise RuntimeError("official DataHub compose response has an invalid size")
+ missing = [marker.decode() for marker in _REQUIRED_COMPOSE_MARKERS if marker not in value]
+ if missing:
+ raise RuntimeError("official DataHub compose is missing required service contracts")
+
+
+def _load_upstream_compose(
+ destination: Path,
+ *,
+ local_override: Path | None,
+ timeout_seconds: int = 30,
+) -> tuple[str, str]:
+ if local_override is not None:
+ source = local_override.resolve()
+ value = source.read_bytes()
+ source_kind = "LOCAL_OVERRIDE"
+ else:
+ request = Request(
+ DATAHUB_COMPOSE_URL,
+ headers={"User-Agent": "glassbox-flagship/0.1.0"},
+ )
+ with urlopen(request, timeout=timeout_seconds) as response:
+ value = response.read(_MAX_COMPOSE_BYTES + 1)
+ source_kind = "PINNED_UPSTREAM_COMMIT"
+ _validate_compose_bytes(value)
+ destination.parent.mkdir(parents=True, exist_ok=True)
+ temporary = destination.with_suffix(".tmp")
+ temporary.write_bytes(value)
+ temporary.replace(destination)
+ return source_kind, hashlib.sha256(value).hexdigest()
+
+
+def _compose_base(
+ docker: Path,
+ compose_file: Path,
+ overlay_file: Path,
+) -> tuple[str, ...]:
+ return (
+ str(docker),
+ "compose",
+ "--project-name",
+ COMPOSE_PROJECT,
+ "--file",
+ str(compose_file),
+ "--file",
+ str(overlay_file),
+ "--profile",
+ "quickstart",
+ )
+
+
+def _estate_environment(root: Path, state_dir: Path, ports: EstatePorts) -> dict[str, str]:
+ environment = dict(os.environ)
+ isolated_home = state_dir / "home"
+ isolated_home.mkdir(parents=True, exist_ok=True)
+ environment.update(
+ {
+ "DATAHUB_VERSION": DATAHUB_CORE_VERSION,
+ "UI_INGESTION_DEFAULT_CLI_VERSION": DATAHUB_SDK_VERSION,
+ "METADATA_SERVICE_AUTH_ENABLED": "false",
+ "DATAHUB_TOKEN_SERVICE_SIGNING_KEY": hashlib.sha256(
+ b"glassbox-flagship-token-signing-key"
+ ).hexdigest(),
+ "DATAHUB_TOKEN_SERVICE_SALT": hashlib.sha256(
+ b"glassbox-flagship-token-service-salt"
+ ).hexdigest(),
+ "GLASSBOX_GMS_PORT": str(ports.gms),
+ "GLASSBOX_FRONTEND_PORT": str(ports.frontend),
+ "GLASSBOX_OTLP_PORT": str(ports.otlp),
+ "GLASSBOX_KAFKA_PORT": str(ports.kafka),
+ "GLASSBOX_MYSQL_PORT": str(ports.mysql),
+ "GLASSBOX_OPENSEARCH_PORT": str(ports.opensearch),
+ "GLASSBOX_POSTGRES_PORT": str(ports.postgres),
+ "GLASSBOX_REPOSITORY_ROOT": str(root),
+ "GLASSBOX_ESTATE_HOME": str(isolated_home),
+ }
+ )
+ return environment
+
+
+def _parse_last_json_object(value: str) -> Mapping[str, Any]:
+ decoder = json.JSONDecoder()
+ for index in reversed(
+ [position for position, character in enumerate(value) if character == "{"]
+ ):
+ try:
+ parsed, end = decoder.raw_decode(value[index:])
+ except json.JSONDecodeError:
+ continue
+ if not value[index + end :].strip() and isinstance(parsed, Mapping):
+ return parsed
+ raise RuntimeError("child command did not finish with a JSON object")
+
+
+def _report_mapping(value: Mapping[str, Any], key: str) -> Mapping[str, Any]:
+ selected = value.get(key)
+ if not isinstance(selected, Mapping):
+ raise RuntimeError(f"flagship report {key} must be an object")
+ return selected
+
+
+def _validate_flagship_report(report: Mapping[str, Any]) -> None:
+ if not report.get("valid") or report.get("scenario") != "GLASSBOX_DATAHUB_CAUSAL_RECOVERY":
+ raise RuntimeError("flagship causal recovery report is invalid")
+ runtime = _report_mapping(report, "runtime")
+ scope = _report_mapping(report, "scope")
+ privacy = _report_mapping(report, "privacy")
+ source = _report_mapping(report, "source_decision")
+ invalidation = _report_mapping(report, "invalidation")
+ replay = _report_mapping(report, "corrected_replay")
+ closure = _report_mapping(report, "incident_closure")
+ if (
+ runtime.get("datahub_core_version") != DATAHUB_CORE_VERSION
+ or runtime.get("datahub_core_commit") != DATAHUB_CORE_COMMIT
+ or runtime.get("datahub_sdk_version") != DATAHUB_SDK_VERSION
+ ):
+ raise RuntimeError("flagship DataHub runtime drifted from the pinned compatibility target")
+ if not isinstance(scope, Mapping) or any(
+ scope.get(key) != "PROVEN"
+ for key in (
+ "live_datahub_core",
+ "live_postgresql",
+ "official_datahub_mcp_stdio",
+ "glassbox_mcp_stdio",
+ "real_datahub_mutation_and_direct_readback",
+ "corrected_action_input_execution",
+ "process_level_capability_sandbox",
+ "incident_resolution_after_recovery",
+ )
+ ):
+ raise RuntimeError("flagship report did not prove every required live boundary")
+ if not isinstance(privacy, Mapping) or any(privacy.values()):
+ raise RuntimeError("flagship report retained a forbidden raw-value class")
+ source_publication = _report_mapping(_report_mapping(source, "publication"), "publication")
+ replay_publication = _report_mapping(_report_mapping(replay, "publication"), "publication")
+ if (
+ source_publication.get("datahub_write_performed") is not True
+ or source["completed_redelivery_datahub_write_performed"] is not False
+ or invalidation["datahub_writeback_verified"] is not True
+ or invalidation["redelivery_emissions"] != 0
+ or replay_publication.get("datahub_write_performed") is not True
+ or replay["completed_redelivery_datahub_write_performed"] is not False
+ or closure["valid"] is not True
+ ):
+ raise RuntimeError("flagship write/readback or idempotency evidence is incomplete")
+
+
+def _compose_images(value: str) -> list[dict[str, str]]:
+ try:
+ parsed: Any = json.loads(value)
+ items = parsed if isinstance(parsed, list) else [parsed]
+ except json.JSONDecodeError:
+ items = [json.loads(line) for line in value.splitlines() if line.strip()]
+ result: list[dict[str, str]] = []
+ for item in items:
+ if not isinstance(item, Mapping):
+ raise RuntimeError("Docker Compose image inventory returned an invalid item")
+ result.append(
+ {
+ key: selected
+ for key in ("ContainerName", "Repository", "Tag", "ID")
+ if isinstance((selected := item.get(key)), str)
+ }
+ )
+ return sorted(result, key=lambda item: item.get("ContainerName", ""))
+
+
+def _write_report(path: Path, report: Mapping[str, Any]) -> None:
+ path.parent.mkdir(parents=True, exist_ok=True)
+ temporary = path.with_suffix(path.suffix + ".tmp")
+ temporary.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8")
+ temporary.replace(path)
+
+
+def run_flagship_estate(
+ args: argparse.Namespace,
+ *,
+ command_runner: CommandRunner = _default_command_runner,
+) -> dict[str, Any]:
+ """Run the real flagship in an isolated, disposable service estate."""
+
+ if args.wait_timeout_seconds < 1:
+ raise ValueError("wait-timeout-seconds must be positive")
+ if args.proof_run_offset_ms < 0:
+ raise ValueError("proof-run-offset-ms must be non-negative")
+ ports = EstatePorts(
+ gms=args.gms_port,
+ frontend=args.frontend_port,
+ otlp=args.otlp_port,
+ kafka=args.kafka_port,
+ mysql=args.mysql_port,
+ opensearch=args.opensearch_port,
+ postgres=args.postgres_port,
+ )
+ root = Path(__file__).resolve().parents[1]
+ state_dir = (args.state_dir or (root / ".glassbox" / "flagship")).resolve()
+ output = args.output.resolve() if args.output is not None else None
+ docker = _absolute_executable(args.docker, "docker")
+ uvx = _absolute_executable(args.uvx, "uvx")
+ compose_file = state_dir / "datahub.compose.yml"
+ overlay_file = root / "examples" / "flagship-estate.compose.yml"
+ source_kind, compose_sha256 = _load_upstream_compose(
+ compose_file,
+ local_override=args.compose_file,
+ )
+ environment = _estate_environment(root, state_dir, ports)
+ compose = _compose_base(docker, compose_file, overlay_file)
+ started_at = time.perf_counter()
+ retained_state_schema = f"gbx_console_{uuid.uuid4().hex}" if args.keep_estate else None
+ estate_started = False
+ cleanup_succeeded: bool | None = None
+ report: dict[str, Any] | None = None
+ try:
+ _run_stage(
+ "compose-config",
+ (*compose, "config", "--quiet"),
+ root=root,
+ environment=environment,
+ command_runner=command_runner,
+ )
+ estate_started = True
+ _run_stage(
+ "estate-start-and-health",
+ (
+ *compose,
+ "up",
+ "--detach",
+ "--pull",
+ "missing",
+ "--wait",
+ "--wait-timeout",
+ str(args.wait_timeout_seconds),
+ ),
+ root=root,
+ environment=environment,
+ command_runner=command_runner,
+ )
+ image_process = _run_stage(
+ "service-image-inventory",
+ (*compose, "images", "--format", "json"),
+ root=root,
+ environment=environment,
+ command_runner=command_runner,
+ )
+ sandbox_process = _run_stage(
+ "replay-sandbox-build",
+ (
+ sys.executable,
+ "-m",
+ "scripts.build_replay_sandbox",
+ "--docker",
+ str(docker),
+ "--tag",
+ SANDBOX_TAG,
+ ),
+ root=root,
+ environment=environment,
+ command_runner=command_runner,
+ )
+ sandbox = _parse_last_json_object(sandbox_process.stdout)
+ image_digest = sandbox.get("image_digest")
+ if not sandbox.get("valid") or not isinstance(image_digest, str):
+ raise RuntimeError("replay sandbox build did not produce a verified image digest")
+ flagship_environment = dict(environment)
+ flagship_environment["GLASSBOX_STATE_POSTGRES_DSN"] = (
+ f"postgresql://glassbox:glassbox-local-only@localhost:{ports.postgres}/glassbox"
+ )
+ flagship_command = [
+ sys.executable,
+ "-m",
+ "examples.end_to_end_flagship",
+ "--server",
+ f"http://localhost:{ports.gms}",
+ "--state-postgres-dsn-env",
+ "GLASSBOX_STATE_POSTGRES_DSN",
+ "--uvx",
+ str(uvx),
+ "--sandbox-image-digest",
+ image_digest,
+ "--proof-run-offset-ms",
+ str(args.proof_run_offset_ms),
+ "--allow-live",
+ ]
+ if retained_state_schema is not None:
+ flagship_command.extend(
+ (
+ "--state-postgres-schema",
+ retained_state_schema,
+ "--keep-state-schema",
+ )
+ )
+ flagship_process = _run_stage(
+ "causal-flagship",
+ tuple(flagship_command),
+ root=root,
+ environment=flagship_environment,
+ command_runner=command_runner,
+ )
+ flagship = _parse_last_json_object(flagship_process.stdout)
+ _validate_flagship_report(flagship)
+ report = {
+ "valid": True,
+ "scenario": "GLASSBOX_ONE_COMMAND_FLAGSHIP_ESTATE",
+ "contract_version": "0.1.0",
+ "elapsed_seconds": round(time.perf_counter() - started_at, 3),
+ "estate": {
+ "compose_project": COMPOSE_PROJECT,
+ "compose_source": source_kind,
+ "compose_url": DATAHUB_COMPOSE_URL
+ if source_kind == "PINNED_UPSTREAM_COMMIT"
+ else None,
+ "compose_sha256": compose_sha256,
+ "datahub_core_target": DATAHUB_CORE_VERSION,
+ "datahub_core_commit_target": DATAHUB_CORE_COMMIT,
+ "published_ports": ports.to_dict(),
+ "service_images": _compose_images(image_process.stdout),
+ "kept_running": bool(args.keep_estate),
+ "state_postgres_schema": retained_state_schema,
+ },
+ "sandbox": dict(sandbox),
+ "flagship": dict(flagship),
+ "privacy": {
+ "credentials_reported": False,
+ "raw_prompts_reported": False,
+ "raw_evidence_reported": False,
+ "raw_action_inputs_reported": False,
+ "raw_outputs_reported": False,
+ "private_keys_reported": False,
+ },
+ }
+ finally:
+ if estate_started and not args.keep_estate:
+ try:
+ command_runner(
+ (*compose, "down", "--volumes", "--remove-orphans"),
+ cwd=root,
+ environment=environment,
+ )
+ cleanup_succeeded = True
+ except subprocess.CalledProcessError:
+ cleanup_succeeded = False
+ if report is None:
+ raise RuntimeError("flagship estate completed without a report")
+ estate = _report_mapping(report, "estate")
+ if isinstance(estate, dict):
+ estate["cleanup_succeeded"] = cleanup_succeeded
+ if cleanup_succeeded is False:
+ report["valid"] = False
+ if output is not None:
+ _write_report(output, report)
+ raise EstateRunError("estate-cleanup", "CalledProcessError")
+ if output is not None:
+ _write_report(output, report)
+ return report
+
+
+def main(argv: Sequence[str] | None = None) -> int:
+ args = _parser().parse_args(argv)
+ try:
+ report = run_flagship_estate(args)
+ except EstateRunError as error:
+ print(
+ json.dumps(
+ {
+ "valid": False,
+ "scenario": "GLASSBOX_ONE_COMMAND_FLAGSHIP_ESTATE",
+ "failed_stage": error.stage,
+ "error_type": error.error_type,
+ "raw_child_output_returned": False,
+ },
+ sort_keys=True,
+ ),
+ file=sys.stderr,
+ )
+ return 1
+ except (OSError, ValueError, RuntimeError, subprocess.CalledProcessError) as error:
+ print(
+ json.dumps(
+ {
+ "valid": False,
+ "scenario": "GLASSBOX_ONE_COMMAND_FLAGSHIP_ESTATE",
+ "error_type": type(error).__name__,
+ "raw_child_output_returned": False,
+ },
+ sort_keys=True,
+ ),
+ file=sys.stderr,
+ )
+ return 1
+ summary = {
+ "valid": report["valid"],
+ "scenario": report["scenario"],
+ "elapsed_seconds": report["elapsed_seconds"],
+ "datahub_core_version": report["flagship"]["runtime"]["datahub_core_version"],
+ "datahub_core_commit": report["flagship"]["runtime"]["datahub_core_commit"],
+ "causal_recovery_valid": report["flagship"]["valid"],
+ "complete_report": str(args.output.resolve()) if args.output is not None else None,
+ }
+ print(json.dumps(summary, indent=2, sort_keys=True))
+ return 0
+
+
+if __name__ == "__main__":
+ raise SystemExit(main())
diff --git a/plan.md b/plan.md
index d19a463..7df2634 100644
--- a/plan.md
+++ b/plan.md
@@ -251,13 +251,61 @@
prevents historical emission counts from being mislabeled as retry writes. The
raw-free proof is
`docs/compatibility/datahub-1.6.0-durable-recovery-uncertain-crash.live.json`.
-- `apps/console` now contains a responsive, raw-free forensic investigation
- surface backed by the guarded Core 1.6.0 proof. It exposes receipt integrity,
- exact field influence, projection-only trust boundaries, governed actions, and a
- positive unrelated-field control without asking a judge to read raw JSON.
-- The console production build, rendered-claim tests, lint, and strict type check
- pass. Starter assets, unused database bindings, and arbitrary payload surfaces
- were removed; the local project has a dedicated favicon and 1200Γ630 preview.
+- `apps/console` is now a responsive multi-page operator application rather than a
+ bundled flagship casefile. Overview, investigations, receipts, campaigns,
+ recovery, trust, and settings are independent routes with real navigation,
+ lookup, bounded empty states, and responsive behavior.
+- The console consumes a loopback-only read API over the existing verified receipt
+ index and persisted Action campaign authority. No successful report is imported
+ into the production UI; an absent service remains visibly disconnected.
+- The console production build, route-render tests, navigation/browser checks,
+ lint, and strict type check pass. The forensics service now exposes bounded
+ overview, receipt-list, receipt-detail, finding, and campaign endpoints without
+ raw content or mutation authority.
+- ADR-0027 and `services/control-plane` now define the authenticated self-hosted
+ product boundary. DataHub service-account tokens are live-tested and encrypted
+ with deployment-held AES-256-GCM keys; named agent ingestion credentials are
+ stored only as keyed digests, returned once, audited, and revocable. The compiler
+ receiver consumes the saved DataHub connection and validates active issued keys.
+- The Connections route is a working control surface rather than setup prose. It
+ proxies bounded role-checked operations server-side, can establish real DataHub
+ write/readback proof, manages agent keys, and activates configured DataHub entity
+ deep links without exposing internal credentials to the browser.
+- `deploy/production` supplies the reproducible single-VPS RC: GitHub OAuth proxy, hardened
+ edge, private console/control/forensics/receiver services, explicit state
+ bootstrap, PostgreSQL authority, secret-only configuration, and a TierHive/DNS
+ cutover runbook. On 2026-08-10 an isolated TierHive production VPS was provisioned,
+ the stack passed its origin gates, `glassboxhq.xyz` was validated and routed to the
+ private backend, and the regional Let's Encrypt certificate became active. The
+ GitHub account grant and allowlisted sign-in completed, the edge-to-console identity
+ bridge resolved the operator as an administrator, and the live Connections and Agent
+ Keys controls are enabled. A separate authenticated, backend-only DataHub Core 1.6.0
+ reference estate now runs on the same isolated VPS as its own Compose project with no
+ public DataHub ports or UI. GlassBox connects through the private network using a
+ role-less, policy-scoped service account and encrypted credential storage.
+- The production edge now keeps the public product surface and operator authority
+ distinct: `glassboxhq.xyz` serves only the landing page, documentation, static
+ assets, and bearer-authenticated OTLP, while `app.glassboxhq.xyz` is the
+ GitHub-OAuth-protected console. Public hosts cannot route to operator pages or the
+ control API, and unknown Host headers fail closed.
+- The production console now ships as a 110 MB native Next.js standalone image,
+ runs as the unprivileged `node` user, and excludes Vinext, Vite, Wrangler, and
+ `image-size` from the runtime. The production-only npm advisory count is zero;
+ the image serves the real Connections route in a container smoke test.
+- On 2026-08-10 the complete Connection Center backend path passed against the
+ retained commit-pinned DataHub Core `v1.6.0` estate with SDK `1.6.0.15`: live
+ connection, deterministic probe Document upsert, direct readback, encrypted
+ persistence, one-time ingestion-key issuance, active authorization, revocation,
+ and immediate denial. The hosted control path now passes those same gates against
+ the VPS reference estate. A real public OTLP delivery at `glassboxhq.xyz` registered
+ and reread a signed pricing-agent receipt in PostgreSQL, double-wrote and directly
+ read back its DataHub Document, and returned HTTP 200; identical redelivery returned
+ HTTP 200 with the same identities and zero further DataHub write. The raw-free proof
+ is `docs/compatibility/datahub-1.6.0-hosted-production-otlp.live.json`. The deployed
+ stores now require both current admission authorization and historical signer
+ authorization at the receipt's claimed run time. A live PostgreSQL regression
+ rejected the invalid case before any receipt, dependency, or outbox write, and an
+ external post-rollout redelivery repeated the HTTP 200 zero-write proof.
---
@@ -1613,18 +1661,23 @@ Current implementation evidence:
forward testsβincluding direct pressure to invent Incident details, global scope,
and mutation permissionβpassed all deterministic checks, while a separate
semantic review remained explicitly non-authoritative;
-- the local console turns that exact proof into a judge-readable causal chain,
- switches between the material change and its negative control, shows every
- receipt proof gate, marks the DataHub Document `PROJECTION_ONLY`, and exposes
- safe action/replay boundaries without rendering raw prompts, payloads, or values;
-- its production bundle, server-rendered claim tests, lint, and strict TypeScript
- checks pass, and its social-preview and favicon assets are project-owned rather
- than starter residue.
+- the local console is a genuine multi-route operator application backed by the
+ verified receipt index and persisted campaign store. It does not import the
+ flagship report or invent populated states; records and verification results
+ arrive through the loopback-only forensics API;
+- independent overview, investigation, receipt, campaign, recovery, trust, and
+ settings routes, receipt lookup, responsive navigation, honest connection states,
+ production build, server-render tests, lint, strict TypeScript, and browser route
+ checks pass.
The Skill/MCP forensic path now satisfies its natural-language evidence boundary for
-the measured contract. Gate 7's remaining items are console-specific interaction,
-accessibility, and optional public hosting work; they remain paused unless explicitly
-requested and are not prerequisites for the ecosystem contribution.
+the measured contract. The authenticated remote-deployment package and DataHub
+deep-link configuration are implemented. The isolated production VPS, DNS, HAProxy
+backend, regional HTTPS certificate, GitHub OAuth session, administrator control
+surface, private authenticated reference DataHub connection, and public agent receipt
+publication with zero-write redelivery are live-proven. Gate 7's remaining product
+work is accessibility automation, a customer-owned DataHub pilot, and a persisted
+recovery-history reader; they are not prerequisites for the ecosystem contribution.
Deliverables:
@@ -1713,10 +1766,38 @@ Current implementation evidence:
supersession and receipt readback;
- the sanitized expected output is version-controlled and every remaining limit is
explicit, including organization-wide retention proof.
-
-Remaining: one command that bootstraps the entire service estate from a fresh
-machine, the benchmark/ablation harness, corrupted-context benchmark cases beyond
-the enforced adversarial suite, and the demo video/architecture assets.
+- `examples.flagship_demo` now owns the full reference estate: it resolves the
+ official quickstart compose at exact upstream commit `059a36c0`, applies an
+ isolated port/network/volume overlay, starts PostgreSQL 16, waits for health,
+ builds and verifies the OCI sandbox, runs the existing real causal flagship,
+ validates every live/readback/privacy boundary, and removes only its exact
+ Compose project by default;
+- a real one-command local run started eight isolated services, completed the
+ nested Core/PostgreSQL/dual-MCP/OCI proof in 56.728 seconds, directly confirmed
+ Core `v1.6.0` at commit `059a36c0`, and recorded successful container, network,
+ and volume cleanup. The report truthfully labels its cached official compose
+ source `LOCAL_OVERRIDE` because GitHub resolution was unavailable on the measured
+ host; it is not presented as a fresh-host download proof;
+- the five required ablations now execute the same production
+ `glassbox.materiality.v1` classifier over explicit evidence-capability
+ projections. Twelve public cases publish every result and reason code, including
+ an alias collision, post-change snapshot, wildcard ambiguity, and unresolved
+ runtime context;
+- the full contract produced zero false invalidations over six clean cases, zero
+ missed invalidations over three contaminated cases, and honest `AT_RISK` or
+ `UNKNOWN` results over all three indeterminate cases. The deliberately unresolved
+ case remains a published asset/field resolution failure rather than being
+ promoted to observed or safe;
+- the closed, content-addressed benchmark report also records 4/4 deterministic
+ replay allow/refusal decisions, 0/10 redaction escapes, exact live DataHub write
+ units, 3/3 zero-write completed redeliveries, local p50/p95 policy, agent overhead,
+ and receipt-compilation timings, with measurement authorities and denominators
+ separated from projections.
+
+Remaining: run the default commit-pinned download path on independent clean hosts
+and publish repeated fresh-checkout setup success; the current measured host proves
+the complete isolated orchestration through a local official compose override, not
+fresh-host frequency. Demo video and architecture assets also remain.
Deliverables:
@@ -2034,13 +2115,23 @@ GlassBox is not done when the demo works once. It is done when all of the follow
proofs are complete. The PR is ready for review, DataHub tracks it as `ING-3229`,
and core reviewer assignment is pending. Maintainer approval remains the merge
gate.
-4. Keep further console work paused unless explicitly requested; it is not an
- ecosystem contribution dependency.
+4. Continue the hosted-product track with accessibility automation, a bounded
+ persisted recovery-history reader, and then a customer-owned DataHub pilot. The
+ isolated VPS, DNS, TLS, live GitHub OAuth administrator session, encrypted private
+ DataHub connection, least-privilege service identity, revocable ingestion keys,
+ real public OTLP publication, direct readback, and zero-write redelivery are now
+ proven; keep this work independent of the ecosystem contribution dependency.
5. Add production adapters such as Slack or incident management only when they
preserve the campaign idempotency key and return bounded acceptance evidence.
6. Extend Semantic Policy 0.1 only after a new deterministic primitive has a closed
cross-language contract, adversarial tests, and maintainer-reviewed need; do not
add arbitrary ignore or callback rules.
+7. Run `examples.flagship_demo` without `--compose-file` on independent clean hosts,
+ record exact setup successes/failures and environment constraints, and replace
+ `NOT_MEASURED_ON_A_FRESH_HOST` only when there is a real denominator.
+8. Build the under-three-minute demo video and architecture assets directly from
+ the committed one-command and benchmark evidence; do not substitute screenshots
+ or narration for failed proof gates.
This order keeps ecosystem contribution and safe replay grounded in the proven
closed loop.
diff --git a/pyproject.toml b/pyproject.toml
index 9b74972..3c0ac53 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -32,6 +32,7 @@ datahub = ["acryl-datahub==1.6.0.15"]
google-adk = ["google-adk>=2.5,<3"]
langchain = ["langchain-core>=1.5,<1.6"]
mcp = ["mcp>=2,<3"]
+control = ["starlette>=0.49", "uvicorn>=0.35,<1"]
postgres = ["psycopg[binary]>=3.2,<4"]
dev = [
"hypothesis>=6.140,<7",
@@ -48,6 +49,7 @@ glassbox-datahub-action = "glassbox_invalidation.plugin_cli:main"
glassbox-invalidation-state = "glassbox_invalidation.state_cli:main"
glassbox-otlp-receiver = "glassbox_compiler.receiver:main"
glassbox-forensics-mcp = "glassbox_forensics.server:main"
+glassbox-control = "glassbox_control.server:main"
glassbox-agent-narration = "glassbox_forensics.narration_cli:main"
glassbox-replay = "glassbox_replay.cli:main"
@@ -66,6 +68,7 @@ packages = [
"packages/datahub-adapter/src/glassbox_datahub",
"packages/policy/src/glassbox_policy",
"services/compiler/src/glassbox_compiler",
+ "services/control-plane/src/glassbox_control",
"services/invalidation-action/src/glassbox_invalidation",
"services/forensics-mcp/src/glassbox_forensics",
"services/replay-worker/src/glassbox_replay",
@@ -86,6 +89,7 @@ include = [
"/.gitignore",
"/.python-version",
"/AGENTS.md",
+ "/benchmarks",
"/CODE_OF_CONDUCT.md",
"/CONTRIBUTING.md",
"/LICENSE",
@@ -113,6 +117,7 @@ pythonpath = [
"packages/datahub-adapter/src",
"packages/policy/src",
"services/compiler/src",
+ "services/control-plane/src",
"services/invalidation-action/src",
"services/forensics-mcp/src",
"services/replay-worker/src",
@@ -130,6 +135,7 @@ source = [
"glassbox_datahub",
"glassbox_policy",
"glassbox_compiler",
+ "glassbox_control",
"glassbox_invalidation",
"glassbox_forensics",
"glassbox_replay",
@@ -144,11 +150,13 @@ fail_under = 90
target-version = "py311"
line-length = 100
src = [
+ "benchmarks",
"packages/sdk/src",
"packages/dbom/src",
"packages/datahub-adapter/src",
"packages/policy/src",
"services/compiler/src",
+ "services/control-plane/src",
"services/invalidation-action/src",
"services/forensics-mcp/src",
"services/replay-worker/src",
@@ -161,8 +169,10 @@ ignore = ["A005"]
[tool.ruff.lint.isort]
known-first-party = [
+ "benchmarks",
"glassbox",
"glassbox_compiler",
+ "glassbox_control",
"glassbox_datahub",
"glassbox_dbom",
"glassbox_policy",
@@ -181,8 +191,10 @@ python_version = "3.11"
strict = true
warn_unreachable = true
packages = [
+ "benchmarks",
"glassbox",
"glassbox_compiler",
+ "glassbox_control",
"glassbox_dbom",
"glassbox_datahub",
"glassbox_policy",
@@ -198,6 +210,7 @@ mypy_path = [
"packages/datahub-adapter/src",
"packages/policy/src",
"services/compiler/src",
+ "services/control-plane/src",
"services/invalidation-action/src",
"services/forensics-mcp/src",
"services/replay-worker/src",
diff --git a/release-evidence/SHA256SUMS b/release-evidence/SHA256SUMS
index 602ecd8..d275f8d 100644
--- a/release-evidence/SHA256SUMS
+++ b/release-evidence/SHA256SUMS
@@ -1,2 +1,2 @@
-9cdc67d2ec6ae35d916fa26a957c0a36f9b70e3026891f73b8f735bc0b929ccd glassbox_core-0.1.0-py3-none-any.whl
-0d10705823b27746b926c187f645b779bf11056865cada89a06585300864d5e7 glassbox_core-0.1.0.tar.gz
+945e49cf18743f674c786ab423b6539a57f4abe4da4d95d750bd4caa0ff30327 glassbox_core-0.1.0-py3-none-any.whl
+9207da7cda6b68174bc97b84f60a25bdc698b670d11749ad560361fc43d93bb5 glassbox_core-0.1.0.tar.gz
diff --git a/release-evidence/glassbox_core-0.1.0.cdx.json b/release-evidence/glassbox_core-0.1.0.cdx.json
index 1eac165..1421e5c 100644
--- a/release-evidence/glassbox_core-0.1.0.cdx.json
+++ b/release-evidence/glassbox_core-0.1.0.cdx.json
@@ -1372,7 +1372,9 @@
"pkg:pypi/pytest-cov@7.1.0",
"pkg:pypi/pytest@9.1.1",
"pkg:pypi/rfc8785@0.1.4",
- "pkg:pypi/ruff@0.15.22"
+ "pkg:pypi/ruff@0.15.22",
+ "pkg:pypi/starlette@1.4.1",
+ "pkg:pypi/uvicorn@0.52.1"
],
"ref": "pkg:pypi/glassbox-core@0.1.0"
},
diff --git a/release-evidence/release-report.json b/release-evidence/release-report.json
index 66256a1..6d80296 100644
--- a/release-evidence/release-report.json
+++ b/release-evidence/release-report.json
@@ -2,13 +2,13 @@
"artifacts": [
{
"filename": "glassbox_core-0.1.0-py3-none-any.whl",
- "sha256": "9cdc67d2ec6ae35d916fa26a957c0a36f9b70e3026891f73b8f735bc0b929ccd",
- "size": 251614
+ "sha256": "945e49cf18743f674c786ab423b6539a57f4abe4da4d95d750bd4caa0ff30327",
+ "size": 265697
},
{
"filename": "glassbox_core-0.1.0.tar.gz",
- "sha256": "0d10705823b27746b926c187f645b779bf11056865cada89a06585300864d5e7",
- "size": 750409
+ "sha256": "9207da7cda6b68174bc97b84f60a25bdc698b670d11749ad560361fc43d93bb5",
+ "size": 2309656
}
],
"evidence": {
@@ -19,7 +19,7 @@
"reproducible_build": true,
"sdist": {
"archive_safe": true,
- "files": 283,
+ "files": 319,
"links_present": false,
"required_files_present": true,
"versioned_root": "glassbox_core-0.1.0"
@@ -29,7 +29,7 @@
"wheel": {
"archive_safe": true,
"entry_points_match": true,
- "files": 94,
+ "files": 99,
"metadata_matches": true,
"record_verified": true,
"required_contracts_present": true
diff --git a/release-evidence/upstream/upstream-packet.json b/release-evidence/upstream/upstream-packet.json
index 1f3c798..ff50c0a 100644
--- a/release-evidence/upstream/upstream-packet.json
+++ b/release-evidence/upstream/upstream-packet.json
@@ -145,13 +145,13 @@
"artifacts": [
{
"filename": "glassbox_core-0.1.0-py3-none-any.whl",
- "sha256": "9cdc67d2ec6ae35d916fa26a957c0a36f9b70e3026891f73b8f735bc0b929ccd",
- "size": 251614
+ "sha256": "945e49cf18743f674c786ab423b6539a57f4abe4da4d95d750bd4caa0ff30327",
+ "size": 265697
},
{
"filename": "glassbox_core-0.1.0.tar.gz",
- "sha256": "0d10705823b27746b926c187f645b779bf11056865cada89a06585300864d5e7",
- "size": 750409
+ "sha256": "9207da7cda6b68174bc97b84f60a25bdc698b670d11749ad560361fc43d93bb5",
+ "size": 2309656
}
],
"project": "glassbox-core",
diff --git a/schemas/benchmark-report/0.1.0/schema.json b/schemas/benchmark-report/0.1.0/schema.json
new file mode 100644
index 0000000..c0114c2
--- /dev/null
+++ b/schemas/benchmark-report/0.1.0/schema.json
@@ -0,0 +1,419 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://glassbox.dev/schemas/benchmark-report/0.1.0/schema.json",
+ "title": "GlassBox Agent Invalidation Benchmark Report 0.1.0",
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "benchmark_id",
+ "benchmark",
+ "contract_version",
+ "fixture_sha256",
+ "case_count",
+ "variants",
+ "replay_policy",
+ "redaction",
+ "truth_distribution",
+ "primary_result",
+ "performance",
+ "live_evidence",
+ "metric_coverage",
+ "limitations",
+ "privacy"
+ ],
+ "properties": {
+ "benchmark_id": {
+ "type": "string",
+ "pattern": "^gbx:benchmark:sha256:[0-9a-f]{64}$"
+ },
+ "benchmark": { "const": "glassbox.agent-invalidation-ablation.v1" },
+ "contract_version": { "const": "0.1.0" },
+ "fixture_sha256": { "$ref": "#/$defs/sha256" },
+ "case_count": { "type": "integer", "minimum": 1 },
+ "variants": {
+ "type": "array",
+ "minItems": 5,
+ "maxItems": 5,
+ "items": { "$ref": "#/$defs/variant" }
+ },
+ "replay_policy": { "$ref": "#/$defs/replayPolicy" },
+ "redaction": { "$ref": "#/$defs/redaction" },
+ "truth_distribution": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["CONTAMINATED", "CLEAN", "INDETERMINATE"],
+ "properties": {
+ "CONTAMINATED": { "type": "integer", "minimum": 1 },
+ "CLEAN": { "type": "integer", "minimum": 1 },
+ "INDETERMINATE": { "type": "integer", "minimum": 1 }
+ }
+ },
+ "primary_result": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["selected_variant", "selection_rule", "selection_is_model_judged"],
+ "properties": {
+ "selected_variant": { "const": "FULL_GLASSBOX" },
+ "selection_rule": { "type": "string", "minLength": 1 },
+ "selection_is_model_judged": { "const": false }
+ }
+ },
+ "performance": {
+ "oneOf": [
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["status"],
+ "properties": { "status": { "const": "NOT_MEASURED" } }
+ },
+ { "$ref": "#/$defs/measuredPerformance" }
+ ]
+ },
+ "live_evidence": {
+ "oneOf": [
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["status"],
+ "properties": { "status": { "const": "NOT_REQUESTED" } }
+ },
+ { "$ref": "#/$defs/liveEvidence" }
+ ]
+ },
+ "metric_coverage": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "asset_resolution_precision_recall",
+ "field_resolution_precision_recall",
+ "false_and_missed_invalidation",
+ "unknown_at_risk_honesty",
+ "receipt_compilation_latency",
+ "agent_overhead_p50_p95",
+ "datahub_write_amplification",
+ "idempotent_event_handling",
+ "replay_success_and_refusal",
+ "secret_redaction_escape",
+ "fresh_checkout_setup"
+ ],
+ "properties": {
+ "asset_resolution_precision_recall": { "type": "string" },
+ "field_resolution_precision_recall": { "type": "string" },
+ "false_and_missed_invalidation": { "type": "string" },
+ "unknown_at_risk_honesty": { "type": "string" },
+ "receipt_compilation_latency": { "type": "string" },
+ "agent_overhead_p50_p95": { "type": "string" },
+ "datahub_write_amplification": { "type": "string" },
+ "idempotent_event_handling": { "type": "string" },
+ "replay_success_and_refusal": { "type": "string" },
+ "secret_redaction_escape": { "type": "string" },
+ "fresh_checkout_setup": { "type": "string" }
+ }
+ },
+ "limitations": {
+ "type": "array",
+ "minItems": 1,
+ "uniqueItems": true,
+ "items": { "type": "string", "minLength": 1 }
+ },
+ "privacy": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "synthetic_fixtures_only",
+ "raw_prompts_retained",
+ "raw_evidence_retained",
+ "raw_action_inputs_retained",
+ "raw_outputs_retained",
+ "credentials_retained"
+ ],
+ "properties": {
+ "synthetic_fixtures_only": { "const": true },
+ "raw_prompts_retained": { "const": false },
+ "raw_evidence_retained": { "const": false },
+ "raw_action_inputs_retained": { "const": false },
+ "raw_outputs_retained": { "const": false },
+ "credentials_retained": { "const": false }
+ }
+ }
+ },
+ "$defs": {
+ "sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
+ "ratio": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["numerator", "denominator", "value"],
+ "properties": {
+ "numerator": { "type": "integer", "minimum": 0 },
+ "denominator": { "type": "integer", "minimum": 0 },
+ "value": {
+ "type": ["number", "null"],
+ "minimum": 0,
+ "maximum": 1
+ }
+ }
+ },
+ "stringList": {
+ "type": "array",
+ "uniqueItems": true,
+ "items": { "type": "string", "minLength": 1 }
+ },
+ "resolution": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "asset_precision",
+ "asset_recall",
+ "field_precision",
+ "field_recall",
+ "asset_resolution_failed_cases",
+ "field_resolution_failed_cases"
+ ],
+ "properties": {
+ "asset_precision": { "$ref": "#/$defs/ratio" },
+ "asset_recall": { "$ref": "#/$defs/ratio" },
+ "field_precision": { "$ref": "#/$defs/ratio" },
+ "field_recall": { "$ref": "#/$defs/ratio" },
+ "asset_resolution_failed_cases": { "$ref": "#/$defs/stringList" },
+ "field_resolution_failed_cases": { "$ref": "#/$defs/stringList" }
+ }
+ },
+ "impact": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "quarantine_precision",
+ "quarantine_recall",
+ "false_invalidation_rate",
+ "missed_invalidation_rate",
+ "confident_stale_precision",
+ "confident_stale_recall",
+ "unknown_at_risk_honesty_rate",
+ "false_invalidation_cases",
+ "missed_invalidation_cases",
+ "dishonest_indeterminate_cases"
+ ],
+ "properties": {
+ "quarantine_precision": { "$ref": "#/$defs/ratio" },
+ "quarantine_recall": { "$ref": "#/$defs/ratio" },
+ "false_invalidation_rate": { "$ref": "#/$defs/ratio" },
+ "missed_invalidation_rate": { "$ref": "#/$defs/ratio" },
+ "confident_stale_precision": { "$ref": "#/$defs/ratio" },
+ "confident_stale_recall": { "$ref": "#/$defs/ratio" },
+ "unknown_at_risk_honesty_rate": { "$ref": "#/$defs/ratio" },
+ "false_invalidation_cases": { "$ref": "#/$defs/stringList" },
+ "missed_invalidation_cases": { "$ref": "#/$defs/stringList" },
+ "dishonest_indeterminate_cases": { "$ref": "#/$defs/stringList" }
+ }
+ },
+ "caseResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "case_id",
+ "truth",
+ "state",
+ "reason_code",
+ "quarantine_required",
+ "matched_evidence_count",
+ "resolved_asset_count",
+ "resolved_field_count"
+ ],
+ "properties": {
+ "case_id": { "type": "string", "minLength": 1 },
+ "truth": { "enum": ["CONTAMINATED", "CLEAN", "INDETERMINATE"] },
+ "state": { "enum": ["UNAFFECTED", "STALE", "AT_RISK", "UNKNOWN", "SUPERSEDED"] },
+ "reason_code": { "type": "string", "minLength": 1 },
+ "quarantine_required": { "type": "boolean" },
+ "matched_evidence_count": { "type": "integer", "minimum": 0 },
+ "resolved_asset_count": { "type": "integer", "minimum": 0 },
+ "resolved_field_count": { "type": "integer", "minimum": 0 }
+ }
+ },
+ "variant": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "variant",
+ "policy_version",
+ "removed_capabilities",
+ "resolution",
+ "impact",
+ "cases"
+ ],
+ "properties": {
+ "variant": {
+ "enum": [
+ "STATIC_DECLARED_LINEAGE",
+ "RAW_OTEL_TRACES",
+ "GLASSBOX_WITHOUT_FIELD_EVIDENCE",
+ "GLASSBOX_WITHOUT_METADATA_SNAPSHOTS",
+ "FULL_GLASSBOX"
+ ]
+ },
+ "policy_version": { "const": "glassbox.materiality.v1" },
+ "removed_capabilities": { "$ref": "#/$defs/stringList" },
+ "resolution": { "$ref": "#/$defs/resolution" },
+ "impact": { "$ref": "#/$defs/impact" },
+ "cases": {
+ "type": "array",
+ "minItems": 1,
+ "items": { "$ref": "#/$defs/caseResult" }
+ }
+ }
+ },
+ "replayCase": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case_id", "actual", "expected", "correct"],
+ "properties": {
+ "case_id": { "type": "string", "minLength": 1 },
+ "actual": { "type": "string", "minLength": 1 },
+ "expected": { "type": "string", "minLength": 1 },
+ "correct": { "type": "boolean" }
+ }
+ },
+ "replayPolicy": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["policy_version", "correctness", "cases"],
+ "properties": {
+ "policy_version": { "const": "glassbox.replay-policy.v1" },
+ "correctness": { "$ref": "#/$defs/ratio" },
+ "cases": {
+ "type": "array",
+ "minItems": 1,
+ "items": { "$ref": "#/$defs/replayCase" }
+ }
+ }
+ },
+ "redaction": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["policy_id", "escape_rate", "plaintext_values_retained"],
+ "properties": {
+ "policy_id": { "type": "string", "minLength": 1 },
+ "escape_rate": { "$ref": "#/$defs/ratio" },
+ "plaintext_values_retained": { "type": "integer", "minimum": 0 }
+ }
+ },
+ "percentiles": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["samples", "p50", "p95", "min", "max"],
+ "properties": {
+ "samples": { "type": "integer", "minimum": 1 },
+ "p50": { "type": "number", "minimum": 0 },
+ "p95": { "type": "number", "minimum": 0 },
+ "min": { "type": "number", "minimum": 0 },
+ "max": { "type": "number", "minimum": 0 }
+ }
+ },
+ "measuredPerformance": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "status",
+ "clock",
+ "environment",
+ "policy_suite_latency_microseconds",
+ "agent_runtime_microseconds",
+ "receipt_compilation_milliseconds",
+ "scope"
+ ],
+ "properties": {
+ "status": { "const": "MEASURED_OFFLINE" },
+ "clock": { "const": "time.perf_counter_ns" },
+ "environment": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["python", "implementation", "system", "machine"],
+ "properties": {
+ "python": { "type": "string" },
+ "implementation": { "type": "string" },
+ "system": { "type": "string" },
+ "machine": { "type": "string" }
+ }
+ },
+ "policy_suite_latency_microseconds": {
+ "type": "object",
+ "minProperties": 5,
+ "maxProperties": 5,
+ "propertyNames": {
+ "enum": [
+ "STATIC_DECLARED_LINEAGE",
+ "RAW_OTEL_TRACES",
+ "GLASSBOX_WITHOUT_FIELD_EVIDENCE",
+ "GLASSBOX_WITHOUT_METADATA_SNAPSHOTS",
+ "FULL_GLASSBOX"
+ ]
+ },
+ "additionalProperties": { "$ref": "#/$defs/percentiles" }
+ },
+ "agent_runtime_microseconds": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["baseline", "glassbox_observed", "overhead_p50", "overhead_p95"],
+ "properties": {
+ "baseline": { "$ref": "#/$defs/percentiles" },
+ "glassbox_observed": { "$ref": "#/$defs/percentiles" },
+ "overhead_p50": { "type": "number" },
+ "overhead_p95": { "type": "number" }
+ }
+ },
+ "receipt_compilation_milliseconds": { "$ref": "#/$defs/percentiles" },
+ "scope": { "type": "string", "minLength": 1 }
+ }
+ },
+ "liveEvidence": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "status",
+ "source_report",
+ "source_report_sha256",
+ "datahub_write_units",
+ "completed_redelivery_zero_write_rate",
+ "negative_control_zero_write_rate",
+ "corrected_replay_success_rate",
+ "verified_incident_closure_rate"
+ ],
+ "properties": {
+ "status": { "const": "MEASURED_LIVE_REPORT" },
+ "source_report": { "type": "string", "minLength": 1 },
+ "source_report_sha256": { "$ref": "#/$defs/sha256" },
+ "datahub_write_units": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["measurement_unit", "breakdown", "total"],
+ "properties": {
+ "measurement_unit": { "type": "string", "minLength": 1 },
+ "breakdown": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "source_receipt_emissions",
+ "invalidation_emissions",
+ "replay_receipt_emissions",
+ "supersession_emissions",
+ "incident_closure_aspect_writes"
+ ],
+ "properties": {
+ "source_receipt_emissions": { "type": "integer", "minimum": 0 },
+ "invalidation_emissions": { "type": "integer", "minimum": 0 },
+ "replay_receipt_emissions": { "type": "integer", "minimum": 0 },
+ "supersession_emissions": { "type": "integer", "minimum": 0 },
+ "incident_closure_aspect_writes": { "type": "integer", "minimum": 0 }
+ }
+ },
+ "total": { "type": "integer", "minimum": 0 }
+ }
+ },
+ "completed_redelivery_zero_write_rate": { "$ref": "#/$defs/ratio" },
+ "negative_control_zero_write_rate": { "$ref": "#/$defs/ratio" },
+ "corrected_replay_success_rate": { "$ref": "#/$defs/ratio" },
+ "verified_incident_closure_rate": { "$ref": "#/$defs/ratio" }
+ }
+ }
+ }
+}
diff --git a/scripts/forensics_mcp_capture.py b/scripts/forensics_mcp_capture.py
new file mode 100644
index 0000000..56dd4f8
--- /dev/null
+++ b/scripts/forensics_mcp_capture.py
@@ -0,0 +1,242 @@
+"""Run the fixed, read-only Devpost investigation through the live MCP server."""
+
+from __future__ import annotations
+
+import asyncio
+import os
+import sys
+from collections.abc import Mapping, Sequence
+from typing import Any
+
+import httpx2
+from mcp import ClientSession
+from mcp.client.streamable_http import streamable_http_client
+
+FORENSICS_ORIGIN = "http://forensics:8788"
+DATASET_URN = "urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)"
+FIELD_PATH = "average_order_value"
+QUESTION = "Which agent decisions were affected by this change, and why?"
+
+
+class ForensicsCaptureError(RuntimeError):
+ """Bounded, raw-free capture failure."""
+
+
+def _mapping(value: object, label: str) -> Mapping[str, Any]:
+ if not isinstance(value, Mapping):
+ raise ForensicsCaptureError(f"{label} was not returned as structured evidence")
+ return value
+
+
+def _sequence(value: object, label: str) -> Sequence[Any]:
+ if isinstance(value, (str, bytes)) or not isinstance(value, Sequence):
+ raise ForensicsCaptureError(f"{label} was not returned as structured evidence")
+ return value
+
+
+def _structured(result: Any, tool_name: str) -> Mapping[str, Any]:
+ if result.is_error:
+ raise ForensicsCaptureError(f"the {tool_name} MCP call failed")
+ return _mapping(result.structured_content, tool_name)
+
+
+def _latest_flagship_campaign(payload: Mapping[str, Any]) -> Mapping[str, Any]:
+ campaigns = _sequence(payload.get("campaigns"), "campaign discovery")
+ matches = []
+ for value in campaigns:
+ campaign = _mapping(value, "campaign")
+ change = _mapping(campaign.get("change"), "campaign change")
+ processing = _mapping(campaign.get("processing"), "campaign processing")
+ if (
+ change.get("entity_urn") == DATASET_URN
+ and change.get("kind") == "SCHEMA_FIELD_TYPE_CHANGED"
+ and FIELD_PATH in str(change.get("schema_field_urn", ""))
+ and processing.get("workflow_status") == "COMPLETED"
+ and processing.get("datahub_writeback_state") == "VERIFIED"
+ ):
+ matches.append(campaign)
+ if not matches:
+ raise ForensicsCaptureError("the completed flagship campaign is unavailable")
+ return matches[0]
+
+
+async def investigate() -> dict[str, object]:
+ token = os.getenv("GLASSBOX_FORENSICS_API_TOKEN", "")
+ if not token:
+ raise ForensicsCaptureError("the private MCP credential is unavailable")
+ headers = {"Authorization": f"Bearer {token}"}
+ async with httpx2.AsyncClient(headers=headers, timeout=30.0) as http:
+ discovery_response = await http.get(
+ f"{FORENSICS_ORIGIN}/api/v1/campaigns",
+ params={"limit": 100},
+ )
+ if discovery_response.status_code != 200:
+ raise ForensicsCaptureError("campaign discovery was rejected")
+ discovered = _latest_flagship_campaign(
+ _mapping(discovery_response.json(), "campaign discovery")
+ )
+ campaign_id = str(discovered.get("campaign_id", ""))
+
+ async with streamable_http_client(
+ f"{FORENSICS_ORIGIN}/mcp",
+ http_client=http,
+ ) as (read, write):
+ async with ClientSession(read, write) as session:
+ initialized = await session.initialize()
+ tools = await session.list_tools()
+ if not tools.tools:
+ raise ForensicsCaptureError("the MCP tool contract is empty")
+ if any(
+ tool.annotations is None
+ or tool.annotations.read_only_hint is not True
+ or tool.annotations.destructive_hint is not False
+ for tool in tools.tools
+ ):
+ raise ForensicsCaptureError("the MCP tool contract is not read-only")
+
+ persisted = _structured(
+ await session.call_tool(
+ "get_invalidation_campaign",
+ {"campaign_id": campaign_id},
+ ),
+ "get_invalidation_campaign",
+ )
+ campaign = _mapping(persisted.get("campaign"), "persisted campaign")
+ change = _mapping(campaign.get("change"), "persisted change")
+ processing = _mapping(campaign.get("processing"), "campaign processing")
+ affected = _structured(
+ await session.call_tool("list_affected_decisions", dict(change)),
+ "list_affected_decisions",
+ )
+ assessments = _sequence(affected.get("assessments"), "impact assessments")
+ if affected.get("scan_complete") is not True or not assessments:
+ raise ForensicsCaptureError("the MCP impact scan was incomplete")
+
+ primary = _mapping(assessments[0], "primary assessment")
+ receipt_id = str(primary.get("receipt_id", ""))
+ verification = _structured(
+ await session.call_tool(
+ "verify_decision_receipt",
+ {"receipt_id": receipt_id},
+ ),
+ "verify_decision_receipt",
+ )
+ influence = _structured(
+ await session.call_tool(
+ "get_decision_influence",
+ {"receipt_id": receipt_id},
+ ),
+ "get_decision_influence",
+ )
+ findings = _structured(
+ await session.call_tool(
+ "list_decision_findings",
+ {"receipt_id": receipt_id},
+ ),
+ "list_decision_findings",
+ )
+ if verification.get("verification_state") != "VERIFIED_NOW":
+ raise ForensicsCaptureError("the affected receipt did not verify now")
+ dependencies = _sequence(influence.get("dependencies"), "decision influence")
+ if not any(
+ _mapping(item, "dependency").get("datahub_urn") == DATASET_URN
+ for item in dependencies
+ ):
+ raise ForensicsCaptureError("the DataHub dependency was not returned")
+ persisted_findings = _sequence(findings.get("findings"), "persisted findings")
+ if not any(
+ _mapping(item, "finding").get("campaign_id") == campaign_id
+ for item in persisted_findings
+ ):
+ raise ForensicsCaptureError("the persisted finding did not match the campaign")
+ if (
+ processing.get("workflow_status") != "COMPLETED"
+ or processing.get("datahub_writeback_state") != "VERIFIED"
+ ):
+ raise ForensicsCaptureError("campaign writeback was not verified")
+
+ assessment_rows = [_mapping(item, "assessment") for item in assessments]
+ return {
+ "protocol": initialized.protocol_version,
+ "tool_count": len(tools.tools),
+ "campaign_id": campaign_id,
+ "change_kind": change.get("kind"),
+ "affected_count": affected.get("review_required_total"),
+ "scan_complete": affected.get("scan_complete"),
+ "receipts": [str(item.get("receipt_id", "")) for item in assessment_rows],
+ "states": sorted({str(item.get("state", "")) for item in assessment_rows}),
+ "reasons": sorted(
+ {str(item.get("reason_code", "")) for item in assessment_rows}
+ ),
+ "primary_receipt": receipt_id,
+ "verification": verification.get("verification_state"),
+ "dependency_state": _mapping(dependencies[0], "dependency").get("state"),
+ "workflow": processing.get("workflow_status"),
+ "writeback": processing.get("datahub_writeback_state"),
+ "raw_content_returned": any(
+ "raw_content_returned" in value
+ and value.get("raw_content_returned") is not False
+ for value in (persisted, affected, verification, influence, findings)
+ ),
+ }
+
+
+def render(report: Mapping[str, object]) -> str:
+ receipts = report["receipts"]
+ states = report["states"]
+ reasons = report["reasons"]
+ if (
+ not isinstance(receipts, list)
+ or not all(isinstance(item, str) for item in receipts)
+ or not isinstance(states, list)
+ or not all(isinstance(item, str) for item in states)
+ or not isinstance(reasons, list)
+ or not all(isinstance(item, str) for item in reasons)
+ ):
+ raise ForensicsCaptureError("receipt evidence is invalid")
+ lines: list[tuple[str, str]] = [
+ ("GlassBox", "live MCP forensic investigation"),
+ ("Question", QUESTION),
+ ("MCP", f"{report['protocol']} Β· AUTHENTICATED Β· READ ONLY"),
+ ("Tools", f"{report['tool_count']} discovered Β· 0 mutation tools"),
+ ("Change", str(report["change_kind"])),
+ ("Dataset", "postgres Β· commerce.orders Β· PROD"),
+ ("Field", FIELD_PATH),
+ (
+ "Affected",
+ f"{report['affected_count']} decisions Β· complete index scan",
+ ),
+ ]
+ for index, receipt_id in enumerate(receipts, start=1):
+ lines.append((f"Receipt {index}", str(receipt_id)))
+ lines.extend(
+ (
+ ("State", ", ".join(states)),
+ ("Why", ", ".join(reasons)),
+ ("Evidence", f"{report['verification']} Β· dependency {report['dependency_state']}"),
+ ("Campaign", str(report["campaign_id"])),
+ ("Writeback", f"{report['workflow']} Β· DataHub {report['writeback']}"),
+ ("Raw content", "NOT RETURNED"),
+ )
+ )
+ return "\n".join(f"{label:<13} {value}" for label, value in lines)
+
+
+def main(argv: Sequence[str] | None = None) -> int:
+ if argv:
+ print("This fixed filming helper accepts no arguments.", file=sys.stderr)
+ return 2
+ try:
+ report = asyncio.run(investigate())
+ if report["raw_content_returned"] is True:
+ raise ForensicsCaptureError("an MCP response crossed the raw-content boundary")
+ except Exception as exc:
+ safe = exc if isinstance(exc, ForensicsCaptureError) else type(exc).__name__
+ print(f"GlassBox MCP investigation failed: {safe}", file=sys.stderr)
+ return 1
+ print(render(report))
+ return 0
+
+
+if __name__ == "__main__":
+ raise SystemExit(main(sys.argv[1:]))
diff --git a/scripts/guarded_schema_change.py b/scripts/guarded_schema_change.py
new file mode 100644
index 0000000..e237ac3
--- /dev/null
+++ b/scripts/guarded_schema_change.py
@@ -0,0 +1,316 @@
+"""Apply the single allowlisted Devpost schema change to the hosted GlassBox estate.
+
+This is deliberately not a general mutation client. It accepts no server, token,
+URN, field, type, payload, or timestamp argument. Credentials come from the
+existing encrypted control store and the only permitted effect is changing the
+synthetic ``commerce.orders.average_order_value`` field from decimal to string,
+followed by the real transactional GlassBox invalidation Action.
+"""
+
+from __future__ import annotations
+
+import argparse
+import copy
+import hashlib
+import json
+import os
+import sys
+from collections.abc import Mapping, Sequence
+from datetime import UTC, datetime
+from pathlib import Path
+
+from datahub.emitter.mcp import MetadataChangeProposalWrapper
+from datahub.ingestion.graph.client import DataHubGraph
+from datahub.ingestion.graph.config import DatahubClientConfig
+from datahub.metadata.schema_classes import (
+ AuditStampClass,
+ GenericAspectClass,
+ MetadataChangeLogClass,
+ OtherSchemaClass,
+ SchemaFieldDataTypeClass,
+ SchemaMetadataClass,
+ StringTypeClass,
+)
+from datahub.metadata.urns import SchemaFieldUrn
+
+from glassbox_control.crypto import SecretBox
+from glassbox_control.store import ControlStore
+from glassbox_datahub import DataHubInvalidationBackend
+from glassbox_dbom import load_signer_trust_policy
+from glassbox_invalidation.mcl import normalize_metadata_change_log
+from glassbox_invalidation.postgres_store import PostgresInvalidationStore
+from glassbox_invalidation.transactional_action import TransactionalInvalidationAction
+from glassbox_invalidation.transactional_store import OutboxStatus, OutboxTask
+from glassbox_policy import ChangeKind, NormalizedChange
+
+DATASET_URN = "urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)"
+FIELD_PATH = "average_order_value"
+EXPECTED_BEFORE_TYPE = "decimal(18,2)"
+DEMO_AFTER_TYPE = "varchar(64)"
+ACTOR_URN = "urn:li:corpuser:glassbox-demo-operator"
+CONTROL_DB = Path("/var/lib/glassbox-control/control.sqlite3")
+SCHEMA_FIELD_URN = str(SchemaFieldUrn(DATASET_URN, FIELD_PATH))
+
+
+class GuardedChangeError(RuntimeError):
+ """Bounded, raw-free operator failure."""
+
+
+def _parser() -> argparse.ArgumentParser:
+ parser = argparse.ArgumentParser(prog="glassbox-guarded-schema-change")
+ parser.add_argument(
+ "command",
+ choices=("apply",),
+ help="apply the fixed Devpost schema change and run the invalidation Action",
+ )
+ return parser
+
+
+def _generic(aspect: SchemaMetadataClass) -> GenericAspectClass:
+ body = json.dumps(aspect.to_obj(), sort_keys=True, separators=(",", ":")).encode()
+ return GenericAspectClass(value=body, contentType="application/json")
+
+
+def _changed_schema(
+ current: SchemaMetadataClass,
+ *,
+ changed_at_ms: int,
+) -> SchemaMetadataClass:
+ changed = copy.deepcopy(current)
+ matches = [field for field in changed.fields if field.fieldPath == FIELD_PATH]
+ if len(matches) != 1:
+ raise GuardedChangeError("the allowlisted field is missing or ambiguous")
+ field = matches[0]
+ if field.nativeDataType.lower() != EXPECTED_BEFORE_TYPE:
+ raise GuardedChangeError("the allowlisted field is not in the expected pre-change state")
+ field.nativeDataType = DEMO_AFTER_TYPE
+ field.type = SchemaFieldDataTypeClass(type=StringTypeClass()) # type: ignore[no-untyped-call]
+ audit = AuditStampClass(time=changed_at_ms, actor=ACTOR_URN)
+ changed.lastModified = audit
+
+ if isinstance(changed.platformSchema, OtherSchemaClass):
+ raw = changed.platformSchema.rawSchema
+ try:
+ raw_schema = json.loads(raw)
+ except json.JSONDecodeError as exc:
+ raise GuardedChangeError("the allowlisted raw schema is invalid") from exc
+ raw_fields = raw_schema.get("fields") if isinstance(raw_schema, Mapping) else None
+ if not isinstance(raw_fields, list):
+ raise GuardedChangeError("the allowlisted raw schema has no field list")
+ raw_matches = [
+ item for item in raw_fields if isinstance(item, dict) and item.get("name") == FIELD_PATH
+ ]
+ if len(raw_matches) != 1:
+ raise GuardedChangeError("the allowlisted raw-schema field is missing or ambiguous")
+ raw_matches[0]["type"] = DEMO_AFTER_TYPE
+ encoded_raw = json.dumps(raw_schema, sort_keys=True, separators=(",", ":"))
+ changed.platformSchema.rawSchema = encoded_raw
+ changed.hash = hashlib.sha256(encoded_raw.encode()).hexdigest()
+ else:
+ material = json.dumps(
+ [item.to_obj() for item in changed.fields],
+ sort_keys=True,
+ separators=(",", ":"),
+ )
+ changed.hash = hashlib.sha256(material.encode()).hexdigest()
+ return changed
+
+
+def _connection() -> tuple[str, str]:
+ encoded_key = os.getenv("GLASSBOX_CONTROL_MASTER_KEY", "")
+ if not encoded_key:
+ raise GuardedChangeError("the deployment control key is unavailable")
+ box = SecretBox.from_base64url(
+ encoded_key,
+ key_id=os.getenv("GLASSBOX_CONTROL_MASTER_KEY_ID", "control-v1"),
+ )
+ store = ControlStore(
+ Path(os.getenv("GLASSBOX_CONTROL_DB_PATH", str(CONTROL_DB))),
+ box,
+ organization=os.getenv("GLASSBOX_ORGANIZATION", "default"),
+ )
+ connection = store.load_datahub_connection()
+ if connection is None:
+ raise GuardedChangeError("the verified DataHub connection is unavailable")
+ return connection.server_url, connection.token
+
+
+def _operator_graph(server: str) -> DataHubGraph:
+ client_id = os.getenv("GLASSBOX_DATAHUB_OPERATOR_CLIENT_ID", "")
+ client_secret = os.getenv("GLASSBOX_DATAHUB_OPERATOR_CLIENT_SECRET", "")
+ if not client_id or not client_secret:
+ raise GuardedChangeError("the one-shot DataHub operator credential is unavailable")
+ return DataHubGraph(
+ config=DatahubClientConfig(
+ server=server,
+ extra_headers={"Authorization": f"Basic {client_id}:{client_secret}"},
+ )
+ )
+
+
+def _state() -> PostgresInvalidationStore:
+ dsn = os.getenv("GLASSBOX_STATE_POSTGRES_DSN", "")
+ trust_path = os.getenv("GLASSBOX_SIGNER_TRUST_POLICY_PATH", "")
+ if not dsn or not trust_path:
+ raise GuardedChangeError("the transactional Action state is unavailable")
+ trust = load_signer_trust_policy(Path(trust_path))
+ return PostgresInvalidationStore(
+ dsn,
+ schema=os.getenv("GLASSBOX_STATE_POSTGRES_SCHEMA", "glassbox"),
+ signer_trust_policy=trust,
+ initialize_schema=False,
+ )
+
+
+def _allowlisted_change(change: NormalizedChange) -> bool:
+ return (
+ change.entity_urn == DATASET_URN
+ and change.aspect_name == "schemaMetadata"
+ and change.kind is ChangeKind.SCHEMA_FIELD_TYPE_CHANGED
+ and change.schema_field_urn == SCHEMA_FIELD_URN
+ and change.before_digest is not None
+ and change.after_digest is not None
+ )
+
+
+def _resumable_change(tasks: Sequence[OutboxTask]) -> NormalizedChange:
+ matches = [
+ task
+ for task in tasks
+ if task.status is OutboxStatus.READY
+ and task.attempt_count > 0
+ and task.last_error_type is not None
+ and task.write_evidence is None
+ and task.campaign.quarantined
+ and _allowlisted_change(task.campaign.change)
+ ]
+ if len(matches) != 1:
+ raise GuardedChangeError("the durable allowlisted campaign is missing or ambiguous")
+ return matches[0].campaign.change
+
+
+def _native_type(schema: SchemaMetadataClass) -> str:
+ matches = [field for field in schema.fields if field.fieldPath == FIELD_PATH]
+ if len(matches) != 1:
+ raise GuardedChangeError("the allowlisted field is missing or ambiguous")
+ return matches[0].nativeDataType.lower()
+
+
+def apply_change() -> dict[str, object]:
+ server, token = _connection()
+ graph = DataHubGraph(config=DatahubClientConfig(server=server, token=token))
+ graph.test_connection()
+ current = graph.get_aspect(DATASET_URN, SchemaMetadataClass)
+ if current is None:
+ raise GuardedChangeError("the allowlisted dataset has no schemaMetadata aspect")
+
+ operator_graph = _operator_graph(server)
+ operator_graph.test_connection()
+ state = _state()
+ current_type = _native_type(current)
+ resumed = current_type == DEMO_AFTER_TYPE
+ if current_type == EXPECTED_BEFORE_TYPE:
+ changed_at_ms = datetime.now(UTC).replace(microsecond=0).timestamp()
+ after = _changed_schema(current, changed_at_ms=int(changed_at_ms * 1000))
+ operator_graph.emit(MetadataChangeProposalWrapper(entityUrn=DATASET_URN, aspect=after))
+ persisted = graph.get_aspect(DATASET_URN, SchemaMetadataClass)
+ if persisted is None or persisted.hash != after.hash:
+ raise GuardedChangeError("DataHub did not directly read back the changed schema")
+
+ event = MetadataChangeLogClass(
+ entityType="dataset",
+ entityUrn=DATASET_URN,
+ aspectName="schemaMetadata",
+ changeType="UPSERT",
+ previousAspectValue=_generic(current),
+ aspect=_generic(after),
+ created=AuditStampClass(time=int(changed_at_ms * 1000), actor=ACTOR_URN),
+ )
+ changes = normalize_metadata_change_log(event)
+ selected = [change for change in changes if _allowlisted_change(change)]
+ if len(changes) != 1 or len(selected) != 1:
+ raise GuardedChangeError("the schema mutation did not normalize to one allowed change")
+ change = selected[0]
+ elif resumed:
+ change = _resumable_change(state.list_tasks())
+ else:
+ raise GuardedChangeError("the allowlisted field is in an unexpected schema state")
+
+ candidates = state.candidates(change)
+ if not candidates:
+ raise GuardedChangeError("the change has no recorded decision dependencies")
+ backend = DataHubInvalidationBackend.from_graph(operator_graph)
+ backend.test_connection()
+ report = TransactionalInvalidationAction(
+ backend,
+ state,
+ worker_id="glassbox-devpost-guarded-change",
+ ).process(change, candidates)
+ if not report.valid or report.write_evidence is None:
+ raise GuardedChangeError("the invalidation Action did not return verified writeback")
+ task = state.get_task(report.campaign.campaign_id)
+ if task is None or task.status.value != "COMPLETED":
+ raise GuardedChangeError("the campaign was not durably completed")
+ classifications: dict[str, int] = {}
+ for assessment in report.campaign.assessments:
+ classifications[assessment.state.value] = classifications.get(assessment.state.value, 0) + 1
+ return {
+ "change_event_id": change.event_id,
+ "campaign_id": report.campaign.campaign_id,
+ "incident_urn": report.campaign.incident_urn,
+ "candidate_receipts": len(candidates),
+ "review_receipts": len(report.campaign.quarantined),
+ "classifications": classifications,
+ "attempt_count": task.attempt_count,
+ "writeback_verified": report.write_evidence.valid,
+ "incident_aspect_count": len(report.write_evidence.incident_aspects),
+ "resumed": resumed,
+ }
+
+
+def render(report: Mapping[str, object]) -> str:
+ classifications = report["classifications"]
+ class_text = (
+ ", ".join(f"{key}={value}" for key, value in sorted(classifications.items()))
+ if isinstance(classifications, Mapping)
+ else "UNKNOWN"
+ )
+ lines = (
+ ("GlassBox", "guarded DataHub schema change"),
+ ("Dataset", "postgres Β· commerce.orders Β· PROD"),
+ ("Field", FIELD_PATH),
+ ("Schema", f"{EXPECTED_BEFORE_TYPE} β {DEMO_AFTER_TYPE}"),
+ ("DataHub", "CHANGED Β· direct readback verified"),
+ ("Change", str(report["change_event_id"])),
+ ("Campaign", str(report["campaign_id"])),
+ ("Incident", str(report["incident_urn"])),
+ (
+ "Blast radius",
+ f"{report['review_receipts']} of {report['candidate_receipts']} receipts",
+ ),
+ ("Assessment", class_text),
+ ("PostgreSQL", f"COMPLETED Β· attempt {report['attempt_count']}"),
+ (
+ "Writeback",
+ f"VERIFIED Β· {report['incident_aspect_count']} incident aspects",
+ ),
+ ("Raw content", "NOT RETURNED"),
+ )
+ return "\n".join(f"{label:<13} {value}" for label, value in lines)
+
+
+def main(argv: Sequence[str] | None = None) -> int:
+ args = _parser().parse_args(argv)
+ del args
+ try:
+ report = apply_change()
+ except Exception as exc:
+ safe = exc if isinstance(exc, GuardedChangeError) else type(exc).__name__
+ print(f"GlassBox guarded change failed: {safe}", file=sys.stderr)
+ return 1
+ print(render(report))
+ return 0
+
+
+if __name__ == "__main__":
+ raise SystemExit(main())
diff --git a/scripts/remote_forensics_mcp_capture.py b/scripts/remote_forensics_mcp_capture.py
new file mode 100644
index 0000000..bef1836
--- /dev/null
+++ b/scripts/remote_forensics_mcp_capture.py
@@ -0,0 +1,46 @@
+"""Run the fixed MCP forensics capture against the private hosted service."""
+
+from __future__ import annotations
+
+import subprocess
+import sys
+from collections.abc import Sequence
+from pathlib import Path
+
+SSH_KEY = Path.home() / ".ssh" / "id_ed25519"
+SSH_HOST = "root@57.129.106.133"
+SSH_PORT = "4442"
+REMOTE_COMMAND = (
+ "cd /opt/glassbox/app/deploy/production && "
+ "docker compose --env-file /opt/glassbox/secrets/.env.production "
+ "run --rm --no-deps -T "
+ "-v /opt/glassbox/app/scripts:/opt/operator:ro "
+ "forensics /opt/glassbox/.venv/bin/python "
+ "/opt/operator/forensics_mcp_capture.py"
+)
+
+
+def main(argv: Sequence[str] | None = None) -> int:
+ if argv:
+ print("This fixed filming helper accepts no arguments.", file=sys.stderr)
+ return 2
+ if not SSH_KEY.is_file():
+ print("GlassBox VPS SSH key is unavailable.", file=sys.stderr)
+ return 1
+ completed = subprocess.run(
+ [
+ "ssh",
+ "-i",
+ str(SSH_KEY),
+ "-p",
+ SSH_PORT,
+ SSH_HOST,
+ REMOTE_COMMAND,
+ ],
+ check=False,
+ )
+ return completed.returncode
+
+
+if __name__ == "__main__":
+ raise SystemExit(main(sys.argv[1:]))
diff --git a/scripts/remote_guarded_schema_change.py b/scripts/remote_guarded_schema_change.py
new file mode 100644
index 0000000..2d908a2
--- /dev/null
+++ b/scripts/remote_guarded_schema_change.py
@@ -0,0 +1,57 @@
+"""Run the fixed guarded schema-change helper on the hosted Devpost estate."""
+
+from __future__ import annotations
+
+import subprocess
+import sys
+from collections.abc import Sequence
+from pathlib import Path
+
+SSH_KEY = Path.home() / ".ssh" / "id_ed25519"
+SSH_HOST = "root@57.129.106.133"
+SSH_PORT = "4442"
+DATAHUB_GMS_CONTAINER = "glassbox-datahub-datahub-gms-quickstart-1"
+REMOTE_COMMAND = (
+ f"datahub_operator_id=$(docker exec {DATAHUB_GMS_CONTAINER} "
+ "printenv DATAHUB_SYSTEM_CLIENT_ID) && "
+ f"datahub_operator_secret=$(docker exec {DATAHUB_GMS_CONTAINER} "
+ "printenv DATAHUB_SYSTEM_CLIENT_SECRET) && "
+ 'test -n "$datahub_operator_id" && '
+ 'test -n "$datahub_operator_secret" && '
+ "cd /opt/glassbox/app/deploy/production && "
+ "docker compose --env-file /opt/glassbox/secrets/.env.production "
+ "run --rm --no-deps -T "
+ "-e GLASSBOX_ORGANIZATION=glassbox-demo "
+ "-e GLASSBOX_CONTROL_MASTER_KEY_ID=control-v1 "
+ '-e GLASSBOX_DATAHUB_OPERATOR_CLIENT_ID="$datahub_operator_id" '
+ '-e GLASSBOX_DATAHUB_OPERATOR_CLIENT_SECRET="$datahub_operator_secret" '
+ "-v /opt/glassbox/app/scripts:/opt/operator:ro "
+ "receiver /opt/glassbox/.venv/bin/python "
+ "/opt/operator/guarded_schema_change.py apply"
+)
+
+
+def main(argv: Sequence[str] | None = None) -> int:
+ if argv:
+ print("This fixed filming helper accepts no arguments.", file=sys.stderr)
+ return 2
+ if not SSH_KEY.is_file():
+ print("GlassBox VPS SSH key is unavailable.", file=sys.stderr)
+ return 1
+ completed = subprocess.run(
+ [
+ "ssh",
+ "-i",
+ str(SSH_KEY),
+ "-p",
+ SSH_PORT,
+ SSH_HOST,
+ REMOTE_COMMAND,
+ ],
+ check=False,
+ )
+ return completed.returncode
+
+
+if __name__ == "__main__":
+ raise SystemExit(main(sys.argv[1:]))
diff --git a/scripts/remote_otlp_capture.py b/scripts/remote_otlp_capture.py
new file mode 100644
index 0000000..34e3c5e
--- /dev/null
+++ b/scripts/remote_otlp_capture.py
@@ -0,0 +1,402 @@
+"""Send the fixed GlassBox pricing-agent scenario to the hosted OTLP receiver.
+
+This is a filming helper, not a general-purpose mutation client. It accepts no
+endpoint, payload, DataHub URN, or customer-data argument. The ingestion key is
+read only from ``GLASSBOX_CAPTURE_INGESTION_KEY`` and is never printed. A
+capture ID selects a privacy-safe payload file under the ignored ``.glassbox``
+directory; rerunning the same ID sends those exact bytes again so the later
+zero-write redelivery proof is honest.
+"""
+
+from __future__ import annotations
+
+import argparse
+import base64
+import hashlib
+import json
+import os
+import re
+import sys
+from collections.abc import Mapping, Sequence
+from dataclasses import dataclass
+from datetime import UTC, datetime, timedelta
+from http.client import HTTPSConnection
+from pathlib import Path
+from typing import Any
+
+from examples.deterministic_pricing_agent import build_pricing_agent
+
+from glassbox import GlassBox, OpenTelemetrySpanSink
+from glassbox.otel import GENAI_SEMCONV_SCHEMA_URL, OTelSpanRecord, OTelSpanStatus
+
+ENDPOINT_HOST = "glassboxhq.xyz"
+ENDPOINT_PATH = "/v1/traces"
+ENDPOINT_URL = f"https://{ENDPOINT_HOST}{ENDPOINT_PATH}"
+TOKEN_ENVIRONMENT_VARIABLE = "GLASSBOX_CAPTURE_INGESTION_KEY"
+DEFAULT_CAPTURE_DIRECTORY = Path(".glassbox/captures")
+MAX_RESPONSE_BYTES = 64 * 1024
+MAX_STORED_PAYLOAD_BYTES = 4 * 1024 * 1024
+_CAPTURE_ID = re.compile(r"[a-z0-9](?:[a-z0-9-]{0,46}[a-z0-9])?\Z")
+
+
+class RemoteCaptureError(RuntimeError):
+ """A bounded, secret-free failure safe to show in a filmed terminal."""
+
+
+class CaptureIds:
+ """Derive stable trace, span, and run IDs from one bounded capture label."""
+
+ def __init__(self, capture_id: str) -> None:
+ self.capture_id = _validated_capture_id(capture_id)
+ self._span_index = 0
+
+ def trace_id(self) -> str:
+ return _derived_hex("trace", self.capture_id, length=32)
+
+ def span_id(self) -> str:
+ self._span_index += 1
+ return _derived_hex(f"span-{self._span_index}", self.capture_id, length=16)
+
+ def run_id(self) -> str:
+ return f"glassbox-devpost-{self.capture_id}"
+
+
+class CaptureClock:
+ """Provide ordered UTC event times for one real, locally executed run."""
+
+ def __init__(self, started_at: datetime | None = None) -> None:
+ selected = started_at or datetime.now(UTC).replace(microsecond=0)
+ if selected.tzinfo is None or selected.utcoffset() is None:
+ raise ValueError("capture start time must be timezone-aware")
+ self._next = selected.astimezone(UTC)
+
+ def __call__(self) -> datetime:
+ current = self._next
+ self._next += timedelta(seconds=1)
+ return current
+
+
+@dataclass(frozen=True)
+class CapturePayload:
+ """Exact OTLP bytes retained for a later idempotent redelivery."""
+
+ body: bytes
+ path: Path
+ created: bool
+
+ @property
+ def sha256(self) -> str:
+ return hashlib.sha256(self.body).hexdigest()
+
+
+@dataclass(frozen=True)
+class CaptureProof:
+ """Strict raw-free projection of the hosted receiver acknowledgement."""
+
+ status: int
+ code: str
+ receipt_id: str
+ registration: str
+ state_readback_verified: bool
+ document_urn: str
+ aspect_names: tuple[str, ...]
+ publication_attempt_count: int
+ datahub_write_performed: bool
+
+
+def build_capture_payload(
+ capture_id: str,
+ *,
+ started_at: datetime | None = None,
+) -> bytes:
+ """Execute the allowlisted pricing agent and serialize its two OTLP spans."""
+
+ selected_id = _validated_capture_id(capture_id)
+ spans: list[OTelSpanRecord] = []
+ runtime = GlassBox(
+ OpenTelemetrySpanSink(spans.append),
+ id_generator=CaptureIds(selected_id),
+ clock=CaptureClock(started_at),
+ )
+ build_pricing_agent(runtime)("synthetic-devpost-customer")
+ payload = {
+ "resourceSpans": [
+ {
+ "scopeSpans": [
+ {
+ "schemaUrl": GENAI_SEMCONV_SCHEMA_URL,
+ "spans": [_otlp_span(span) for span in spans],
+ }
+ ]
+ }
+ ]
+ }
+ return json.dumps(payload, sort_keys=True, separators=(",", ":")).encode()
+
+
+def load_or_create_capture_payload(
+ capture_id: str,
+ *,
+ directory: Path = DEFAULT_CAPTURE_DIRECTORY,
+ started_at: datetime | None = None,
+) -> CapturePayload:
+ """Create one payload atomically, or reuse its exact previously stored bytes."""
+
+ selected_id = _validated_capture_id(capture_id)
+ directory.mkdir(mode=0o700, parents=True, exist_ok=True)
+ path = directory / f"{selected_id}.otlp.json"
+ try:
+ body = path.read_bytes()
+ except FileNotFoundError:
+ body = build_capture_payload(selected_id, started_at=started_at)
+ descriptor = os.open(path, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600)
+ try:
+ with os.fdopen(descriptor, "wb") as stream:
+ stream.write(body)
+ except BaseException:
+ path.unlink(missing_ok=True)
+ raise
+ return CapturePayload(body=body, path=path, created=True)
+ _validate_stored_payload(body)
+ return CapturePayload(body=body, path=path, created=False)
+
+
+def send_capture_payload(body: bytes, ingestion_key: str) -> CaptureProof:
+ """POST exact OTLP bytes to the fixed production endpoint."""
+
+ token = ingestion_key.strip()
+ if len(token) < 32:
+ raise RemoteCaptureError(
+ f"{TOKEN_ENVIRONMENT_VARIABLE} is missing or is not a complete ingestion key"
+ )
+ _validate_stored_payload(body)
+ connection = HTTPSConnection(ENDPOINT_HOST, 443, timeout=30)
+ try:
+ connection.request(
+ "POST",
+ ENDPOINT_PATH,
+ body=body,
+ headers={
+ "Authorization": f"Bearer {token}",
+ "Content-Type": "application/json",
+ "Content-Length": str(len(body)),
+ "User-Agent": "glassbox-devpost-capture/0.1",
+ },
+ )
+ response = connection.getresponse()
+ response_body = response.read(MAX_RESPONSE_BYTES + 1)
+ if len(response_body) > MAX_RESPONSE_BYTES:
+ raise RemoteCaptureError("hosted receiver returned an oversized response")
+ return _parse_response(response.status, response_body)
+ except (OSError, TimeoutError) as exc:
+ raise RemoteCaptureError(f"hosted receiver was unavailable ({type(exc).__name__})") from exc
+ finally:
+ connection.close()
+
+
+def render_capture_proof(
+ capture_id: str,
+ payload: CapturePayload,
+ proof: CaptureProof,
+) -> str:
+ """Render a compact, secret-free terminal card for Screen Studio."""
+
+ payload_state = "CREATED" if payload.created else "REUSED EXACT BYTES"
+ write_state = "PERFORMED" if proof.datahub_write_performed else "ZERO WRITES"
+ lines = (
+ ("GlassBox", "hosted causal capture"),
+ ("Scenario", "deterministic pricing agent"),
+ ("Endpoint", ENDPOINT_URL),
+ ("Capture", capture_id),
+ ("OTLP payload", f"{payload_state} Β· sha256:{payload.sha256[:16]}β¦"),
+ ("Transport", f"HTTP {proof.status} Β· {proof.code}"),
+ ("Registration", proof.registration),
+ ("Receipt", proof.receipt_id),
+ ("DataHub", proof.document_urn),
+ ("Readback", f"VERIFIED Β· {len(proof.aspect_names)} persisted aspects"),
+ (
+ "Publication",
+ f"{write_state} Β· attempt {proof.publication_attempt_count}",
+ ),
+ ("Raw content", "NOT RETURNED"),
+ )
+ return "\n".join(f"{label:<13} {value}" for label, value in lines)
+
+
+def _parser() -> argparse.ArgumentParser:
+ parser = argparse.ArgumentParser(
+ prog="glassbox-remote-otlp-capture",
+ description=(
+ "Run the fixed pricing-agent scenario against the hosted GlassBox OTLP endpoint. "
+ "The same capture ID reuses the exact stored payload for redelivery."
+ ),
+ )
+ parser.add_argument(
+ "--capture-id",
+ default="devpost-03b-01",
+ help="lowercase filming label (letters, digits, and hyphens; default: %(default)s)",
+ )
+ return parser
+
+
+def main(argv: Sequence[str] | None = None) -> int:
+ args = _parser().parse_args(argv)
+ try:
+ capture_id = _validated_capture_id(args.capture_id)
+ token = os.getenv(TOKEN_ENVIRONMENT_VARIABLE, "")
+ payload = load_or_create_capture_payload(capture_id)
+ proof = send_capture_payload(payload.body, token)
+ except (RemoteCaptureError, ValueError) as exc:
+ print(f"GlassBox capture failed: {exc}", file=sys.stderr)
+ return 1
+ print(render_capture_proof(capture_id, payload, proof))
+ return 0
+
+
+def _validated_capture_id(value: str) -> str:
+ if not _CAPTURE_ID.fullmatch(value):
+ raise ValueError("capture ID must be 1-48 lowercase letters, digits, or interior hyphens")
+ return value
+
+
+def _derived_hex(namespace: str, capture_id: str, *, length: int) -> str:
+ material = f"glassbox.devpost.capture.v1:{namespace}:{capture_id}".encode()
+ return hashlib.sha256(material).hexdigest()[:length]
+
+
+def _otlp_span(span: OTelSpanRecord) -> dict[str, Any]:
+ return {
+ "traceId": base64.b64encode(bytes.fromhex(span.trace_id)).decode(),
+ "spanId": base64.b64encode(bytes.fromhex(span.span_id)).decode(),
+ **(
+ {"parentSpanId": base64.b64encode(bytes.fromhex(span.parent_span_id)).decode()}
+ if span.parent_span_id
+ else {}
+ ),
+ "name": span.name,
+ "kind": "SPAN_KIND_INTERNAL",
+ "startTimeUnixNano": str(_timestamp_nanos(span.start_time)),
+ "endTimeUnixNano": str(_timestamp_nanos(span.end_time)),
+ "attributes": _attributes(span.attributes),
+ "events": [
+ {
+ "name": event.name,
+ "timeUnixNano": str(_timestamp_nanos(event.occurred_at)),
+ "attributes": _attributes(event.attributes),
+ }
+ for event in span.events
+ ],
+ "status": {
+ "code": (
+ "STATUS_CODE_ERROR" if span.status is OTelSpanStatus.ERROR else "STATUS_CODE_UNSET"
+ )
+ },
+ }
+
+
+def _attributes(attributes: Mapping[str, object]) -> list[dict[str, Any]]:
+ return [{"key": key, "value": _any_value(value)} for key, value in sorted(attributes.items())]
+
+
+def _any_value(value: object) -> dict[str, object]:
+ if isinstance(value, bool):
+ return {"boolValue": value}
+ if isinstance(value, int):
+ return {"intValue": str(value)}
+ if isinstance(value, float):
+ return {"doubleValue": value}
+ if not isinstance(value, str):
+ raise ValueError("capture span attribute is not an OTLP scalar")
+ return {"stringValue": value}
+
+
+def _timestamp_nanos(value: str) -> int:
+ parsed = datetime.fromisoformat(value.replace("Z", "+00:00"))
+ if parsed.tzinfo is None or parsed.utcoffset() is None:
+ raise ValueError("OTLP timestamp must be timezone-aware")
+ utc = parsed.astimezone(UTC)
+ return int(utc.timestamp()) * 1_000_000_000 + utc.microsecond * 1_000
+
+
+def _validate_stored_payload(body: bytes) -> None:
+ if not body or len(body) > MAX_STORED_PAYLOAD_BYTES:
+ raise RemoteCaptureError("stored OTLP payload is empty or exceeds the receiver limit")
+ try:
+ payload = json.loads(body)
+ except (UnicodeDecodeError, json.JSONDecodeError) as exc:
+ raise RemoteCaptureError("stored OTLP payload is not valid JSON") from exc
+ if not isinstance(payload, dict) or set(payload) != {"resourceSpans"}:
+ raise RemoteCaptureError("stored OTLP payload is not the fixed capture envelope")
+
+
+def _parse_response(status: int, body: bytes) -> CaptureProof:
+ try:
+ response = json.loads(body)
+ except (UnicodeDecodeError, json.JSONDecodeError) as exc:
+ raise RemoteCaptureError(f"hosted receiver returned invalid JSON (HTTP {status})") from exc
+ if not isinstance(response, dict):
+ raise RemoteCaptureError(f"hosted receiver returned an invalid envelope (HTTP {status})")
+ code = response.get("code")
+ safe_code = code if isinstance(code, str) and code else "UnknownResponse"
+ if status != 200:
+ raise RemoteCaptureError(
+ f"hosted receiver rejected the trace (HTTP {status} Β· {safe_code})"
+ )
+ if response.get("valid") is not True or safe_code != "ReceiptPublished":
+ raise RemoteCaptureError("hosted receiver did not return a valid publication proof")
+ if response.get("raw_content_returned") is not False:
+ raise RemoteCaptureError("hosted receiver did not confirm the raw-free response boundary")
+
+ detail = _mapping(response, "detail")
+ state = _mapping(detail, "state")
+ datahub = _mapping(detail, "datahub")
+ publication = _mapping(detail, "publication")
+ receipt_id = _string(detail, "receipt_id")
+ registration = _string(state, "registration")
+ if registration not in {"INSERTED", "REUSED"}:
+ raise RemoteCaptureError("hosted receiver returned an unknown registration state")
+ if state.get("readback_verified") is not True or datahub.get("valid") is not True:
+ raise RemoteCaptureError("hosted receiver did not prove state and DataHub readback")
+ document_urn = _string(datahub, "document_urn")
+ aspects = datahub.get("aspect_names")
+ if (
+ not isinstance(aspects, list)
+ or not aspects
+ or not all(isinstance(item, str) and item for item in aspects)
+ ):
+ raise RemoteCaptureError("hosted receiver returned invalid DataHub aspect evidence")
+ attempt_count = publication.get("attempt_count")
+ write_performed = publication.get("datahub_write_performed")
+ if not isinstance(attempt_count, int) or attempt_count < 1:
+ raise RemoteCaptureError("hosted receiver returned an invalid publication attempt count")
+ if not isinstance(write_performed, bool):
+ raise RemoteCaptureError("hosted receiver returned an invalid publication write state")
+ return CaptureProof(
+ status=status,
+ code=safe_code,
+ receipt_id=receipt_id,
+ registration=registration,
+ state_readback_verified=True,
+ document_urn=document_urn,
+ aspect_names=tuple(aspects),
+ publication_attempt_count=attempt_count,
+ datahub_write_performed=write_performed,
+ )
+
+
+def _mapping(source: Mapping[str, object], key: str) -> Mapping[str, object]:
+ value = source.get(key)
+ if not isinstance(value, Mapping):
+ raise RemoteCaptureError(f"hosted receiver omitted {key} proof")
+ return value
+
+
+def _string(source: Mapping[str, object], key: str) -> str:
+ value = source.get(key)
+ if not isinstance(value, str) or not value:
+ raise RemoteCaptureError(f"hosted receiver omitted {key} proof")
+ return value
+
+
+if __name__ == "__main__":
+ raise SystemExit(main())
diff --git a/services/compiler/src/glassbox_compiler/receiver.py b/services/compiler/src/glassbox_compiler/receiver.py
index c636fac..256fa70 100644
--- a/services/compiler/src/glassbox_compiler/receiver.py
+++ b/services/compiler/src/glassbox_compiler/receiver.py
@@ -8,6 +8,7 @@
import json
import os
import sys
+import time
from collections.abc import Callable, Mapping, Sequence
from dataclasses import dataclass, field, replace
from http import HTTPStatus
@@ -43,6 +44,7 @@ class OTLPReceiverConfig:
"""Transport limits and authentication for one receiver instance."""
bearer_token: str | None = field(default=None, repr=False)
+ bearer_token_validator: Callable[[str], bool] | None = field(default=None, repr=False)
max_body_bytes: int = 4 * 1024 * 1024
max_spans: int = 10_000
request_timeout_seconds: float = 30.0
@@ -209,12 +211,17 @@ def log_message(self, message_format: str, *args: object) -> None:
def _authorized(self) -> bool:
token = selected_config.bearer_token
- if token is None:
+ validator = selected_config.bearer_token_validator
+ if token is None and validator is None:
return True
authorization = self.headers.get("Authorization")
- return authorization is not None and hmac.compare_digest(
- authorization.encode(), f"Bearer {token}".encode()
+ if authorization is None or not authorization.startswith("Bearer "):
+ return False
+ presented = authorization.removeprefix("Bearer ")
+ static_match = token is not None and hmac.compare_digest(
+ presented.encode(), token.encode()
)
+ return static_match or (validator is not None and validator(presented))
def _respond(
self,
@@ -260,6 +267,12 @@ def _parser() -> argparse.ArgumentParser:
serve.add_argument("--request-timeout-seconds", type=float, default=30.0)
serve.add_argument("--run-span-id")
serve.add_argument("--signing-key-env", default="GLASSBOX_RECEIPT_SIGNING_KEY")
+ serve.add_argument(
+ "--startup-retry-seconds",
+ type=float,
+ default=0.0,
+ help="retry live dependency initialization instead of exiting (zero disables)",
+ )
serve.add_argument("--signing-key-id", required=True)
serve.add_argument("--environment", choices=[item.value for item in Environment], required=True)
serve.add_argument("--output-kind", required=True)
@@ -286,6 +299,15 @@ def _add_live_options(parser: argparse.ArgumentParser) -> None:
parser.add_argument("--datahub-server", default="http://localhost:8080")
parser.add_argument("--datahub-token-env", default="DATAHUB_GMS_TOKEN")
parser.add_argument("--allow-remote-datahub", action="store_true")
+ parser.add_argument(
+ "--control-database",
+ type=Path,
+ default=None,
+ help="control database containing the saved DataHub connection",
+ )
+ parser.add_argument("--control-master-key-env", default="GLASSBOX_CONTROL_MASTER_KEY")
+ parser.add_argument("--control-master-key-id", default="control-v1")
+ parser.add_argument("--control-organization", default="default")
parser.add_argument("--worker-id")
parser.add_argument("--lease-duration-ms", type=int, default=60_000)
parser.add_argument(
@@ -338,8 +360,17 @@ def _live_components(
connect_timeout_seconds=args.state_connect_timeout_seconds,
signer_trust_policy=trust_policy,
).connect()
- server = validate_probe_target(args.datahub_server, allow_remote=args.allow_remote_datahub)
- backend = DataHubReceiptBackend(server=server, token=_optional_secret(args.datahub_token_env))
+ control_connection = _control_connection(args)
+ server = validate_probe_target(
+ control_connection.server_url if control_connection is not None else args.datahub_server,
+ allow_remote=(True if control_connection is not None else args.allow_remote_datahub),
+ )
+ token = (
+ control_connection.token
+ if control_connection is not None
+ else _optional_secret(args.datahub_token_env)
+ )
+ backend = DataHubReceiptBackend(server=server, token=token)
backend.test_connection()
return (
state,
@@ -350,7 +381,7 @@ def _live_components(
def _run(args: argparse.Namespace) -> int:
- state, emitter, backend, trust_policy = _live_components(args)
+ state, emitter, backend, trust_policy = _startup_live_components(args)
if args.command == "drain":
worker = ReceiptPublicationWorker(
state,
@@ -376,9 +407,11 @@ def _run(args: argparse.Namespace) -> int:
return 0 if not failures else 1
bearer_token = _optional_secret(args.bearer_token_env)
+ bearer_token_validator = _control_ingestion_key_validator(args)
if (
not _loopback_bind(args.bind)
and bearer_token is None
+ and bearer_token_validator is None
and not (args.allow_unauthenticated_remote)
):
raise ValueError(
@@ -406,6 +439,7 @@ def _run(args: argparse.Namespace) -> int:
)
config = OTLPReceiverConfig(
bearer_token=bearer_token,
+ bearer_token_validator=bearer_token_validator,
max_body_bytes=args.max_body_bytes,
max_spans=args.max_spans,
request_timeout_seconds=args.request_timeout_seconds,
@@ -430,6 +464,83 @@ def _run(args: argparse.Namespace) -> int:
return 0
+def _startup_live_components(
+ args: argparse.Namespace,
+) -> tuple[Any, ReceiptEmitter, DataHubReceiptBackend, SignerTrustPolicy]:
+ """Load live dependencies, optionally waiting through onboarding or outages."""
+
+ retry_seconds = float(getattr(args, "startup_retry_seconds", 0.0))
+ if retry_seconds < 0:
+ raise ValueError("startup retry interval cannot be negative")
+ attempt = 0
+ previous_error_type: str | None = None
+ while True:
+ try:
+ return _live_components(args)
+ except Exception as exc:
+ if args.command != "serve" or retry_seconds == 0:
+ raise
+ attempt += 1
+ error_type = type(exc).__name__
+ if attempt == 1 or error_type != previous_error_type or attempt % 12 == 0:
+ print(
+ json.dumps(
+ {
+ "valid": False,
+ "state": "WAITING_FOR_LIVE_DEPENDENCIES",
+ "error_type": error_type,
+ "retry_seconds": retry_seconds,
+ "raw_content_returned": False,
+ },
+ sort_keys=True,
+ ),
+ file=sys.stderr,
+ )
+ previous_error_type = error_type
+ time.sleep(retry_seconds)
+
+
+def _control_store(args: argparse.Namespace) -> Any | None:
+ database = getattr(args, "control_database", None)
+ if database is None:
+ return None
+ from glassbox_control import ControlStore, SecretBox
+
+ secret_box = SecretBox.from_base64url(
+ _required_secret(args.control_master_key_env, "control master key"),
+ key_id=args.control_master_key_id,
+ )
+ return ControlStore(
+ database,
+ secret_box,
+ organization=args.control_organization,
+ )
+
+
+def _control_connection(args: argparse.Namespace) -> Any | None:
+ store = _control_store(args)
+ if store is None:
+ return None
+ connection = store.load_datahub_connection()
+ if connection is None:
+ raise ValueError("control database does not contain a verified DataHub connection")
+ return connection
+
+
+def _control_ingestion_key_validator(args: argparse.Namespace) -> Callable[[str], bool] | None:
+ store = _control_store(args)
+ if store is None:
+ return None
+
+ def validate(clear: str) -> bool:
+ try:
+ return bool(store.authorize_ingestion_key(clear))
+ except Exception:
+ return False
+
+ return validate
+
+
def main(argv: Sequence[str] | None = None) -> int:
args = _parser().parse_args(argv)
try:
diff --git a/services/control-plane/src/glassbox_control/__init__.py b/services/control-plane/src/glassbox_control/__init__.py
new file mode 100644
index 0000000..2a9a5dd
--- /dev/null
+++ b/services/control-plane/src/glassbox_control/__init__.py
@@ -0,0 +1,6 @@
+"""Authenticated deployment control plane for GlassBox."""
+
+from glassbox_control.crypto import EncryptedSecret, SecretBox
+from glassbox_control.store import ControlStore, DataHubConnection
+
+__all__ = ["ControlStore", "DataHubConnection", "EncryptedSecret", "SecretBox"]
diff --git a/services/control-plane/src/glassbox_control/crypto.py b/services/control-plane/src/glassbox_control/crypto.py
new file mode 100644
index 0000000..302cbad
--- /dev/null
+++ b/services/control-plane/src/glassbox_control/crypto.py
@@ -0,0 +1,93 @@
+"""Small, versioned cryptographic boundary for deployment credentials."""
+
+from __future__ import annotations
+
+import base64
+import hashlib
+import hmac
+import os
+from dataclasses import dataclass
+
+from cryptography.hazmat.primitives.ciphers.aead import AESGCM
+
+_NONCE_BYTES = 12
+_MASTER_KEY_BYTES = 32
+_INGESTION_PREFIX = "gbx_ingest_"
+
+
+@dataclass(frozen=True)
+class EncryptedSecret:
+ """One AES-GCM ciphertext plus its non-secret key selector."""
+
+ nonce: bytes
+ ciphertext: bytes
+ key_id: str
+
+
+class SecretBox:
+ """Encrypt control secrets and derive one-way ingestion-key digests."""
+
+ def __init__(self, key: bytes, *, key_id: str = "control-v1") -> None:
+ if len(key) != _MASTER_KEY_BYTES:
+ raise ValueError("control master key must contain exactly 32 bytes")
+ if not key_id or len(key_id) > 64:
+ raise ValueError("control master key ID must contain 1 to 64 characters")
+ self._key = bytes(key)
+ self.key_id = key_id
+ self._aead = AESGCM(self._key)
+
+ @classmethod
+ def from_base64url(cls, encoded: str, *, key_id: str = "control-v1") -> SecretBox:
+ """Load an unpadded base64url-encoded 32-byte key."""
+
+ if not encoded:
+ raise ValueError("control master key is unset")
+ try:
+ padded = encoded + "=" * (-len(encoded) % 4)
+ key = base64.urlsafe_b64decode(padded.encode("ascii"))
+ except (UnicodeEncodeError, ValueError) as exc:
+ raise ValueError("control master key is not valid base64url") from exc
+ return cls(key, key_id=key_id)
+
+ @staticmethod
+ def generate_base64url() -> str:
+ """Generate a new deployment key for delivery to a secret manager."""
+
+ return base64.urlsafe_b64encode(os.urandom(_MASTER_KEY_BYTES)).rstrip(b"=").decode()
+
+ def encrypt(self, value: str, *, aad: bytes) -> EncryptedSecret:
+ if not value:
+ raise ValueError("secret value must be non-empty")
+ nonce = os.urandom(_NONCE_BYTES)
+ ciphertext = self._aead.encrypt(nonce, value.encode("utf-8"), aad)
+ return EncryptedSecret(nonce=nonce, ciphertext=ciphertext, key_id=self.key_id)
+
+ def decrypt(self, encrypted: EncryptedSecret, *, aad: bytes) -> str:
+ if encrypted.key_id != self.key_id:
+ raise ValueError("encrypted secret references an unavailable key ID")
+ return self._aead.decrypt(encrypted.nonce, encrypted.ciphertext, aad).decode("utf-8")
+
+ def issue_ingestion_key(self) -> tuple[str, str, str]:
+ """Return the clear key once, its display prefix, and its stored digest."""
+
+ clear = _INGESTION_PREFIX + base64.urlsafe_b64encode(os.urandom(32)).rstrip(b"=").decode()
+ return clear, clear[:20], self.ingestion_key_digest(clear)
+
+ def ingestion_key_digest(self, clear: str) -> str:
+ if not clear.startswith(_INGESTION_PREFIX) or len(clear) < 40:
+ return ""
+ return hmac.new(
+ self._key,
+ b"glassbox.ingestion-key.v1\0" + clear.encode("utf-8"),
+ hashlib.sha256,
+ ).hexdigest()
+
+ def ingestion_key_matches(self, clear: str, expected_digest: str) -> bool:
+ actual = self.ingestion_key_digest(clear)
+ return bool(actual) and hmac.compare_digest(actual, expected_digest)
+
+
+def datahub_secret_aad(*, organization: str, connection_id: str) -> bytes:
+ """Bind ciphertext to its exact deployment record and format."""
+
+ return f"glassbox.datahub-token.v1\0{organization}\0{connection_id}".encode()
diff --git a/services/control-plane/src/glassbox_control/datahub.py b/services/control-plane/src/glassbox_control/datahub.py
new file mode 100644
index 0000000..6d80427
--- /dev/null
+++ b/services/control-plane/src/glassbox_control/datahub.py
@@ -0,0 +1,148 @@
+"""Real, bounded DataHub connection and permission verification."""
+
+from __future__ import annotations
+
+from importlib import metadata
+from typing import Any
+from urllib.parse import urlparse
+
+from glassbox_datahub.capability_probe import PINNED_DATAHUB_SDK_VERSION
+
+_PROBE_DOCUMENT_ID = "glassbox.connection.probe"
+
+
+class DataHubConnectionTestError(RuntimeError):
+ """Bounded test failure that never carries a remote response or credential."""
+
+ def __init__(self, stage: str, failure_type: str) -> None:
+ super().__init__(f"{stage}: {failure_type}")
+ self.stage = stage
+ self.failure_type = failure_type
+
+
+class DataHubPublicationReadbackVerifier: # pragma: no cover - live SDK boundary
+ """Freshly prove that a deterministic receipt Document still exists in DataHub."""
+
+ def verify(self, *, server_url: str, token: str, receipt_id: str) -> dict[str, Any]:
+ from glassbox_datahub import DataHubReceiptBackend, receipt_document_urn
+
+ document_urn = receipt_document_urn(receipt_id)
+ try:
+ backend = DataHubReceiptBackend(server=server_url, token=token)
+ backend.test_connection()
+ aspect_names = tuple(sorted(set(backend.direct_read_aspects(document_urn))))
+ except Exception as exc:
+ raise DataHubConnectionTestError(
+ "PUBLICATION_READBACK",
+ type(exc).__name__,
+ ) from exc
+ if not aspect_names:
+ raise DataHubConnectionTestError("PUBLICATION_READBACK", "DocumentNotFound")
+ return {
+ "contract_version": "glassbox.publication-readback.v1",
+ "receipt_id": receipt_id,
+ "document_urn": document_urn,
+ "verification_state": "VERIFIED_NOW",
+ "aspect_names": list(aspect_names),
+ "aspect_count": len(aspect_names),
+ "raw_content_returned": False,
+ }
+
+
+def normalize_datahub_url(value: str, *, label: str) -> str:
+ selected = value.strip().rstrip("/")
+ parsed = urlparse(selected)
+ if (
+ parsed.scheme not in {"http", "https"}
+ or not parsed.hostname
+ or parsed.username is not None
+ or parsed.password is not None
+ or parsed.query
+ or parsed.fragment
+ or parsed.path not in {"", "/"}
+ ):
+ raise ValueError(f"{label} must be an HTTP(S) origin without credentials or a path")
+ return selected
+
+
+class DataHubConnectionTester: # pragma: no cover - live SDK boundary
+ """Prove reachability and optionally prove write/readback permission."""
+
+ def test(self, *, server_url: str, token: str, write_proof: bool) -> dict[str, Any]:
+ from datahub.ingestion.graph.client import DataHubGraph
+ from datahub.ingestion.graph.config import DatahubClientConfig
+
+ if not token:
+ raise ValueError("DataHub service-account token is required")
+ server_url = normalize_datahub_url(server_url, label="DataHub GMS URL")
+ sdk_version = metadata.version("acryl-datahub")
+ if sdk_version != PINNED_DATAHUB_SDK_VERSION:
+ raise DataHubConnectionTestError("SDK_COMPATIBILITY", "SdkVersionMismatch")
+ graph = DataHubGraph(config=DatahubClientConfig(server=server_url, token=token))
+ try:
+ graph.test_connection()
+ config = graph.get_config()
+ except Exception as exc:
+ raise DataHubConnectionTestError("CONNECTION", type(exc).__name__) from exc
+
+ report: dict[str, Any] = {
+ "contract_version": "glassbox.datahub-connection.v1",
+ "connection": "PROVEN",
+ "authentication": "PROVEN",
+ "sdk_compatibility": "PROVEN",
+ "sdk_version": sdk_version,
+ "server_version": _server_version(config),
+ "write_proof": "UNVERIFIED",
+ "probe_document_urn": None,
+ "raw_content_returned": False,
+ }
+ if not write_proof:
+ return report
+
+ try:
+ from datahub.sdk.document import Document
+ from datahub.sdk.main_client import DataHubClient
+
+ client = DataHubClient(graph=graph)
+ document = Document.create_document(
+ id=_PROBE_DOCUMENT_ID,
+ title="GlassBox connection permission proof",
+ text=(
+ "Synthetic, idempotent control-plane probe. Contains no credential, "
+ "customer record, prompt, model output, or agent payload."
+ ),
+ subtype="GlassBox Connection Probe",
+ show_in_global_context=False,
+ custom_properties={
+ "glassbox.probe_contract": "glassbox.datahub-connection.v1",
+ "glassbox.synthetic": "true",
+ },
+ )
+ client.entities.upsert(document)
+ urn = str(document.urn)
+ raw = graph.get_entity_raw(urn)
+ aspects = raw.get("aspects") if isinstance(raw, dict) else None
+ if not isinstance(aspects, dict) or not any(
+ value is not None for value in aspects.values()
+ ):
+ raise RuntimeError("direct readback returned no persisted aspects")
+ except Exception as exc:
+ raise DataHubConnectionTestError("WRITE_READBACK", type(exc).__name__) from exc
+ report["write_proof"] = "PROVEN"
+ report["probe_document_urn"] = urn
+ return report
+
+
+def _server_version(config: Any) -> str | None:
+ if not isinstance(config, dict):
+ return None
+ candidates = (
+ config.get("datahub", {}).get("version")
+ if isinstance(config.get("datahub"), dict)
+ else None,
+ config.get("versions", {}).get("acryldata/datahub")
+ if isinstance(config.get("versions"), dict)
+ else None,
+ config.get("version"),
+ )
+ return next((value for value in candidates if isinstance(value, str) and value), None)
diff --git a/services/control-plane/src/glassbox_control/server.py b/services/control-plane/src/glassbox_control/server.py
new file mode 100644
index 0000000..90e13e8
--- /dev/null
+++ b/services/control-plane/src/glassbox_control/server.py
@@ -0,0 +1,425 @@
+"""Authenticated GlassBox control-plane HTTP service and bootstrap CLI."""
+
+from __future__ import annotations
+
+import argparse
+import hmac
+import json
+import os
+import sys
+from collections.abc import Mapping, Sequence
+from pathlib import Path
+from typing import Any, Protocol
+
+from glassbox_control.crypto import SecretBox
+from glassbox_control.datahub import (
+ DataHubConnectionTester,
+ DataHubConnectionTestError,
+ DataHubPublicationReadbackVerifier,
+ normalize_datahub_url,
+)
+from glassbox_control.store import ControlStore, ControlStoreError
+
+_MAX_REQUEST_BYTES = 32 * 1024
+_ROLES = {"viewer": 1, "operator": 2, "admin": 3}
+
+
+class ConnectionTester(Protocol):
+ def test(self, *, server_url: str, token: str, write_proof: bool) -> dict[str, Any]: ...
+
+
+class PublicationReadbackVerifier(Protocol):
+ def verify(self, *, server_url: str, token: str, receipt_id: str) -> dict[str, Any]: ...
+
+
+def build_app(
+ store: ControlStore,
+ *,
+ internal_token: str,
+ tester: ConnectionTester | None = None,
+ publication_readback: PublicationReadbackVerifier | None = None,
+) -> Any:
+ """Build the private API. Identity headers are trusted only with service auth."""
+
+ try:
+ from starlette.applications import Starlette
+ from starlette.requests import Request
+ from starlette.responses import JSONResponse
+ from starlette.routing import Route
+ except ImportError as exc: # pragma: no cover - optional dependency boundary
+ raise RuntimeError("glassbox-control requires the control optional dependencies") from exc
+
+ if len(internal_token) < 32:
+ raise ValueError("control API token must contain at least 32 characters")
+ selected_tester = tester or DataHubConnectionTester()
+ selected_publication_readback = publication_readback or DataHubPublicationReadbackVerifier()
+
+ def response(payload: Mapping[str, Any], status_code: int = 200) -> Any:
+ return JSONResponse(
+ dict(payload),
+ status_code=status_code,
+ headers={
+ "Cache-Control": "no-store",
+ "X-Content-Type-Options": "nosniff",
+ "Referrer-Policy": "no-referrer",
+ },
+ )
+
+ def error(code: str, message: str, status_code: int) -> Any:
+ return response(
+ {
+ "contract_version": "glassbox.control-api.v1",
+ "error": {"code": code, "message": message},
+ "raw_content_returned": False,
+ },
+ status_code,
+ )
+
+ def principal(request: Any, required_role: str) -> tuple[str, str] | Any:
+ authorization = request.headers.get("authorization")
+ expected = f"Bearer {internal_token}"
+ if authorization is None or not hmac.compare_digest(
+ authorization.encode(), expected.encode()
+ ):
+ return error("UNAUTHENTICATED", "Service authentication failed.", 401)
+ subject = request.headers.get("x-glassbox-subject", "").strip()
+ role = request.headers.get("x-glassbox-role", "").strip().lower()
+ if not subject or role not in _ROLES:
+ return error("INVALID_IDENTITY", "Operator identity is incomplete.", 403)
+ if _ROLES[role] < _ROLES[required_role]:
+ return error("FORBIDDEN", "This operation requires a higher role.", 403)
+ return subject[:254], role
+
+ async def body(request: Any) -> dict[str, Any]:
+ raw_length = request.headers.get("content-length")
+ if raw_length is not None:
+ try:
+ if int(raw_length) > _MAX_REQUEST_BYTES:
+ raise ValueError("request body exceeds 32 KiB")
+ except ValueError as exc:
+ raise ValueError("request body length is invalid") from exc
+ raw = await request.body()
+ if len(raw) > _MAX_REQUEST_BYTES:
+ raise ValueError("request body exceeds 32 KiB")
+ try:
+ value = json.loads(raw)
+ except (UnicodeDecodeError, json.JSONDecodeError) as exc:
+ raise ValueError("request body must be a JSON object") from exc
+ if not isinstance(value, dict):
+ raise ValueError("request body must be a JSON object")
+ return value
+
+ async def health(_: Request) -> Any:
+ return response(
+ {
+ "status": "ok",
+ "service": "glassbox-control",
+ "contract_version": "glassbox.control-api.v1",
+ }
+ )
+
+ async def get_connection(request: Request) -> Any:
+ selected = principal(request, "viewer")
+ if not isinstance(selected, tuple):
+ return selected
+ connection = store.connection_summary()
+ return response(
+ {
+ "contract_version": "glassbox.control-api.v1",
+ "configured": connection is not None,
+ "connection": connection,
+ "raw_content_returned": False,
+ }
+ )
+
+ async def verify_publication_readback(request: Request) -> Any:
+ selected = principal(request, "viewer")
+ if not isinstance(selected, tuple):
+ return selected
+ receipt_id = request.path_params["receipt_id"]
+ try:
+ _require_receipt_id(receipt_id)
+ connection = store.load_datahub_connection()
+ if connection is None:
+ return error(
+ "DATAHUB_NOT_CONFIGURED",
+ "A verified DataHub connection is required.",
+ 409,
+ )
+ report = selected_publication_readback.verify(
+ server_url=connection.server_url,
+ token=connection.token,
+ receipt_id=receipt_id,
+ )
+ except DataHubConnectionTestError as exc:
+ return error(
+ "DATAHUB_READBACK_FAILED",
+ f"DataHub verification failed at {exc.stage} ({exc.failure_type}).",
+ 502,
+ )
+ except ControlStoreError:
+ return error("CONTROL_STATE_UNAVAILABLE", "Control state is unavailable.", 503)
+ except ValueError as exc:
+ return error("INVALID_ARGUMENT", str(exc), 400)
+ return response(report)
+
+ async def test_connection(request: Request) -> Any:
+ selected = principal(request, "admin")
+ if not isinstance(selected, tuple):
+ return selected
+ try:
+ payload = await body(request)
+ server_url, _, token, write_proof = _connection_input(payload)
+ report = selected_tester.test(
+ server_url=server_url,
+ token=token,
+ write_proof=write_proof,
+ )
+ except DataHubConnectionTestError as exc:
+ return error(
+ "DATAHUB_TEST_FAILED",
+ f"DataHub verification failed at {exc.stage} ({exc.failure_type}).",
+ 422,
+ )
+ except ValueError as exc:
+ return error("INVALID_ARGUMENT", str(exc), 400)
+ return response(
+ {
+ "contract_version": "glassbox.control-api.v1",
+ "report": report,
+ "persisted": False,
+ "raw_content_returned": False,
+ }
+ )
+
+ async def save_connection(request: Request) -> Any:
+ selected = principal(request, "admin")
+ if not isinstance(selected, tuple):
+ return selected
+ subject, _ = selected
+ try:
+ payload = await body(request)
+ server_url, ui_url, token, write_proof = _connection_input(payload)
+ if not write_proof:
+ raise ValueError("saving requires the DataHub write/readback proof")
+ report = selected_tester.test(
+ server_url=server_url,
+ token=token,
+ write_proof=True,
+ )
+ if report.get("write_proof") != "PROVEN":
+ raise DataHubConnectionTestError("WRITE_READBACK", "ProofNotEstablished")
+ summary = store.save_datahub_connection(
+ server_url=server_url,
+ ui_url=ui_url,
+ token=token,
+ probe=report,
+ actor=subject,
+ )
+ except DataHubConnectionTestError as exc:
+ return error(
+ "DATAHUB_TEST_FAILED",
+ f"DataHub verification failed at {exc.stage} ({exc.failure_type}).",
+ 422,
+ )
+ except ValueError as exc:
+ return error("INVALID_ARGUMENT", str(exc), 400)
+ except ControlStoreError:
+ return error("CONTROL_STATE_UNAVAILABLE", "Control state is unavailable.", 503)
+ return response(
+ {
+ "contract_version": "glassbox.control-api.v1",
+ "configured": True,
+ "connection": summary,
+ "raw_content_returned": False,
+ }
+ )
+
+ async def list_keys(request: Request) -> Any:
+ selected = principal(request, "admin")
+ if not isinstance(selected, tuple):
+ return selected
+ return response(
+ {
+ "contract_version": "glassbox.control-api.v1",
+ "keys": store.list_ingestion_keys(),
+ "raw_content_returned": False,
+ }
+ )
+
+ async def create_key(request: Request) -> Any:
+ selected = principal(request, "admin")
+ if not isinstance(selected, tuple):
+ return selected
+ subject, _ = selected
+ try:
+ payload = await body(request)
+ name = payload.get("name")
+ if not isinstance(name, str):
+ raise ValueError("ingestion key name is required")
+ summary, clear = store.create_ingestion_key(name=name, actor=subject)
+ except ValueError as exc:
+ return error("INVALID_ARGUMENT", str(exc), 400)
+ return response(
+ {
+ "contract_version": "glassbox.control-api.v1",
+ "key": summary,
+ "secret": clear,
+ "secret_display": "RETURNED_ONCE",
+ "raw_content_returned": False,
+ },
+ 201,
+ )
+
+ async def revoke_key(request: Request) -> Any:
+ selected = principal(request, "admin")
+ if not isinstance(selected, tuple):
+ return selected
+ subject, _ = selected
+ key_id = request.path_params["key_id"]
+ if not key_id.startswith("ik_") or len(key_id) != 35:
+ return error("INVALID_ARGUMENT", "ingestion key ID is invalid", 400)
+ if not store.revoke_ingestion_key(key_id, actor=subject):
+ return error("NOT_FOUND", "Active ingestion key was not found.", 404)
+ return response(
+ {
+ "contract_version": "glassbox.control-api.v1",
+ "key_id": key_id,
+ "state": "REVOKED",
+ "raw_content_returned": False,
+ }
+ )
+
+ return Starlette(
+ debug=False,
+ routes=[
+ Route("/health", health, methods=["GET"]),
+ Route("/api/v1/connection", get_connection, methods=["GET"]),
+ Route(
+ "/api/v1/publications/{receipt_id}/readback",
+ verify_publication_readback,
+ methods=["GET"],
+ ),
+ Route("/api/v1/connection/test", test_connection, methods=["POST"]),
+ Route("/api/v1/connection", save_connection, methods=["PUT"]),
+ Route("/api/v1/ingestion-keys", list_keys, methods=["GET"]),
+ Route("/api/v1/ingestion-keys", create_key, methods=["POST"]),
+ Route("/api/v1/ingestion-keys/{key_id}", revoke_key, methods=["DELETE"]),
+ ],
+ )
+
+
+def _connection_input(payload: Mapping[str, Any]) -> tuple[str, str | None, str, bool]:
+ raw_server = payload.get("server_url")
+ raw_ui = payload.get("ui_url")
+ token = payload.get("token")
+ write_proof = payload.get("write_proof", False)
+ if not isinstance(raw_server, str):
+ raise ValueError("DataHub GMS URL is required")
+ if raw_ui is not None and not isinstance(raw_ui, str):
+ raise ValueError("DataHub UI URL must be a string")
+ if not isinstance(token, str) or not token.strip():
+ raise ValueError("DataHub service-account token is required")
+ if not isinstance(write_proof, bool):
+ raise ValueError("write_proof must be a boolean")
+ server_url = normalize_datahub_url(raw_server, label="DataHub GMS URL")
+ ui_url = normalize_datahub_url(raw_ui, label="DataHub UI URL") if raw_ui else None
+ return server_url, ui_url, token.strip(), write_proof
+
+
+def _require_receipt_id(receipt_id: str) -> None:
+ prefix = "gbx:receipt:sha256:"
+ digest = receipt_id.removeprefix(prefix)
+ if (
+ not receipt_id.startswith(prefix)
+ or len(digest) != 64
+ or any(character not in "0123456789abcdef" for character in digest)
+ ):
+ raise ValueError("receipt_id must be a GlassBox SHA-256 content address")
+
+
+def _parser() -> argparse.ArgumentParser:
+ parser = argparse.ArgumentParser(prog="glassbox-control")
+ commands = parser.add_subparsers(dest="command", required=True)
+ commands.add_parser("master-key", help="Generate a new base64url deployment master key")
+ init = commands.add_parser("init", help="Initialize an empty control database")
+ _store_options(init)
+ init.add_argument(
+ "--if-needed",
+ action="store_true",
+ help="verify an existing compatible database instead of failing",
+ )
+ serve = commands.add_parser("serve", help="Run the private authenticated control API")
+ _store_options(serve)
+ serve.add_argument("--bind", default="127.0.0.1")
+ serve.add_argument("--port", type=int, default=8790)
+ serve.add_argument("--api-token-env", default="GLASSBOX_CONTROL_API_TOKEN")
+ return parser
+
+
+def _store_options(parser: argparse.ArgumentParser) -> None:
+ parser.add_argument(
+ "--database",
+ type=Path,
+ default=Path(os.getenv("GLASSBOX_CONTROL_DB_PATH", ".glassbox/control.sqlite3")),
+ )
+ parser.add_argument("--organization", default=os.getenv("GLASSBOX_ORGANIZATION", "default"))
+ parser.add_argument("--master-key-env", default="GLASSBOX_CONTROL_MASTER_KEY")
+ parser.add_argument(
+ "--master-key-id",
+ default=os.getenv("GLASSBOX_CONTROL_MASTER_KEY_ID", "control-v1"),
+ )
+
+
+def main(argv: Sequence[str] | None = None) -> int:
+ args = _parser().parse_args(argv)
+ if args.command == "master-key":
+ print(SecretBox.generate_base64url())
+ return 0
+ try:
+ encoded_key = os.getenv(args.master_key_env, "")
+ secret_box = SecretBox.from_base64url(encoded_key, key_id=args.master_key_id)
+ initialize = args.command == "init" and not (args.if_needed and args.database.exists())
+ store = ControlStore(
+ args.database,
+ secret_box,
+ organization=args.organization,
+ initialize=initialize,
+ )
+ if args.command == "init":
+ print(
+ json.dumps(
+ {
+ "valid": True,
+ "database": str(args.database),
+ "initialized": initialize,
+ "schema_version": 1,
+ "raw_content_returned": False,
+ },
+ sort_keys=True,
+ )
+ )
+ return 0
+ internal_token = os.getenv(args.api_token_env, "")
+ app = build_app(store, internal_token=internal_token)
+ import uvicorn
+
+ uvicorn.run(app, host=args.bind, port=args.port, access_log=False)
+ return 0
+ except Exception as exc:
+ print(
+ json.dumps(
+ {
+ "valid": False,
+ "error_type": type(exc).__name__,
+ "raw_content_returned": False,
+ },
+ sort_keys=True,
+ ),
+ file=sys.stderr,
+ )
+ return 2
+
+
+if __name__ == "__main__":
+ raise SystemExit(main())
diff --git a/services/control-plane/src/glassbox_control/store.py b/services/control-plane/src/glassbox_control/store.py
new file mode 100644
index 0000000..dd7934f
--- /dev/null
+++ b/services/control-plane/src/glassbox_control/store.py
@@ -0,0 +1,412 @@
+"""Explicitly initialized single-node control state with encrypted secrets."""
+
+from __future__ import annotations
+
+import json
+import sqlite3
+import uuid
+from dataclasses import dataclass
+from datetime import UTC, datetime
+from pathlib import Path
+from typing import Any
+
+from glassbox_control.crypto import EncryptedSecret, SecretBox, datahub_secret_aad
+
+SCHEMA_VERSION = 1
+CONNECTION_ID = "primary"
+
+
+class ControlStoreError(RuntimeError):
+ """Raised when control state is missing, incompatible, or corrupt."""
+
+
+@dataclass(frozen=True)
+class DataHubConnection:
+ """Decrypted server-side DataHub connection. Never serialize this object."""
+
+ server_url: str
+ ui_url: str | None
+ token: str
+ probe: dict[str, Any]
+ verified_at: str
+
+
+_SCHEMA = """
+CREATE TABLE control_metadata (
+ singleton INTEGER PRIMARY KEY CHECK (singleton = 1),
+ schema_version INTEGER NOT NULL
+);
+INSERT INTO control_metadata(singleton, schema_version) VALUES (1, 1);
+
+CREATE TABLE datahub_connections (
+ connection_id TEXT PRIMARY KEY,
+ organization TEXT NOT NULL,
+ server_url TEXT NOT NULL,
+ ui_url TEXT,
+ token_nonce BLOB NOT NULL,
+ token_ciphertext BLOB NOT NULL,
+ token_key_id TEXT NOT NULL,
+ probe_json TEXT NOT NULL,
+ verified_at TEXT NOT NULL,
+ updated_at TEXT NOT NULL,
+ updated_by TEXT NOT NULL
+);
+
+CREATE TABLE ingestion_keys (
+ key_id TEXT PRIMARY KEY,
+ name TEXT NOT NULL,
+ display_prefix TEXT NOT NULL,
+ secret_digest TEXT NOT NULL UNIQUE,
+ created_at TEXT NOT NULL,
+ created_by TEXT NOT NULL,
+ revoked_at TEXT,
+ revoked_by TEXT
+);
+
+CREATE TABLE control_audit_events (
+ event_id TEXT PRIMARY KEY,
+ occurred_at TEXT NOT NULL,
+ actor TEXT NOT NULL,
+ action TEXT NOT NULL,
+ target TEXT NOT NULL,
+ outcome TEXT NOT NULL,
+ detail_json TEXT NOT NULL
+);
+CREATE INDEX control_audit_time_idx
+ ON control_audit_events(occurred_at DESC, event_id DESC);
+"""
+
+
+class ControlStore:
+ """Transactional low-write control state for one self-hosted deployment."""
+
+ def __init__(
+ self,
+ path: Path,
+ secret_box: SecretBox,
+ *,
+ organization: str = "default",
+ initialize: bool = False,
+ ) -> None:
+ if not organization or len(organization) > 128:
+ raise ValueError("organization must contain 1 to 128 characters")
+ self.path = path
+ self._secret_box = secret_box
+ self.organization = organization
+ if initialize:
+ self._initialize()
+ self._verify_schema()
+
+ def _initialize(self) -> None:
+ self.path.parent.mkdir(parents=True, exist_ok=True)
+ if self.path.exists():
+ raise ControlStoreError("control database already exists")
+ connection = sqlite3.connect(self.path)
+ try:
+ connection.executescript(_SCHEMA)
+ connection.commit()
+ finally:
+ connection.close()
+ self.path.chmod(0o600)
+
+ def _connect(self) -> sqlite3.Connection:
+ if not self.path.is_file():
+ raise ControlStoreError("control database is not initialized")
+ connection = sqlite3.connect(self.path, timeout=5.0)
+ connection.row_factory = sqlite3.Row
+ connection.execute("PRAGMA foreign_keys = ON")
+ connection.execute("PRAGMA busy_timeout = 5000")
+ return connection
+
+ def _verify_schema(self) -> None:
+ try:
+ with self._connect() as connection:
+ row = connection.execute(
+ "SELECT schema_version FROM control_metadata WHERE singleton = 1"
+ ).fetchone()
+ except sqlite3.Error as exc:
+ raise ControlStoreError("control database schema is unavailable") from exc
+ if row is None or row["schema_version"] != SCHEMA_VERSION:
+ raise ControlStoreError("control database schema version is unsupported")
+
+ def save_datahub_connection(
+ self,
+ *,
+ server_url: str,
+ ui_url: str | None,
+ token: str,
+ probe: dict[str, Any],
+ actor: str,
+ now: datetime | None = None,
+ ) -> dict[str, Any]:
+ selected_now = _timestamp(now)
+ encrypted = self._secret_box.encrypt(
+ token,
+ aad=datahub_secret_aad(
+ organization=self.organization,
+ connection_id=CONNECTION_ID,
+ ),
+ )
+ probe_json = _bounded_json(probe)
+ with self._connect() as connection:
+ connection.execute("BEGIN IMMEDIATE")
+ connection.execute(
+ """
+ INSERT INTO datahub_connections(
+ connection_id, organization, server_url, ui_url,
+ token_nonce, token_ciphertext, token_key_id, probe_json,
+ verified_at, updated_at, updated_by
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+ ON CONFLICT(connection_id) DO UPDATE SET
+ organization = excluded.organization,
+ server_url = excluded.server_url,
+ ui_url = excluded.ui_url,
+ token_nonce = excluded.token_nonce,
+ token_ciphertext = excluded.token_ciphertext,
+ token_key_id = excluded.token_key_id,
+ probe_json = excluded.probe_json,
+ verified_at = excluded.verified_at,
+ updated_at = excluded.updated_at,
+ updated_by = excluded.updated_by
+ """,
+ (
+ CONNECTION_ID,
+ self.organization,
+ server_url,
+ ui_url,
+ encrypted.nonce,
+ encrypted.ciphertext,
+ encrypted.key_id,
+ probe_json,
+ selected_now,
+ selected_now,
+ actor,
+ ),
+ )
+ self._audit(
+ connection,
+ actor=actor,
+ action="DATAHUB_CONNECTION_SAVED",
+ target=CONNECTION_ID,
+ outcome="SUCCEEDED",
+ detail={"server_origin": server_url, "write_proof": probe.get("write_proof")},
+ occurred_at=selected_now,
+ )
+ connection.commit()
+ summary = self.connection_summary()
+ if summary is None: # pragma: no cover - transaction invariant
+ raise ControlStoreError("saved DataHub connection is unavailable")
+ return summary
+
+ def connection_summary(self) -> dict[str, Any] | None:
+ with self._connect() as connection:
+ row = connection.execute(
+ """
+ SELECT server_url, ui_url, probe_json, verified_at, updated_at, updated_by
+ FROM datahub_connections WHERE connection_id = ? AND organization = ?
+ """,
+ (CONNECTION_ID, self.organization),
+ ).fetchone()
+ if row is None:
+ return None
+ return {
+ "connection_id": CONNECTION_ID,
+ "server_url": row["server_url"],
+ "ui_url": row["ui_url"],
+ "probe": json.loads(row["probe_json"]),
+ "verified_at": row["verified_at"],
+ "updated_at": row["updated_at"],
+ "updated_by": row["updated_by"],
+ "credential_state": "ENCRYPTED",
+ }
+
+ def load_datahub_connection(self) -> DataHubConnection | None:
+ with self._connect() as connection:
+ row = connection.execute(
+ """
+ SELECT server_url, ui_url, token_nonce, token_ciphertext, token_key_id,
+ probe_json, verified_at
+ FROM datahub_connections WHERE connection_id = ? AND organization = ?
+ """,
+ (CONNECTION_ID, self.organization),
+ ).fetchone()
+ if row is None:
+ return None
+ encrypted = EncryptedSecret(
+ nonce=bytes(row["token_nonce"]),
+ ciphertext=bytes(row["token_ciphertext"]),
+ key_id=row["token_key_id"],
+ )
+ try:
+ token = self._secret_box.decrypt(
+ encrypted,
+ aad=datahub_secret_aad(
+ organization=self.organization,
+ connection_id=CONNECTION_ID,
+ ),
+ )
+ except Exception as exc:
+ raise ControlStoreError("DataHub credential decryption failed") from exc
+ return DataHubConnection(
+ server_url=row["server_url"],
+ ui_url=row["ui_url"],
+ token=token,
+ probe=json.loads(row["probe_json"]),
+ verified_at=row["verified_at"],
+ )
+
+ def create_ingestion_key(
+ self,
+ *,
+ name: str,
+ actor: str,
+ now: datetime | None = None,
+ ) -> tuple[dict[str, Any], str]:
+ selected_name = name.strip()
+ if not 2 <= len(selected_name) <= 80:
+ raise ValueError("ingestion key name must contain 2 to 80 characters")
+ clear, display_prefix, digest = self._secret_box.issue_ingestion_key()
+ key_id = f"ik_{uuid.uuid4().hex}"
+ created_at = _timestamp(now)
+ with self._connect() as connection:
+ connection.execute("BEGIN IMMEDIATE")
+ connection.execute(
+ """
+ INSERT INTO ingestion_keys(
+ key_id, name, display_prefix, secret_digest, created_at, created_by
+ ) VALUES (?, ?, ?, ?, ?, ?)
+ """,
+ (key_id, selected_name, display_prefix, digest, created_at, actor),
+ )
+ self._audit(
+ connection,
+ actor=actor,
+ action="INGESTION_KEY_CREATED",
+ target=key_id,
+ outcome="SUCCEEDED",
+ detail={"name": selected_name},
+ occurred_at=created_at,
+ )
+ connection.commit()
+ return (
+ {
+ "key_id": key_id,
+ "name": selected_name,
+ "display_prefix": display_prefix,
+ "created_at": created_at,
+ "created_by": actor,
+ "state": "ACTIVE",
+ },
+ clear,
+ )
+
+ def list_ingestion_keys(self) -> list[dict[str, Any]]:
+ with self._connect() as connection:
+ rows = connection.execute(
+ """
+ SELECT key_id, name, display_prefix, created_at, created_by,
+ revoked_at, revoked_by
+ FROM ingestion_keys ORDER BY created_at DESC, key_id DESC
+ """
+ ).fetchall()
+ return [
+ {
+ "key_id": row["key_id"],
+ "name": row["name"],
+ "display_prefix": row["display_prefix"],
+ "created_at": row["created_at"],
+ "created_by": row["created_by"],
+ "revoked_at": row["revoked_at"],
+ "revoked_by": row["revoked_by"],
+ "state": "REVOKED" if row["revoked_at"] else "ACTIVE",
+ }
+ for row in rows
+ ]
+
+ def revoke_ingestion_key(
+ self,
+ key_id: str,
+ *,
+ actor: str,
+ now: datetime | None = None,
+ ) -> bool:
+ revoked_at = _timestamp(now)
+ with self._connect() as connection:
+ connection.execute("BEGIN IMMEDIATE")
+ changed = connection.execute(
+ """
+ UPDATE ingestion_keys SET revoked_at = ?, revoked_by = ?
+ WHERE key_id = ? AND revoked_at IS NULL
+ """,
+ (revoked_at, actor, key_id),
+ ).rowcount
+ if changed:
+ self._audit(
+ connection,
+ actor=actor,
+ action="INGESTION_KEY_REVOKED",
+ target=key_id,
+ outcome="SUCCEEDED",
+ detail={},
+ occurred_at=revoked_at,
+ )
+ connection.commit()
+ return bool(changed)
+
+ def authorize_ingestion_key(self, clear: str) -> bool:
+ digest = self._secret_box.ingestion_key_digest(clear)
+ if not digest:
+ return False
+ with self._connect() as connection:
+ row = connection.execute(
+ """
+ SELECT secret_digest FROM ingestion_keys
+ WHERE secret_digest = ? AND revoked_at IS NULL
+ """,
+ (digest,),
+ ).fetchone()
+ return row is not None and self._secret_box.ingestion_key_matches(
+ clear, row["secret_digest"]
+ )
+
+ @staticmethod
+ def _audit(
+ connection: sqlite3.Connection,
+ *,
+ actor: str,
+ action: str,
+ target: str,
+ outcome: str,
+ detail: dict[str, Any],
+ occurred_at: str,
+ ) -> None:
+ connection.execute(
+ """
+ INSERT INTO control_audit_events(
+ event_id, occurred_at, actor, action, target, outcome, detail_json
+ ) VALUES (?, ?, ?, ?, ?, ?, ?)
+ """,
+ (
+ f"evt_{uuid.uuid4().hex}",
+ occurred_at,
+ actor,
+ action,
+ target,
+ outcome,
+ _bounded_json(detail),
+ ),
+ )
+
+
+def _timestamp(value: datetime | None) -> str:
+ selected = value or datetime.now(UTC)
+ if selected.tzinfo is None or selected.utcoffset() is None:
+ raise ValueError("control timestamps must be timezone-aware")
+ return selected.astimezone(UTC).isoformat().replace("+00:00", "Z")
+
+
+def _bounded_json(value: dict[str, Any]) -> str:
+ encoded = json.dumps(value, sort_keys=True, separators=(",", ":"))
+ if len(encoded.encode("utf-8")) > 32 * 1024:
+ raise ValueError("control metadata exceeds 32 KiB")
+ return encoded
diff --git a/services/forensics-mcp/src/glassbox_forensics/__init__.py b/services/forensics-mcp/src/glassbox_forensics/__init__.py
index 25eb822..d4183cd 100644
--- a/services/forensics-mcp/src/glassbox_forensics/__init__.py
+++ b/services/forensics-mcp/src/glassbox_forensics/__init__.py
@@ -21,8 +21,10 @@
ForensicsNotFoundError,
ForensicsService,
PersistedCampaign,
+ PersistedReceiptPublication,
ReceiptArtifactReader,
ReceiptProfileReader,
+ ReceiptPublicationReader,
)
__all__ = [
@@ -39,8 +41,10 @@
"MCPToolContract",
"NarrationContractError",
"PersistedCampaign",
+ "PersistedReceiptPublication",
"ReceiptArtifactReader",
"ReceiptProfileReader",
+ "ReceiptPublicationReader",
"build_narration_brief",
"compose_dual_mcp_evidence",
"evaluate_agent_narration",
diff --git a/services/forensics-mcp/src/glassbox_forensics/live_state.py b/services/forensics-mcp/src/glassbox_forensics/live_state.py
index c1aede7..50f0f67 100644
--- a/services/forensics-mcp/src/glassbox_forensics/live_state.py
+++ b/services/forensics-mcp/src/glassbox_forensics/live_state.py
@@ -2,9 +2,9 @@
from __future__ import annotations
-from glassbox_forensics.service import PersistedCampaign
+from glassbox_forensics.service import PersistedCampaign, PersistedReceiptPublication
from glassbox_invalidation.transactional_protocol import TransactionalInvalidationStore
-from glassbox_invalidation.transactional_store import OutboxTask
+from glassbox_invalidation.transactional_store import OutboxTask, ReceiptPublicationTask
class TransactionalCampaignReader:
@@ -21,6 +21,27 @@ def all_campaigns(self) -> tuple[PersistedCampaign, ...]:
return tuple(_campaign(task) for task in self._store.list_tasks())
+class TransactionalReceiptPublicationReader:
+ """Project sealed publication tasks into the bounded forensics read model."""
+
+ def __init__(
+ self,
+ store: TransactionalInvalidationStore,
+ *,
+ durability_authority: str = "TRANSACTIONAL_STATE",
+ ) -> None:
+ self._store = store
+ self._durability_authority = durability_authority
+
+ def get_publication(self, receipt_id: str) -> PersistedReceiptPublication | None:
+ task = self._store.get_receipt_publication_task(receipt_id)
+ return (
+ _publication(task, durability_authority=self._durability_authority)
+ if task is not None
+ else None
+ )
+
+
def _campaign(task: OutboxTask) -> PersistedCampaign:
return PersistedCampaign(
campaign=task.campaign,
@@ -31,4 +52,22 @@ def _campaign(task: OutboxTask) -> PersistedCampaign:
)
-__all__ = ["TransactionalCampaignReader"]
+def _publication(
+ task: ReceiptPublicationTask,
+ *,
+ durability_authority: str,
+) -> PersistedReceiptPublication:
+ evidence = task.publication_evidence
+ return PersistedReceiptPublication(
+ receipt_id=task.receipt_id,
+ workflow_status=task.status.value,
+ attempt_count=task.attempt_count,
+ last_error_recorded=task.last_error_type is not None,
+ document_urn=evidence.document_urn if evidence is not None else None,
+ aspect_names=evidence.aspect_names if evidence is not None else (),
+ emission_count=evidence.emission_count if evidence is not None else None,
+ durability_authority=durability_authority,
+ )
+
+
+__all__ = ["TransactionalCampaignReader", "TransactionalReceiptPublicationReader"]
diff --git a/services/forensics-mcp/src/glassbox_forensics/server.py b/services/forensics-mcp/src/glassbox_forensics/server.py
index a8b64d7..185362b 100644
--- a/services/forensics-mcp/src/glassbox_forensics/server.py
+++ b/services/forensics-mcp/src/glassbox_forensics/server.py
@@ -3,13 +3,21 @@
from __future__ import annotations
import argparse
+import hmac
import os
from pathlib import Path
from typing import Any
from glassbox_dbom import load_signer_trust_policy
-from glassbox_forensics.live_state import TransactionalCampaignReader
-from glassbox_forensics.service import ForensicsService
+from glassbox_forensics.live_state import (
+ TransactionalCampaignReader,
+ TransactionalReceiptPublicationReader,
+)
+from glassbox_forensics.service import (
+ ForensicsInputError,
+ ForensicsNotFoundError,
+ ForensicsService,
+)
from glassbox_invalidation import VerifiedReceiptStore
from glassbox_policy import ChangeKind, NormalizedChange
@@ -18,7 +26,7 @@ class MCPDependencyError(RuntimeError):
"""Raised when the optional MCP transport dependency is unavailable."""
-def build_server(service: ForensicsService) -> Any:
+def build_server(service: ForensicsService, *, http_bearer_token: str | None = None) -> Any:
"""Create the MCP server without putting policy inside the transport layer."""
try:
@@ -56,6 +64,12 @@ def get_decision_influence(receipt_id: str) -> dict[str, object]:
return service.get_decision_influence(receipt_id)
+ @server.tool(annotations=read_only)
+ def get_decision_publication(receipt_id: str) -> dict[str, object]:
+ """Get sealed durable DataHub-publication evidence for one decision receipt."""
+
+ return service.get_decision_publication(receipt_id)
+
@server.tool(annotations=read_only)
def classify_decision_impact(
receipt_id: str,
@@ -123,6 +137,121 @@ def list_decision_findings(
return service.list_decision_findings(receipt_id, limit=limit)
+ try:
+ from starlette.requests import Request
+ from starlette.responses import JSONResponse
+ except ImportError: # pragma: no cover - MCP installs the HTTP dependency
+ return server
+
+ def unauthorized(request: Request) -> Any | None:
+ if http_bearer_token is None:
+ return None
+ authorization = request.headers.get("authorization")
+ expected = f"Bearer {http_bearer_token}"
+ if authorization is not None and hmac.compare_digest(
+ authorization.encode(), expected.encode()
+ ):
+ return None
+ return _console_error("UNAUTHENTICATED", "Service authentication failed.", status_code=401)
+
+ async def health(request: Request) -> Any:
+ if (rejected := unauthorized(request)) is not None:
+ return rejected
+ return JSONResponse(
+ {
+ "status": "ok",
+ "service": "glassbox-forensics",
+ "contract_version": "glassbox.console-api.v1",
+ }
+ )
+
+ async def console_overview(request: Request) -> Any:
+ if (rejected := unauthorized(request)) is not None:
+ return rejected
+ return JSONResponse(service.get_console_overview())
+
+ async def console_receipts(request: Request) -> Any:
+ if (rejected := unauthorized(request)) is not None:
+ return rejected
+ try:
+ return JSONResponse(
+ service.list_decisions(
+ query=request.query_params.get("query"),
+ limit=_query_int(request, "limit", 100),
+ offset=_query_int(request, "offset", 0),
+ )
+ )
+ except ForensicsInputError as exc:
+ return _console_error("INVALID_ARGUMENT", str(exc), status_code=400)
+
+ async def console_receipt_findings(request: Request) -> Any:
+ if (rejected := unauthorized(request)) is not None:
+ return rejected
+ try:
+ return JSONResponse(
+ service.list_decision_findings(
+ request.path_params["receipt_id"],
+ limit=_query_int(request, "limit", 100),
+ )
+ )
+ except ForensicsInputError as exc:
+ return _console_error("INVALID_ARGUMENT", str(exc), status_code=400)
+ except ForensicsNotFoundError as exc:
+ return _console_error("NOT_FOUND", str(exc), status_code=404)
+
+ async def console_receipt(request: Request) -> Any:
+ if (rejected := unauthorized(request)) is not None:
+ return rejected
+ try:
+ receipt_id = request.path_params["receipt_id"]
+ return JSONResponse(
+ {
+ "contract_version": "glassbox.console-api.v1",
+ "verification": service.verify_decision_receipt(receipt_id),
+ "influence": service.get_decision_influence(receipt_id),
+ "publication": service.get_decision_publication(receipt_id),
+ }
+ )
+ except ForensicsInputError as exc:
+ return _console_error("INVALID_ARGUMENT", str(exc), status_code=400)
+ except ForensicsNotFoundError as exc:
+ return _console_error("NOT_FOUND", str(exc), status_code=404)
+
+ async def console_campaigns(request: Request) -> Any:
+ if (rejected := unauthorized(request)) is not None:
+ return rejected
+ try:
+ return JSONResponse(
+ service.list_invalidation_campaigns(
+ limit=_query_int(request, "limit", 100),
+ offset=_query_int(request, "offset", 0),
+ )
+ )
+ except ForensicsInputError as exc:
+ return _console_error("INVALID_ARGUMENT", str(exc), status_code=400)
+
+ async def console_campaign(request: Request) -> Any:
+ if (rejected := unauthorized(request)) is not None:
+ return rejected
+ try:
+ return JSONResponse(
+ service.get_invalidation_campaign(request.path_params["campaign_id"])
+ )
+ except ForensicsInputError as exc:
+ return _console_error("INVALID_ARGUMENT", str(exc), status_code=400)
+ except ForensicsNotFoundError as exc:
+ return _console_error("NOT_FOUND", str(exc), status_code=404)
+
+ server.custom_route("/health", methods=["GET"])(health)
+ server.custom_route("/api/v1/overview", methods=["GET"])(console_overview)
+ server.custom_route("/api/v1/receipts", methods=["GET"])(console_receipts)
+ server.custom_route(
+ "/api/v1/receipts/{receipt_id:path}/findings",
+ methods=["GET"],
+ )(console_receipt_findings)
+ server.custom_route("/api/v1/receipts/{receipt_id:path}", methods=["GET"])(console_receipt)
+ server.custom_route("/api/v1/campaigns", methods=["GET"])(console_campaigns)
+ server.custom_route("/api/v1/campaigns/{campaign_id:path}", methods=["GET"])(console_campaign)
return server
@@ -168,6 +297,28 @@ def main() -> None:
default=10.0,
help="bounded PostgreSQL connection timeout",
)
+ parser.add_argument(
+ "--transport",
+ choices=("stdio", "streamable-http"),
+ default="stdio",
+ help="serve MCP over stdio or the loopback HTTP operator surface",
+ )
+ parser.add_argument(
+ "--http-host",
+ default="127.0.0.1",
+ help="loopback host for streamable HTTP (default: 127.0.0.1)",
+ )
+ parser.add_argument(
+ "--http-port",
+ type=int,
+ default=8788,
+ help="port for streamable HTTP and the console API (default: 8788)",
+ )
+ parser.add_argument(
+ "--http-bearer-token-env",
+ default="GLASSBOX_FORENSICS_API_TOKEN",
+ help="environment variable containing the private console API bearer token",
+ )
args = parser.parse_args()
configured = args.receipt_store or _path_from_environment()
if configured is not None and args.state_postgres_dsn_env is not None:
@@ -202,6 +353,10 @@ def main() -> None:
postgres_store,
artifacts=postgres_store,
findings=TransactionalCampaignReader(postgres_store),
+ publications=TransactionalReceiptPublicationReader(
+ postgres_store,
+ durability_authority="POSTGRESQL",
+ ),
require_signature=require_signature,
signer_trust_policy=signer_trust_policy,
)
@@ -222,7 +377,26 @@ def main() -> None:
require_signature=require_signature,
signer_trust_policy=signer_trust_policy,
)
- build_server(service).run()
+ http_bearer_token = os.getenv(args.http_bearer_token_env) or None
+ server = (
+ build_server(service, http_bearer_token=http_bearer_token)
+ if http_bearer_token is not None
+ else build_server(service)
+ )
+ if args.transport == "stdio":
+ server.run()
+ else:
+ if args.http_host not in {"127.0.0.1", "localhost", "::1"} and http_bearer_token is None:
+ parser.error("a non-loopback console API bind requires bearer authentication")
+ if not 1 <= args.http_port <= 65535:
+ parser.error("http-port must be between 1 and 65535")
+ server.run(
+ transport="streamable-http",
+ host=args.http_host,
+ port=args.http_port,
+ json_response=True,
+ stateless_http=True,
+ )
def _path_from_environment() -> Path | None:
@@ -235,6 +409,29 @@ def _trust_path_from_environment() -> Path | None:
return Path(value) if value else None
+def _query_int(request: Any, name: str, default: int) -> int:
+ raw = request.query_params.get(name)
+ if raw is None:
+ return default
+ try:
+ return int(raw)
+ except ValueError as exc:
+ raise ForensicsInputError(f"{name} must be an integer") from exc
+
+
+def _console_error(code: str, message: str, *, status_code: int) -> Any:
+ from starlette.responses import JSONResponse
+
+ return JSONResponse(
+ {
+ "contract_version": "glassbox.console-api.v1",
+ "error": {"code": code, "message": message},
+ "raw_content_returned": False,
+ },
+ status_code=status_code,
+ )
+
+
def _change(
*,
event_id: str,
diff --git a/services/forensics-mcp/src/glassbox_forensics/service.py b/services/forensics-mcp/src/glassbox_forensics/service.py
index b7cf830..3fb560f 100644
--- a/services/forensics-mcp/src/glassbox_forensics/service.py
+++ b/services/forensics-mcp/src/glassbox_forensics/service.py
@@ -68,6 +68,26 @@ def get_campaign(self, campaign_id: str) -> PersistedCampaign | None: ...
def all_campaigns(self) -> tuple[PersistedCampaign, ...]: ...
+@dataclass(frozen=True)
+class PersistedReceiptPublication:
+ """Bounded projection of one durable receipt-publication obligation."""
+
+ receipt_id: str
+ workflow_status: str
+ attempt_count: int
+ last_error_recorded: bool
+ document_urn: str | None
+ aspect_names: tuple[str, ...]
+ emission_count: int | None
+ durability_authority: str
+
+
+class ReceiptPublicationReader(Protocol):
+ """Read-only projection over durable receipt-publication state."""
+
+ def get_publication(self, receipt_id: str) -> PersistedReceiptPublication | None: ...
+
+
class ForensicsService:
"""Answer forensic questions without returning raw prompts, outputs, or values."""
@@ -77,12 +97,14 @@ def __init__(
*,
artifacts: ReceiptArtifactReader | None = None,
findings: CampaignFindingReader | None = None,
+ publications: ReceiptPublicationReader | None = None,
require_signature: bool = True,
signer_trust_policy: SignerTrustPolicy | None = None,
) -> None:
self._profiles = profiles
self._artifacts = artifacts
self._findings = findings
+ self._publications = publications
self._require_signature = require_signature
self._signer_trust_policy = signer_trust_policy
@@ -198,6 +220,48 @@ def get_decision_influence(self, receipt_id: str) -> dict[str, object]:
"raw_content_returned": False,
}
+ def get_decision_publication(self, receipt_id: str) -> dict[str, object]:
+ """Return sealed durable publication evidence without querying DataHub."""
+
+ profile = self._find_profile(receipt_id)
+ if self._publications is None:
+ return {
+ "contract_version": CONTRACT_VERSION,
+ "scope": "CONFIGURED_PUBLICATION_STORE",
+ "receipt_id": profile.receipt_id,
+ "availability": "PUBLICATION_STORE_NOT_CONFIGURED",
+ "raw_content_returned": False,
+ }
+ publication = self._publications.get_publication(receipt_id)
+ if publication is None:
+ return {
+ "contract_version": CONTRACT_VERSION,
+ "scope": "CONFIGURED_PUBLICATION_STORE",
+ "receipt_id": profile.receipt_id,
+ "availability": "PUBLICATION_NOT_STAGED",
+ "raw_content_returned": False,
+ }
+ return {
+ "contract_version": CONTRACT_VERSION,
+ "scope": "CONFIGURED_PUBLICATION_STORE",
+ "receipt_id": profile.receipt_id,
+ "availability": "AVAILABLE",
+ "durability": {
+ "authority": publication.durability_authority,
+ "workflow_status": publication.workflow_status,
+ "attempt_count": publication.attempt_count,
+ "last_error_recorded": publication.last_error_recorded,
+ "sealed_evidence": publication.document_urn is not None,
+ },
+ "datahub": {
+ "document_urn": publication.document_urn,
+ "aspect_names": list(publication.aspect_names),
+ "aspect_count": len(publication.aspect_names),
+ "emission_count": publication.emission_count,
+ },
+ "raw_content_returned": False,
+ }
+
def classify_decision_impact(
self, receipt_id: str, change: NormalizedChange
) -> dict[str, object]:
@@ -330,6 +394,119 @@ def list_decision_findings(
"raw_content_returned": False,
}
+ def get_console_overview(self) -> dict[str, object]:
+ """Return a bounded operational summary without inventing decision state."""
+
+ profiles = self._profiles.all_profiles()
+ campaigns = self._findings.all_campaigns() if self._findings is not None else ()
+ latest = _latest_assessments(campaigns)
+ states = Counter(
+ _profile_state(profile, latest.get(profile.receipt_id)) for profile in profiles
+ )
+ return {
+ "contract_version": CONTRACT_VERSION,
+ "scope": "CONFIGURED_EVIDENCE_STORES",
+ "availability": {
+ "receipt_index": "AVAILABLE",
+ "campaign_store": ("AVAILABLE" if self._findings is not None else "NOT_CONFIGURED"),
+ },
+ "counts": {
+ "receipts": len(profiles),
+ "dependencies": sum(len(profile.dependencies) for profile in profiles),
+ "unresolved_dependencies": sum(
+ not dependency.resolved
+ for profile in profiles
+ for dependency in profile.dependencies
+ ),
+ "campaigns": len(campaigns),
+ "review_required": sum(
+ states[state.value]
+ for state in sorted(_REVIEW_STATES, key=lambda item: item.value)
+ ),
+ },
+ "state_counts": {key: states[key] for key in sorted(states)},
+ "raw_content_returned": False,
+ }
+
+ def list_decisions(
+ self,
+ *,
+ query: str | None = None,
+ limit: int = DEFAULT_RESULT_LIMIT,
+ offset: int = 0,
+ ) -> dict[str, object]:
+ """List safe receipt projections for the operator console."""
+
+ _require_page(limit=limit, offset=offset)
+ selected_query = query.strip().lower() if query is not None else ""
+ profiles = self._profiles.all_profiles()
+ campaigns = self._findings.all_campaigns() if self._findings is not None else ()
+ latest = _latest_assessments(campaigns)
+ decisions = [
+ _decision_summary(profile, latest.get(profile.receipt_id)) for profile in profiles
+ ]
+ if selected_query:
+ decisions = [
+ item
+ for item in decisions
+ if selected_query in _searchable_decision_text(item).lower()
+ ]
+ decisions.sort(
+ key=lambda item: (str(item["ended_at"]), str(item["receipt_id"])),
+ reverse=True,
+ )
+ returned = decisions[offset : offset + limit]
+ return {
+ "contract_version": CONTRACT_VERSION,
+ "scope": "CONFIGURED_RECEIPT_INDEX",
+ "availability": "AVAILABLE",
+ "total": len(decisions),
+ "offset": offset,
+ "returned": len(returned),
+ "truncated": offset + len(returned) < len(decisions),
+ "decisions": returned,
+ "raw_content_returned": False,
+ }
+
+ def list_invalidation_campaigns(
+ self,
+ *,
+ limit: int = DEFAULT_RESULT_LIMIT,
+ offset: int = 0,
+ ) -> dict[str, object]:
+ """List persisted Action campaigns without exposing raw event bodies."""
+
+ _require_page(limit=limit, offset=offset)
+ if self._findings is None:
+ return {
+ "contract_version": CONTRACT_VERSION,
+ "scope": "CONFIGURED_CAMPAIGN_STORE",
+ "availability": "CAMPAIGN_STORE_NOT_CONFIGURED",
+ "total": 0,
+ "offset": offset,
+ "returned": 0,
+ "truncated": False,
+ "campaigns": [],
+ "raw_content_returned": False,
+ }
+ campaigns = sorted(
+ self._findings.all_campaigns(),
+ key=lambda item: (item.campaign.change.occurred_at, item.campaign.campaign_id),
+ reverse=True,
+ )
+ returned = campaigns[offset : offset + limit]
+ return {
+ "contract_version": CONTRACT_VERSION,
+ "scope": "CONFIGURED_CAMPAIGN_STORE",
+ "availability": "AVAILABLE",
+ "total": len(campaigns),
+ "offset": offset,
+ "returned": len(returned),
+ "truncated": offset + len(returned) < len(campaigns),
+ "campaigns": [_persisted_campaign_to_dict(item) for item in returned],
+ "raw_content_returned": False,
+ }
+
def _profile_integrity(self, receipt_id: str) -> dict[str, object]:
if self._artifacts is None:
return {
@@ -424,3 +601,90 @@ def _processing_to_dict(value: PersistedCampaign) -> dict[str, object]:
"datahub_writeback_state": writeback_state,
"last_error_recorded": value.last_error_recorded,
}
+
+
+def _latest_assessments(
+ campaigns: tuple[PersistedCampaign, ...],
+) -> dict[str, tuple[PersistedCampaign, ImpactAssessment]]:
+ latest: dict[str, tuple[PersistedCampaign, ImpactAssessment]] = {}
+ ordered = sorted(
+ campaigns,
+ key=lambda item: (item.campaign.change.occurred_at, item.campaign.campaign_id),
+ reverse=True,
+ )
+ for campaign in ordered:
+ for assessment in campaign.campaign.assessments:
+ latest.setdefault(assessment.receipt_id, (campaign, assessment))
+ return latest
+
+
+def _profile_state(
+ profile: ReceiptDependencyProfile,
+ latest: tuple[PersistedCampaign, ImpactAssessment] | None,
+) -> str:
+ if profile.superseded_by is not None:
+ return ImpactState.SUPERSEDED.value
+ if latest is None:
+ return "NO_RECORDED_FINDING"
+ return latest[1].state.value
+
+
+def _decision_summary(
+ profile: ReceiptDependencyProfile,
+ latest: tuple[PersistedCampaign, ImpactAssessment] | None,
+) -> dict[str, object]:
+ dependencies = [
+ {
+ "evidence_id": item.evidence_id,
+ "datahub_urn": item.datahub_urn,
+ "schema_field_urn": item.schema_field_urn,
+ "state": item.state.value,
+ "role": item.role.value,
+ }
+ for item in profile.dependencies
+ ]
+ finding = None
+ if latest is not None:
+ campaign, assessment = latest
+ finding = {
+ "campaign_id": campaign.campaign.campaign_id,
+ "incident_urn": campaign.campaign.incident_urn,
+ "occurred_at": campaign.campaign.change.occurred_at,
+ "assessment": _assessment_to_dict(assessment),
+ "processing": _processing_to_dict(campaign),
+ }
+ return {
+ "receipt_id": profile.receipt_id,
+ "document_urn": profile.document_urn,
+ "ended_at": profile.ended_at,
+ "superseded_by": profile.superseded_by,
+ "state": _profile_state(profile, latest),
+ "dependency_count": len(dependencies),
+ "resolved_dependency_count": sum(item.resolved for item in profile.dependencies),
+ "field_lineage_coverage": profile.field_lineage.coverage.value,
+ "wildcard_query": profile.field_lineage.wildcard_query,
+ "dependencies": dependencies,
+ "latest_finding": finding,
+ }
+
+
+def _searchable_decision_text(value: Mapping[str, object]) -> str:
+ dependencies = value.get("dependencies")
+ safe_parts = [str(value.get("receipt_id", "")), str(value.get("document_urn", ""))]
+ if isinstance(dependencies, list):
+ for dependency in dependencies:
+ if isinstance(dependency, Mapping):
+ safe_parts.extend(
+ (
+ str(dependency.get("datahub_urn", "")),
+ str(dependency.get("schema_field_urn", "")),
+ )
+ )
+ return " ".join(safe_parts)
+
+
+def _require_page(*, limit: int, offset: int) -> None:
+ if isinstance(limit, bool) or not 1 <= limit <= MAX_RESULT_LIMIT:
+ raise ForensicsInputError(f"limit must be between 1 and {MAX_RESULT_LIMIT}")
+ if isinstance(offset, bool) or offset < 0:
+ raise ForensicsInputError("offset must be a non-negative integer")
diff --git a/services/invalidation-action/src/glassbox_invalidation/postgres_store.py b/services/invalidation-action/src/glassbox_invalidation/postgres_store.py
index 7821e15..ea302fd 100644
--- a/services/invalidation-action/src/glassbox_invalidation/postgres_store.py
+++ b/services/invalidation-action/src/glassbox_invalidation/postgres_store.py
@@ -303,15 +303,19 @@ def _register_receipt(
raise TransactionalStoreError(
f"receipt {receipt_id} already has conflicting dependency metadata"
)
+ admission = _signer_admission_evidence(self.signer_trust_policy, receipt)
profile = ReceiptDependencyProfile.from_receipt(
receipt,
field_lineage=proof,
superseded_by=superseded_by,
require_signature=self.require_signature,
signer_trust_policy=self.signer_trust_policy,
- signer_trust_mode=SignerTrustMode.ADMISSION,
+ signer_trust_mode=(
+ SignerTrustMode.HISTORICAL
+ if self.signer_trust_policy is not None
+ else SignerTrustMode.ADMISSION
+ ),
)
- admission = _signer_admission_evidence(self.signer_trust_policy, receipt)
material = {
**core_material,
"signer_admission": admission.to_dict() if admission is not None else None,
diff --git a/services/invalidation-action/src/glassbox_invalidation/receipt_store.py b/services/invalidation-action/src/glassbox_invalidation/receipt_store.py
index 372cadd..ca90169 100644
--- a/services/invalidation-action/src/glassbox_invalidation/receipt_store.py
+++ b/services/invalidation-action/src/glassbox_invalidation/receipt_store.py
@@ -80,15 +80,19 @@ def register(
raise ReceiptStoreError(
f"receipt {receipt_id} already has conflicting dependency metadata"
)
+ admission = _admission_evidence(self.signer_trust_policy, receipt)
profile = ReceiptDependencyProfile.from_receipt(
receipt,
field_lineage=proof,
superseded_by=superseded_by,
require_signature=self.require_signature,
signer_trust_policy=self.signer_trust_policy,
- signer_trust_mode=SignerTrustMode.ADMISSION,
+ signer_trust_mode=(
+ SignerTrustMode.HISTORICAL
+ if self.signer_trust_policy is not None
+ else SignerTrustMode.ADMISSION
+ ),
)
- admission = _admission_evidence(self.signer_trust_policy, receipt)
material = {
"receipt": copy.deepcopy(dict(receipt)),
"field_lineage": _lineage_to_dict(proof),
diff --git a/services/invalidation-action/src/glassbox_invalidation/transactional_store.py b/services/invalidation-action/src/glassbox_invalidation/transactional_store.py
index 65e8e06..eacd1a1 100644
--- a/services/invalidation-action/src/glassbox_invalidation/transactional_store.py
+++ b/services/invalidation-action/src/glassbox_invalidation/transactional_store.py
@@ -362,15 +362,19 @@ def _register_receipt(
raise TransactionalStoreError(
f"receipt {receipt_id} already has conflicting dependency metadata"
)
+ admission = _signer_admission_evidence(self.signer_trust_policy, receipt)
profile = ReceiptDependencyProfile.from_receipt(
receipt,
field_lineage=proof,
superseded_by=superseded_by,
require_signature=self.require_signature,
signer_trust_policy=self.signer_trust_policy,
- signer_trust_mode=SignerTrustMode.ADMISSION,
+ signer_trust_mode=(
+ SignerTrustMode.HISTORICAL
+ if self.signer_trust_policy is not None
+ else SignerTrustMode.ADMISSION
+ ),
)
- admission = _signer_admission_evidence(self.signer_trust_policy, receipt)
material = {
**core_material,
"signer_admission": admission.to_dict() if admission is not None else None,
diff --git a/tests/integration/test_postgres_invalidation.py b/tests/integration/test_postgres_invalidation.py
index 1f0ea41..0face6c 100644
--- a/tests/integration/test_postgres_invalidation.py
+++ b/tests/integration/test_postgres_invalidation.py
@@ -5,7 +5,6 @@
import json
import os
import threading
-import time
import uuid
from collections.abc import Mapping
from concurrent.futures import ThreadPoolExecutor
@@ -95,6 +94,7 @@ def _trust_policy(
key: SigningKey,
*,
status: SignerStatus = SignerStatus.ACTIVE,
+ not_before: str = "2020-01-01T00:00:00Z",
) -> SignerTrustPolicy:
return SignerTrustPolicy(
policy_id="postgres-integration-trust-v1",
@@ -105,7 +105,7 @@ def _trust_policy(
public_key=signing_key_public_key(key),
public_key_sha256=signing_key_fingerprint(key),
status=status,
- not_before="2020-01-01T00:00:00Z",
+ not_before=not_before,
not_after="2100-01-01T00:00:00Z",
),
),
@@ -337,6 +337,32 @@ def test_postgres_enforces_trusted_admission_and_rotation_history(
)
+def test_postgres_rejects_receipt_from_before_signer_validity_without_writing(
+ postgres_schema: str,
+) -> None:
+ assert POSTGRES_DSN is not None
+ key = SigningKey("postgres-future-at-receipt-time", Ed25519PrivateKey.generate())
+ store = PostgresInvalidationStore(
+ POSTGRES_DSN,
+ schema=postgres_schema,
+ signer_trust_policy=_trust_policy(
+ key,
+ not_before="2026-08-07T00:00:00Z",
+ ),
+ )
+
+ with pytest.raises(PolicyInputError, match="BEFORE_VALIDITY_WINDOW"):
+ store.register(
+ _receipt(run_id="postgres-before-key-validity", signing_key=key),
+ field_lineage=_lineage(),
+ )
+
+ report = store.verify_integrity()
+ assert report.receipts == 0
+ assert report.dependencies == 0
+ assert report.receipt_publication_tasks == 0
+
+
def test_signed_state_transfer_round_trips_between_sqlite_and_postgres(
tmp_path: Path,
postgres_schema: str,
@@ -638,15 +664,24 @@ def test_postgres_uses_server_clock_for_expired_lease_recovery(
campaign.campaign_id,
worker_id="first",
now_ms=1,
- lease_duration_ms=50,
+ lease_duration_ms=10_000,
)
blocked = store.claim(
campaign.campaign_id,
worker_id="second",
now_ms=9_999_999_999_999,
- lease_duration_ms=50,
+ lease_duration_ms=10_000,
)
- time.sleep(0.08)
+ with store._transaction() as cursor:
+ cursor.execute(
+ """
+ UPDATE campaign_outbox
+ SET lease_expires_at_ms =
+ FLOOR(EXTRACT(EPOCH FROM clock_timestamp()) * 1000)::BIGINT - 1
+ WHERE campaign_id = %s
+ """,
+ (campaign.campaign_id,),
+ )
recovered = store.claim(
campaign.campaign_id,
worker_id="second",
diff --git a/tests/unit/test_agent_invalidation_benchmark.py b/tests/unit/test_agent_invalidation_benchmark.py
new file mode 100644
index 0000000..206927c
--- /dev/null
+++ b/tests/unit/test_agent_invalidation_benchmark.py
@@ -0,0 +1,101 @@
+"""Deterministic correctness and schema contracts for the flagship benchmark."""
+
+from __future__ import annotations
+
+import copy
+import json
+from pathlib import Path
+
+import pytest
+from jsonschema import ValidationError
+
+from benchmarks.agent_invalidation.runner import (
+ Ablation,
+ FixtureError,
+ build_benchmark_report,
+ load_cases,
+ validate_benchmark_report,
+)
+
+
+def _variants(report: dict) -> dict[str, dict]:
+ return {item["variant"]: item for item in report["variants"]}
+
+
+def _case(variant: dict, case_id: str) -> dict:
+ return next(item for item in variant["cases"] if item["case_id"] == case_id)
+
+
+def test_five_way_ablation_is_content_addressed_schema_valid_and_repeatable() -> None:
+ first = build_benchmark_report()
+ second = build_benchmark_report()
+
+ assert first == second
+ validate_benchmark_report(first)
+ assert first["case_count"] == 12
+ assert [item["variant"] for item in first["variants"]] == [item.value for item in Ablation]
+ assert first["replay_policy"]["correctness"] == {
+ "numerator": 4,
+ "denominator": 4,
+ "value": 1.0,
+ }
+ assert first["redaction"]["escape_rate"]["value"] == 0.0
+ assert first["live_evidence"]["completed_redelivery_zero_write_rate"]["value"] == 1.0
+
+
+def test_full_evidence_removes_false_invalidations_without_hiding_unknowns() -> None:
+ variants = _variants(build_benchmark_report(live_report_path=None))
+ static = variants[Ablation.STATIC_DECLARED_LINEAGE.value]
+ raw = variants[Ablation.RAW_OTEL_TRACES.value]
+ no_field = variants[Ablation.GLASSBOX_WITHOUT_FIELD_EVIDENCE.value]
+ no_snapshot = variants[Ablation.GLASSBOX_WITHOUT_METADATA_SNAPSHOTS.value]
+ full = variants[Ablation.FULL_GLASSBOX.value]
+
+ assert static["impact"]["false_invalidation_rate"]["value"] == 0.833333
+ assert raw["impact"]["false_invalidation_rate"]["value"] == 0.666667
+ assert no_field["impact"]["false_invalidation_rate"]["value"] == 0.5
+ assert no_snapshot["impact"]["false_invalidation_rate"]["value"] == 0.166667
+ assert full["impact"]["false_invalidation_rate"]["value"] == 0.0
+ assert full["impact"]["missed_invalidation_rate"]["value"] == 0.0
+ assert full["impact"]["unknown_at_risk_honesty_rate"]["value"] == 1.0
+ assert full["resolution"]["field_recall"]["value"] == 0.888889
+ assert full["resolution"]["field_resolution_failed_cases"] == ["unresolved-runtime-context"]
+
+
+def test_field_and_snapshot_ablation_changes_the_expected_causal_cases() -> None:
+ variants = _variants(build_benchmark_report(live_report_path=None))
+ full = variants[Ablation.FULL_GLASSBOX.value]
+ no_field = variants[Ablation.GLASSBOX_WITHOUT_FIELD_EVIDENCE.value]
+ no_snapshot = variants[Ablation.GLASSBOX_WITHOUT_METADATA_SNAPSHOTS.value]
+ raw = variants[Ablation.RAW_OTEL_TRACES.value]
+
+ assert _case(full, "unrelated-field-same-asset")["state"] == "UNAFFECTED"
+ assert _case(no_field, "unrelated-field-same-asset")["state"] == "AT_RISK"
+ assert _case(full, "matching-post-change-snapshot")["state"] == "UNAFFECTED"
+ assert _case(no_snapshot, "matching-post-change-snapshot")["state"] == "STALE"
+ assert _case(full, "trace-alias-collision")["state"] == "UNAFFECTED"
+ assert _case(raw, "trace-alias-collision")["state"] == "AT_RISK"
+ assert _case(full, "unresolved-runtime-context")["state"] == "UNKNOWN"
+
+
+def test_fixture_and_report_contracts_fail_closed(tmp_path: Path) -> None:
+ raw, _ = load_cases()
+ malformed = copy.deepcopy(raw)
+ malformed["unexpected"] = True
+ fixture = tmp_path / "fixtures.json"
+ fixture.write_text(json.dumps(malformed), encoding="utf-8")
+ with pytest.raises(FixtureError, match="missing or unexpected"):
+ load_cases(fixture)
+
+ report = build_benchmark_report(live_report_path=None)
+ report["unexpected"] = True
+ with pytest.raises(ValidationError):
+ validate_benchmark_report(report)
+
+
+def test_benchmark_report_never_contains_redaction_sentinels_or_personal_paths() -> None:
+ rendered = json.dumps(build_benchmark_report(live_report_path=None), sort_keys=True)
+
+ assert "benchmark-sensitive-value" not in rendered
+ assert "/" + "Users/" not in rendered
+ assert "postgresql://" not in rendered
diff --git a/tests/unit/test_control_plane.py b/tests/unit/test_control_plane.py
new file mode 100644
index 0000000..c8e50ca
--- /dev/null
+++ b/tests/unit/test_control_plane.py
@@ -0,0 +1,625 @@
+"""Security and contract tests for the self-hosted control plane."""
+
+from __future__ import annotations
+
+import json
+import sqlite3
+from datetime import UTC, datetime
+from pathlib import Path
+from typing import Any
+
+import pytest
+from cryptography.exceptions import InvalidTag
+from starlette.testclient import TestClient
+
+from glassbox_control import datahub as datahub_module
+from glassbox_control.crypto import SecretBox, datahub_secret_aad
+from glassbox_control.datahub import DataHubConnectionTestError, normalize_datahub_url
+from glassbox_control.server import build_app
+from glassbox_control.server import main as control_main
+from glassbox_control.store import ControlStore, ControlStoreError
+
+MASTER_KEY = bytes(range(32))
+API_TOKEN = "control-api-token-that-is-deliberately-long-enough"
+NOW = datetime(2026, 8, 10, 12, 0, tzinfo=UTC)
+
+
+def _store(tmp_path: Path) -> ControlStore:
+ return ControlStore(
+ tmp_path / "control.sqlite3",
+ SecretBox(MASTER_KEY),
+ organization="glassbox-test",
+ initialize=True,
+ )
+
+
+def test_secret_box_binds_ciphertext_and_ingestion_keys() -> None:
+ box = SecretBox(MASTER_KEY, key_id="test-v1")
+ aad = datahub_secret_aad(organization="org", connection_id="primary")
+ encrypted = box.encrypt("never-store-me-clear", aad=aad)
+
+ assert box.decrypt(encrypted, aad=aad) == "never-store-me-clear"
+ with pytest.raises(InvalidTag):
+ box.decrypt(encrypted, aad=aad + b"-other")
+
+ clear, prefix, digest = box.issue_ingestion_key()
+ assert clear.startswith("gbx_ingest_")
+ assert clear.startswith(prefix)
+ assert clear not in digest
+ assert box.ingestion_key_matches(clear, digest)
+ assert not box.ingestion_key_matches(clear + "x", digest)
+
+
+def test_secret_box_rejects_invalid_keys_values_and_key_selectors() -> None:
+ with pytest.raises(ValueError, match="exactly 32 bytes"):
+ SecretBox(b"short")
+ with pytest.raises(ValueError, match="1 to 64 characters"):
+ SecretBox(MASTER_KEY, key_id="")
+ with pytest.raises(ValueError, match="unset"):
+ SecretBox.from_base64url("")
+ with pytest.raises(ValueError, match="valid base64url"):
+ SecretBox.from_base64url("not-ascii-β")
+
+ encoded = SecretBox.generate_base64url()
+ box = SecretBox.from_base64url(encoded, key_id="primary")
+ with pytest.raises(ValueError, match="non-empty"):
+ box.encrypt("", aad=b"scope")
+ encrypted = box.encrypt("secret", aad=b"scope")
+ with pytest.raises(ValueError, match="unavailable key ID"):
+ SecretBox(MASTER_KEY, key_id="replacement").decrypt(encrypted, aad=b"scope")
+ assert box.ingestion_key_digest("invalid") == ""
+ assert not box.ingestion_key_matches("invalid", "")
+
+
+def test_control_store_encrypts_connection_and_revokes_named_keys(tmp_path: Path) -> None:
+ store = _store(tmp_path)
+ report = {
+ "connection": "PROVEN",
+ "authentication": "PROVEN",
+ "sdk_compatibility": "PROVEN",
+ "write_proof": "PROVEN",
+ }
+ summary = store.save_datahub_connection(
+ server_url="https://gms.example.com",
+ ui_url="https://datahub.example.com",
+ token="datahub-service-account-secret",
+ probe=report,
+ actor="admin@example.com",
+ now=NOW,
+ )
+
+ assert summary["credential_state"] == "ENCRYPTED"
+ assert "token" not in summary
+ loaded = store.load_datahub_connection()
+ assert loaded is not None
+ assert loaded.token == "datahub-service-account-secret"
+
+ with sqlite3.connect(store.path) as connection:
+ row = connection.execute(
+ "SELECT token_ciphertext, probe_json FROM datahub_connections"
+ ).fetchone()
+ assert b"datahub-service-account-secret" not in bytes(row[0])
+ assert "datahub-service-account-secret" not in row[1]
+
+ key, clear = store.create_ingestion_key(
+ name="Production pricing agent",
+ actor="admin@example.com",
+ now=NOW,
+ )
+ assert store.authorize_ingestion_key(clear)
+ assert store.revoke_ingestion_key(key["key_id"], actor="admin@example.com", now=NOW)
+ assert not store.authorize_ingestion_key(clear)
+ assert store.list_ingestion_keys()[0]["state"] == "REVOKED"
+
+
+def test_control_store_requires_explicit_bootstrap_and_matching_key(tmp_path: Path) -> None:
+ path = tmp_path / "missing.sqlite3"
+ with pytest.raises(ControlStoreError, match="not initialized"):
+ ControlStore(path, SecretBox(MASTER_KEY))
+
+ store = ControlStore(path, SecretBox(MASTER_KEY), initialize=True)
+ store.save_datahub_connection(
+ server_url="http://datahub-gms:8080",
+ ui_url=None,
+ token="secret",
+ probe={"write_proof": "PROVEN"},
+ actor="operator",
+ now=NOW,
+ )
+ mismatched = ControlStore(path, SecretBox(bytes(reversed(MASTER_KEY))))
+ with pytest.raises(ControlStoreError, match="decryption failed"):
+ mismatched.load_datahub_connection()
+
+
+def test_control_store_rejects_invalid_bootstrap_and_bounded_metadata(tmp_path: Path) -> None:
+ with pytest.raises(ValueError, match="organization"):
+ ControlStore(tmp_path / "bad-org.sqlite3", SecretBox(MASTER_KEY), organization="")
+
+ store = _store(tmp_path)
+ with pytest.raises(ControlStoreError, match="already exists"):
+ ControlStore(store.path, SecretBox(MASTER_KEY), initialize=True)
+ with pytest.raises(ValueError, match="2 to 80"):
+ store.create_ingestion_key(name="x", actor="operator")
+ with pytest.raises(ValueError, match="timezone-aware"):
+ store.create_ingestion_key(
+ name="valid key",
+ actor="operator",
+ now=NOW.replace(tzinfo=None),
+ )
+ with pytest.raises(ValueError, match="exceeds 32 KiB"):
+ store.save_datahub_connection(
+ server_url="https://gms.example.com",
+ ui_url=None,
+ token="secret",
+ probe={"oversized": "x" * (33 * 1024)},
+ actor="operator",
+ now=NOW,
+ )
+ assert store.authorize_ingestion_key("invalid") is False
+
+ unavailable = tmp_path / "unavailable.sqlite3"
+ with sqlite3.connect(unavailable) as connection:
+ connection.execute("CREATE TABLE unrelated (value TEXT)")
+ with pytest.raises(ControlStoreError, match="schema is unavailable"):
+ ControlStore(unavailable, SecretBox(MASTER_KEY))
+
+ with sqlite3.connect(store.path) as connection:
+ connection.execute("UPDATE control_metadata SET schema_version = 999")
+ with pytest.raises(ControlStoreError, match="version is unsupported"):
+ ControlStore(store.path, SecretBox(MASTER_KEY))
+
+
+class FakeTester:
+ def __init__(self) -> None:
+ self.calls: list[dict[str, Any]] = []
+
+ def test(self, *, server_url: str, token: str, write_proof: bool) -> dict[str, Any]:
+ self.calls.append({"server_url": server_url, "token": token, "write_proof": write_proof})
+ return {
+ "contract_version": "glassbox.datahub-connection.v1",
+ "connection": "PROVEN",
+ "authentication": "PROVEN",
+ "sdk_compatibility": "PROVEN",
+ "sdk_version": "1.6.0.15",
+ "server_version": "1.6.0",
+ "write_proof": "PROVEN" if write_proof else "UNVERIFIED",
+ "probe_document_urn": (
+ "urn:li:document:glassbox.connection.probe" if write_proof else None
+ ),
+ "raw_content_returned": False,
+ }
+
+
+class FakePublicationReadback:
+ def __init__(self) -> None:
+ self.calls: list[dict[str, str]] = []
+
+ def verify(self, *, server_url: str, token: str, receipt_id: str) -> dict[str, Any]:
+ self.calls.append({"server_url": server_url, "token": token, "receipt_id": receipt_id})
+ digest = receipt_id.removeprefix("gbx:receipt:sha256:")
+ aspects = ["documentInfo", "globalTags", "status"]
+ return {
+ "contract_version": "glassbox.publication-readback.v1",
+ "receipt_id": receipt_id,
+ "document_urn": f"urn:li:document:glassbox.receipt.{digest}",
+ "verification_state": "VERIFIED_NOW",
+ "aspect_names": aspects,
+ "aspect_count": len(aspects),
+ "raw_content_returned": False,
+ }
+
+
+class FailingTester:
+ def test(self, *, server_url: str, token: str, write_proof: bool) -> dict[str, Any]:
+ raise DataHubConnectionTestError("CONNECTION", "TimeoutError")
+
+
+class UnprovenTester(FakeTester):
+ def test(self, *, server_url: str, token: str, write_proof: bool) -> dict[str, Any]:
+ report = super().test(server_url=server_url, token=token, write_proof=write_proof)
+ report["write_proof"] = "UNVERIFIED"
+ return report
+
+
+class FailingPublicationReadback:
+ def verify(self, *, server_url: str, token: str, receipt_id: str) -> dict[str, Any]:
+ raise DataHubConnectionTestError("PUBLICATION_READBACK", "TimeoutError")
+
+
+def _headers(role: str = "admin") -> dict[str, str]:
+ return {
+ "authorization": f"Bearer {API_TOKEN}",
+ "x-glassbox-subject": "admin@example.com",
+ "x-glassbox-role": role,
+ }
+
+
+def test_control_api_enforces_service_auth_roles_and_real_proof_before_save(
+ tmp_path: Path,
+) -> None:
+ store = _store(tmp_path)
+ tester = FakeTester()
+ app = build_app(store, internal_token=API_TOKEN, tester=tester)
+ payload = {
+ "server_url": "https://gms.example.com/",
+ "ui_url": "https://datahub.example.com/",
+ "token": "datahub-secret",
+ "write_proof": True,
+ }
+ with TestClient(app) as client:
+ assert client.get("/health").status_code == 200
+ assert client.get("/api/v1/connection").status_code == 401
+ forbidden = client.put(
+ "/api/v1/connection",
+ headers=_headers("viewer"),
+ json=payload,
+ )
+ assert forbidden.status_code == 403
+
+ tested = client.post("/api/v1/connection/test", headers=_headers(), json=payload)
+ saved = client.put("/api/v1/connection", headers=_headers(), json=payload)
+ fetched = client.get("/api/v1/connection", headers=_headers("viewer"))
+
+ assert tested.status_code == 200
+ assert tested.json()["persisted"] is False
+ assert saved.status_code == 200
+ assert saved.json()["connection"]["credential_state"] == "ENCRYPTED"
+ assert "datahub-secret" not in saved.text
+ assert fetched.json()["configured"] is True
+ assert tester.calls[-1]["server_url"] == "https://gms.example.com"
+
+
+def test_control_api_returns_one_time_key_and_revocation_is_immediate(tmp_path: Path) -> None:
+ store = _store(tmp_path)
+ app = build_app(store, internal_token=API_TOKEN, tester=FakeTester())
+ with TestClient(app) as client:
+ created = client.post(
+ "/api/v1/ingestion-keys",
+ headers=_headers(),
+ json={"name": "CI agent"},
+ )
+ clear = created.json()["secret"]
+ key_id = created.json()["key"]["key_id"]
+ listed = client.get("/api/v1/ingestion-keys", headers=_headers())
+ revoked = client.delete(f"/api/v1/ingestion-keys/{key_id}", headers=_headers())
+
+ assert created.status_code == 201
+ assert clear.startswith("gbx_ingest_")
+ assert clear not in listed.text
+ assert store.authorize_ingestion_key(clear) is False
+ assert revoked.json()["state"] == "REVOKED"
+
+
+def test_control_api_performs_bounded_fresh_publication_readback(tmp_path: Path) -> None:
+ store = _store(tmp_path)
+ store.save_datahub_connection(
+ server_url="https://gms.example.com",
+ ui_url="https://datahub.example.com",
+ token="datahub-service-account-secret",
+ probe={"write_proof": "PROVEN"},
+ actor="admin@example.com",
+ now=NOW,
+ )
+ readback = FakePublicationReadback()
+ app = build_app(
+ store,
+ internal_token=API_TOKEN,
+ tester=FakeTester(),
+ publication_readback=readback,
+ )
+ receipt_id = "gbx:receipt:sha256:" + "a" * 64
+
+ with TestClient(app) as client:
+ verified = client.get(
+ f"/api/v1/publications/{receipt_id}/readback",
+ headers=_headers("viewer"),
+ )
+ rejected = client.get(
+ "/api/v1/publications/not-a-receipt/readback",
+ headers=_headers("viewer"),
+ )
+
+ assert verified.status_code == 200
+ assert verified.json()["verification_state"] == "VERIFIED_NOW"
+ assert verified.json()["aspect_count"] == 3
+ assert verified.json()["raw_content_returned"] is False
+ assert readback.calls == [
+ {
+ "server_url": "https://gms.example.com",
+ "token": "datahub-service-account-secret",
+ "receipt_id": receipt_id,
+ }
+ ]
+ assert "datahub-service-account-secret" not in verified.text
+ assert rejected.status_code == 400
+ assert rejected.json()["error"]["code"] == "INVALID_ARGUMENT"
+
+
+def test_control_api_returns_bounded_errors_for_invalid_inputs_and_remote_failures(
+ tmp_path: Path,
+) -> None:
+ store = _store(tmp_path)
+ receipt_id = "gbx:receipt:sha256:" + "b" * 64
+ with pytest.raises(ValueError, match="at least 32"):
+ build_app(store, internal_token="short")
+
+ app = build_app(store, internal_token=API_TOKEN, tester=FailingTester())
+ incomplete_identity = {"authorization": f"Bearer {API_TOKEN}"}
+ with TestClient(app) as client:
+ empty_connection = client.get("/api/v1/connection", headers=_headers("viewer"))
+ assert client.get("/api/v1/connection", headers=incomplete_identity).status_code == 403
+ assert client.get(f"/api/v1/publications/{receipt_id}/readback").status_code == 401
+ assert client.post("/api/v1/connection/test", json={}).status_code == 401
+ assert client.get("/api/v1/ingestion-keys").status_code == 401
+ assert client.post("/api/v1/ingestion-keys", json={}).status_code == 401
+ assert client.delete(f"/api/v1/ingestion-keys/ik_{'a' * 32}").status_code == 401
+ missing_connection = client.get(
+ f"/api/v1/publications/{receipt_id}/readback",
+ headers=_headers("viewer"),
+ )
+ malformed = client.post(
+ "/api/v1/connection/test",
+ headers={**_headers(), "content-type": "application/json"},
+ content=b"{",
+ )
+ invalid_length = client.post(
+ "/api/v1/connection/test",
+ headers={
+ **_headers(),
+ "content-type": "application/json",
+ "content-length": "not-a-number",
+ },
+ content=b"{}",
+ )
+ oversized = client.post(
+ "/api/v1/connection/test",
+ headers=_headers(),
+ json={"padding": "x" * (33 * 1024)},
+ )
+ non_object = client.post(
+ "/api/v1/connection/test",
+ headers=_headers(),
+ json=["not", "an", "object"],
+ )
+ remote_failure = client.post(
+ "/api/v1/connection/test",
+ headers=_headers(),
+ json={
+ "server_url": "https://gms.example.com",
+ "token": "secret",
+ "write_proof": True,
+ },
+ )
+ invalid_key_name = client.post(
+ "/api/v1/ingestion-keys",
+ headers=_headers(),
+ json={"name": 42},
+ )
+ invalid_key_id = client.delete("/api/v1/ingestion-keys/not-a-key", headers=_headers())
+ missing_key = client.delete(
+ f"/api/v1/ingestion-keys/ik_{'a' * 32}",
+ headers=_headers(),
+ )
+
+ assert empty_connection.json()["configured"] is False
+ assert missing_connection.status_code == 409
+ assert missing_connection.json()["error"]["code"] == "DATAHUB_NOT_CONFIGURED"
+ assert malformed.status_code == 400
+ assert invalid_length.status_code == 400
+ assert oversized.status_code == 400
+ assert non_object.status_code == 400
+ assert remote_failure.status_code == 422
+ assert remote_failure.json()["error"]["code"] == "DATAHUB_TEST_FAILED"
+ assert "TimeoutError" in remote_failure.text
+ assert invalid_key_name.status_code == 400
+ assert invalid_key_id.status_code == 400
+ assert missing_key.status_code == 404
+
+
+@pytest.mark.parametrize(
+ "payload",
+ [
+ {"token": "secret", "write_proof": True},
+ {
+ "server_url": "https://gms.example.com",
+ "ui_url": 42,
+ "token": "secret",
+ "write_proof": True,
+ },
+ {"server_url": "https://gms.example.com", "write_proof": True},
+ {
+ "server_url": "https://gms.example.com",
+ "token": "secret",
+ "write_proof": "yes",
+ },
+ ],
+)
+def test_control_api_rejects_incomplete_connection_contracts(
+ tmp_path: Path,
+ payload: dict[str, Any],
+) -> None:
+ app = build_app(_store(tmp_path), internal_token=API_TOKEN, tester=FakeTester())
+ with TestClient(app) as client:
+ result = client.post(
+ "/api/v1/connection/test",
+ headers=_headers(),
+ json=payload,
+ )
+ assert result.status_code == 400
+ assert result.json()["error"]["code"] == "INVALID_ARGUMENT"
+
+
+def test_control_api_requires_write_proof_and_bounds_readback_failures(tmp_path: Path) -> None:
+ store = _store(tmp_path)
+ app = build_app(store, internal_token=API_TOKEN, tester=UnprovenTester())
+ connection = {
+ "server_url": "https://gms.example.com",
+ "token": "datahub-secret",
+ "write_proof": False,
+ }
+ with TestClient(app) as client:
+ proof_required = client.put(
+ "/api/v1/connection",
+ headers=_headers(),
+ json=connection,
+ )
+ unproven = client.put(
+ "/api/v1/connection",
+ headers=_headers(),
+ json={**connection, "write_proof": True},
+ )
+
+ assert proof_required.status_code == 400
+ assert unproven.status_code == 422
+ assert "ProofNotEstablished" in unproven.text
+
+ store.save_datahub_connection(
+ server_url="https://gms.example.com",
+ ui_url=None,
+ token="datahub-secret",
+ probe={"write_proof": "PROVEN"},
+ actor="operator",
+ now=NOW,
+ )
+ failing_app = build_app(
+ store,
+ internal_token=API_TOKEN,
+ tester=FakeTester(),
+ publication_readback=FailingPublicationReadback(),
+ )
+ receipt_id = "gbx:receipt:sha256:" + "c" * 64
+ with TestClient(failing_app) as client:
+ failed = client.get(
+ f"/api/v1/publications/{receipt_id}/readback",
+ headers=_headers("viewer"),
+ )
+ assert failed.status_code == 502
+ assert failed.json()["error"]["code"] == "DATAHUB_READBACK_FAILED"
+ assert "datahub-secret" not in failed.text
+
+
+def test_control_api_bounds_unavailable_state(
+ tmp_path: Path,
+ monkeypatch: pytest.MonkeyPatch,
+) -> None:
+ store = _store(tmp_path)
+ receipt_id = "gbx:receipt:sha256:" + "d" * 64
+
+ def unavailable(*args: Any, **kwargs: Any) -> Any:
+ raise ControlStoreError("synthetic unavailable state")
+
+ monkeypatch.setattr(store, "load_datahub_connection", unavailable)
+ readback_app = build_app(store, internal_token=API_TOKEN, tester=FakeTester())
+ with TestClient(readback_app) as client:
+ readback = client.get(
+ f"/api/v1/publications/{receipt_id}/readback",
+ headers=_headers("viewer"),
+ )
+ assert readback.status_code == 503
+ assert readback.json()["error"]["code"] == "CONTROL_STATE_UNAVAILABLE"
+
+ monkeypatch.setattr(store, "load_datahub_connection", lambda: None)
+ monkeypatch.setattr(store, "save_datahub_connection", unavailable)
+ save_app = build_app(store, internal_token=API_TOKEN, tester=FakeTester())
+ with TestClient(save_app) as client:
+ saved = client.put(
+ "/api/v1/connection",
+ headers=_headers(),
+ json={
+ "server_url": "https://gms.example.com",
+ "token": "datahub-secret",
+ "write_proof": True,
+ },
+ )
+ assert saved.status_code == 503
+ assert saved.json()["error"]["code"] == "CONTROL_STATE_UNAVAILABLE"
+
+
+def test_control_cli_initializes_reopens_serves_and_reports_bounded_failures(
+ tmp_path: Path,
+ monkeypatch: pytest.MonkeyPatch,
+ capsys: pytest.CaptureFixture[str],
+) -> None:
+ database = tmp_path / "control.sqlite3"
+ master_key_env = "GLASSBOX_TEST_CONTROL_MASTER_KEY"
+ api_token_env = "GLASSBOX_TEST_CONTROL_API_TOKEN"
+ monkeypatch.setenv(master_key_env, SecretBox.generate_base64url())
+ monkeypatch.setenv(api_token_env, API_TOKEN)
+
+ assert control_main(["master-key"]) == 0
+ generated = capsys.readouterr().out.strip()
+ assert SecretBox.from_base64url(generated).key_id == "control-v1"
+
+ common = [
+ "--database",
+ str(database),
+ "--organization",
+ "test-org",
+ "--master-key-env",
+ master_key_env,
+ ]
+ assert control_main(["init", *common]) == 0
+ initialized = json.loads(capsys.readouterr().out)
+ assert initialized["initialized"] is True
+ assert initialized["raw_content_returned"] is False
+
+ assert control_main(["init", *common, "--if-needed"]) == 0
+ reopened = json.loads(capsys.readouterr().out)
+ assert reopened["initialized"] is False
+
+ uvicorn_calls: list[dict[str, Any]] = []
+
+ def fake_run(app: Any, **kwargs: Any) -> None:
+ uvicorn_calls.append({"app": app, **kwargs})
+
+ monkeypatch.setattr("uvicorn.run", fake_run)
+ assert (
+ control_main(
+ [
+ "serve",
+ *common,
+ "--bind",
+ "127.0.0.2",
+ "--port",
+ "9876",
+ "--api-token-env",
+ api_token_env,
+ ]
+ )
+ == 0
+ )
+ assert uvicorn_calls[0]["host"] == "127.0.0.2"
+ assert uvicorn_calls[0]["port"] == 9876
+ assert uvicorn_calls[0]["access_log"] is False
+
+ monkeypatch.delenv(master_key_env)
+ assert control_main(["serve", *common, "--api-token-env", api_token_env]) == 2
+ failure = json.loads(capsys.readouterr().err)
+ assert failure == {
+ "error_type": "ValueError",
+ "raw_content_returned": False,
+ "valid": False,
+ }
+
+
+@pytest.mark.parametrize(
+ "value",
+ [
+ "datahub.example.com",
+ "ftp://datahub.example.com",
+ "https://user:pass@datahub.example.com",
+ "https://datahub.example.com/api/graphql",
+ "https://datahub.example.com?token=nope",
+ ],
+)
+def test_datahub_origins_reject_ambiguous_or_credentialed_urls(value: str) -> None:
+ with pytest.raises(ValueError):
+ normalize_datahub_url(value, label="DataHub URL")
+
+
+def test_datahub_server_version_accepts_known_config_shapes() -> None:
+ assert datahub_module._server_version(None) is None
+ assert datahub_module._server_version({"datahub": {"version": "1.6.0"}}) == "1.6.0"
+ assert datahub_module._server_version({"versions": {"acryldata/datahub": "1.5.0"}}) == "1.5.0"
+ assert datahub_module._server_version({"version": "1.4.0"}) == "1.4.0"
+ assert datahub_module._server_version({}) is None
diff --git a/tests/unit/test_flagship_demo.py b/tests/unit/test_flagship_demo.py
new file mode 100644
index 0000000..3d9e5c9
--- /dev/null
+++ b/tests/unit/test_flagship_demo.py
@@ -0,0 +1,259 @@
+"""Contracts for the isolated one-command flagship estate."""
+
+from __future__ import annotations
+
+import argparse
+import hashlib
+import json
+import subprocess
+from pathlib import Path
+
+import pytest
+from examples.flagship_demo import (
+ _REQUIRED_COMPOSE_MARKERS,
+ EstatePorts,
+ EstateRunError,
+ _compose_base,
+ _load_upstream_compose,
+ _parse_last_json_object,
+ _validate_flagship_report,
+ run_flagship_estate,
+)
+
+ROOT = Path(__file__).resolve().parents[2]
+LIVE_REPORT = ROOT / "docs" / "compatibility" / "datahub-1.6.0-flagship-causal-recovery.live.json"
+ONE_COMMAND_REPORT = (
+ ROOT / "docs" / "compatibility" / "datahub-1.6.0-one-command-flagship.live.json"
+)
+
+
+def _compose_fixture() -> bytes:
+ return b"\n".join(_REQUIRED_COMPOSE_MARKERS) + b"\n"
+
+
+def _args(tmp_path: Path, compose_file: Path, output: Path) -> argparse.Namespace:
+ return argparse.Namespace(
+ allow_live=True,
+ state_dir=tmp_path / "state",
+ output=output,
+ compose_file=compose_file,
+ docker=Path("/bin/echo"),
+ uvx=Path("/bin/echo"),
+ keep_estate=False,
+ wait_timeout_seconds=30,
+ proof_run_offset_ms=0,
+ gms_port=18080,
+ frontend_port=19002,
+ otlp_port=14319,
+ kafka_port=19092,
+ mysql_port=13306,
+ opensearch_port=19200,
+ postgres_port=15432,
+ )
+
+
+def test_estate_ports_reject_invalid_or_overlapping_publications() -> None:
+ assert EstatePorts().gms == 18080
+ with pytest.raises(ValueError, match="between 1 and 65535"):
+ EstatePorts(gms=0)
+ with pytest.raises(ValueError, match="must be unique"):
+ EstatePorts(gms=19002)
+
+
+def test_local_compose_override_is_validated_hashed_and_copied(tmp_path: Path) -> None:
+ source = tmp_path / "source.yml"
+ destination = tmp_path / "runtime" / "datahub.yml"
+ value = _compose_fixture()
+ source.write_bytes(value)
+
+ source_kind, digest = _load_upstream_compose(
+ destination,
+ local_override=source,
+ )
+
+ assert source_kind == "LOCAL_OVERRIDE"
+ assert digest == hashlib.sha256(value).hexdigest()
+ assert destination.read_bytes() == value
+
+ source.write_text("services: {}\n", encoding="utf-8")
+ with pytest.raises(RuntimeError, match="missing required service contracts"):
+ _load_upstream_compose(destination, local_override=source)
+
+
+def test_compose_command_uses_exact_project_and_both_files(tmp_path: Path) -> None:
+ command = _compose_base(
+ Path("/bin/echo"),
+ tmp_path / "upstream.yml",
+ tmp_path / "overlay.yml",
+ )
+
+ assert command[:4] == ("/bin/echo", "compose", "--project-name", "glassbox-flagship")
+ assert command.count("--file") == 2
+ assert command[-2:] == ("--profile", "quickstart")
+
+
+def test_child_json_parser_ignores_build_logs_but_requires_final_object() -> None:
+ assert _parse_last_json_object('build {not-json}\n{"valid": true}\n') == {"valid": True}
+ with pytest.raises(RuntimeError, match="did not finish with a JSON object"):
+ _parse_last_json_object("build complete")
+
+
+def test_committed_live_report_satisfies_one_command_acceptance_boundary() -> None:
+ report = json.loads(LIVE_REPORT.read_text(encoding="utf-8"))
+ _validate_flagship_report(report)
+
+ report["runtime"]["datahub_core_commit"] = "0" * 40
+ with pytest.raises(RuntimeError, match="runtime drifted"):
+ _validate_flagship_report(report)
+
+
+def test_committed_one_command_report_is_raw_free_and_records_cleanup() -> None:
+ report = json.loads(ONE_COMMAND_REPORT.read_text(encoding="utf-8"))
+
+ assert report["valid"]
+ assert report["scenario"] == "GLASSBOX_ONE_COMMAND_FLAGSHIP_ESTATE"
+ assert report["estate"]["compose_project"] == "glassbox-flagship"
+ assert report["estate"]["compose_source"] == "LOCAL_OVERRIDE"
+ assert report["estate"]["cleanup_succeeded"] is True
+ assert report["estate"]["kept_running"] is False
+ assert len(report["estate"]["service_images"]) == 8
+ _validate_flagship_report(report["flagship"])
+ rendered = json.dumps(report, sort_keys=True)
+ assert "/" + "Users/" not in rendered
+ assert "postgresql://" not in rendered
+ assert "glassbox-local-only" not in rendered
+
+
+def test_orchestrator_runs_real_flagship_contract_and_always_cleans_its_project(
+ tmp_path: Path,
+) -> None:
+ compose_file = tmp_path / "upstream.yml"
+ compose_file.write_bytes(_compose_fixture())
+ output = tmp_path / "one-command.json"
+ live = LIVE_REPORT.read_text(encoding="utf-8")
+ commands: list[tuple[str, ...]] = []
+
+ def fake_runner(
+ command: tuple[str, ...],
+ *,
+ cwd: Path,
+ environment: dict[str, str],
+ ) -> subprocess.CompletedProcess[str]:
+ del cwd
+ commands.append(command)
+ assert environment["DATAHUB_VERSION"] == "v1.6.0"
+ assert "GLASSBOX_STATE_POSTGRES_DSN" not in environment or (
+ environment["GLASSBOX_STATE_POSTGRES_DSN"].startswith("postgresql://glassbox:")
+ )
+ if "images" in command:
+ stdout = json.dumps(
+ [
+ {
+ "ContainerName": "glassbox-flagship-datahub-gms-quickstart-1",
+ "Repository": "acryldata/datahub-gms",
+ "Tag": "v1.6.0",
+ "ID": "sha256:synthetic",
+ }
+ ]
+ )
+ elif "scripts.build_replay_sandbox" in command:
+ stdout = json.dumps(
+ {
+ "valid": True,
+ "image_digest": "sha256:" + "a" * 64,
+ "raw_values_retained": False,
+ }
+ )
+ elif "examples.end_to_end_flagship" in command:
+ stdout = live
+ else:
+ stdout = ""
+ return subprocess.CompletedProcess(command, 0, stdout=stdout, stderr="")
+
+ report = run_flagship_estate(
+ _args(tmp_path, compose_file, output),
+ command_runner=fake_runner,
+ )
+
+ assert report["valid"]
+ assert report["estate"]["compose_source"] == "LOCAL_OVERRIDE"
+ assert report["estate"]["cleanup_succeeded"] is True
+ assert report["flagship"]["valid"]
+ assert output.exists()
+ assert any("up" in command for command in commands)
+ assert any("down" in command and "--volumes" in command for command in commands)
+ rendered = output.read_text(encoding="utf-8")
+ assert "glassbox-local-only" not in rendered
+ assert "postgresql://" not in rendered
+
+
+def test_kept_estate_retains_the_exact_live_state_schema(tmp_path: Path) -> None:
+ compose_file = tmp_path / "upstream.yml"
+ compose_file.write_bytes(_compose_fixture())
+ args = _args(tmp_path, compose_file, tmp_path / "kept.json")
+ args.keep_estate = True
+ live = LIVE_REPORT.read_text(encoding="utf-8")
+ commands: list[tuple[str, ...]] = []
+
+ def fake_runner(
+ command: tuple[str, ...],
+ *,
+ cwd: Path,
+ environment: dict[str, str],
+ ) -> subprocess.CompletedProcess[str]:
+ del cwd, environment
+ commands.append(command)
+ if "images" in command:
+ stdout = json.dumps([])
+ elif "scripts.build_replay_sandbox" in command:
+ stdout = json.dumps({"valid": True, "image_digest": "sha256:" + "a" * 64})
+ elif "examples.end_to_end_flagship" in command:
+ stdout = live
+ else:
+ stdout = ""
+ return subprocess.CompletedProcess(command, 0, stdout=stdout, stderr="")
+
+ report = run_flagship_estate(args, command_runner=fake_runner)
+
+ schema = report["estate"]["state_postgres_schema"]
+ assert isinstance(schema, str) and schema.startswith("gbx_console_")
+ child = next(command for command in commands if "examples.end_to_end_flagship" in command)
+ assert child[child.index("--state-postgres-schema") + 1] == schema
+ assert "--keep-state-schema" in child
+ assert not any("down" in command for command in commands)
+
+
+def test_failed_estate_start_is_bounded_and_still_cleans_the_exact_project(
+ tmp_path: Path,
+) -> None:
+ compose_file = tmp_path / "upstream.yml"
+ compose_file.write_bytes(_compose_fixture())
+ commands: list[tuple[str, ...]] = []
+
+ def failing_runner(
+ command: tuple[str, ...],
+ *,
+ cwd: Path,
+ environment: dict[str, str],
+ ) -> subprocess.CompletedProcess[str]:
+ del cwd, environment
+ commands.append(command)
+ if "up" in command:
+ raise subprocess.CalledProcessError(
+ 17,
+ command,
+ output="forbidden-child-output",
+ stderr="forbidden-child-error",
+ )
+ return subprocess.CompletedProcess(command, 0, stdout="", stderr="")
+
+ with pytest.raises(EstateRunError) as raised:
+ run_flagship_estate(
+ _args(tmp_path, compose_file, tmp_path / "failure.json"),
+ command_runner=failing_runner,
+ )
+
+ assert raised.value.stage == "estate-start-and-health"
+ assert "forbidden-child-output" not in str(raised.value)
+ assert "forbidden-child-error" not in str(raised.value)
+ assert any("down" in command and "--volumes" in command for command in commands)
diff --git a/tests/unit/test_forensics_mcp.py b/tests/unit/test_forensics_mcp.py
index 623551b..9c874ec 100644
--- a/tests/unit/test_forensics_mcp.py
+++ b/tests/unit/test_forensics_mcp.py
@@ -7,10 +7,14 @@
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
from mcp.client import Client
+from starlette.testclient import TestClient
from glassbox_dbom import SigningKey, seal_receipt
from glassbox_forensics import ForensicsService
-from glassbox_forensics.live_state import TransactionalCampaignReader
+from glassbox_forensics.live_state import (
+ TransactionalCampaignReader,
+ TransactionalReceiptPublicationReader,
+)
from glassbox_forensics.server import build_server
from glassbox_invalidation import SQLiteInvalidationStore, VerifiedReceiptStore
from glassbox_policy import (
@@ -25,6 +29,59 @@
FIELD = f"urn:li:schemaField:({DATASET},revenue)"
+def test_loopback_console_api_reads_service_state_without_bundled_success(
+ tmp_path: Path,
+) -> None:
+ payload = receipt_payload()
+ payload["evidence"][0]["schema_field_urn"] = FIELD
+ receipt = seal_receipt(
+ payload,
+ signing_keys=[SigningKey("console-api-key", Ed25519PrivateKey.generate())],
+ )
+ store = VerifiedReceiptStore(tmp_path / "console-receipts.jsonl", sync=False)
+ store.register(receipt)
+ server = build_server(ForensicsService(store, artifacts=store))
+ app = server.streamable_http_app(stateless_http=True, json_response=True)
+
+ with TestClient(app) as client:
+ health = client.get("/health")
+ overview = client.get("/api/v1/overview")
+ receipts = client.get("/api/v1/receipts", params={"query": "commerce.orders"})
+ detail = client.get(f"/api/v1/receipts/{receipt['receipt_id']}")
+ invalid = client.get("/api/v1/receipts", params={"offset": -1})
+
+ assert health.status_code == 200
+ assert health.json()["contract_version"] == "glassbox.console-api.v1"
+ assert overview.json()["counts"]["receipts"] == 1
+ assert overview.json()["availability"]["campaign_store"] == "NOT_CONFIGURED"
+ assert receipts.json()["total"] == 1
+ assert receipts.json()["decisions"][0]["receipt_id"] == receipt["receipt_id"]
+ assert detail.json()["verification"]["verification_state"] == "VERIFIED_NOW"
+ assert detail.json()["influence"]["raw_content_returned"] is False
+ assert invalid.status_code == 400
+ assert invalid.json()["error"]["code"] == "INVALID_ARGUMENT"
+
+
+def test_console_api_bearer_auth_protects_every_read_route(tmp_path: Path) -> None:
+ store = VerifiedReceiptStore(tmp_path / "protected-receipts.jsonl", sync=False)
+ server = build_server(
+ ForensicsService(store, artifacts=store),
+ http_bearer_token="private-forensics-token",
+ )
+ app = server.streamable_http_app(stateless_http=True, json_response=True)
+
+ with TestClient(app) as client:
+ rejected = client.get("/api/v1/overview")
+ accepted = client.get(
+ "/api/v1/overview",
+ headers={"authorization": "Bearer private-forensics-token"},
+ )
+
+ assert rejected.status_code == 401
+ assert rejected.json()["error"]["code"] == "UNAUTHENTICATED"
+ assert accepted.status_code == 200
+
+
def test_official_client_discovers_only_read_only_tools_and_calls_every_contract(
tmp_path: Path,
) -> None:
@@ -67,6 +124,7 @@ async def scenario() -> None:
store,
artifacts=store,
findings=TransactionalCampaignReader(store),
+ publications=TransactionalReceiptPublicationReader(store),
)
)
@@ -75,6 +133,7 @@ async def scenario() -> None:
assert [tool.name for tool in discovered.tools] == [
"verify_decision_receipt",
"get_decision_influence",
+ "get_decision_publication",
"classify_decision_impact",
"list_affected_decisions",
"get_invalidation_campaign",
@@ -92,6 +151,9 @@ async def scenario() -> None:
influence = await client.call_tool(
"get_decision_influence", {"receipt_id": receipt["receipt_id"]}
)
+ publication = await client.call_tool(
+ "get_decision_publication", {"receipt_id": receipt["receipt_id"]}
+ )
change = {
"event_id": "mcl-schema-001",
"entity_urn": DATASET,
@@ -115,6 +177,8 @@ async def scenario() -> None:
assert verified.is_error is False
assert verified.structured_content["verification_state"] == "VERIFIED_NOW"
assert influence.structured_content["raw_content_returned"] is False
+ assert publication.structured_content["availability"] == "AVAILABLE"
+ assert publication.structured_content["durability"]["workflow_status"] == "READY"
assert impact.structured_content["assessment"]["state"] == "STALE"
assert reverse.structured_content["review_required_total"] == 1
assert reverse.structured_content["scan_complete"] is True
diff --git a/tests/unit/test_forensics_mcp_capture.py b/tests/unit/test_forensics_mcp_capture.py
new file mode 100644
index 0000000..0584f80
--- /dev/null
+++ b/tests/unit/test_forensics_mcp_capture.py
@@ -0,0 +1,56 @@
+"""Closed-surface tests for the filmed live MCP investigation helper."""
+
+from __future__ import annotations
+
+from scripts.forensics_mcp_capture import QUESTION, _latest_flagship_campaign, render
+from scripts.remote_forensics_mcp_capture import REMOTE_COMMAND
+from scripts.remote_forensics_mcp_capture import main as remote_main
+
+
+def _campaign() -> dict[str, object]:
+ return {
+ "campaign_id": "gbx:invalidation:sha256:" + "a" * 64,
+ "change": {
+ "entity_urn": ("urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)"),
+ "kind": "SCHEMA_FIELD_TYPE_CHANGED",
+ "schema_field_urn": "urn:li:schemaField:(commerce.orders,average_order_value)",
+ },
+ "processing": {
+ "workflow_status": "COMPLETED",
+ "datahub_writeback_state": "VERIFIED",
+ },
+ }
+
+
+def test_campaign_discovery_selects_only_completed_verified_flagship() -> None:
+ selected = _latest_flagship_campaign({"campaigns": [_campaign()]})
+ assert selected["campaign_id"] == "gbx:invalidation:sha256:" + "a" * 64
+
+
+def test_render_is_raw_free_and_names_the_real_mcp_question() -> None:
+ output = render(
+ {
+ "protocol": "2025-11-25",
+ "tool_count": 7,
+ "change_kind": "SCHEMA_FIELD_TYPE_CHANGED",
+ "affected_count": 2,
+ "receipts": ["gbx:receipt:sha256:" + "b" * 64],
+ "states": ["STALE"],
+ "reasons": ["EXACT_FIELD_DEPENDENCY"],
+ "verification": "VERIFIED_NOW",
+ "dependency_state": "OBSERVED",
+ "campaign_id": "gbx:invalidation:sha256:" + "a" * 64,
+ "workflow": "COMPLETED",
+ "writeback": "VERIFIED",
+ }
+ )
+ assert QUESTION in output
+ assert "AUTHENTICATED Β· READ ONLY" in output
+ assert "Raw content NOT RETURNED" in output
+
+
+def test_remote_wrapper_has_no_mutation_or_secret_arguments() -> None:
+ assert remote_main(["--campaign-id", "anything"]) == 2
+ assert "forensics_mcp_capture.py" in REMOTE_COMMAND
+ assert "GLASSBOX_FORENSICS_API_TOKEN" not in REMOTE_COMMAND
+ assert "guarded_schema_change" not in REMOTE_COMMAND
diff --git a/tests/unit/test_forensics_service.py b/tests/unit/test_forensics_service.py
index 40e45d5..a4413c7 100644
--- a/tests/unit/test_forensics_service.py
+++ b/tests/unit/test_forensics_service.py
@@ -8,10 +8,15 @@
import pytest
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
+from glassbox_datahub import receipt_document_urn
from glassbox_dbom import SigningKey, seal_receipt
from glassbox_forensics import ForensicsInputError, ForensicsNotFoundError, ForensicsService
-from glassbox_forensics.live_state import TransactionalCampaignReader
+from glassbox_forensics.live_state import (
+ TransactionalCampaignReader,
+ TransactionalReceiptPublicationReader,
+)
from glassbox_invalidation import SQLiteInvalidationStore, VerifiedReceiptStore
+from glassbox_invalidation.transactional_store import ReceiptPublicationEvidence
from glassbox_policy import (
ChangeKind,
InvalidationWriteEvidence,
@@ -166,6 +171,9 @@ def test_live_campaign_findings_come_from_shared_transactional_state(tmp_path: P
persisted = service.get_invalidation_campaign(campaign.campaign_id)
findings = service.list_decision_findings(receipt["receipt_id"])
+ overview = service.get_console_overview()
+ decisions = service.list_decisions(query="commerce.orders")
+ campaigns = service.list_invalidation_campaigns()
assert persisted["availability"] == "AVAILABLE"
assert persisted["campaign"]["processing"] == {
@@ -180,8 +188,73 @@ def test_live_campaign_findings_come_from_shared_transactional_state(tmp_path: P
assert findings["findings_total"] == 1
assert findings["findings"][0]["campaign_id"] == campaign.campaign_id
assert findings["findings"][0]["assessment"]["state"] == "STALE"
+ assert overview["counts"] == {
+ "receipts": 1,
+ "dependencies": 1,
+ "unresolved_dependencies": 0,
+ "campaigns": 1,
+ "review_required": 1,
+ }
+ assert overview["state_counts"] == {"STALE": 1}
+ assert decisions["total"] == 1
+ assert decisions["decisions"][0]["state"] == "STALE"
+ assert decisions["decisions"][0]["latest_finding"]["campaign_id"] == campaign.campaign_id
+ assert campaigns["availability"] == "AVAILABLE"
+ assert campaigns["campaigns"][0]["campaign_id"] == campaign.campaign_id
assert secret not in repr(persisted)
assert secret not in repr(findings)
+ assert secret not in repr(overview)
+ assert secret not in repr(decisions)
+ assert secret not in repr(campaigns)
+
+
+def test_publication_proof_comes_from_sealed_transactional_state(tmp_path: Path) -> None:
+ receipt = _signed_receipt(secret="never-return-publication-secret")
+ receipt_id = receipt["receipt_id"]
+ store = SQLiteInvalidationStore(tmp_path / "publication-state.sqlite3")
+ store.register(receipt)
+ claimed = store.claim_receipt_publication(
+ receipt_id,
+ worker_id="receipt-publisher",
+ now_ms=1,
+ lease_duration_ms=10_000,
+ )
+ assert claimed is not None
+ store.complete_receipt_publication(
+ receipt_id,
+ ReceiptPublicationEvidence(
+ document_urn=receipt_document_urn(receipt_id),
+ aspect_names=("documentInfo", "globalTags", "status"),
+ ),
+ worker_id="receipt-publisher",
+ )
+ service = ForensicsService(
+ store,
+ artifacts=store,
+ publications=TransactionalReceiptPublicationReader(
+ store,
+ durability_authority="POSTGRESQL",
+ ),
+ )
+
+ publication = service.get_decision_publication(receipt_id)
+
+ assert publication["availability"] == "AVAILABLE"
+ assert publication["durability"] == {
+ "authority": "POSTGRESQL",
+ "workflow_status": "COMPLETED",
+ "attempt_count": 1,
+ "last_error_recorded": False,
+ "sealed_evidence": True,
+ }
+ assert publication["datahub"] == {
+ "document_urn": receipt_document_urn(receipt_id),
+ "aspect_names": ["documentInfo", "globalTags", "status"],
+ "aspect_count": 3,
+ "emission_count": 2,
+ }
+ assert publication["raw_content_returned"] is False
+ assert "never-return-publication-secret" not in repr(publication)
def test_campaign_tools_expose_unavailable_state_without_inventing_history(
@@ -193,9 +266,17 @@ def test_campaign_tools_expose_unavailable_state_without_inventing_history(
campaign = service.get_invalidation_campaign(campaign_id)
findings = service.list_decision_findings(receipt["receipt_id"])
+ overview = service.get_console_overview()
+ campaigns = service.list_invalidation_campaigns()
assert campaign["availability"] == "CAMPAIGN_STORE_NOT_CONFIGURED"
assert findings["availability"] == "CAMPAIGN_STORE_NOT_CONFIGURED"
assert findings["scan_complete"] is False
+ assert overview["availability"]["campaign_store"] == "NOT_CONFIGURED"
+ assert overview["state_counts"] == {"NO_RECORDED_FINDING": 1}
+ assert campaigns["availability"] == "CAMPAIGN_STORE_NOT_CONFIGURED"
+ assert campaigns["campaigns"] == []
with pytest.raises(ForensicsInputError, match="campaign_id"):
service.get_invalidation_campaign("not-a-campaign")
+ with pytest.raises(ForensicsInputError, match="offset"):
+ service.list_decisions(offset=-1)
diff --git a/tests/unit/test_guarded_schema_change.py b/tests/unit/test_guarded_schema_change.py
new file mode 100644
index 0000000..2255e1c
--- /dev/null
+++ b/tests/unit/test_guarded_schema_change.py
@@ -0,0 +1,117 @@
+"""Closed-surface tests for the filmed production schema-change helper."""
+
+from __future__ import annotations
+
+import json
+
+import pytest
+from datahub.metadata.schema_classes import (
+ AuditStampClass,
+ NumberTypeClass,
+ OtherSchemaClass,
+ SchemaFieldClass,
+ SchemaFieldDataTypeClass,
+ SchemaMetadataClass,
+)
+
+from glassbox_policy import ChangeKind, NormalizedChange
+from scripts.guarded_schema_change import (
+ ACTOR_URN,
+ DEMO_AFTER_TYPE,
+ FIELD_PATH,
+ SCHEMA_FIELD_URN,
+ GuardedChangeError,
+ _allowlisted_change,
+ _changed_schema,
+ _operator_graph,
+ _parser,
+)
+from scripts.remote_guarded_schema_change import REMOTE_COMMAND
+from scripts.remote_guarded_schema_change import main as remote_main
+
+
+def _schema(native_type: str = "decimal(18,2)") -> SchemaMetadataClass:
+ raw = json.dumps(
+ {
+ "fields": [
+ {"name": "order_id", "type": "varchar(64)"},
+ {"name": FIELD_PATH, "type": native_type},
+ ]
+ }
+ )
+ audit = AuditStampClass(time=1, actor=ACTOR_URN)
+ return SchemaMetadataClass(
+ schemaName="commerce.orders",
+ platform="urn:li:dataPlatform:postgres",
+ version=0,
+ hash="a" * 64,
+ platformSchema=OtherSchemaClass(rawSchema=raw),
+ fields=[
+ SchemaFieldClass(
+ fieldPath=FIELD_PATH,
+ type=SchemaFieldDataTypeClass(type=NumberTypeClass()), # type: ignore[no-untyped-call]
+ nativeDataType=native_type,
+ nullable=False,
+ )
+ ],
+ created=audit,
+ lastModified=audit,
+ )
+
+
+def test_change_is_fixed_consistent_and_does_not_mutate_source() -> None:
+ source = _schema()
+ changed = _changed_schema(source, changed_at_ms=1000)
+
+ assert source.fields[0].nativeDataType == "decimal(18,2)"
+ assert changed.fields[0].nativeDataType == DEMO_AFTER_TYPE
+ assert changed.fields[0].type.type.__class__.__name__ == "StringTypeClass"
+ assert json.loads(changed.platformSchema.rawSchema)["fields"][1]["type"] == DEMO_AFTER_TYPE
+ assert changed.hash != source.hash
+
+
+def test_change_rejects_drift_and_cli_accepts_no_mutation_parameters() -> None:
+ with pytest.raises(GuardedChangeError, match="expected pre-change"):
+ _changed_schema(_schema("varchar(64)"), changed_at_ms=1000)
+ with pytest.raises(SystemExit):
+ _parser().parse_args(["apply", "--server", "https://example.com"])
+ assert remote_main(["--server", "https://example.com"]) == 2
+ assert "guarded_schema_change.py apply" in REMOTE_COMMAND
+ assert "DATAHUB_GMS_TOKEN" not in REMOTE_COMMAND
+ assert "DATAHUB_SYSTEM_CLIENT_SECRET" in REMOTE_COMMAND
+ assert 'GLASSBOX_DATAHUB_OPERATOR_CLIENT_SECRET="$datahub_operator_secret"' in REMOTE_COMMAND
+
+
+def test_operator_graph_requires_a_separate_one_shot_credential(
+ monkeypatch: pytest.MonkeyPatch,
+) -> None:
+ monkeypatch.delenv("GLASSBOX_DATAHUB_OPERATOR_CLIENT_ID", raising=False)
+ monkeypatch.delenv("GLASSBOX_DATAHUB_OPERATOR_CLIENT_SECRET", raising=False)
+ with pytest.raises(GuardedChangeError, match="one-shot DataHub operator credential"):
+ _operator_graph("http://datahub-gms:8080")
+
+
+def test_resume_filter_accepts_only_the_fixed_schema_field_change() -> None:
+ change = NormalizedChange(
+ event_id="datahub:mcl:sha256:" + "1" * 64,
+ entity_urn="urn:li:dataset:(urn:li:dataPlatform:postgres,commerce.orders,PROD)",
+ aspect_name="schemaMetadata",
+ kind=ChangeKind.SCHEMA_FIELD_TYPE_CHANGED,
+ occurred_at="2026-08-10T20:00:00Z",
+ schema_field_urn=SCHEMA_FIELD_URN,
+ before_digest="2" * 64,
+ after_digest="3" * 64,
+ )
+ assert _allowlisted_change(change)
+
+ drifted = NormalizedChange(
+ event_id=change.event_id,
+ entity_urn=change.entity_urn,
+ aspect_name=change.aspect_name,
+ kind=change.kind,
+ occurred_at=change.occurred_at,
+ schema_field_urn=str(SCHEMA_FIELD_URN).replace("average_order_value", "customer_email"),
+ before_digest=change.before_digest,
+ after_digest=change.after_digest,
+ )
+ assert not _allowlisted_change(drifted)
diff --git a/tests/unit/test_production_edge.py b/tests/unit/test_production_edge.py
new file mode 100644
index 0000000..136297f
--- /dev/null
+++ b/tests/unit/test_production_edge.py
@@ -0,0 +1,68 @@
+from pathlib import Path
+
+ROOT = Path(__file__).resolve().parents[2]
+
+
+def test_oauth_identity_bridge_preserves_security_order() -> None:
+ caddyfile = (ROOT / "deploy" / "production" / "Caddyfile").read_text()
+ fallback = caddyfile[caddyfile.index("\thandle @console_host {") :]
+
+ assert "\t\troute {" in fallback
+ assert fallback.index("request_header -X-Auth-Request-User") < fallback.index(
+ "forward_auth oauth2-proxy:4180"
+ )
+ assert fallback.index("forward_auth oauth2-proxy:4180") < fallback.index(
+ "reverse_proxy console:3000"
+ )
+ assert "copy_headers X-Auth-Request-User X-Auth-Request-Email" in fallback
+
+
+def test_non_human_endpoints_bypass_oauth() -> None:
+ caddyfile = (ROOT / "deploy" / "production" / "Caddyfile").read_text()
+ oauth_fallback = caddyfile.index("forward_auth oauth2-proxy:4180")
+
+ assert caddyfile.index("handle /healthz") < oauth_fallback
+ assert caddyfile.index("@otlp path /v1/traces") < oauth_fallback
+ assert "redir * /oauth2/sign_in?rd={uri}" in caddyfile
+
+
+def test_public_surface_is_allowlisted_away_from_operator_and_control_routes() -> None:
+ caddyfile = (ROOT / "deploy" / "production" / "Caddyfile").read_text()
+ public_surface = caddyfile[
+ caddyfile.index("\t@public_surface {") : caddyfile.index("\t@public_unknown")
+ ]
+
+ assert "host {$GLASSBOX_PUBLIC_DOMAIN}" in public_surface
+ assert "/docs /docs/* /architecture" in public_surface
+ assert "/api" not in public_surface
+ assert "/settings" not in public_surface
+ assert "request_header -X-Auth-Request-User" in public_surface
+ assert "@public_unknown host {$GLASSBOX_PUBLIC_DOMAIN}" in caddyfile
+ assert "@console_host host {$GLASSBOX_CONSOLE_DOMAIN}" in caddyfile
+ assert caddyfile.rstrip().endswith("}")
+ assert "respond 421" in caddyfile
+
+
+def test_receiver_reads_the_control_plane_organization() -> None:
+ compose = (ROOT / "deploy" / "production" / "compose.yml").read_text()
+ receiver = compose[compose.index(" receiver:\n") :]
+
+ assert "- --control-database" in receiver
+ assert "- --control-organization" in receiver
+ assert "- ${GLASSBOX_ORGANIZATION:-default}" in receiver
+
+
+def test_compose_binds_public_and_console_hosts_to_distinct_boundaries() -> None:
+ compose = (ROOT / "deploy" / "production" / "compose.yml").read_text()
+
+ assert (
+ "GLASSBOX_PUBLIC_DOMAIN: ${GLASSBOX_PUBLIC_DOMAIN:?set GLASSBOX_PUBLIC_DOMAIN}" in compose
+ )
+ assert (
+ "GLASSBOX_CONSOLE_DOMAIN: ${GLASSBOX_CONSOLE_DOMAIN:?set GLASSBOX_CONSOLE_DOMAIN}"
+ in compose
+ )
+ assert "GLASSBOX_PUBLIC_HOSTS: ${GLASSBOX_PUBLIC_DOMAIN:?set GLASSBOX_PUBLIC_DOMAIN}" in compose
+ assert (
+ "https://${GLASSBOX_CONSOLE_DOMAIN:?set GLASSBOX_CONSOLE_DOMAIN}/oauth2/callback" in compose
+ )
diff --git a/tests/unit/test_receiver_entrypoint.py b/tests/unit/test_receiver_entrypoint.py
index c87e255..905788b 100644
--- a/tests/unit/test_receiver_entrypoint.py
+++ b/tests/unit/test_receiver_entrypoint.py
@@ -176,6 +176,53 @@ def __init__(self, backend: object, *, signer_trust_policy: object) -> None:
assert backend_calls == ["tested"]
+def test_receiver_waits_for_live_dependencies_during_production_onboarding(
+ monkeypatch: pytest.MonkeyPatch,
+ capsys: pytest.CaptureFixture[str],
+) -> None:
+ attempts = 0
+ sleeps: list[float] = []
+
+ def load(_: Namespace) -> tuple[int, int, int, int]:
+ nonlocal attempts
+ attempts += 1
+ if attempts == 1:
+ raise ValueError("connection not configured")
+ return (1, 2, 3, 4)
+
+ monkeypatch.setattr(receiver_module, "_live_components", load)
+ monkeypatch.setattr(receiver_module.time, "sleep", sleeps.append)
+
+ selected = receiver_module._startup_live_components(
+ Namespace(command="serve", startup_retry_seconds=0.25)
+ )
+
+ report = json.loads(capsys.readouterr().err)
+ assert selected == (1, 2, 3, 4)
+ assert attempts == 2
+ assert sleeps == [0.25]
+ assert report["state"] == "WAITING_FOR_LIVE_DEPENDENCIES"
+ assert report["error_type"] == "ValueError"
+ assert report["raw_content_returned"] is False
+
+
+def test_receiver_startup_retry_is_opt_in(monkeypatch: pytest.MonkeyPatch) -> None:
+ monkeypatch.setattr(
+ receiver_module,
+ "_live_components",
+ lambda _: (_ for _ in ()).throw(ValueError("connection not configured")),
+ )
+
+ with pytest.raises(ValueError, match="connection not configured"):
+ receiver_module._startup_live_components(
+ Namespace(command="serve", startup_retry_seconds=0.0)
+ )
+ with pytest.raises(ValueError, match="cannot be negative"):
+ receiver_module._startup_live_components(
+ Namespace(command="serve", startup_retry_seconds=-1.0)
+ )
+
+
@pytest.mark.parametrize("fail", [False, True])
def test_drain_entrypoint_reports_bounded_completion(
fail: bool,
@@ -419,6 +466,25 @@ def test_handler_requires_exact_content_length_and_object_envelope() -> None:
assert non_object_responses[0][1] == "InvalidOTLPRequest"
+def test_handler_accepts_only_active_control_plane_ingestion_keys() -> None:
+ valid = "gbx_ingest_active"
+ handler, responses = _direct_handler(
+ object(),
+ headers={"Authorization": f"Bearer {valid}"},
+ config=OTLPReceiverConfig(bearer_token_validator=lambda token: token == valid),
+ )
+ handler.do_POST()
+ assert responses[0][1] != "Unauthorized"
+
+ rejected, rejected_responses = _direct_handler(
+ object(),
+ headers={"Authorization": "Bearer gbx_ingest_revoked"},
+ config=OTLPReceiverConfig(bearer_token_validator=lambda token: token == valid),
+ )
+ rejected.do_POST()
+ assert rejected_responses[0][1] == "Unauthorized"
+
+
@pytest.mark.parametrize(
("failure", "expected"),
[
diff --git a/tests/unit/test_remote_otlp_capture.py b/tests/unit/test_remote_otlp_capture.py
new file mode 100644
index 0000000..33a597f
--- /dev/null
+++ b/tests/unit/test_remote_otlp_capture.py
@@ -0,0 +1,196 @@
+"""Tests for the bounded hosted OTLP filming helper."""
+
+from __future__ import annotations
+
+import json
+from datetime import UTC, datetime
+from pathlib import Path
+from typing import Any, ClassVar
+
+import pytest
+
+from glassbox_compiler import CompilationProfile, Environment, compile_otlp_json
+from glassbox_dbom import verify_receipt
+from scripts import remote_otlp_capture
+
+
+def _response(*, registration: str = "INSERTED", write_performed: bool = True) -> bytes:
+ return json.dumps(
+ {
+ "valid": True,
+ "code": "ReceiptPublished",
+ "raw_content_returned": False,
+ "detail": {
+ "valid": True,
+ "receipt_id": "gbx:receipt:sha256:" + "a" * 64,
+ "state": {
+ "registration": registration,
+ "readback_verified": True,
+ "field_lineage": {
+ "coverage": "ASSET_ONLY",
+ "rule_id": "glassbox.asset-lineage.v1",
+ "wildcard_query": False,
+ },
+ },
+ "datahub": {
+ "valid": True,
+ "receipt_id": "gbx:receipt:sha256:" + "a" * 64,
+ "document_urn": "urn:li:document:glassbox.receipt." + "a" * 64,
+ "aspect_names": ["documentInfo", "documentKey"],
+ "emissions": 2,
+ },
+ "publication": {
+ "attempt_count": 1,
+ "datahub_write_performed": write_performed,
+ },
+ "raw_content_returned": False,
+ },
+ }
+ ).encode()
+
+
+def test_capture_payload_executes_real_agent_and_compiles_raw_free() -> None:
+ body = remote_otlp_capture.build_capture_payload(
+ "devpost-03b-test",
+ started_at=datetime(2026, 8, 10, 12, 0, tzinfo=UTC),
+ )
+ payload = json.loads(body)
+ spans = payload["resourceSpans"][0]["scopeSpans"][0]["spans"]
+ receipt = compile_otlp_json(
+ payload,
+ profile=CompilationProfile(
+ environment=Environment.DEV,
+ output_kind="pricing-recommendation",
+ output_mime_type="application/json",
+ ),
+ )
+
+ assert len(spans) == 2
+ assert verify_receipt(receipt).valid
+ assert receipt["agent"]["id"] == "glassbox.demo.pricing-agent"
+ assert receipt["evidence"][0]["datahub_urn"].endswith("commerce.orders,PROD)")
+ assert b"demo-secret" not in body
+ assert b"authorization" not in body.lower()
+ assert b"synthetic-devpost-customer" not in body
+
+
+def test_capture_payload_is_deterministic_for_label_and_start_time() -> None:
+ started_at = datetime(2026, 8, 10, 12, 0, tzinfo=UTC)
+ first = remote_otlp_capture.build_capture_payload("devpost-a", started_at=started_at)
+ second = remote_otlp_capture.build_capture_payload("devpost-a", started_at=started_at)
+ different = remote_otlp_capture.build_capture_payload("devpost-b", started_at=started_at)
+
+ assert first == second
+ assert first != different
+
+
+def test_capture_payload_file_is_created_once_and_exactly_reused(tmp_path: Path) -> None:
+ started_at = datetime(2026, 8, 10, 12, 0, tzinfo=UTC)
+ first = remote_otlp_capture.load_or_create_capture_payload(
+ "devpost-file",
+ directory=tmp_path,
+ started_at=started_at,
+ )
+ second = remote_otlp_capture.load_or_create_capture_payload(
+ "devpost-file",
+ directory=tmp_path,
+ started_at=datetime(2026, 8, 11, 12, 0, tzinfo=UTC),
+ )
+
+ assert first.created is True
+ assert second.created is False
+ assert first.body == second.body == first.path.read_bytes()
+ assert first.sha256 == second.sha256
+ assert first.path.stat().st_mode & 0o777 == 0o600
+
+
+class _FakeResponse:
+ def __init__(self, status: int, body: bytes) -> None:
+ self.status = status
+ self._body = body
+
+ def read(self, limit: int) -> bytes:
+ return self._body[:limit]
+
+
+class _FakeConnection:
+ instances: ClassVar[list[_FakeConnection]] = []
+ response: ClassVar[_FakeResponse] = _FakeResponse(200, _response())
+
+ def __init__(self, host: str, port: int, timeout: int) -> None:
+ self.host = host
+ self.port = port
+ self.timeout = timeout
+ self.request_data: dict[str, Any] = {}
+ self.closed = False
+ self.instances.append(self)
+
+ def request(
+ self,
+ method: str,
+ path: str,
+ *,
+ body: bytes,
+ headers: dict[str, str],
+ ) -> None:
+ self.request_data = {"method": method, "path": path, "body": body, "headers": headers}
+
+ def getresponse(self) -> _FakeResponse:
+ return self.response
+
+ def close(self) -> None:
+ self.closed = True
+
+
+def test_sender_uses_fixed_tls_endpoint_and_returns_bounded_proof(
+ monkeypatch: pytest.MonkeyPatch,
+) -> None:
+ _FakeConnection.instances.clear()
+ _FakeConnection.response = _FakeResponse(200, _response())
+ monkeypatch.setattr(remote_otlp_capture, "HTTPSConnection", _FakeConnection)
+ body = remote_otlp_capture.build_capture_payload(
+ "devpost-send",
+ started_at=datetime(2026, 8, 10, 12, 0, tzinfo=UTC),
+ )
+
+ proof = remote_otlp_capture.send_capture_payload(body, "x" * 48)
+
+ connection = _FakeConnection.instances[0]
+ assert (connection.host, connection.port, connection.timeout) == ("glassboxhq.xyz", 443, 30)
+ assert connection.request_data["method"] == "POST"
+ assert connection.request_data["path"] == "/v1/traces"
+ assert connection.request_data["body"] == body
+ assert connection.request_data["headers"]["Authorization"] == "Bearer " + "x" * 48
+ assert connection.closed is True
+ assert proof.registration == "INSERTED"
+ assert proof.datahub_write_performed is True
+
+
+def test_sender_failure_is_sanitized_and_never_echoes_key(
+ monkeypatch: pytest.MonkeyPatch,
+) -> None:
+ _FakeConnection.instances.clear()
+ _FakeConnection.response = _FakeResponse(
+ 401,
+ json.dumps(
+ {"valid": False, "code": "Unauthorized", "raw_content_returned": False}
+ ).encode(),
+ )
+ monkeypatch.setattr(remote_otlp_capture, "HTTPSConnection", _FakeConnection)
+ token = "super-secret-ingestion-key-" + "x" * 32
+ body = remote_otlp_capture.build_capture_payload(
+ "devpost-reject",
+ started_at=datetime(2026, 8, 10, 12, 0, tzinfo=UTC),
+ )
+
+ with pytest.raises(remote_otlp_capture.RemoteCaptureError) as raised:
+ remote_otlp_capture.send_capture_payload(body, token)
+
+ assert "HTTP 401 Β· Unauthorized" in str(raised.value)
+ assert token not in str(raised.value)
+
+
+@pytest.mark.parametrize("capture_id", ["", "UPPER", "bad/slash", "-leading", "trailing-"])
+def test_capture_id_rejects_unsafe_paths(capture_id: str) -> None:
+ with pytest.raises(ValueError, match="capture ID"):
+ remote_otlp_capture.build_capture_payload(capture_id)
diff --git a/tests/unit/test_trusted_receipt_state.py b/tests/unit/test_trusted_receipt_state.py
index a32a6e5..1941565 100644
--- a/tests/unit/test_trusted_receipt_state.py
+++ b/tests/unit/test_trusted_receipt_state.py
@@ -37,6 +37,7 @@ def _policy(
key: SigningKey,
*,
status: SignerStatus = SignerStatus.ACTIVE,
+ not_before: str = "2020-01-01T00:00:00Z",
) -> SignerTrustPolicy:
return SignerTrustPolicy(
policy_id="glassbox-state-test-trust-v1",
@@ -47,7 +48,7 @@ def _policy(
public_key=signing_key_public_key(key),
public_key_sha256=signing_key_fingerprint(key),
status=status,
- not_before="2020-01-01T00:00:00Z",
+ not_before=not_before,
not_after="2100-01-01T00:00:00Z",
),
),
@@ -79,6 +80,32 @@ def test_sqlite_admission_rejects_untrusted_signer_before_receipt_or_outbox_writ
assert report.receipt_publication_tasks == 0
+def test_durable_stores_reject_receipt_from_before_signer_validity_without_writing(
+ tmp_path: Path,
+) -> None:
+ key = SigningKey("future-at-receipt-time", Ed25519PrivateKey.generate())
+ policy = _policy(key, not_before="2026-08-07T00:00:00Z")
+ receipt = _receipt(key, run_id="receipt-before-key-validity")
+
+ sqlite = SQLiteInvalidationStore(
+ tmp_path / "historical-window.sqlite3",
+ signer_trust_policy=policy,
+ )
+ with pytest.raises(PolicyInputError, match="BEFORE_VALIDITY_WINDOW"):
+ sqlite.register(receipt)
+ sqlite_report = sqlite.verify_integrity()
+ assert sqlite_report.receipts == 0
+ assert sqlite_report.dependencies == 0
+ assert sqlite_report.receipt_publication_tasks == 0
+
+ jsonl_path = tmp_path / "historical-window.jsonl"
+ jsonl = VerifiedReceiptStore(jsonl_path, signer_trust_policy=policy)
+ with pytest.raises(PolicyInputError, match="BEFORE_VALIDITY_WINDOW"):
+ jsonl.register(receipt)
+ assert not jsonl_path.exists()
+ assert jsonl.all_profiles() == ()
+
+
def test_sqlite_rotation_keeps_exact_history_but_blocks_new_retired_key_admission(
tmp_path: Path,
) -> None:
diff --git a/uv.lock b/uv.lock
index c5b96f1..368fddf 100644
--- a/uv.lock
+++ b/uv.lock
@@ -953,6 +953,10 @@ dependencies = [
actions = [
{ name = "acryl-datahub-actions" },
]
+control = [
+ { name = "starlette" },
+ { name = "uvicorn" },
+]
datahub = [
{ name = "acryl-datahub" },
]
@@ -992,8 +996,10 @@ requires-dist = [
{ name = "pytest-cov", marker = "extra == 'dev'", specifier = ">=6.2,<8" },
{ name = "rfc8785", specifier = ">=0.1.4,<0.2" },
{ name = "ruff", marker = "extra == 'dev'", specifier = ">=0.12,<0.16" },
+ { name = "starlette", marker = "extra == 'control'", specifier = ">=0.49" },
+ { name = "uvicorn", marker = "extra == 'control'", specifier = ">=0.35,<1" },
]
-provides-extras = ["actions", "datahub", "google-adk", "langchain", "mcp", "postgres", "dev"]
+provides-extras = ["actions", "datahub", "google-adk", "langchain", "mcp", "control", "postgres", "dev"]
[[package]]
name = "google-adk"