diff --git a/README.md b/README.md index a7e8f0b18..5b541b48a 100644 --- a/README.md +++ b/README.md @@ -8,17 +8,17 @@ [![Rust](https://img.shields.io/badge/rust-nightly-e32828?style=flat-square&logo=rust)](https://rustup.rs/) [![License](https://img.shields.io/badge/license-MIT-blue?style=flat-square)](./LICENSE.md) -[Quick Start](#quick-start) · [How It Works](#how-it-works) · [Examples](./noir-examples/) · [Repository Map](#repository-map) · [Contributing](./CONTRIBUTING.md) +[Quick Start](#quick-start) · [Docs](./docs/) · [How It Works](#how-it-works) · [Examples](./noir-examples/) · [Repository Map](#repository-map) · [Contributing](./CONTRIBUTING.md) -ProveKit is a zero-knowledge proof system toolkit that compiles [Noir](https://noir-lang.org/) programs to R1CS constraints and generates and verifies [WHIR](https://github.com/WizardOfMenlo/whir) proofs using a Spartan-based protocol. It includes custom SIMD-accelerated field arithmetic and memory-efficient algorithms for resource-constrained environments, with a complete proving and verification stack plus recursive verification support for on-chain Groth16 applications. +ProveKit compiles [Noir](https://noir-lang.org/) programs to R1CS constraints and generates and verifies [WHIR](https://github.com/WizardOfMenlo/whir) proofs using a Spartan-based protocol. The repository includes SIMD-accelerated field arithmetic, memory-conscious proving code, CLI tooling, host-language bindings, and recursive-verifier export for Go/gnark and Groth16 workflows. ## Why ProveKit - **Noir frontend:** write circuits in Noir and use ProveKit to prepare keys, prove, and verify with one CLI. -- **Post-quantum secure proofs:** produce WHIR proofs designed around post-quantum security assumptions. -- **Integration-ready surface:** use ProveKit from Swift, Kotlin, JavaScript, and Rust, or use the C-compatible FFI when you need another language. +- **WHIR proof backend:** produce and verify WHIR proofs from prepared ProveKit artifacts. +- **Host integrations:** use ProveKit from Rust, JavaScript, Swift, Kotlin, or any host that can call the C-compatible FFI. - **Recursive verifier for on-chain Groth16:** export verifier/proof data for a recursive verifier when an on-chain Groth16 wrapper is required. ## Quick Start @@ -33,9 +33,9 @@ The smallest end-to-end path is the [`noir-examples/basic`](./noir-examples/basi ```sh cd noir-examples/basic -cargo run --release --bin provekit-cli prepare -cargo run --release --bin provekit-cli prove -cargo run --release --bin provekit-cli verify +cargo run --release --bin provekit-cli -- prepare +cargo run --release --bin provekit-cli -- prove +cargo run --release --bin provekit-cli -- verify ``` `prepare` writes a **ProveKit Prover** key (`.pkp`) and a **ProveKit Verifier** key (`.pkv`). `prove` reads the PKP plus `Prover.toml` and writes `proof.np`. `verify` reads the PKV and the proof. @@ -89,6 +89,10 @@ fn main(plains: [Field; 2], result: Field) { For larger circuits and integration experiments, see [`noir-examples/`](./noir-examples/). +For the full end-to-end handbook, including artifact generation, Rust, JS/TypeScript, +Swift, Kotlin, troubleshooting, and deployment checklists, see +[`docs/`](./docs/). + ## Repository Map | Layer | Path | Crate/package | Purpose | diff --git a/assets/favicon.svg b/assets/favicon.svg new file mode 100644 index 000000000..54bc0f6d4 --- /dev/null +++ b/assets/favicon.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/logo.svg b/assets/logo.svg new file mode 100644 index 000000000..4574541a7 --- /dev/null +++ b/assets/logo.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 000000000..62c787003 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,9 @@ +# Local website build artifacts +node_modules/ +dist/ +.astro/ + +# Root .gitignore ignores *.json because the Rust workspace emits proof artifacts. +# Keep the website's source/config JSON files trackable. +!pnpm-lock.yaml +!tsconfig.json diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 000000000..ac2ecbe78 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,48 @@ +# ProveKit Docs Website + +Standalone documentation website for ProveKit, built with Astro and Starlight. + +The public docs are organized by task: + +- **Start here:** installation, setup, and first proof. +- **Build and integrate:** end-to-end artifact generation and host-language integration paths. +- **Concepts:** proving flow, artifact lifecycle, and trust boundaries. +- **Reference:** CLI commands, versioning policy, glossary, and production readiness. +- **Troubleshooting:** failure diagnosis and recovery steps. + +## Commands + +```sh +cd docs +corepack enable +pnpm install +pnpm check +pnpm dev +pnpm build +``` + +Run `pnpm check` and `pnpm build` before publishing documentation changes. + +## Content layout + +Documentation source lives in `src/content/docs/`. + +- `index.mdx` is the docs homepage. +- Section folders map to URL paths, for example `getting-started/quickstart.mdx` -> `/getting-started/quickstart/`. +- Sidebar structure is configured in `astro.config.mjs`. +- Custom theme polish lives in `src/styles/starlight.css`. +- Conceptual pages live under `concepts/`. +- Integration and end-to-end pages live under `e2e/` and `integrations/`. +- Reference pages live under `reference/`. +- Troubleshooting pages live under `troubleshooting/`. + +The repository root `README.md` remains the project entry point for contributors and the CLI quick start. + +## Writing standards + +- Keep runnable commands copy-pasteable from a fresh checkout. +- Prefer explicit artifact paths in production and CI examples. +- State generated files, owners, and regeneration rules. +- Separate tutorials, how-to material, conceptual explanation, and reference content. +- Mark active-development caveats instead of implying stable guarantees. +- Link to source files or reference pages when a claim depends on implementation details. diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs new file mode 100644 index 000000000..fb6dd6e9c --- /dev/null +++ b/docs/astro.config.mjs @@ -0,0 +1,102 @@ +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + site: 'https://docs.provekit.dev', + publicDir: '../assets', + integrations: [ + starlight({ + title: 'ProveKit Docs', + description: + 'Documentation for compiling Noir programs to R1CS, generating WHIR proofs, and integrating ProveKit across native, browser, mobile, service, and recursive-verifier environments.', + tagline: 'Noir to WHIR proofs, from first proof to production integration.', + favicon: '/favicon.svg', + logo: { + // Dark wordmark for light mode (ink #2D2D2B), pale brand-ink for dark mode. + light: './src/assets/logo-light.svg', + dark: './src/assets/logo.svg', + alt: 'ProveKit', + replacesTitle: true, + }, + customCss: ['./src/styles/starlight.css'], + // Force light as the canonical theme on first visit (brand is light-only). + // Toggle still works for users who switch. + head: [ + { + tag: 'script', + content: `(()=>{try{if(!localStorage.getItem('starlight-theme'))localStorage.setItem('starlight-theme','light');}catch(e){}})();`, + }, + ], + lastUpdated: true, + tableOfContents: { + minHeadingLevel: 2, + maxHeadingLevel: 3, + }, + editLink: { + baseUrl: 'https://github.com/worldfnd/provekit/edit/main/docs/', + }, + social: [ + { + icon: 'github', + label: 'GitHub', + href: 'https://github.com/worldfnd/provekit', + }, + ], + sidebar: [ + { + label: 'Start here', + items: [ + { label: 'Overview', link: '/' }, + { slug: 'concepts/what-is-provekit', label: 'What is ProveKit?' }, + { slug: 'getting-started/installation' }, + { slug: 'getting-started/quickstart' }, + { slug: 'getting-started/tutorial', label: 'Tutorial: prove without revealing' }, + ], + }, + { + label: 'Build and integrate', + items: [ + { slug: 'e2e/overview' }, + { slug: 'e2e/generate-artifacts' }, + { slug: 'e2e/rust' }, + { slug: 'e2e/js-typescript' }, + { slug: 'e2e/swift' }, + { slug: 'e2e/kotlin' }, + { slug: 'integrations/overview' }, + { slug: 'reference/starter-template', label: 'Starter templates' }, + ], + }, + { + label: 'Concepts', + items: [ + { slug: 'concepts/proving-flow' }, + { slug: 'concepts/designing-circuits', label: 'Designing circuits for ProveKit' }, + { slug: 'concepts/artifact-lifecycle' }, + { slug: 'concepts/security-model' }, + ], + }, + { + label: 'Reference', + items: [ + { slug: 'cli/overview', label: 'CLI reference' }, + { slug: 'reference/performance' }, + { slug: 'reference/comparison', label: 'How ProveKit compares' }, + { slug: 'reference/examples', label: 'Examples catalog' }, + { slug: 'reference/error-codes', label: 'FFI error codes' }, + { slug: 'reference/faq', label: 'FAQ' }, + { slug: 'reference/glossary' }, + ], + }, + { + label: 'Operations', + items: [ + { slug: 'reference/production-checklist' }, + { slug: 'reference/project-status', label: 'Project status' }, + { slug: 'reference/changelog' }, + { slug: 'troubleshooting/common-errors', label: 'Troubleshooting' }, + ], + }, + ], + }), + ], +}); diff --git a/docs/package.json b/docs/package.json new file mode 100644 index 000000000..3c1f6c216 --- /dev/null +++ b/docs/package.json @@ -0,0 +1,20 @@ +{ + "name": "provekit-docs", + "version": "0.1.0", + "private": true, + "type": "module", + "scripts": { + "dev": "astro dev", + "build": "astro build", + "check": "astro sync && tsc --noEmit", + "preview": "astro preview" + }, + "dependencies": { + "@astrojs/starlight": "^0.39.1", + "astro": "^6.3.1" + }, + "devDependencies": { + "typescript": "^6.0.3" + }, + "packageManager": "pnpm@9.15.4+sha512.b2dc20e2fc72b3e18848459b37359a32064663e5627a51e4c74b2c29dd8e8e0491483c3abb40789cfd578bf362fb6ba8261b05f0387d76792ed6e23ea3b1b6a0" +} diff --git a/docs/pnpm-lock.yaml b/docs/pnpm-lock.yaml new file mode 100644 index 000000000..42cd1a00b --- /dev/null +++ b/docs/pnpm-lock.yaml @@ -0,0 +1,3967 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@astrojs/starlight': + specifier: ^0.39.1 + version: 0.39.1(astro@6.3.1(@types/node@24.12.3)(rollup@4.60.3))(typescript@6.0.3) + astro: + specifier: ^6.3.1 + version: 6.3.1(@types/node@24.12.3)(rollup@4.60.3) + devDependencies: + typescript: + specifier: ^6.0.3 + version: 6.0.3 + +packages: + + '@astrojs/compiler@4.0.0': + resolution: {integrity: sha512-eouss7G8ygdZqHuke033VMcVw5HTZUu+PXd/h06DGDUg/jt5btPYPqh66ENWw/mU78rBrf/oeC4oqoBwMtDMNA==} + + '@astrojs/internal-helpers@0.9.0': + resolution: {integrity: sha512-GdYkzR26re8izmyYlBqf4z2s7zNngmWLFuxw0UKiPNqHraZGS6GKWIwSHgS22RDlu2ePFJ8bzmpBcUszut/SDg==} + + '@astrojs/markdown-remark@7.1.1': + resolution: {integrity: sha512-C6e9BnLGlbdv6bV8MYGeHpHxsUHrCrB4OuRLqi5LI7oiBVcBcqfUN06zpwFQdHgV48QCCrMmLpyqBr7VqC+swA==} + + '@astrojs/mdx@5.0.4': + resolution: {integrity: sha512-tSbuuYueNODiFAFaME7pjHY5lOLoxBYJi1cKd6scw9+a4ZO7C7UGdafEoVAQvOV2eO8a6RaHSAJYGVPL1w8BPA==} + engines: {node: '>=22.12.0'} + peerDependencies: + astro: ^6.0.0 + + '@astrojs/prism@4.0.1': + resolution: {integrity: sha512-nksZQVjlferuWzhPsBpQ1JE5XuKAf1id1/9Hj4a9KG4+ofrlzxUUwX4YGQF/SuDiuiGKEnzopGOt38F3AnVWsQ==} + engines: {node: '>=22.12.0'} + + '@astrojs/sitemap@3.7.2': + resolution: {integrity: sha512-PqkzkcZTb5ICiyIR8VoKbIAP/laNRXi5tw616N1Ckk+40oNB8Can1AzVV56lrbC5GKSZFCyJYUVYqVivMisvpA==} + + '@astrojs/starlight@0.39.1': + resolution: {integrity: sha512-9kIAXBwcqAuFQ7Ft419fr6rz6p0SPg7Yfgc28TfzoCcuOH9utZgIola9yOq5YIMDrR8rmm8kyl7pCsfrPVmLhQ==} + peerDependencies: + astro: ^6.0.0 + + '@astrojs/telemetry@3.3.2': + resolution: {integrity: sha512-j8DNruA8ors99Al39RYZPJK4DC1bKkoNm93mAMuBhY9TCNC4R8n1q7ovFnJ5qhGh5Lsh7pa1gpQVpYpsJPeTHQ==} + engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0} + + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.28.5': + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.29.3': + resolution: {integrity: sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/types@7.29.0': + resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} + engines: {node: '>=6.9.0'} + + '@capsizecss/unpack@4.0.0': + resolution: {integrity: sha512-VERIM64vtTP1C4mxQ5thVT9fK0apjPFobqybMtA1UdUujWka24ERHbRHFGmpbbhp73MhV+KSsHQH9C6uOTdEQA==} + engines: {node: '>=18'} + + '@clack/core@1.3.0': + resolution: {integrity: sha512-xJPHpAmEQUBrXSLx0gF+q5K/IyihXpsHZcha+jB+tyahsKRK3Dxo4D0coZDewHo12NhiuzC3dTtMPbm53GEAAA==} + engines: {node: '>= 20.12.0'} + + '@clack/prompts@1.3.0': + resolution: {integrity: sha512-GgcWwRCs/xPtaqlMy8qRhPnZf9vlWcWZNHAitnVQ3yk7JmSralSiq5q07yaffYE8SogtDm7zFeKccx1QNVARpw==} + engines: {node: '>= 20.12.0'} + + '@ctrl/tinycolor@4.2.0': + resolution: {integrity: sha512-kzyuwOAQnXJNLS9PSyrk0CWk35nWJW/zl/6KvnTBMFK65gm7U1/Z5BqjxeapjZCIhQcM/DsrEmcbRwDyXyXK4A==} + engines: {node: '>=14'} + + '@emnapi/runtime@1.10.0': + resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==} + + '@esbuild/aix-ppc64@0.27.7': + resolution: {integrity: sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.27.7': + resolution: {integrity: sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.27.7': + resolution: {integrity: sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.27.7': + resolution: {integrity: sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.27.7': + resolution: {integrity: sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.27.7': + resolution: {integrity: sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.27.7': + resolution: {integrity: sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.27.7': + resolution: {integrity: sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.27.7': + resolution: {integrity: sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.27.7': + resolution: {integrity: sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.27.7': + resolution: {integrity: sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.27.7': + resolution: {integrity: sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.27.7': + resolution: {integrity: sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.27.7': + resolution: {integrity: sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.27.7': + resolution: {integrity: sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.27.7': + resolution: {integrity: sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.27.7': + resolution: {integrity: sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.27.7': + resolution: {integrity: sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.27.7': + resolution: {integrity: sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.27.7': + resolution: {integrity: sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.27.7': + resolution: {integrity: sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.27.7': + resolution: {integrity: sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.27.7': + resolution: {integrity: sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.27.7': + resolution: {integrity: sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.27.7': + resolution: {integrity: sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.27.7': + resolution: {integrity: sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@expressive-code/core@0.42.0': + resolution: {integrity: sha512-MN11+9nfmaC7sYu2BZJXAXqwkBRt8t1xTSqP+Ti1NfTEskgl6xUnzDxoaiQkg0BMzpglA0pys4dpDKquP/cyIw==} + + '@expressive-code/plugin-frames@0.42.0': + resolution: {integrity: sha512-XtkPm+941Uta7Y+81Acv+OA/20F1NJmJhCX6UYGKpqEIGqplNh3PTOhcURp6tcruhlzJcWcvpWy6Oigz3SrjqA==} + + '@expressive-code/plugin-shiki@0.42.0': + resolution: {integrity: sha512-PMKey/kLmewttAHQezL+Y5Fx3vVssfDi3+FJOYQQS2mXP3tQspFELtKKAfsXfmSXdToZYgwoO69HJndqfE+09g==} + + '@expressive-code/plugin-text-markers@0.42.0': + resolution: {integrity: sha512-l59lUx8fq1v5g6SpmbDjiU0+7IdfbiWnAyRmtTVSpfhyq+nZMN4UcmYyu2b9Mynhzt7Gr+O+cXyEPDNb2AVWVQ==} + + '@img/colour@1.1.0': + resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==} + engines: {node: '>=18'} + + '@img/sharp-darwin-arm64@0.34.5': + resolution: {integrity: sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [darwin] + + '@img/sharp-darwin-x64@0.34.5': + resolution: {integrity: sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-darwin-arm64@1.2.4': + resolution: {integrity: sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==} + cpu: [arm64] + os: [darwin] + + '@img/sharp-libvips-darwin-x64@1.2.4': + resolution: {integrity: sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-linux-arm64@1.2.4': + resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linux-arm@1.2.4': + resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==} + cpu: [arm] + os: [linux] + + '@img/sharp-libvips-linux-ppc64@1.2.4': + resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==} + cpu: [ppc64] + os: [linux] + + '@img/sharp-libvips-linux-riscv64@1.2.4': + resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==} + cpu: [riscv64] + os: [linux] + + '@img/sharp-libvips-linux-s390x@1.2.4': + resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==} + cpu: [s390x] + os: [linux] + + '@img/sharp-libvips-linux-x64@1.2.4': + resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==} + cpu: [x64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-arm64@1.2.4': + resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-x64@1.2.4': + resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==} + cpu: [x64] + os: [linux] + + '@img/sharp-linux-arm64@0.34.5': + resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + + '@img/sharp-linux-arm@0.34.5': + resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm] + os: [linux] + + '@img/sharp-linux-ppc64@0.34.5': + resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [ppc64] + os: [linux] + + '@img/sharp-linux-riscv64@0.34.5': + resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [riscv64] + os: [linux] + + '@img/sharp-linux-s390x@0.34.5': + resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [s390x] + os: [linux] + + '@img/sharp-linux-x64@0.34.5': + resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + + '@img/sharp-linuxmusl-arm64@0.34.5': + resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + + '@img/sharp-linuxmusl-x64@0.34.5': + resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + + '@img/sharp-wasm32@0.34.5': + resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [wasm32] + + '@img/sharp-win32-arm64@0.34.5': + resolution: {integrity: sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [win32] + + '@img/sharp-win32-ia32@0.34.5': + resolution: {integrity: sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [ia32] + os: [win32] + + '@img/sharp-win32-x64@0.34.5': + resolution: {integrity: sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [win32] + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@mdx-js/mdx@3.1.1': + resolution: {integrity: sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ==} + + '@oslojs/encoding@1.1.0': + resolution: {integrity: sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==} + + '@pagefind/darwin-arm64@1.5.2': + resolution: {integrity: sha512-MXpI+7HsAdPkvJ0gk9xj9g541BCqBZOBbdwj9g6lB5LCj6kSV6nqDSjzcAJwvOsfu0fjwvC8hQU+ecfhp+MpiQ==} + cpu: [arm64] + os: [darwin] + + '@pagefind/darwin-x64@1.5.2': + resolution: {integrity: sha512-IojxFWMEJe0RQ7PQ3KXQsPIImNsbpPYpoZ+QUDrL8fAl/O27IX+LVLs74/UzEZy5uA2LD8Nz1AiwKr72vrkZQw==} + cpu: [x64] + os: [darwin] + + '@pagefind/default-ui@1.5.2': + resolution: {integrity: sha512-pm1LMnQg8N2B3n2TnjKlhaFihpz6zTiA4HiGQ6/slKO/+8K9CAU5kcjdSSPgpuk1PMuuN4hxLipUIifnrkl3Sg==} + + '@pagefind/freebsd-x64@1.5.2': + resolution: {integrity: sha512-7EVzo9+0w+2cbe671BtMj10UlNo83I+HrLVLfRxO731svHRJKUfJ/mo05gU14pe9PCfpKNQT8FS3Xc/oDN6pOA==} + cpu: [x64] + os: [freebsd] + + '@pagefind/linux-arm64@1.5.2': + resolution: {integrity: sha512-Ovt9+K35sqzn8H3ZMXGwls4TD/wMJuvRtShHIsmUQREmaxjrDEX7gHckRCrwYJ4XE1H1p6HkLz3wukrAnsfXQw==} + cpu: [arm64] + os: [linux] + + '@pagefind/linux-x64@1.5.2': + resolution: {integrity: sha512-V+tFqHKXhQKq/WqPBD67AFy7scn1/aZID00ws4fSDd+1daSi5UHR9VVlRrOUYKxn3VuFQYRD7lYXdZK1WED1YA==} + cpu: [x64] + os: [linux] + + '@pagefind/windows-arm64@1.5.2': + resolution: {integrity: sha512-hN9Nh90fNW61nNRCW9ZyQrAj/mD0eRvmJ8NlTUzkbuW8kIzGJUi3cxjFkEcMZ5h/8FsKWD/VcouZl4yo1F7B6g==} + cpu: [arm64] + os: [win32] + + '@pagefind/windows-x64@1.5.2': + resolution: {integrity: sha512-Fa2Iyw7kaDRzGMfNYNUXNW2zbL5FQVDgSOcbDHdzBrDEdpqOqg8TcZ68F22ol6NJ9IGzvUdmeyZypLW5dyhqsg==} + cpu: [x64] + os: [win32] + + '@rollup/pluginutils@5.3.0': + resolution: {integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/rollup-android-arm-eabi@4.60.3': + resolution: {integrity: sha512-x35CNW/ANXG3hE/EZpRU8MXX1JDN86hBb2wMGAtltkz7pc6cxgjpy1OMMfDosOQ+2hWqIkag/fGok1Yady9nGw==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.60.3': + resolution: {integrity: sha512-xw3xtkDApIOGayehp2+Rz4zimfkaX65r4t47iy+ymQB2G4iJCBBfj0ogVg5jpvjpn8UWn/+q9tprxleYeNp3Hw==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.60.3': + resolution: {integrity: sha512-vo6Y5Qfpx7/5EaamIwi0WqW2+zfiusVihKatLvtN1VFVy3D13uERk/6gZLU1UiHRL6fDXqj/ELIeVRGnvcTE1g==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.60.3': + resolution: {integrity: sha512-D+0QGcZhBzTN82weOnsSlY7V7+RMmPuF1CkbxyMAGE8+ZHeUjyb76ZiWmBlCu//AQQONvxcqRbwZTajZKqjuOw==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.60.3': + resolution: {integrity: sha512-6HnvHCT7fDyj6R0Ph7A6x8dQS/S38MClRWeDLqc0MdfWkxjiu1HSDYrdPhqSILzjTIC/pnXbbJbo+ft+gy/9hQ==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.60.3': + resolution: {integrity: sha512-KHLgC3WKlUYW3ShFKnnosZDOJ0xjg9zp7au3sIm2bs/tGBeC2ipmvRh/N7JKi0t9Ue20C0dpEshi8WUubg+cnA==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.60.3': + resolution: {integrity: sha512-DV6fJoxEYWJOvaZIsok7KrYl0tPvga5OZ2yvKHNNYyk/2roMLqQAbGhr78EQ5YhHpnhLKJD3S1WFusAkmUuV5g==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.60.3': + resolution: {integrity: sha512-mQKoJAzvuOs6F+TZybQO4GOTSMUu7v0WdxEk24krQ/uUxXoPTtHjuaUuPmFhtBcM4K0ons8nrE3JyhTuCFtT/w==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.60.3': + resolution: {integrity: sha512-Whjj2qoiJ6+OOJMGptTYazaJvjOJm+iKHpXQM1P3LzGjt7Ff++Tp7nH4N8J/BUA7R9IHfDyx4DJIflifwnbmIA==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.60.3': + resolution: {integrity: sha512-4YTNHKqGng5+yiZt3mg77nmyuCfmNfX4fPmyUapBcIk+BdwSwmCWGXOUxhXbBEkFHtoN5boLj/5NON+u5QC9tg==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-loong64-gnu@4.60.3': + resolution: {integrity: sha512-SU3kNlhkpI4UqlUc2VXPGK9o886ZsSeGfMAX2ba2b8DKmMXq4AL7KUrkSWVbb7koVqx41Yczx6dx5PNargIrEA==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-loong64-musl@4.60.3': + resolution: {integrity: sha512-6lDLl5h4TXpB1mTf2rQWnAk/LcXrx9vBfu/DT5TIPhvMhRWaZ5MxkIc8u4lJAmBo6klTe1ywXIUHFjylW505sg==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-ppc64-gnu@4.60.3': + resolution: {integrity: sha512-BMo8bOw8evlup/8G+cj5xWtPyp93xPdyoSN16Zy90Q2QZ0ZYRhCt6ZJSwbrRzG9HApFabjwj2p25TUPDWrhzqQ==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-ppc64-musl@4.60.3': + resolution: {integrity: sha512-E0L8X1dZN1/Rph+5VPF6Xj2G7JJvMACVXtamTJIDrVI44Y3K+G8gQaMEAavbqCGTa16InptiVrX6eM6pmJ+7qA==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.60.3': + resolution: {integrity: sha512-oZJ/WHaVfHUiRAtmTAeo3DcevNsVvH8mbvodjZy7D5QKvCefO371SiKRpxoDcCxB3PTRTLayWBkvmDQKTcX/sw==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-riscv64-musl@4.60.3': + resolution: {integrity: sha512-Dhbyh7j9FybM3YaTgaHmVALwA8AkUwTPccyCQ79TG9AJUsMQqgN1DDEZNr4+QUfwiWvLDumW5vdwzoeUF+TNxQ==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.60.3': + resolution: {integrity: sha512-cJd1X5XhHHlltkaypz1UcWLA8AcoIi1aWhsvaWDskD1oz2eKCypnqvTQ8ykMNI0RSmm7NkTdSqSSD7zM0xa6Ig==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.60.3': + resolution: {integrity: sha512-DAZDBHQfG2oQuhY7mc6I3/qB4LU2fQCjRvxbDwd/Jdvb9fypP4IJ4qmtu6lNjes6B531AI8cg1aKC2di97bUxA==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.60.3': + resolution: {integrity: sha512-cRxsE8c13mZOh3vP+wLDxpQBRrOHDIGOWyDL93Sy0Ga8y515fBcC2pjUfFwUe5T7tqvTvWbCpg1URM/AXdWIXA==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-openbsd-x64@4.60.3': + resolution: {integrity: sha512-QaWcIgRxqEdQdhJqW4DJctsH6HCmo5vHxY0krHSX4jMtOqfzC+dqDGuHM87bu4H8JBeibWx7jFz+h6/4C8wA5Q==} + cpu: [x64] + os: [openbsd] + + '@rollup/rollup-openharmony-arm64@4.60.3': + resolution: {integrity: sha512-AaXwSvUi3QIPtroAUw1t5yHGIyqKEXwH54WUocFolZhpGDruJcs8c+xPNDRn4XiQsS7MEwnYsHW2l0MBLDMkWg==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.60.3': + resolution: {integrity: sha512-65LAKM/bAWDqKNEelHlcHvm2V+Vfb8C6INFxQXRHCvaVN1rJfwr4NvdP4FyzUaLqWfaCGaadf6UbTm8xJeYfEg==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.60.3': + resolution: {integrity: sha512-EEM2gyhBF5MFnI6vMKdX1LAosE627RGBzIoGMdLloPZkXrUN0Ckqgr2Qi8+J3zip/8NVVro3/FjB+tjhZUgUHA==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-gnu@4.60.3': + resolution: {integrity: sha512-E5Eb5H/DpxaoXH++Qkv28RcUJboMopmdDUALBczvHMf7hNIxaDZqwY5lK12UK1BHacSmvupoEWGu+n993Z0y1A==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.60.3': + resolution: {integrity: sha512-hPt/bgL5cE+Qp+/TPHBqptcAgPzgj46mPcg/16zNUmbQk0j+mOEQV/+Lqu8QRtDV3Ek95Q6FeFITpuhl6OTsAA==} + cpu: [x64] + os: [win32] + + '@shikijs/core@4.0.2': + resolution: {integrity: sha512-hxT0YF4ExEqB8G/qFdtJvpmHXBYJ2lWW7qTHDarVkIudPFE6iCIrqdgWxGn5s+ppkGXI0aEGlibI0PAyzP3zlw==} + engines: {node: '>=20'} + + '@shikijs/engine-javascript@4.0.2': + resolution: {integrity: sha512-7PW0Nm49DcoUIQEXlJhNNBHyoGMjalRETTCcjMqEaMoJRLljy1Bi/EGV3/qLBgLKQejdspiiYuHGQW6dX94Nag==} + engines: {node: '>=20'} + + '@shikijs/engine-oniguruma@4.0.2': + resolution: {integrity: sha512-UpCB9Y2sUKlS9z8juFSKz7ZtysmeXCgnRF0dlhXBkmQnek7lAToPte8DkxmEYGNTMii72zU/lyXiCB6StuZeJg==} + engines: {node: '>=20'} + + '@shikijs/langs@4.0.2': + resolution: {integrity: sha512-KaXby5dvoeuZzN0rYQiPMjFoUrz4hgwIE+D6Du9owcHcl6/g16/yT5BQxSW5cGt2MZBz6Hl0YuRqf12omRfUUg==} + engines: {node: '>=20'} + + '@shikijs/primitive@4.0.2': + resolution: {integrity: sha512-M6UMPrSa3fN5ayeJwFVl9qWofl273wtK1VG8ySDZ1mQBfhCpdd8nEx7nPZ/tk7k+TYcpqBZzj/AnwxT9lO+HJw==} + engines: {node: '>=20'} + + '@shikijs/themes@4.0.2': + resolution: {integrity: sha512-mjCafwt8lJJaVSsQvNVrJumbnnj1RI8jbUKrPKgE6E3OvQKxnuRoBaYC51H4IGHePsGN/QtALglWBU7DoKDFnA==} + engines: {node: '>=20'} + + '@shikijs/types@4.0.2': + resolution: {integrity: sha512-qzbeRooUTPnLE+sHD/Z8DStmaDgnbbc/pMrU203950aRqjX/6AFHeDYT+j00y2lPdz0ywJKx7o/7qnqTivtlXg==} + engines: {node: '>=20'} + + '@shikijs/vscode-textmate@10.0.2': + resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} + + '@types/debug@4.1.13': + resolution: {integrity: sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==} + + '@types/estree-jsx@1.0.5': + resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==} + + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + + '@types/estree@1.0.9': + resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} + + '@types/hast@3.0.4': + resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} + + '@types/js-yaml@4.0.9': + resolution: {integrity: sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==} + + '@types/mdast@4.0.4': + resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} + + '@types/mdx@2.0.13': + resolution: {integrity: sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==} + + '@types/ms@2.1.0': + resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} + + '@types/nlcst@2.0.3': + resolution: {integrity: sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA==} + + '@types/node@24.12.3': + resolution: {integrity: sha512-8oljBDGun9cIsZRJR6fkihn0TSXJI0UDOOhncYaERq6M0JMDoPLxyscwruJcb4GKS6dvK/d8xebYBg27h/duaQ==} + + '@types/sax@1.2.7': + resolution: {integrity: sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==} + + '@types/unist@2.0.11': + resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} + + '@types/unist@3.0.3': + resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} + + '@ungap/structured-clone@1.3.1': + resolution: {integrity: sha512-mUFwbeTqrVgDQxFveS+df2yfap6iuP20NAKAsBt5jDEoOTDew+zwLAOilHCeQJOVSvmgCX4ogqIrA0mnyr08yQ==} + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn@8.16.0: + resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} + engines: {node: '>=0.4.0'} + hasBin: true + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + arg@5.0.2: + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + aria-query@5.3.2: + resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} + engines: {node: '>= 0.4'} + + array-iterate@2.0.1: + resolution: {integrity: sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==} + + astring@1.9.0: + resolution: {integrity: sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==} + hasBin: true + + astro-expressive-code@0.42.0: + resolution: {integrity: sha512-aiTePi2Cn0mJPYWZSzP1GcxCinX9mNtJyCCshVVPSg1yRwM7ADvFJOx0FnS440M9t65hp8JH//dc2qr22Bm4ag==} + peerDependencies: + astro: ^4.0.0-beta || ^5.0.0-beta || ^3.3.0 || ^6.0.0-beta + + astro@6.3.1: + resolution: {integrity: sha512-atz6dmkE3Gu24bDgb7g2RE/BYnKqPYIHd6hTUM1UXvu/i7qNZOKLAqEHvgYpv9PQVcgWsXpk4/OOXZ0E/FzvSQ==} + engines: {node: '>=22.12.0', npm: '>=9.6.5', pnpm: '>=7.1.0'} + hasBin: true + + axobject-query@4.1.0: + resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} + engines: {node: '>= 0.4'} + + bail@2.0.2: + resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} + + bcp-47-match@2.0.3: + resolution: {integrity: sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ==} + + bcp-47@2.1.0: + resolution: {integrity: sha512-9IIS3UPrvIa1Ej+lVDdDwO7zLehjqsaByECw0bu2RRGP73jALm6FYbzI5gWbgHLvNdkvfXB5YrSbocZdOS0c0w==} + + boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + + ccount@2.0.1: + resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + + character-entities-html4@2.1.0: + resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} + + character-entities-legacy@3.0.0: + resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} + + character-entities@2.0.2: + resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} + + character-reference-invalid@2.0.1: + resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==} + + chokidar@5.0.0: + resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==} + engines: {node: '>= 20.19.0'} + + ci-info@4.4.0: + resolution: {integrity: sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==} + engines: {node: '>=8'} + + clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + + collapse-white-space@2.1.0: + resolution: {integrity: sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==} + + comma-separated-tokens@2.0.3: + resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} + + commander@11.1.0: + resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} + engines: {node: '>=16'} + + common-ancestor-path@2.0.0: + resolution: {integrity: sha512-dnN3ibLeoRf2HNC+OlCiNc5d2zxbLJXOtiZUudNFSXZrNSydxcCsSpRzXwfu7BBWCIfHPw+xTayeBvJCP/D8Ng==} + engines: {node: '>= 18'} + + cookie-es@1.2.3: + resolution: {integrity: sha512-lXVyvUvrNXblMqzIRrxHb57UUVmqsSWlxqt3XIjCkUP0wDAf6uicO6KMbEgYrMNtEvWgWHwe42CKxPu9MYAnWw==} + + cookie@1.1.1: + resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==} + engines: {node: '>=18'} + + crossws@0.3.5: + resolution: {integrity: sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==} + + css-select@5.2.2: + resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} + + css-selector-parser@3.3.0: + resolution: {integrity: sha512-Y2asgMGFqJKF4fq4xHDSlFYIkeVfRsm69lQC1q9kbEsH5XtnINTMrweLkjYMeaUgiXBy/uvKeO/a1JHTNnmB2g==} + + css-tree@2.2.1: + resolution: {integrity: sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} + + css-tree@3.2.1: + resolution: {integrity: sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + + css-what@6.2.2: + resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==} + engines: {node: '>= 6'} + + cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + + csso@5.0.5: + resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decode-named-character-reference@1.3.0: + resolution: {integrity: sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==} + + defu@6.1.7: + resolution: {integrity: sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==} + + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + + destr@2.0.5: + resolution: {integrity: sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==} + + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + + devalue@5.8.0: + resolution: {integrity: sha512-2zA9pFEsnp7vWBZbXF5JAgAq0fsUIt/1XPbRiAmRV3lp/2C3upzH+sADiyy66aFCihoLEsrQHxNM5w1gIDfsBg==} + + devlop@1.1.0: + resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} + + diff@8.0.4: + resolution: {integrity: sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==} + engines: {node: '>=0.3.1'} + + direction@2.0.1: + resolution: {integrity: sha512-9S6m9Sukh1cZNknO1CWAr2QAWsbKLafQiyM5gZ7VgXHeuaoUwffKN4q6NC4A/Mf9iiPlOXQEKW/Mv/mh9/3YFA==} + hasBin: true + + dom-serializer@2.0.0: + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + + domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + + domhandler@5.0.3: + resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} + engines: {node: '>= 4'} + + domutils@3.2.2: + resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} + + dset@3.1.4: + resolution: {integrity: sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==} + engines: {node: '>=4'} + + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + + entities@6.0.1: + resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} + engines: {node: '>=0.12'} + + es-module-lexer@2.1.0: + resolution: {integrity: sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==} + + esast-util-from-estree@2.0.0: + resolution: {integrity: sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==} + + esast-util-from-js@2.0.1: + resolution: {integrity: sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==} + + esbuild@0.27.7: + resolution: {integrity: sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==} + engines: {node: '>=18'} + hasBin: true + + escape-string-regexp@5.0.0: + resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} + engines: {node: '>=12'} + + estree-util-attach-comments@3.0.0: + resolution: {integrity: sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw==} + + estree-util-build-jsx@3.0.1: + resolution: {integrity: sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ==} + + estree-util-is-identifier-name@3.0.0: + resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==} + + estree-util-scope@1.0.0: + resolution: {integrity: sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ==} + + estree-util-to-js@2.0.0: + resolution: {integrity: sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==} + + estree-util-visit@2.0.0: + resolution: {integrity: sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==} + + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + eventemitter3@5.0.4: + resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==} + + expressive-code@0.42.0: + resolution: {integrity: sha512-V5DtJLEKuj4wf9O6IRtPtRObkMVy2ggR+S0MdjrTw6m58krZnDioyhW1si3Y04c5YPeooP4nd85Yq9NwEVHS4g==} + + extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + + fast-string-truncated-width@3.0.3: + resolution: {integrity: sha512-0jjjIEL6+0jag3l2XWWizO64/aZVtpiGE3t0Zgqxv0DPuxiMjvB3M24fCyhZUO4KomJQPj3LTSUnDP3GpdwC0g==} + + fast-string-width@3.0.2: + resolution: {integrity: sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg==} + + fast-wrap-ansi@0.2.0: + resolution: {integrity: sha512-rLV8JHxTyhVmFYhBJuMujcrHqOT2cnO5Zxj37qROj23CP39GXubJRBUFF0z8KFK77Uc0SukZUf7JZhsVEQ6n8w==} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + flattie@1.1.1: + resolution: {integrity: sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ==} + engines: {node: '>=8'} + + fontace@0.4.1: + resolution: {integrity: sha512-lDMvbAzSnHmbYMTEld5qdtvNH2/pWpICOqpean9IgC7vUbUJc3k+k5Dokp85CegamqQpFbXf0rAVkbzpyTA8aw==} + + fontkitten@1.0.3: + resolution: {integrity: sha512-Wp1zXWPVUPBmfoa3Cqc9ctaKuzKAV6uLstRqlR56kSjplf5uAce+qeyYym7F+PHbGTk+tCEdkCW6RD7DX/gBZw==} + engines: {node: '>=20'} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + get-tsconfig@5.0.0-beta.4: + resolution: {integrity: sha512-7nF7C9fIPFEMHgEMEfgIlO9wDdZ8CyHw27rWciFZfHvHDReIiPhsYuzPRXsfvBCqFy1l8RRyyWV7QLM+ZhUJsQ==} + engines: {node: '>=20.20.0'} + + github-slugger@2.0.0: + resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==} + + h3@1.15.11: + resolution: {integrity: sha512-L3THSe2MPeBwgIZVSH5zLdBBU90TOxarvhK9d04IDY2AmVS8j2Jz2LIWtwsGOU3lu2I5jCN7FNvVfY2+XyF+mg==} + + hast-util-embedded@3.0.0: + resolution: {integrity: sha512-naH8sld4Pe2ep03qqULEtvYr7EjrLK2QHY8KJR6RJkTUjPGObe1vnx585uzem2hGra+s1q08DZZpfgDVYRbaXA==} + + hast-util-format@1.1.0: + resolution: {integrity: sha512-yY1UDz6bC9rDvCWHpx12aIBGRG7krurX0p0Fm6pT547LwDIZZiNr8a+IHDogorAdreULSEzP82Nlv5SZkHZcjA==} + + hast-util-from-html@2.0.3: + resolution: {integrity: sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==} + + hast-util-from-parse5@8.0.3: + resolution: {integrity: sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==} + + hast-util-has-property@3.0.0: + resolution: {integrity: sha512-MNilsvEKLFpV604hwfhVStK0usFY/QmM5zX16bo7EjnAEGofr5YyI37kzopBlZJkHD4t887i+q/C8/tr5Q94cA==} + + hast-util-is-body-ok-link@3.0.1: + resolution: {integrity: sha512-0qpnzOBLztXHbHQenVB8uNuxTnm/QBFUOmdOSsEn7GnBtyY07+ENTWVFBAnXd/zEgd9/SUG3lRY7hSIBWRgGpQ==} + + hast-util-is-element@3.0.0: + resolution: {integrity: sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==} + + hast-util-minify-whitespace@1.0.1: + resolution: {integrity: sha512-L96fPOVpnclQE0xzdWb/D12VT5FabA7SnZOUMtL1DbXmYiHJMXZvFkIZfiMmTCNJHUeO2K9UYNXoVyfz+QHuOw==} + + hast-util-parse-selector@4.0.0: + resolution: {integrity: sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==} + + hast-util-phrasing@3.0.1: + resolution: {integrity: sha512-6h60VfI3uBQUxHqTyMymMZnEbNl1XmEGtOxxKYL7stY2o601COo62AWAYBQR9lZbYXYSBoxag8UpPRXK+9fqSQ==} + + hast-util-raw@9.1.0: + resolution: {integrity: sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw==} + + hast-util-select@6.0.4: + resolution: {integrity: sha512-RqGS1ZgI0MwxLaKLDxjprynNzINEkRHY2i8ln4DDjgv9ZhcYVIHN9rlpiYsqtFwrgpYU361SyWDQcGNIBVu3lw==} + + hast-util-to-estree@3.1.3: + resolution: {integrity: sha512-48+B/rJWAp0jamNbAAf9M7Uf//UVqAoMmgXhBdxTDJLGKY+LRnZ99qcG+Qjl5HfMpYNzS5v4EAwVEF34LeAj7w==} + + hast-util-to-html@9.0.5: + resolution: {integrity: sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==} + + hast-util-to-jsx-runtime@2.3.6: + resolution: {integrity: sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==} + + hast-util-to-parse5@8.0.1: + resolution: {integrity: sha512-MlWT6Pjt4CG9lFCjiz4BH7l9wmrMkfkJYCxFwKQic8+RTZgWPuWxwAfjJElsXkex7DJjfSJsQIt931ilUgmwdA==} + + hast-util-to-string@3.0.1: + resolution: {integrity: sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A==} + + hast-util-to-text@4.0.2: + resolution: {integrity: sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==} + + hast-util-whitespace@3.0.0: + resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==} + + hastscript@9.0.1: + resolution: {integrity: sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==} + + html-escaper@3.0.3: + resolution: {integrity: sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==} + + html-void-elements@3.0.0: + resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} + + html-whitespace-sensitive-tag-names@3.0.1: + resolution: {integrity: sha512-q+310vW8zmymYHALr1da4HyXUQ0zgiIwIicEfotYPWGN0OJVEN/58IJ3A4GBYcEq3LGAZqKb+ugvP0GNB9CEAA==} + + http-cache-semantics@4.2.0: + resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==} + + i18next@26.0.10: + resolution: {integrity: sha512-k3yGPAlWR2RdMYoVXJoDZDT87qeHIWKH7gVksdZMpRty7QX/D9QZeYGvN08KGbKHke9wn01eYT+EEsrqX/YTlw==} + peerDependencies: + typescript: ^5 || ^6 + peerDependenciesMeta: + typescript: + optional: true + + inline-style-parser@0.2.7: + resolution: {integrity: sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==} + + iron-webcrypto@1.2.1: + resolution: {integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==} + + is-alphabetical@2.0.1: + resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==} + + is-alphanumerical@2.0.1: + resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==} + + is-decimal@2.0.1: + resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} + + is-docker@3.0.0: + resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + hasBin: true + + is-docker@4.0.0: + resolution: {integrity: sha512-LHE+wROyG/Y/0ZnbktRCoTix2c1RhgWaZraMZ8o1Q7zCh0VSrICJQO5oqIIISrcSBtrXv0o233w1IYwsWCjTzA==} + engines: {node: '>=20'} + hasBin: true + + is-hexadecimal@2.0.1: + resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==} + + is-inside-container@1.0.0: + resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} + engines: {node: '>=14.16'} + hasBin: true + + is-plain-obj@4.1.0: + resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} + engines: {node: '>=12'} + + is-wsl@3.1.1: + resolution: {integrity: sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==} + engines: {node: '>=16'} + + js-yaml@4.1.1: + resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} + hasBin: true + + jsonc-parser@3.3.1: + resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==} + + klona@2.0.6: + resolution: {integrity: sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==} + engines: {node: '>= 8'} + + longest-streak@3.1.0: + resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} + + lru-cache@11.3.6: + resolution: {integrity: sha512-Gf/KoL3C/MlI7Bt0PGI9I+TeTC/I6r/csU58N4BSNc4lppLBeKsOdFYkK+dX0ABDUMJNfCHTyPpzwwO21Awd3A==} + engines: {node: 20 || >=22} + + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + + magicast@0.5.2: + resolution: {integrity: sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==} + + markdown-extensions@2.0.0: + resolution: {integrity: sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==} + engines: {node: '>=16'} + + markdown-table@3.0.4: + resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==} + + mdast-util-definitions@6.0.0: + resolution: {integrity: sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ==} + + mdast-util-directive@3.1.0: + resolution: {integrity: sha512-I3fNFt+DHmpWCYAT7quoM6lHf9wuqtI+oCOfvILnoicNIqjh5E3dEJWiXuYME2gNe8vl1iMQwyUHa7bgFmak6Q==} + + mdast-util-find-and-replace@3.0.2: + resolution: {integrity: sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==} + + mdast-util-from-markdown@2.0.3: + resolution: {integrity: sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==} + + mdast-util-gfm-autolink-literal@2.0.1: + resolution: {integrity: sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==} + + mdast-util-gfm-footnote@2.1.0: + resolution: {integrity: sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==} + + mdast-util-gfm-strikethrough@2.0.0: + resolution: {integrity: sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==} + + mdast-util-gfm-table@2.0.0: + resolution: {integrity: sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==} + + mdast-util-gfm-task-list-item@2.0.0: + resolution: {integrity: sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==} + + mdast-util-gfm@3.1.0: + resolution: {integrity: sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==} + + mdast-util-mdx-expression@2.0.1: + resolution: {integrity: sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==} + + mdast-util-mdx-jsx@3.2.0: + resolution: {integrity: sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==} + + mdast-util-mdx@3.0.0: + resolution: {integrity: sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==} + + mdast-util-mdxjs-esm@2.0.1: + resolution: {integrity: sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==} + + mdast-util-phrasing@4.1.0: + resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==} + + mdast-util-to-hast@13.2.1: + resolution: {integrity: sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==} + + mdast-util-to-markdown@2.1.2: + resolution: {integrity: sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==} + + mdast-util-to-string@4.0.0: + resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} + + mdn-data@2.0.28: + resolution: {integrity: sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==} + + mdn-data@2.27.1: + resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==} + + micromark-core-commonmark@2.0.3: + resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==} + + micromark-extension-directive@4.0.0: + resolution: {integrity: sha512-/C2nqVmXXmiseSSuCdItCMho7ybwwop6RrrRPk0KbOHW21JKoCldC+8rFOaundDoRBUWBnJJcxeA/Kvi34WQXg==} + + micromark-extension-gfm-autolink-literal@2.1.0: + resolution: {integrity: sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==} + + micromark-extension-gfm-footnote@2.1.0: + resolution: {integrity: sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==} + + micromark-extension-gfm-strikethrough@2.1.0: + resolution: {integrity: sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==} + + micromark-extension-gfm-table@2.1.1: + resolution: {integrity: sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==} + + micromark-extension-gfm-tagfilter@2.0.0: + resolution: {integrity: sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==} + + micromark-extension-gfm-task-list-item@2.1.0: + resolution: {integrity: sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==} + + micromark-extension-gfm@3.0.0: + resolution: {integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==} + + micromark-extension-mdx-expression@3.0.1: + resolution: {integrity: sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q==} + + micromark-extension-mdx-jsx@3.0.2: + resolution: {integrity: sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ==} + + micromark-extension-mdx-md@2.0.0: + resolution: {integrity: sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==} + + micromark-extension-mdxjs-esm@3.0.0: + resolution: {integrity: sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==} + + micromark-extension-mdxjs@3.0.0: + resolution: {integrity: sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==} + + micromark-factory-destination@2.0.1: + resolution: {integrity: sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==} + + micromark-factory-label@2.0.1: + resolution: {integrity: sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==} + + micromark-factory-mdx-expression@2.0.3: + resolution: {integrity: sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ==} + + micromark-factory-space@2.0.1: + resolution: {integrity: sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==} + + micromark-factory-title@2.0.1: + resolution: {integrity: sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==} + + micromark-factory-whitespace@2.0.1: + resolution: {integrity: sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==} + + micromark-util-character@2.1.1: + resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==} + + micromark-util-chunked@2.0.1: + resolution: {integrity: sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==} + + micromark-util-classify-character@2.0.1: + resolution: {integrity: sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==} + + micromark-util-combine-extensions@2.0.1: + resolution: {integrity: sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==} + + micromark-util-decode-numeric-character-reference@2.0.2: + resolution: {integrity: sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==} + + micromark-util-decode-string@2.0.1: + resolution: {integrity: sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==} + + micromark-util-encode@2.0.1: + resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==} + + micromark-util-events-to-acorn@2.0.3: + resolution: {integrity: sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg==} + + micromark-util-html-tag-name@2.0.1: + resolution: {integrity: sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==} + + micromark-util-normalize-identifier@2.0.1: + resolution: {integrity: sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==} + + micromark-util-resolve-all@2.0.1: + resolution: {integrity: sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==} + + micromark-util-sanitize-uri@2.0.1: + resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==} + + micromark-util-subtokenize@2.1.0: + resolution: {integrity: sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==} + + micromark-util-symbol@2.0.1: + resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==} + + micromark-util-types@2.0.2: + resolution: {integrity: sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==} + + micromark@4.0.2: + resolution: {integrity: sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==} + + mrmime@2.0.1: + resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==} + engines: {node: '>=10'} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + nanoid@3.3.12: + resolution: {integrity: sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + neotraverse@0.6.18: + resolution: {integrity: sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA==} + engines: {node: '>= 10'} + + nlcst-to-string@4.0.0: + resolution: {integrity: sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA==} + + node-fetch-native@1.6.7: + resolution: {integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==} + + node-mock-http@1.0.4: + resolution: {integrity: sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ==} + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + + obug@2.1.1: + resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==} + + ofetch@1.5.1: + resolution: {integrity: sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==} + + ohash@2.0.11: + resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==} + + oniguruma-parser@0.12.2: + resolution: {integrity: sha512-6HVa5oIrgMC6aA6WF6XyyqbhRPJrKR02L20+2+zpDtO5QAzGHAUGw5TKQvwi5vctNnRHkJYmjAhRVQF2EKdTQw==} + + oniguruma-to-es@4.3.6: + resolution: {integrity: sha512-csuQ9x3Yr0cEIs/Zgx/OEt9iBw9vqIunAPQkx19R/fiMq2oGVTgcMqO/V3Ybqefr1TBvosI6jU539ksaBULJyA==} + + p-limit@7.3.0: + resolution: {integrity: sha512-7cIXg/Z0M5WZRblrsOla88S4wAK+zOQQWeBYfV3qJuJXMr+LnbYjaadrFaS0JILfEDPVqHyKnZ1Z/1d6J9VVUw==} + engines: {node: '>=20'} + + p-queue@9.2.0: + resolution: {integrity: sha512-dWgLE8AH0HjQ9fe74pUkKkvzzYT18Inp4zra3lKHnnwqGvcfcUBrvF2EAVX+envufDNBOzpPq/IBUONDbI7+3g==} + engines: {node: '>=20'} + + p-timeout@7.0.1: + resolution: {integrity: sha512-AxTM2wDGORHGEkPCt8yqxOTMgpfbEHqF51f/5fJCmwFC3C/zNcGT63SymH2ttOAaiIws2zVg4+izQCjrakcwHg==} + engines: {node: '>=20'} + + package-manager-detector@1.6.0: + resolution: {integrity: sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==} + + pagefind@1.5.2: + resolution: {integrity: sha512-XTUaK0hXMCu2jszWE584JGQT7y284TmMV9l/HX3rnG5uo3rHI/uHU56XTyyyPFjeWEBxECbAi0CaFDJOONtG0Q==} + hasBin: true + + parse-entities@4.0.2: + resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==} + + parse-latin@7.0.0: + resolution: {integrity: sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ==} + + parse5@7.3.0: + resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} + + piccolore@0.1.3: + resolution: {integrity: sha512-o8bTeDWjE086iwKrROaDf31K0qC/BENdm15/uH9usSC/uZjJOKb2YGiVHfLY4GhwsERiPI1jmwI2XrA7ACOxVw==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.2: + resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==} + engines: {node: '>=8.6'} + + picomatch@4.0.4: + resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} + engines: {node: '>=12'} + + postcss-nested@6.2.0: + resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.2.14 + + postcss-selector-parser@6.1.2: + resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} + engines: {node: '>=4'} + + postcss@8.5.14: + resolution: {integrity: sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==} + engines: {node: ^10 || ^12 || >=14} + + prismjs@1.30.0: + resolution: {integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==} + engines: {node: '>=6'} + + property-information@7.1.0: + resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==} + + radix3@1.1.2: + resolution: {integrity: sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==} + + readdirp@5.0.0: + resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==} + engines: {node: '>= 20.19.0'} + + recma-build-jsx@1.0.0: + resolution: {integrity: sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==} + + recma-jsx@1.0.1: + resolution: {integrity: sha512-huSIy7VU2Z5OLv6oFLosQGGDqPqdO1iq6bWNAdhzMxSJP7RAso4fCZ1cKu8j9YHCZf3TPrq4dw3okhrylgcd7w==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + recma-parse@1.0.0: + resolution: {integrity: sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ==} + + recma-stringify@1.0.0: + resolution: {integrity: sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==} + + regex-recursion@6.0.2: + resolution: {integrity: sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==} + + regex-utilities@2.3.0: + resolution: {integrity: sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==} + + regex@6.1.0: + resolution: {integrity: sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==} + + rehype-expressive-code@0.42.0: + resolution: {integrity: sha512-8rp/1YMEVVSYbtz+bFBx+uSx3vA4i4T8RwRm5Q/IWbucQnnQqQ0hDqtmKOr8tv+59Cik6cu5aH3WPo0I7csuTA==} + + rehype-format@5.0.1: + resolution: {integrity: sha512-zvmVru9uB0josBVpr946OR8ui7nJEdzZobwLOOqHb/OOD88W0Vk2SqLwoVOj0fM6IPCCO6TaV9CvQvJMWwukFQ==} + + rehype-parse@9.0.1: + resolution: {integrity: sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag==} + + rehype-raw@7.0.0: + resolution: {integrity: sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==} + + rehype-recma@1.0.0: + resolution: {integrity: sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==} + + rehype-stringify@10.0.1: + resolution: {integrity: sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA==} + + rehype@13.0.2: + resolution: {integrity: sha512-j31mdaRFrwFRUIlxGeuPXXKWQxet52RBQRvCmzl5eCefn/KGbomK5GMHNMsOJf55fgo3qw5tST5neDuarDYR2A==} + + remark-directive@4.0.0: + resolution: {integrity: sha512-7sxn4RfF1o3izevPV1DheyGDD6X4c9hrGpfdUpm7uC++dqrnJxIZVkk7CoKqcLm0VUMAuOol7Mno3m6g8cfMuA==} + + remark-gfm@4.0.1: + resolution: {integrity: sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==} + + remark-mdx@3.1.1: + resolution: {integrity: sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg==} + + remark-parse@11.0.0: + resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==} + + remark-rehype@11.1.2: + resolution: {integrity: sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==} + + remark-smartypants@3.0.2: + resolution: {integrity: sha512-ILTWeOriIluwEvPjv67v7Blgrcx+LZOkAUVtKI3putuhlZm84FnqDORNXPPm+HY3NdZOMhyDwZ1E+eZB/Df5dA==} + engines: {node: '>=16.0.0'} + + remark-stringify@11.0.0: + resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==} + + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + + retext-latin@4.0.0: + resolution: {integrity: sha512-hv9woG7Fy0M9IlRQloq/N6atV82NxLGveq+3H2WOi79dtIYWN8OaxogDm77f8YnVXJL2VD3bbqowu5E3EMhBYA==} + + retext-smartypants@6.2.0: + resolution: {integrity: sha512-kk0jOU7+zGv//kfjXEBjdIryL1Acl4i9XNkHxtM7Tm5lFiCog576fjNC9hjoR7LTKQ0DsPWy09JummSsH1uqfQ==} + + retext-stringify@4.0.0: + resolution: {integrity: sha512-rtfN/0o8kL1e+78+uxPTqu1Klt0yPzKuQ2BfWwwfgIUSayyzxpM1PJzkKt4V8803uB9qSy32MvI7Xep9khTpiA==} + + retext@9.0.0: + resolution: {integrity: sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA==} + + rollup@4.60.3: + resolution: {integrity: sha512-pAQK9HalE84QSm4Po3EmWIZPd3FnjkShVkiMlz1iligWYkWQ7wHYd1PF/T7QZ5TVSD6uSTon5gBVMSM4JfBV+A==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + sax@1.6.0: + resolution: {integrity: sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==} + engines: {node: '>=11.0.0'} + + semver@7.7.4: + resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} + engines: {node: '>=10'} + hasBin: true + + sharp@0.34.5: + resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + + shiki@4.0.2: + resolution: {integrity: sha512-eAVKTMedR5ckPo4xne/PjYQYrU3qx78gtJZ+sHlXEg5IHhhoQhMfZVzetTYuaJS0L2Ef3AcCRzCHV8T0WI6nIQ==} + engines: {node: '>=20'} + + sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + + sitemap@9.0.1: + resolution: {integrity: sha512-S6hzjGJSG3d6if0YoF5kTyeRJvia6FSTBroE5fQ0bu1QNxyJqhhinfUsXi9fH3MgtXODWvwo2BDyQSnhPQ88uQ==} + engines: {node: '>=20.19.5', npm: '>=10.8.2'} + hasBin: true + + smol-toml@1.6.1: + resolution: {integrity: sha512-dWUG8F5sIIARXih1DTaQAX4SsiTXhInKf1buxdY9DIg4ZYPZK5nGM1VRIYmEbDbsHt7USo99xSLFu5Q1IqTmsg==} + engines: {node: '>= 18'} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + source-map@0.7.6: + resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==} + engines: {node: '>= 12'} + + space-separated-tokens@2.0.2: + resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} + + stream-replace-string@2.0.0: + resolution: {integrity: sha512-TlnjJ1C0QrmxRNrON00JvaFFlNh5TTG00APw23j74ET7gkQpTASi6/L2fuiav8pzK715HXtUeClpBTw2NPSn6w==} + + stringify-entities@4.0.4: + resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} + + style-to-js@1.1.21: + resolution: {integrity: sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==} + + style-to-object@1.0.14: + resolution: {integrity: sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==} + + svgo@4.0.1: + resolution: {integrity: sha512-XDpWUOPC6FEibaLzjfe0ucaV0YrOjYotGJO1WpF0Zd+n6ZGEQUsSugaoLq9QkEZtAfQIxT42UChcssDVPP3+/w==} + engines: {node: '>=16'} + hasBin: true + + tiny-inflate@1.0.3: + resolution: {integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==} + + tinyclip@0.1.12: + resolution: {integrity: sha512-Ae3OVUqifDw0wBriIBS7yVaW44Dp6eSHQcyq4Igc7eN2TJH/2YsicswaW+J/OuMvhpDPOKEgpAZCjkb4hpoyeA==} + engines: {node: ^16.14.0 || >= 17.3.0} + + tinyexec@1.1.2: + resolution: {integrity: sha512-dAqSqE/RabpBKI8+h26GfLq6Vb3JVXs30XYQjdMjaj/c2tS8IYYMbIzP599KtRj7c57/wYApb3QjgRgXmrCukA==} + engines: {node: '>=18'} + + tinyglobby@0.2.16: + resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==} + engines: {node: '>=12.0.0'} + + trim-lines@3.0.1: + resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} + + trough@2.2.0: + resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + typescript@6.0.3: + resolution: {integrity: sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==} + engines: {node: '>=14.17'} + hasBin: true + + ufo@1.6.4: + resolution: {integrity: sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==} + + ultrahtml@1.6.0: + resolution: {integrity: sha512-R9fBn90VTJrqqLDwyMph+HGne8eqY1iPfYhPzZrvKpIfwkWZbcYlfpsb8B9dTvBfpy1/hqAD7Wi8EKfP9e8zdw==} + + uncrypto@0.1.3: + resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==} + + undici-types@7.16.0: + resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} + + unified@11.0.5: + resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==} + + unifont@0.7.4: + resolution: {integrity: sha512-oHeis4/xl42HUIeHuNZRGEvxj5AaIKR+bHPNegRq5LV1gdc3jundpONbjglKpihmJf+dswygdMJn3eftGIMemg==} + + unist-util-find-after@5.0.0: + resolution: {integrity: sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==} + + unist-util-is@6.0.1: + resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==} + + unist-util-modify-children@4.0.0: + resolution: {integrity: sha512-+tdN5fGNddvsQdIzUF3Xx82CU9sMM+fA0dLgR9vOmT0oPT2jH+P1nd5lSqfCfXAw+93NhcXNY2qqvTUtE4cQkw==} + + unist-util-position-from-estree@2.0.0: + resolution: {integrity: sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==} + + unist-util-position@5.0.0: + resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==} + + unist-util-remove-position@5.0.0: + resolution: {integrity: sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==} + + unist-util-stringify-position@4.0.0: + resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} + + unist-util-visit-children@3.0.0: + resolution: {integrity: sha512-RgmdTfSBOg04sdPcpTSD1jzoNBjt9a80/ZCzp5cI9n1qPzLZWF9YdvWGN2zmTumP1HWhXKdUWexjy/Wy/lJ7tA==} + + unist-util-visit-parents@6.0.2: + resolution: {integrity: sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==} + + unist-util-visit@5.1.0: + resolution: {integrity: sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==} + + unstorage@1.17.5: + resolution: {integrity: sha512-0i3iqvRfx29hkNntHyQvJTpf5W9dQ9ZadSoRU8+xVlhVtT7jAX57fazYO9EHvcRCfBCyi5YRya7XCDOsbTgkPg==} + peerDependencies: + '@azure/app-configuration': ^1.8.0 + '@azure/cosmos': ^4.2.0 + '@azure/data-tables': ^13.3.0 + '@azure/identity': ^4.6.0 + '@azure/keyvault-secrets': ^4.9.0 + '@azure/storage-blob': ^12.26.0 + '@capacitor/preferences': ^6 || ^7 || ^8 + '@deno/kv': '>=0.9.0' + '@netlify/blobs': ^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0 + '@planetscale/database': ^1.19.0 + '@upstash/redis': ^1.34.3 + '@vercel/blob': '>=0.27.1' + '@vercel/functions': ^2.2.12 || ^3.0.0 + '@vercel/kv': ^1 || ^2 || ^3 + aws4fetch: ^1.0.20 + db0: '>=0.2.1' + idb-keyval: ^6.2.1 + ioredis: ^5.4.2 + uploadthing: ^7.4.4 + peerDependenciesMeta: + '@azure/app-configuration': + optional: true + '@azure/cosmos': + optional: true + '@azure/data-tables': + optional: true + '@azure/identity': + optional: true + '@azure/keyvault-secrets': + optional: true + '@azure/storage-blob': + optional: true + '@capacitor/preferences': + optional: true + '@deno/kv': + optional: true + '@netlify/blobs': + optional: true + '@planetscale/database': + optional: true + '@upstash/redis': + optional: true + '@vercel/blob': + optional: true + '@vercel/functions': + optional: true + '@vercel/kv': + optional: true + aws4fetch: + optional: true + db0: + optional: true + idb-keyval: + optional: true + ioredis: + optional: true + uploadthing: + optional: true + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + vfile-location@5.0.3: + resolution: {integrity: sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==} + + vfile-message@4.0.3: + resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==} + + vfile@6.0.3: + resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} + + vite@7.3.3: + resolution: {integrity: sha512-/4XH147Ui7OGTjg3HbdWe5arnZQSbfuRzdr9Ec7TQi5I7R+ir0Rlc9GIvD4v0XZurELqA035KVXJXpR61xhiTA==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + jiti: '>=1.21.0' + less: ^4.0.0 + lightningcss: ^1.21.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vitefu@1.1.3: + resolution: {integrity: sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg==} + peerDependencies: + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + vite: + optional: true + + web-namespaces@2.0.1: + resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==} + + which-pm-runs@1.1.0: + resolution: {integrity: sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==} + engines: {node: '>=4'} + + xxhash-wasm@1.1.0: + resolution: {integrity: sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==} + + yargs-parser@22.0.0: + resolution: {integrity: sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==} + engines: {node: ^20.19.0 || ^22.12.0 || >=23} + + yocto-queue@1.2.2: + resolution: {integrity: sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==} + engines: {node: '>=12.20'} + + zod@4.4.3: + resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==} + + zwitch@2.0.4: + resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} + +snapshots: + + '@astrojs/compiler@4.0.0': {} + + '@astrojs/internal-helpers@0.9.0': + dependencies: + picomatch: 4.0.4 + + '@astrojs/markdown-remark@7.1.1': + dependencies: + '@astrojs/internal-helpers': 0.9.0 + '@astrojs/prism': 4.0.1 + github-slugger: 2.0.0 + hast-util-from-html: 2.0.3 + hast-util-to-text: 4.0.2 + js-yaml: 4.1.1 + mdast-util-definitions: 6.0.0 + rehype-raw: 7.0.0 + rehype-stringify: 10.0.1 + remark-gfm: 4.0.1 + remark-parse: 11.0.0 + remark-rehype: 11.1.2 + remark-smartypants: 3.0.2 + retext-smartypants: 6.2.0 + shiki: 4.0.2 + smol-toml: 1.6.1 + unified: 11.0.5 + unist-util-remove-position: 5.0.0 + unist-util-visit: 5.1.0 + unist-util-visit-parents: 6.0.2 + vfile: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@astrojs/mdx@5.0.4(astro@6.3.1(@types/node@24.12.3)(rollup@4.60.3))': + dependencies: + '@astrojs/markdown-remark': 7.1.1 + '@mdx-js/mdx': 3.1.1 + acorn: 8.16.0 + astro: 6.3.1(@types/node@24.12.3)(rollup@4.60.3) + es-module-lexer: 2.1.0 + estree-util-visit: 2.0.0 + hast-util-to-html: 9.0.5 + piccolore: 0.1.3 + rehype-raw: 7.0.0 + remark-gfm: 4.0.1 + remark-smartypants: 3.0.2 + source-map: 0.7.6 + unist-util-visit: 5.1.0 + vfile: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@astrojs/prism@4.0.1': + dependencies: + prismjs: 1.30.0 + + '@astrojs/sitemap@3.7.2': + dependencies: + sitemap: 9.0.1 + stream-replace-string: 2.0.0 + zod: 4.4.3 + + '@astrojs/starlight@0.39.1(astro@6.3.1(@types/node@24.12.3)(rollup@4.60.3))(typescript@6.0.3)': + dependencies: + '@astrojs/markdown-remark': 7.1.1 + '@astrojs/mdx': 5.0.4(astro@6.3.1(@types/node@24.12.3)(rollup@4.60.3)) + '@astrojs/sitemap': 3.7.2 + '@pagefind/default-ui': 1.5.2 + '@types/hast': 3.0.4 + '@types/js-yaml': 4.0.9 + '@types/mdast': 4.0.4 + astro: 6.3.1(@types/node@24.12.3)(rollup@4.60.3) + astro-expressive-code: 0.42.0(astro@6.3.1(@types/node@24.12.3)(rollup@4.60.3)) + bcp-47: 2.1.0 + hast-util-from-html: 2.0.3 + hast-util-select: 6.0.4 + hast-util-to-string: 3.0.1 + hastscript: 9.0.1 + i18next: 26.0.10(typescript@6.0.3) + js-yaml: 4.1.1 + klona: 2.0.6 + magic-string: 0.30.21 + mdast-util-directive: 3.1.0 + mdast-util-to-markdown: 2.1.2 + mdast-util-to-string: 4.0.0 + pagefind: 1.5.2 + rehype: 13.0.2 + rehype-format: 5.0.1 + remark-directive: 4.0.0 + ultrahtml: 1.6.0 + unified: 11.0.5 + unist-util-visit: 5.1.0 + vfile: 6.0.3 + transitivePeerDependencies: + - supports-color + - typescript + + '@astrojs/telemetry@3.3.2': + dependencies: + ci-info: 4.4.0 + dset: 3.1.4 + is-docker: 4.0.0 + is-wsl: 3.1.1 + which-pm-runs: 1.1.0 + + '@babel/helper-string-parser@7.27.1': {} + + '@babel/helper-validator-identifier@7.28.5': {} + + '@babel/parser@7.29.3': + dependencies: + '@babel/types': 7.29.0 + + '@babel/types@7.29.0': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + + '@capsizecss/unpack@4.0.0': + dependencies: + fontkitten: 1.0.3 + + '@clack/core@1.3.0': + dependencies: + fast-wrap-ansi: 0.2.0 + sisteransi: 1.0.5 + + '@clack/prompts@1.3.0': + dependencies: + '@clack/core': 1.3.0 + fast-string-width: 3.0.2 + fast-wrap-ansi: 0.2.0 + sisteransi: 1.0.5 + + '@ctrl/tinycolor@4.2.0': {} + + '@emnapi/runtime@1.10.0': + dependencies: + tslib: 2.8.1 + optional: true + + '@esbuild/aix-ppc64@0.27.7': + optional: true + + '@esbuild/android-arm64@0.27.7': + optional: true + + '@esbuild/android-arm@0.27.7': + optional: true + + '@esbuild/android-x64@0.27.7': + optional: true + + '@esbuild/darwin-arm64@0.27.7': + optional: true + + '@esbuild/darwin-x64@0.27.7': + optional: true + + '@esbuild/freebsd-arm64@0.27.7': + optional: true + + '@esbuild/freebsd-x64@0.27.7': + optional: true + + '@esbuild/linux-arm64@0.27.7': + optional: true + + '@esbuild/linux-arm@0.27.7': + optional: true + + '@esbuild/linux-ia32@0.27.7': + optional: true + + '@esbuild/linux-loong64@0.27.7': + optional: true + + '@esbuild/linux-mips64el@0.27.7': + optional: true + + '@esbuild/linux-ppc64@0.27.7': + optional: true + + '@esbuild/linux-riscv64@0.27.7': + optional: true + + '@esbuild/linux-s390x@0.27.7': + optional: true + + '@esbuild/linux-x64@0.27.7': + optional: true + + '@esbuild/netbsd-arm64@0.27.7': + optional: true + + '@esbuild/netbsd-x64@0.27.7': + optional: true + + '@esbuild/openbsd-arm64@0.27.7': + optional: true + + '@esbuild/openbsd-x64@0.27.7': + optional: true + + '@esbuild/openharmony-arm64@0.27.7': + optional: true + + '@esbuild/sunos-x64@0.27.7': + optional: true + + '@esbuild/win32-arm64@0.27.7': + optional: true + + '@esbuild/win32-ia32@0.27.7': + optional: true + + '@esbuild/win32-x64@0.27.7': + optional: true + + '@expressive-code/core@0.42.0': + dependencies: + '@ctrl/tinycolor': 4.2.0 + hast-util-select: 6.0.4 + hast-util-to-html: 9.0.5 + hast-util-to-text: 4.0.2 + hastscript: 9.0.1 + postcss: 8.5.14 + postcss-nested: 6.2.0(postcss@8.5.14) + unist-util-visit: 5.1.0 + unist-util-visit-parents: 6.0.2 + + '@expressive-code/plugin-frames@0.42.0': + dependencies: + '@expressive-code/core': 0.42.0 + + '@expressive-code/plugin-shiki@0.42.0': + dependencies: + '@expressive-code/core': 0.42.0 + shiki: 4.0.2 + + '@expressive-code/plugin-text-markers@0.42.0': + dependencies: + '@expressive-code/core': 0.42.0 + + '@img/colour@1.1.0': + optional: true + + '@img/sharp-darwin-arm64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.2.4 + optional: true + + '@img/sharp-darwin-x64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.2.4 + optional: true + + '@img/sharp-libvips-darwin-arm64@1.2.4': + optional: true + + '@img/sharp-libvips-darwin-x64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-arm64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-arm@1.2.4': + optional: true + + '@img/sharp-libvips-linux-ppc64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-riscv64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-s390x@1.2.4': + optional: true + + '@img/sharp-libvips-linux-x64@1.2.4': + optional: true + + '@img/sharp-libvips-linuxmusl-arm64@1.2.4': + optional: true + + '@img/sharp-libvips-linuxmusl-x64@1.2.4': + optional: true + + '@img/sharp-linux-arm64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.2.4 + optional: true + + '@img/sharp-linux-arm@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.2.4 + optional: true + + '@img/sharp-linux-ppc64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-ppc64': 1.2.4 + optional: true + + '@img/sharp-linux-riscv64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-riscv64': 1.2.4 + optional: true + + '@img/sharp-linux-s390x@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-s390x': 1.2.4 + optional: true + + '@img/sharp-linux-x64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.2.4 + optional: true + + '@img/sharp-linuxmusl-arm64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.2.4 + optional: true + + '@img/sharp-linuxmusl-x64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.2.4 + optional: true + + '@img/sharp-wasm32@0.34.5': + dependencies: + '@emnapi/runtime': 1.10.0 + optional: true + + '@img/sharp-win32-arm64@0.34.5': + optional: true + + '@img/sharp-win32-ia32@0.34.5': + optional: true + + '@img/sharp-win32-x64@0.34.5': + optional: true + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@mdx-js/mdx@3.1.1': + dependencies: + '@types/estree': 1.0.9 + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 + '@types/mdx': 2.0.13 + acorn: 8.16.0 + collapse-white-space: 2.1.0 + devlop: 1.1.0 + estree-util-is-identifier-name: 3.0.0 + estree-util-scope: 1.0.0 + estree-walker: 3.0.3 + hast-util-to-jsx-runtime: 2.3.6 + markdown-extensions: 2.0.0 + recma-build-jsx: 1.0.0 + recma-jsx: 1.0.1(acorn@8.16.0) + recma-stringify: 1.0.0 + rehype-recma: 1.0.0 + remark-mdx: 3.1.1 + remark-parse: 11.0.0 + remark-rehype: 11.1.2 + source-map: 0.7.6 + unified: 11.0.5 + unist-util-position-from-estree: 2.0.0 + unist-util-stringify-position: 4.0.0 + unist-util-visit: 5.1.0 + vfile: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@oslojs/encoding@1.1.0': {} + + '@pagefind/darwin-arm64@1.5.2': + optional: true + + '@pagefind/darwin-x64@1.5.2': + optional: true + + '@pagefind/default-ui@1.5.2': {} + + '@pagefind/freebsd-x64@1.5.2': + optional: true + + '@pagefind/linux-arm64@1.5.2': + optional: true + + '@pagefind/linux-x64@1.5.2': + optional: true + + '@pagefind/windows-arm64@1.5.2': + optional: true + + '@pagefind/windows-x64@1.5.2': + optional: true + + '@rollup/pluginutils@5.3.0(rollup@4.60.3)': + dependencies: + '@types/estree': 1.0.9 + estree-walker: 2.0.2 + picomatch: 4.0.4 + optionalDependencies: + rollup: 4.60.3 + + '@rollup/rollup-android-arm-eabi@4.60.3': + optional: true + + '@rollup/rollup-android-arm64@4.60.3': + optional: true + + '@rollup/rollup-darwin-arm64@4.60.3': + optional: true + + '@rollup/rollup-darwin-x64@4.60.3': + optional: true + + '@rollup/rollup-freebsd-arm64@4.60.3': + optional: true + + '@rollup/rollup-freebsd-x64@4.60.3': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.60.3': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.60.3': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.60.3': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.60.3': + optional: true + + '@rollup/rollup-linux-loong64-gnu@4.60.3': + optional: true + + '@rollup/rollup-linux-loong64-musl@4.60.3': + optional: true + + '@rollup/rollup-linux-ppc64-gnu@4.60.3': + optional: true + + '@rollup/rollup-linux-ppc64-musl@4.60.3': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.60.3': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.60.3': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.60.3': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.60.3': + optional: true + + '@rollup/rollup-linux-x64-musl@4.60.3': + optional: true + + '@rollup/rollup-openbsd-x64@4.60.3': + optional: true + + '@rollup/rollup-openharmony-arm64@4.60.3': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.60.3': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.60.3': + optional: true + + '@rollup/rollup-win32-x64-gnu@4.60.3': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.60.3': + optional: true + + '@shikijs/core@4.0.2': + dependencies: + '@shikijs/primitive': 4.0.2 + '@shikijs/types': 4.0.2 + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 + hast-util-to-html: 9.0.5 + + '@shikijs/engine-javascript@4.0.2': + dependencies: + '@shikijs/types': 4.0.2 + '@shikijs/vscode-textmate': 10.0.2 + oniguruma-to-es: 4.3.6 + + '@shikijs/engine-oniguruma@4.0.2': + dependencies: + '@shikijs/types': 4.0.2 + '@shikijs/vscode-textmate': 10.0.2 + + '@shikijs/langs@4.0.2': + dependencies: + '@shikijs/types': 4.0.2 + + '@shikijs/primitive@4.0.2': + dependencies: + '@shikijs/types': 4.0.2 + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 + + '@shikijs/themes@4.0.2': + dependencies: + '@shikijs/types': 4.0.2 + + '@shikijs/types@4.0.2': + dependencies: + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 + + '@shikijs/vscode-textmate@10.0.2': {} + + '@types/debug@4.1.13': + dependencies: + '@types/ms': 2.1.0 + + '@types/estree-jsx@1.0.5': + dependencies: + '@types/estree': 1.0.9 + + '@types/estree@1.0.8': {} + + '@types/estree@1.0.9': {} + + '@types/hast@3.0.4': + dependencies: + '@types/unist': 3.0.3 + + '@types/js-yaml@4.0.9': {} + + '@types/mdast@4.0.4': + dependencies: + '@types/unist': 3.0.3 + + '@types/mdx@2.0.13': {} + + '@types/ms@2.1.0': {} + + '@types/nlcst@2.0.3': + dependencies: + '@types/unist': 3.0.3 + + '@types/node@24.12.3': + dependencies: + undici-types: 7.16.0 + + '@types/sax@1.2.7': + dependencies: + '@types/node': 24.12.3 + + '@types/unist@2.0.11': {} + + '@types/unist@3.0.3': {} + + '@ungap/structured-clone@1.3.1': {} + + acorn-jsx@5.3.2(acorn@8.16.0): + dependencies: + acorn: 8.16.0 + + acorn@8.16.0: {} + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.2 + + arg@5.0.2: {} + + argparse@2.0.1: {} + + aria-query@5.3.2: {} + + array-iterate@2.0.1: {} + + astring@1.9.0: {} + + astro-expressive-code@0.42.0(astro@6.3.1(@types/node@24.12.3)(rollup@4.60.3)): + dependencies: + astro: 6.3.1(@types/node@24.12.3)(rollup@4.60.3) + rehype-expressive-code: 0.42.0 + + astro@6.3.1(@types/node@24.12.3)(rollup@4.60.3): + dependencies: + '@astrojs/compiler': 4.0.0 + '@astrojs/internal-helpers': 0.9.0 + '@astrojs/markdown-remark': 7.1.1 + '@astrojs/telemetry': 3.3.2 + '@capsizecss/unpack': 4.0.0 + '@clack/prompts': 1.3.0 + '@oslojs/encoding': 1.1.0 + '@rollup/pluginutils': 5.3.0(rollup@4.60.3) + aria-query: 5.3.2 + axobject-query: 4.1.0 + ci-info: 4.4.0 + clsx: 2.1.1 + common-ancestor-path: 2.0.0 + cookie: 1.1.1 + devalue: 5.8.0 + diff: 8.0.4 + dset: 3.1.4 + es-module-lexer: 2.1.0 + esbuild: 0.27.7 + flattie: 1.1.1 + fontace: 0.4.1 + get-tsconfig: 5.0.0-beta.4 + github-slugger: 2.0.0 + html-escaper: 3.0.3 + http-cache-semantics: 4.2.0 + js-yaml: 4.1.1 + jsonc-parser: 3.3.1 + magic-string: 0.30.21 + magicast: 0.5.2 + mrmime: 2.0.1 + neotraverse: 0.6.18 + obug: 2.1.1 + p-limit: 7.3.0 + p-queue: 9.2.0 + package-manager-detector: 1.6.0 + piccolore: 0.1.3 + picomatch: 4.0.4 + rehype: 13.0.2 + semver: 7.7.4 + shiki: 4.0.2 + smol-toml: 1.6.1 + svgo: 4.0.1 + tinyclip: 0.1.12 + tinyexec: 1.1.2 + tinyglobby: 0.2.16 + ultrahtml: 1.6.0 + unifont: 0.7.4 + unist-util-visit: 5.1.0 + unstorage: 1.17.5 + vfile: 6.0.3 + vite: 7.3.3(@types/node@24.12.3) + vitefu: 1.1.3(vite@7.3.3(@types/node@24.12.3)) + xxhash-wasm: 1.1.0 + yargs-parser: 22.0.0 + zod: 4.4.3 + optionalDependencies: + sharp: 0.34.5 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@types/node' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - db0 + - idb-keyval + - ioredis + - jiti + - less + - lightningcss + - rollup + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - uploadthing + - yaml + + axobject-query@4.1.0: {} + + bail@2.0.2: {} + + bcp-47-match@2.0.3: {} + + bcp-47@2.1.0: + dependencies: + is-alphabetical: 2.0.1 + is-alphanumerical: 2.0.1 + is-decimal: 2.0.1 + + boolbase@1.0.0: {} + + ccount@2.0.1: {} + + character-entities-html4@2.1.0: {} + + character-entities-legacy@3.0.0: {} + + character-entities@2.0.2: {} + + character-reference-invalid@2.0.1: {} + + chokidar@5.0.0: + dependencies: + readdirp: 5.0.0 + + ci-info@4.4.0: {} + + clsx@2.1.1: {} + + collapse-white-space@2.1.0: {} + + comma-separated-tokens@2.0.3: {} + + commander@11.1.0: {} + + common-ancestor-path@2.0.0: {} + + cookie-es@1.2.3: {} + + cookie@1.1.1: {} + + crossws@0.3.5: + dependencies: + uncrypto: 0.1.3 + + css-select@5.2.2: + dependencies: + boolbase: 1.0.0 + css-what: 6.2.2 + domhandler: 5.0.3 + domutils: 3.2.2 + nth-check: 2.1.1 + + css-selector-parser@3.3.0: {} + + css-tree@2.2.1: + dependencies: + mdn-data: 2.0.28 + source-map-js: 1.2.1 + + css-tree@3.2.1: + dependencies: + mdn-data: 2.27.1 + source-map-js: 1.2.1 + + css-what@6.2.2: {} + + cssesc@3.0.0: {} + + csso@5.0.5: + dependencies: + css-tree: 2.2.1 + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + decode-named-character-reference@1.3.0: + dependencies: + character-entities: 2.0.2 + + defu@6.1.7: {} + + dequal@2.0.3: {} + + destr@2.0.5: {} + + detect-libc@2.1.2: + optional: true + + devalue@5.8.0: {} + + devlop@1.1.0: + dependencies: + dequal: 2.0.3 + + diff@8.0.4: {} + + direction@2.0.1: {} + + dom-serializer@2.0.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + entities: 4.5.0 + + domelementtype@2.3.0: {} + + domhandler@5.0.3: + dependencies: + domelementtype: 2.3.0 + + domutils@3.2.2: + dependencies: + dom-serializer: 2.0.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + + dset@3.1.4: {} + + entities@4.5.0: {} + + entities@6.0.1: {} + + es-module-lexer@2.1.0: {} + + esast-util-from-estree@2.0.0: + dependencies: + '@types/estree-jsx': 1.0.5 + devlop: 1.1.0 + estree-util-visit: 2.0.0 + unist-util-position-from-estree: 2.0.0 + + esast-util-from-js@2.0.1: + dependencies: + '@types/estree-jsx': 1.0.5 + acorn: 8.16.0 + esast-util-from-estree: 2.0.0 + vfile-message: 4.0.3 + + esbuild@0.27.7: + optionalDependencies: + '@esbuild/aix-ppc64': 0.27.7 + '@esbuild/android-arm': 0.27.7 + '@esbuild/android-arm64': 0.27.7 + '@esbuild/android-x64': 0.27.7 + '@esbuild/darwin-arm64': 0.27.7 + '@esbuild/darwin-x64': 0.27.7 + '@esbuild/freebsd-arm64': 0.27.7 + '@esbuild/freebsd-x64': 0.27.7 + '@esbuild/linux-arm': 0.27.7 + '@esbuild/linux-arm64': 0.27.7 + '@esbuild/linux-ia32': 0.27.7 + '@esbuild/linux-loong64': 0.27.7 + '@esbuild/linux-mips64el': 0.27.7 + '@esbuild/linux-ppc64': 0.27.7 + '@esbuild/linux-riscv64': 0.27.7 + '@esbuild/linux-s390x': 0.27.7 + '@esbuild/linux-x64': 0.27.7 + '@esbuild/netbsd-arm64': 0.27.7 + '@esbuild/netbsd-x64': 0.27.7 + '@esbuild/openbsd-arm64': 0.27.7 + '@esbuild/openbsd-x64': 0.27.7 + '@esbuild/openharmony-arm64': 0.27.7 + '@esbuild/sunos-x64': 0.27.7 + '@esbuild/win32-arm64': 0.27.7 + '@esbuild/win32-ia32': 0.27.7 + '@esbuild/win32-x64': 0.27.7 + + escape-string-regexp@5.0.0: {} + + estree-util-attach-comments@3.0.0: + dependencies: + '@types/estree': 1.0.9 + + estree-util-build-jsx@3.0.1: + dependencies: + '@types/estree-jsx': 1.0.5 + devlop: 1.1.0 + estree-util-is-identifier-name: 3.0.0 + estree-walker: 3.0.3 + + estree-util-is-identifier-name@3.0.0: {} + + estree-util-scope@1.0.0: + dependencies: + '@types/estree': 1.0.9 + devlop: 1.1.0 + + estree-util-to-js@2.0.0: + dependencies: + '@types/estree-jsx': 1.0.5 + astring: 1.9.0 + source-map: 0.7.6 + + estree-util-visit@2.0.0: + dependencies: + '@types/estree-jsx': 1.0.5 + '@types/unist': 3.0.3 + + estree-walker@2.0.2: {} + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.9 + + eventemitter3@5.0.4: {} + + expressive-code@0.42.0: + dependencies: + '@expressive-code/core': 0.42.0 + '@expressive-code/plugin-frames': 0.42.0 + '@expressive-code/plugin-shiki': 0.42.0 + '@expressive-code/plugin-text-markers': 0.42.0 + + extend@3.0.2: {} + + fast-string-truncated-width@3.0.3: {} + + fast-string-width@3.0.2: + dependencies: + fast-string-truncated-width: 3.0.3 + + fast-wrap-ansi@0.2.0: + dependencies: + fast-string-width: 3.0.2 + + fdir@6.5.0(picomatch@4.0.4): + optionalDependencies: + picomatch: 4.0.4 + + flattie@1.1.1: {} + + fontace@0.4.1: + dependencies: + fontkitten: 1.0.3 + + fontkitten@1.0.3: + dependencies: + tiny-inflate: 1.0.3 + + fsevents@2.3.3: + optional: true + + get-tsconfig@5.0.0-beta.4: + dependencies: + resolve-pkg-maps: 1.0.0 + + github-slugger@2.0.0: {} + + h3@1.15.11: + dependencies: + cookie-es: 1.2.3 + crossws: 0.3.5 + defu: 6.1.7 + destr: 2.0.5 + iron-webcrypto: 1.2.1 + node-mock-http: 1.0.4 + radix3: 1.1.2 + ufo: 1.6.4 + uncrypto: 0.1.3 + + hast-util-embedded@3.0.0: + dependencies: + '@types/hast': 3.0.4 + hast-util-is-element: 3.0.0 + + hast-util-format@1.1.0: + dependencies: + '@types/hast': 3.0.4 + hast-util-embedded: 3.0.0 + hast-util-minify-whitespace: 1.0.1 + hast-util-phrasing: 3.0.1 + hast-util-whitespace: 3.0.0 + html-whitespace-sensitive-tag-names: 3.0.1 + unist-util-visit-parents: 6.0.2 + + hast-util-from-html@2.0.3: + dependencies: + '@types/hast': 3.0.4 + devlop: 1.1.0 + hast-util-from-parse5: 8.0.3 + parse5: 7.3.0 + vfile: 6.0.3 + vfile-message: 4.0.3 + + hast-util-from-parse5@8.0.3: + dependencies: + '@types/hast': 3.0.4 + '@types/unist': 3.0.3 + devlop: 1.1.0 + hastscript: 9.0.1 + property-information: 7.1.0 + vfile: 6.0.3 + vfile-location: 5.0.3 + web-namespaces: 2.0.1 + + hast-util-has-property@3.0.0: + dependencies: + '@types/hast': 3.0.4 + + hast-util-is-body-ok-link@3.0.1: + dependencies: + '@types/hast': 3.0.4 + + hast-util-is-element@3.0.0: + dependencies: + '@types/hast': 3.0.4 + + hast-util-minify-whitespace@1.0.1: + dependencies: + '@types/hast': 3.0.4 + hast-util-embedded: 3.0.0 + hast-util-is-element: 3.0.0 + hast-util-whitespace: 3.0.0 + unist-util-is: 6.0.1 + + hast-util-parse-selector@4.0.0: + dependencies: + '@types/hast': 3.0.4 + + hast-util-phrasing@3.0.1: + dependencies: + '@types/hast': 3.0.4 + hast-util-embedded: 3.0.0 + hast-util-has-property: 3.0.0 + hast-util-is-body-ok-link: 3.0.1 + hast-util-is-element: 3.0.0 + + hast-util-raw@9.1.0: + dependencies: + '@types/hast': 3.0.4 + '@types/unist': 3.0.3 + '@ungap/structured-clone': 1.3.1 + hast-util-from-parse5: 8.0.3 + hast-util-to-parse5: 8.0.1 + html-void-elements: 3.0.0 + mdast-util-to-hast: 13.2.1 + parse5: 7.3.0 + unist-util-position: 5.0.0 + unist-util-visit: 5.1.0 + vfile: 6.0.3 + web-namespaces: 2.0.1 + zwitch: 2.0.4 + + hast-util-select@6.0.4: + dependencies: + '@types/hast': 3.0.4 + '@types/unist': 3.0.3 + bcp-47-match: 2.0.3 + comma-separated-tokens: 2.0.3 + css-selector-parser: 3.3.0 + devlop: 1.1.0 + direction: 2.0.1 + hast-util-has-property: 3.0.0 + hast-util-to-string: 3.0.1 + hast-util-whitespace: 3.0.0 + nth-check: 2.1.1 + property-information: 7.1.0 + space-separated-tokens: 2.0.2 + unist-util-visit: 5.1.0 + zwitch: 2.0.4 + + hast-util-to-estree@3.1.3: + dependencies: + '@types/estree': 1.0.9 + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 + comma-separated-tokens: 2.0.3 + devlop: 1.1.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.1 + mdast-util-mdx-jsx: 3.2.0 + mdast-util-mdxjs-esm: 2.0.1 + property-information: 7.1.0 + space-separated-tokens: 2.0.2 + style-to-js: 1.1.21 + unist-util-position: 5.0.0 + zwitch: 2.0.4 + transitivePeerDependencies: + - supports-color + + hast-util-to-html@9.0.5: + dependencies: + '@types/hast': 3.0.4 + '@types/unist': 3.0.3 + ccount: 2.0.1 + comma-separated-tokens: 2.0.3 + hast-util-whitespace: 3.0.0 + html-void-elements: 3.0.0 + mdast-util-to-hast: 13.2.1 + property-information: 7.1.0 + space-separated-tokens: 2.0.2 + stringify-entities: 4.0.4 + zwitch: 2.0.4 + + hast-util-to-jsx-runtime@2.3.6: + dependencies: + '@types/estree': 1.0.9 + '@types/hast': 3.0.4 + '@types/unist': 3.0.3 + comma-separated-tokens: 2.0.3 + devlop: 1.1.0 + estree-util-is-identifier-name: 3.0.0 + hast-util-whitespace: 3.0.0 + mdast-util-mdx-expression: 2.0.1 + mdast-util-mdx-jsx: 3.2.0 + mdast-util-mdxjs-esm: 2.0.1 + property-information: 7.1.0 + space-separated-tokens: 2.0.2 + style-to-js: 1.1.21 + unist-util-position: 5.0.0 + vfile-message: 4.0.3 + transitivePeerDependencies: + - supports-color + + hast-util-to-parse5@8.0.1: + dependencies: + '@types/hast': 3.0.4 + comma-separated-tokens: 2.0.3 + devlop: 1.1.0 + property-information: 7.1.0 + space-separated-tokens: 2.0.2 + web-namespaces: 2.0.1 + zwitch: 2.0.4 + + hast-util-to-string@3.0.1: + dependencies: + '@types/hast': 3.0.4 + + hast-util-to-text@4.0.2: + dependencies: + '@types/hast': 3.0.4 + '@types/unist': 3.0.3 + hast-util-is-element: 3.0.0 + unist-util-find-after: 5.0.0 + + hast-util-whitespace@3.0.0: + dependencies: + '@types/hast': 3.0.4 + + hastscript@9.0.1: + dependencies: + '@types/hast': 3.0.4 + comma-separated-tokens: 2.0.3 + hast-util-parse-selector: 4.0.0 + property-information: 7.1.0 + space-separated-tokens: 2.0.2 + + html-escaper@3.0.3: {} + + html-void-elements@3.0.0: {} + + html-whitespace-sensitive-tag-names@3.0.1: {} + + http-cache-semantics@4.2.0: {} + + i18next@26.0.10(typescript@6.0.3): + optionalDependencies: + typescript: 6.0.3 + + inline-style-parser@0.2.7: {} + + iron-webcrypto@1.2.1: {} + + is-alphabetical@2.0.1: {} + + is-alphanumerical@2.0.1: + dependencies: + is-alphabetical: 2.0.1 + is-decimal: 2.0.1 + + is-decimal@2.0.1: {} + + is-docker@3.0.0: {} + + is-docker@4.0.0: {} + + is-hexadecimal@2.0.1: {} + + is-inside-container@1.0.0: + dependencies: + is-docker: 3.0.0 + + is-plain-obj@4.1.0: {} + + is-wsl@3.1.1: + dependencies: + is-inside-container: 1.0.0 + + js-yaml@4.1.1: + dependencies: + argparse: 2.0.1 + + jsonc-parser@3.3.1: {} + + klona@2.0.6: {} + + longest-streak@3.1.0: {} + + lru-cache@11.3.6: {} + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + magicast@0.5.2: + dependencies: + '@babel/parser': 7.29.3 + '@babel/types': 7.29.0 + source-map-js: 1.2.1 + + markdown-extensions@2.0.0: {} + + markdown-table@3.0.4: {} + + mdast-util-definitions@6.0.0: + dependencies: + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + unist-util-visit: 5.1.0 + + mdast-util-directive@3.1.0: + dependencies: + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + ccount: 2.0.1 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.3 + mdast-util-to-markdown: 2.1.2 + parse-entities: 4.0.2 + stringify-entities: 4.0.4 + unist-util-visit-parents: 6.0.2 + transitivePeerDependencies: + - supports-color + + mdast-util-find-and-replace@3.0.2: + dependencies: + '@types/mdast': 4.0.4 + escape-string-regexp: 5.0.0 + unist-util-is: 6.0.1 + unist-util-visit-parents: 6.0.2 + + mdast-util-from-markdown@2.0.3: + dependencies: + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + decode-named-character-reference: 1.3.0 + devlop: 1.1.0 + mdast-util-to-string: 4.0.0 + micromark: 4.0.2 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-decode-string: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + unist-util-stringify-position: 4.0.0 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm-autolink-literal@2.0.1: + dependencies: + '@types/mdast': 4.0.4 + ccount: 2.0.1 + devlop: 1.1.0 + mdast-util-find-and-replace: 3.0.2 + micromark-util-character: 2.1.1 + + mdast-util-gfm-footnote@2.1.0: + dependencies: + '@types/mdast': 4.0.4 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.3 + mdast-util-to-markdown: 2.1.2 + micromark-util-normalize-identifier: 2.0.1 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm-strikethrough@2.0.0: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-from-markdown: 2.0.3 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm-table@2.0.0: + dependencies: + '@types/mdast': 4.0.4 + devlop: 1.1.0 + markdown-table: 3.0.4 + mdast-util-from-markdown: 2.0.3 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm-task-list-item@2.0.0: + dependencies: + '@types/mdast': 4.0.4 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.3 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm@3.1.0: + dependencies: + mdast-util-from-markdown: 2.0.3 + mdast-util-gfm-autolink-literal: 2.0.1 + mdast-util-gfm-footnote: 2.1.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.1.2 + transitivePeerDependencies: + - supports-color + + mdast-util-mdx-expression@2.0.1: + dependencies: + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.3 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + + mdast-util-mdx-jsx@3.2.0: + dependencies: + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + ccount: 2.0.1 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.3 + mdast-util-to-markdown: 2.1.2 + parse-entities: 4.0.2 + stringify-entities: 4.0.4 + unist-util-stringify-position: 4.0.0 + vfile-message: 4.0.3 + transitivePeerDependencies: + - supports-color + + mdast-util-mdx@3.0.0: + dependencies: + mdast-util-from-markdown: 2.0.3 + mdast-util-mdx-expression: 2.0.1 + mdast-util-mdx-jsx: 3.2.0 + mdast-util-mdxjs-esm: 2.0.1 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + + mdast-util-mdxjs-esm@2.0.1: + dependencies: + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.3 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + + mdast-util-phrasing@4.1.0: + dependencies: + '@types/mdast': 4.0.4 + unist-util-is: 6.0.1 + + mdast-util-to-hast@13.2.1: + dependencies: + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + '@ungap/structured-clone': 1.3.1 + devlop: 1.1.0 + micromark-util-sanitize-uri: 2.0.1 + trim-lines: 3.0.1 + unist-util-position: 5.0.0 + unist-util-visit: 5.1.0 + vfile: 6.0.3 + + mdast-util-to-markdown@2.1.2: + dependencies: + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + longest-streak: 3.1.0 + mdast-util-phrasing: 4.1.0 + mdast-util-to-string: 4.0.0 + micromark-util-classify-character: 2.0.1 + micromark-util-decode-string: 2.0.1 + unist-util-visit: 5.1.0 + zwitch: 2.0.4 + + mdast-util-to-string@4.0.0: + dependencies: + '@types/mdast': 4.0.4 + + mdn-data@2.0.28: {} + + mdn-data@2.27.1: {} + + micromark-core-commonmark@2.0.3: + dependencies: + decode-named-character-reference: 1.3.0 + devlop: 1.1.0 + micromark-factory-destination: 2.0.1 + micromark-factory-label: 2.0.1 + micromark-factory-space: 2.0.1 + micromark-factory-title: 2.0.1 + micromark-factory-whitespace: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-chunked: 2.0.1 + micromark-util-classify-character: 2.0.1 + micromark-util-html-tag-name: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-resolve-all: 2.0.1 + micromark-util-subtokenize: 2.1.0 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-directive@4.0.0: + dependencies: + devlop: 1.1.0 + micromark-factory-space: 2.0.1 + micromark-factory-whitespace: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + parse-entities: 4.0.2 + + micromark-extension-gfm-autolink-literal@2.1.0: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-sanitize-uri: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-gfm-footnote@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-core-commonmark: 2.0.3 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-sanitize-uri: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-gfm-strikethrough@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-util-chunked: 2.0.1 + micromark-util-classify-character: 2.0.1 + micromark-util-resolve-all: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-gfm-table@2.1.1: + dependencies: + devlop: 1.1.0 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-gfm-tagfilter@2.0.0: + dependencies: + micromark-util-types: 2.0.2 + + micromark-extension-gfm-task-list-item@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-gfm@3.0.0: + dependencies: + micromark-extension-gfm-autolink-literal: 2.1.0 + micromark-extension-gfm-footnote: 2.1.0 + micromark-extension-gfm-strikethrough: 2.1.0 + micromark-extension-gfm-table: 2.1.1 + micromark-extension-gfm-tagfilter: 2.0.0 + micromark-extension-gfm-task-list-item: 2.1.0 + micromark-util-combine-extensions: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-mdx-expression@3.0.1: + dependencies: + '@types/estree': 1.0.9 + devlop: 1.1.0 + micromark-factory-mdx-expression: 2.0.3 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-events-to-acorn: 2.0.3 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-mdx-jsx@3.0.2: + dependencies: + '@types/estree': 1.0.9 + devlop: 1.1.0 + estree-util-is-identifier-name: 3.0.0 + micromark-factory-mdx-expression: 2.0.3 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-events-to-acorn: 2.0.3 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + vfile-message: 4.0.3 + + micromark-extension-mdx-md@2.0.0: + dependencies: + micromark-util-types: 2.0.2 + + micromark-extension-mdxjs-esm@3.0.0: + dependencies: + '@types/estree': 1.0.9 + devlop: 1.1.0 + micromark-core-commonmark: 2.0.3 + micromark-util-character: 2.1.1 + micromark-util-events-to-acorn: 2.0.3 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + unist-util-position-from-estree: 2.0.0 + vfile-message: 4.0.3 + + micromark-extension-mdxjs@3.0.0: + dependencies: + acorn: 8.16.0 + acorn-jsx: 5.3.2(acorn@8.16.0) + micromark-extension-mdx-expression: 3.0.1 + micromark-extension-mdx-jsx: 3.0.2 + micromark-extension-mdx-md: 2.0.0 + micromark-extension-mdxjs-esm: 3.0.0 + micromark-util-combine-extensions: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-factory-destination@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-factory-label@2.0.1: + dependencies: + devlop: 1.1.0 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-factory-mdx-expression@2.0.3: + dependencies: + '@types/estree': 1.0.9 + devlop: 1.1.0 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-events-to-acorn: 2.0.3 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + unist-util-position-from-estree: 2.0.0 + vfile-message: 4.0.3 + + micromark-factory-space@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-types: 2.0.2 + + micromark-factory-title@2.0.1: + dependencies: + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-factory-whitespace@2.0.1: + dependencies: + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-character@2.1.1: + dependencies: + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-chunked@2.0.1: + dependencies: + micromark-util-symbol: 2.0.1 + + micromark-util-classify-character@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-combine-extensions@2.0.1: + dependencies: + micromark-util-chunked: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-decode-numeric-character-reference@2.0.2: + dependencies: + micromark-util-symbol: 2.0.1 + + micromark-util-decode-string@2.0.1: + dependencies: + decode-named-character-reference: 1.3.0 + micromark-util-character: 2.1.1 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-symbol: 2.0.1 + + micromark-util-encode@2.0.1: {} + + micromark-util-events-to-acorn@2.0.3: + dependencies: + '@types/estree': 1.0.9 + '@types/unist': 3.0.3 + devlop: 1.1.0 + estree-util-visit: 2.0.0 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + vfile-message: 4.0.3 + + micromark-util-html-tag-name@2.0.1: {} + + micromark-util-normalize-identifier@2.0.1: + dependencies: + micromark-util-symbol: 2.0.1 + + micromark-util-resolve-all@2.0.1: + dependencies: + micromark-util-types: 2.0.2 + + micromark-util-sanitize-uri@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-encode: 2.0.1 + micromark-util-symbol: 2.0.1 + + micromark-util-subtokenize@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-util-chunked: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-symbol@2.0.1: {} + + micromark-util-types@2.0.2: {} + + micromark@4.0.2: + dependencies: + '@types/debug': 4.1.13 + debug: 4.4.3 + decode-named-character-reference: 1.3.0 + devlop: 1.1.0 + micromark-core-commonmark: 2.0.3 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-chunked: 2.0.1 + micromark-util-combine-extensions: 2.0.1 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-encode: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-resolve-all: 2.0.1 + micromark-util-sanitize-uri: 2.0.1 + micromark-util-subtokenize: 2.1.0 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + transitivePeerDependencies: + - supports-color + + mrmime@2.0.1: {} + + ms@2.1.3: {} + + nanoid@3.3.12: {} + + neotraverse@0.6.18: {} + + nlcst-to-string@4.0.0: + dependencies: + '@types/nlcst': 2.0.3 + + node-fetch-native@1.6.7: {} + + node-mock-http@1.0.4: {} + + normalize-path@3.0.0: {} + + nth-check@2.1.1: + dependencies: + boolbase: 1.0.0 + + obug@2.1.1: {} + + ofetch@1.5.1: + dependencies: + destr: 2.0.5 + node-fetch-native: 1.6.7 + ufo: 1.6.4 + + ohash@2.0.11: {} + + oniguruma-parser@0.12.2: {} + + oniguruma-to-es@4.3.6: + dependencies: + oniguruma-parser: 0.12.2 + regex: 6.1.0 + regex-recursion: 6.0.2 + + p-limit@7.3.0: + dependencies: + yocto-queue: 1.2.2 + + p-queue@9.2.0: + dependencies: + eventemitter3: 5.0.4 + p-timeout: 7.0.1 + + p-timeout@7.0.1: {} + + package-manager-detector@1.6.0: {} + + pagefind@1.5.2: + optionalDependencies: + '@pagefind/darwin-arm64': 1.5.2 + '@pagefind/darwin-x64': 1.5.2 + '@pagefind/freebsd-x64': 1.5.2 + '@pagefind/linux-arm64': 1.5.2 + '@pagefind/linux-x64': 1.5.2 + '@pagefind/windows-arm64': 1.5.2 + '@pagefind/windows-x64': 1.5.2 + + parse-entities@4.0.2: + dependencies: + '@types/unist': 2.0.11 + character-entities-legacy: 3.0.0 + character-reference-invalid: 2.0.1 + decode-named-character-reference: 1.3.0 + is-alphanumerical: 2.0.1 + is-decimal: 2.0.1 + is-hexadecimal: 2.0.1 + + parse-latin@7.0.0: + dependencies: + '@types/nlcst': 2.0.3 + '@types/unist': 3.0.3 + nlcst-to-string: 4.0.0 + unist-util-modify-children: 4.0.0 + unist-util-visit-children: 3.0.0 + vfile: 6.0.3 + + parse5@7.3.0: + dependencies: + entities: 6.0.1 + + piccolore@0.1.3: {} + + picocolors@1.1.1: {} + + picomatch@2.3.2: {} + + picomatch@4.0.4: {} + + postcss-nested@6.2.0(postcss@8.5.14): + dependencies: + postcss: 8.5.14 + postcss-selector-parser: 6.1.2 + + postcss-selector-parser@6.1.2: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss@8.5.14: + dependencies: + nanoid: 3.3.12 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + prismjs@1.30.0: {} + + property-information@7.1.0: {} + + radix3@1.1.2: {} + + readdirp@5.0.0: {} + + recma-build-jsx@1.0.0: + dependencies: + '@types/estree': 1.0.9 + estree-util-build-jsx: 3.0.1 + vfile: 6.0.3 + + recma-jsx@1.0.1(acorn@8.16.0): + dependencies: + acorn: 8.16.0 + acorn-jsx: 5.3.2(acorn@8.16.0) + estree-util-to-js: 2.0.0 + recma-parse: 1.0.0 + recma-stringify: 1.0.0 + unified: 11.0.5 + + recma-parse@1.0.0: + dependencies: + '@types/estree': 1.0.9 + esast-util-from-js: 2.0.1 + unified: 11.0.5 + vfile: 6.0.3 + + recma-stringify@1.0.0: + dependencies: + '@types/estree': 1.0.9 + estree-util-to-js: 2.0.0 + unified: 11.0.5 + vfile: 6.0.3 + + regex-recursion@6.0.2: + dependencies: + regex-utilities: 2.3.0 + + regex-utilities@2.3.0: {} + + regex@6.1.0: + dependencies: + regex-utilities: 2.3.0 + + rehype-expressive-code@0.42.0: + dependencies: + expressive-code: 0.42.0 + + rehype-format@5.0.1: + dependencies: + '@types/hast': 3.0.4 + hast-util-format: 1.1.0 + + rehype-parse@9.0.1: + dependencies: + '@types/hast': 3.0.4 + hast-util-from-html: 2.0.3 + unified: 11.0.5 + + rehype-raw@7.0.0: + dependencies: + '@types/hast': 3.0.4 + hast-util-raw: 9.1.0 + vfile: 6.0.3 + + rehype-recma@1.0.0: + dependencies: + '@types/estree': 1.0.9 + '@types/hast': 3.0.4 + hast-util-to-estree: 3.1.3 + transitivePeerDependencies: + - supports-color + + rehype-stringify@10.0.1: + dependencies: + '@types/hast': 3.0.4 + hast-util-to-html: 9.0.5 + unified: 11.0.5 + + rehype@13.0.2: + dependencies: + '@types/hast': 3.0.4 + rehype-parse: 9.0.1 + rehype-stringify: 10.0.1 + unified: 11.0.5 + + remark-directive@4.0.0: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-directive: 3.1.0 + micromark-extension-directive: 4.0.0 + unified: 11.0.5 + transitivePeerDependencies: + - supports-color + + remark-gfm@4.0.1: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-gfm: 3.1.0 + micromark-extension-gfm: 3.0.0 + remark-parse: 11.0.0 + remark-stringify: 11.0.0 + unified: 11.0.5 + transitivePeerDependencies: + - supports-color + + remark-mdx@3.1.1: + dependencies: + mdast-util-mdx: 3.0.0 + micromark-extension-mdxjs: 3.0.0 + transitivePeerDependencies: + - supports-color + + remark-parse@11.0.0: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-from-markdown: 2.0.3 + micromark-util-types: 2.0.2 + unified: 11.0.5 + transitivePeerDependencies: + - supports-color + + remark-rehype@11.1.2: + dependencies: + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + mdast-util-to-hast: 13.2.1 + unified: 11.0.5 + vfile: 6.0.3 + + remark-smartypants@3.0.2: + dependencies: + retext: 9.0.0 + retext-smartypants: 6.2.0 + unified: 11.0.5 + unist-util-visit: 5.1.0 + + remark-stringify@11.0.0: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-to-markdown: 2.1.2 + unified: 11.0.5 + + resolve-pkg-maps@1.0.0: {} + + retext-latin@4.0.0: + dependencies: + '@types/nlcst': 2.0.3 + parse-latin: 7.0.0 + unified: 11.0.5 + + retext-smartypants@6.2.0: + dependencies: + '@types/nlcst': 2.0.3 + nlcst-to-string: 4.0.0 + unist-util-visit: 5.1.0 + + retext-stringify@4.0.0: + dependencies: + '@types/nlcst': 2.0.3 + nlcst-to-string: 4.0.0 + unified: 11.0.5 + + retext@9.0.0: + dependencies: + '@types/nlcst': 2.0.3 + retext-latin: 4.0.0 + retext-stringify: 4.0.0 + unified: 11.0.5 + + rollup@4.60.3: + dependencies: + '@types/estree': 1.0.8 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.60.3 + '@rollup/rollup-android-arm64': 4.60.3 + '@rollup/rollup-darwin-arm64': 4.60.3 + '@rollup/rollup-darwin-x64': 4.60.3 + '@rollup/rollup-freebsd-arm64': 4.60.3 + '@rollup/rollup-freebsd-x64': 4.60.3 + '@rollup/rollup-linux-arm-gnueabihf': 4.60.3 + '@rollup/rollup-linux-arm-musleabihf': 4.60.3 + '@rollup/rollup-linux-arm64-gnu': 4.60.3 + '@rollup/rollup-linux-arm64-musl': 4.60.3 + '@rollup/rollup-linux-loong64-gnu': 4.60.3 + '@rollup/rollup-linux-loong64-musl': 4.60.3 + '@rollup/rollup-linux-ppc64-gnu': 4.60.3 + '@rollup/rollup-linux-ppc64-musl': 4.60.3 + '@rollup/rollup-linux-riscv64-gnu': 4.60.3 + '@rollup/rollup-linux-riscv64-musl': 4.60.3 + '@rollup/rollup-linux-s390x-gnu': 4.60.3 + '@rollup/rollup-linux-x64-gnu': 4.60.3 + '@rollup/rollup-linux-x64-musl': 4.60.3 + '@rollup/rollup-openbsd-x64': 4.60.3 + '@rollup/rollup-openharmony-arm64': 4.60.3 + '@rollup/rollup-win32-arm64-msvc': 4.60.3 + '@rollup/rollup-win32-ia32-msvc': 4.60.3 + '@rollup/rollup-win32-x64-gnu': 4.60.3 + '@rollup/rollup-win32-x64-msvc': 4.60.3 + fsevents: 2.3.3 + + sax@1.6.0: {} + + semver@7.7.4: {} + + sharp@0.34.5: + dependencies: + '@img/colour': 1.1.0 + detect-libc: 2.1.2 + semver: 7.7.4 + optionalDependencies: + '@img/sharp-darwin-arm64': 0.34.5 + '@img/sharp-darwin-x64': 0.34.5 + '@img/sharp-libvips-darwin-arm64': 1.2.4 + '@img/sharp-libvips-darwin-x64': 1.2.4 + '@img/sharp-libvips-linux-arm': 1.2.4 + '@img/sharp-libvips-linux-arm64': 1.2.4 + '@img/sharp-libvips-linux-ppc64': 1.2.4 + '@img/sharp-libvips-linux-riscv64': 1.2.4 + '@img/sharp-libvips-linux-s390x': 1.2.4 + '@img/sharp-libvips-linux-x64': 1.2.4 + '@img/sharp-libvips-linuxmusl-arm64': 1.2.4 + '@img/sharp-libvips-linuxmusl-x64': 1.2.4 + '@img/sharp-linux-arm': 0.34.5 + '@img/sharp-linux-arm64': 0.34.5 + '@img/sharp-linux-ppc64': 0.34.5 + '@img/sharp-linux-riscv64': 0.34.5 + '@img/sharp-linux-s390x': 0.34.5 + '@img/sharp-linux-x64': 0.34.5 + '@img/sharp-linuxmusl-arm64': 0.34.5 + '@img/sharp-linuxmusl-x64': 0.34.5 + '@img/sharp-wasm32': 0.34.5 + '@img/sharp-win32-arm64': 0.34.5 + '@img/sharp-win32-ia32': 0.34.5 + '@img/sharp-win32-x64': 0.34.5 + optional: true + + shiki@4.0.2: + dependencies: + '@shikijs/core': 4.0.2 + '@shikijs/engine-javascript': 4.0.2 + '@shikijs/engine-oniguruma': 4.0.2 + '@shikijs/langs': 4.0.2 + '@shikijs/themes': 4.0.2 + '@shikijs/types': 4.0.2 + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 + + sisteransi@1.0.5: {} + + sitemap@9.0.1: + dependencies: + '@types/node': 24.12.3 + '@types/sax': 1.2.7 + arg: 5.0.2 + sax: 1.6.0 + + smol-toml@1.6.1: {} + + source-map-js@1.2.1: {} + + source-map@0.7.6: {} + + space-separated-tokens@2.0.2: {} + + stream-replace-string@2.0.0: {} + + stringify-entities@4.0.4: + dependencies: + character-entities-html4: 2.1.0 + character-entities-legacy: 3.0.0 + + style-to-js@1.1.21: + dependencies: + style-to-object: 1.0.14 + + style-to-object@1.0.14: + dependencies: + inline-style-parser: 0.2.7 + + svgo@4.0.1: + dependencies: + commander: 11.1.0 + css-select: 5.2.2 + css-tree: 3.2.1 + css-what: 6.2.2 + csso: 5.0.5 + picocolors: 1.1.1 + sax: 1.6.0 + + tiny-inflate@1.0.3: {} + + tinyclip@0.1.12: {} + + tinyexec@1.1.2: {} + + tinyglobby@0.2.16: + dependencies: + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 + + trim-lines@3.0.1: {} + + trough@2.2.0: {} + + tslib@2.8.1: + optional: true + + typescript@6.0.3: {} + + ufo@1.6.4: {} + + ultrahtml@1.6.0: {} + + uncrypto@0.1.3: {} + + undici-types@7.16.0: {} + + unified@11.0.5: + dependencies: + '@types/unist': 3.0.3 + bail: 2.0.2 + devlop: 1.1.0 + extend: 3.0.2 + is-plain-obj: 4.1.0 + trough: 2.2.0 + vfile: 6.0.3 + + unifont@0.7.4: + dependencies: + css-tree: 3.2.1 + ofetch: 1.5.1 + ohash: 2.0.11 + + unist-util-find-after@5.0.0: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.1 + + unist-util-is@6.0.1: + dependencies: + '@types/unist': 3.0.3 + + unist-util-modify-children@4.0.0: + dependencies: + '@types/unist': 3.0.3 + array-iterate: 2.0.1 + + unist-util-position-from-estree@2.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-position@5.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-remove-position@5.0.0: + dependencies: + '@types/unist': 3.0.3 + unist-util-visit: 5.1.0 + + unist-util-stringify-position@4.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-visit-children@3.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-visit-parents@6.0.2: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.1 + + unist-util-visit@5.1.0: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.1 + unist-util-visit-parents: 6.0.2 + + unstorage@1.17.5: + dependencies: + anymatch: 3.1.3 + chokidar: 5.0.0 + destr: 2.0.5 + h3: 1.15.11 + lru-cache: 11.3.6 + node-fetch-native: 1.6.7 + ofetch: 1.5.1 + ufo: 1.6.4 + + util-deprecate@1.0.2: {} + + vfile-location@5.0.3: + dependencies: + '@types/unist': 3.0.3 + vfile: 6.0.3 + + vfile-message@4.0.3: + dependencies: + '@types/unist': 3.0.3 + unist-util-stringify-position: 4.0.0 + + vfile@6.0.3: + dependencies: + '@types/unist': 3.0.3 + vfile-message: 4.0.3 + + vite@7.3.3(@types/node@24.12.3): + dependencies: + esbuild: 0.27.7 + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 + postcss: 8.5.14 + rollup: 4.60.3 + tinyglobby: 0.2.16 + optionalDependencies: + '@types/node': 24.12.3 + fsevents: 2.3.3 + + vitefu@1.1.3(vite@7.3.3(@types/node@24.12.3)): + optionalDependencies: + vite: 7.3.3(@types/node@24.12.3) + + web-namespaces@2.0.1: {} + + which-pm-runs@1.1.0: {} + + xxhash-wasm@1.1.0: {} + + yargs-parser@22.0.0: {} + + yocto-queue@1.2.2: {} + + zod@4.4.3: {} + + zwitch@2.0.4: {} diff --git a/docs/src/assets/logo-light.svg b/docs/src/assets/logo-light.svg new file mode 100644 index 000000000..29dacbae3 --- /dev/null +++ b/docs/src/assets/logo-light.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/src/assets/logo.svg b/docs/src/assets/logo.svg new file mode 100644 index 000000000..4574541a7 --- /dev/null +++ b/docs/src/assets/logo.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/docs/src/content.config.ts b/docs/src/content.config.ts new file mode 100644 index 000000000..6a7b7a02b --- /dev/null +++ b/docs/src/content.config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from 'astro:content'; +import { docsLoader } from '@astrojs/starlight/loaders'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), +}; diff --git a/docs/src/content/docs/cli/overview.mdx b/docs/src/content/docs/cli/overview.mdx new file mode 100644 index 000000000..71e7639dc --- /dev/null +++ b/docs/src/content/docs/cli/overview.mdx @@ -0,0 +1,165 @@ +--- +title: CLI overview +description: Command reference for preparing keys, proving, verifying, inspecting circuits, and exporting recursive-verifier inputs. +--- + +`provekit-cli` is the primary entry point for preparing keys, proving, verifying, inspecting circuits, and exporting recursive-verifier inputs. + +**Rust API references:** +[`provekit-common`](https://docs.rs/provekit-common) · +[`provekit-prover`](https://docs.rs/provekit-prover) · +[`provekit-verifier`](https://docs.rs/provekit-verifier) · +[`provekit-r1cs-compiler`](https://docs.rs/provekit-r1cs-compiler). +Unfamiliar terms? See the [glossary](/reference/glossary/). + +From a source checkout, run commands through Cargo: + +```sh +cargo run --release --bin provekit-cli -- [options] +``` + +Most examples below assume the current directory contains a Noir package's `Nargo.toml`. When in doubt, pass explicit artifact paths instead of relying on defaults. + +## Artifact defaults + +| Artifact | Default path | Produced by | Consumed by | +| :--- | :--- | :--- | :--- | +| Prover key | `.pkp` | `prepare` | `prove`, `analyze-pkp`, FFI/WASM provers | +| Verifier key | `.pkv` | `prepare` | `verify`, `show-inputs`, `generate-gnark-inputs`, verifier server | +| Proof | `./proof.np` | `prove` | `verify`, `show-inputs`, `generate-gnark-inputs` | +| Noir inputs | `./Prover.toml` | User / Noir tooling | `prove` | +| Recursive params | `./params_for_recursive_verifier` | `generate-gnark-inputs` | Go/gnark recursive verifier | +| Recursive R1CS | `./r1cs.json` | `generate-gnark-inputs` | Go/gnark recursive verifier, verifier server | + +Default key names come from the enclosing Nargo package name. When a command can't infer the package, pass `--pkp`, `--pkv`, `--prover`, or `--verifier` explicitly. + +## Primary workflow + +```sh +cd noir-examples/basic +cargo run --release --bin provekit-cli -- prepare +cargo run --release --bin provekit-cli -- prove +cargo run --release --bin provekit-cli -- verify +``` + +The same workflow with explicit paths: + +```sh +cargo run --release --bin provekit-cli -- prepare \ + . \ + --pkp artifacts/basic.pkp \ + --pkv artifacts/basic.pkv \ + --hash skyscraper + +cargo run --release --bin provekit-cli -- prove \ + --prover artifacts/basic.pkp \ + --input Prover.toml \ + --out artifacts/proof.np + +cargo run --release --bin provekit-cli -- verify \ + --verifier artifacts/basic.pkv \ + --proof artifacts/proof.np +``` + +Keep the `.pkp`, `.pkv`, proof, inputs, circuit source, compiler backend, and `--hash` choice aligned. Regenerate artifacts after any change to the circuit, inputs, branch, compiler, or hash. + +## `prepare` + +Compile a Noir package and write the ProveKit key files. + +```sh +provekit-cli prepare [program_path] [options] +``` + +| Option | Purpose | +| :--- | :--- | +| `program_path` | Directory containing `Nargo.toml`. Defaults to `.`. | +| `--package ` | Compile a single Noir package from a workspace. | +| `--workspace` | Compile every binary package in a Noir workspace. | +| `--target-dir ` | Override the Noir target directory for compiled artifacts. | +| `--deny-warnings` | Treat Noir warnings as errors. | +| `--silence-warnings` | Suppress Noir warnings. | +| `--print-acir` | Print the compiled ACIR. | +| `--skip-underconstrained-check` | Skip Noir's under-constrained-values check. | +| `--skip-brillig-constraints-check` | Skip the Brillig call-constraints check. | +| `--force` | Force recompilation, ignoring cached artifacts. | +| `--pkp`, `-p ` | Output prover key path. Defaults to `.pkp`. | +| `--pkv`, `-v ` | Output verifier key path. Defaults to `.pkv`. | +| `--hash ` | Merkle commitment hash: `skyscraper`, `sha256`, `keccak`, `blake3`, or `poseidon2`. Defaults to `skyscraper`. | + +Notes: + +- `--pkp` and `--pkv` cannot be used when compiling multiple binary packages. +- Keys generated with one hash configuration are only compatible with proofs generated from the matching keys. + +## `prove` + +Read a prover key plus input TOML and write a proof. + +```sh +provekit-cli prove [options] +``` + +| Option | Purpose | +| :--- | :--- | +| `--prover`, `-p ` | Prover key path. Defaults to `.pkp`. | +| `--input`, `-i ` | Noir input file. Defaults to `./Prover.toml`. | +| `--out`, `-o ` | Proof output path. Defaults to `./proof.np`. | + +`prove` consumes the prepared key material and writes a serialized `NoirProof`. For browser, mobile, or service integrations, treat the proof as an artifact that must stay paired with its verifier key and public inputs. + +## `verify` + +Read a verifier key plus proof and verify the proof. + +```sh +provekit-cli verify [options] +``` + +| Option | Purpose | +| :--- | :--- | +| `--verifier`, `-v ` | Verifier key path. Defaults to `.pkv`. | +| `--proof ` | Proof path. Defaults to `./proof.np`. | + +A verification failure usually means the proof, verifier key, public inputs, circuit, branch, or hash configuration don't match. Regenerate from `prepare` when any of those inputs change. + +## Inspection and export commands + +| Command | Purpose | +| :--- | :--- | +| `circuit-stats ` | Analyze Noir ACIR circuit statistics and R1CS complexity. Noir only. | +| `analyze-pkp ` | Print the size breakdown of a Noir prover key. Noir only. | +| `show-inputs [--hex] ` | Display public inputs from a proof using ABI variable names. | +| `generate-gnark-inputs [--params ] [--r1cs ]` | Export recursive-verifier parameters and an R1CS JSON file. | + +Example recursive-verifier export: + +```sh +cargo run --release --bin provekit-cli -- generate-gnark-inputs \ + artifacts/basic.pkv \ + artifacts/proof.np \ + --params artifacts/params_for_recursive_verifier \ + --r1cs artifacts/r1cs.json +``` + +## Profiling flags + +The CLI prints span timing and memory statistics through its tracing layer. When built with the `tracy` feature, these global flags are also available: + +| Flag | Purpose | +| :--- | :--- | +| `--tracy` | Enable Tracy profiling. | +| `--tracy-allocations ` | Track allocations at the given stack depth (`0` for no stack traces). | +| `--tracy-keepalive` | Keep the process alive after completion so Tracy can collect data. | + +Build with Tracy support before using those flags: + +```sh +cargo run --release --features tracy --bin provekit-cli -- --tracy prepare +``` + +## Troubleshooting quick links + +- [Common errors](/troubleshooting/common-errors/), setup, artifact mismatch, WASM, and verifier-server failures. +- [Project status and versioning](/reference/project-status/), read before mixing artifacts across branches. +- [Production checklist](/reference/production-checklist/), pre-launch checks for ProveKit-backed workflows. diff --git a/docs/src/content/docs/concepts/artifact-lifecycle.mdx b/docs/src/content/docs/concepts/artifact-lifecycle.mdx new file mode 100644 index 000000000..0a53eab89 --- /dev/null +++ b/docs/src/content/docs/concepts/artifact-lifecycle.mdx @@ -0,0 +1,96 @@ +--- +title: Artifact lifecycle +description: How ProveKit artifacts are generated, paired, transported, regenerated, and retired. +--- + +import { Aside, Steps } from '@astrojs/starlight/components'; + +ProveKit is artifact-driven. A safe integration treats every generated key, proof, and recursive-verifier export as a versioned deployment object, with explicit provenance and strict pairing rules. + +## Artifact map + +| Artifact | Produced by | Consumed by | Stays paired with | +| :--- | :--- | :--- | :--- | +| `.pkp` | `provekit-cli prepare` | `prove`, WASM/FFI/Rust provers | Matching `.pkv`, circuit source, compiler backend, hash choice, commit. | +| `.pkv` | `provekit-cli prepare` | `verify`, `show-inputs`, `generate-gnark-inputs`, verifier server | Matching `.pkp`, the proof set, public input encoding. | +| `proof.np` | `provekit-cli prove` | `verify`, `show-inputs`, `generate-gnark-inputs` | Matching `.pkv`, public inputs, witness provenance. | +| `params_for_recursive_verifier` | `generate-gnark-inputs` | `recursive-verifier/` | The exact `.pkv` and `proof.np` used to export it. | +| `r1cs.json` | `generate-gnark-inputs` | `recursive-verifier/`, verifier server | The exact `.pkv` and `proof.np` used to export it. | + +## Lifecycle stages + + +1. **Generate** artifacts from a clean checkout using explicit paths. + + ```sh + mkdir -p artifacts + cargo run --release --bin provekit-cli -- prepare . \ + --pkp artifacts/app.pkp \ + --pkv artifacts/app.pkv + ``` + +2. **Record provenance.** Capture the branch, commit, `Cargo.lock`, `rust-toolchain.toml`, full command line, feature flags, compiler backend, hash choice, and checksums. + +3. **Prove** using inputs that target this exact prepared circuit. + + ```sh + cargo run --release --bin provekit-cli -- prove \ + --prover artifacts/app.pkp \ + --input Prover.toml \ + --out artifacts/proof.np + ``` + +4. **Verify** before moving artifacts across a trust boundary. + + ```sh + cargo run --release --bin provekit-cli -- verify \ + --verifier artifacts/app.pkv \ + --proof artifacts/proof.np + ``` + +5. **Export recursive inputs** only after the base proof verifies. + + ```sh + cargo run --release --bin provekit-cli -- generate-gnark-inputs \ + artifacts/app.pkv \ + artifacts/proof.np \ + --params artifacts/params_for_recursive_verifier \ + --r1cs artifacts/r1cs.json + ``` + + +## When to regenerate + +Regenerate every affected artifact when any of these inputs change: + +- Git branch, commit, dependency lockfile, Rust toolchain, or relevant feature flags. +- Noir source, package selection, workspace layout, or compiler backend. +- `prepare --hash` value. +- Prover inputs (when a new proof is expected). +- The proof / verifier pair used for a recursive export. +- Serialization or transport changes affecting proof JSON or public input encoding. + + + +## Custody and storage + +| File | Recommended handling | +| :--- | :--- | +| `.pkp` | Restrict to trusted proving hosts. It enables proof generation for the prepared circuit. | +| `.pkv` | Distributable to verifiers, but keep integrity-protected and versioned. | +| `proof.np` / proof JSON | Transport through authenticated application channels; preserve public inputs byte-for-byte. | +| `Prover.toml` / witnesses | Treat private witness values as sensitive unless your application explicitly defines them as public. | +| Recursive params + `r1cs.json` | Keep with the exact proof / verifier pair that produced them. | + +## Deployment evidence + +Before publishing or accepting an artifact set, retain: + +- SHA-256 checksums (or equivalent content hashes) for every file. +- The full CLI command lines used to generate them. +- A local `verify` success record. +- `show-inputs --hex` output reviewed by the application owner. +- Negative-test evidence, mismatched or corrupted proofs are rejected. +- An owner and rotation plan for regenerating the set. diff --git a/docs/src/content/docs/concepts/designing-circuits.mdx b/docs/src/content/docs/concepts/designing-circuits.mdx new file mode 100644 index 000000000..fc517da5c --- /dev/null +++ b/docs/src/content/docs/concepts/designing-circuits.mdx @@ -0,0 +1,127 @@ +--- +title: Designing circuits for ProveKit +description: ProveKit-specific mechanics that shape how you author circuits, hash arities, public-input ABI, verifier lifecycle, and artifact compatibility. +--- + +import { Aside } from '@astrojs/starlight/components'; + +ProveKit doesn't constrain how you build circuits, that's Noir's job. But a handful of mechanics are specific to *this* proof system, and getting them right saves real debugging time. This page covers them. + +For general zero-knowledge design patterns (Merkle membership, nullifiers, public-input binding theory), see the [external references](#external-references-for-general-zk-design) below. + +## Hash arities in `poseidon2::bn254` + +The `poseidon2` Noir dependency exposes a fixed set of arities: + +| Function | Arity | +| :--- | :--- | +| `hash_2` | 2 field elements | +| `hash_4` | 4 field elements | +| `hash_8` | 8 | +| `hash_12` | 12 | +| `hash_16` | 16 | + +No `hash_1`, no `hash_3`. For an arity that isn't in the list, chain `hash_2` calls or pad to the next supported size: + +```rust +// 3 inputs → chain two hash_2 calls. +let mid = poseidon2::bn254::hash_2([a, b]); +let h = poseidon2::bn254::hash_2([mid, c]); +``` + +This is the most common ProveKit-specific surprise, the `hash_3` you'd expect from other Poseidon libraries doesn't exist here. + +## In-circuit hash ≠ transcript hash + +ProveKit uses hashes in two independent places: + +- **Inside the circuit**, whatever your Noir code calls (`poseidon2::bn254::hash_*`, `sha256`, etc.). +- **Outside the circuit, for Merkle commitments and the Fiat-Shamir transcript**, controlled by `prepare --hash`. + +They are independent choices. The default `prepare --hash skyscraper` works for almost every circuit because Skyscraper is BN254-tuned and fastest in the transcript role. You typically only override `--hash` when a downstream consumer (an EVM contract checking the transcript hash, for example) demands a specific algorithm. + +Available `--hash` values: `skyscraper` *(default)*, `sha256`, `keccak`, `blake3`, `poseidon2`. + + + +## Public-input ABI is a contract + +Public inputs are exposed to the verifier and are *part of the artifact ABI*. Two things follow: + +**1. Order matters.** Reordering public inputs in the Noir signature changes the ABI and invalidates every existing `.pkv` and proof. Treat the public-input list like a versioned API. + +**2. Verification ≠ authorization.** A successful `verify()` says the proof is valid against *these* public inputs. Your application code must then check that "these" are the ones it expected, same election ID, same chain, same account. Skipping this check is the most common ZK-app authorization bug. + +After `verify()` returns success: + +```rust +let public_inputs = proof.public_inputs.0; +assert_eq!(public_inputs[0], expected_election_id, "wrong election"); +assert_eq!(public_inputs[1], expected_chain_id, "wrong chain"); +``` + +To confirm what your circuit actually exposes: + +```sh +cargo run --release --bin provekit-cli -- show-inputs --hex \ + circuit.pkv proof.np +``` + +Record this output alongside released artifacts. It's the ground truth of what your verifier sees. + +## Verifier state is consumed per call + +ProveKit's native `Verify::verify(&mut self, ...)` consumes internal verifier state on each call. To verify multiple proofs in one process, reload or clone fresh verifier state per attempt: + +```rust +// Reload for each proof. +let mut verifier: Verifier = read(pkv_path)?; +verifier.verify(&proof_a)?; + +let mut verifier: Verifier = read(pkv_path)?; +verifier.verify(&proof_b)?; +``` + +The error message on the second use of a stale verifier is `Verifier has already been consumed; cannot verify twice`. The WASM `Verifier` is reusable because its binding handles the consumption differently, but its `Prover` *is* consumed after one `proveBytes()` / `proveJs()` call. Plan the lifecycle explicitly per host. + +## Artifact compatibility is by construction + +ProveKit doesn't need a circuit-version field in your proof, the `.pkp` and `.pkv` pair is bound to the exact circuit, branch, compiler backend, hash choice, and lockfile from one `prepare` run. Cross-circuit replay is impossible: a proof made with `circuit_v1.pkp` cannot verify against `circuit_v2.pkv`, even if both came from "the same Noir source" with a comma changed. + +This means: + +- You cannot accidentally accept a proof from a different circuit version. +- You *can* accidentally produce a workflow where new artifacts get deployed without matching the proofs already in flight, match `.pkv` to the proof set being verified. + +See [Artifact lifecycle](/concepts/artifact-lifecycle/) for the full pairing rules. + +## Recursive verifier exposes public inputs + +`provekit-cli generate-gnark-inputs` produces `params_for_recursive_verifier` and `r1cs.json` from a matching `.pkv` and proof. When wrapped in Groth16 by the Go/gnark recursive verifier, those public inputs become the on-chain public inputs of the outer proof. Two implications: + +- **Anything in public inputs gets stored on-chain** after Groth16 wrapping. Don't put privacy-sensitive values there. +- **Match the `--hash` between base proof and recursive verifier expectations.** If the recursive verifier was built against a different transcript hash, the wrap fails. + +## Skyscraper as default + +`skyscraper` is ProveKit's BN254-tuned hash engine (lives in [`skyscraper/`](https://github.com/worldfnd/provekit/tree/main/skyscraper)). It's the default for `--hash` because it produces the smallest transcript-side overhead with SIMD-accelerated BN254 arithmetic on `aarch64`. Use it unless a downstream consumer requires a specific alternative, there is no realistic "wrong" default here for ProveKit-internal flows. + +## External references for general ZK design + +The patterns below show up in every ZK application. They aren't ProveKit-specific, so we link rather than duplicate: + +- **Merkle membership proofs**, prove "this leaf is in a set with this root." See the [Aztec Noir tutorials](https://noir-lang.org/docs/) and the [`noir-passport`](https://github.com/worldfnd/provekit/tree/main/noir-examples/noir-passport) example for production-scale instances. +- **Nullifiers**, public, deterministic, one-way functions of a secret bound to a context, used to prevent replay. Common in vote schemes, airdrops, and credential systems. See [ZK Hack write-ups](https://zkhack.dev/) and the [Aztec privacy docs](https://docs.aztec.network/) for canonical treatments. +- **Public-input binding**, binding context like `chain_id`, `session_id`, or `epoch` into the proof. Every ZK app needs this; the principle is universal across proof systems. +- **Hash selection for in-circuit work**, Poseidon2 is cheapest in-circuit on BN254; SHA-256 and Keccak cost roughly 100× more constraints but match what EVM contracts already expect. See the [Ethproofs CSP benchmarks](https://ethproofs.org/csp-benchmarks) for measured comparisons across hashes and proof systems. + +If your circuit pulls one of these patterns from a published library (e.g., a Noir Merkle tree crate, a nullifier helper), prefer the published implementation over copying a sketch from any documentation, including this site. + +## Related pages + +- [Proving flow](/concepts/proving-flow/), the conceptual pipeline. +- [Artifact lifecycle](/concepts/artifact-lifecycle/), pairing and regeneration rules. +- [Security and trust model](/concepts/security-model/), what verification proves and what it doesn't. +- [CLI reference](/cli/overview/), `prepare --hash`, `show-inputs`, `generate-gnark-inputs`. diff --git a/docs/src/content/docs/concepts/proving-flow.mdx b/docs/src/content/docs/concepts/proving-flow.mdx new file mode 100644 index 000000000..b9a816205 --- /dev/null +++ b/docs/src/content/docs/concepts/proving-flow.mdx @@ -0,0 +1,152 @@ +--- +title: Proving flow +description: How ProveKit turns Noir programs into verifiable WHIR proofs. +--- + +import { Aside, Card, CardGrid } from '@astrojs/starlight/components'; + +ProveKit connects circuit authoring, constraint generation, key preparation, proving, verification, and optional recursive-verifier export. The CLI wraps this lifecycle in three primary commands, `prepare`, `prove`, and `verify`, plus an export step (`generate-gnark-inputs`) when you need recursive verification. + + + + + + + + + + + + + + + + + + + + + Noir circuit + .nr source + + + ACIR + Noir IR + + + R1CS + constraints + + + prepare + compile + emit + + + .pkp + prover key + + + .pkv + verifier key + + + prove + → proof.np + + + verify + valid / invalid + + + gnark + wrap + Groth16 + + + + + +## Mental model + + + + Express the computation and its public/private boundary as a Noir package. + + + Compile the circuit to produce a matching `.pkp` prover key and `.pkv` verifier key. + + + Combine the prover key with concrete witness inputs from `Prover.toml` or an SDK witness map. + + + Verify with the matching `.pkv` locally, in a service, in WASM, through FFI, or via recursive verification. + + + +## Core concepts + +| Concept | Description | +| :--- | :--- | +| **Noir** | The user-facing circuit language used for ProveKit's primary authoring path. | +| **ACIR** | Abstract Circuit Intermediate Representation emitted by the Noir frontend. | +| **R1CS** | Rank-1 Constraint System used by the ProveKit proving pipeline. | +| **Prover key (`.pkp`)** | Key material used to generate a proof for a prepared circuit. | +| **Verifier key (`.pkv`)** | Key material used to verify proofs from the matching prepared circuit. | +| **WHIR proof** | Proof object generated by the prover and consumed by every verification path. | +| **Recursive export** | `params_for_recursive_verifier` and `r1cs.json` derived from a matching verifier key and proof. | + +## Command responsibilities + +| Command | Responsibility | Run when | +| :--- | :--- | :--- | +| `prepare` | Compile the circuit and write `.pkp` / `.pkv`. | The circuit source, compiler backend, hash choice, branch, or proof format changes. | +| `prove` | Generate `proof.np` from a prover key and inputs. | Once per witness or proof request. | +| `verify` | Check a proof against a verifier key. | At every trust boundary. | +| `show-inputs` | Decode public inputs from a verifier key and proof. | During integration testing and production validation. | +| `generate-gnark-inputs` | Export recursive-verifier inputs from a verifier key and proof. | Whenever the verifier key or proof changes. | + +## The setup boundary + + + +This page stays at the product-flow level. For deployment controls and the security model, continue with: + +- [Artifact lifecycle](/concepts/artifact-lifecycle/) +- [Security and trust model](/concepts/security-model/) +- [Production checklist](/reference/production-checklist/) diff --git a/docs/src/content/docs/concepts/security-model.mdx b/docs/src/content/docs/concepts/security-model.mdx new file mode 100644 index 000000000..1fa4edc91 --- /dev/null +++ b/docs/src/content/docs/concepts/security-model.mdx @@ -0,0 +1,74 @@ +--- +title: Security and trust model +description: Security boundaries and operational assumptions for teams integrating ProveKit. +--- + +import { Aside } from '@astrojs/starlight/components'; + +This page documents integration-level security expectations. It is not a cryptographic proof, audit report, or production-readiness certification, use it to decide where artifacts live, who may generate them, and which checks must run before accepting a proof. + + + +## Trust boundaries + +| Boundary | What crosses it | Required control | +| :--- | :--- | :--- | +| Circuit authoring → key preparation | Noir source, compiler backend, hash choice | Code review, pinned commit, reproducible command line. | +| Key preparation → prover runtime | `.pkp` | Access control, integrity checks, recorded provenance. | +| Prover runtime → verifier runtime | `proof.np` / proof JSON and public inputs | Verification with the matching `.pkv`; public-input review. | +| Verifier runtime → application decision | Boolean validity plus decoded public inputs | Application-level authorization and policy checks. | +| Recursive export → Go/gnark wrapper | `params_for_recursive_verifier`, `r1cs.json` | Regenerated from the exact verifier/proof pair; setup keys managed explicitly. | + +## What verification proves + +A successful ProveKit verification means the proof is valid against the verifier key and public-input binding presented to the verifier. **It does not tell your application what to do with that proof.** + +Your application still owns these decisions: + +- Whether a user is allowed to submit a proof for a given account or session. +- Whether public inputs match the expected credential, nullifier, domain separator, or request ID. +- Whether the proof / key / artifact version is still accepted by the service. +- Whether replay protection or one-time-use semantics apply. + +## Cryptographic assumptions + +ProveKit's security rests on different assumptions for the base proof and the optional recursive wrapper. Treat them separately when modeling threats. + +| Layer | Underlying primitives | Quantum-resistance | +| :--- | :--- | :--- | +| **Base WHIR proof** | Hash-based polynomial commitment scheme (WHIR) + Spartan-style sumcheck. Security reduces to the chosen hash's collision resistance. | **Post-quantum secure** under conjectured hash-function PQ-security. Grover's algorithm imposes a quadratic speedup on preimage finding, so 256-bit hashes retain ~128-bit security against quantum adversaries. | +| **Recursive Groth16 wrap** | Pairing-based SNARK over BN254. Security relies on the q-SDH / Knowledge-of-Exponent assumptions on pairings. | **Not post-quantum secure.** Shor's algorithm breaks discrete-log on elliptic curves; any Groth16-wrapped proof is vulnerable to a sufficiently capable quantum attacker. | + +If post-quantum security is part of your threat model, scope on-chain settlement carefully: verify the base WHIR proof off-chain (post-quantum secure path) rather than relying on the Groth16 outer proof for cryptographic guarantees. The wrapper is appropriate for cost-efficient EVM verification, not as a long-term cryptographic anchor. + +## Sensitive material + +| Material | Sensitivity | +| :--- | :--- | +| Private witness inputs | Sensitive by default. Keep out of logs and client-visible telemetry. | +| `.pkp` prover keys | Operationally sensitive, they enable proof generation for the prepared circuit. | +| `.pkv` verifier keys | Usually distributable, but always integrity-protected and versioned. | +| Proofs | May carry public inputs and metadata that are sensitive in your application context. | +| Recursive proving keys | Manage explicitly. Development-time generation is not sufficient for production. | + +## Operational controls + +- Pin the branch, commit, lockfile, toolchain, compiler backend, and hash choice for every artifact release. +- Verify locally before publishing or accepting any proof artifact. +- Review public inputs with `show-inputs --hex` for byte-exact comparison. +- Reject proofs whose provenance is unknown or spans multiple generations. +- Restrict verifier-server artifact URLs to trusted sources, or proxy downloads through trusted storage. +- Keep FFI buffer ownership, mobile memory settings, and WASM prover lifecycle under test on real target devices. +- Add negative tests for mismatched key / proof pairs and corrupted proof payloads. + +## Red-team prompts for reviewers + +Ask these questions during every integration review: + +1. Can a client choose the `.pkv`, `r1cs.json`, proving key, or verifying key used by a verifier service? +2. Are public inputs bound to the correct account, session, chain, domain, or request? +3. Can a previously valid proof be replayed after a policy or circuit change? +4. Could an artifact generated from `main` be accepted by a `v1` deployment by accident? +5. Are witness values, proofs, or prover keys logged anywhere, CLI wrappers, web servers, mobile crash reporters? diff --git a/docs/src/content/docs/concepts/what-is-provekit.mdx b/docs/src/content/docs/concepts/what-is-provekit.mdx new file mode 100644 index 000000000..84d4d27dc --- /dev/null +++ b/docs/src/content/docs/concepts/what-is-provekit.mdx @@ -0,0 +1,99 @@ +--- +title: What is ProveKit? +description: A developer-friendly introduction to ProveKit, the WHIR proof system it builds on, and the problems it's designed to solve. +--- + +import { Aside, Card, CardGrid } from "@astrojs/starlight/components"; + +ProveKit is a zero knowledge Spartan + WHIR based proof system. You write a circuit in [Noir](https://noir-lang.org/); ProveKit compiles it to R1CS, generates [WHIR](https://eprint.iacr.org/2024/1586.pdf) proofs from your inputs, and verifies those proofs from Rust, WebAssembly, mobile FFI, an HTTP service, or via a Groth16 outer proof for on-chain settlement. + +## The problem ProveKit solves + +A zero-knowledge proof lets one party (the **prover**) convince another (the **verifier**) that a statement is true, _without revealing the data that makes the statement true_. + +A few statements ProveKit can help you prove: + +- "I am over 18", without revealing a date of birth. +- "I own a passport issued by country X", without revealing the passport. +- "This vote came from a registered voter", without revealing which voter. +- "This off-chain computation produced this result", without re-running it on-chain. + +The workflow is the same shape every time: + +1. **Write a circuit** in Noir. A small program defining what counts as "true." +2. **Prepare** prover and verifier keys from the compiled circuit. +3. **Prove** a specific instance using your real (private) inputs and the prover key. +4. **Verify** the proof anywhere using the verifier key and the public inputs. + +ProveKit owns steps 2–4 and the runtime that runs them on every platform you ship to. You bring the Noir circuit; ProveKit handles the rest. + +## What's in the box + +ProveKit is a workspace of focused Rust crates plus tooling. Each piece has one job: + +| Crate / tool | Job | +| :------------------------------------------------------------------------------------------------ | :--------------------------------------------------------------------------------------------------------------------------------------------------- | +| [`provekit-r1cs-compiler`](https://github.com/worldfnd/provekit/tree/main/provekit/r1cs-compiler) | Lower Noir's ACIR into R1CS, with specialized handling for Poseidon2, SHA-256 compression, range checks, multi-scalar multiplication. | +| [`provekit-prover`](https://github.com/worldfnd/provekit/tree/main/provekit/prover) | Solve the witness in layers, commit via Merkle hashing, and produce the WHIR proof via Spartan-style sumcheck. | +| [`provekit-verifier`](https://github.com/worldfnd/provekit/tree/main/provekit/verifier) | Replay the Fiat-Shamir transcript, run sumcheck verification, and bind the public inputs. | +| [`provekit-cli`](https://github.com/worldfnd/provekit/tree/main/tooling/cli) | The command-line entry point. Subcommands: `prepare`, `prove`, `verify`, plus inspection and recursive-verifier export. | +| [`provekit-wasm`](https://github.com/worldfnd/provekit/tree/main/tooling/provekit-wasm) | Browser and Node.js bindings using `wasm-bindgen-rayon` for in-browser parallel proving when `SharedArrayBuffer` is available. | +| [`provekit-ffi`](https://github.com/worldfnd/provekit/tree/main/tooling/provekit-ffi) | C ABI for Swift, Kotlin, Python, and any host that can call a shared library. Includes an mmap-backed allocator for mobile circuits that exceed RAM. | +| [`verifier-server`](https://github.com/worldfnd/provekit/tree/main/tooling/verifier-server) | An Axum HTTP service that downloads artifacts and orchestrates verification with configurable concurrency and timeouts. | +| [`recursive-verifier/`](https://github.com/worldfnd/provekit/tree/main/recursive-verifier) | A Go/gnark module that wraps a ProveKit proof in Groth16 so it can be verified by an EVM contract. | +| [`skyscraper`](https://github.com/worldfnd/provekit/tree/main/skyscraper) | A custom BN254 hash engine with SIMD-accelerated field arithmetic. | + +## What makes ProveKit specifically different + +- **No trusted setup.** WHIR's commitment scheme is hash-based. The base proof needs no per-circuit ceremony and no toxic-waste handling. You compile a circuit and ship. +- **Post-quantum secure base proof.** WHIR inherits PQ-security from the chosen hash function (Skyscraper, SHA-256, Keccak, Blake3, or Poseidon2), so its hardness assumptions survive Shor-style attacks. The optional Groth16 wrapper for on-chain settlement uses pairing-based crypto (BN254) and is **not** post-quantum secure, scope on-chain proofs accordingly. + +## Before you build + +Two pages matter on day one: [Artifact lifecycle](/concepts/artifact-lifecycle/) for how `.pkp` / `.pkv` / `proof.np` are paired and versioned, and [Security and trust model](/concepts/security-model/) for what verification does and doesn't say about authorization. + +## A worked picture + +The checked-in `noir-examples/basic` circuit proves you know two field elements that hash (via Poseidon2) to a known commitment: + +```rust +use dep::poseidon2; + +fn main(plains: [Field; 2], result: pub Field) { + let hash = poseidon2::bn254::hash_2(plains); + assert(hash == result); +} +``` + +`plains` stays private; only the prover sees it. `result` is the public input that goes into the proof. A successful verification means _the prover knows two field elements that hash to `result`_, and the verifier learns the prover does, without learning `plains`. + +That tiny circuit is the same shape as much bigger ones: identity attestation, set membership, off-chain computation, range proofs. Once you can build, prove, and verify this one, every other circuit follows the same workflow. + +## Where to go next + + + + Five-minute path: prepare, prove, verify the basic example on your machine. + + [Quickstart →](/getting-started/quickstart/) + + + + The full proving and verification flow from Noir source to recursive export. + + [Proving flow →](/concepts/proving-flow/) + + + + Decide where ProveKit runs in your system: CLI, Rust, WASM, FFI, HTTP service, or recursive. + + [Integrations overview →](/integrations/overview/) + + + + A catalog of Noir circuits shipped with the repo, from hash primitives to passport verification. + + [Examples catalog →](/reference/examples/) + + + diff --git a/docs/src/content/docs/e2e/generate-artifacts.mdx b/docs/src/content/docs/e2e/generate-artifacts.mdx new file mode 100644 index 000000000..24c800163 --- /dev/null +++ b/docs/src/content/docs/e2e/generate-artifacts.mdx @@ -0,0 +1,129 @@ +--- +title: Generate artifacts +description: Produce reproducible ProveKit keys, proofs, and recursive-verifier exports with explicit paths. +--- + +import { Aside, Steps } from '@astrojs/starlight/components'; + +Use this guide when you need reproducible artifact paths for tests, demos, CI jobs, release bundles, or downstream integrations. + +## Default artifact flow + +From `noir-examples/basic`: + +```sh +cargo run --release --bin provekit-cli -- prepare +cargo run --release --bin provekit-cli -- prove +cargo run --release --bin provekit-cli -- verify +``` + +This writes: + +| File | Created by | Consumed by | +| :--- | :--- | :--- | +| `basic.pkp` | `prepare` | `prove` | +| `basic.pkv` | `prepare` | `verify`, `show-inputs`, `generate-gnark-inputs` | +| `proof.np` | `prove` | `verify`, `show-inputs`, `generate-gnark-inputs` | +| `target/basic.json` | Noir compilation during `prepare` | ProveKit internals and inspection workflows | + +## Explicit artifact directory + + +1. Enter the Noir package and create an output directory. + + ```sh + cd noir-examples/basic + mkdir -p artifacts + ``` + +2. Prepare key material. + + ```sh + cargo run --release --bin provekit-cli -- prepare . \ + --pkp ./artifacts/basic.pkp \ + --pkv ./artifacts/basic.pkv + ``` + +3. Generate a proof. + + ```sh + cargo run --release --bin provekit-cli -- prove \ + --prover ./artifacts/basic.pkp \ + --input ./Prover.toml \ + --out ./artifacts/proof.np + ``` + +4. Verify the proof. + + ```sh + cargo run --release --bin provekit-cli -- verify \ + --verifier ./artifacts/basic.pkv \ + --proof ./artifacts/proof.np + ``` + + +## Hash choice + +`prepare` defaults to `skyscraper`. The CLI also accepts `sha256`, `keccak`, `blake3`, and `poseidon2` via `--hash`: + +```sh +cargo run --release --bin provekit-cli -- prepare . --hash blake3 +``` + +The hash is part of the artifact's identity. Regenerate the prover key, verifier key, and every proof after changing it. + + + +## Inspect public inputs + +Decode public inputs as part of integration testing: + +```sh +cargo run --release --bin provekit-cli -- show-inputs --hex \ + ./artifacts/basic.pkv \ + ./artifacts/proof.np +``` + +Review the output with the application owner. Verification proves the proof is valid for the verifier key, your application still owns the decision about whether those inputs authorize the requested action. + +## Recursive-verifier export + +After the proof verifies, export inputs for the Go/gnark recursive verifier: + +```sh +cargo run --release --bin provekit-cli -- generate-gnark-inputs \ + ./artifacts/basic.pkv \ + ./artifacts/proof.np \ + --params ./artifacts/params_for_recursive_verifier \ + --r1cs ./artifacts/r1cs.json +``` + +The command reads the verifier key and proof, then writes the recursive parameters and an R1CS JSON. Keep those outputs paired with the exact `basic.pkv` and `proof.np` that produced them. + +## CI evidence template + +A release-producing CI job should persist at least: + +```text +commit: +rust-toolchain: +lockfile: Cargo.lock +compiler: noir +prepare_hash: skyscraper +commands: + - cargo run --release --bin provekit-cli -- prepare ... + - cargo run --release --bin provekit-cli -- prove ... + - cargo run --release --bin provekit-cli -- verify ... +artifacts: + - artifacts/basic.pkp + - artifacts/basic.pkv + - artifacts/proof.np +``` + +## Cleanup + +```sh +rm -rf artifacts target basic.pkp basic.pkv proof.np params_for_recursive_verifier r1cs.json +``` diff --git a/docs/src/content/docs/e2e/js-typescript.mdx b/docs/src/content/docs/e2e/js-typescript.mdx new file mode 100644 index 000000000..c92353a8d --- /dev/null +++ b/docs/src/content/docs/e2e/js-typescript.mdx @@ -0,0 +1,60 @@ +--- +title: JS / TypeScript end-to-end +description: Drive ProveKit's WASM backend from JavaScript or TypeScript in Node.js and browser applications. +--- + +import { Aside } from '@astrojs/starlight/components'; + +This guide uses the Verity JS / TypeScript SDK, which wraps ProveKit's WASM backend for browser and Node.js environments. References below are pinned to Verity commit `3f6b8ad6e7c994a740a204fbf35c0a3f3001e4d3`. + + + +## SDK surface + +At the pinned Verity revision: + +- `sdks/js/package.json` publishes `@atheon/verity` as an ESM-first package with Node and browser export targets. +- `sdks/js/src/index.ts` exports `Verity`, `Backend`, `Proof`, and the scheme types. +- `sdks/js/src/verity.ts` constructs `Verity` via `Verity.create(Backend.ProveKit)` and loads prover and verifier schemes from bytes. +- `sdks/js/src/types.ts` defines `ProverScheme.prove(inputs: Record | string)` and `VerifierScheme.verify(proof)`. +- `verity.ts` also exposes `verity.prove(...)` and `verity.verify(...)` convenience delegates, but the scheme methods shown below are the canonical API. +- `sdks/js/src/backends/provekit.ts` loads the ProveKit WASM module, extracts Noir circuit JSON from `.pkp` bytes, uses `@noir-lang/noir_js` and `@noir-lang/acvm_js` for witness generation, and verifies proofs through the WASM verifier. + +## Minimal flow + +```ts +import { Backend, Verity } from "@atheon/verity"; + +const verity = await Verity.create(Backend.ProveKit); + +const prover = await verity.loadProver(proverBytes); // Uint8Array of .pkp +const verifier = await verity.loadVerifier(verifierBytes); // Uint8Array of .pkv + +const proof = await prover.prove({ age: "25", threshold: "18" }); +const valid = await verifier.verify(proof); + +if (!valid) { + throw new Error("proof did not verify"); +} + +prover.dispose(); +verifier.dispose(); +``` + +`inputs` may be a plain object or a JSON object string. For Noir circuits with arrays or structured inputs, keep the object layout aligned with the circuit ABI and validate it in application tests. + +## Build and packaging notes + +- Build the ProveKit WASM artifact before running the browser or Node path from the Verity repo: `make core-wasm`. +- Generate demo/test `.pkp` and `.pkv` fixtures via `bash scripts/generate-js-artifacts.sh` when using the Verity fixture flow. +- Install the optional Noir peer dependencies for JS witness generation: `@noir-lang/noir_js` and `@noir-lang/acvm_js`. +- Browser threading depends on `SharedArrayBuffer`. The Verity ProveKit binding falls back to a non-threaded path when worker/thread-pool initialization is unavailable. +- `proverBytes` and `verifierBytes` are assumed to be `Uint8Array` values already loaded by the application. Fetching, caching, integrity checks, and lifecycle cleanup are the host's responsibility. + +## Related pages + +- [End-to-end overview](/e2e/overview/) +- [Generate artifacts](/e2e/generate-artifacts/) +- [Integrations overview](/integrations/overview/) diff --git a/docs/src/content/docs/e2e/kotlin.mdx b/docs/src/content/docs/e2e/kotlin.mdx new file mode 100644 index 000000000..3cd66a81d --- /dev/null +++ b/docs/src/content/docs/e2e/kotlin.mdx @@ -0,0 +1,66 @@ +--- +title: Kotlin end-to-end +description: Integrate ProveKit on Android via the Verity Kotlin SDK, using the published AAR or a local build. +--- + +import { Aside } from '@astrojs/starlight/components'; + +This guide uses the Verity Kotlin SDK, which wraps the JNI bridge, shared dispatcher, and ProveKit backend for Android. References below are pinned to Verity commit `3f6b8ad6e7c994a740a204fbf35c0a3f3001e4d3`. + + + +## SDK surface + +At the pinned Verity revision: + +- `sdks/kotlin/build.gradle.kts` defines an Android library and currently publishes `arm64-v8a` JNI libraries. +- `Backend.kt` exposes `Backend.PROVEKIT` for the ProveKit WHIR backend. +- `Verity.kt` loads `verity_jni`, initializes a backend once, and loads prover/verifier schemes from file paths or `ByteArray`. +- `Witness.kt` supports TOML files, flat maps of field-element strings, and JSON strings for arrays or nested objects. +- `ProverScheme.kt`, `VerifierScheme.kt`, and `Proof.kt` expose `prove`, `verify`, serialization, deterministic `close()`, and `use { ... }` cleanup patterns. + +## Gradle declaration + +```kotlin +dependencies { + implementation("xyz.atheon:verity:0.3.0") +} +``` + +Confirm the published version and ABI coverage for your release. At the pinned revision, the Gradle metadata indicates `arm64-v8a` is the published ABI. + +## Minimal flow + +```kotlin +import xyz.atheon.verity.* + +val verity = Verity(Backend.PROVEKIT) +val prover = verity.loadProver("scheme.pkp") +val verifier = verity.loadVerifier("scheme.pkv") + +prover.use { p -> + verifier.use { v -> + val witness = Witness.of(mapOf("age" to "25", "threshold" to "18")) + val proof = p.prove(witness) + check(v.verify(proof)) { "proof did not verify" } + } +} +``` + +Use `loadProver(ByteArray)` and `loadVerifier(ByteArray)` when the app stores artifacts as Android assets, downloads them, or manages them through encrypted storage. + +## Build and packaging notes + +- `make test-kotlin` runs Android `connectedAndroidTest` in the Verity repo; fixture generation requires `core-native`. +- The pinned build notes record that the published Kotlin AAR currently ships `arm64-v8a` JNI libraries only. +- Local Android builds use `core/build/build-android.sh`, which accepts `VERITY_ANDROID_ABIS=arm64-v8a,x86_64` for additional ABI outputs. +- Call `Verity.configureMemory(...)` before constructing `Verity` when large ProveKit circuits need Android RAM limits or file-backed memory. +- The snippet assumes `scheme.pkp` and `scheme.pkv` are readable from the app's filesystem. Package them as assets and copy to a readable path, or load them as bytes, depending on your distribution model. + +## Related pages + +- [End-to-end overview](/e2e/overview/) +- [Generate artifacts](/e2e/generate-artifacts/) +- [Integrations overview](/integrations/overview/) diff --git a/docs/src/content/docs/e2e/overview.mdx b/docs/src/content/docs/e2e/overview.mdx new file mode 100644 index 000000000..be477ad72 --- /dev/null +++ b/docs/src/content/docs/e2e/overview.mdx @@ -0,0 +1,151 @@ +--- +title: End-to-end overview +description: How a ProveKit run moves from Noir source to a verified proof and (optionally) a recursive-verifier export. +--- + +import { Aside, Card, CardGrid, Steps } from '@astrojs/starlight/components'; + +A complete ProveKit run starts with one Noir package and ends with a verified proof. The same `.pkp`, `.pkv`, and `proof.np` files flow through every integration path, CLI workflows, SDK examples, the verifier service, and recursive-verifier export. + +## The full path + + + +## Working-directory rule + +By default, the CLI resolves the enclosing Noir package from the current directory: + +- `prepare` compiles `.` when no package path is provided. +- `prove` looks for `.pkp` and `./Prover.toml`. +- `verify` looks for `.pkv` and `./proof.np`. + +For `noir-examples/basic`, the defaults are `basic.pkp`, `basic.pkv`, `Prover.toml`, and `proof.np`. + + + +## Artifact ownership + +| File | Owner | Regenerate when | +| :--- | :--- | :--- | +| `.pkp` | Prover-side runtime | Circuit, compiler backend, branch/commit, hash, or proving configuration changes. | +| `.pkv` | Verifier-side runtime | The prover key is regenerated, or verifier configuration changes. | +| `proof.np` | Proof transport / storage layer | Inputs change, the prover key changes, or a fresh proof is required. | +| `params_for_recursive_verifier` + `r1cs.json` | Recursive-verifier integration | The verifier key or proof changes. | + +## Local command sequence + + +1. Prepare keys. + + ```sh + cargo run --release --bin provekit-cli -- prepare + ``` + +2. Generate a proof. + + ```sh + cargo run --release --bin provekit-cli -- prove + ``` + +3. Verify locally. + + ```sh + cargo run --release --bin provekit-cli -- verify + ``` + +4. *(Optional)* Export recursive-verifier inputs. + + ```sh + cargo run --release --bin provekit-cli -- generate-gnark-inputs basic.pkv proof.np + ``` + + +## Explicit output paths + +Create the target directory before writing into it: + +```sh +mkdir -p artifacts +``` + +Then run with explicit paths: + +```sh +cargo run --release --bin provekit-cli -- prepare . \ + --pkp ./artifacts/basic.pkp \ + --pkv ./artifacts/basic.pkv + +cargo run --release --bin provekit-cli -- prove \ + --prover ./artifacts/basic.pkp \ + --input ./Prover.toml \ + --out ./artifacts/proof.np + +cargo run --release --bin provekit-cli -- verify \ + --verifier ./artifacts/basic.pkv \ + --proof ./artifacts/proof.np +``` + +## Pick the next guide + + + + Deterministic paths, pinned hash choices, and recursive-verifier export. + + [Generate artifacts →](/e2e/generate-artifacts/) + + + Load `.pkp` / `.pkv`, prove from TOML, persist `proof.np`, and verify through the ProveKit crates. + + [Rust guide →](/e2e/rust/) + + + Load `.pkp` / `.pkv` bytes and use WASM-backed proving and verification. + + [JS / TypeScript guide →](/e2e/js-typescript/) + + + Integrate through the mobile SDKs and their native/FFI packaging. + + [Swift →](/e2e/swift/) · [Kotlin →](/e2e/kotlin/) + + + Pin artifact provenance and complete pre-launch checks. + + [Production checklist →](/reference/production-checklist/) + + + +## Related pages + +- [Quickstart](/getting-started/quickstart/), runs the default-path flow. +- [Artifact lifecycle](/concepts/artifact-lifecycle/), pairing and regeneration rules. +- [CLI overview](/cli/overview/), every command option and hash choice. diff --git a/docs/src/content/docs/e2e/rust.mdx b/docs/src/content/docs/e2e/rust.mdx new file mode 100644 index 000000000..5e9bd493f --- /dev/null +++ b/docs/src/content/docs/e2e/rust.mdx @@ -0,0 +1,112 @@ +--- +title: Rust end-to-end +description: Drive ProveKit directly from Rust, load prepared artifacts, prove from TOML inputs, and verify in process. +--- + +import { Aside } from '@astrojs/starlight/components'; + +Use the Rust path when a service, test harness, or release pipeline can link the ProveKit crates and own artifact loading directly, instead of shelling out to `provekit-cli`. + + + +## Flow at a glance + +The Rust path mirrors the CLI: + +1. Generate `.pkp` and `.pkv` via the CLI (or the compiler APIs). +2. Load `.pkp` into `provekit_common::Prover`. +3. Generate a `NoirProof` with `provekit_prover::Prove::prove_with_toml`. +4. Persist the proof with `provekit_common::file::write` when needed. +5. Load `.pkv` into `provekit_common::Verifier`. +6. Verify with `provekit_verifier::Verify::verify`. + +## Prepare artifacts + +Start from the checked-in basic Noir package: + +```sh +cd noir-examples/basic +mkdir -p artifacts + +cargo run --release --bin provekit-cli -- prepare . \ + --pkp artifacts/basic.pkp \ + --pkv artifacts/basic.pkv +``` + +The Rust program below reads these `.pkp` and `.pkv` files. + +## Cargo dependencies + +The crates are published on crates.io. Pin exact versions; the current release is `1.0.0` (see [GitHub Releases](https://github.com/worldfnd/provekit/releases) for newer tags). + +```toml +[dependencies] +provekit-common = "1.0.0" +provekit-prover = "1.0.0" +provekit-verifier = "1.0.0" +``` + +Use path or Git dependencies only when you are deliberately testing an unpublished checkout. + +## Minimal program + +Run the program from the repository root so the example paths resolve to `noir-examples/basic/...`. + +```rust +use std::{error::Error, path::Path}; + +use provekit_common::{ + file::{read, write}, + NoirProof, Prover, Verifier, +}; +use provekit_prover::Prove; +use provekit_verifier::Verify; + +fn main() -> Result<(), Box> { + let prover_path = Path::new("noir-examples/basic/artifacts/basic.pkp"); + let verifier_path = Path::new("noir-examples/basic/artifacts/basic.pkv"); + let input_path = Path::new("noir-examples/basic/Prover.toml"); + let proof_path = Path::new("noir-examples/basic/artifacts/proof.np"); + + let prover: Prover = read(prover_path)?; + let proof = prover.prove_with_toml(input_path)?; + write(&proof, proof_path)?; + + let mut verifier: Verifier = read(verifier_path)?; + verifier.verify(&proof)?; + + // Optional: confirm the serialized proof round-trips through the same + // file format used by the CLI. + let persisted_proof: NoirProof = read(proof_path)?; + let mut fresh_verifier: Verifier = read(verifier_path)?; + fresh_verifier.verify(&persisted_proof)?; + + Ok(()) +} +``` + +## Verifier lifecycle + + + +The sample above intentionally loads `fresh_verifier` for the round-trip check. A long-lived service should make that lifecycle explicit. + +## Production notes + +- Use absolute, explicit artifact paths. Don't depend on the process current directory in services. +- Treat `.pkp`, `.pkv`, and `proof.np` as versioned deployment artifacts. +- Validate public inputs with `show-inputs` during integration testing. +- Add negative tests for mismatched `.pkv` / proof pairs. +- Regenerate keys and proofs after any change to circuit, branch, compiler backend, lockfile, toolchain, or `prepare --hash`. +- Walk through the [Production checklist](/reference/production-checklist/) before shipping a Rust prover or verifier service. + +## Related pages + +- [End-to-end overview](/e2e/overview/) +- [Generate artifacts](/e2e/generate-artifacts/) +- [CLI overview](/cli/overview/) +- [Artifact lifecycle](/concepts/artifact-lifecycle/) diff --git a/docs/src/content/docs/e2e/swift.mdx b/docs/src/content/docs/e2e/swift.mdx new file mode 100644 index 000000000..1c180118b --- /dev/null +++ b/docs/src/content/docs/e2e/swift.mdx @@ -0,0 +1,76 @@ +--- +title: Swift end-to-end +description: Integrate ProveKit on iOS via the Verity Swift SDK and Swift Package Manager. +--- + +import { Aside } from '@astrojs/starlight/components'; + +This guide uses the Verity Swift SDK, which wraps the shared Verity dispatcher and the ProveKit backend for iOS. References below are pinned to Verity commit `3f6b8ad6e7c994a740a204fbf35c0a3f3001e4d3`. + + + + + +## SDK surface + +At the pinned Verity revision: + +- The root `Package.swift` exposes the `Verity` library product. ProveKit targets iOS 15+; the package's macOS platform declaration is upstream-only. The native binary artifacts are iOS-only. +- `Package.swift` selects `source-only`, `native`, or `release` mode via the `VERITY_SWIFT_SDK_MODE` environment variable (or auto-detection). +- `sdks/swift/Sources/Verity/Verity.swift` defines `Backend.provekit`, initializes the backend once, and loads prover/verifier schemes from file paths, URLs, or `Data`. +- `Witness.swift` accepts TOML paths, dictionaries of field-element strings, and JSON strings. +- `ProverScheme.swift` and `VerifierScheme.swift` expose `prove(witness:)`, `verify(proof:)`, `serialize()`, `save(to:)`, and explicit `close()` lifecycle methods. + +## Package declaration + +```swift +// Package.swift +dependencies: [ + .package(url: "https://github.com/atheonxyz/verity", from: "0.3.2") +], +targets: [ + .target(name: "MyApp", dependencies: [ + .product(name: "Verity", package: "verity") + ]) +] +``` + +## Minimal flow + +```swift +import Verity + +let verity = try Verity(backend: .provekit) + +let prover = try verity.loadProver(from: "scheme.pkp") +let verifier = try verity.loadVerifier(from: "scheme.pkv") + +let witness = Witness(values: ["age": "25", "threshold": "18"]) +let proof = try prover.prove(witness: witness) + +let valid = try verifier.verify(proof: proof) +precondition(valid, "proof did not verify") + +prover.close() +verifier.close() +``` + +Use `loadProver(data:)` and `loadVerifier(data:)` when the app downloads or bundles artifacts as `Data`. + +## Build and packaging notes + +- `source-only` validates the Swift wrapper and public API without linking the iOS xcframework, it is not a native proof harness on its own. +- `native` requires a locally built `output/Verity.xcframework`. `release` consumes the published xcframework declared by the package manifest. +- The pinned build notes record that the native mobile artifact currently bundles the ProveKit backend only. +- Use Xcode's iOS simulator test runner for native verification. +- Call ProveKit's memory configuration before constructing `Verity` when the app needs mobile RAM limits or file-backed memory. + +## Related pages + +- [End-to-end overview](/e2e/overview/) +- [Generate artifacts](/e2e/generate-artifacts/) +- [Integrations overview](/integrations/overview/) diff --git a/docs/src/content/docs/getting-started/installation.mdx b/docs/src/content/docs/getting-started/installation.mdx new file mode 100644 index 000000000..64f11dcd2 --- /dev/null +++ b/docs/src/content/docs/getting-started/installation.mdx @@ -0,0 +1,112 @@ +--- +title: Installation and setup +description: Install provekit-cli from crates.io, or set up a source checkout for development and bundled examples. +--- + +import { Aside, Steps, Tabs, TabItem } from '@astrojs/starlight/components'; + +There are two ways to get `provekit-cli` on a machine. Use **`cargo install`** when you just need the CLI and have your own circuit. Use a **source checkout** when you want the bundled Noir examples, the WASM/FFI/server crates, or you're contributing to ProveKit. + +## Prerequisites + +| Requirement | Why it matters | +| :--- | :--- | +| **Rust via `rustup`** | Cargo installs and builds the CLI. Source builds use the toolchain pinned in `rust-toolchain.toml`. | +| **Git** *(source path only)* | Clones the repository and records exact commits for artifact provenance. | +| **Corepack + pnpm** *(optional)* | Required only to edit or build this docs site. | +| **Go toolchain** *(optional)* | Required only for recursive-verifier development. | + +## Install the CLI + + + +```sh +cargo install provekit-cli +provekit-cli --help +``` + +This builds and installs the latest published release into `~/.cargo/bin/`. Use this when you have your own Noir package and don't need the bundled examples or extra tooling. + +Pin a specific version for reproducible CI: + +```sh +cargo install provekit-cli --version 1.0.0 --locked +``` + + +```sh +git clone https://github.com/worldfnd/provekit.git +cd provekit +rustup show # confirms the pinned nightly is selected +cargo run --release --bin provekit-cli -- --help +``` + +This gives you the full workspace: examples in `noir-examples/`, WASM bindings in `tooling/provekit-wasm/`, FFI in `tooling/provekit-ffi/`, the verifier server, and the recursive-verifier Go module. Use this when you're contributing to ProveKit or want to run the checked-in examples directly. + + + + + +## Run the example proof + +If you installed via `cargo install`, point the CLI at your own Noir package. To run the canonical example, you need a copy of `noir-examples/basic/` from the repository: + + + +```sh +cd noir-examples/basic +cargo run --release --bin provekit-cli -- prepare +cargo run --release --bin provekit-cli -- prove +cargo run --release --bin provekit-cli -- verify +``` + + +```sh +git clone --depth 1 https://github.com/worldfnd/provekit.git +cd provekit/noir-examples/basic +provekit-cli prepare +provekit-cli prove +provekit-cli verify +``` + +The `cargo install` binary doesn't need `cargo run --release --bin provekit-cli --` in front of every command; call `provekit-cli` directly. + + + +If `verify` returns exit code `0`, your setup is healthy. + +## Build the documentation site + +The docs live in `docs/` and are built with [Astro Starlight](https://starlight.astro.build/). Source checkout only. + +```sh +cd docs +corepack enable +pnpm install +pnpm check +pnpm build +``` + +Use `pnpm dev` for live preview while authoring. + +## Optional host tooling + +| Target | Additional tooling | +| :--- | :--- | +| **Browser / Node.js** | Build the WASM package in `tooling/provekit-wasm/` and load `.pkp` / `.pkv` artifacts as bytes. | +| **iOS** | Build or consume the Swift SDK package mode used by your app, then link the required native artifacts. macOS is not supported. | +| **Android** | Package the JNI libraries required by the Kotlin/Android host and test on target ABIs. | +| **Verifier server** | Build the Rust HTTP server in `tooling/verifier-server/` and configure the Go verifier binary path. | +| **Recursive verifier** | Use the Go module in `recursive-verifier/` with the `params_for_recursive_verifier` and `r1cs.json` exported by the CLI. | + +All of these require a source checkout. + +## Verify your setup + +A healthy setup satisfies all of these checks: + +- `provekit-cli --help` (or `cargo run --release --bin provekit-cli -- --help` for source builds) prints the CLI help text. +- The [Quickstart](/getting-started/quickstart/) completes with `verify` returning exit code `0`. +- For docs work: `pnpm check` and `pnpm build` both pass inside `docs/`. diff --git a/docs/src/content/docs/getting-started/quickstart.mdx b/docs/src/content/docs/getting-started/quickstart.mdx new file mode 100644 index 000000000..b3b66ccc0 --- /dev/null +++ b/docs/src/content/docs/getting-started/quickstart.mdx @@ -0,0 +1,79 @@ +--- +title: Quickstart +description: Run the end-to-end ProveKit proof flow against the checked-in example circuit. +--- + +import { Aside, Steps } from '@astrojs/starlight/components'; + +This quickstart takes you through the shortest reliable path through ProveKit: compile the checked-in `noir-examples/basic` circuit, generate a proof from its prover inputs, and verify the proof locally. About five minutes. + +You'll need `provekit-cli` available (`cargo install provekit-cli` or a source checkout) and a copy of `noir-examples/basic/` to run against. See [Installation and setup](/getting-started/installation/) if either is missing. + +The commands below assume `provekit-cli` is on your PATH. **Source-checkout users:** substitute `cargo run --release --bin provekit-cli --` for `provekit-cli` in every command. + +## Run your first proof + + +1. Enter the example Noir package. + + ```sh + cd noir-examples/basic + ``` + +2. Prepare the prover and verifier keys. + + ```sh + provekit-cli prepare + ``` + +3. Generate a proof from `Prover.toml`. + + ```sh + provekit-cli prove + ``` + +4. Verify the proof locally. + + ```sh + provekit-cli verify + ``` + + + + +## What each command reads and writes + +| Step | Command | Reads | Writes | +| :--- | :--- | :--- | :--- | +| 1 | `prepare` | `Nargo.toml`, `src/main.nr`, Noir dependencies | `basic.pkp`, `basic.pkv`, Noir `target/` artifacts | +| 2 | `prove` | `basic.pkp`, `Prover.toml` | `proof.np` | +| 3 | `verify` | `basic.pkv`, `proof.np` | exit status only, no output file | + +`basic.pkp`, `basic.pkv`, and `proof.np` are generated. Don't commit them unless a downstream integration explicitly relies on checked-in fixtures. + +## Generated artifacts + +| Artifact | Purpose | Default location | +| :--- | :--- | :--- | +| `basic.pkp` | Prover key written by `prepare`. | Named after the enclosing Noir package. | +| `basic.pkv` | Verifier key written by `prepare`. | Named after the enclosing Noir package. | +| `proof.np` | Proof written by `prove`, consumed by `verify`. | `./proof.np` (override with `prove --out`). | +| `Prover.toml` | Prover inputs for the example circuit. | Checked into `noir-examples/basic/`. | + +## Clean up + +Return the example directory to a source-only state: + +```sh +rm -f basic.pkp basic.pkv proof.np +rm -rf target +``` + +## Where to go next + +- [End-to-end overview](/e2e/overview/), working-directory and artifact rules across every integration path. +- [Generate artifacts](/e2e/generate-artifacts/), explicit output paths, hash choices, and recursive-verifier exports. +- [Artifact lifecycle](/concepts/artifact-lifecycle/), pairing, regeneration, and custody rules before sharing files. +- [Common errors](/troubleshooting/common-errors/), if `prepare`, `prove`, or `verify` can't find expected files. diff --git a/docs/src/content/docs/getting-started/tutorial.mdx b/docs/src/content/docs/getting-started/tutorial.mdx new file mode 100644 index 000000000..df42dcf52 --- /dev/null +++ b/docs/src/content/docs/getting-started/tutorial.mdx @@ -0,0 +1,194 @@ +--- +title: "Tutorial: prove without revealing" +description: Build a zero-knowledge "I know a secret that hashes to a public commitment" flow end-to-end, Noir circuit, ProveKit CLI, and a Rust verifier you control. +--- + +import { Aside, Steps } from '@astrojs/starlight/components'; + +This tutorial walks you through the smallest meaningful zero-knowledge application: a prover convinces a verifier that they know a secret without revealing it. You'll write the Noir circuit, prepare keys, generate a proof, and verify it from your own Rust program. + +By the end you'll understand the full ProveKit loop and be ready to apply it to real workloads like credential verification, vote eligibility, or off-chain computation attestation. + +**Time:** about 20 minutes. **Prerequisites:** a working ProveKit checkout, see [Installation](/getting-started/installation/). + +## What you'll build + +A circuit that proves *"I know two field elements whose Poseidon2 hash equals this public commitment"*, and a Rust program that loads the resulting proof, verifies it, and prints the public commitment. + +In a real application the "two field elements" might be the components of a private identity key; the "public commitment" is the hash that gets stored on-chain or in a server. Verification proves the prover holds the secret without revealing it. + +## Step 1: scaffold the Noir circuit + + +1. Create a new Noir package inside the repo for this tutorial. + + ```sh + cd noir-examples + mkdir secret-knowledge && cd secret-knowledge + ``` + +2. Add a `Nargo.toml` that pulls in the `poseidon2` dependency. + + ```toml title="Nargo.toml" + [package] + name = "secret_knowledge" + type = "bin" + authors = [""] + compiler_version = ">=0.22.0" + + [dependencies] + poseidon2 = { tag = "v0.5.0-beta.0", git = "https://github.com/TaceoLabs/noir-poseidon", directory = "poseidon2" } + ``` + +3. Write the circuit. Public inputs go in the function signature *after* private ones, but you mark public inputs with the `pub` keyword. + + ```rust title="src/main.nr" + use dep::poseidon2; + + fn main(secret: [Field; 2], commitment: pub Field) { + let computed = poseidon2::bn254::hash_2(secret); + assert(computed == commitment); + } + ``` + + This circuit enforces one constraint: that `poseidon2(secret) == commitment`. Because `secret` is private and `commitment` is public, the resulting proof says "the prover knows a secret that hashes to commitment", and nothing else. + + +## Step 2: pick inputs + +You need a valid `(secret, commitment)` pair where `commitment == poseidon2(secret)`. Computing Poseidon2 outside the circuit takes an off-circuit hash implementation; for this tutorial, reuse a precomputed pair from `noir-examples/basic`: + +```toml title="Prover.toml" +secret = ["1", "2"] +commitment = "0x0e90c132311e864e0c8bca37976f28579a2dd9436bbc11326e21ec7c00cea5b2" +``` + +That commitment is Poseidon2(BN254) of `[1, 2]`, already verified by the canonical basic example. Once you've completed the tutorial, swap in your own `(secret, commitment)` pair generated however you like. + +Then compile the circuit: + +```sh +cargo run --release --bin provekit-cli -- prepare +``` + +`prepare` reads only the Noir source, not `Prover.toml`. It writes `secret_knowledge.pkp` (prover key) and `secret_knowledge.pkv` (verifier key) into the package directory. + +## Step 3: prove and verify with the CLI + + +1. Generate a proof. ProveKit reads the prover key (`.pkp`) and your inputs, and writes `proof.np`. + + ```sh + cargo run --release --bin provekit-cli -- prove + ``` + +2. Verify it locally, this is the fastest sanity check before integrating elsewhere. + + ```sh + cargo run --release --bin provekit-cli -- verify + ``` + + Exit code `0` means the proof verifies. If you see a failure, the most common cause is a stale `.pkp` / `.pkv` pair, re-run `prepare`. + +3. Inspect the public inputs the proof actually exposes. + + ```sh + cargo run --release --bin provekit-cli -- show-inputs --hex \ + secret_knowledge.pkv \ + proof.np + ``` + + You'll see only `commitment`, the secret never appears. + + + + +## Step 4: verify from your own Rust program + +The CLI is great for development. In production, the verifier usually runs inside *your* code, a backend service, a smart-contract gateway, a CLI tool. Let's verify the same proof from a standalone Rust binary. + + +1. Create a new Cargo project alongside (not inside) the repo. + + ```sh + cd ../.. # back to repo root + cd .. # leave the provekit directory + cargo new --bin secret-verifier + cd secret-verifier + ``` + +2. Add ProveKit's published verifier crate. + + ```toml title="Cargo.toml" + [package] + name = "secret-verifier" + version = "0.1.0" + edition = "2021" + + [dependencies] + provekit-common = "1.0.0" + provekit-verifier = "1.0.0" + ``` + +3. Write the verifier. + + ```rust title="src/main.rs" + use std::path::Path; + use provekit_common::{file::read, NoirProof, Verifier}; + use provekit_verifier::Verify; + + fn main() -> anyhow::Result<()> { + // Adjust these paths to wherever you ran `prepare`/`prove`. + let pkv_path = Path::new("../provekit/noir-examples/secret-knowledge/secret_knowledge.pkv"); + let proof_path = Path::new("../provekit/noir-examples/secret-knowledge/proof.np"); + + let mut verifier: Verifier = read(pkv_path)?; + let proof: NoirProof = read(proof_path)?; + + verifier.verify(&proof)?; + println!("Proof verified. Prover knows a Poseidon2 preimage of the published commitment."); + Ok(()) + } + ``` + +4. Add `anyhow` and run it. + + ```sh + cargo add anyhow + cargo run --release + ``` + + You should see `Proof verified.` + + +## What you proved + +A user with a `Prover.toml` can convince anyone with the matching `.pkv` and `proof.np` that they know two field elements that hash to the commitment, **without ever transmitting those elements**. + +That's the whole zero-knowledge claim. Everything else in ProveKit is plumbing around this shape: bigger circuits, more complex public input contracts, different hash configurations, different transport layers. + +## Extend this circuit + +Try these next: + +- **Make the commitment a Merkle root**, then proving `secret` hashes to *some leaf* of the tree, without revealing which leaf. See the [`noir-passport`](https://github.com/worldfnd/provekit/tree/main/noir-examples/noir-passport) example for a production-scale instance. +- **Add a nullifier**, bind the secret to a context (election ID, session, chain) and expose the resulting hash as a public input. See [Designing circuits for ProveKit](/concepts/designing-circuits/) for ProveKit-specific mechanics. +- **Verify in a browser**, load the same `.pkv` bytes from a `Uint8Array` and verify in WASM. See [JS/TypeScript end-to-end](/e2e/js-typescript/). +- **Push to chain**, export recursive-verifier inputs and produce a Groth16 outer proof. See [Recursive verifier](/integrations/overview/#recursive-verifier--gnark). + +## Clean up + +```sh +cd ../provekit/noir-examples/secret-knowledge +rm -f secret_knowledge.pkp secret_knowledge.pkv proof.np +rm -rf target +``` + +## Where to go next + +- [Proving flow](/concepts/proving-flow/), the conceptual pipeline behind what you just ran. +- [Artifact lifecycle](/concepts/artifact-lifecycle/), the rules for treating `.pkp`/`.pkv`/`proof.np` as deployment artifacts. +- [Integrations overview](/integrations/overview/), pick the host language where ProveKit will run in your system. +- [Designing circuits for ProveKit](/concepts/designing-circuits/), ProveKit-specific mechanics for shaping your circuit. diff --git a/docs/src/content/docs/index.mdx b/docs/src/content/docs/index.mdx new file mode 100644 index 000000000..0e5329914 --- /dev/null +++ b/docs/src/content/docs/index.mdx @@ -0,0 +1,102 @@ +--- +title: ProveKit Documentation +description: Compile Noir circuits to R1CS, generate WHIR proofs, and verify them anywhere, from the CLI to browsers, mobile apps, services, and on-chain via a recursive verifier. +template: splash +hero: + tagline: A zero-knowledge proof toolkit for shipping Noir circuits to production, across native, browser, mobile, server, and on-chain verification. + actions: + - text: Run the quickstart + link: /getting-started/quickstart/ + icon: right-arrow + variant: primary + - text: What is ProveKit? + link: /concepts/what-is-provekit/ + icon: open-book + - text: View on GitHub + link: https://github.com/worldfnd/provekit + icon: external +--- + +import { Aside, Card, CardGrid, LinkCard } from '@astrojs/starlight/components'; + +

+ProveKit turns a Noir circuit into a verifiable WHIR proof, then lets you verify that proof wherever you need it, locally, in a Rust service, in the browser, on iOS or Android, or on-chain through a Groth16 recursive verifier. +

+ +## See it in three commands + +From a fresh checkout of the [ProveKit repository](https://github.com/worldfnd/provekit): + +```sh +cd noir-examples/basic +cargo run --release --bin provekit-cli -- prepare # compile circuit → .pkp + .pkv +cargo run --release --bin provekit-cli -- prove # .pkp + Prover.toml → proof.np +cargo run --release --bin provekit-cli -- verify # .pkv + proof.np → exit 0 +``` + +That's the whole proving pipeline. Every other integration, Rust, WASM, mobile, is the same flow against the same artifacts. [Walk through it step by step →](/getting-started/quickstart/) + +## Get started + + + + Prepare keys, generate `proof.np`, and verify it locally using the `noir-examples/basic` circuit. + + [Run the quickstart →](/getting-started/quickstart/) + + + A developer-friendly introduction to zero-knowledge proofs and the problems this toolkit solves. + + [Read the overview →](/concepts/what-is-provekit/) + + + Choose where ProveKit runs in your system, CLI, Rust, WASM, mobile, or recursive. + + [Integrations overview →](/integrations/overview/) + + + The provenance, evidence, and operational controls required before accepting proofs in production. + + [Review the checklist →](/reference/production-checklist/) + + + +## Host integrations + +ProveKit runs the same proof artifacts across server, browser, and mobile. For the full menu, including CLI, HTTP verifier, and recursive paths, see [Integrations overview](/integrations/overview/). + + + + + + +## Core artifacts at a glance + +
+
.pkpProver key, produced by `prepare`, consumed by `prove`.
+
.pkvVerifier key, produced by `prepare`, consumed by `verify` and recursive export.
+
proof.npWHIR proof, produced by `prove`, consumed by every verification path.
+
r1cs.jsonRecursive-verifier R1CS, exported from a matching `.pkv` and proof.
+
+ +Every artifact is bound to a specific circuit, commit, compiler backend, and hash choice. Treat them as versioned deployment objects. See [Artifact lifecycle](/concepts/artifact-lifecycle/) for the full pairing rules. + + diff --git a/docs/src/content/docs/integrations/overview.mdx b/docs/src/content/docs/integrations/overview.mdx new file mode 100644 index 000000000..0af704da7 --- /dev/null +++ b/docs/src/content/docs/integrations/overview.mdx @@ -0,0 +1,241 @@ +--- +title: Integrations overview +description: Pick the integration path that matches where ProveKit will prove or verify in your system. +--- + +import { Aside, Card, CardGrid, Tabs, TabItem } from '@astrojs/starlight/components'; + +ProveKit ships six integration paths: the CLI, native Rust crates, WebAssembly, a C FFI for mobile, an HTTP verifier service, and a Go/gnark recursive verifier. Choose the path that matches where proof generation or verification needs to run, then keep artifact provenance consistent across boundaries. + +**Rust API:** [`provekit-common`](https://docs.rs/provekit-common) · [`provekit-prover`](https://docs.rs/provekit-prover) · [`provekit-verifier`](https://docs.rs/provekit-verifier). New here? Start with [What is ProveKit?](/concepts/what-is-provekit/) and the [glossary](/reference/glossary/). + +## The same flow, every host + +Every integration runs the same three-step pipeline. Here's what verifying a proof looks like in each: + + + +```sh +cargo run --release --bin provekit-cli -- verify \ + --verifier app.pkv \ + --proof proof.np +# exit 0 = valid +``` + + +```rust +use provekit_common::{file::read, NoirProof, Verifier}; +use provekit_verifier::Verify; + +let mut verifier: Verifier = read("app.pkv")?; +let proof: NoirProof = read("proof.np")?; +verifier.verify(&proof)?; +``` + + +```ts +import { Backend, Verity } from "@atheon/verity"; + +const verity = await Verity.create(Backend.ProveKit); +const verifier = await verity.loadVerifier(pkvBytes); +const valid = await verifier.verify(proof); +``` + + +```swift +import Verity + +let verity = try Verity(backend: .provekit) +let verifier = try verity.loadVerifier(from: "app.pkv") +let valid = try verifier.verify(proof: proof) +``` + + +```kotlin +import xyz.atheon.verity.* + +val verity = Verity(Backend.PROVEKIT) +val verifier = verity.loadVerifier("app.pkv") +verifier.use { v -> check(v.verify(proof)) } +``` + + +```sh +curl -X POST http://verifier:3000/verify -d '{ + "pkvUrl": "https://example.com/app.pkv", + "r1csUrl": "https://example.com/r1cs.json", + "np": { /* NoirProof JSON */ } +}' +``` + + + +The same `.pkv` and proof artifact drive every path. Pick by where you want verification to live. + +## Decision table + +| Path | Repo location | Use when | Primary artifacts | +| :--- | :--- | :--- | :--- | +| **CLI** | `tooling/cli/` | You want a command-line prepare/prove/verify workflow or CI artifact generation. | `.pkp`, `.pkv`, `proof.np`, `r1cs.json`, recursive params. | +| **Rust crates** | `provekit/*`, `tooling/*` | You are embedding ProveKit in Rust services, tools, or tests. | Rust `Prover`, `Verifier`, `NoirProof` values plus `.pkp` / `.pkv` files. | +| **WASM** | `tooling/provekit-wasm/` | You need proving or verification in a browser or Node.js application. | `.pkp` / `.pkv` bytes, witness map, JSON proof bytes/object. | +| **FFI** | `tooling/provekit-ffi/` | You need C ABI bindings for Swift/iOS, Kotlin/Android, Python, or another host. | Native library, `provekit_ffi.h`, `.pkp`, TOML inputs, proof file or JSON buffer. | +| **Verifier server** | `tooling/verifier-server/` | You need an HTTP API that downloads artifacts and orchestrates verification. | `pkvUrl`, `r1csUrl`, JSON `NoirProof`, optional Groth16 `pkUrl` / `vkUrl`. | +| **Recursive verifier** | `recursive-verifier/` | You need Go/gnark recursive verification and Groth16 wrapping. | `params_for_recursive_verifier`, `r1cs.json`, optional proving/verifying keys. | + +## Choose by runtime + + + + Use the CLI for auditable release artifact generation and CI checks. + + + Embed the crates when the service can own artifact loading, verification policy, and the proof/key lifecycle directly. + + + Use the WASM bindings when proof generation or verification has to happen in JavaScript. + + + Use the FFI-backed Swift or Kotlin SDK when native packaging, memory limits, and deterministic cleanup matter. + + + +## Artifact rules + +Every integration path follows the same rules: + +1. Run `prepare` for the exact circuit source, branch, compiler backend, and hash configuration you plan to deploy. +2. Keep the generated `.pkp` and `.pkv` together. Never pair a prover key from one build with a verifier key from another. +3. Generate proofs from inputs intended for that circuit and key pair. +4. Verify before crossing any trust boundary. +5. Regenerate recursive-verifier artifacts after the verifier key, proof, circuit, or hash choice changes. +6. Treat `.pkp`, `.pkv`, proofs, public inputs, `r1cs.json`, and recursive params as versioned deployment artifacts. + + + +## CLI-driven services + +Use the CLI when CI or a build job is responsible for producing deployment artifacts. + +```sh +mkdir -p artifacts +cargo run --release --bin provekit-cli -- prepare \ + . \ + --pkp artifacts/app.pkp \ + --pkv artifacts/app.pkv +cargo run --release --bin provekit-cli -- prove \ + --prover artifacts/app.pkp \ + --input Prover.toml \ + --out artifacts/proof.np +cargo run --release --bin provekit-cli -- verify \ + --verifier artifacts/app.pkv \ + --proof artifacts/proof.np +``` + +Prefer explicit output paths in automation. Default key names depend on the enclosing Nargo package, which can be surprising in multi-package workspaces. + +## Rust embedding + +Embed the crates when your application can link ProveKit directly. + +- `provekit-common`, shared proof, key, R1CS, file, and serialization types. +- `provekit-r1cs-compiler`, lowers Noir ACIR into ProveKit proof schemes. +- `provekit-prover`, exposes the `Prove` trait for proof generation. +- `provekit-verifier`, exposes the `Verify` trait for proof verification. +- `provekit-gnark`, writes the Rust-side recursive-verifier bridge artifacts. + +Operational notes: + +- Native verifier values are consumed by the `Verify` implementation; reload or clone verifier state when verifying multiple proofs in one process. +- Match CLI behavior in tests by reading and writing artifacts through `provekit_common::file` helpers. +- Keep the hash configuration explicit in services so deployments don't drift on a changed default. + +## WASM / JavaScript + +`tooling/provekit-wasm` exports the browser-facing bindings: + +| Export | Purpose | +| :--- | :--- | +| `initPanicHook()` | Install better panic reporting in the browser console. | +| `initThreadPool(n)` | Initialize the Rayon-backed WASM thread pool. | +| `new Prover(pkpBytes)` | Load a `.pkp` prover artifact from binary or JSON bytes. | +| `Prover.getCircuit()` | Return Noir circuit JSON for `@noir-lang/noir_js`. Noir provers only. | +| `Prover.getNumConstraints()` | Return the prepared circuit constraint count. | +| `Prover.getNumWitnesses()` | Return the prepared circuit witness count. | +| `Prover.proveBytes(witnessMap)` | Generate a JSON-serialized proof as bytes. Consumes the prover. | +| `Prover.proveJs(witnessMap)` | Generate a proof as a JavaScript value. Consumes the prover. | +| `new Verifier(pkvBytes)` | Load a `.pkv` verifier artifact from binary or JSON bytes. | +| `Verifier.verifyBytes(proofJson)` | Verify proof JSON bytes. Verifier is reusable. | +| `Verifier.verifyJs(proof)` | Verify a proof JavaScript value. Verifier is reusable. | + +Witness maps may be `Map` values or plain objects like `{ "0": "0x..." }`. Values must be hex strings that fit BN254 field elements. + +## FFI / mobile hosts + +`tooling/provekit-ffi` provides a C ABI for hosts that can't link Rust directly. + +| Function | Purpose | +| :--- | :--- | +| `pk_init()` | Initialize ProveKit before any other FFI call. | +| `pk_prove_to_file(prover_path, input_path, out_path)` | Generate a proof and write it to a file. | +| `pk_prove_to_json(prover_path, input_path, out_buf)` | Generate a JSON proof buffer. | +| `pk_free_buf(buf)` | Free buffers returned by FFI calls. | +| `pk_set_allocator(alloc, dealloc)` | Configure host allocator callbacks before initialization. | +| `pk_configure_memory(limit, file_backed, path)` | Configure the mmap allocator before `pk_init()`. | +| `pk_get_memory_stats(...)` | Read RAM, swap, and peak memory statistics. | + +Swift, Kotlin, and Python examples live in `tooling/provekit-ffi/README.md`. For mobile builds, compile the static library for each target architecture and ship `tooling/provekit-ffi/include/provekit_ffi.h` alongside the resulting libraries. + +## Verifier server + +`tooling/verifier-server` exposes an Axum HTTP service: + +| Route | Method | Purpose | +| :--- | :--- | :--- | +| `/health` | `GET` | Return server health, version, and timestamp. | +| `/verify` | `POST` | Verify a JSON proof using downloaded artifacts. | + +A verification request looks like: + +```json +{ + "pkvUrl": "https://example.com/verifier.pkv", + "r1csUrl": "https://example.com/r1cs.json", + "pkUrl": "https://example.com/proving_key.bin", + "vkUrl": "https://example.com/verification_key.bin", + "np": { "proof": "NoirProof JSON fields" }, + "verificationParams": { "maxVerificationTime": 300 }, + "metadata": { "requestId": "request-123" } +} +``` + +`pkUrl`, `vkUrl`, `verificationParams`, and `metadata` are optional. Artifact URLs must use HTTP or HTTPS. The server defaults to one concurrent verification and a 10 MiB request body limit, tune both through the `VERIFIER_*` environment variables documented in `tooling/verifier-server/README.md`. + +## Recursive verifier / gnark + +Use `generate-gnark-inputs` to bridge a ProveKit verifier key and proof into the Go/gnark recursive verifier: + +```sh +cargo run --release --bin provekit-cli -- generate-gnark-inputs \ + artifacts/app.pkv \ + artifacts/proof.np \ + --params artifacts/params_for_recursive_verifier \ + --r1cs artifacts/r1cs.json +``` + +Then run the Go CLI or server from `recursive-verifier/` with those files. If you omit the recursive proving and verifying keys, the Go tool can generate them for development, production deployments should manage trusted-setup keys explicitly. + +## Production readiness + +Before shipping any integration, complete the [Production checklist](/reference/production-checklist/). At a minimum: pin the branch or release, record artifact provenance, define who may generate keys, configure verifier-server limits, and add an end-to-end regeneration test in CI. + +## Platform guides + +The platform pages cover the supported API paths, default artifact flow, and build constraints. Run the snippets inside a real app or test target before relying on them. + +- **[Rust](/e2e/rust/)**, direct crate integration for services, tools, and tests. +- **[JS / TypeScript](/e2e/js-typescript/)**, browser and Node.js usage via the ProveKit WASM backend. +- **[Swift](/e2e/swift/)**, Swift Package Manager integration with source-only, native, and release modes. +- **[Kotlin](/e2e/kotlin/)**, Android integration with JNI packaging guidance. diff --git a/docs/src/content/docs/reference/changelog.mdx b/docs/src/content/docs/reference/changelog.mdx new file mode 100644 index 000000000..49c122065 --- /dev/null +++ b/docs/src/content/docs/reference/changelog.mdx @@ -0,0 +1,89 @@ +--- +title: Changelog +description: A curated record of substantive changes to ProveKit. Grouped by theme, derived from the Git history on the `main` and `v1` branches. +--- + +import { Aside } from '@astrojs/starlight/components'; + +Tagged releases live on [GitHub Releases](https://github.com/worldfnd/provekit/releases) — that's the authoritative record of what's in each version. This page summarizes themes alongside the release notes, plus the rolling work on `main` between tags. For the exhaustive log, use the [GitHub commit history](https://github.com/worldfnd/provekit/commits/main). + + + +## v1.0.0 + +The first tagged release of ProveKit. Crates published to crates.io: `provekit-cli`, `provekit-common`, `provekit-prover`, `provekit-verifier`, `provekit-r1cs-compiler`, `provekit-gnark`, `provekit-ffi`, `provekit-wasm`. + +See the [v1.0.0 release notes](https://github.com/worldfnd/provekit/releases/tag/v1.0.0) for the full change list. + +## Unreleased (rolling, `main`) + +### Breaking changes + +- **CLI subcommand renamed.** `circuit_stats` → `circuit-stats`. Update scripts and CI jobs. +- **Hash configuration is stored on `WhirR1CSScheme`.** Process-global hash drift is no longer possible; consumers reading scheme types directly should fetch the hash from the scheme instead of process state. +- **Digest hashers unified, V1 domain separation tag added.** Proof hashing is now consistent across paths. + +### CLI + +- **Zero-arg defaults for `prepare` / `prove` / `verify`.** Each command runs from the enclosing Noir package without explicit paths, with full `--pkp` / `--pkv` / `--prover` / `--verifier` / `--input` / `--out` overrides still available. +- Improved CSP benchmark scripts to match the new `prove` / `verify` flags. + +### Performance + +- **Poseidon2 hot path:** inlined permutation helpers, squaring S-box, zero-allocation byte/field conversion, in-place API. +- **Native Keccak benchmarks** rebalanced for lower witness count. +- **NTT** picked up an explicit `roots` method, b51-mode NTT enabled in WASM, and a canonicalized comparison test. + +### Hash and proof system + +- **Poseidon2 hash config** is now selectable via `--hash poseidon2` alongside Skyscraper, SHA-256, Keccak, and Blake3. +- **Public-input hashing** is aligned with the chosen `HashConfig`. Mixing public-input encoding across hash choices was previously possible and is now prevented. +- **Process-global hash drift eliminated.** Hash configuration is stored on the scheme. + +### Benchmarks + +- **Ethproofs CSP benchmark suite added** under `noir-examples/csp-benchmarks/`. Targets: SHA-256 (128–2048 bytes), Keccak-256 (128–2048 bytes), Poseidon (states 2–16), Poseidon2 (states 2–16), and ECDSA over secp256r1. +- **Sticky CSP PR comment** in CI reports constraints, witnesses, and deltas vs. the `main` baseline. + +### Compiler and tests + +- **Noir blackbox hash paths** are preferred where ProveKit lowers them efficiently. The CSP suite documents where native Noir paths win instead. +- **Verifier-visible public input equalities** are preserved by Noir prepare. + +### Documentation + +- Restructured docs site (Astro Starlight) with a Diátaxis-aligned IA: Start here / Build and integrate / Concepts / Reference / Operations. +- Added: *What is ProveKit?* explainer, *Tutorial* (private-knowledge proof), *Designing circuits for ProveKit* (ProveKit-specific circuit mechanics), *Performance*, *Comparison*, *FAQ*, *Examples catalog*, *FFI error codes*, *Starter templates*, *Changelog*. + +### WASM + +- Re-routed the wasm-demo through Verity without changing the ProveKit UX surface. +- Raised the SHA-256 demo circuit workload to better exercise the in-browser path. + +### Acknowledged work in progress + +These are tracked, not yet shipped: + +- Tagged releases and SemVer guarantees. +- Public audit certification. +- Native (non-Groth16) recursive verification. +- Hosted rustdoc and generated C-header reference linked from the docs. +- Release binaries for `provekit-cli`. +- An official starter-app repository (see [Starter templates](/reference/starter-template/) for the assembly recipe meanwhile). + +## Branch policy recap + +| Branch | Purpose | Compatibility | +| :--- | :--- | :--- | +| `v1` | Current stable interface. | Treat as the reproducibility target. | +| `main` | Active development. | Formats and APIs may change between commits. | + +See [Project status and versioning](/reference/project-status/) for the full policy. + +## Where this changelog comes from + +Per-release content comes from [GitHub Releases](https://github.com/worldfnd/provekit/releases). The "Unreleased" section above is curated from substantive commits on `main` between tags. It is *not* a complete log; every change is in Git, but most don't belong in a user-facing changelog. The selection criterion: would a user who upgraded benefit from knowing this? + +If you spot a missing change that affects users, open an issue or PR against `docs/src/content/docs/reference/changelog.mdx`. diff --git a/docs/src/content/docs/reference/comparison.mdx b/docs/src/content/docs/reference/comparison.mdx new file mode 100644 index 000000000..8202cef3c --- /dev/null +++ b/docs/src/content/docs/reference/comparison.mdx @@ -0,0 +1,70 @@ +--- +title: How ProveKit compares +description: Side-by-side comparison of ProveKit with other zero-knowledge proof systems, Halo2, Plonky2, Circom + SnarkJS, RISC Zero. +--- + +import { Aside } from '@astrojs/starlight/components'; + +There is no single "best" ZK proof system, choices depend on the frontend you want, the verification target, audit posture, and operational tooling. This page summarizes how ProveKit positions itself against the most common alternatives. + + + +## Comparison matrix + +| Dimension | **ProveKit** | Halo2 (PSE / zcash) | Plonky2 | Circom + SnarkJS / RapidSnark | RISC Zero | +| :--- | :--- | :--- | :--- | :--- | :--- | +| **Frontend** | Noir | Rust DSL (in-circuit `Region`/`Gate` API) | Rust DSL | Circom | Rust binary (zkVM) | +| **Proof system** | WHIR + Spartan-style sumcheck | Plonkish + IPA / KZG | FRI-based PLONK | Groth16 (default) | STARK + Groth16 wrap | +| **Trusted setup (base proof)** | None | None (IPA) / per-circuit (KZG) | None | Per-circuit ceremony | None | +| **Post-quantum secure (base proof)** | Yes (hash-based WHIR) | No (IPA = discrete log; KZG = pairings) | Yes (FRI / hash-based) | No (pairings) | Yes (FRI-based STARK) | +| **Post-quantum secure (on-chain wrap)** | No (Groth16 over BN254) | KZG: no; direct IPA verification not standard on Ethereum | No (Groth16 wrap) | No | No (Groth16 wrap) | +| **Field** | BN254 | BN254 / Pasta | Goldilocks | BN254 / BLS12-381 | Baby Bear → BN254 wrap | +| **On-chain target** | Groth16 wrap via Go/gnark | Direct on Ethereum (KZG mode) | Wrap to Groth16 | Direct on Ethereum | Groth16 wrap | +| **Native host support** | CLI, Rust, WASM, FFI, HTTP server, recursive | Rust | Rust | JS/WASM, native binary | Rust, WASM | +| **Mobile path** | First-class (Swift + Kotlin SDKs via FFI) | DIY | DIY | DIY | Experimental | +| **Recursive verification** | Via gnark Groth16 wrapper | Native | Native (fast) | Limited | Native (zkVM-style) | +| **Audit status** | No public audit yet | Multiple audits | Audited (Polygon) | Multiple audits | Multiple audits | +| **License** | MIT | MIT / Apache-2 | Apache-2 / MIT | GPL-3 / MIT components | Apache-2 | +| **Best when** | You want Noir + production-shaped runtime + cheap EVM verification | You want maximum control inside Ethereum tooling | You want fast recursion in pure Rust | You're already invested in Circom or need legacy EVM verifiers | You want to prove arbitrary Rust without writing a circuit | + +## Where ProveKit shines + +- **Noir frontend.** Higher-level than Halo2's in-circuit API, less constrained than Circom's signal-based model, type-checked unlike most circuit DSLs. +- **Cross-host runtime out of the box.** CLI, Rust, WASM, FFI, mobile, and recursive paths from one codebase. Most alternatives leave host integration to you. +- **No trusted setup for the base proof.** WHIR's commitment scheme avoids per-circuit ceremonies; only the optional Groth16 outer wrap involves one. +- **Production-shaped tooling.** Versioned artifacts, hash-choice control, public-input inspection, memory configuration on mobile, and a verifier service with concurrency controls. + +## Where ProveKit is weaker today + +- **Audit maturity.** No public audit certification yet. Halo2, Plonky2, and Circom-based stacks have multiple audits behind them. +- **Recursive verification.** Native recursion isn't yet a first-class operation, the path goes through gnark Groth16 wrapping. Plonky2 and RISC Zero have direct recursion built in. +- **Established benchmarks.** WHIR is newer than PLONK and FRI families; published numbers from competing systems are not directly comparable yet. +- **Ecosystem.** Noir's ecosystem is younger than Circom's. Reusable libraries (signatures, primitives) are growing but smaller in scope. + +## Choosing between them + +| If your priority is... | Consider | +| :--- | :--- | +| **Ship a credential or attestation app across web + mobile** | ProveKit. The integration story is the differentiator. | +| **Verify directly on Ethereum without a wrapper** | Halo2 (KZG mode) or Circom + SnarkJS. Mature on-chain verifiers exist. | +| **Prove arbitrary Rust binaries without a circuit** | RISC Zero. zkVM approach trades constraint efficiency for developer ergonomics. | +| **Maximize recursion throughput** | Plonky2. Native fast recursion is the headline feature. | +| **Battle-tested + Ethereum-native** | Halo2. Most production Ethereum ZK stacks lean on it. | +| **Audit-mature signature schemes** | Circom ecosystem. The largest catalog of audited primitives. | + +## What to verify before committing + +For any proof system, validate these before building on top: + +1. **Run your real circuit through it.** Synthetic benchmarks rarely predict your workload. +2. **Confirm the verification target.** Where does the verifier run? On-chain? In a phone? In a browser? +3. **Check audit status.** Has the proof system, the frontend, and the recursive verifier been independently reviewed? +4. **Test the deployment story.** Versioning, artifact distribution, key management, these are where most ZK projects struggle, regardless of the proof system underneath. + +## Related pages + +- [What is ProveKit?](/concepts/what-is-provekit/), the ProveKit overview. +- [FAQ](/reference/faq/), broader Q&A on capabilities and limits. +- [Performance](/reference/performance/), how to measure ProveKit honestly. diff --git a/docs/src/content/docs/reference/error-codes.mdx b/docs/src/content/docs/reference/error-codes.mdx new file mode 100644 index 000000000..b00f1abfa --- /dev/null +++ b/docs/src/content/docs/reference/error-codes.mdx @@ -0,0 +1,86 @@ +--- +title: FFI error codes +description: Every PKError returned by the ProveKit FFI, what triggers it, and how to recover. +--- + +import { Aside } from '@astrojs/starlight/components'; + +The ProveKit C FFI (`tooling/provekit-ffi/`) returns a `PKError` code on every function call. `PK_SUCCESS` (0) means success; any other value indicates failure. Hosts (Swift, Kotlin, Python, custom C/C++) should branch on the numeric code in production paths. + +The codes below are mirrored from [`provekit_ffi.h`](https://github.com/worldfnd/provekit/blob/main/tooling/provekit-ffi/include/provekit_ffi.h). + +## Error code reference + +| Code | Constant | Meaning | Common causes | Resolution | +| :--- | :--- | :--- | :--- | :--- | +| 0 | `PK_SUCCESS` | Success. |, |, | +| 1 | `PK_INVALID_INPUT` | Invalid input parameters, for example a null pointer where one was required. | Forgot to populate a path string, passed a null buffer, or pre-init memory configuration left `ram_limit_bytes` at `0`. | Validate non-null pointers and required path arguments before the call. Configure memory before `pk_init()`. | +| 2 | `PK_SCHEME_READ_ERROR` | Failed to read or deserialize the `.pkp` (prover key) file. | Missing file, wrong path, corrupted artifact, or a `.pkp` from an incompatible ProveKit version. | Verify the path through the host filesystem APIs. Confirm the file came from the matching `prepare` run on the deployed branch. | +| 3 | `PK_WITNESS_READ_ERROR` | Failed to read or parse the witness / input TOML for this circuit. | Wrong file, mismatched circuit ABI, malformed TOML, or incorrect hex encoding in a witness map. | Run `provekit-cli show-inputs` on the corresponding proof to confirm the expected ABI. Validate witness encoding (hex strings ≤ 32 bytes, BN254 field range). | +| 4 | `PK_PROOF_ERROR` | Proof generation failed inside the prover. | Inputs that don't satisfy the circuit (constraint violation), exhausted memory, or a bug in a witness builder for unusual inputs. | Reproduce with the CLI using the same inputs. If the CLI fails too, the inputs likely don't satisfy the circuit. Otherwise capture stderr and open an issue. | +| 5 | `PK_SERIALIZATION_ERROR` | Failed to serialize the output (proof bytes or JSON). | Internal serializer failure, often paired with an unexpected allocator or buffer-size condition. | Free intermediate buffers, check `pk_get_memory_stats()` for allocator pressure, and re-run from a clean state. | +| 6 | `PK_UTF8_ERROR` | UTF-8 conversion error. | A path or string argument contained bytes that don't form valid UTF-8. | Ensure all `const char *` arguments are valid UTF-8 null-terminated strings. | +| 7 | `PK_FILE_WRITE_ERROR` | Failed to write an output file. | Path doesn't exist, parent directory is read-only, or disk is full. | Create the output directory first. Check permissions. Verify free space on the target volume. | + + + +## Functions that return error codes + +Every FFI entry point that performs work returns a `PKError` (as `int`): + +| Function | Purpose | Returns | +| :--- | :--- | :--- | +| `pk_init()` | Initialize the library. Call once before any other operation. | `PK_SUCCESS` on success. | +| `pk_prove_to_file(prover_path, input_path, out_path)` | Generate a proof and write it to a file. | `PK_SUCCESS` or a `PKError` code. | +| `pk_prove_to_json(prover_path, input_path, *out_buf)` | Generate a proof as a JSON buffer (when built with JSON support). | `PK_SUCCESS` or a `PKError` code. | +| `pk_configure_memory(ram_limit_bytes, use_file_backed, swap_file_path)` | Configure the mmap allocator. **Must be called before `pk_init()`.** | `PK_SUCCESS` or `PK_INVALID_INPUT`. | +| `pk_get_memory_stats(*ram_used, *swap_used, *peak_ram)` | Read RAM, swap, and peak memory statistics. | `PK_SUCCESS`. | + +`pk_free_buf` and `pk_set_allocator` return `void`. + +## Recovery patterns + +### Mobile: branch on the error class + +```swift +let status = pk_prove_to_file(proverPath, inputPath, outputPath) +switch status { +case Int32(PK_SUCCESS.rawValue): + return .success +case Int32(PK_SCHEME_READ_ERROR.rawValue), + Int32(PK_WITNESS_READ_ERROR.rawValue): + // Bad input, re-fetch artifacts, validate paths, retry once. + return .reloadArtifacts +case Int32(PK_PROOF_ERROR.rawValue), + Int32(PK_SERIALIZATION_ERROR.rawValue): + return .failedProof +default: + return .systemError +} +``` + +### Server: distinguish soft and hard failures + +`PK_INVALID_INPUT`, `PK_WITNESS_READ_ERROR`, `PK_UTF8_ERROR` are client-shaped, the request was malformed. Return a 4xx HTTP status. + +`PK_PROOF_ERROR`, `PK_SERIALIZATION_ERROR`, `PK_FILE_WRITE_ERROR`, and `PK_SCHEME_READ_ERROR` are environment-shaped, your runtime is unhealthy (missing files, allocator pressure, or a real prover bug). Return a 5xx and alert. + +### CLI smoke test for any FFI failure + +When an FFI host reports an error, the fastest reproduction is the CLI: + +```sh +cargo run --release --bin provekit-cli -- prove --prover circuit.pkp --input Prover.toml +cargo run --release --bin provekit-cli -- verify --verifier circuit.pkv --proof proof.np +cargo run --release --bin provekit-cli -- show-inputs --hex circuit.pkv proof.np +``` + +If the CLI fails the same way, the artifact set is the problem. If the CLI succeeds, the FFI host integration is. + +## Related pages + +- [Common errors](/troubleshooting/common-errors/), broader failure diagnosis across CLI, WASM, FFI, and verifier server. +- [Integrations overview](/integrations/overview/#ffi--mobile-hosts), FFI surface and lifecycle. +- [Production checklist](/reference/production-checklist/), FFI lifecycle controls before launch. diff --git a/docs/src/content/docs/reference/examples.mdx b/docs/src/content/docs/reference/examples.mdx new file mode 100644 index 000000000..b83ad0451 --- /dev/null +++ b/docs/src/content/docs/reference/examples.mdx @@ -0,0 +1,109 @@ +--- +title: Examples catalog +description: Noir circuits shipped with ProveKit, grouped by what they demonstrate. +--- + +import { Aside } from '@astrojs/starlight/components'; + +The [`noir-examples/`](https://github.com/worldfnd/provekit/tree/main/noir-examples) directory contains circuits that exercise ProveKit's compiler and proving pipeline. Some are minimal demos; others are real-world primitives used to benchmark and validate the system end-to-end. + +Each example is a self-contained Noir package. To run any of them: + +```sh +cd noir-examples/ +cargo run --release --bin provekit-cli -- prepare +cargo run --release --bin provekit-cli -- prove +cargo run --release --bin provekit-cli -- verify +``` + + + +## Hash primitives + +Circuits demonstrating the hash functions ProveKit can prove over. + +| Example | What it demonstrates | +| :--- | :--- | +| **`basic`** | Poseidon2 BN254 preimage proof, the canonical "hello world" circuit. | +| **`basic-2`, `basic-3`, `basic-4`** | Progressive Poseidon variations for compiler testing. | +| **`poseidon2`** | Direct Poseidon2 hashing primitive in isolation. | +| **`many_poseidons`** | Stress test with many Poseidon hash calls in one circuit. | +| **`poseidon-rounds`** | Single-round Poseidon decomposition, useful for understanding round structure. | +| **`sha256`, `noir_sha256`, `noir-native-sha256`** | SHA-256 variants compiled through Noir's black-box and native paths. | +| **`partial_sha256`** | SHA-256 with a partial preimage, common for incremental hashing patterns. | + +## Elliptic curves and signatures + +Circuits exercising scalar multiplication, signature schemes, and curve arithmetic. + +| Example | What it demonstrates | +| :--- | :--- | +| **`babyjubjub`** | Baby Jubjub curve operations, the standard curve for in-circuit ECC over BN254. | +| **`eddsa_poseidon2`** | EdDSA signature verification using Poseidon2 for hashing. | +| **`embedded_curve_msm`** | Multi-scalar multiplication on the embedded curve via Noir's intrinsic. | +| **`native_msm`** | MSM expressed without the embedded-curve intrinsic, heavier circuit, useful for comparisons. | +| **`msm_conditional`** | Conditional MSM, pick scalars or points at runtime inside the circuit. | +| **`msm_conditional_nested`** | Nested conditional MSM, demonstrating composition. | +| **`p256_std`** | P-256 (secp256r1) signature verification over the standard curve. | +| **`p256_bigcurve`** | P-256 with bigcurve representation, relevant when proving WebAuthn or hardware-attestation signatures. | + +## Identity and credentials + +Circuits demonstrating real-world identity workflows. + +| Example | What it demonstrates | +| :--- | :--- | +| **`noir-passport`** | Passport-style credential verification, the foundation for selective disclosure. | +| **`noir-passport-examples`** | Variations of the passport flow used for testing different selective-disclosure patterns. | +| **`noir-passport-monolithic`** | Single-circuit version of the passport workflow, useful for understanding the full constraint cost. | +| **`oprf`** | Oblivious Pseudorandom Function, a primitive used in private set intersection and de-anonymization defenses. | + +## Arithmetic primitives + +Small circuits that ProveKit uses internally for testing and benchmarking. + +| Example | What it demonstrates | +| :--- | :--- | +| **`power`** | Modular exponentiation inside a circuit. | +| **`rangechecks`** | Range constraints, the building block for bounded arithmetic. | +| **`noir-r1cs-test-programs`** | A suite of programs used by the R1CS compiler's own test harness. | + +## Applications + +Larger circuits modeled after real applications. + +| Example | What it demonstrates | +| :--- | :--- | +| **`zkchase`** | A small game-like circuit demonstrating state transitions and rule enforcement. | + +## Benchmarks + +| Example | What it demonstrates | +| :--- | :--- | +| **`csp-benchmarks`** | Constraint system performance benchmarks. Use these as a baseline when measuring circuit cost. | + +## Reading an example + +Every example follows the same layout: + +``` +noir-examples/basic/ +├── Nargo.toml # Noir package metadata + dependencies +├── Prover.toml # Witness inputs (private + public) +└── src/ + └── main.nr # Circuit definition +``` + +The `Prover.toml` is the only file you typically edit to change what's being proven, the circuit is fixed; the inputs vary per proof. To inspect what a verified proof actually exposes: + +```sh +cargo run --release --bin provekit-cli -- show-inputs --hex \ + .pkv \ + proof.np +``` + +## Contributing examples + +Pull requests adding new example circuits are welcome. Keep them minimal, focused on one primitive, and accompanied by a `Prover.toml` that produces a verifiable proof out of the box. diff --git a/docs/src/content/docs/reference/faq.mdx b/docs/src/content/docs/reference/faq.mdx new file mode 100644 index 000000000..2620561e6 --- /dev/null +++ b/docs/src/content/docs/reference/faq.mdx @@ -0,0 +1,123 @@ +--- +title: Frequently asked questions +description: Common questions about ProveKit's maturity, scope, performance, and how it compares to other ZK systems. +--- + +import { Aside } from '@astrojs/starlight/components'; + +## Project and maturity + +### Is ProveKit production-ready? + +ProveKit is under active development. The proof system, key formats, and integration APIs continue to evolve on `main`. The `v1` branch holds the current stable interface, use it for any work where reproducibility matters. The [Production checklist](/reference/production-checklist/) outlines the controls you should have in place before shipping a user-facing workflow. + +### Which branch should I use? + +| Use `v1` when | Use `main` when | +| :--- | :--- | +| Reproducibility, stable formats, and clean upgrades matter. | You are contributing, testing experimental features, or accept regenerating artifacts as formats change. | + +See [Project status and versioning](/reference/project-status/) for the full policy. + +### Has ProveKit been audited? + +There is no public audit certification yet. Treat ProveKit as alpha-grade cryptographic software for the purpose of risk management. The codebase ships with property-based tests, regression tests, and a documented soundness checklist for reviewers in `CLAUDE.md` at the repo root. + +### What's the license? + +[MIT](https://github.com/worldfnd/provekit/blob/main/LICENSE.md). + +## Capabilities and scope + +### What proof system does ProveKit use? + +A **Spartan-based protocol** with [WHIR](https://github.com/WizardOfMenlo/whir) as the polynomial commitment scheme. Spartan is a SNARK for R1CS that uses sumcheck rounds; WHIR backs those rounds with a hash-based polynomial commitment. No trusted setup for the base proof. The optional recursive verifier wraps proofs in Groth16 for on-chain settlement. + +### Is ProveKit post-quantum secure? + +The **base proof is post-quantum secure** under conjectured hash-function PQ-security. WHIR's commitment scheme is hash-based, so soundness reduces to the collision resistance of the chosen `--hash` (Skyscraper, SHA-256, Keccak, Blake3, or Poseidon2). Grover's algorithm imposes a quadratic speedup on preimage finding, so 256-bit hashes still retain roughly 128-bit security against a quantum adversary. + +The **optional Groth16 recursive wrapper is not post-quantum secure**. It uses pairing-based cryptography over BN254, which Shor's algorithm breaks. If long-term post-quantum security matters in your threat model, verify the base WHIR proof off-chain instead of relying on the Groth16 outer proof as your cryptographic anchor. See [Security and trust model](/concepts/security-model/#cryptographic-assumptions) for the breakdown. + +### What's the BN254 curve doing here? + +ProveKit's field arithmetic is performed over the BN254 scalar field. BN254 is well-supported on EVM chains, which makes the recursive Groth16 wrapper natural for on-chain verification. You don't interact with the field directly, Noir handles it. + +### Can I verify on-chain? + +Yes, through the [recursive verifier](/integrations/overview/#recursive-verifier--gnark): export `params_for_recursive_verifier` and `r1cs.json` with `provekit-cli generate-gnark-inputs`, then feed them into the Go/gnark wrapper in `recursive-verifier/`. The wrapper produces a Groth16 outer proof that can be verified by an EVM contract. + +### What hash functions are available? + +`--hash` accepts `skyscraper` (default, custom-optimized for BN254), `sha256`, `keccak`, `blake3`, and `poseidon2`. The hash is part of the artifact's identity, keys, proofs, and recursive exports made with one hash are not interchangeable with another. See the [CLI overview](/cli/overview/#prepare) for details. + +## Performance and limits + +### How big a circuit can ProveKit handle? + +There is no architectural cap. Practical limits depend on the host: the mobile FFI ships a file-backed mmap allocator so circuits whose witness exceeds device RAM can still prove. For very large circuits, configure memory before initialization (`pk_configure_memory` on FFI, `Verity.configureMemory` on mobile SDKs). + +### How long does proving take? + +It depends on circuit size, hash choice, and host. The proving pipeline is parallelized with [Rayon](https://github.com/rayon-rs/rayon); SIMD-accelerated BN254 arithmetic gives an extra boost on `aarch64`. The fastest path is `--hash skyscraper` on native Rust; the slowest paths are typically constrained-memory mobile builds. Benchmark your specific circuit before estimating production timing. + +### How fast is verification? + +Verification is significantly cheaper than proving and runs on every supported host. The verifier server defaults to a single concurrent verification (`VERIFIER_SEMAPHORE_LIMIT=1`) and a 20-minute request timeout (`VERIFIER_REQUEST_TIMEOUT=1200`, `VERIFIER_TIMEOUT_SECONDS=1200`). Per-request `verificationParams.maxVerificationTime` is capped at 300 seconds. Tune all of those for your circuit. WASM verification is reusable: load a `Verifier` once and verify many proofs without rebuilding state. + +### Can I prove in the browser? + +Yes. The [WASM bindings](/integrations/overview/#wasm--javascript) load `.pkp` bytes, accept a witness map, and produce a JSON proof. Threading depends on `SharedArrayBuffer`; the binding falls back to a single-threaded path when worker setup isn't available. Note: each `Prover` is consumed by one `prove()` call, instantiate a new one per proof. + +## Integration + +### Do I need to know Rust to use ProveKit? + +Only if you embed it through the Rust crates. The CLI is the primary entry point and works with any language that can shell out. The [WASM bindings](/integrations/overview/#wasm--javascript), [Swift SDK](/e2e/swift/), and [Kotlin SDK](/e2e/kotlin/) wrap ProveKit for non-Rust hosts. + +### Can I generate `.pkp` and `.pkv` on one machine and use them on another? + +Yes, that is the deployment model. Generate keys in CI, record the [provenance](/concepts/artifact-lifecycle/), distribute the verifier key alongside your application, and keep the prover key on the proving host. The artifacts are independent of platform. + +### Can I switch hash configurations after deployment? + +Only by regenerating every artifact. `.pkp`, `.pkv`, and the resulting proofs are all tied to the chosen hash. Plan hash choice as a versioned decision, not a runtime knob. + +### What happens if I modify the circuit? + +Every downstream artifact is invalidated, `.pkp`, `.pkv`, proofs, recursive params, and `r1cs.json`. Re-run `prepare` and propagate the new artifacts. The verifier will not accept proofs from the old keys. See [Artifact lifecycle](/concepts/artifact-lifecycle/) for the regeneration rules. + +## Comparisons + +### How is ProveKit different from raw Noir? + +Noir is a circuit language; ProveKit is a proof system, runtime, and deployment toolkit built around it. Noir defines what you want to prove; ProveKit handles the compilation to R1CS, proof generation, verification, and the host-language integrations. You can think of Noir as your source code and ProveKit as your compiler-plus-runtime. + +### How does this compare to Halo2, Plonky2, or Circom? + +The big differentiators: + +- **Noir frontend.** You write circuits in a high-level language with type checking, not at the constraint level. +- **WHIR backend.** No trusted setup for the base proof; modern verification cost characteristics. +- **Cross-host runtime.** First-class CLI, Rust, WASM, FFI, server, and recursive paths from one codebase. +- **Production tooling.** Memory configuration, artifact versioning, hash selection, and a verifier service. + +Performance comparisons depend heavily on circuit shape, benchmark for your workload. + +### Do I have to use the recursive verifier for on-chain settlement? + +You have to use *some* on-chain verifier. ProveKit's path is the Go/gnark wrapper, which produces a Groth16 proof that's cheap to verify on EVM chains. Other recursion targets (other proof systems, other curves) would require separate engineering. + +## Getting help + +### Where do I report bugs? + +Open an issue on the [GitHub repository](https://github.com/worldfnd/provekit/issues). Include the information from the "Still stuck?" section of [Common errors](/troubleshooting/common-errors/#still-stuck) so the maintainers can reproduce. + +### Where do I find the source for a specific component? + +The [Repository Map](https://github.com/worldfnd/provekit#repository-map) in the root README lists every crate, its purpose, and its path. The CLI lives in `tooling/cli/`, the proof system in `provekit/`, and the recursive verifier in `recursive-verifier/`. + +### Is there a changelog? + +Yes. Tagged releases live on [GitHub Releases](https://github.com/worldfnd/provekit/releases); each release page is the authoritative record of what changed. The [Changelog](/reference/changelog/) page in these docs summarizes major themes alongside the release notes. diff --git a/docs/src/content/docs/reference/glossary.mdx b/docs/src/content/docs/reference/glossary.mdx new file mode 100644 index 000000000..8f951302d --- /dev/null +++ b/docs/src/content/docs/reference/glossary.mdx @@ -0,0 +1,48 @@ +--- +title: Glossary +description: Common ProveKit, Noir, R1CS, WHIR, artifact, and integration terms. +--- + +Use this glossary when reading ProveKit docs, debugging artifacts, or writing integration runbooks. + +## A–C + +| Term | Meaning | +| :--- | :--- | +| **ACIR** | Abstract Circuit Intermediate Representation emitted by Noir before backend-specific lowering. | +| **Artifact provenance** | The branch, commit, toolchain, lockfile, command line, feature flags, hash choice, and checksum record for a generated file. | +| **BN254** | Elliptic-curve scalar field used by the current field-element and witness encoding paths. | +| **Circuit** | The constrained computation being proven. In the default flow it is authored as a Noir package. | +| **Compiler backend** | The path used by `prepare` to derive a ProveKit proof scheme from Noir source. | + +## D–P + +| Term | Meaning | +| :--- | :--- | +| **FFI** | Foreign Function Interface. ProveKit exposes a C ABI for mobile and native hosts that cannot link Rust directly. | +| **Hash choice** | The Merkle commitment hash selected by `prepare --hash`: `skyscraper`, `sha256`, `keccak`, `blake3`, or `poseidon2`. | +| **Noir** | Circuit language used by ProveKit's primary authoring flow. | +| **PKP** | ProveKit prover key file (`.pkp`), produced by `prepare`, consumed by provers. | +| **PKV** | ProveKit verifier key file (`.pkv`), produced by `prepare`, consumed by verifiers. | +| **Proof** | Serialized proof output, `proof.np` from the CLI, or JSON proof values in WASM and server flows. | +| **Public inputs** | Values intentionally exposed by the circuit and bound into verification. Your application is responsible for interpreting them. | + +## R–Z + +| Term | Meaning | +| :--- | :--- | +| **R1CS** | Rank-1 Constraint System used by the ProveKit proving pipeline. | +| **Recursive verifier** | Go/gnark wrapper that verifies a ProveKit proof inside an outer Groth16-style workflow. | +| **`r1cs.json`** | Recursive-verifier R1CS export generated from a matching verifier key and proof. | +| **`params_for_recursive_verifier`** | Recursive-verifier parameter file generated from a matching verifier key and proof. | +| **Skyscraper** | Custom BN254-tuned hash engine used as ProveKit's default Merkle commitment and Fiat-Shamir transcript hash. | +| **Verifier server** | HTTP service in `tooling/verifier-server` that downloads artifacts and orchestrates proof verification. | +| **Witness** | Private and public assignment values used to satisfy the circuit during proving. | +| **WHIR** | Proof system family used by ProveKit for proof generation and verification. | + +## Related pages + +- [Proving flow](/concepts/proving-flow/) +- [Artifact lifecycle](/concepts/artifact-lifecycle/) +- [CLI overview](/cli/overview/) +- [Common errors](/troubleshooting/common-errors/) diff --git a/docs/src/content/docs/reference/performance.mdx b/docs/src/content/docs/reference/performance.mdx new file mode 100644 index 000000000..5f8008163 --- /dev/null +++ b/docs/src/content/docs/reference/performance.mdx @@ -0,0 +1,106 @@ +--- +title: Performance +description: How to measure ProveKit on your circuit, the benchmark suite shipped with the repo, and what shapes performance most. +--- + +import { Aside } from '@astrojs/starlight/components'; + +ProveKit is fast enough to ship in production for many workloads, but "fast" depends almost entirely on circuit shape. This page tells you how to measure your circuit honestly, what dimensions matter, and where the benchmark suite lives. + + + +## What drives performance + +| Dimension | Effect | +| :--- | :--- | +| **Constraint count** | Roughly linear in R1CS row count for the dominant proving phases (witness solve, commitment, sumcheck). | +| **Hash choice** | `skyscraper` is the fastest option for BN254 Merkle commitments. SHA-256, Keccak, Blake3, and Poseidon2 are slower in different ways, Keccak and SHA-256 have larger constraint footprints inside Noir circuits, while Skyscraper, Blake3, and Poseidon2 are cheaper in-circuit. | +| **Witness layer count** | Witness builders execute in layers (see [Proving flow](/concepts/proving-flow/)). Deep layer graphs add coordination overhead. | +| **CPU architecture** | `aarch64` benefits from SIMD-accelerated BN254 arithmetic in `skyscraper/core`. x86_64 falls back to portable arithmetic. | +| **Parallelism** | Proving uses [Rayon](https://github.com/rayon-rs/rayon). More cores help up to the parallelism inherent in the circuit. WASM threading depends on `SharedArrayBuffer`. | +| **Host memory** | Mobile FFI hosts can swap to disk via `pk_configure_memory(...)`. File-backed mmap allocation is slower than RAM but unlocks larger circuits. | + +## Measuring your circuit + +The CLI prints span timings and memory statistics through its tracing layer. The simplest measurement: + +```sh +cargo run --release --bin provekit-cli -- prove --prover circuit.pkp +``` + +Inspect the structured timing output it prints. For finer-grained profiling, build with the Tracy feature: + +```sh +cargo run --release --features tracy --bin provekit-cli -- --tracy prove +``` + +For programmatic benchmarking, across hash configurations, host variants, and circuit sizes, use the `provekit-bench` crate in `tooling/provekit-bench/`. It hooks into `criterion` and reports proving time, verification time, peak memory, and proof size. + +## Inspecting the circuit before proving + +Two CLI commands tell you what you're about to prove: + +```sh +# R1CS structure and ACIR statistics. +cargo run --release --bin provekit-cli -- circuit-stats target/.json + +# Size breakdown of the prover key, matrix sparsity, witness builders, hash config. +cargo run --release --bin provekit-cli -- analyze-pkp .pkp +``` + +Use `circuit-stats` to confirm constraint counts match your expectations before committing to a host. A circuit that fits comfortably on a server may exceed practical proving time on mobile. + +## The ProveKit benchmark suite + +`noir-examples/csp-benchmarks/` contains the [Ethproofs CSP benchmarks](https://ethproofs.org/csp-benchmarks), a standardized suite of client-side proving targets used to compare proof systems on common workloads. + +| Target | Circuit sizes | Implementation note | +| :--- | :--- | :--- | +| **SHA-256** | 128, 256, 512, 1024, 2048 bytes | Uses `noir-lang/sha256::sha256_var`, lowering compression through Noir's SHA-256 blackbox. | +| **Keccak-256** | 128, 256, 512, 1024, 2048 bytes | Native Noir Keccak circuit with a witness-focused u32 lane representation. | +| **Poseidon** | 2, 4, 8, 12, 16 field elements | `noir-lang/poseidon` BN254 native Noir helpers. | +| **Poseidon2** | 2, 4, 8, 12, 16 field elements | `TaceoLabs/noir-poseidon` for states 2, 8, 12, 16; state 4 intentionally exercises Noir's Poseidon2 blackbox. | +| **ECDSA** | secp256r1 over a 32-byte digest | `zkpassport/noir-ecdsa` native P-256 verification (P-256 blackbox is not yet lowered by ProveKit). | + +To run any benchmark target: + +```sh +cd noir-examples/csp-benchmarks/sha256_512 +cargo run --release --bin provekit-cli -- prepare +cargo run --release --bin provekit-cli -- prove +cargo run --release --bin provekit-cli -- verify +``` + +Combine that with the CLI's timing output (or the `provekit-bench` harness) to capture proving time, verification time, and memory for each target on your machine. + +## What to expect across hosts + +The fundamentals don't change between hosts, but resource constraints do: + +- **Native Rust on a workstation.** The reference platform. Smallest measured proving time, largest available memory. +- **WASM in a browser.** Slower than native, the proof system runs single-threaded unless `SharedArrayBuffer` is available, and JavaScript marshalling adds overhead at the boundaries. +- **WASM in Node.js.** Closer to native than browser WASM, but still single-process unless you orchestrate workers externally. +- **iOS / Android via FFI.** Bounded by device RAM unless you configure `pk_configure_memory` for file-backed mmap. Modern phones can prove non-trivial credential circuits on-device; budget memory carefully. +- **Verifier server.** Verification dominates. Concurrency is configurable through `VERIFIER_SEMAPHORE_LIMIT`; the default of one keeps memory usage predictable. + +## Recursive verification cost + +The Groth16 wrapper through the Go/gnark recursive verifier adds a fixed per-proof cost, typically a one-time setup cost (proving key generation) and a recurring proving cost for the outer proof. The base proof's verification is the inner workload; everything else is the wrapper. Plan for the Groth16 step to dominate end-to-end latency when on-chain settlement is the goal. + +## Optimization checklist + +If proving is slower than you need: + +1. **Run `circuit-stats`.** Confirm constraint count matches expectations. Unexpected blowups usually indicate accidentally-quadratic constraint generation. +2. **Switch to `skyscraper` if you haven't.** It's the default but worth confirming. Other hashes are slower in-circuit. +3. **Audit black-box vs native lowerings.** Some Noir black boxes (SHA-256, Keccak) are heavier in ProveKit than their native R1CS implementations. The CSP benchmarks call this out explicitly. +4. **Profile with Tracy.** Run `cargo run --release --features tracy --bin provekit-cli -- --tracy prove` and inspect span timings. Look for layers that dominate the witness solve. +5. **Split the circuit if possible.** Two smaller proofs may verify faster than one giant proof, depending on transport overhead and what the verifier needs to check. + +## Related pages + +- [CLI reference](/cli/overview/), flags for `circuit-stats`, `analyze-pkp`, and Tracy profiling. +- [Examples catalog](/reference/examples/), circuits you can benchmark against. +- [Proving flow](/concepts/proving-flow/), the conceptual pipeline being measured. diff --git a/docs/src/content/docs/reference/production-checklist.mdx b/docs/src/content/docs/reference/production-checklist.mdx new file mode 100644 index 000000000..eaef96452 --- /dev/null +++ b/docs/src/content/docs/reference/production-checklist.mdx @@ -0,0 +1,139 @@ +--- +title: Production checklist +description: Pre-launch checklist for ProveKit artifact generation, integration, verification, and operations. +--- + +Use this checklist before shipping a workflow backed by ProveKit. It is intentionally conservative, ProveKit is still under active development and `main` may change proof, key, recursive-verifier, or API formats between commits. + +## 1. Pin the implementation + +- Choose the branch or release. Use `v1` for the current stable interface; use `main` only for early-adopter work. +- Record the Git commit, `Cargo.lock`, and `rust-toolchain.toml` used to generate artifacts. +- Record exact CLI commands, feature flags, compiler backend, and the `prepare --hash` value. +- Rebuild from a clean checkout in CI before trusting a new artifact set. + +## 2. Control artifact provenance + +For every generated artifact, store the path, checksum, source commit, generating command, and owner. + +| Artifact | Required provenance | +| :--- | :--- | +| `.pkp` | Circuit source, compiler backend, hash, commit, generating command. | +| `.pkv` | Same generation record as the matching `.pkp`. | +| `proof.np` or JSON proof | Matching `.pkp`, input file, public inputs, commit. | +| `params_for_recursive_verifier` | Matching `.pkv` and proof. | +| `r1cs.json` | Matching `.pkv` and recursive-verifier export command. | +| Groth16 `pk` / `vk` | Setup ceremony or development-only generation record. | + +Do not mix artifacts generated from different branches, commits, hash choices, circuits, or verifier/proof pairs. + +## 3. Lock the end-to-end workflow + +Add a CI job that runs the exact deployment path: + +```sh +mkdir -p artifacts +cargo run --release --bin provekit-cli -- prepare \ + . \ + --pkp artifacts/app.pkp \ + --pkv artifacts/app.pkv +cargo run --release --bin provekit-cli -- prove \ + --prover artifacts/app.pkp \ + --input Prover.toml \ + --out artifacts/proof.np +cargo run --release --bin provekit-cli -- verify \ + --verifier artifacts/app.pkv \ + --proof artifacts/proof.np +cargo run --release --bin provekit-cli -- show-inputs --hex \ + artifacts/app.pkv \ + artifacts/proof.np +``` + +If recursive verification is part of the product, add the export step and verify the Go/gnark path with the exact generated files: + +```sh +cargo run --release --bin provekit-cli -- generate-gnark-inputs \ + artifacts/app.pkv \ + artifacts/proof.np \ + --params artifacts/params_for_recursive_verifier \ + --r1cs artifacts/r1cs.json +``` + +## 4. Define trust boundaries + +- Decide who is allowed to generate `.pkp` and `.pkv` files. +- Decide where proofs are generated and where they are verified. +- Treat public input encoding as an API contract; test it with `show-inputs`. +- Keep private witnesses, prover keys, and generated proofs out of logs unless explicitly approved. +- Document whether verification depends on the local CLI, embedded Rust, WASM, FFI, the verifier server, or the recursive verifier. + +## 5. Harden integration hosts + +### Rust services + +- Reload or clone verifier state when verifying multiple proofs in one process. +- Expose hash, compiler, and backend choices in configuration. +- Add regression tests that confirm mismatched key/proof pairs are rejected. + +### WASM / JavaScript + +- Call `initPanicHook()` and `initThreadPool()` before proving when using threaded builds. +- Create a new `Prover` for each proof, `proveBytes()` / `proveJs()` consume the prover. +- Validate witness maps before calling `proveBytes()` or `proveJs()`. +- Load `.pkp` and `.pkv` artifacts from authenticated, integrity-checked sources. + +### FFI / mobile + +- Call `pk_init()` once before proving. +- Configure the custom allocator or mmap memory *before* initialization. +- Free every returned `PKBuf` with `pk_free_buf()`. +- Test low-memory and cancellation behavior on target devices. + +### Verifier server + +- Restrict artifact URL sources or proxy them through trusted storage. +- Tune `VERIFIER_MAX_REQUEST_SIZE`, `VERIFIER_REQUEST_TIMEOUT`, `VERIFIER_TIMEOUT_SECONDS`, and `VERIFIER_SEMAPHORE_LIMIT` for real proof sizes. +- Monitor `/health`, request IDs, verification latency, timeout rate, and invalid-proof rate. +- Decide how long downloaded artifacts remain in `VERIFIER_ARTIFACTS_DIR`. + +### Recursive verifier + +- Manage Groth16 proving and verifying keys explicitly for production. +- Treat development-time key generation as unsafe unless release-specific setup guidance says otherwise. +- Re-run the recursive export after changing the proof, verifier key, branch, circuit, or hash configuration. + +## 6. Capture operational evidence + +Before launch, capture evidence for each check: + +| Check | Evidence to retain | +| :--- | :--- | +| Build reproducibility | Clean-checkout build logs and artifact checksums. | +| Local verification | `verify` success output and the command line used. | +| Public inputs | `show-inputs --hex` output reviewed by the application owner. | +| Negative tests | Proof/key mismatch or corrupted proof is rejected. | +| Performance | Proving and verification time and memory for expected circuit sizes. | +| Recovery | Procedure for regenerating and rolling back artifacts. | +| Observability | Logs and metrics that identify request ID, artifact version, and failure class. | + +## 7. Red flags + +Pause deployment if any of these are true: + +- Artifact provenance is unknown or spans multiple branches or commits. +- `verify` fails locally for a proof the service plans to accept. +- Recursive-verifier params or `r1cs.json` were not regenerated with the current `.pkv` and proof. +- Public input ordering is undocumented. +- Verifier-server artifact URLs can be controlled by untrusted clients without filtering. +- FFI buffers are not freed, or allocator setup happens after `pk_init()`. +- Browser proving reuses a consumed WASM `Prover` instance. +- The deployment depends on `main` behavior without a migration or rollback plan. + +## Related references + +- [CLI overview](/cli/overview/) +- [Integrations overview](/integrations/overview/) +- [Artifact lifecycle](/concepts/artifact-lifecycle/) +- [Security and trust model](/concepts/security-model/) +- [Common errors](/troubleshooting/common-errors/) +- [Project status and versioning](/reference/project-status/) diff --git a/docs/src/content/docs/reference/project-status.mdx b/docs/src/content/docs/reference/project-status.mdx new file mode 100644 index 000000000..ec5d401a7 --- /dev/null +++ b/docs/src/content/docs/reference/project-status.mdx @@ -0,0 +1,68 @@ +--- +title: Project status and versioning +description: Branch policy, artifact compatibility, and integration maturity for ProveKit. +--- + +import { Aside } from '@astrojs/starlight/components'; + +ProveKit is under active development. Code, proof and key formats, recursive-verifier inputs, and integration APIs are branch-scoped unless a release note explicitly says otherwise. + + + +## Branch policy + +| Branch | Audience | Documentation expectation | +| :--- | :--- | :--- | +| `v1` | Users who need a stable interface today. | The stable docs target this branch first. | +| `main` | Contributors and early adopters. | May include breaking changes to proof, key, recursive-verifier, or API formats. | + +Use `v1` when reproducibility matters more than testing the newest implementation. Use `main` only when you are prepared to regenerate artifacts and adapt to source-level changes. + +## Artifact compatibility + +Do not assume compatibility across branches or commits unless a release note states the formats are unchanged. + +Regenerate every affected artifact after changing any of: + +- Git branch, commit, or dependency lockfile. +- Noir circuit source, package selection, or workspace layout. +- Compiler version or lockfile pins for Noir dependencies. +- `prepare --hash` value. +- Prover inputs (when a new proof is expected). +- Recursive-verifier export settings or the proof/verifier pair. + +The safest deployment record includes the Git commit, `rust-toolchain.toml`, `Cargo.lock`, every CLI command line, artifact checksums, and the public input encoding expected by downstream systems. + +## Integration status + +| Path | Status | Compatibility notes | +| :--- | :--- | :--- | +| CLI `prepare` / `prove` / `verify` | Primary local workflow. | Defaults are package-derived; use explicit paths in CI and production. | +| Rust crates | Internal integration path. | API names and proof/key types may move while `main` evolves. | +| WASM bindings | Active browser/JavaScript path. | Provers are consumed after one proof; `getCircuit()` is available for Noir provers. | +| FFI bindings | Active mobile/native host path. | Hosts must manage initialization, allocator configuration, and buffer ownership. | +| Verifier server | Active HTTP verification path. | Requires reachable HTTP/HTTPS artifact URLs and tuned request/time/concurrency limits. | +| Recursive verifier | Active Go/gnark wrapper. | Recursive params and R1CS JSON must be regenerated with the matching verifier/proof pair. | + +## Documentation policy + +- Stable docs target `v1` unless a page is marked development-only. +- Examples that require `main`-only behavior are flagged explicitly. +- Command examples must run from a fresh checkout. +- Docs aimed at CI, services, or production use explicit artifact paths. +- Generated Rust API docs are linked separately from task-based user docs when hosted API docs are available. +- Artifact custody and trust-boundary guidance stays aligned with the [Security and trust model](/concepts/security-model/). + +## Known launch gaps + +Resolve or explicitly accept each of these before recommending ProveKit for external production users: + +- Hosted API docs for the Rust crates and the generated C header. +- Pre-built binary artifacts for `provekit-cli` attached to GitHub Releases (currently `cargo install` only). +- Executable app templates or CI-backed fixtures for each supported host language and platform. +- Release-specific security review notes, audit status, and trusted-setup key handling guidance. +- A support policy for branch-specific docs and migration notes. + +Track deployment-specific readiness in the [Production checklist](/reference/production-checklist/). diff --git a/docs/src/content/docs/reference/starter-template.mdx b/docs/src/content/docs/reference/starter-template.mdx new file mode 100644 index 000000000..84bc38d97 --- /dev/null +++ b/docs/src/content/docs/reference/starter-template.mdx @@ -0,0 +1,165 @@ +--- +title: Starter templates +description: Cloneable starting points and deployment recipes for shipping a ProveKit-backed application. +--- + +import { Aside } from '@astrojs/starlight/components'; + +A ZK application typically has three moving parts: a Noir circuit, a prover that runs near the user (server, browser, or mobile), and a verifier that runs wherever the trust boundary sits (your backend, a chain, or both). This page collects starting points and deployment patterns for each. + + + +## Starting points by shape + +### A Rust service that verifies proofs + +Use this when verification happens in your backend (HTTP API, gRPC service, job worker). + +**Skeleton:** + +```toml title="Cargo.toml" +[package] +name = "my-verifier" +version = "0.1.0" +edition = "2021" + +[dependencies] +provekit-common = "1.0.0" +provekit-verifier = "1.0.0" +axum = "0.7" # or actix, tonic, etc. +serde = { version = "1", features = ["derive"] } +tokio = { version = "1", features = ["full"] } +anyhow = "1" +``` + +**Implementation guide:** [Rust end-to-end](/e2e/rust/) shows the verifier setup. Wrap `verify()` behind your transport layer; refer to [Common errors](/troubleshooting/common-errors/) for failure modes to translate into HTTP statuses. + +### A browser app that proves locally + +Use this when the user's device holds the secret and proves on-device, the canonical privacy-preserving pattern. + +**Skeleton:** + +```ts title="package.json (dependencies)" +{ + "dependencies": { + "@atheon/verity": "^0.3.2", + "@noir-lang/noir_js": "^0.x", + "@noir-lang/acvm_js": "^0.x" + } +} +``` + +**Implementation guide:** [JS / TypeScript end-to-end](/e2e/js-typescript/). Notes: + +- For Next.js, place WASM artifacts under `public/` and configure headers for `SharedArrayBuffer` (`Cross-Origin-Opener-Policy: same-origin`, `Cross-Origin-Embedder-Policy: require-corp`). +- For Vite, copy WASM artifacts via `assetsInclude` or a plugin and serve with the same headers. + +### A mobile app that proves on-device + +Use this when the user is on iOS or Android and the secret never leaves their device. + +| Platform | Starting point | +| :--- | :--- | +| iOS | [Swift end-to-end](/e2e/swift/), SPM package, three build modes. macOS is not supported. | +| Android | [Kotlin end-to-end](/e2e/kotlin/), AAR + JNI, ABI packaging guidance. | + +Plan ahead for memory configuration (`pk_configure_memory` / `Verity.configureMemory`) before backend initialization, mobile circuits routinely require file-backed mmap. + +### A verifier service behind HTTP + +Use the bundled HTTP service when you want artifact-driven verification without writing transport glue. + +```sh +# From the repo root. +cd tooling/verifier-server +cargo run --release +``` + +Configure with the `VERIFIER_*` environment variables documented in `tooling/verifier-server/README.md`. The service downloads `.pkv` and `r1cs.json` from URLs in each request, restrict those URL sources for production. + +### An on-chain Groth16 verifier + +Use when the verification result needs to settle on-chain. + +```sh +# 1. Produce the recursive-verifier inputs. +cargo run --release --bin provekit-cli -- generate-gnark-inputs \ + circuit.pkv proof.np \ + --params recursive/params --r1cs recursive/r1cs.json + +# 2. Run the Go/gnark wrapper. +cd recursive-verifier +go run ./cmd/cli ... +``` + +Manage Groth16 proving and verifying keys explicitly. Development-time key generation should not be reused in production. The Go module lives in `recursive-verifier/`, its CLI is the entry point for one-shot wrapping; its server mode is the entry point for batched workflows. + +## Deployment recipes + +### Docker for the verifier server + +```dockerfile title="Dockerfile (sketch)" +FROM rust:1.85 AS build +WORKDIR /src +COPY . . +RUN cargo build --release -p verifier-server + +FROM debian:bookworm-slim +COPY --from=build /src/target/release/verifier-server /usr/local/bin/ +EXPOSE 3000 +ENV VERIFIER_SEMAPHORE_LIMIT=2 \ + VERIFIER_REQUEST_TIMEOUT=60 \ + VERIFIER_TIMEOUT_SECONDS=120 +ENTRYPOINT ["/usr/local/bin/verifier-server"] +``` + +Adjust the `VERIFIER_*` envs for your circuit profile. The defaults (one concurrent verification, 10 MiB request body) are conservative. + +### CI pipeline for artifact generation + +A minimal release-producing job (GitHub Actions, GitLab CI, or equivalent): + +```yaml +- name: Prepare keys + run: cargo run --release --bin provekit-cli -- prepare . --pkp out/app.pkp --pkv out/app.pkv + +- name: Generate test proof + run: cargo run --release --bin provekit-cli -- prove --prover out/app.pkp --input fixtures/Prover.toml --out out/proof.np + +- name: Verify locally + run: cargo run --release --bin provekit-cli -- verify --verifier out/app.pkv --proof out/proof.np + +- name: Record public inputs + run: cargo run --release --bin provekit-cli -- show-inputs --hex out/app.pkv out/proof.np > out/public_inputs.txt + +- name: Publish artifacts with provenance + run: sha256sum out/* > out/CHECKSUMS && upload out/ +``` + +See [Generate artifacts](/e2e/generate-artifacts/) for the full CI evidence template. + +### Distributing the verifier key + +`.pkv` is typically shipped *with* the application that verifies. Options: + +- **Embedded in the binary.** Smallest deployment footprint; requires a release per circuit version. +- **Loaded from CDN at startup.** Decouples circuit upgrades from app releases; requires integrity checks (subresource integrity or signed manifests). +- **Pinned per request.** Verifier server pattern: the client supplies the `.pkv` URL alongside the proof. Restrict URL sources or proxy through trusted storage. + +## Anti-patterns + +Avoid these shortcuts, they cause production incidents: + +- **Reusing `.pkp` across circuit versions.** Keys are bound to the circuit; mixing breaks verification silently. +- **Logging private witnesses or `Prover.toml` contents.** They are secrets by default. +- **Verifying without checking public inputs.** Verification proves the proof; *your code* proves the proof authorizes the action. +- **Shipping `main`-branch artifacts without a regeneration plan.** Format changes are possible between commits. + +## Related pages + +- [Production checklist](/reference/production-checklist/), pre-launch checks for every host. +- [Integrations overview](/integrations/overview/), the menu of where ProveKit can run. +- [Security and trust model](/concepts/security-model/), what verification proves and what it doesn't. diff --git a/docs/src/content/docs/troubleshooting/common-errors.mdx b/docs/src/content/docs/troubleshooting/common-errors.mdx new file mode 100644 index 000000000..f3d07c29a --- /dev/null +++ b/docs/src/content/docs/troubleshooting/common-errors.mdx @@ -0,0 +1,213 @@ +--- +title: Common errors +description: Diagnose setup, proving, verification, integration, and deployment failures. +--- + +Use this page to diagnose setup, artifact, CLI, WASM, FFI, verifier-server, and recursive-verifier failures. The first question to ask every time: *which artifact was produced by which command, branch, compiler backend, and hash configuration?* + +## Rust toolchain mismatch + +**Symptom.** Cargo fails before building ProveKit crates, or reports an unexpected nightly/stable compiler. + +**Checks.** + +```sh +rustup show +cargo --version +cat rust-toolchain.toml +``` + +**Fix.** Run commands from a checkout that contains `rust-toolchain.toml` so Cargo selects the pinned toolchain. If the toolchain is missing, install or update it with `rustup` and retry from the repository root. + +## Cargo cannot find `provekit-cli` + +**Symptom.** `cargo run` reports that the binary target cannot be found, or CLI arguments are parsed by Cargo instead of ProveKit. + +**Checks.** + +```sh +cargo metadata --no-deps --format-version 1 | rg 'provekit-cli|tooling/cli' +cargo run --release --bin provekit-cli -- --help +``` + +**Fix.** Run from the workspace root and pass CLI arguments after `--`: + +```sh +cargo run --release --bin provekit-cli -- prepare +``` + +## No enclosing Noir package + +**Symptom.** `prepare`, `prove`, or `verify` cannot infer default key names, or a Noir command cannot find a package manifest. + +**Checks.** + +```sh +pwd +find .. -name Nargo.toml -maxdepth 4 +``` + +**Fix.** Run from the Noir package directory, pass `prepare `, or use explicit artifact paths (`--pkp`, `--pkv`, `--prover`, `--verifier`). + +## Multiple binary packages with explicit key outputs + +**Symptom.** `prepare --workspace --pkp ... --pkv ...` fails because multiple binary packages would write to a single explicit key pair. + +**Fix.** Either compile one package with `--package `, or omit `--pkp`/`--pkv` so each binary package uses its package-derived output names. + +## Unsupported hash choice + +**Symptom.** `prepare --hash ` rejects the hash argument. + +**Fix.** Use one of the supported names: + +- `skyscraper` +- `sha256` +- `keccak` +- `blake3` +- `poseidon2` + +Regenerate the prover key, verifier key, and every proof after changing the hash. + +## Missing or stale artifacts + +**Symptom.** `prove` or `verify` cannot find expected `.pkp`, `.pkv`, or `proof.np` files. + +**Checks.** + +```sh +ls -lh *.pkp *.pkv proof.np 2>/dev/null || true +cargo run --release --bin provekit-cli -- prepare --help +``` + +**Fix.** Re-run the workflow from `prepare` in the same Noir package directory, or pass explicit paths for every artifact: + +```sh +mkdir -p artifacts +cargo run --release --bin provekit-cli -- prepare \ + . \ + --pkp artifacts/app.pkp \ + --pkv artifacts/app.pkv +cargo run --release --bin provekit-cli -- prove \ + --prover artifacts/app.pkp \ + --input Prover.toml \ + --out artifacts/proof.np +cargo run --release --bin provekit-cli -- verify \ + --verifier artifacts/app.pkv \ + --proof artifacts/proof.np +``` + +## Verification failure + +**Symptom.** `verify` rejects a generated or supplied proof. + +**Likely causes.** + +- The proof was generated with a different `.pkp` than the `.pkv` used for verification. +- The circuit source or Noir package changed after `prepare`. +- The proof was generated from inputs that don't satisfy the circuit. +- The branch changed between artifact generation and verification. +- The hash configuration changed. +- Public inputs were serialized or transported incorrectly. + +**Fix.** Regenerate `.pkp`, `.pkv`, and `proof.np` from the same checkout and hash choice. Use `show-inputs` to inspect public inputs: + +```sh +cargo run --release --bin provekit-cli -- show-inputs --hex artifacts/app.pkv artifacts/proof.np +``` + +## `show-inputs` reports an ABI/public-input mismatch + +**Symptom.** `show-inputs` says the ABI expects more public inputs than the proof contains. + +**Fix.** The proof and verifier key are not from the same compiled circuit, or the proof JSON was modified or truncated. Regenerate from `prepare` and avoid manually editing proof JSON. + +## `circuit-stats` cannot read the circuit JSON + +**Symptom.** `circuit-stats` reports a missing `bytecode` field or a base64 decode error. + +**Fix.** Pass the Noir ACIR artifact JSON produced under the Noir target directory, not a `.pkp`, `.pkv`, proof, or recursive-verifier `r1cs.json` file. + +## WASM prover has already been consumed + +**Symptom.** Browser code receives `Prover has been consumed by a previous prove() call`. + +**Fix.** Create a new `Prover` for each proof. The WASM `Verifier` is reusable, but `Prover.proveBytes()` and `Prover.proveJs()` consume the prover state. + +## WASM witness map parsing fails + +**Symptom.** Browser code reports an empty witness map, unsupported key type, non-string value, invalid hex, or a field element larger than 32 bytes. + +**Fix.** Pass a JavaScript `Map` or plain object that maps witness indices to hex strings: + +```js +const witnessMap = new Map([ + [0, "0x01"], + [1, "0x02"], +]); +``` + +Values are reduced as BN254 field elements and must fit within 32 bytes. + +## FFI returns an error code + +**Symptom.** A C, Swift, Kotlin, Python, or other FFI host receives a non-zero `PKError`. + +**Checks.** + +- `PK_INVALID_INPUT`, ensure pointers and paths are not null. +- `PK_SCHEME_READ_ERROR`, confirm the `.pkp` path exists and is readable. +- `PK_WITNESS_READ_ERROR`, confirm the input TOML path exists and matches the circuit ABI. +- `PK_PROOF_ERROR`, regenerate artifacts and try the same inputs with the CLI. +- `PK_SERIALIZATION_ERROR` or `PK_FILE_WRITE_ERROR`, check output paths and permissions. + +**Fix.** Call `pk_init()` before proving, free returned buffers with `pk_free_buf()`, and configure custom allocators or mmap memory before initialization. + +## Verifier server rejects a request + +**Symptom.** `/verify` returns validation errors, `isValid: false`, a timeout status, or an HTTP error. + +**Checks.** + +```sh +curl http://localhost:3000/health +``` + +Confirm the request body has: + +- `pkvUrl`, a non-empty HTTP/HTTPS URL to a `.pkv` artifact. +- `r1csUrl`, a non-empty HTTP/HTTPS URL to recursive-verifier R1CS JSON. +- `np`, a non-null JSON `NoirProof` object. +- Optional `verificationParams.maxVerificationTime`, greater than `0` and at most `300` seconds. + +**Fix.** Make artifacts reachable from the server, raise `VERIFIER_MAX_REQUEST_SIZE` for larger requests, tune `VERIFIER_REQUEST_TIMEOUT` and `VERIFIER_TIMEOUT_SECONDS` for long verification runs, and keep `VERIFIER_SEMAPHORE_LIMIT` aligned with available CPU and memory. + +## Recursive-verifier input mismatch + +**Symptom.** The Go recursive verifier fails with config, R1CS, or key errors. + +**Fix.** Re-run `generate-gnark-inputs` from the same `.pkv` and proof you plan to verify: + +```sh +cargo run --release --bin provekit-cli -- generate-gnark-inputs \ + artifacts/app.pkv \ + artifacts/proof.np \ + --params artifacts/params_for_recursive_verifier \ + --r1cs artifacts/r1cs.json +``` + +Pass those exact files to the Go CLI or server. Do not reuse recursive params after changing the proof, verifier key, branch, circuit, or hash configuration. + +## Still stuck? + +Collect this information before opening an issue or escalating internally: + +- Git branch and commit. +- Rust toolchain from `rustup show`. +- Full command line and stderr. +- Whether artifacts were generated on `v1` or `main`. +- The `prepare --hash` value. +- File sizes and modification times for `.pkp`, `.pkv`, `proof.np`, `r1cs.json`, and recursive params. +- Whether the same proof verifies with the local CLI. + +Before deploying any fix, walk through the [Production checklist](/reference/production-checklist/). diff --git a/docs/src/styles/starlight.css b/docs/src/styles/starlight.css new file mode 100644 index 000000000..e62cfa49e --- /dev/null +++ b/docs/src/styles/starlight.css @@ -0,0 +1,1012 @@ +/* ============================================================ + PROVEKIT DESIGN SYSTEM — applied to Astro Starlight + Light-first. Borders, not shadows. Square corners. Outfit + Geist Mono. + Selectors verified against the rendered Starlight DOM. + ============================================================ */ + +@import url('https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&family=Geist+Mono:wght@400;500&display=swap'); + +/* ============================================================ + 1. Brand tokens + ============================================================ */ + +:root { + --pk-ink: #2D2D2B; + --pk-ink-alt: #2D2D30; + /* Mid-tone between ink (#2D2D2B) and mute (#949494). ~6.4:1 contrast on white, + passes WCAG AA for body text without reading as jet-black. Used for nav items. */ + --pk-ink-soft: #5C5C5A; + --pk-mute: #949494; + --pk-mute-soft: #B7B7B7; + + --pk-canvas: #F8FEFF; + --pk-surface: #FFFFFF; + --pk-surface-tint: rgba(190, 225, 255, 0.04); + + --pk-line: #D1F5FF; + --pk-line-soft: #EEF7FF; + --pk-line-mid: #BCEEFF; + + --pk-brand: #0D74FF; + --pk-brand-hover: #0A66E0; + --pk-brand-ink: #A2D0FC; + + --pk-font-sans: "Outfit", system-ui, -apple-system, "Segoe UI", sans-serif; + --pk-font-mono: "Geist Mono", ui-monospace, "SF Mono", monospace; +} + +/* ============================================================ + 2. Starlight token map — LIGHT (canonical brand mode) + ============================================================ */ + +:root, +:root[data-theme='light'] { + color-scheme: light; + + --sl-font: var(--pk-font-sans); + --sl-font-mono: var(--pk-font-mono); + + --sl-color-text: var(--pk-ink); + --sl-color-text-accent: var(--pk-brand); + --sl-color-text-invert: #FFFFFF; + + --sl-color-bg: var(--pk-canvas); + --sl-color-bg-nav: var(--pk-surface); + --sl-color-bg-sidebar: var(--pk-surface); + --sl-color-bg-inline-code:var(--pk-line-soft); + --sl-color-bg-accent: var(--pk-brand); + + --sl-color-accent-low: #EAF4FF; + --sl-color-accent: var(--pk-brand); + --sl-color-accent-high: var(--pk-brand-hover); + + --sl-color-hairline-light:var(--pk-line); + --sl-color-hairline: var(--pk-line); + --sl-color-hairline-shade:var(--pk-line-soft); + + --sl-color-white: var(--pk-ink); + --sl-color-black: var(--pk-surface); + + --sl-color-gray-1: var(--pk-ink-alt); + --sl-color-gray-2: var(--pk-mute); + --sl-color-gray-3: var(--pk-mute); + --sl-color-gray-4: var(--pk-mute-soft); + --sl-color-gray-5: var(--pk-line-mid); + --sl-color-gray-6: var(--pk-line); + + --sl-shadow-sm: none; + --sl-shadow-md: none; + --sl-shadow-lg: none; +} + +/* ============================================================ + 3. Starlight token map — DARK (derivative, kept for toggle users) + ============================================================ */ + +:root[data-theme='dark'] { + color-scheme: dark; + + --sl-color-text: #EAF4FF; + --sl-color-text-accent: var(--pk-brand-ink); + --sl-color-text-invert: var(--pk-ink); + + --sl-color-bg: #14171C; + --sl-color-bg-nav: #1A1E25; + --sl-color-bg-sidebar: #1A1E25; + --sl-color-bg-inline-code:#1E242F; + --sl-color-bg-accent: var(--pk-brand-ink); + + --sl-color-accent-low: #102542; + --sl-color-accent: var(--pk-brand-ink); + --sl-color-accent-high: #E3F2FF; + + --sl-color-hairline-light:#2D3648; + --sl-color-hairline: #2D3648; + --sl-color-hairline-shade:#1F2A3A; + + --sl-color-white: #EAF4FF; + --sl-color-black: #14171C; + + --sl-color-gray-1: #EAF4FF; + --sl-color-gray-2: #9AA8BC; + --sl-color-gray-3: #7B8CA3; + --sl-color-gray-4: #4A5A73; + --sl-color-gray-5: #2D3648; + --sl-color-gray-6: #1F2A3A; +} + +/* ============================================================ + 4. Body type + ============================================================ */ + +html { scroll-behavior: smooth; } + +body { + font-family: var(--pk-font-sans); + font-weight: 400; + letter-spacing: -0.005em; +} + +.sl-markdown-content :is(h1, h2, h3, h4, h5, h6):not(:where(.not-content *)) { + font-family: var(--pk-font-sans); + font-weight: 500; + letter-spacing: -0.02em; +} + +.sl-markdown-content h2:not(:where(.not-content *)) { font-size: 1.65rem; } +.sl-markdown-content h3:not(:where(.not-content *)) { font-size: 1.22rem; } + +.sl-markdown-content .lead { + color: var(--sl-color-text); + font-weight: 400; + font-size: clamp(1.1rem, 1rem + 0.5vw, 1.32rem); + line-height: 1.55; + margin-top: 0; +} + +:root[data-theme='dark'] .sl-markdown-content .lead { + color: #C5D6EE; +} + +/* ============================================================ + 5. Sidebar — group labels in Geist Mono ALL CAPS + Actual DOM: Title + ============================================================ */ + +.sidebar-content .group-label, +.sidebar-content .group-label .large { + font-family: var(--pk-font-mono); + text-transform: uppercase; + letter-spacing: 0.02em; + font-weight: 500; + font-size: 0.78rem; +} + +.sidebar-content .top-level > li > details > summary { + padding-block: 0.5rem; +} + +/* Sidebar links — mid-tone ink, readable but not pitch black. */ +.sidebar-content ul a { + font-family: var(--pk-font-sans); + font-size: 0.95rem; + color: var(--pk-ink-soft); +} + +:root[data-theme='dark'] .sidebar-content ul a { + color: #BFC9D8; +} + +.sidebar-content ul a:hover { + color: var(--pk-brand); +} + +:root[data-theme='dark'] .sidebar-content ul a:hover { + color: var(--pk-brand-ink); +} + +/* Current page indicator */ +.sidebar-content ul a[aria-current="page"] { + background: var(--pk-line-soft); + color: var(--pk-brand); + border-inline-start: 2px solid var(--pk-brand); +} + +:root[data-theme='dark'] .sidebar-content ul a[aria-current="page"] { + background: #102542; + color: var(--pk-brand-ink); + border-inline-start-color: var(--pk-brand-ink); +} + +/* ============================================================ + 6. Right sidebar — TOC heading in mono uppercase + ============================================================ */ + +.right-sidebar-panel h2 { + font-family: var(--pk-font-mono); + text-transform: uppercase; + letter-spacing: 0.02em; + font-weight: 500; + font-size: 0.74rem; + color: var(--pk-mute); +} + +/* ============================================================ + 7. Header + ============================================================ */ + +/* Scoped to the semantic
element to avoid double-bordering + the inner
wrapper Starlight nests. */ +header.header { + background: var(--sl-color-bg-nav); + border-bottom: 1px solid var(--sl-color-hairline); + box-shadow: none; +} + +/* Inner header wrapper carries no border; just layout. */ +header.header > .header { + background: transparent; + border: 0; +} + +header.header :is(a, button, select), +header.header .icon { + color: var(--sl-color-text); +} + +header.header [data-open-modal] { + border: 1px solid var(--sl-color-hairline); + border-radius: 0; + background: var(--sl-color-bg); +} + +header.header [data-open-modal] kbd { + background: var(--pk-line-soft); + color: var(--pk-brand); + border-radius: 0; +} + +:root[data-theme='dark'] .header [data-open-modal] kbd { + background: #1F2A3A; + color: var(--pk-brand-ink); +} + +.site-title img { max-width: min(12rem, 48vw); } + +/* ============================================================ + 8. Cards (both Card and LinkCard render as
) + ============================================================ */ + +.card { + border-radius: 0 !important; + border: 1px solid var(--sl-color-hairline) !important; + background: var(--sl-color-bg-nav) !important; + box-shadow: none !important; + transition: border-color 120ms cubic-bezier(0.2, 0.8, 0.2, 1), + background 120ms cubic-bezier(0.2, 0.8, 0.2, 1); +} + +.card:hover { + border-color: var(--pk-brand); +} + +:root[data-theme='dark'] .card:hover { + border-color: var(--pk-brand-ink); +} + +/* The CardGrid wrapper */ +.card-grid { gap: 0.75rem; } + +/* ============================================================ + 9. Asides + ============================================================ */ + +.starlight-aside { + border-radius: 0 !important; + box-shadow: none !important; + border-inline-start-width: 3px; +} + +/* ============================================================ + 10. Hero CTAs — square, mono uppercase + Actual class: + ============================================================ */ + +.sl-link-button { + border-radius: 0 !important; + font-family: var(--pk-font-mono); + text-transform: uppercase; + letter-spacing: 0.02em; + font-weight: 400; + font-size: 0.85rem; +} + +.sl-link-button.primary { + background: var(--pk-brand); + color: #FFFFFF; + border-color: var(--pk-brand); +} + +.sl-link-button.primary:hover { + background: var(--pk-brand-hover); + border-color: var(--pk-brand-hover); + color: #FFFFFF; +} + +.sl-link-button:not(.primary) { + border: 1px solid var(--sl-color-hairline); + color: var(--sl-color-text); + background: var(--sl-color-bg-nav); +} + +.sl-link-button:not(.primary):hover { + background: var(--pk-line-soft); + border-color: var(--pk-line-mid); +} + +:root[data-theme='dark'] .sl-link-button:not(.primary):hover { + background: #1F2A3A; + border-color: var(--pk-brand); +} + +/* Hero text */ +.hero h1 { + font-family: var(--pk-font-sans); + font-weight: 500; + letter-spacing: -0.025em; +} + +.hero .tagline { + font-family: var(--pk-font-sans); + color: var(--pk-mute); + font-weight: 400; +} + +:root[data-theme='dark'] .hero .tagline { + color: #9AA8BC; +} + +/* Subtle bloom behind hero */ +.hero { position: relative; } + +.hero::after { + content: ''; + position: absolute; + inset-block-start: -3rem; + inset-inline-end: -3rem; + width: min(40vw, 28rem); + height: 22rem; + background: radial-gradient(circle, color-mix(in srgb, var(--pk-brand), transparent 88%), transparent 60%); + pointer-events: none; + z-index: -1; +} + +:root[data-theme='dark'] .hero::after { + background: radial-gradient(circle, color-mix(in srgb, var(--pk-brand-ink), transparent 85%), transparent 60%); +} + +/* ============================================================ + 11. Links + inline code + ============================================================ */ + +.sl-markdown-content a:not(:where(.not-content *)) { + color: var(--sl-color-text-accent); + text-decoration-color: color-mix(in srgb, var(--sl-color-text-accent), transparent 60%); + text-underline-offset: 0.18em; +} + +.sl-markdown-content a:not(:where(.not-content *)):hover { + text-decoration-color: var(--sl-color-text-accent); +} + +.sl-markdown-content code:not(:where(pre code, .not-content *)) { + background: var(--sl-color-bg-inline-code); + border: 1px solid var(--sl-color-hairline); + border-radius: 0; + padding: 0.05rem 0.35rem; + font-family: var(--pk-font-mono); + font-size: 0.92em; +} + +/* ============================================================ + 12. Tables — header row in mono uppercase + ============================================================ */ + +.sl-markdown-content table:not(:where(.not-content *)) { + border-collapse: collapse; + font-size: 0.94rem; +} + +.sl-markdown-content table:not(:where(.not-content *)) th, +.sl-markdown-content table:not(:where(.not-content *)) td { + border-color: var(--sl-color-hairline); +} + +.sl-markdown-content table:not(:where(.not-content *)) th { + background: var(--pk-line-soft); + color: var(--pk-ink); + font-family: var(--pk-font-mono); + text-transform: uppercase; + letter-spacing: 0.02em; + font-weight: 500; + font-size: 0.78rem; +} + +/* Inline identifiers inside table cells should not break at hyphens. + Crate names like `provekit-r1cs-compiler` look broken when wrapped. */ +.sl-markdown-content table:not(:where(.not-content *)) code { + white-space: nowrap; +} + +/* Make sure the table can scroll horizontally if a row gets too wide for the column. */ +.sl-markdown-content table:not(:where(.not-content *)) { + display: block; + max-width: 100%; + overflow-x: auto; +} + +:root[data-theme='dark'] .sl-markdown-content table:not(:where(.not-content *)) th { + background: #1F2A3A; + color: #EAF4FF; +} + +/* ============================================================ + 13. Code blocks (Expressive Code) + Actual structure:
>
+ ============================================================ */ + +.expressive-code .frame { + border-radius: 0 !important; +} + +.expressive-code .frame pre { + border-radius: 0 !important; +} + +.expressive-code .copy button { + border-radius: 0 !important; +} + +/* ============================================================ + 14. pk-* components (legacy classes used in MDX content) + ============================================================ */ + +.pk-pill-row { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; + margin: 1rem 0 1.5rem; +} +.pk-pill-row > * { margin-top: 0 !important; } + +.pk-pill { + border: 1px solid var(--sl-color-hairline); + border-radius: 0; + color: var(--pk-mute); + font-family: var(--pk-font-mono); + text-transform: uppercase; + letter-spacing: 0.02em; + font-size: 0.72rem; + padding: 0.3rem 0.65rem; + background: var(--sl-color-bg-nav); +} + +.pk-metric-grid { + display: grid; + gap: 1rem; + grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); + margin: 1.5rem 0; +} +.pk-metric-grid > * { margin-top: 0 !important; } + +.pk-metric { + background: var(--sl-color-bg-nav); + border: 1px solid var(--sl-color-hairline); + border-radius: 0; + padding: 1.25rem; +} +.pk-metric > * { margin-top: 0 !important; } + +.pk-metric strong { + display: block; + color: var(--sl-color-text); + font-family: var(--pk-font-mono); + font-weight: 500; + font-size: 1.05rem; + letter-spacing: 0; + text-transform: none; + line-height: 1.15; +} + +.pk-metric span { + display: block; + color: var(--pk-mute); + font-size: 0.88rem; + margin-top: 0.4rem; + line-height: 1.4; +} + +/* ============================================================ + 15. pk-flow — multi-row pipeline diagram + ============================================================ */ + +.pk-flow { + background: var(--sl-color-bg-nav); + border: 1px solid var(--sl-color-hairline); + border-radius: 0; + box-shadow: none; + margin: 1.5rem 0 2rem; + overflow-x: auto; + padding: 1.25rem; +} + +.pk-flow > *, +.pk-flow-row > *, +.pk-flow-node > * { margin-top: 0 !important; } + +.pk-flow-row { + align-items: stretch; + column-gap: 0.75rem; + display: grid; + justify-content: center; + margin: 0.65rem auto; + row-gap: 0.75rem; + width: 100%; +} + +.pk-flow-row--two { grid-template-columns: minmax(10rem, 12rem) 2rem minmax(10rem, 13rem); } +.pk-flow-row--three { grid-template-columns: minmax(9rem, 10.5rem) 2rem minmax(9rem, 10.5rem) 2rem minmax(9rem, 10.5rem); } +.pk-flow-row--wide { grid-template-columns: minmax(10rem, 12rem) 2rem minmax(11rem, 13.5rem) 2rem minmax(10rem, 13rem); } + +.pk-flow-node { + align-items: center; + border: 1px solid var(--sl-color-hairline); + border-radius: 0; + background: var(--sl-color-bg-nav); + color: var(--sl-color-text); + display: flex; + flex-direction: column; + font-family: var(--pk-font-sans); + font-weight: 500; + justify-content: center; + line-height: 1.25; + min-height: 4.1rem; + min-width: 0; + padding: 0.75rem 0.9rem; + text-align: center; + width: 100%; +} + +.pk-flow-node--accent { + background: var(--pk-line-soft); + border-color: var(--pk-brand-ink); +} + +:root[data-theme='dark'] .pk-flow-node--accent { + background: #1F2A3A; + border-color: var(--pk-brand); +} + +.pk-flow-node--output { + border-color: var(--pk-brand); +} + +.pk-flow-arrow { + align-items: center; + color: var(--pk-brand); + display: flex; + font-size: 1.35rem; + font-weight: 600; + justify-content: center; + line-height: 1; + min-width: 2rem; +} + +.pk-flow-split { + border-top: 1px solid var(--sl-color-hairline); + margin-top: 1rem; + padding-top: 1rem; +} + +.pk-flow-caption { + color: var(--pk-mute); + display: block; + font-family: var(--pk-font-mono); + font-size: 0.65rem; + font-weight: 400; + text-transform: uppercase; + letter-spacing: 0.02em; + margin-top: 0.3rem; +} + +@media (max-width: 42rem) { + .pk-flow-row, + .pk-flow-row--two, + .pk-flow-row--three, + .pk-flow-row--wide { + align-items: stretch; + display: flex; + flex-direction: column; + } + + .pk-flow-node { width: 100%; } + + .pk-flow-arrow { + align-self: center; + margin: 0.35rem 0; + transform: rotate(90deg); + } +} + +/* ============================================================ + 16. pk-arch SVG — architecture overview + ============================================================ */ + +.pk-arch-svg { + border: 1px solid var(--sl-color-hairline); + border-radius: 0; + background: var(--sl-color-bg-nav); + box-shadow: none; + display: block; + height: auto; + margin: 1.5rem 0 1.75rem; + padding: 1rem; + width: 100%; +} + +.pk-arch-edges path { + fill: none; + stroke: var(--pk-brand); + stroke-width: 1.6; +} + +.pk-arch-edges marker path, +.pk-arch-svg marker path { + fill: var(--pk-brand); + stroke: none; +} + +.pk-arch-node { + fill: var(--sl-color-bg-nav); + stroke: var(--pk-line-mid); + stroke-width: 1.25; +} + +:root[data-theme='dark'] .pk-arch-node { + stroke: #2D3648; +} + +.pk-arch-node--source { + fill: var(--pk-line-soft); + stroke: var(--pk-brand); +} + +:root[data-theme='dark'] .pk-arch-node--source { + fill: #1F2A3A; +} + +.pk-arch-node--cmd { stroke: var(--pk-brand); } +.pk-arch-node--artifact { + stroke: var(--pk-brand); + stroke-dasharray: 4 3; +} +.pk-arch-node--optional { + stroke: var(--pk-brand-ink); + stroke-dasharray: 2 3; +} + +.pk-arch-label { + fill: var(--sl-color-text); + font-family: var(--pk-font-sans); + font-weight: 500; + font-size: 13.5px; + letter-spacing: -0.005em; + text-anchor: middle; +} + +.pk-arch-sub { + fill: var(--pk-mute); + font-family: var(--pk-font-mono); + font-weight: 400; + font-size: 10px; + letter-spacing: 0.02em; + text-transform: uppercase; + text-anchor: middle; +} + +/* ============================================================ + 17. Pagination — bordered prev/next blocks, mono "Next/Prev" + ============================================================ */ + +.pagination-links { + gap: 0.75rem; +} + +.pagination-links a { + border: 1px solid var(--sl-color-hairline) !important; + border-radius: 0 !important; + background: var(--sl-color-bg-nav) !important; + padding: 1rem 1.25rem !important; + transition: border-color 120ms cubic-bezier(0.2, 0.8, 0.2, 1), + background 120ms cubic-bezier(0.2, 0.8, 0.2, 1); +} + +.pagination-links a:hover { + border-color: var(--pk-brand) !important; + background: var(--pk-line-soft) !important; +} + +:root[data-theme='dark'] .pagination-links a:hover { + background: #1F2A3A !important; + border-color: var(--pk-brand-ink) !important; +} + +.pagination-links a > span > br + .link-title { + font-family: var(--pk-font-sans); + font-weight: 500; + letter-spacing: -0.005em; +} + +.pagination-links .link-title { + font-family: var(--pk-font-sans); + font-weight: 500; + letter-spacing: -0.005em; +} + +/* "Next" / "Previous" label */ +.pagination-links a > span { + font-family: var(--pk-font-mono); + text-transform: uppercase; + letter-spacing: 0.02em; + font-size: 0.72rem; + color: var(--pk-mute); +} + +.pagination-links a > span > .link-title { + text-transform: none; + letter-spacing: -0.005em; + font-size: 1rem; + color: var(--sl-color-text); + font-family: var(--pk-font-sans); +} + +/* ============================================================ + 18. Right-sidebar TOC items — active highlight + ============================================================ */ + +.right-sidebar-panel a { + font-family: var(--pk-font-sans); + font-size: 0.85rem; + color: var(--pk-ink-soft); +} + +:root[data-theme='dark'] .right-sidebar-panel a { + color: #BFC9D8; +} + +.right-sidebar-panel a:hover { + color: var(--pk-brand); +} + +:root[data-theme='dark'] .right-sidebar-panel a:hover { + color: var(--pk-brand-ink); +} + +.right-sidebar-panel a[aria-current="true"], +.right-sidebar-panel a.display-current { + color: var(--pk-brand) !important; + font-weight: 500; +} + +:root[data-theme='dark'] .right-sidebar-panel a[aria-current="true"], +:root[data-theme='dark'] .right-sidebar-panel a.display-current { + color: var(--pk-brand-ink) !important; +} + +/* ============================================================ + 19. Asides — brand-palette accent overrides + Default Starlight: note=blue, tip=green, caution=yellow, danger=red + Brand: note=brand, tip=cyan-ink, caution=orange, danger=pink + ============================================================ */ + +.starlight-aside--note { + --sl-color-asides-text-accent: var(--pk-brand); + --sl-color-asides-border: var(--pk-brand); + background: color-mix(in srgb, var(--pk-brand), white 92%); + border-color: var(--pk-brand); +} + +.starlight-aside--tip { + --sl-color-asides-text-accent: var(--pk-brand); + --sl-color-asides-border: var(--pk-brand-ink); + background: var(--pk-line-soft); + border-color: var(--pk-brand-ink); +} + +.starlight-aside--caution { + --sl-color-asides-text-accent: #B5651D; + --sl-color-asides-border: var(--pk-bloom-orange, #FDCC91); + background: color-mix(in srgb, var(--pk-bloom-orange, #FDCC91), white 70%); + border-color: var(--pk-bloom-orange, #FDCC91); +} + +.starlight-aside--danger { + --sl-color-asides-text-accent: #C53030; + --sl-color-asides-border: var(--pk-bloom-pink, #FF9AA0); + background: color-mix(in srgb, var(--pk-bloom-pink, #FF9AA0), white 78%); + border-color: var(--pk-bloom-pink, #FF9AA0); +} + +:root[data-theme='dark'] .starlight-aside--note { + background: color-mix(in srgb, var(--pk-brand), #15171B 80%); +} +:root[data-theme='dark'] .starlight-aside--tip { + background: #1F2A3A; +} +:root[data-theme='dark'] .starlight-aside--caution { + background: color-mix(in srgb, var(--pk-bloom-orange, #FDCC91), #15171B 80%); +} +:root[data-theme='dark'] .starlight-aside--danger { + background: color-mix(in srgb, var(--pk-bloom-pink, #FF9AA0), #15171B 82%); +} + +.starlight-aside__title { + font-family: var(--pk-font-mono); + text-transform: uppercase; + letter-spacing: 0.02em; + font-size: 0.78rem; + font-weight: 500; +} + +/* ============================================================ + 20. Code frame — explicit brand background + cyan border + ============================================================ */ + +.expressive-code { + margin-block: 1.25rem; +} + +.expressive-code .frame { + border: 1px solid var(--sl-color-hairline) !important; + background: var(--sl-color-bg-nav) !important; + box-shadow: none !important; +} + +.expressive-code .frame pre { + background: var(--sl-color-bg-nav) !important; +} + +.expressive-code .frame .header { + background: var(--pk-line-soft) !important; + border-bottom: 1px solid var(--sl-color-hairline) !important; +} + +:root[data-theme='dark'] .expressive-code .frame .header { + background: #1F2A3A !important; +} + +.expressive-code .frame .title { + font-family: var(--pk-font-mono) !important; + text-transform: uppercase !important; + letter-spacing: 0.02em !important; + font-size: 0.72rem !important; + color: var(--pk-mute) !important; +} + +.expressive-code .copy button { + border: 1px solid var(--sl-color-hairline) !important; + background: var(--sl-color-bg-nav) !important; +} + +/* ============================================================ + 21. Dialog / search modal — square + cyan border + ============================================================ */ + +.dialog-frame, +dialog.dialog-frame, +[role="dialog"] { + border-radius: 0 !important; + border: 1px solid var(--sl-color-hairline) !important; + box-shadow: none !important; + background: var(--sl-color-bg-nav) !important; +} + +/* Pagefind search results inside dialog */ +.dialog-frame input, +.dialog-frame [role="listbox"], +.dialog-frame [role="option"] { + border-radius: 0 !important; +} + +.dialog-frame [role="option"][aria-selected="true"] { + background: var(--pk-line-soft) !important; + color: var(--pk-brand) !important; +} + +/* ============================================================ + 22. Misc content — hr, kbd, blockquote, mark + ============================================================ */ + +.sl-markdown-content hr { + border: 0; + border-top: 1px solid var(--sl-color-hairline); + margin-block: 2rem; +} + +.sl-markdown-content kbd { + background: var(--pk-line-soft); + border: 1px solid var(--sl-color-hairline); + border-radius: 0; + padding: 0.05rem 0.4rem; + font-family: var(--pk-font-mono); + font-size: 0.85em; + color: var(--pk-brand); +} + +:root[data-theme='dark'] .sl-markdown-content kbd { + background: #1F2A3A; + color: var(--pk-brand-ink); +} + +.sl-markdown-content blockquote { + border-inline-start: 3px solid var(--pk-brand); + padding-inline-start: 1.25rem; + color: var(--sl-color-text); + background: var(--pk-line-soft); + padding-block: 0.5rem; + border-radius: 0; +} + +:root[data-theme='dark'] .sl-markdown-content blockquote { + background: #1F2A3A; +} + +.sl-markdown-content mark { + background: color-mix(in srgb, var(--pk-bloom-orange, #FDCC91), white 30%); + color: var(--pk-ink); + padding: 0 0.2em; + border-radius: 0; +} + +/* ============================================================ + 23. Scrollbars (Chromium / WebKit) + ============================================================ */ + +::-webkit-scrollbar { + width: 10px; + height: 10px; +} + +::-webkit-scrollbar-track { + background: var(--sl-color-bg); +} + +::-webkit-scrollbar-thumb { + background: var(--sl-color-hairline); + border-radius: 0; + border: 2px solid var(--sl-color-bg); +} + +::-webkit-scrollbar-thumb:hover { + background: var(--pk-brand-ink); +} + +:root[data-theme='dark'] ::-webkit-scrollbar-thumb:hover { + background: var(--pk-brand); +} + +/* Firefox */ +* { + scrollbar-width: thin; + scrollbar-color: var(--sl-color-hairline) var(--sl-color-bg); +} + +/* ============================================================ + 24. Sidebar caret — explicit brand-aware coloring + ============================================================ */ + +.sidebar-content .caret { + color: var(--pk-mute); + transition: transform 120ms cubic-bezier(0.2, 0.8, 0.2, 1); +} + +details[open] > summary .caret { + transform: rotate(90deg); +} + +/* ============================================================ + 25. Footer / meta line + ============================================================ */ + +footer .meta a, +footer .meta p { + font-family: var(--pk-font-mono); + text-transform: uppercase; + letter-spacing: 0.02em; + font-size: 0.72rem; + color: var(--pk-mute); +} + +footer .meta a:hover { + color: var(--pk-brand); +} diff --git a/docs/tsconfig.json b/docs/tsconfig.json new file mode 100644 index 000000000..adbbd073a --- /dev/null +++ b/docs/tsconfig.json @@ -0,0 +1,5 @@ +{ + "extends": "astro/tsconfigs/strict", + "include": [".astro/types.d.ts", "**/*"], + "exclude": ["dist", "node_modules"] +}