diff --git a/.github/pages-bootstrap/index.html b/.github/pages-bootstrap/index.html deleted file mode 100644 index f34cd8c..0000000 --- a/.github/pages-bootstrap/index.html +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - MAVULA Developer Docs - - - diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 3d3174a..d9a0339 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -1,5 +1,6 @@ name: Publish API Reference on: + push: { branches: [main] } workflow_dispatch: {} permissions: contents: read @@ -12,8 +13,17 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 + - uses: pnpm/action-setup@v6 + with: { version: 10.33.0 } + - uses: actions/setup-node@v6 + with: { node-version: 22.22.3, cache: pnpm } + - run: pnpm install --frozen-lockfile + - run: pnpm guardian:check + - run: pnpm contracts:check + - run: pnpm test + - run: pnpm build - uses: actions/upload-pages-artifact@v4 - with: { path: .github/pages-bootstrap } + with: { path: dist } deploy: if: github.ref == 'refs/heads/main' permissions: diff --git a/.github/workflows/required-ci.yml b/.github/workflows/required-ci.yml index d54efaa..d631473 100644 --- a/.github/workflows/required-ci.yml +++ b/.github/workflows/required-ci.yml @@ -8,6 +8,12 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 + - uses: pnpm/action-setup@v6 + with: { version: 10.33.0 } - uses: actions/setup-node@v6 - with: { node-version: 22.22.3 } - - run: node scripts/guardian.mjs + with: { node-version: 22.22.3, cache: pnpm } + - run: pnpm install --frozen-lockfile + - run: pnpm guardian:check + - run: pnpm contracts:check + - run: pnpm test + - run: pnpm build diff --git a/.gitignore b/.gitignore index 32bd014..0168d4d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,9 @@ node_modules/ dist/ +.astro/ +.playwright/ +playwright-report/ +test-results/ .redocly/ *.log .env diff --git a/README.md b/README.md index 6c2e27a..03d3ec3 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,37 @@ -# MAVULA Developer Documentation +# MAVULA Developer Docs -Versioned public API contracts and developer documentation for MAVULA. +Public integration guides and versioned API contracts for MAVULA financial infrastructure. The repository publishes approved Identity Access, Ledger Core and Workbench interfaces. Internal callbacks, health checks and observability endpoints are excluded from the public reference. +The Astro and Starlight portal covers identity, tenant isolation, account and +financial controls, payment jobs, configuration, projections and legacy batch +operations. Scalar renders the three public OpenAPI contracts locally. + +## Contracts + +- `identity-access.public.v1.yaml` +- `ledger-core.public.v1.yaml` +- `workbench.public.v1.yaml` + +`sources.lock.json` binds each published copy to its owner repository and +SHA-256 digest. `pnpm contracts:check` rejects drift and internal routes. + +## Validation + +```bash +pnpm guardian:check +pnpm contracts:check +pnpm test +pnpm build +pnpm test:e2e +``` + +Run `pnpm dev` for local authoring. The production site is published from +GitHub Actions to `https://mavulahq.github.io/developer-docs/`. + ## License AGPL-3.0-only. MAVULA names and marks remain reserved. diff --git a/astro.config.mjs b/astro.config.mjs new file mode 100644 index 0000000..3904639 --- /dev/null +++ b/astro.config.mjs @@ -0,0 +1,80 @@ +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +const sidebar = [ + { label: 'Home', link: '/' }, + { + label: 'Get started', + items: [ + { label: 'Overview', link: '/v1/' }, + { label: 'Quickstart', link: '/v1/getting-started/quickstart/' }, + { label: 'Authentication', link: '/v1/getting-started/authentication/' }, + { label: 'Roles and permissions', link: '/v1/getting-started/roles-permissions/' }, + { label: 'Request reliability', link: '/v1/getting-started/request-reliability/' }, + { label: 'Postman collection', link: '/v1/resources/code-examples/#postman' }, + ], + }, + { + label: 'Guides', + items: [ + { label: 'Account setup', link: '/v1/guides/account-setup/' }, + { label: 'Financial controls', link: '/v1/guides/account-lifecycle/' }, + { label: 'Adjustments', link: '/v1/guides/financial-adjustments/' }, + { label: 'Configuration', link: '/v1/guides/configuration/' }, + { label: 'Payment jobs', link: '/v1/guides/payment-jobs/' }, + { label: 'Legacy batches', link: '/v1/guides/legacy-batches/' }, + ], + }, + { + label: 'Concepts', + items: [ + { label: 'Tenant isolation', link: '/v1/concepts/tenant-isolation/' }, + { label: 'Idempotency and retries', link: '/v1/concepts/idempotency/' }, + { label: 'Errors', link: '/v1/concepts/errors/' }, + { label: 'Projections', link: '/v1/concepts/projections/' }, + ], + }, + { + label: 'Reference', + items: [ + { label: 'Identity Access API', link: '/v1/api/identity-access/' }, + { label: 'Ledger Core API', link: '/v1/api/ledger-core/' }, + { label: 'Workbench API', link: '/v1/api/workbench/' }, + { label: 'Current limitations', link: '/v1/resources/limitations/' }, + ], + }, + { + label: 'Resources', + items: [ + { label: 'Code examples', link: '/v1/resources/code-examples/' }, + { label: 'GitHub', link: 'https://github.com/mavulahq' }, + { label: 'Support', link: 'https://github.com/orgs/mavulahq/discussions' }, + ], + }, +]; + +export default defineConfig({ + site: 'https://mavulahq.github.io', + base: '/developer-docs', + integrations: [ + starlight({ + title: 'MAVULA Developer Docs', + description: 'Integration guides and public API reference for MAVULA financial infrastructure.', + customCss: ['./src/styles/custom.css'], + favicon: '/favicon.svg', + social: [ + { icon: 'github', label: 'GitHub', href: 'https://github.com/mavulahq/developer-docs' }, + ], + sidebar, + pagination: true, + lastUpdated: true, + editLink: { + baseUrl: 'https://github.com/mavulahq/developer-docs/edit/main/', + }, + head: [ + { tag: 'meta', attrs: { name: 'theme-color', content: '#071a45' } }, + { tag: 'meta', attrs: { property: 'og:site_name', content: 'MAVULA Developer Docs' } }, + ], + }), + ], +}); diff --git a/examples/postman/MAVULA-API-v1.postman_collection.json b/examples/postman/MAVULA-API-v1.postman_collection.json new file mode 100644 index 0000000..fbb37de --- /dev/null +++ b/examples/postman/MAVULA-API-v1.postman_collection.json @@ -0,0 +1,76 @@ +{ + "info": { + "name": "MAVULA API v1", + "description": "Public identity, ledger and workbench integration workflows.", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "variable": [ + { "key": "identity_base_url", "value": "https://identity.mavula.dev" }, + { "key": "ledger_base_url", "value": "https://ledger.mavula.dev" }, + { "key": "workbench_base_url", "value": "https://workbench.mavula.dev" }, + { "key": "access_token", "value": "" }, + { "key": "account_id", "value": "" }, + { "key": "request_id", "value": "" } + ], + "item": [ + { + "name": "Identity", + "item": [ + { + "name": "Effective identity", + "request": { + "method": "GET", + "header": [{ "key": "Authorization", "value": "Bearer {{access_token}}" }], + "url": "{{identity_base_url}}/api/v1/me" + } + } + ] + }, + { + "name": "Accounts", + "item": [ + { + "name": "Create account", + "request": { + "method": "POST", + "header": [ + { "key": "Authorization", "value": "Bearer {{access_token}}" }, + { "key": "Content-Type", "value": "application/json" }, + { "key": "Idempotency-Key", "value": "{{$guid}}" }, + { "key": "X-Correlation-ID", "value": "{{$guid}}" } + ], + "body": { "mode": "raw", "raw": "{\n \"customer_id\": \"customer_001\",\n \"product_id\": \"current_account_mzn\",\n \"name\": \"Operating account\",\n \"currency\": \"MZN\"\n}" }, + "url": "{{ledger_base_url}}/api/accounts" + } + }, + { + "name": "Submit freeze request", + "request": { + "method": "POST", + "header": [ + { "key": "Authorization", "value": "Bearer {{access_token}}" }, + { "key": "Content-Type", "value": "application/json" }, + { "key": "Idempotency-Key", "value": "{{$guid}}" }, + { "key": "X-Correlation-ID", "value": "{{$guid}}" } + ], + "body": { "mode": "raw", "raw": "{\n \"transition\": \"FREEZE\",\n \"reason\": \"Suspected fraud\"\n}" }, + "url": "{{ledger_base_url}}/api/accounts/{{account_id}}/status-transitions" + } + } + ] + }, + { + "name": "Workbench", + "item": [ + { + "name": "Read platform status", + "request": { + "method": "GET", + "header": [{ "key": "Authorization", "value": "Bearer {{access_token}}" }], + "url": "{{workbench_base_url}}/api/status" + } + } + ] + } + ] +} diff --git a/openapi/identity-access.public.v1.yaml b/openapi/identity-access.public.v1.yaml new file mode 100644 index 0000000..7434d0f --- /dev/null +++ b/openapi/identity-access.public.v1.yaml @@ -0,0 +1,280 @@ +openapi: 3.1.0 +info: + title: MAVULA Identity Access API + version: 1.0.0 + description: | + Institutional OAuth 2.0 and OpenID Connect authorization surface. + Tokens carry effective tenant, institution, branch, role, and permission claims derived from persisted identity state. + license: + name: GNU Affero General Public License v3.0 only + identifier: AGPL-3.0-only +servers: + - url: https://identity.mavula.dev + description: Identity Access public endpoint +tags: + - name: Discovery + description: OpenID Provider metadata and signing keys. + - name: OAuth2 + description: Authorization, token exchange, refresh, service credentials, and revocation. + - name: Identity + description: Effective authenticated operator or service identity. +security: [] +paths: + /.well-known/openid-configuration: + get: + operationId: getOpenIdConfiguration + summary: Read OpenID Provider metadata + description: Discover issuer endpoints, supported grants, claims, scopes, and signing algorithms. + tags: [Discovery] + responses: + '200': + description: OpenID Provider metadata + content: + application/json: + schema: { $ref: '#/components/schemas/OpenIdConfiguration' } + example: + issuer: https://identity.mavula.dev + authorization_endpoint: https://identity.mavula.dev/auth + token_endpoint: https://identity.mavula.dev/token + jwks_uri: https://identity.mavula.dev/jwks + revocation_endpoint: https://identity.mavula.dev/token/revocation + response_types_supported: [code] + grant_types_supported: [authorization_code, refresh_token, client_credentials] + token_endpoint_auth_methods_supported: [client_secret_basic, client_secret_post] + id_token_signing_alg_values_supported: [PS256] + /jwks: + get: + operationId: getJsonWebKeySet + summary: Read public signing keys + description: Retrieve the PS256 public keys used by MAVULA resource servers to verify access tokens. + tags: [Discovery] + responses: + '200': + description: Public JSON Web Key Set + content: + application/json: + schema: { $ref: '#/components/schemas/JsonWebKeySet' } + /auth: + get: + operationId: authorize + summary: Start operator authorization + description: Start Authorization Code with PKCE. The user agent follows the resulting interaction and redirect flow. + tags: [OAuth2] + parameters: + - { in: query, name: client_id, required: true, description: Registered public client identifier., schema: { type: string } } + - { in: query, name: redirect_uri, required: true, description: Exact registered callback URI., schema: { type: string, format: uri } } + - { in: query, name: response_type, required: true, schema: { const: code } } + - { in: query, name: scope, required: true, description: Space-delimited scopes including openid., schema: { type: string, example: 'openid profile finance.read' } } + - { in: query, name: state, required: true, description: Opaque client value used to prevent request forgery., schema: { type: string, minLength: 16 } } + - { in: query, name: code_challenge, required: true, schema: { type: string } } + - { in: query, name: code_challenge_method, required: true, schema: { const: S256 } } + responses: + '302': + description: Redirect to the operator interaction or registered callback URI + headers: + Location: { schema: { type: string, format: uri } } + '400': { $ref: '#/components/responses/OAuthError' } + /token: + post: + operationId: exchangeToken + summary: Exchange credentials for tokens + description: Exchange an authorization code, refresh token, or service client credentials for an access token. + tags: [OAuth2] + requestBody: + required: true + content: + application/x-www-form-urlencoded: + schema: + oneOf: + - $ref: '#/components/schemas/AuthorizationCodeTokenRequest' + - $ref: '#/components/schemas/RefreshTokenRequest' + - $ref: '#/components/schemas/ClientCredentialsTokenRequest' + examples: + authorization_code: + value: { grant_type: authorization_code, code: auth_code_value, redirect_uri: 'https://app.example/callback', code_verifier: pkce_verifier } + client_credentials: + value: { grant_type: client_credentials, client_id: service_client, client_secret: redacted, scope: internal.worker } + responses: + '200': + description: OAuth token response + content: + application/json: + schema: { $ref: '#/components/schemas/TokenResponse' } + '400': { $ref: '#/components/responses/OAuthError' } + '401': { $ref: '#/components/responses/OAuthError' } + /token/revocation: + post: + operationId: revokeToken + summary: Revoke a token + description: Revoke an access or refresh token. A successful response does not disclose whether the token existed. + tags: [OAuth2] + requestBody: + required: true + content: + application/x-www-form-urlencoded: + schema: { $ref: '#/components/schemas/RevokeTokenRequest' } + example: { token: refresh_token_value, token_type_hint: refresh_token } + responses: + '200': { description: Revocation accepted } + '400': { $ref: '#/components/responses/OAuthError' } + '401': { $ref: '#/components/responses/OAuthError' } + /api/v1/me: + get: + operationId: getEffectiveOperatorIdentity + summary: Read effective identity + description: Return the trusted tenant, institution, branch, roles, and permissions carried by the current access token. + tags: [Identity] + security: [{ oauth2: [profile] }, { bearerAuth: [] }] + responses: + '200': + description: Effective identity + content: + application/json: + schema: { $ref: '#/components/schemas/EffectiveIdentity' } + example: + sub: operator_01 + tenant_id: tenant_01 + institution_id: institution_01 + branch_id: branch_maputo + roles: [operations_maker] + permissions: [finance.read, finance.write, workbench.read, workbench.jobs.write] + client_id: institutional_portal + '401': { $ref: '#/components/responses/Unauthorized' } +components: + securitySchemes: + bearerAuth: { type: http, scheme: bearer, bearerFormat: JWT } + oauth2: + type: oauth2 + flows: + authorizationCode: + authorizationUrl: /auth + tokenUrl: /token + refreshUrl: /token + scopes: + openid: Authenticate an operator. + profile: Read effective identity claims. + finance.read: Read tenant-scoped financial resources. + clientCredentials: + tokenUrl: /token + scopes: + internal.worker: Invoke protected service callbacks. + schemas: + OpenIdConfiguration: + type: object + required: [issuer, authorization_endpoint, token_endpoint, jwks_uri, response_types_supported] + properties: + issuer: { type: string, format: uri } + authorization_endpoint: { type: string, format: uri } + token_endpoint: { type: string, format: uri } + jwks_uri: { type: string, format: uri } + revocation_endpoint: { type: string, format: uri } + response_types_supported: { type: array, items: { type: string } } + grant_types_supported: { type: array, items: { type: string } } + token_endpoint_auth_methods_supported: { type: array, items: { type: string } } + id_token_signing_alg_values_supported: { type: array, items: { type: string } } + additionalProperties: true + JsonWebKeySet: + type: object + required: [keys] + properties: + keys: + type: array + items: + type: object + required: [kty, kid, use, alg] + properties: + kty: { type: string } + kid: { type: string } + use: { type: string, const: sig } + alg: { type: string, const: PS256 } + n: { type: string } + e: { type: string } + AuthorizationCodeTokenRequest: + type: object + additionalProperties: false + required: [grant_type, code, redirect_uri, code_verifier] + properties: + grant_type: { const: authorization_code } + code: { type: string } + redirect_uri: { type: string, format: uri } + code_verifier: { type: string } + client_id: { type: string } + RefreshTokenRequest: + type: object + additionalProperties: false + required: [grant_type, refresh_token] + properties: + grant_type: { const: refresh_token } + refresh_token: { type: string } + client_id: { type: string } + scope: { type: string } + ClientCredentialsTokenRequest: + type: object + additionalProperties: false + required: [grant_type] + properties: + grant_type: { const: client_credentials } + client_id: { type: string } + client_secret: { type: string, format: password } + scope: { type: string } + RevokeTokenRequest: + type: object + additionalProperties: false + required: [token] + properties: + token: { type: string } + token_type_hint: { type: string, enum: [access_token, refresh_token] } + client_id: { type: string } + client_secret: { type: string, format: password } + TokenResponse: + type: object + required: [access_token, token_type, expires_in] + properties: + access_token: { type: string } + token_type: { const: Bearer } + expires_in: { type: integer, minimum: 1 } + id_token: { type: string } + refresh_token: { type: string } + scope: { type: string } + EffectiveIdentity: + type: object + additionalProperties: false + required: [sub, tenant_id, institution_id, roles, permissions] + properties: + sub: { type: string } + tenant_id: { type: string } + institution_id: { type: string } + branch_id: { type: string } + roles: + type: array + items: { type: string, enum: [institution_admin, operations_maker, operations_checker, compliance_officer, auditor] } + permissions: + type: array + items: + type: string + enum: [finance.read, finance.write, finance.approve, configuration.write, compliance.manage, audit.read, identity.admin, workbench.read, workbench.jobs.write, observability.read, internal.worker] + client_id: { type: string } + OAuthError: + type: object + required: [error] + properties: + error: { type: string } + error_description: { type: string } + error_uri: { type: string, format: uri } + HttpError: + type: object + required: [statusCode, message] + properties: + statusCode: { type: integer } + message: + oneOf: + - { type: string } + - { type: array, items: { type: string } } + error: { type: string } + responses: + OAuthError: + description: OAuth 2.0 protocol error + content: { application/json: { schema: { $ref: '#/components/schemas/OAuthError' } } } + Unauthorized: + description: Bearer token is missing, expired, invalid, or issued for a different audience + content: { application/json: { schema: { $ref: '#/components/schemas/HttpError' } } } diff --git a/openapi/ledger-core.public.v1.yaml b/openapi/ledger-core.public.v1.yaml new file mode 100644 index 0000000..91d0e56 --- /dev/null +++ b/openapi/ledger-core.public.v1.yaml @@ -0,0 +1,948 @@ +openapi: 3.1.0 +info: + title: MAVULA Ledger Core API + version: 1.0.0 + description: | + Tenant-scoped accounts, controlled financial adjustments, product configuration, workflows, and read projections. + Ledger Core is the financial source of truth and enforces idempotency, tenant isolation, and maker-checker controls. + license: + name: GNU Affero General Public License v3.0 only + identifier: AGPL-3.0-only +servers: + - url: https://ledger.mavula.dev + description: Ledger Core public endpoint +security: [{ bearerAuth: [] }] +tags: + - { name: Accounts, description: 'Tenant-scoped accounts, balances, and statements.' } + - { name: Account lifecycle, description: 'Freeze, unfreeze, and close requests with maker-checker approval.' } + - { name: Financial adjustments, description: Controlled reversal and correction requests. } + - { name: Configuration, description: Institutional financial product configuration. } + - { name: Rules, description: Product rule definitions and defaults. } + - { name: Schemas, description: Institution-defined entity schemas. } + - { name: Workflows, description: Configurable workflow definitions and executions. } + - { name: Projections, description: Eventually consistent activity and publication read models. } +paths: + /api/accounts: + get: + operationId: listAccounts + summary: List accounts + description: List accounts visible to the authenticated tenant. + tags: [Accounts] + x-mavula-permissions: [finance.read] + responses: + '200': { description: Accounts, content: { application/json: { schema: { type: array, items: { $ref: '#/components/schemas/Account' } } } } } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + post: + operationId: createAccount + summary: Create an account + description: Create an active tenant-scoped account. An identical Idempotency-Key replay returns the original response. + tags: [Accounts] + x-mavula-permissions: [finance.write] + parameters: [{ $ref: '#/components/parameters/IdempotencyKey' }, { $ref: '#/components/parameters/CorrelationId' }] + requestBody: + required: true + content: + application/json: + schema: { $ref: '#/components/schemas/CreateAccount' } + example: { customer_id: customer_001, product_id: savings_standard, name: Primary Savings, currency: MZN } + responses: + '201': { description: Account created, content: { application/json: { schema: { $ref: '#/components/schemas/Account' } } } } + '400': { $ref: '#/components/responses/BadRequest' } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + '409': { $ref: '#/components/responses/Conflict' } + /api/accounts/{accountId}: + get: + operationId: getAccount + summary: Read an account + tags: [Accounts] + x-mavula-permissions: [finance.read] + parameters: [{ $ref: '#/components/parameters/AccountId' }] + responses: + '200': { description: Account, content: { application/json: { schema: { $ref: '#/components/schemas/Account' } } } } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + '404': { $ref: '#/components/responses/NotFound' } + /api/accounts/{accountId}/balance: + get: + operationId: getAccountBalance + summary: Read account balance + description: Read the synchronous account balance used for financial decisions. + tags: [Accounts] + x-mavula-permissions: [finance.read] + parameters: [{ $ref: '#/components/parameters/AccountId' }] + responses: + '200': { description: Account balance, content: { application/json: { schema: { $ref: '#/components/schemas/AccountBalance' } } } } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + '404': { $ref: '#/components/responses/NotFound' } + /api/accounts/{accountId}/statement: + get: + operationId: getAccountStatement + summary: Read account statement + description: Read entries ordered by posting time with stable cursor pagination. + tags: [Accounts] + x-mavula-permissions: [finance.read] + parameters: + - { $ref: '#/components/parameters/AccountId' } + - { in: query, name: from, schema: { type: string, format: date-time } } + - { in: query, name: to, schema: { type: string, format: date-time } } + - { in: query, name: cursor, schema: { type: string } } + - { in: query, name: limit, schema: { type: integer, minimum: 1, maximum: 100, default: 50 } } + responses: + '200': { description: Paginated statement, content: { application/json: { schema: { $ref: '#/components/schemas/AccountStatementPage' } } } } + '400': { $ref: '#/components/responses/BadRequest' } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + '404': { $ref: '#/components/responses/NotFound' } + /api/accounts/{accountId}/status-transitions: + post: + operationId: submitAccountStatusTransition + summary: Submit an account status transition + description: Submit FREEZE, UNFREEZE, or CLOSE for approval by a different operator. + tags: [Account lifecycle] + x-mavula-permissions: [finance.write] + parameters: [{ $ref: '#/components/parameters/AccountId' }, { $ref: '#/components/parameters/IdempotencyKey' }, { $ref: '#/components/parameters/CorrelationId' }] + requestBody: + required: true + content: + application/json: + schema: { $ref: '#/components/schemas/SubmitAccountTransition' } + example: { transition: FREEZE, reason: Suspected unauthorized activity } + responses: + '201': { description: Lifecycle request submitted, content: { application/json: { schema: { $ref: '#/components/schemas/AccountLifecycleRequest' } } } } + '400': { $ref: '#/components/responses/BadRequest' } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + '404': { $ref: '#/components/responses/NotFound' } + '409': { $ref: '#/components/responses/Conflict' } + /api/account-lifecycle-requests: + get: + operationId: listAccountLifecycleRequests + summary: List account lifecycle requests + tags: [Account lifecycle] + x-mavula-permissions: [finance.read] + parameters: + - { in: query, name: account_id, schema: { type: string } } + - { in: query, name: status, schema: { $ref: '#/components/schemas/DecisionStatus' } } + - { in: query, name: cursor, schema: { type: string } } + - { in: query, name: limit, schema: { type: integer, minimum: 1, maximum: 100, default: 50 } } + responses: + '200': { description: Lifecycle requests, content: { application/json: { schema: { $ref: '#/components/schemas/AccountLifecyclePage' } } } } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + /api/account-lifecycle-requests/{requestId}: + get: + operationId: getAccountLifecycleRequest + summary: Read an account lifecycle request + tags: [Account lifecycle] + x-mavula-permissions: [finance.read] + parameters: [{ $ref: '#/components/parameters/RequestId' }] + responses: + '200': { description: Lifecycle request, content: { application/json: { schema: { $ref: '#/components/schemas/AccountLifecycleRequest' } } } } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + '404': { $ref: '#/components/responses/NotFound' } + /api/account-lifecycle-requests/{requestId}/approve: + post: + operationId: approveAccountLifecycleRequest + summary: Approve an account lifecycle request + description: Apply a pending transition. The checker must have finance.approve and cannot be the maker. + tags: [Account lifecycle] + x-mavula-permissions: [finance.approve] + parameters: [{ $ref: '#/components/parameters/RequestId' }, { $ref: '#/components/parameters/IdempotencyKey' }, { $ref: '#/components/parameters/CorrelationId' }] + requestBody: { $ref: '#/components/requestBodies/OptionalDecision' } + responses: + '201': { description: Lifecycle request applied, content: { application/json: { schema: { $ref: '#/components/schemas/AccountLifecycleRequest' } } } } + '400': { $ref: '#/components/responses/BadRequest' } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + '404': { $ref: '#/components/responses/NotFound' } + '409': { $ref: '#/components/responses/Conflict' } + /api/account-lifecycle-requests/{requestId}/reject: + post: + operationId: rejectAccountLifecycleRequest + summary: Reject an account lifecycle request + tags: [Account lifecycle] + x-mavula-permissions: [finance.approve] + parameters: [{ $ref: '#/components/parameters/RequestId' }, { $ref: '#/components/parameters/IdempotencyKey' }, { $ref: '#/components/parameters/CorrelationId' }] + requestBody: { $ref: '#/components/requestBodies/RequiredDecision' } + responses: + '201': { description: Lifecycle request rejected, content: { application/json: { schema: { $ref: '#/components/schemas/AccountLifecycleRequest' } } } } + '400': { $ref: '#/components/responses/BadRequest' } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + '404': { $ref: '#/components/responses/NotFound' } + '409': { $ref: '#/components/responses/Conflict' } + /api/financial-adjustment-requests: + get: + operationId: listFinancialAdjustmentRequests + summary: List financial adjustment requests + tags: [Financial adjustments] + x-mavula-permissions: [finance.read] + parameters: + - { in: query, name: status, schema: { $ref: '#/components/schemas/DecisionStatus' } } + - { in: query, name: adjustment_type, schema: { type: string, enum: [REVERSAL, CORRECTION] } } + - { in: query, name: target_type, schema: { type: string, enum: [TRANSACTION, JOURNAL_ENTRY] } } + - { in: query, name: target_id, schema: { type: string } } + - { in: query, name: cursor, schema: { type: string } } + - { in: query, name: limit, schema: { type: integer, minimum: 1, maximum: 100, default: 50 } } + responses: + '200': { description: Adjustment requests, content: { application/json: { schema: { $ref: '#/components/schemas/FinancialAdjustmentPage' } } } } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + post: + operationId: submitFinancialAdjustmentRequest + summary: Submit a financial adjustment + description: Submit a reversal or correction without mutating the immutable original record. + tags: [Financial adjustments] + x-mavula-permissions: [finance.write] + parameters: [{ $ref: '#/components/parameters/IdempotencyKey' }, { $ref: '#/components/parameters/CorrelationId' }] + requestBody: + required: true + content: + application/json: + schema: { $ref: '#/components/schemas/CreateFinancialAdjustment' } + examples: + reversal: { value: { target_type: TRANSACTION, target_id: transaction_001, adjustment_type: REVERSAL, reason: Duplicate posting } } + correction: + value: + target_type: JOURNAL_ENTRY + target_id: journal_001 + adjustment_type: CORRECTION + reason: Correct clearing account + correction: { journal: { ledger_lines: [{ account_code: '1100', debit_amount: '100.00' }, { account_code: '2100', credit_amount: '100.00' }] } } + responses: + '201': { description: Adjustment request submitted, content: { application/json: { schema: { $ref: '#/components/schemas/FinancialAdjustmentRequest' } } } } + '400': { $ref: '#/components/responses/BadRequest' } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + '404': { $ref: '#/components/responses/NotFound' } + '409': { $ref: '#/components/responses/Conflict' } + /api/financial-adjustment-requests/{requestId}: + get: + operationId: getFinancialAdjustmentRequest + summary: Read a financial adjustment request + tags: [Financial adjustments] + x-mavula-permissions: [finance.read] + parameters: [{ $ref: '#/components/parameters/RequestId' }] + responses: + '200': { description: Adjustment request, content: { application/json: { schema: { $ref: '#/components/schemas/FinancialAdjustmentRequest' } } } } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + '404': { $ref: '#/components/responses/NotFound' } + /api/financial-adjustment-requests/{requestId}/approve: + post: + operationId: approveFinancialAdjustmentRequest + summary: Approve a financial adjustment + description: Atomically post the reversal and optional replacement. Self-approval is rejected. + tags: [Financial adjustments] + x-mavula-permissions: [finance.approve] + parameters: [{ $ref: '#/components/parameters/RequestId' }, { $ref: '#/components/parameters/IdempotencyKey' }, { $ref: '#/components/parameters/CorrelationId' }] + requestBody: { $ref: '#/components/requestBodies/OptionalDecision' } + responses: + '201': { description: Adjustment applied, content: { application/json: { schema: { $ref: '#/components/schemas/FinancialAdjustmentRequest' } } } } + '400': { $ref: '#/components/responses/BadRequest' } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + '404': { $ref: '#/components/responses/NotFound' } + '409': { $ref: '#/components/responses/Conflict' } + /api/financial-adjustment-requests/{requestId}/reject: + post: + operationId: rejectFinancialAdjustmentRequest + summary: Reject a financial adjustment + tags: [Financial adjustments] + x-mavula-permissions: [finance.approve] + parameters: [{ $ref: '#/components/parameters/RequestId' }, { $ref: '#/components/parameters/IdempotencyKey' }, { $ref: '#/components/parameters/CorrelationId' }] + requestBody: { $ref: '#/components/requestBodies/RequiredDecision' } + responses: + '201': { description: Adjustment rejected, content: { application/json: { schema: { $ref: '#/components/schemas/FinancialAdjustmentRequest' } } } } + '400': { $ref: '#/components/responses/BadRequest' } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + '404': { $ref: '#/components/responses/NotFound' } + '409': { $ref: '#/components/responses/Conflict' } + /api/products: + get: + operationId: listProducts + summary: List financial products + tags: [Configuration] + x-mavula-permissions: [finance.read] + responses: + '200': { description: Products, content: { application/json: { schema: { type: array, items: { $ref: '#/components/schemas/Product' } } } } } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + post: + operationId: upsertProduct + summary: Create or update a product + tags: [Configuration] + x-mavula-permissions: [configuration.write] + parameters: [{ $ref: '#/components/parameters/IdempotencyKey' }, { $ref: '#/components/parameters/CorrelationId' }] + requestBody: { $ref: '#/components/requestBodies/UpsertProduct' } + responses: + '201': { description: Product configuration stored, content: { application/json: { schema: { $ref: '#/components/schemas/Product' } } } } + '400': { $ref: '#/components/responses/BadRequest' } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + '409': { $ref: '#/components/responses/Conflict' } + /api/products/config: + get: + operationId: getProductConfiguration + summary: Read tenant product configuration + tags: [Configuration] + x-mavula-permissions: [finance.read] + responses: + '200': { description: Tenant product configuration, content: { application/json: { schema: { $ref: '#/components/schemas/TenantProductConfiguration' } } } } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + '404': { $ref: '#/components/responses/NotFound' } + /api/products/config/generate: + post: + operationId: generateProductConfiguration + summary: Generate jurisdiction defaults + tags: [Configuration] + x-mavula-permissions: [configuration.write] + parameters: [{ $ref: '#/components/parameters/IdempotencyKey' }, { $ref: '#/components/parameters/CorrelationId' }] + requestBody: + required: true + content: { application/json: { schema: { $ref: '#/components/schemas/GenerateTenantConfiguration' }, example: { jurisdiction: MZ } } } + responses: + '201': { description: Configuration generated, content: { application/json: { schema: { $ref: '#/components/schemas/TenantProductConfiguration' } } } } + '400': { $ref: '#/components/responses/BadRequest' } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + '409': { $ref: '#/components/responses/Conflict' } + /api/products/{productId}: + get: + operationId: getProduct + summary: Read a financial product + tags: [Configuration] + x-mavula-permissions: [finance.read] + parameters: [{ $ref: '#/components/parameters/ProductId' }] + responses: + '200': { description: Product, content: { application/json: { schema: { $ref: '#/components/schemas/Product' } } } } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + '404': { $ref: '#/components/responses/NotFound' } + /api/products/{productId}/rules: + get: + operationId: listRules + summary: List product rules + tags: [Rules] + x-mavula-permissions: [finance.read] + parameters: [{ $ref: '#/components/parameters/ProductId' }] + responses: + '200': { description: Rules, content: { application/json: { schema: { type: array, items: { $ref: '#/components/schemas/Rule' } } } } } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + post: + operationId: createRule + summary: Create a product rule + tags: [Rules] + x-mavula-permissions: [configuration.write] + parameters: [{ $ref: '#/components/parameters/ProductId' }, { $ref: '#/components/parameters/IdempotencyKey' }, { $ref: '#/components/parameters/CorrelationId' }] + requestBody: { $ref: '#/components/requestBodies/CreateRule' } + responses: + '201': { description: Rule created, content: { application/json: { schema: { $ref: '#/components/schemas/Rule' } } } } + '400': { $ref: '#/components/responses/BadRequest' } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + '409': { $ref: '#/components/responses/Conflict' } + /api/products/{productId}/rules/defaults: + post: + operationId: seedDefaultRules + summary: Seed default product rules + tags: [Rules] + x-mavula-permissions: [configuration.write] + parameters: [{ $ref: '#/components/parameters/ProductId' }, { $ref: '#/components/parameters/IdempotencyKey' }, { $ref: '#/components/parameters/CorrelationId' }] + responses: + '201': { description: Default rules created, content: { application/json: { schema: { type: array, items: { $ref: '#/components/schemas/Rule' } } } } } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + '409': { $ref: '#/components/responses/Conflict' } + /api/products/{productId}/rules/{ruleId}: + put: + operationId: updateRule + summary: Update a product rule + tags: [Rules] + x-mavula-permissions: [configuration.write] + parameters: [{ $ref: '#/components/parameters/ProductId' }, { $ref: '#/components/parameters/RuleId' }, { $ref: '#/components/parameters/IdempotencyKey' }, { $ref: '#/components/parameters/CorrelationId' }] + requestBody: { $ref: '#/components/requestBodies/UpdateRule' } + responses: + '200': { description: Rule updated, content: { application/json: { schema: { $ref: '#/components/schemas/MutationStatus' } } } } + '400': { $ref: '#/components/responses/BadRequest' } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + '409': { $ref: '#/components/responses/Conflict' } + delete: + operationId: deleteRule + summary: Delete a product rule + tags: [Rules] + x-mavula-permissions: [configuration.write] + parameters: [{ $ref: '#/components/parameters/ProductId' }, { $ref: '#/components/parameters/RuleId' }, { $ref: '#/components/parameters/IdempotencyKey' }, { $ref: '#/components/parameters/CorrelationId' }] + responses: + '200': { description: Rule deleted, content: { application/json: { schema: { $ref: '#/components/schemas/MutationStatus' } } } } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + '409': { $ref: '#/components/responses/Conflict' } + /api/schemas: + get: + operationId: listSchemas + summary: List entity schemas + tags: [Schemas] + x-mavula-permissions: [finance.read] + responses: + '200': { description: Schemas, content: { application/json: { schema: { type: array, items: { $ref: '#/components/schemas/EntitySchema' } } } } } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + post: + operationId: createSchema + summary: Create an entity schema + tags: [Schemas] + x-mavula-permissions: [configuration.write] + parameters: [{ $ref: '#/components/parameters/IdempotencyKey' }, { $ref: '#/components/parameters/CorrelationId' }] + requestBody: { $ref: '#/components/requestBodies/CreateSchema' } + responses: + '201': { description: Schema created, content: { application/json: { schema: { $ref: '#/components/schemas/EntitySchema' } } } } + '400': { $ref: '#/components/responses/BadRequest' } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + '409': { $ref: '#/components/responses/Conflict' } + /api/schemas/import: + post: + operationId: importSchema + summary: Import an entity schema + tags: [Schemas] + x-mavula-permissions: [configuration.write] + parameters: [{ $ref: '#/components/parameters/IdempotencyKey' }, { $ref: '#/components/parameters/CorrelationId' }] + requestBody: { $ref: '#/components/requestBodies/CreateSchema' } + responses: + '201': { description: Schema imported, content: { application/json: { schema: { $ref: '#/components/schemas/EntitySchema' } } } } + '400': { $ref: '#/components/responses/BadRequest' } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + '409': { $ref: '#/components/responses/Conflict' } + /api/schemas/presets/business-registration: + post: + operationId: createBusinessRegistrationSchema + summary: Create the business registration preset + tags: [Schemas] + x-mavula-permissions: [configuration.write] + parameters: [{ $ref: '#/components/parameters/IdempotencyKey' }, { $ref: '#/components/parameters/CorrelationId' }] + responses: + '201': { description: Preset schema created, content: { application/json: { schema: { $ref: '#/components/schemas/EntitySchema' } } } } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + '409': { $ref: '#/components/responses/Conflict' } + /api/schemas/{schemaId}: + get: + operationId: getSchema + summary: Read an entity schema + tags: [Schemas] + x-mavula-permissions: [finance.read] + parameters: [{ $ref: '#/components/parameters/SchemaId' }] + responses: + '200': { description: Schema, content: { application/json: { schema: { $ref: '#/components/schemas/EntitySchema' } } } } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + '404': { $ref: '#/components/responses/NotFound' } + /api/schemas/{schemaId}/export: + get: + operationId: exportSchema + summary: Export an entity schema + tags: [Schemas] + x-mavula-permissions: [finance.read] + parameters: [{ $ref: '#/components/parameters/SchemaId' }] + responses: + '200': { description: Portable schema definition, content: { application/json: { schema: { $ref: '#/components/schemas/EntitySchema' } } } } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + '404': { $ref: '#/components/responses/NotFound' } + /api/workflows: + get: + operationId: listWorkflows + summary: List workflows + tags: [Workflows] + x-mavula-permissions: [finance.read] + responses: + '200': { description: Workflows, content: { application/json: { schema: { type: array, items: { $ref: '#/components/schemas/Workflow' } } } } } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + post: + operationId: createWorkflow + summary: Create a workflow + tags: [Workflows] + x-mavula-permissions: [configuration.write] + parameters: [{ $ref: '#/components/parameters/IdempotencyKey' }, { $ref: '#/components/parameters/CorrelationId' }] + requestBody: { $ref: '#/components/requestBodies/CreateWorkflow' } + responses: + '201': { description: Workflow created, content: { application/json: { schema: { $ref: '#/components/schemas/Workflow' } } } } + '400': { $ref: '#/components/responses/BadRequest' } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + '409': { $ref: '#/components/responses/Conflict' } + /api/workflows/trigger/{trigger}: + get: + operationId: listWorkflowsByTrigger + summary: List workflows by trigger + tags: [Workflows] + x-mavula-permissions: [finance.read] + parameters: [{ in: path, name: trigger, required: true, schema: { type: string } }] + responses: + '200': { description: Matching workflows, content: { application/json: { schema: { type: array, items: { $ref: '#/components/schemas/Workflow' } } } } } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + /api/workflows/presets/loan-approval-notification: + post: + operationId: createLoanApprovalNotificationWorkflow + summary: Create the loan approval notification preset + tags: [Workflows] + x-mavula-permissions: [configuration.write] + parameters: [{ $ref: '#/components/parameters/IdempotencyKey' }, { $ref: '#/components/parameters/CorrelationId' }] + responses: + '201': { description: Preset workflow created, content: { application/json: { schema: { $ref: '#/components/schemas/Workflow' } } } } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + '409': { $ref: '#/components/responses/Conflict' } + /api/workflows/presets/monthly-fee-charge: + post: + operationId: createMonthlyFeeChargeWorkflow + summary: Create the monthly fee charge preset + tags: [Workflows] + x-mavula-permissions: [configuration.write] + parameters: [{ $ref: '#/components/parameters/IdempotencyKey' }, { $ref: '#/components/parameters/CorrelationId' }] + responses: + '201': { description: Preset workflow created, content: { application/json: { schema: { $ref: '#/components/schemas/Workflow' } } } } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + '409': { $ref: '#/components/responses/Conflict' } + /api/workflows/{workflowId}: + get: + operationId: getWorkflow + summary: Read a workflow + tags: [Workflows] + x-mavula-permissions: [finance.read] + parameters: [{ $ref: '#/components/parameters/WorkflowId' }] + responses: + '200': { description: Workflow, content: { application/json: { schema: { $ref: '#/components/schemas/Workflow' } } } } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + '404': { $ref: '#/components/responses/NotFound' } + /api/workflows/{workflowId}/execute: + post: + operationId: executeWorkflow + summary: Execute a workflow + tags: [Workflows] + x-mavula-permissions: [finance.write] + parameters: [{ $ref: '#/components/parameters/WorkflowId' }, { $ref: '#/components/parameters/IdempotencyKey' }, { $ref: '#/components/parameters/CorrelationId' }] + requestBody: + required: true + content: { application/json: { schema: { $ref: '#/components/schemas/ExecuteWorkflow' }, example: { context: { account_id: account_001, event: MONTH_END } } } } + responses: + '201': { description: Workflow execution completed, content: { application/json: { schema: { type: object, additionalProperties: true } } } } + '400': { $ref: '#/components/responses/BadRequest' } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + '404': { $ref: '#/components/responses/NotFound' } + '409': { $ref: '#/components/responses/Conflict' } + /api/projections/status: + get: + operationId: getProjectionStatus + summary: Read projection checkpoints + description: Read freshness and last-event checkpoints. Projections are eventually consistent and not command-side truth. + tags: [Projections] + x-mavula-permissions: [finance.read] + responses: + '200': { description: Projection checkpoints, content: { application/json: { schema: { type: array, items: { $ref: '#/components/schemas/ProjectionStatus' } } } } } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + /api/projections/loan-activity: + get: { operationId: listLoanActivity, summary: List loan activity projections, tags: [Projections], x-mavula-permissions: [finance.read], responses: { '200': { description: Loan activity projections, content: { application/json: { schema: { type: array, items: { $ref: '#/components/schemas/Projection' } } } } }, '401': { $ref: '#/components/responses/Unauthorized' }, '403': { $ref: '#/components/responses/Forbidden' } } } + /api/projections/loan-activity/{loanId}: + get: { operationId: getLoanActivity, summary: Read a loan activity projection, tags: [Projections], x-mavula-permissions: [finance.read], parameters: [{ in: path, name: loanId, required: true, schema: { type: string } }], responses: { '200': { description: Loan activity projection, content: { application/json: { schema: { $ref: '#/components/schemas/Projection' } } } }, '401': { $ref: '#/components/responses/Unauthorized' }, '403': { $ref: '#/components/responses/Forbidden' }, '404': { $ref: '#/components/responses/NotFound' } } } + /api/projections/ledger-activity: + get: { operationId: listLedgerActivity, summary: List ledger activity projections, tags: [Projections], x-mavula-permissions: [finance.read], responses: { '200': { description: Ledger activity projections, content: { application/json: { schema: { type: array, items: { $ref: '#/components/schemas/Projection' } } } } }, '401': { $ref: '#/components/responses/Unauthorized' }, '403': { $ref: '#/components/responses/Forbidden' } } } + /api/projections/ledger-activity/{journalEntryId}: + get: { operationId: getLedgerActivity, summary: Read a ledger activity projection, tags: [Projections], x-mavula-permissions: [finance.read], parameters: [{ in: path, name: journalEntryId, required: true, schema: { type: string } }], responses: { '200': { description: Ledger activity projection, content: { application/json: { schema: { $ref: '#/components/schemas/Projection' } } } }, '401': { $ref: '#/components/responses/Unauthorized' }, '403': { $ref: '#/components/responses/Forbidden' }, '404': { $ref: '#/components/responses/NotFound' } } } + /api/projections/product-publications: + get: { operationId: listProductPublications, summary: List product publication projections, tags: [Projections], x-mavula-permissions: [finance.read], responses: { '200': { description: Product publication projections, content: { application/json: { schema: { type: array, items: { $ref: '#/components/schemas/Projection' } } } } }, '401': { $ref: '#/components/responses/Unauthorized' }, '403': { $ref: '#/components/responses/Forbidden' } } } + /api/projections/product-publications/{productId}: + get: { operationId: getProductPublication, summary: Read a product publication projection, tags: [Projections], x-mavula-permissions: [finance.read], parameters: [{ $ref: '#/components/parameters/ProductId' }], responses: { '200': { description: Product publication projection, content: { application/json: { schema: { $ref: '#/components/schemas/Projection' } } } }, '401': { $ref: '#/components/responses/Unauthorized' }, '403': { $ref: '#/components/responses/Forbidden' }, '404': { $ref: '#/components/responses/NotFound' } } } +components: + securitySchemes: + bearerAuth: { type: http, scheme: bearer, bearerFormat: JWT } + parameters: + IdempotencyKey: { in: header, name: Idempotency-Key, required: true, description: Reuse only with the same operation and payload., schema: { type: string, minLength: 16, maxLength: 128, pattern: '^[A-Za-z0-9._:-]+$' } } + CorrelationId: { in: header, name: X-Correlation-ID, required: false, description: Recommended trace identifier. The server generates one when omitted., schema: { type: string, minLength: 1, maxLength: 128, pattern: '^[A-Za-z0-9._:-]+$' } } + AccountId: { in: path, name: accountId, required: true, schema: { type: string } } + ProductId: { in: path, name: productId, required: true, schema: { type: string } } + RequestId: { in: path, name: requestId, required: true, schema: { type: string } } + RuleId: { in: path, name: ruleId, required: true, schema: { type: string } } + SchemaId: { in: path, name: schemaId, required: true, schema: { type: string } } + WorkflowId: { in: path, name: workflowId, required: true, schema: { type: string } } + requestBodies: + OptionalDecision: + required: true + content: { application/json: { schema: { $ref: '#/components/schemas/OptionalDecision' }, example: { reason: Reviewed against supporting evidence } } } + RequiredDecision: + required: true + content: { application/json: { schema: { $ref: '#/components/schemas/RequiredDecision' }, example: { reason: Supporting evidence is insufficient } } } + UpsertProduct: + required: true + content: { application/json: { schema: { $ref: '#/components/schemas/UpsertProduct' }, example: { type: SAVINGS, config: { currency: MZN, minimum_balance: '0.00' } } } } + CreateRule: + required: true + content: { application/json: { schema: { $ref: '#/components/schemas/CreateRule' }, example: { rule_type: ELIGIBILITY, condition: 'customer.age >= 18', action: { allow: true }, priority: 10, enabled: true } } } + UpdateRule: + required: true + content: { application/json: { schema: { $ref: '#/components/schemas/UpdateRule' } } } + CreateSchema: + required: true + content: { application/json: { schema: { $ref: '#/components/schemas/CreateSchema' } } } + CreateWorkflow: + required: true + content: { application/json: { schema: { $ref: '#/components/schemas/CreateWorkflow' } } } + schemas: + HttpError: + type: object + required: [statusCode, message] + properties: + statusCode: { type: integer } + message: + oneOf: + - { type: string } + - { type: array, items: { type: string } } + error: { type: string } + CreateAccount: + type: object + additionalProperties: false + required: [customer_id, product_id, name, currency] + properties: + customer_id: { type: string, minLength: 1, maxLength: 128 } + product_id: { type: string, minLength: 1, maxLength: 128 } + name: { type: string, minLength: 1, maxLength: 160 } + currency: { type: string, pattern: '^[A-Z]{3}$' } + Account: + type: object + required: [id, name, currency, status, balance, version, created_at, updated_at] + properties: + id: { type: string } + customer_id: { type: string } + product_id: { type: string } + name: { type: string } + currency: { type: string, pattern: '^[A-Z]{3}$' } + status: { type: string, enum: [ACTIVE, FROZEN, CLOSED] } + balance: { type: string, pattern: '^-?(0|[1-9][0-9]*)(\.[0-9]{2})$' } + version: { type: integer, minimum: 1 } + frozen_at: { type: string, format: date-time } + closed_at: { type: string, format: date-time } + created_at: { type: string, format: date-time } + updated_at: { type: string, format: date-time } + AccountBalance: + type: object + required: [account_id, balance, currency] + properties: + account_id: { type: string } + balance: { type: string } + currency: { type: string, pattern: '^[A-Z]{3}$' } + version: { type: integer } + AccountEntry: + type: object + required: [id, account_id, posting_key, entry_type, direction, amount, currency, balance_after, posted_at] + properties: + id: { type: string } + account_id: { type: string } + journal_entry_id: { type: string } + transaction_id: { type: string } + posting_key: { type: string } + entry_type: { type: string, enum: [OPENING_BALANCE, POSTING, REVERSAL, CORRECTION] } + direction: { type: string, enum: [DEBIT, CREDIT] } + amount: { type: string } + currency: { type: string } + balance_after: { type: string } + reference: { type: string } + posted_at: { type: string, format: date-time } + AccountStatementPage: + type: object + required: [items] + properties: + items: { type: array, items: { $ref: '#/components/schemas/AccountEntry' } } + next_cursor: { type: string } + SubmitAccountTransition: + type: object + additionalProperties: false + required: [transition, reason] + properties: + transition: { type: string, enum: [FREEZE, UNFREEZE, CLOSE] } + reason: { type: string, minLength: 1, maxLength: 500 } + DecisionStatus: { type: string, enum: [PENDING_APPROVAL, APPLIED, REJECTED, FAILED] } + OptionalDecision: + type: object + additionalProperties: false + properties: { reason: { type: string, maxLength: 500 } } + RequiredDecision: + type: object + additionalProperties: false + required: [reason] + properties: { reason: { type: string, minLength: 1, maxLength: 500 } } + AccountLifecycleRequest: + type: object + required: [id, account_id, transition, from_status, target_status, status, reason, requested_by, correlation_id, created_at] + properties: + id: { type: string } + account_id: { type: string } + transition: { type: string, enum: [FREEZE, UNFREEZE, CLOSE] } + from_status: { type: string, enum: [ACTIVE, FROZEN, CLOSED] } + target_status: { type: string, enum: [ACTIVE, FROZEN, CLOSED] } + status: { $ref: '#/components/schemas/DecisionStatus' } + reason: { type: string } + requested_by: { type: string } + decided_by: { type: string } + decision_reason: { type: string } + failure_reason: { type: string } + correlation_id: { type: string } + created_at: { type: string, format: date-time } + decided_at: { type: string, format: date-time } + applied_at: { type: string, format: date-time } + AccountLifecyclePage: + type: object + required: [items] + properties: + items: { type: array, items: { $ref: '#/components/schemas/AccountLifecycleRequest' } } + next_cursor: { type: string } + LedgerLine: + type: object + additionalProperties: false + required: [account_code] + properties: + account_code: { type: string, minLength: 1, maxLength: 64 } + debit_amount: { type: string } + credit_amount: { type: string } + AccountPosting: + type: object + additionalProperties: false + required: [account_id, direction, amount, currency] + properties: + account_id: { type: string } + direction: { type: string, enum: [DEBIT, CREDIT] } + amount: { type: string } + currency: { type: string, pattern: '^[A-Z]{3}$' } + reference: { type: string, maxLength: 160 } + FinancialCorrection: + type: object + additionalProperties: false + properties: + lending: + type: object + required: [amount, currency] + properties: + amount: { type: string } + currency: { type: string, pattern: '^[A-Z]{3}$' } + allocation: + type: object + required: [principal, interest, fees] + properties: { principal: { type: string }, interest: { type: string }, fees: { type: string } } + journal: + type: object + required: [ledger_lines] + properties: + ledger_lines: { type: array, minItems: 2, items: { $ref: '#/components/schemas/LedgerLine' } } + account_postings: { type: array, items: { $ref: '#/components/schemas/AccountPosting' } } + CreateFinancialAdjustment: + type: object + additionalProperties: false + required: [target_type, target_id, adjustment_type, reason] + properties: + target_type: { type: string, enum: [TRANSACTION, JOURNAL_ENTRY] } + target_id: { type: string, minLength: 1, maxLength: 128 } + adjustment_type: { type: string, enum: [REVERSAL, CORRECTION] } + reason: { type: string, minLength: 1, maxLength: 500 } + correction: { $ref: '#/components/schemas/FinancialCorrection' } + FinancialAdjustmentRequest: + allOf: + - $ref: '#/components/schemas/CreateFinancialAdjustment' + - type: object + required: [id, status, requested_by, correlation_id, created_at] + properties: + id: { type: string } + status: { $ref: '#/components/schemas/DecisionStatus' } + target_transaction_id: { type: string } + target_journal_entry_id: { type: string } + target_loan_id: { type: string } + requested_by: { type: string } + decided_by: { type: string } + decision_reason: { type: string } + failure_reason: { type: string } + correlation_id: { type: string } + reversal_transaction_id: { type: string } + reversal_journal_entry_id: { type: string } + replacement_transaction_id: { type: string } + replacement_journal_entry_id: { type: string } + created_at: { type: string, format: date-time } + decided_at: { type: string, format: date-time } + applied_at: { type: string, format: date-time } + FinancialAdjustmentPage: + type: object + required: [items] + properties: + items: { type: array, items: { $ref: '#/components/schemas/FinancialAdjustmentRequest' } } + next_cursor: { type: string } + UpsertProduct: + type: object + additionalProperties: false + required: [type, config] + properties: + type: { type: string } + config: { type: object, additionalProperties: true } + Product: + type: object + required: [id, type, config] + properties: + id: { type: string } + tenant_id: { type: string } + type: { type: string } + config: { type: object, additionalProperties: true } + version: { type: integer } + created_at: { type: string, format: date-time } + updated_at: { type: string, format: date-time } + additionalProperties: true + GenerateTenantConfiguration: + type: object + additionalProperties: false + required: [jurisdiction] + properties: { jurisdiction: { type: string, pattern: '^[A-Z][A-Z0-9_-]{1,15}$' } } + TenantProductConfiguration: + type: object + properties: + jurisdiction: { type: string } + products: { type: array, items: { $ref: '#/components/schemas/Product' } } + additionalProperties: true + CreateRule: + type: object + additionalProperties: false + required: [rule_type, condition, action] + properties: + id: { type: string, maxLength: 128 } + rule_type: { type: string } + condition: { type: string, maxLength: 2000 } + action: { type: object, additionalProperties: true } + priority: { type: integer } + enabled: { type: boolean } + applies_to: { type: array, items: { type: string } } + UpdateRule: + type: object + additionalProperties: false + properties: + condition: { type: string, maxLength: 2000 } + action: { type: object, additionalProperties: true } + priority: { type: integer } + enabled: { type: boolean } + applies_to: { type: array, items: { type: string } } + Rule: + allOf: + - $ref: '#/components/schemas/CreateRule' + - type: object + required: [id, tenant_id, product_id, created_at, updated_at] + properties: + id: { type: string } + tenant_id: { type: string } + product_id: { type: string } + created_at: { type: string, format: date-time } + updated_at: { type: string, format: date-time } + MutationStatus: + type: object + required: [status, rule_id] + properties: { status: { const: ok }, rule_id: { type: string } } + FieldDefinition: + type: object + additionalProperties: false + required: [name, type, required] + properties: + name: { type: string } + type: { type: string, enum: [STRING, NUMBER, DATE, BOOLEAN, ENUM, REFERENCE] } + required: { type: boolean } + maxLength: { type: integer, minimum: 1 } + pattern: { type: string } + enum_values: { type: array, items: { type: string } } + reference_table: { type: string } + default: {} + description: { type: string } + CreateSchema: + type: object + additionalProperties: false + required: [entity_name, display_name, fields] + properties: + entity_name: { type: string, pattern: '^[a-z][a-z0-9_]{1,63}$' } + display_name: { type: string, maxLength: 160 } + fields: { type: array, items: { $ref: '#/components/schemas/FieldDefinition' } } + EntitySchema: + allOf: + - $ref: '#/components/schemas/CreateSchema' + - type: object + properties: + id: { type: string } + tenant_id: { type: string } + version: { type: integer } + created_at: { type: string, format: date-time } + updated_at: { type: string, format: date-time } + WorkflowStep: + type: object + additionalProperties: false + required: [order, name, action, parameters] + properties: + order: { type: integer, minimum: 1 } + name: { type: string } + action: { type: string } + parameters: { type: object, additionalProperties: true } + condition: { type: string } + CreateWorkflow: + type: object + additionalProperties: false + required: [name, trigger, steps] + properties: + name: { type: string, maxLength: 160 } + trigger: { type: string, pattern: '^[A-Z][A-Z0-9_]{2,100}$' } + steps: { type: array, items: { $ref: '#/components/schemas/WorkflowStep' } } + Workflow: + allOf: + - $ref: '#/components/schemas/CreateWorkflow' + - type: object + properties: + id: { type: string } + tenant_id: { type: string } + created_at: { type: string, format: date-time } + updated_at: { type: string, format: date-time } + ExecuteWorkflow: + type: object + additionalProperties: false + required: [context] + properties: { context: { type: object, additionalProperties: true } } + Projection: + type: object + required: [projection_name, entity_id, payload] + properties: + projection_name: { type: string, enum: [loan_activity, ledger_activity, product_publication] } + entity_id: { type: string } + payload: { type: object, additionalProperties: true } + last_event_id: { type: string } + last_event_type: { type: string } + last_event_version: { type: integer } + updated_at: { type: string, format: date-time } + additionalProperties: true + ProjectionStatus: + type: object + required: [projection_name] + properties: + projection_name: { type: string } + last_event_id: { type: string } + last_occurred_at: { type: string, format: date-time } + updated_at: { type: string, format: date-time } + lag_seconds: { type: number, minimum: 0 } + additionalProperties: true + responses: + BadRequest: { description: Request contract or Idempotency-Key is invalid, content: { application/json: { schema: { $ref: '#/components/schemas/HttpError' } } } } + Unauthorized: { description: 'Bearer token is missing, expired, invalid, or issued for another audience', content: { application/json: { schema: { $ref: '#/components/schemas/HttpError' } } } } + Forbidden: { description: 'Permission, maker-checker, institution, or tenant policy denied the operation', content: { application/json: { schema: { $ref: '#/components/schemas/HttpError' } } } } + NotFound: { description: Tenant-scoped resource was not found, content: { application/json: { schema: { $ref: '#/components/schemas/HttpError' } } } } + Conflict: { description: State conflict or Idempotency-Key reuse with a different payload, content: { application/json: { schema: { $ref: '#/components/schemas/HttpError' } } } } diff --git a/openapi/workbench.public.v1.yaml b/openapi/workbench.public.v1.yaml new file mode 100644 index 0000000..7cd1255 --- /dev/null +++ b/openapi/workbench.public.v1.yaml @@ -0,0 +1,434 @@ +openapi: 3.1.0 +info: + title: MAVULA Workbench API + version: 1.0.0 + description: | + Authenticated operational API for tenant-scoped jobs, platform status, and durable legacy interoperability. + Workbench orchestrates execution but does not own financial state. + license: + name: GNU Affero General Public License v3.0 only + identifier: AGPL-3.0-only +servers: + - url: https://workbench.mavula.dev + description: Workbench public endpoint +security: [{ bearerAuth: [] }] +tags: + - name: Jobs + description: Submit supported payment work and inspect durable execution state. + - name: Legacy interoperability + description: Generate regulatory exports and validate inbound fixed-width files. + - name: Status + description: Read authenticated platform, queue, and schedule status. +paths: + /api/jobs: + post: + operationId: createJob + summary: Submit a payment job + description: Submit tenant-scoped payment work. The tenant is always derived from the access token. + tags: [Jobs] + x-mavula-permissions: [workbench.jobs.write] + requestBody: + required: true + content: + application/json: + schema: { $ref: '#/components/schemas/CreateJob' } + examples: + payment_capture: + value: + queue: payments + type: PAYMENT_CAPTURE + max_attempts: 3 + payload: + idempotency_key: payment_capture_20260715_001 + correlation_id: checkout_20260715_001 + rail: mpesa + amount: { currency: MZN, valueMinor: 125000 } + payer: { accountRef: customer_001, phoneNumber: '+258840000001' } + payee: { accountRef: merchant_001 } + responses: + '201': + description: Job accepted + content: { application/json: { schema: { $ref: '#/components/schemas/WorkerJob' } } } + '400': { $ref: '#/components/responses/BadRequest' } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + /api/jobs/{jobId}: + get: + operationId: getJob + summary: Read job status + description: Read current status, attempts, result, and final failure details for a tenant-scoped job. + tags: [Jobs] + x-mavula-permissions: [workbench.read] + parameters: + - { in: path, name: jobId, required: true, schema: { type: string } } + responses: + '200': + description: Tenant-scoped job status + content: { application/json: { schema: { $ref: '#/components/schemas/WorkerJob' } } } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + '404': { $ref: '#/components/responses/NotFound' } + /api/regulatory-exports: + post: + operationId: createRegulatoryExport + summary: Request a regulatory export + description: Create an idempotent export receipt and queue generation from posted Ledger Core transactions. + tags: [Legacy interoperability] + x-mavula-permissions: [compliance.manage] + parameters: + - { $ref: '#/components/parameters/IdempotencyKey' } + - { $ref: '#/components/parameters/CorrelationId' } + requestBody: + required: true + content: + application/json: + schema: { $ref: '#/components/schemas/CreateRegulatoryExport' } + example: + period_from: '2026-07-01' + period_to: '2026-07-31' + legal_basis_code: MZ-AML-14-2023-ART-43 + retention_until: '2036-07-31' + responses: + '201': { $ref: '#/components/responses/LegacyBatchCreated' } + '400': { $ref: '#/components/responses/BadRequest' } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + '409': { $ref: '#/components/responses/Conflict' } + /api/legacy-imports: + post: + operationId: createLegacyImport + summary: Stage and validate a legacy file + description: Store an inbound fixed-width file and queue validation. Imports never post ledger or lending effects. + tags: [Legacy interoperability] + x-mavula-permissions: [compliance.manage] + parameters: + - { $ref: '#/components/parameters/IdempotencyKey' } + - { $ref: '#/components/parameters/CorrelationId' } + requestBody: + required: true + content: + multipart/form-data: + schema: + type: object + additionalProperties: false + required: [file] + properties: + file: + type: string + format: binary + description: US-ASCII file no larger than 10 MiB and 5,000 detail records. + responses: + '201': { $ref: '#/components/responses/LegacyBatchCreated' } + '400': { $ref: '#/components/responses/BadRequest' } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + '409': { $ref: '#/components/responses/Conflict' } + /api/legacy-batches: + get: + operationId: listLegacyBatches + summary: List legacy batches + description: List durable export and import receipts for the authenticated tenant. + tags: [Legacy interoperability] + x-mavula-permissions: [compliance.manage] + responses: + '200': + description: Tenant-scoped batch receipts + content: { application/json: { schema: { type: array, items: { $ref: '#/components/schemas/LegacyBatchReceipt' } } } } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + /api/legacy-batches/{batchId}: + get: + operationId: getLegacyBatch + summary: Read a legacy batch + description: Read durable state, attempt count, totals, delivery evidence, and failure reason. + tags: [Legacy interoperability] + x-mavula-permissions: [compliance.manage] + parameters: [{ $ref: '#/components/parameters/BatchId' }] + responses: + '200': { description: Batch receipt, content: { application/json: { schema: { $ref: '#/components/schemas/LegacyBatchReceipt' } } } } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + '404': { $ref: '#/components/responses/NotFound' } + /api/legacy-batches/{batchId}/artifact: + get: + operationId: downloadLegacyBatchArtifact + summary: Download a generated artifact + description: Download the immutable US-ASCII fixed-width file. Verify the HTTP ETag and trailer checksum before delivery. + tags: [Legacy interoperability] + x-mavula-permissions: [compliance.manage] + parameters: [{ $ref: '#/components/parameters/BatchId' }] + responses: + '200': + description: US-ASCII fixed-width artifact + headers: + ETag: { description: SHA-256 digest of the complete artifact., schema: { type: string } } + Content-Disposition: { description: Server-generated safe filename., schema: { type: string } } + Content-Length: { schema: { type: integer } } + content: { text/plain: { schema: { type: string, format: binary } } } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + '404': { $ref: '#/components/responses/NotFound' } + /api/legacy-batches/{batchId}/rejections: + get: + operationId: getLegacyBatchRejections + summary: Read deterministic rejections + description: Read stable record, field, code, and reference details for rejected source or import records. + tags: [Legacy interoperability] + x-mavula-permissions: [compliance.manage] + parameters: [{ $ref: '#/components/parameters/BatchId' }] + responses: + '200': + description: Deterministic rejection report + content: { application/json: { schema: { $ref: '#/components/schemas/LegacyRejectionReport' } } } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + '404': { $ref: '#/components/responses/NotFound' } + /api/regulatory-exports/{batchId}/delivery: + post: + operationId: recordRegulatoryExportDelivery + summary: Record authority delivery + description: Mark a generated export as delivered and retain the external authority reference as evidence. + tags: [Legacy interoperability] + x-mavula-permissions: [compliance.manage] + parameters: + - { $ref: '#/components/parameters/BatchId' } + - { $ref: '#/components/parameters/IdempotencyKey' } + - { $ref: '#/components/parameters/CorrelationId' } + requestBody: + required: true + content: + application/json: + schema: { $ref: '#/components/schemas/RecordExportDelivery' } + example: { authority_reference: BM-REPORT-2026-07-001, delivered_at: '2026-08-02T09:00:00Z' } + responses: + '201': + description: Export receipt in DELIVERED state + content: { application/json: { schema: { $ref: '#/components/schemas/LegacyBatchReceipt' } } } + '400': { $ref: '#/components/responses/BadRequest' } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + '404': { $ref: '#/components/responses/NotFound' } + '409': { $ref: '#/components/responses/Conflict' } + /api/status: + get: + operationId: getPlatformStatus + summary: Read platform status + tags: [Status] + x-mavula-permissions: [workbench.read] + responses: + '200': { description: Worker and dependency status, content: { application/json: { schema: { $ref: '#/components/schemas/PlatformStatus' } } } } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + /api/status/queues: + get: + operationId: getQueueStatus + summary: Read queue status + tags: [Status] + x-mavula-permissions: [workbench.read] + responses: + '200': { description: Queue status, content: { application/json: { schema: { type: array, items: { $ref: '#/components/schemas/QueueStats' } } } } } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } + /api/status/schedules: + get: + operationId: getScheduleStatus + summary: Read registered schedules + tags: [Status] + x-mavula-permissions: [workbench.read] + responses: + '200': { description: Registered schedules, content: { application/json: { schema: { type: array, items: { $ref: '#/components/schemas/ScheduledJob' } } } } } + '401': { $ref: '#/components/responses/Unauthorized' } + '403': { $ref: '#/components/responses/Forbidden' } +components: + securitySchemes: + bearerAuth: { type: http, scheme: bearer, bearerFormat: JWT } + parameters: + BatchId: { in: path, name: batchId, required: true, schema: { type: string, format: uuid } } + IdempotencyKey: { in: header, name: Idempotency-Key, required: true, description: Reuse only with an identical request., schema: { type: string, minLength: 1, maxLength: 255 } } + CorrelationId: { in: header, name: X-Correlation-ID, required: true, schema: { type: string, minLength: 1, maxLength: 128, pattern: '^[A-Za-z0-9._:-]+$' } } + schemas: + MoneyMinor: + type: object + additionalProperties: false + required: [currency, valueMinor] + properties: + currency: { type: string, const: MZN } + valueMinor: { type: integer, minimum: 1, description: Amount in centavos. } + PaymentParty: + type: object + additionalProperties: false + required: [accountRef] + properties: + accountRef: { type: string } + displayName: { type: string } + phoneNumber: { type: string } + PaymentStartPayload: + type: object + additionalProperties: true + required: [idempotency_key, correlation_id, rail, amount, payer, payee] + properties: + idempotency_key: { type: string } + correlation_id: { type: string } + rail: { type: string, enum: [mpesa, emola, mkesh, bank_transfer] } + amount: { $ref: '#/components/schemas/MoneyMinor' } + payer: { $ref: '#/components/schemas/PaymentParty' } + payee: { $ref: '#/components/schemas/PaymentParty' } + provider_reference: { type: string } + metadata: { type: object, additionalProperties: { type: string } } + PaymentSettlementPayload: + type: object + additionalProperties: true + required: [provider_reference, provider_event_id, status] + properties: + provider_reference: { type: string } + provider_event_id: { type: string } + status: { type: string, enum: [pending, succeeded, failed] } + failure_reason: { type: string } + PaymentReconciliationPayload: + type: object + additionalProperties: false + properties: { limit: { type: integer, minimum: 1, maximum: 500 } } + CreateJob: + type: object + additionalProperties: false + required: [type, payload] + properties: + type: { type: string, enum: [PAYMENT_CAPTURE, PAYMENT_DISBURSEMENT, PAYMENT_SETTLEMENT, PAYMENT_RECONCILIATION] } + queue: { type: string, const: payments, default: payments } + payload: + oneOf: + - $ref: '#/components/schemas/PaymentStartPayload' + - $ref: '#/components/schemas/PaymentSettlementPayload' + - $ref: '#/components/schemas/PaymentReconciliationPayload' + max_attempts: { type: integer, minimum: 1, default: 3 } + WorkerJob: + type: object + required: [id, queue, type, tenant_id, payload, status, attempts, max_attempts, created_at, updated_at] + properties: + id: { type: string } + queue: { type: string } + type: { type: string } + tenant_id: { type: string } + payload: { type: object, additionalProperties: true } + status: { type: string, enum: [QUEUED, PROCESSING, COMPLETED, FAILED] } + attempts: { type: integer, minimum: 0 } + max_attempts: { type: integer, minimum: 1 } + result: { type: object, additionalProperties: true } + last_error: { type: string } + created_at: { type: string, format: date-time } + updated_at: { type: string, format: date-time } + started_at: { type: string, format: date-time } + completed_at: { type: string, format: date-time } + failed_at: { type: string, format: date-time } + CreateRegulatoryExport: + type: object + additionalProperties: false + required: [period_from, period_to, legal_basis_code, retention_until] + properties: + period_from: { type: string, format: date } + period_to: { type: string, format: date } + generated_at: { type: string, format: date-time } + legal_basis_code: { type: string, minLength: 1, maxLength: 64 } + retention_until: { type: string, format: date, description: Must preserve at least the required ten-year retention period. } + RecordExportDelivery: + type: object + additionalProperties: false + required: [authority_reference] + properties: + authority_reference: { type: string, minLength: 1, maxLength: 255 } + delivered_at: { type: string, format: date-time } + LegacyRejection: + type: object + required: [record, field, code] + properties: + record: { type: integer, minimum: 1 } + field: { type: string } + code: { type: string } + reference: { type: string } + LegacyRejectionReport: + type: object + required: [batch_id, rejections] + properties: + batch_id: { type: string, format: uuid } + rejections: { type: array, items: { $ref: '#/components/schemas/LegacyRejection' } } + LegacyBatchReceipt: + type: object + required: [id, tenant_id, institution_id, direction, contract_id, state, correlation_id, attempts, max_attempts, created_at, updated_at] + properties: + id: { type: string, format: uuid } + tenant_id: { type: string } + institution_id: { type: string } + direction: { type: string, enum: [EXPORT, IMPORT] } + contract_id: { type: string, const: 'legacy.regulatory_transaction_export@1' } + state: { type: string, enum: [QUEUED, PROCESSING, GENERATED, VALIDATED, REJECTED, FAILED, DELIVERED] } + correlation_id: { type: string } + source_count: { type: integer, minimum: 0 } + record_count: { type: integer, minimum: 0 } + total_amount_minor: { type: string, pattern: '^[0-9]+$' } + content_sha256: { type: string, pattern: '^[a-f0-9]{64}$' } + attempts: { type: integer, minimum: 0 } + max_attempts: { type: integer, minimum: 1 } + rejection_report: { type: array, items: { $ref: '#/components/schemas/LegacyRejection' } } + delivered_at: { type: string, format: date-time } + authority_reference: { type: string } + failure_reason: { type: string } + created_at: { type: string, format: date-time } + updated_at: { type: string, format: date-time } + QueueStats: + type: object + required: [queue, queued, processing, delayed, dead_letter, total, completed, failed] + properties: + queue: { type: string } + queued: { type: integer } + processing: { type: integer } + delayed: { type: integer } + dead_letter: { type: integer } + total: { type: integer } + completed: { type: integer } + failed: { type: integer } + ScheduledJob: + type: object + required: [id, queue, type, every_ms, payload] + properties: + id: { type: string } + queue: { type: string } + type: { type: string } + every_ms: { type: integer, minimum: 1 } + payload: { type: object, additionalProperties: true } + PlatformStatus: + type: object + properties: + service: { type: string } + status: { type: string, enum: [ok, degraded, down] } + timestamp: { type: string, format: date-time } + worker: { type: object, additionalProperties: true } + dependencies: { type: object, additionalProperties: true } + HttpError: + type: object + required: [statusCode, message] + properties: + statusCode: { type: integer } + message: + oneOf: + - { type: string } + - { type: array, items: { type: string } } + error: { type: string } + responses: + LegacyBatchCreated: + description: Durable batch receipt + content: { application/json: { schema: { $ref: '#/components/schemas/LegacyBatchReceipt' } } } + BadRequest: + description: Request contract is invalid + content: { application/json: { schema: { $ref: '#/components/schemas/HttpError' } } } + Unauthorized: + description: Bearer token is missing or invalid + content: { application/json: { schema: { $ref: '#/components/schemas/HttpError' } } } + Forbidden: + description: Required permission or tenant boundary is not satisfied + content: { application/json: { schema: { $ref: '#/components/schemas/HttpError' } } } + NotFound: + description: Tenant-scoped resource was not found + content: { application/json: { schema: { $ref: '#/components/schemas/HttpError' } } } + Conflict: + description: Idempotency key, state, or delivery reference conflicts with existing state + content: { application/json: { schema: { $ref: '#/components/schemas/HttpError' } } } diff --git a/package.json b/package.json index 5e4b963..2907cfa 100644 --- a/package.json +++ b/package.json @@ -7,5 +7,21 @@ "license": "AGPL-3.0-only", "packageManager": "pnpm@10.33.0", "engines": { "node": "22.22.3", "pnpm": "10.33.0" }, - "scripts": { "guardian:check": "node scripts/guardian.mjs" } + "scripts": { + "dev": "astro dev", + "preview": "astro preview", + "guardian:check": "node scripts/guardian.mjs", + "contracts:check": "node scripts/check-contracts.mjs", + "build": "node scripts/build-docs.mjs", + "test": "node --test test/*.test.mjs", + "test:e2e": "playwright test" + }, + "devDependencies": { + "@astrojs/starlight": "0.41.3", + "@playwright/test": "1.59.1", + "@redocly/cli": "2.39.0", + "@scalar/api-reference": "1.62.6", + "astro": "7.0.9", + "yaml": "2.9.0" + } } diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 0000000..a30abca --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,24 @@ +import { defineConfig, devices } from '@playwright/test'; + +export default defineConfig({ + testDir: './test/e2e', + outputDir: '.playwright/results', + reporter: [['list'], ['html', { outputFolder: '.playwright/report', open: 'never' }]], + use: { + baseURL: 'http://127.0.0.1:4321/developer-docs', + trace: 'retain-on-failure', + launchOptions: { + executablePath: process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH, + }, + }, + projects: [ + { name: 'desktop', use: { ...devices['Desktop Chrome'], viewport: { width: 1440, height: 1000 } } }, + { name: 'mobile', use: { ...devices['Pixel 7'] } }, + ], + webServer: { + command: 'node_modules/.bin/astro preview --host 127.0.0.1 --port 4321', + url: 'http://127.0.0.1:4321/developer-docs/', + reuseExistingServer: true, + timeout: 60_000, + }, +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..fae5c27 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,5898 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + devDependencies: + '@astrojs/starlight': + specifier: 0.41.3 + version: 0.41.3(@astrojs/markdown-remark@7.2.1)(astro@7.0.9(@astrojs/markdown-remark@7.2.1)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)(@types/node@24.13.3)(yaml@2.9.0)) + '@playwright/test': + specifier: 1.59.1 + version: 1.59.1 + '@redocly/cli': + specifier: 2.39.0 + version: 2.39.0 + '@scalar/api-reference': + specifier: 1.62.6 + version: 1.62.6(tailwindcss@4.3.2)(zod@4.4.3) + astro: + specifier: 7.0.9 + version: 7.0.9(@astrojs/markdown-remark@7.2.1)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)(@types/node@24.13.3)(yaml@2.9.0) + yaml: + specifier: 2.9.0 + version: 2.9.0 + +packages: + + '@ai-sdk/gateway@3.0.13': + resolution: {integrity: sha512-g7nE4PFtngOZNZSy1lOPpkC+FAiHxqBJXqyRMEG7NUrEVZlz5goBdtHg1YgWRJIX776JTXAmbOI5JreAKVAsVA==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/provider-utils@4.0.5': + resolution: {integrity: sha512-Ow/X/SEkeExTTc1x+nYLB9ZHK2WUId8+9TlkamAx7Tl9vxU+cKzWx2dwjgMHeCN6twrgwkLrrtqckQeO4mxgVA==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/provider@3.0.2': + resolution: {integrity: sha512-HrEmNt/BH/hkQ7zpi2o6N3k1ZR1QTb7z85WYhYygiTxOQuaml4CMtHCWRbric5WPU+RNsYI7r1EpyVQMKO1pYw==} + engines: {node: '>=18'} + + '@ai-sdk/vue@3.0.33': + resolution: {integrity: sha512-czM9Js3a7f+Eo35gjEYEeJYUoPvMg5Dfi4bOLyDBghLqn0gaVg8yTmTaSuHCg+3K/+1xPjyXd4+2XcQIohWWiQ==} + engines: {node: '>=18'} + peerDependencies: + vue: ^3.3.4 + + '@astrojs/compiler-binding-darwin-arm64@0.3.1': + resolution: {integrity: sha512-IEmEF2fUIlTHtpeE/isyEGVOB14cEyh/LZOFYt6wn3jNyVpdC8aR5OZ+RzFUR/f+8ZDM1LaMwZKvoA7eMyJeFw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@astrojs/compiler-binding-darwin-x64@0.3.1': + resolution: {integrity: sha512-GF2kIxjpPDLsn94zbZNMsxEmkU828QqnmM7kiQJnaooS3jmI+I7kk6+oI6EpwOsK3femCMdcm+wmOsEqtGrmjQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@astrojs/compiler-binding-linux-arm64-gnu@0.3.1': + resolution: {integrity: sha512-XJL3SDmOtVrqFhCirNcHwE91+IesJqlgNo23I4qW9QUYfwzm/TBZuH61fgqsb1ttgR1mMYz6ooPWs0JDhwMqpQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@astrojs/compiler-binding-linux-arm64-musl@0.3.1': + resolution: {integrity: sha512-xqE8BVbDoBueK/B47w30PtkVofUWJKGkwoMVE+EOMLf11rnoANxIAdA9FPqY+rng4oNI5ndHGsri1yPj2k8vZQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@astrojs/compiler-binding-linux-x64-gnu@0.3.1': + resolution: {integrity: sha512-1y0StU1qiCuDFH3rmbRJXcxdfHxFPrES1Rd+RLffosvUR7I2cH5SF5SFnBN9vXpzpkmyElZm3Yr47iJBPN7vVA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@astrojs/compiler-binding-linux-x64-musl@0.3.1': + resolution: {integrity: sha512-16q0fYf7kpbmdObZEeZJEup8hQv/whgNwVjrSvT8umrKwLDSnNIWiQpm09lQQu6bweZB0XyIvHwlPitvJhC+hg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@astrojs/compiler-binding-wasm32-wasi@0.3.1': + resolution: {integrity: sha512-cB456shIwDv/PrVT+2QG7LFndpHkVge5HjqADKZgGaAc9JHVktCtjSrcdkRQ+3tbkPazNKaTLRjXLIiz2NIx9g==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@astrojs/compiler-binding-win32-arm64-msvc@0.3.1': + resolution: {integrity: sha512-ur/9+If/yTE69mmeX5MqSZndL0HOyx67GeNZUy3N7wVdWpLz9UTJXwyWS4UR2PUQHitghjsM5xoX0Ge56WRVQQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@astrojs/compiler-binding-win32-x64-msvc@0.3.1': + resolution: {integrity: sha512-k0W+kDBzDkNZOqu4kElDvCOIbKw5Ut9S1WZ1Krj3KTgNuBERNKXsMMsRLLcbgfdMdbe7bTekQLshZrrvmYpmwA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@astrojs/compiler-binding@0.3.1': + resolution: {integrity: sha512-DaAUj29AIBU2XdJ8uwcab8lW5O2pk9pY8AXkcMw0sw77nVa3oeTYRcO+Dvbbpoexf6ThMc0FMWYCQ/wN1/T7oQ==} + engines: {node: ^20.19.0 || >=22.12.0} + + '@astrojs/compiler-rs@0.3.1': + resolution: {integrity: sha512-aT7xkgsbNoS6nriY5qKpbihK43slFHO41iqgHCTdOvn1ifaQxLCc5yXy+6GzAtiafoaC1zA7OwVXCXMsvUZOkg==} + engines: {node: '>=22.12.0'} + + '@astrojs/internal-helpers@0.10.1': + resolution: {integrity: sha512-5phcroT/vmOOrYuuAxtkbPixy5hePtlz9i8K4OeDv3dNK6/UQRuXPOSRTxIOBbUY5Sonw2UaxjbuVc43Mcir6Q==} + + '@astrojs/markdown-remark@7.2.1': + resolution: {integrity: sha512-jPVNIqTvk+yKviikszv/Y1U4jGUSKpp/Nw48QZV4qjWgp70j4Lkq3lhSDRbWwCfgKvEyO9GHuVbV1dM2WYXy1w==} + + '@astrojs/markdown-satteri@0.3.4': + resolution: {integrity: sha512-6Lvt/bQZEBW+zzdhPblvfZEy5PGEYJaUsUqaCgwHeRPxZJL1gc9I+DRLKWJjjYTWDzVUTzXlMq4WwSK+X34CVw==} + + '@astrojs/mdx@7.0.3': + resolution: {integrity: sha512-RxyIwU0uFam5ftwqKOjpIdhnFxZ/kEikeimLyQy3eGXbHT8WgRGzzesOIHVU8+m9TY8ag5WVOyvV24/GyqPdPQ==} + engines: {node: '>=22.12.0'} + peerDependencies: + '@astrojs/markdown-satteri': ^0.3.1 + astro: ^7.0.0 + peerDependenciesMeta: + '@astrojs/markdown-satteri': + optional: true + + '@astrojs/prism@4.0.2': + resolution: {integrity: sha512-KTivpmnz6lDsC6o9H4+DNm2SrE/GHzw8cNAvEJwAvUT+eoaEnn/4NtbDNfRRaxaJHdp15gf+tfHAWiXR4wB3BA==} + engines: {node: '>=22.12.0'} + + '@astrojs/sitemap@3.7.3': + resolution: {integrity: sha512-f8euLVsyeAmAkSm/1M2Kb8sL8byQmfgbvBNaHFItCheTj/IpiJYSEWVcqDHZ/yEHxiS7+w87mQkzwZaPHmk5GA==} + + '@astrojs/starlight@0.41.3': + resolution: {integrity: sha512-8xsG6UpK581TJmtOc7/pnxHKEbP16rV06VLWaVa7FOyE/VEwnaHOsLtL+miifCEfuiuv0Wn+j8u3JSluRQesMQ==} + peerDependencies: + '@astrojs/markdown-remark': ^7.2.0 + astro: ^7.0.2 + peerDependenciesMeta: + '@astrojs/markdown-remark': + optional: true + + '@astrojs/telemetry@3.3.3': + resolution: {integrity: sha512-C1TLn5sPJr0x4vk56piHWKbnqlEB8BKyte5Y45V02U+D7BGO5eMqZDH5aPjnkXQWJggvmsTXxH03QMZ9NgWLzQ==} + engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0} + + '@babel/helper-string-parser@7.29.7': + resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.29.7': + resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.29.7': + resolution: {integrity: sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/types@7.29.7': + resolution: {integrity: sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==} + engines: {node: '>=6.9.0'} + + '@bruits/satteri-darwin-arm64@0.9.5': + resolution: {integrity: sha512-iw4nZgx9v30lWo/MTngQqi1pI78KI0DnkSm+lVJGYdmPLgAyDNJigVhpG42/Iq55A6c1Ll8q66ljyyRiQUxwow==} + cpu: [arm64] + os: [darwin] + + '@bruits/satteri-darwin-x64@0.9.5': + resolution: {integrity: sha512-6T26Z5Kf3cFW2PSlk9p7zT7yVxvuBSiJvYyz9u8KjYwMTqZyIDOj2wDyNpxKV4+6yUVG7rddq2QwvG/8LJA2+Q==} + cpu: [x64] + os: [darwin] + + '@bruits/satteri-linux-arm64-gnu@0.9.5': + resolution: {integrity: sha512-u51id17uJwNEMK9nBlICsq6U31c+XVqQueVBkwRIzZG+gMpS8TOJctt5h5Wz33Z8xnMdTd+adtACVz0yHgGuOA==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@bruits/satteri-linux-arm64-musl@0.9.5': + resolution: {integrity: sha512-v39HxiwGC5Rqm01HksP6+5Y+xKLPlsuVFgIgpEAo+SiQ22c+mJVhS3u7Z6ePAKdhL5NJoK1xq70kLz3L13AhpQ==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@bruits/satteri-linux-x64-gnu@0.9.5': + resolution: {integrity: sha512-F3uO8uFp3pAP5ZGXttwvh57GS7s0lL953tnNdyI2gRyP4kOOkp6pyGojNJzCjkDvWI2Cvb9iNrKok3aqQPauAw==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@bruits/satteri-linux-x64-musl@0.9.5': + resolution: {integrity: sha512-bicEqglLlz++mWyADaZoP0JY20s4vDfLjaPYgQqC+NI4zZLTOOg1T4GB8aqtc822Pqji8SQBmSrTb7CrP8i08Q==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@bruits/satteri-wasm32-wasi@0.9.5': + resolution: {integrity: sha512-zauAuMwfPnKPUkd4AFixRFpXdgKwP2mKgxrIIo2gJzW0/ZneF9dbHnLkojSpaBnCCp7VUL1hIi5WWZvB1CqmAQ==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@bruits/satteri-win32-arm64-msvc@0.9.5': + resolution: {integrity: sha512-SrfE7NEsgZjBvU3c+RR6oQRu0ToXY5uVJEbieXEF0YTctIV2zAVlbaMjWLts074QCgh3a+XHWkR/lWh2VH2LUg==} + cpu: [arm64] + os: [win32] + + '@bruits/satteri-win32-x64-msvc@0.9.5': + resolution: {integrity: sha512-5Kw9ZAtTGS8WHizyn+CJhjjfIQrw+7jcZodpmpXJjefnO15M8UexIi6JR2E5thyvsmHyhL6ZDDMUNR4bKJPd4g==} + cpu: [x64] + os: [win32] + + '@capsizecss/unpack@4.0.1': + resolution: {integrity: sha512-CuNiSqg7+e1cO/GjffyMOm5Tt2jUF9CWHHnvQ/UkqvtkGfHdgwEC0wpmq7fkN3gxwpRnrAN0WzO3vREKmNolMQ==} + engines: {node: '>=18'} + + '@clack/core@1.4.3': + resolution: {integrity: sha512-/kr3UWNtdJfxZtPgDqUOmG2pvwlmcLGheex5yiZKdwbzZJxhV+HMNR9QNmyY5cGwTNV6LrR7Jtp+KjhUAP1qBQ==} + engines: {node: '>= 20.12.0'} + + '@clack/prompts@1.7.0': + resolution: {integrity: sha512-y7/yvZ2TPAnR9+jnc00klvNNLkJiXFFrQA/hlLCcxA9a2A4zQIOimyFQ9XfwYKiGD1fb5GY8vbKIIgO8d5Tb2A==} + engines: {node: '>= 20.12.0'} + + '@codemirror/autocomplete@6.20.3': + resolution: {integrity: sha512-tlosUqb+3BbxCxZdu4tKeRghPFC+QM7q4X5YhKV2eCmPG+1r2F3f4AaSz5sCrFqUtX4Jh20VFTKecl16MgiV9g==} + + '@codemirror/commands@6.10.4': + resolution: {integrity: sha512-Ryk9y9T0FFVF0cUGhAknveAyUOl/A1qReTFi+qPKtOh2Z9F4AUBz3XOrYD4ZEgZirdugVzHvd/2/Wcwy5OliTg==} + + '@codemirror/lang-css@6.3.1': + resolution: {integrity: sha512-kr5fwBGiGtmz6l0LSJIbno9QrifNMUusivHbnA1H6Dmqy4HZFte3UAICix1VuKo0lMPKQr2rqB+0BkKi/S3Ejg==} + + '@codemirror/lang-html@6.4.11': + resolution: {integrity: sha512-9NsXp7Nwp891pQchI7gPdTwBuSuT3K65NGTHWHNJ55HjYcHLllr0rbIZNdOzas9ztc1EUVBlHou85FFZS4BNnw==} + + '@codemirror/lang-javascript@6.2.5': + resolution: {integrity: sha512-zD4e5mS+50htS7F+TYjBPsiIFGanfVqg4HyUz6WNFikgOPf2BgKlx+TQedI1w6n/IqRBVBbBWmGFdLB/7uxO4A==} + + '@codemirror/lang-json@6.0.2': + resolution: {integrity: sha512-x2OtO+AvwEHrEwR0FyyPtfDUiloG3rnVTSZV1W8UteaLL8/MajQd8DpvUb2YVzC+/T18aSDv0H9mu+xw0EStoQ==} + + '@codemirror/lang-xml@6.1.0': + resolution: {integrity: sha512-3z0blhicHLfwi2UgkZYRPioSgVTo9PV5GP5ducFH6FaHy0IAJRg+ixj5gTR1gnT/glAIC8xv4w2VL1LoZfs+Jg==} + + '@codemirror/lang-yaml@6.1.3': + resolution: {integrity: sha512-AZ8DJBuXGVHybpBQhmZtgew5//4hv3tdkXnr3vDmOUMJRuB6vn/uuwtmTOTlqEaQFg3hQSVeA90NmvIQyUV6FQ==} + + '@codemirror/language@6.12.4': + resolution: {integrity: sha512-1q4PaT+o6PbgpkJt4Q8Fv5XJxTy4FUZ4MWETtyiDw3J0Pyr9E2vqcKL+k9wcvjNTIsauxvE7OfmWj3FRPHQ76A==} + + '@codemirror/lint@6.9.7': + resolution: {integrity: sha512-28/+iWLYxKxsvGYhSYL7zaCZqLz5+FFFDq9tVsvGv9kv8RY4fFAchJ5WX9M3YrrRlTIsECjsXPqeNgnSmNP2dg==} + + '@codemirror/state@6.7.1': + resolution: {integrity: sha512-9QzNDgE4EYDnAHfrTlR2lwiPciiOymLtwKK+8yHQzCc7GXhAP9xdEbEJFy2IWB1j9UGUl9BsgMmTo/ImA02T7A==} + + '@codemirror/view@6.43.6': + resolution: {integrity: sha512-EVunGSYN1wz1p75WY1s3Xg7t3i8Yol0kGZGizNdX9BUFgMFILYVe8/u6EVpo7Ff5PwbZuILb4QAq7IZoKzIEQA==} + + '@ctrl/tinycolor@4.2.0': + resolution: {integrity: sha512-kzyuwOAQnXJNLS9PSyrk0CWk35nWJW/zl/6KvnTBMFK65gm7U1/Z5BqjxeapjZCIhQcM/DsrEmcbRwDyXyXK4A==} + engines: {node: '>=14'} + + '@emnapi/core@1.11.1': + resolution: {integrity: sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==} + + '@emnapi/runtime@1.11.1': + resolution: {integrity: sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==} + + '@emnapi/runtime@1.11.2': + resolution: {integrity: sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA==} + + '@emnapi/wasi-threads@1.2.2': + resolution: {integrity: sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==} + + '@esbuild/aix-ppc64@0.28.1': + resolution: {integrity: sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.28.1': + resolution: {integrity: sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.28.1': + resolution: {integrity: sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.28.1': + resolution: {integrity: sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.28.1': + resolution: {integrity: sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.28.1': + resolution: {integrity: sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.28.1': + resolution: {integrity: sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.28.1': + resolution: {integrity: sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.28.1': + resolution: {integrity: sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.28.1': + resolution: {integrity: sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.28.1': + resolution: {integrity: sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.28.1': + resolution: {integrity: sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.28.1': + resolution: {integrity: sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.28.1': + resolution: {integrity: sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.28.1': + resolution: {integrity: sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.28.1': + resolution: {integrity: sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.28.1': + resolution: {integrity: sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.28.1': + resolution: {integrity: sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.28.1': + resolution: {integrity: sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.28.1': + resolution: {integrity: sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.28.1': + resolution: {integrity: sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.28.1': + resolution: {integrity: sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.28.1': + resolution: {integrity: sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.28.1': + resolution: {integrity: sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.28.1': + resolution: {integrity: sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.28.1': + resolution: {integrity: sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@expressive-code/core@0.44.0': + resolution: {integrity: sha512-xgiF2P6tYUbrhi3+x0S8xHZWT1t3Bvb3U91tAtRbLb9HLejLvYc5GZUqKICKLaUN4iSGhhNJu2fM/aH8e5yCMg==} + + '@expressive-code/plugin-frames@0.44.0': + resolution: {integrity: sha512-V6M6+zVc1GzqCvXkQHc2m5rcFOIVzJgMq5gnfrMnVf2gwtj/sg4H93c1f/mGeqHycubwkHFUDyParAOiGeDZeA==} + + '@expressive-code/plugin-shiki@0.44.0': + resolution: {integrity: sha512-RZsdaqlbGqyAQKuoX4myQXxjmiE2l5KBpJ/gKPh62tCdIdpWyjbzVqSo8+5XsezZxkfi8AJ/J6EUaBTPROFX/Q==} + + '@expressive-code/plugin-text-markers@0.44.0': + resolution: {integrity: sha512-0/m3A5b+lz2upyNq+wzZ1S69HRoJmyFs5LsR42lVZ9pmGRlBiSBYQpvqlji4DBj1+Riamxc0AvcCr5kuzOQeWA==} + + '@floating-ui/core@1.8.0': + resolution: {integrity: sha512-0CIZ5itps/8x7BG8dEIhs53BvCUH2PCoogtakwRTut+Arm58sJooJ0AuZhLw2HJYIR5cMLNPBSS728sPho2khQ==} + + '@floating-ui/dom@1.8.0': + resolution: {integrity: sha512-yXSrzeHZBTZadLOlfyhCkJHNeLJnHRnRInwdZ40L7ZiaAtrBwoYlsDrX3v5zB1Utk7CLfzcOVnVVWoXEky7Ceg==} + + '@floating-ui/utils@0.2.10': + resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==} + + '@floating-ui/utils@0.2.12': + resolution: {integrity: sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==} + + '@floating-ui/vue@1.1.11': + resolution: {integrity: sha512-HzHKCNVxnGS35r9fCHBc3+uCnjw9IWIlCPL683cGgM9Kgj2BiAl8x1mS7vtvP6F9S/e/q4O6MApwSHj8hNLGfw==} + + '@floating-ui/vue@1.1.9': + resolution: {integrity: sha512-BfNqNW6KA83Nexspgb9DZuz578R7HT8MZw1CfK9I6Ah4QReNWEJsXWHN+SdmOVLNGmTPDi+fDT535Df5PzMLbQ==} + + '@headlessui/tailwindcss@0.2.2': + resolution: {integrity: sha512-xNe42KjdyA4kfUKLLPGzME9zkH7Q3rOZ5huFihWNWOQFxnItxPB3/67yBI8/qBfY8nwBRx5GHn4VprsoluVMGw==} + engines: {node: '>=10'} + peerDependencies: + tailwindcss: ^3.0 || ^4.0 + + '@headlessui/vue@1.7.23': + resolution: {integrity: sha512-JzdCNqurrtuu0YW6QaDtR2PIYCKPUWq28csDyMvN4zmGccmE7lz40Is6hc3LA4HFeCI7sekZ/PQMTNmn9I/4Wg==} + engines: {node: '>=10'} + peerDependencies: + vue: ^3.2.0 + + '@img/colour@1.1.0': + resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==} + engines: {node: '>=18'} + + '@img/sharp-darwin-arm64@0.35.3': + resolution: {integrity: sha512-RMnFX7YQsMoh7lWfcM4NEHHymBX/rLuKNPVM84XE9ONPcaSCDgE7CHIHpSgPcO2xcRthgBy1HfNO319mwhIAkg==} + engines: {node: '>=20.9.0'} + cpu: [arm64] + os: [darwin] + + '@img/sharp-darwin-x64@0.35.3': + resolution: {integrity: sha512-Xo+5uFBtLN0BKqieTxiFzFPQAUlBbbH5iBKyRX/z1JrbnYsHTfKJnUfL8+p2TPXr1pXqao4eeL4Rl144uDpK9w==} + engines: {node: '>=20.9.0'} + cpu: [x64] + os: [darwin] + + '@img/sharp-freebsd-wasm32@0.35.3': + resolution: {integrity: sha512-lUxcqWIj2wMQ9BrwNjngcr1gWUr5xgaGThBRqPPalIC2n67Cqj1uPh8NnA/ZhAg8hUbKl+kVHKwgUIwe6ZYPrg==} + engines: {node: '>=20.9.0'} + os: [freebsd] + + '@img/sharp-libvips-darwin-arm64@1.3.2': + resolution: {integrity: sha512-9J6ypZFpQBj4YnePGoq/S38w6nz+vqg5WZLrLGY4YuSemdMq47GMLBPO42MzwdGwpg/agZ7xzZcFHa48xlywfg==} + cpu: [arm64] + os: [darwin] + + '@img/sharp-libvips-darwin-x64@1.3.2': + resolution: {integrity: sha512-m2pW1n6cns9VaubNwsZ+c3CRYjxNQWgJ5gPlnL1nbBcpkBvFm6SCFN5o0psFHI8w9n11NKhFkeEDns98tiqbEw==} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-linux-arm64@1.3.2': + resolution: {integrity: sha512-dqVSFynCox4C/J8kT16V7SIFAns0IjgLwkvYT7p8LQVmJ5OS5b6tI9IGflxTeuBS//zXeFIUbwt5dwxyZ17cnA==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-arm@1.3.2': + resolution: {integrity: sha512-1eMLzy92I4J6rmi4mAT8yC3HxOtniyGELlzGbNMLLeqe052ahFQ0h6LFq+lh5DsDIdYViIDst08abvSbcEdLXQ==} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-ppc64@1.3.2': + resolution: {integrity: sha512-3z0NHDxD6n5I9gc05U1eW1AyRm+Gznzq3naMrthPNqE6oYykcogW0l/jfpJdjYnuNl8R7yI9pNbE1XiUeyq0Aw==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-riscv64@1.3.2': + resolution: {integrity: sha512-bsb4rI+NldGOsXuej2r8OdSS8+zXDVaCWxyWrcv6kneTOlgAHtZABRzBBCwdsPiD90J4myNJuHpg6kA20ImW/w==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-s390x@1.3.2': + resolution: {integrity: sha512-/ABshyj8gCpyIrNXnHn4LorDJ0HHm1VhXPBlxZ8zAtfVPAaSafXPGn+sUSIRiwaSBy0mmFjSjiXI5mkcwdChKQ==} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-x64@1.3.2': + resolution: {integrity: sha512-ITPEtgffGJ0S6G9dRyw/366tJQqFRcHWPHhC+Stpg3Z8AEMrDrTr2lhdz4f/Y/HMbRh//7Z5mBzEpVdi62Oc3w==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linuxmusl-arm64@1.3.2': + resolution: {integrity: sha512-zE9EdiUzUmg5mDT5a1rk5fYJ6GWPloTwWBYDS14naqHsL+EaMpDj1AWnpLgh3u0YCORv2Tt50wrcrpYqkP97Kw==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@img/sharp-libvips-linuxmusl-x64@1.3.2': + resolution: {integrity: sha512-m0lrLiUt+lBYnCFr8qV/65yMR4E/c7/wf78I5eKTdkEakFAlZ9QlzEM3QIhhAwVeUhLAHLcCq7a7Vszq/oFNZQ==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@img/sharp-linux-arm64@0.35.3': + resolution: {integrity: sha512-QgKDspHPnrU+GQ55XPhGwyhC8acLVOOSyAvo1oVfFmrIXLkDNmGWzAfDZ4xK8oSA1qBQrALcHX0G5UZni/SuFQ==} + engines: {node: '>=20.9.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-arm@0.35.3': + resolution: {integrity: sha512-affVWCTLooy8TSxbDx2qkzuDeaWLNVBA+P//FNBirHsXpP2fuBhk5AuboYUnrDnzoXes8GFjpTx0SBFOCRg+FA==} + engines: {node: '>=20.9.0'} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-ppc64@0.35.3': + resolution: {integrity: sha512-sMd8rDxmpLOwv/7N44klFjOD5DUO7FLdjiXDI0hoxYaf7Ar262dQIEkosE98bps+5HPLtp/EvNqeqQtOycP/IA==} + engines: {node: '>=20.9.0'} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-riscv64@0.35.3': + resolution: {integrity: sha512-0Eob78yjlYPfL5vMNWAW55l3R9Y6BQS/gOfe0ZcP9mEz9ohhKSt4im1hayiknXgf8AWrFqMvJcKIdmLmEe7yeQ==} + engines: {node: '>=20.9.0'} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-s390x@0.35.3': + resolution: {integrity: sha512-KgAxQ0DxpNOq1rG2t5cgTgShJFGSuU7XO45cqC+1NVOuZnP6tlgZRuSYOfNupGkHID0o3cJOsw4DVeJpMovcGw==} + engines: {node: '>=20.9.0'} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-x64@0.35.3': + resolution: {integrity: sha512-8pqvxubL2PGdhlPy6GLqzDYMUjyRmKAwKHYKixpdJYBUK7PJ0C029XdsnpFIdgRZG68fZiGdHVWcKPvtiPB4cA==} + engines: {node: '>=20.9.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@img/sharp-linuxmusl-arm64@0.35.3': + resolution: {integrity: sha512-Vz0iQjzzcSX3HCbfwFfCSG/9SCIqyO0mH2sXyiHaAYfBk0cRsCWXRyQYX0ovCK/PAQBbTzQ0dsPQHh5MAFL59w==} + engines: {node: '>=20.9.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@img/sharp-linuxmusl-x64@0.35.3': + resolution: {integrity: sha512-6O1NPKcDVj9QEdg7Hx549EX8U0rp6yXQERqru6yRN7fGBn32UvIRJUlWnk+8xDCiG76hXVBbX82NZ/ZKr0euIg==} + engines: {node: '>=20.9.0'} + cpu: [x64] + os: [linux] + libc: [musl] + + '@img/sharp-wasm32@0.35.3': + resolution: {integrity: sha512-cZ0XkcYGpHZkqW6iCkqTcmUC0CD9DhD5d/qeZlZkfRBn6GnHniZXLUo5+9xw8Iv76YE6LQFN9YNBlKREcCG76w==} + engines: {node: '>=20.9.0'} + + '@img/sharp-webcontainers-wasm32@0.35.3': + resolution: {integrity: sha512-2rnq7bX3NzeR2T4YWgz8qiG4h3TSdMe+vN1iQXpJleSJ3SM5zQ8Fy2SyyXAWlbxpEZ2Y+Z4u1BePgJEYbSy80Q==} + engines: {node: '>=20.9.0'} + cpu: [wasm32] + + '@img/sharp-win32-arm64@0.35.3': + resolution: {integrity: sha512-4bPwFdMbeC4JQ8L8LOyWp6nsHcboP5fxkp6iPOXz2Vg49R42TuMs2whkJ5OAP4/Ul035qOzy0AecOF9VOscn4w==} + engines: {node: '>=20.9.0'} + cpu: [arm64] + os: [win32] + + '@img/sharp-win32-ia32@0.35.3': + resolution: {integrity: sha512-r53mXsBN6lFUDiST764SvgwUdHAqM4rPAiDzAmf4fLoB6X/rkfyTrLCg6+g17wJJiCmB3JYgHuUldCWUIRFSXw==} + engines: {node: ^20.9.0} + cpu: [ia32] + os: [win32] + + '@img/sharp-win32-x64@0.35.3': + resolution: {integrity: sha512-D4y1vNeZrIIJCN+uHaWVtH86B+aCrdMYYjicy9pXHvbGZeGYLLSd3wdVuC37FxVXlU1ARsk84eKWfWMXGYEqvA==} + engines: {node: '>=20.9.0'} + cpu: [x64] + os: [win32] + + '@internationalized/date@3.12.2': + resolution: {integrity: sha512-FY1Y+H64NDs+HAF6omlnWxm3mEpfgaCSWtL5l551ZZfImA+kGjPFgrnJrGjH6lfmLL0g8Z/mBu1R3kufeCp6Jw==} + + '@internationalized/number@3.6.7': + resolution: {integrity: sha512-3ji1fcrT+FPAK86UqEhB/psHixYo6niWPJtt7+qRaYFynt/BaJG8GhAPimtWUpEiVSTq8ZM8L5psMxGquiB/Vg==} + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@lezer/common@1.5.2': + resolution: {integrity: sha512-sxQE460fPZyU3sdc8lafxiPwJHBzZRy/udNFynGQky1SePYBdhkBl1kOagA9uT3pxR8K09bOrmTUqA9wb/PjSQ==} + + '@lezer/css@1.3.4': + resolution: {integrity: sha512-N+tn9tej2hPvyKgHEApMOQfHczDJCwxrRFS3SPn9QjYN+uwHvEDnCgKRrb3mxDYxRS8sKMM8fhC3+lc04Abz5Q==} + + '@lezer/highlight@1.2.3': + resolution: {integrity: sha512-qXdH7UqTvGfdVBINrgKhDsVTJTxactNNxLk7+UMwZhU13lMHaOBlJe9Vqp907ya56Y3+ed2tlqzys7jDkTmW0g==} + + '@lezer/html@1.3.13': + resolution: {integrity: sha512-oI7n6NJml729m7pjm9lvLvmXbdoMoi2f+1pwSDJkl9d68zGr7a9Btz8NdHTGQZtW2DA25ybeuv/SyDb9D5tseg==} + + '@lezer/javascript@1.5.4': + resolution: {integrity: sha512-vvYx3MhWqeZtGPwDStM2dwgljd5smolYD2lR2UyFcHfxbBQebqx8yjmFmxtJ/E6nN6u1D9srOiVWm3Rb4tmcUA==} + + '@lezer/json@1.0.3': + resolution: {integrity: sha512-BP9KzdF9Y35PDpv04r0VeSTKDeox5vVr3efE7eBbx3r4s3oNLfunchejZhjArmeieBH+nVOpgIiBJpEAv8ilqQ==} + + '@lezer/lr@1.4.10': + resolution: {integrity: sha512-rnCpTIBafOx4mRp43xOxDJbFipJm/c0cia/V5TiGlhmMa+wsSdoGmUN3w5Bqrks/09Q/D4tNAmWaT8p6NRi77A==} + + '@lezer/xml@1.0.6': + resolution: {integrity: sha512-CdDwirL0OEaStFue/66ZmFSeppuL6Dwjlk8qk153mSQwiSH/Dlri4GNymrNWnUmPl2Um7QfV1FO9KFUyX3Twww==} + + '@lezer/yaml@1.0.4': + resolution: {integrity: sha512-2lrrHqxalACEbxIbsjhqGpSW8kWpUKuY6RHgnSAFZa6qK62wvnPxA8hGOwOoDbwHcOFs5M4o27mjGu+P7TvBmw==} + + '@marijn/find-cluster-break@1.0.3': + resolution: {integrity: sha512-FY+MKLBoTsLNJF/eLWaOsXGdz6uh3Iu1axjPf6TUq92IYumcTcXWHoS747JARLkcdlJ/Waiaxc5wQfFO8jC6NA==} + + '@mdx-js/mdx@3.1.1': + resolution: {integrity: sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ==} + + '@napi-rs/wasm-runtime@1.1.6': + resolution: {integrity: sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==} + peerDependencies: + '@emnapi/core': ^1.7.1 + '@emnapi/runtime': ^1.7.1 + + '@opentelemetry/api@1.9.0': + resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} + engines: {node: '>=8.0.0'} + + '@oslojs/encoding@1.1.0': + resolution: {integrity: sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==} + + '@oxc-project/types@0.139.0': + resolution: {integrity: sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==} + + '@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] + + '@phosphor-icons/core@2.1.1': + resolution: {integrity: sha512-v4ARvrip4qBCImOE5rmPUylOEK4iiED9ZyKjcvzuezqMaiRASCHKcRIuvvxL/twvLpkfnEODCOJp5dM4eZilxQ==} + + '@playwright/test@1.59.1': + resolution: {integrity: sha512-PG6q63nQg5c9rIi4/Z5lR5IVF7yU5MqmKaPOe0HSc0O2cX1fPi96sUQu5j7eo4gKCkB2AnNGoWt7y4/Xx3Kcqg==} + engines: {node: '>=18'} + hasBin: true + + '@redocly/cli@2.39.0': + resolution: {integrity: sha512-xA0Z9YMEhlzbpn/BVErlE2UzuKfahp9llBwEnVtAYuhWdF8UCIm+cgYX8f/gHQIJ/TKwB93awAewTOgEsbZFZw==} + engines: {node: '>=22.12.0 || >=20.19.0 <21.0.0', npm: '>=10'} + hasBin: true + + '@replit/codemirror-css-color-picker@6.3.0': + resolution: {integrity: sha512-19biDANghUm7Fz7L1SNMIhK48tagaWuCOHj4oPPxc7hxPGkTVY2lU/jVZ8tsbTKQPVG7BO2CBDzs7CBwb20t4A==} + peerDependencies: + '@codemirror/language': ^6.0.0 + '@codemirror/state': ^6.0.0 + '@codemirror/view': ^6.0.0 + + '@rolldown/binding-android-arm64@1.1.5': + resolution: {integrity: sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@rolldown/binding-darwin-arm64@1.1.5': + resolution: {integrity: sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@rolldown/binding-darwin-x64@1.1.5': + resolution: {integrity: sha512-Tm+gbfC0aHu1tBA/JvKQh32S0K6YgCHkiAF4/W6xX0K0RmNuc94VeK419dJoE65R5aRxmo+noZQSWrAMF6yb6g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@rolldown/binding-freebsd-x64@1.1.5': + resolution: {integrity: sha512-JMzDKCCXq93YccG5gz3hvOs1oXRKAf0XYpfOS88e+wZrC8Iugj6j68867vrYZkvpDDpKn/KoKORThmchMpF6TA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@rolldown/binding-linux-arm-gnueabihf@1.1.5': + resolution: {integrity: sha512-uML21j2K5TfPGutKxub+M+nLjZIrWjXQ5Grx4lCe/nimTj9B4L63zHpjXLl4y0L3mcm2htEQIb06oCG/szerNw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@rolldown/binding-linux-arm64-gnu@1.1.5': + resolution: {integrity: sha512-navSiuTMogvnQoZoM/v+l3ZWo50/NTwSHSzheABx/RCnmUPaKwq9qSo4Br2OYRs21+Fz8uFqITZM3H4opOB0/Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-arm64-musl@1.1.5': + resolution: {integrity: sha512-lAryqH7IteztmCXQXk0etKj4wBQ7Gx5S6LjKhsgp9zb8I5bsuvU/2llH1hDQcjsFeqIsovMVN339/8pUDDBXxA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rolldown/binding-linux-ppc64-gnu@1.1.5': + resolution: {integrity: sha512-fsK/sNBnxzBlL4O1JNrZakVQxPspqpED5dLtNsZS9oOKmtSpdNIzxH2kkol5HYTWJN47sE20ztMJPxfZ89qGOg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-s390x-gnu@1.1.5': + resolution: {integrity: sha512-gLYb4BIadlfTOYT5gO503n8zQjXflgzpD0FcyKh0Mzx3rqCZKnHoJWV9xe1KXUJ5lx2JfcSHr/mhzS0PC/McAA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-x64-gnu@1.1.5': + resolution: {integrity: sha512-FjcpEKUyJygHgs1o50VYNvkt5+7Le/VEdYt0AkRpkL33MnyQfwr8l5mXwMmfmTbyMPr5vJLC+8/Gd9gXnwU1QQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-x64-musl@1.1.5': + resolution: {integrity: sha512-Me+PfPI2TMeOQk0gYWfLQZtTktrmzbr8cDboqX83XKc7UrgAi55gF+2dUkWdxd19n55Essp2yeca+O9N5rBxHg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rolldown/binding-openharmony-arm64@1.1.5': + resolution: {integrity: sha512-yc5WrLzXks6zCQfn9Oxr8pORKyl/pF+QjHmW/Qx3qu0oyrrNC+y2JLTU1E2rcWYAmzlnqngWXHQjy51VzW70Vw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@rolldown/binding-wasm32-wasi@1.1.5': + resolution: {integrity: sha512-VbQGPX2b4r48TAMIM2cjgluIM1HYutm4pcTEJsle7iEP7sB1dFqtPLBVbdLAZCxy1txCcPxf4QFf4v8uvltPqA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [wasm32] + + '@rolldown/binding-win32-arm64-msvc@1.1.5': + resolution: {integrity: sha512-gHv82k63z4qpV5+Q1y/12KrK0ltWBukVDI8nZcbT7Tt/ZlOIVwppazneq0F93oDxTo3IgAMEDIoQh3E2n6mVsw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@rolldown/binding-win32-x64-msvc@1.1.5': + resolution: {integrity: sha512-tTZuDBPw85tEN5PQi1pnEBzDy0Z49HtScLAbD5t6hyeU92A95pRWaSMw1GZZi/RwgSgUIl0xrSlXIT/9QzvYSA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@rolldown/pluginutils@1.0.1': + resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} + + '@rollup/pluginutils@5.4.0': + resolution: {integrity: sha512-MfPp06CjRLfXQ3wY0R8vJDYBy/MvVcc9OulEfR0B8Iv9ko+GCNaRZ+EpJYFl27LhKsZK0o420sYCRHCjfCgeUg==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@scalar/agent-chat@0.12.19': + resolution: {integrity: sha512-0reaPFMl70ripCr1pYLIFnwtVfyt4Naz7yfZo81lnfcbBR/uOM6SlCxMj7gghVSJR/MhhXdMfiAfZpxRnufxaw==} + engines: {node: '>=22'} + + '@scalar/api-client@3.13.4': + resolution: {integrity: sha512-86DHrjB6PIL5J9Q5+brjbUtcUSPDCbyXGAJ2H/fqGg4w4h+3eh/52yFS+jVaE3mc6PefgXrHzD+HIelNPE+Yyg==} + engines: {node: '>=22'} + + '@scalar/api-reference@1.62.6': + resolution: {integrity: sha512-ZN1gQuO2I1l/Ecd5X6rKvR375kE2hFsNc4wU/QlVrjoEGpQTCR6g24QnvBjDUTzTCGfwPO4aCaXzUy7chn0Lyw==} + engines: {node: '>=22'} + + '@scalar/asyncapi-upgrader@0.1.2': + resolution: {integrity: sha512-h6NUhsctrhucrbO2XHWbTXp9EWt7eL5vvlsooUEw2bB014KSPd41JrBQ6t0h/dFdmhwxdbBI7Hmg9eZa/mlCXA==} + engines: {node: '>=22'} + + '@scalar/blocks@0.1.5': + resolution: {integrity: sha512-/pHR3Ahjm7jw1hL03tPMjEgN9PYYZdduxe28/eozXtBbpnByMyNCI7zNx5cQc4hrw/oQ6vJapHZxwQ9vheJjNg==} + engines: {node: '>=22'} + + '@scalar/code-highlight@0.4.1': + resolution: {integrity: sha512-pnr8gbQuvSXu4fcPPNkFNjAxxMWiJLffN57lRgVN3FCk+Q8hKHWWT01ulAT1/0Kg3/VmgtObrMHhX2qYnpM9+g==} + engines: {node: '>=22'} + + '@scalar/components@0.27.6': + resolution: {integrity: sha512-jXTv2VgYn7/13yCAGKtc/26LCnrQSULGjcnP0LasJDqkVKDdRm1StHDG5iRniqrIzS21gJ6YcNGokksdLIrgQw==} + engines: {node: '>=22'} + + '@scalar/helpers@0.9.0': + resolution: {integrity: sha512-M34CLRCttqC1bXthI/QSzQj0s5C6nrU2PFWf/vOT3RpycbiGDGQbqR+5RfFzpOIQvRqbHfNdcRbeiZBw+vCbkQ==} + engines: {node: '>=22'} + + '@scalar/icons@0.7.3': + resolution: {integrity: sha512-5uSUvumj6yJEAZT7/MKpgrkNl76waDXUpu0kUBBFJ83GhZirBIK+Z9SktShEvJT0+rk/j9Zaer3BHoEhYwAEBQ==} + engines: {node: '>=22'} + + '@scalar/json-magic@0.12.17': + resolution: {integrity: sha512-Vw2nrUDIjhvMP6vxFtkiiFlabJ6SyTtfn1BsOxgnr1hIB+/rkngMguiDzl5em21VjyfFGIoADia+QWKM2hdcdA==} + engines: {node: '>=22'} + + '@scalar/oas-utils@0.19.5': + resolution: {integrity: sha512-Z5WEem7AKygqoPaR+viCub4xE6iQ4FlWHzDa1t40CfalpquP+CefRo7i+lX/uy94llqF6SU35tPXskeyl36siA==} + engines: {node: '>=22'} + + '@scalar/openapi-types@0.9.1': + resolution: {integrity: sha512-gkGhSkxSzADaBiNg+ZAbJuwj+ZUmzP2Pg9CWZ7ZP+0fck2WjPeDDM7aAbouAm0aQQMF9xBjSPXSA9a/qTHYaTw==} + engines: {node: '>=22'} + + '@scalar/openapi-upgrader@0.2.9': + resolution: {integrity: sha512-D5b0rGLLZgmkO9mdW2j/ND1KBlH1u3RCpr87HPxv9P9ZSr6PtM5iLqFOJq0ACiaHjY2mikCrxgDmnUEhTzRpHQ==} + engines: {node: '>=22'} + + '@scalar/schemas@0.7.2': + resolution: {integrity: sha512-6Ble6WcbiKgD3ypIva+wgZv1qIClmeEjXA6jrOo1bKpYUu6sh4e89LZxDK+LULa2jQl/2O5GEaa6aZ0ImlpkHg==} + engines: {node: '>=22'} + + '@scalar/sidebar@0.9.30': + resolution: {integrity: sha512-HxSp05swt20GB0QLLaGsU+9XfScYOmpBICwPoIcw9+I5WfxAmppFnBX8SGNUro+eeaCbfN8g5IvdbfOiuj79Xw==} + engines: {node: '>=22'} + + '@scalar/snippetz@0.9.21': + resolution: {integrity: sha512-0XFKdiKh5OnBxnK/NCBxaXpva53MRpvW4o6T2SMEUd+/xVa4Xmz7oHCHoq2g86+uY4bmepG1kZ0ndapyQjg/vw==} + engines: {node: '>=22'} + + '@scalar/themes@0.16.2': + resolution: {integrity: sha512-4mAn7z2W5/ASi1OF06dqf04xjxTHnMzESC2E+qVMukJsEsV4kDlYSIfm/g5hwWxhqWsBMjorF9Dtlqd0ycJ92g==} + engines: {node: '>=22'} + + '@scalar/typebox@0.1.3': + resolution: {integrity: sha512-lU055AUccECZMIfGA0z/C1StYmboAYIPJLDFBzOO81yXBi35Pxdq+I4fWX6iUZ8qcoHneiLGk9jAUM1rA93iEg==} + + '@scalar/types@0.16.2': + resolution: {integrity: sha512-QAlCtDVRsX/UV1N9ctLqPsKQy84eceFf4dMnTZM0JhaRfwS/Ovwp8oFf3POSpqQILNiqLFZLE6IV6p/5rNoAag==} + engines: {node: '>=22'} + + '@scalar/use-codemirror@0.14.12': + resolution: {integrity: sha512-m+0tmVOHZVAybbcNEizR3m9RYOLtU59AStRkk29J5qaW4J+tsjrz4BDMceeTpoVawL/lxp2vDvQR+w/gKC3miQ==} + engines: {node: '>=22'} + + '@scalar/use-hooks@0.4.7': + resolution: {integrity: sha512-8zajxhnKMJuO1HF36y8TeVuSIol2pueYdRvITZTEY8TuRbnwxrvJZk25II7YpxGMORAEDr0bwNF88Dr+QUfw1w==} + engines: {node: '>=22'} + + '@scalar/use-toasts@0.10.2': + resolution: {integrity: sha512-1iHQFbDXv0YQRp13aa63S5EcTJ5K8T0ocnLxk+nziloPrLjKt6jdRt6vOHsLSv5sm9kFKcVKNQTQgialmKCOGA==} + engines: {node: '>=22'} + + '@scalar/validation@0.6.0': + resolution: {integrity: sha512-tpmmG+/xRE2Kn9RpflU3AIyZv08v10+E1ZrJCx7z6+/91zHVxy0M73kC1LT4/8PbYNt85ywyC8+n+D99JdMcGA==} + engines: {node: '>=20'} + + '@scalar/workspace-store@0.55.4': + resolution: {integrity: sha512-zpodJmejOuRDbQRlcIP4kqnxYo4/yfgtLr2XBqms+6/gaFwBV2naM/ydMkGZ645Ohqm201/Z+QzrgrBevGYjgQ==} + engines: {node: '>=22'} + + '@shikijs/core@4.3.1': + resolution: {integrity: sha512-ANMDxuaPsNMdDC1m4vfvhlDmJweMwkE5XitTwrq2rWHx5jM+dlm4MmHt2PP6t0uejfR77SuhrhJ0zEijIF/uhA==} + engines: {node: '>=20'} + + '@shikijs/engine-javascript@4.3.1': + resolution: {integrity: sha512-JBItcnPuYq7jVJdZo/vMj94r+szT7XEjHFX+mvFDGSEIbVAXAGyHAHzhbWzpGOwYidCZrErJLLgn2PVeiokHnQ==} + engines: {node: '>=20'} + + '@shikijs/engine-oniguruma@4.3.1': + resolution: {integrity: sha512-OXyNMzg0pews+msMj4cHeqT4xiYKKvbnn6VbdAXxfoFl3SSx4fJTc8FadECuc5/H9p3BzhNAoAUXKwAu9rWYhg==} + engines: {node: '>=20'} + + '@shikijs/langs@4.3.1': + resolution: {integrity: sha512-m0l9nsDqgBHvbZbk7A0/kXz/impK3uB/c6rAn6Gpg/uPtdZRQ+alsN/17MU5thb68XTj/4DxkZAotrM0GGSpDQ==} + engines: {node: '>=20'} + + '@shikijs/primitive@4.3.1': + resolution: {integrity: sha512-CXQRQOYy1leqQ8ceTeJdmXv/bsUY++6QyLpXJ94LZAAYj5X2SKRdc5ipguv4NPyGVKItB2PPwUpRNe0Sjh5S1A==} + engines: {node: '>=20'} + + '@shikijs/themes@4.3.1': + resolution: {integrity: sha512-dgpoJ4WqNi2yTmizQHBJ5zcX6j2lE6icN/0yt4l1kkf16jrY/pwPLoTb1ETsWMz0OBLf9ZNvwmxft+cH+N9qSA==} + engines: {node: '>=20'} + + '@shikijs/types@4.3.1': + resolution: {integrity: sha512-CHFxE0jztBIZRHH6gxXE7DXUCFXjReEGxZ/j0rfSLGKZuwp2xBYycEP14875DSa9KLL/6700oxIq6oO6ef9K2g==} + engines: {node: '>=20'} + + '@shikijs/vscode-textmate@10.0.2': + resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} + + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + + '@swc/helpers@0.5.23': + resolution: {integrity: sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==} + + '@tanstack/virtual-core@3.17.4': + resolution: {integrity: sha512-nGm5KteqxasUdThLc2izl6dHUqLv0LQj7Nuyo5gYalTPf/U8a9ermvsl7reT+6ioBW1l8WfpP/mcU338nLXpqw==} + + '@tanstack/vue-virtual@3.13.32': + resolution: {integrity: sha512-E8OCutx7QnwZdvpJijz0Q2PHsYDWBWjnGr3TvgWiqxTU35jB1kVhtkd93scRV7tTFuId2tg3x2iFiw+IE4evjQ==} + peerDependencies: + vue: ^2.7.0 || ^3.0.0 + + '@tybys/wasm-util@0.10.3': + resolution: {integrity: sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==} + + '@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.9': + resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} + + '@types/har-format@1.2.16': + resolution: {integrity: sha512-fluxdy7ryD3MV6h8pTfTYpy/xQzCFC7m89nOH9y94cNqJ1mDIDPut7MnRHI3F6qRmh/cT2fUjG1MLdCNb4hE9A==} + + '@types/hast@3.0.5': + resolution: {integrity: sha512-rp/ezSWaD1m44dPKICGhiskI13nVr7qTloFwDa/IYkhhf5nzwP+zIQcIJh3WIFSBOy/H1PzB40jPjMDksN4F+g==} + + '@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.14': + resolution: {integrity: sha512-T48PeuJtvLosNTPVhfnIp3i/n3a4g4Bad7YCq5k64D4u7NwDrAotikQ+5+sjtUvBmxCMlbo3dVL+C2dP0rWHzg==} + + '@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.13.3': + resolution: {integrity: sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q==} + + '@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==} + + '@types/web-bluetooth@0.0.20': + resolution: {integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==} + + '@types/web-bluetooth@0.0.21': + resolution: {integrity: sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==} + + '@ungap/structured-clone@1.3.3': + resolution: {integrity: sha512-60YRaenCQcVjYEKOcG824+DRGGIQ3VKErcBoAEDJZz5bKIs2ZG+X/H9Nk+Q6EVkwJk5QNApxbrc5QtBSwtrXAg==} + + '@unhead/vue@2.1.15': + resolution: {integrity: sha512-SSByXfEjhzPn8gXdEdgpYqpLMPSkLUH2HVE0GxZfOtNsJ0GgOHQs0g9T67ZZ1z0kTELLKdtOtYrzrbv9+ffF7g==} + peerDependencies: + vue: '>=3.5.18' + + '@vercel/oidc@3.1.0': + resolution: {integrity: sha512-Fw28YZpRnA3cAHHDlkt7xQHiJ0fcL+NRcIqsocZQUSmbzeIKRpwttJjik5ZGanXP+vlA4SbTg+AbA3bP363l+w==} + engines: {node: '>= 20'} + + '@vue/compiler-core@3.5.39': + resolution: {integrity: sha512-16KBTEXAJCpDr0mwlw+AZyhu8iyC7R3S2vBwsI7QnWJU6X3WKc9VKeNEZpiMdZ569qWhz9574L3vV55qRL0Vtw==} + + '@vue/compiler-dom@3.5.39': + resolution: {integrity: sha512-oQPigALqYbNxTNPvNgSOe+czwVExfbVF02lz8jP0S3AXJiu3jxYDygNUiqSep4ezzW8XgnubqH63My2A7JR/vg==} + + '@vue/compiler-sfc@3.5.39': + resolution: {integrity: sha512-d0ki86iOyN8LoZPBmk5SJWNwHP19CnDDCfuo//+2WJa2g5Ke0Jay983PIBIcSSzldC68I8DrD5GrHV3OSDfodg==} + + '@vue/compiler-ssr@3.5.39': + resolution: {integrity: sha512-Ce7/wvwMHai74bdszfXExdazFigYnlF9zgCmEQUcM1j0fOymlouZ7XilTYNo8oUjhlnjYOZbGrcYKuqjz89Ucw==} + + '@vue/reactivity@3.5.39': + resolution: {integrity: sha512-TpsuBJ9gGlZa5d23XcM2y8EXanz9dZeVDQBXRwzy46ItgvM+rWpzs+UVM0wcRLxGvcav0HE5jz2gNL53xlRAog==} + + '@vue/runtime-core@3.5.39': + resolution: {integrity: sha512-9GLtNyRvPAUMbX+7ono0RC2j0guo2LXVi8LvcmAooImACUKm0oFf0jjwbX8/H0AE/t1nxhAkn8RSl9PMCzzxZw==} + + '@vue/runtime-dom@3.5.39': + resolution: {integrity: sha512-7Y6aAGboKcXAZ3ECuUy7RrS5yy2r47dhTp2SKaJmYxjopImaVFaNa5Ne66NwGovsrxVAl5S5rwc7m22UG7Lmww==} + + '@vue/server-renderer@3.5.39': + resolution: {integrity: sha512-yZSakiAGw85rZfG7UM8akMnIF+FmeiNk47uvHf2nVBBSe+dIKUhZuZq9+XgJhbV3nS5Z4ALH23/MpXofW+mbcw==} + peerDependencies: + vue: 3.5.39 + + '@vue/shared@3.5.39': + resolution: {integrity: sha512-l1rrBtBfTnmxvtsvdQDXltUUy8S1Y+ZaqdfUzmAnJkTd8Z8rv5v/ytW+TKiqEOWyHPoqtPlNFSs0lhRmYVSHVA==} + + '@vueuse/core@10.11.1': + resolution: {integrity: sha512-guoy26JQktXPcz+0n3GukWIy/JDNKti9v6VEMu6kV2sYBsWuGiTU8OWdg+ADfUbHg3/3DlqySDe7JmdHrktiww==} + + '@vueuse/core@13.9.0': + resolution: {integrity: sha512-ts3regBQyURfCE2BcytLqzm8+MmLlo5Ln/KLoxDVcsZ2gzIwVNnQpQOL/UKV8alUqjSZOlpFZcRNsLRqj+OzyA==} + peerDependencies: + vue: ^3.5.0 + + '@vueuse/integrations@13.9.0': + resolution: {integrity: sha512-SDobKBbPIOe0cVL7QxMzGkuUGHvWTdihi9zOrrWaWUgFKe15cwEcwfWmgrcNzjT6kHnNmWuTajPHoIzUjYNYYQ==} + peerDependencies: + async-validator: ^4 + axios: ^1 + change-case: ^5 + drauu: ^0.4 + focus-trap: ^7 + fuse.js: ^7 + idb-keyval: ^6 + jwt-decode: ^4 + nprogress: ^0.2 + qrcode: ^1.5 + sortablejs: ^1 + universal-cookie: ^7 || ^8 + vue: ^3.5.0 + peerDependenciesMeta: + async-validator: + optional: true + axios: + optional: true + change-case: + optional: true + drauu: + optional: true + focus-trap: + optional: true + fuse.js: + optional: true + idb-keyval: + optional: true + jwt-decode: + optional: true + nprogress: + optional: true + qrcode: + optional: true + sortablejs: + optional: true + universal-cookie: + optional: true + + '@vueuse/metadata@10.11.1': + resolution: {integrity: sha512-IGa5FXd003Ug1qAZmyE8wF3sJ81xGLSqTqtQ6jaVfkeZ4i5kS2mwQF61yhVqojRnenVew5PldLyRgvdl4YYuSw==} + + '@vueuse/metadata@13.9.0': + resolution: {integrity: sha512-1AFRvuiGphfF7yWixZa0KwjYH8ulyjDCC0aFgrGRz8+P4kvDFSdXLVfTk5xAN9wEuD1J6z4/myMoYbnHoX07zg==} + + '@vueuse/shared@10.11.1': + resolution: {integrity: sha512-LHpC8711VFZlDaYUXEBbFBCQ7GS3dVU9mjOhhMhXP6txTV4EhYQg/KGnQuvt/sPAtoUKq7VVUnL6mVtFoL42sA==} + + '@vueuse/shared@13.9.0': + resolution: {integrity: sha512-e89uuTLMh0U5cZ9iDpEI2senqPGfbPRTHM/0AaQkcxnpqjkZqDYP8rpfm7edOz8s+pOCOROEy1PIveSW8+fL5g==} + peerDependencies: + vue: ^3.5.0 + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn@8.17.0: + resolution: {integrity: sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==} + engines: {node: '>=0.4.0'} + hasBin: true + + ai@6.0.33: + resolution: {integrity: sha512-bVokbmy2E2QF6Efl+5hOJx5MRWoacZ/CZY/y1E+VcewknvGlgaiCzMu8Xgddz6ArFJjiMFNUPHKxAhIePE4rmg==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + am-i-vibing@0.4.0: + resolution: {integrity: sha512-MxT4XZL7pzLHpuvhDKdMaQHMGGkJDLluKBLsbstn+8wv9sWcFT6h+0ve9qkml95amVTZtZV83gQe2hY+ojgHLg==} + 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-hidden@1.2.6: + resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==} + engines: {node: '>=10'} + + 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.44.0: + resolution: {integrity: sha512-b1wN/ZvbJprzxlGKIpIes2kQrCY5KRLwys2tWbZAZyjGZcW5ZtgneZnBwzNRiBna9/48d4mQl19KLjcRuhO1hw==} + peerDependencies: + astro: ^4.0.0-beta || ^5.0.0-beta || ^3.3.0 || ^6.0.0-beta || ^7.0.0 + + astro@7.0.9: + resolution: {integrity: sha512-WB5pA4LLQnmqjBh6EIu0z8aUV4q2/AoThgSZq57Rsp+oqqvPu7OwZ5eF+W4ku20TUTxIhiJW8dccuGvJPiW2UA==} + engines: {node: '>=22.12.0', npm: '>=9.6.5', pnpm: '>=7.1.0'} + hasBin: true + peerDependencies: + '@astrojs/markdown-remark': 7.2.1 + peerDependenciesMeta: + '@astrojs/markdown-remark': + optional: 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.1: + resolution: {integrity: sha512-KLw+H/gd2p4zly1X7Yh/qziuyae5/w/QFnvTng9eZL5fvszL7Whl3MBoWF8yxL7ksUjBfOD+OxkytiqbBpG+Fw==} + + boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + + ccount@2.0.1: + resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + + chalk@5.6.2: + resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + + 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'} + + convert-hrtime@5.0.0: + resolution: {integrity: sha512-lOETlkIeYSJWcbbcvjRKGxVMXJR+8+OQb/mTPbA4ObPMytYIsUbuOE0Jzy60hjARYszq1id0j8KgVhC+WGZVTg==} + engines: {node: '>=12'} + + cookie-es@1.2.3: + resolution: {integrity: sha512-lXVyvUvrNXblMqzIRrxHb57UUVmqsSWlxqt3XIjCkUP0wDAf6uicO6KMbEgYrMNtEvWgWHwe42CKxPu9MYAnWw==} + + cookie@1.1.1: + resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==} + engines: {node: '>=18'} + + crelt@1.0.7: + resolution: {integrity: sha512-aK6BbWfhf4U/wCcLHKPJl/xa6VkVstRaPywWtMKGwuOLc/wZTyQYuoxgvZnNsBvv7Kg3YTBQYYBCggcviQczuA==} + + 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'} + + csstype@3.2.3: + resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + + cva@1.0.0-beta.4: + resolution: {integrity: sha512-F/JS9hScapq4DBVQXcK85l9U91M6ePeXoBMSp7vypzShoefUBxjQTo3g3935PUHgQd+IW77DjbPRIxugy4/GCQ==} + peerDependencies: + typescript: '>= 4.5.5' + peerDependenciesMeta: + typescript: + optional: true + + 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.1: + resolution: {integrity: sha512-4CXDYRBGqN+57wVJkuXBYmpAVUSg3L6JAQa/DFqm238G73E1wuyc/JhGQJzN7vUf/CMphYau2zXbfWzDR5aTEw==} + + 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'} + + entities@7.0.1: + resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==} + engines: {node: '>=0.12'} + + es-module-lexer@2.3.1: + resolution: {integrity: sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==} + + 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.28.1: + resolution: {integrity: sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==} + 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==} + + eventsource-parser@3.1.0: + resolution: {integrity: sha512-kJezFj9YFAMLeORyi7aCLxLbD5/qWMQnoMVlVPyHIll7lgRJCc3JVln9Vgl9nwQi0YkMnhdGTMNn7CkRRAptMg==} + engines: {node: '>=18.0.0'} + + expressive-code@0.44.0: + resolution: {integrity: sha512-JXVWVNCKlLuZLMQH8cOiDUSosT0Bb+elwE/dbAkpwFwDFmyFyWlECoWZIohh2FkIF1iI67TQJ+Ts9k7oNDh2qA==} + + extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + 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.2: + resolution: {integrity: sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q==} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + flatted@3.4.2: + resolution: {integrity: sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==} + + flattie@1.1.1: + resolution: {integrity: sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ==} + engines: {node: '>=8'} + + focus-trap@7.8.0: + resolution: {integrity: sha512-/yNdlIkpWbM0ptxno3ONTuf+2g318kh2ez3KSeZN5dZ8YC6AAmgeWz+GasYYiBJPFaYcSAPeu4GfhUaChzIJXA==} + + 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.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-timeout@1.0.2: + resolution: {integrity: sha512-939eZS4gJ3htTHAldmyyuzlrD58P03fHG49v2JfFXbV6OhvZKRC9j2yAtdHw/zrp2zXHuv05zMIy40F0ge7spA==} + engines: {node: '>=18'} + + fuse.js@7.5.0: + resolution: {integrity: sha512-sQtrEfA+ez/3G0cCZecF70oqpCRttCexYUG4mUrtWL49ULUzUyxokt5kyqwtKzj1270RaKih+hcP3qLcumccow==} + engines: {node: '>=10'} + + get-own-enumerable-keys@1.0.0: + resolution: {integrity: sha512-PKsK2FSrQCyxcGHsGrLDcK0lx+0Ke+6e8KFFozA9/fIQLhQzPaRvJFdcz7+Axg3jUH/Mq+NI4xa5u/UT2tQskA==} + engines: {node: '>=14.16'} + + 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==} + + guess-json-indent@3.0.1: + resolution: {integrity: sha512-LWZ3Vr8BG7DHE3TzPYFqkhjNRw4vYgFSsv2nfMuHklAlOfiy54/EwiDQuQfFVLxENCVv20wpbjfTayooQHrEhQ==} + engines: {node: '>=18.18.0'} + + 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-sanitize@5.0.2: + resolution: {integrity: sha512-3yTWghByc50aGS7JlGhk61SPenfE/p1oaFeNwkOOyrscaOkMGrcW9+Cy/QAIOBpZxP1yqDIzFMR0+Np0i0+usg==} + + 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==} + + highlight.js@11.11.1: + resolution: {integrity: sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==} + engines: {node: '>=12.0.0'} + + hookable@6.1.1: + resolution: {integrity: sha512-U9LYDy1CwhMCnprUfeAZWZGByVbhd54hwepegYTK7Pi5NvqEj63ifz5z+xukznehT7i6NIZRu89Ay1AZmRsLEQ==} + + 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.3.6: + resolution: {integrity: sha512-Bu5Z2nAXgfVyM8xvW3jk9EKRIuX37PudsrBViThNFx7CR7aaYTpP01cxNB/E4c4UUzTDiAZRstEhsRfPOL/8xA==} + peerDependencies: + typescript: ^5 || ^6 || ^7 + peerDependenciesMeta: + typescript: + optional: true + + identifier-regex@1.1.0: + resolution: {integrity: sha512-SLX4H/vtcYlYnL7XqnuJKHU7Z8517TgsW9nmQiGOgMCjQ8V/deLYu6bEmbGoXe7WMMhc9+EUGyFFneHja8KabA==} + engines: {node: '>=18'} + + inline-style-parser@0.2.7: + resolution: {integrity: sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==} + + iron-webcrypto@1.2.1: + resolution: {integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==} + + is-absolute-url@4.0.1: + resolution: {integrity: sha512-/51/TKE88Lmm7Gc4/8btclNXWS+g50wXhYJq8HWIBAGUBnoAdRu1aXeh364t/O7wXDAcTJDP8PNuNKWUDWie+A==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + 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@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-identifier@1.1.0: + resolution: {integrity: sha512-NhOds0mDx9lJu+1lBRO0xbwFo5nobA7GCk/0e5xjr6+6XugX985+0OyGX35BNrTkPAsdLcIKg02HUQJOK8D8kw==} + engines: {node: '>=18'} + + is-obj@3.0.0: + resolution: {integrity: sha512-IlsXEHOjtKhpN8r/tRFj2nDyTmHvcfNeu/nrRIcXE17ROeatXchkojffa1SpdqW4cr/Fj6QkEf/Gn4zf6KKvEQ==} + engines: {node: '>=12'} + + is-plain-obj@4.1.0: + resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} + engines: {node: '>=12'} + + is-regexp@3.1.0: + resolution: {integrity: sha512-rbku49cWloU5bSMI+zaRaXdQHXnthP6DZ/vLnfdSKyL4zUzuWnomtOEiZZOd+ioQ+avFo/qau3KPTc7Fjy1uPA==} + engines: {node: '>=12'} + + js-base64@3.9.1: + resolution: {integrity: sha512-U73qptcvf/HIOauFOmqT3a0mDUp0MYlfd15oqoe9kqZt5XhiXVb+HG09sLvI9PQ9tZIBFS4nlErai8zbWazP0g==} + + js-yaml@4.3.0: + resolution: {integrity: sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==} + hasBin: true + + json-schema@0.4.0: + resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} + + 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'} + + lightningcss-android-arm64@1.32.0: + resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.32.0: + resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.32.0: + resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.32.0: + resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.32.0: + resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.32.0: + resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + lightningcss-linux-arm64-musl@1.32.0: + resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + + lightningcss-linux-x64-gnu@1.32.0: + resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + + lightningcss-linux-x64-musl@1.32.0: + resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + + lightningcss-win32-arm64-msvc@1.32.0: + resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.32.0: + resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.32.0: + resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} + engines: {node: '>= 12.0.0'} + + longest-streak@3.1.0: + resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} + + lowlight@3.3.0: + resolution: {integrity: sha512-0JNhgFoPvP6U6lE/UdVsSq99tn6DhjjpAj5MxG49ewd2mOBVtwWYIT8ClyABhq198aXXODMU6Ox8DrGy/CpTZQ==} + + lru-cache@11.5.2: + resolution: {integrity: sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==} + engines: {node: 20 || >=22} + + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + + magicast@0.5.3: + resolution: {integrity: sha512-pVKE4UdSQ7DvHzivsCIFx2BJn1mHG6KsyrFcaxFx6tONdneEuThrDx0Cj3AMg58KyN4pzYT+LHOotxDQDjNvkw==} + + make-asynchronous@1.1.0: + resolution: {integrity: sha512-ayF7iT+44LXdxJLTrTd3TLQpFDDvPCBxXxbv+pMUSuHA5Q8zyAfwkRP6aHHwNVFBUFWtxAHqwNJxF8vMZLAbVg==} + engines: {node: '>=18'} + + 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==} + + microdiff@1.5.0: + resolution: {integrity: sha512-Drq+/THMvDdzRYrK0oxJmOKiC24ayUV8ahrt8l3oRK51PWt6gdtrIGrlIH3pT/lFh1z93FbAcidtsHcWbnRz8Q==} + + 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.16: + resolution: {integrity: sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + nanoid@5.1.16: + resolution: {integrity: sha512-kVrnsrJqMR8+oLJnGEmSWw9BivK5mt7H3FZatVRjrc5wGqFYuBxX1yG7+A7Gi5AefkX6t/oCkizcQgpu0cY1dQ==} + engines: {node: ^18 || >=20} + hasBin: true + + neotraverse@0.6.18: + resolution: {integrity: sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA==} + engines: {node: '>= 10'} + + neverpanic@0.0.8: + resolution: {integrity: sha512-vVdkelrLxaow/fdWDumzNBO+jwm6X8bxeLJc34THtpj70u0C5QBkcV6CRCu2X726km7XD45N0A3QtYCla4RvKw==} + + 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.3: + resolution: {integrity: sha512-9miFgM2OFba7hB+pRgvtV84pYTBaoTHohvmIgiRt6dRIzbwEOIaNaP+dIlGs2fNFoB0SeISs0Jz5WFVRid6Xyg==} + engines: {node: '>=12.20.0'} + + 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-event@6.0.1: + resolution: {integrity: sha512-Q6Bekk5wpzW5qIyUP4gdMEujObYstZl6DMMOSenwBvV0BlE5LkDwkjs5yHbZmdCEq2o4RJx4tE1vwxFVf2FG1w==} + engines: {node: '>=16.17'} + + p-limit@7.3.0: + resolution: {integrity: sha512-7cIXg/Z0M5WZRblrsOla88S4wAK+zOQQWeBYfV3qJuJXMr+LnbYjaadrFaS0JILfEDPVqHyKnZ1Z/1d6J9VVUw==} + engines: {node: '>=20'} + + p-queue@9.3.1: + resolution: {integrity: sha512-POWdiIPmsUPGwb4FeQ4OBg46aqmcInSWe45CKDsGHiOBiVQM9chqfQTuqhuTzcg2Vz9faTI65at0KkVyVEiCHw==} + engines: {node: '>=20'} + + p-timeout@6.1.4: + resolution: {integrity: sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg==} + engines: {node: '>=14.16'} + + p-timeout@7.0.1: + resolution: {integrity: sha512-AxTM2wDGORHGEkPCt8yqxOTMgpfbEHqF51f/5fJCmwFC3C/zNcGT63SymH2ttOAaiIws2zVg4+izQCjrakcwHg==} + engines: {node: '>=20'} + + package-manager-detector@1.7.0: + resolution: {integrity: sha512-xg1eHpwYL/D/HEdWw2goFZP6vV0FH7W+PZ5rFkGjdIDLtxq7EkzBUeT3m+lndYCt8wKbmofUu1MUdMCXkCk9ZQ==} + + 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==} + + parse-ms@4.0.0: + resolution: {integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==} + engines: {node: '>=18'} + + parse5@7.3.0: + resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} + + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + 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.5: + resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==} + engines: {node: '>=12'} + + playwright-core@1.59.1: + resolution: {integrity: sha512-HBV/RJg81z5BiiZ9yPzIiClYV/QMsDCKUyogwH9p3MCP6IYjUFu/MActgYAvK0oWyV9NlwM3GLBjADyWgydVyg==} + engines: {node: '>=18'} + hasBin: true + + playwright@1.59.1: + resolution: {integrity: sha512-C8oWjPR3F81yljW9o5OxcWzfh6avkVwDD2VYdwIGqTkl+OGFISgypqzfu7dOe4QNLL2aqcWBmI3PMtLIK233lw==} + engines: {node: '>=18'} + hasBin: true + + 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.4: + resolution: {integrity: sha512-bIoJLOmjCO1S9XdY/DcnR5hJxvrDir1PbGChrzXG3vw0/FOliy/fA3dmdhQ441kah4gKv+TwckGzex6wNS5cnQ==} + engines: {node: '>=4'} + + postcss@8.5.19: + resolution: {integrity: sha512-Mz8SaolMd8nB+G13WkORcxQKHZ/NE4xXevtkJHVuG+guo9/wYKlIMTKAqGdEmYOXR2ijPjTYNHssizdaVSUNdQ==} + engines: {node: ^10 || ^12 || >=14} + + pretty-ms@9.3.0: + resolution: {integrity: sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==} + engines: {node: '>=18'} + + prismjs@1.30.0: + resolution: {integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==} + engines: {node: '>=6'} + + process-ancestry@0.1.0: + resolution: {integrity: sha512-tGqJW/UnclpYASFcM6Xh8D8l/BMtaQ9+CSG0vlJSJTcdMM4lDRv4c6H0Pdcsfted+bVczdYSfk2fdukg2gQkZg==} + engines: {node: '>=18.0.0'} + + property-information@7.2.0: + resolution: {integrity: sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg==} + + radix-vue@1.9.17: + resolution: {integrity: sha512-mVCu7I2vXt1L2IUYHTt0sZMz7s1K2ZtqKeTIxG3yC5mMFfLBG4FtE1FDeRMpDd+Hhg/ybi9+iXmAP1ISREndoQ==} + peerDependencies: + vue: '>= 3.2.0' + + 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.44.0: + resolution: {integrity: sha512-5r74C5F2sMR3X+QJH8OKWgZBO/cqRw5W1fLT6GVlSfLqepk+4j8tGFkyPqZYWjwntsBHzKPDH2zI68sZ7ScLfA==} + + rehype-external-links@3.0.0: + resolution: {integrity: sha512-yp+e5N9V3C6bwBeAC4n796kc86M4gJCdlVhiMTxIrJG5UHDMh+PJANf9heqORJbt1nrCbDwIlAZKjANIaVBbvw==} + + 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-sanitize@6.0.0: + resolution: {integrity: sha512-CsnhKNsyI8Tub6L4sm5ZFsme4puGfc6pYylvXo1AeqaGbjOYyzNv3qZPwvs0oMJ39eryyeOdmxwUIo94IpEhqg==} + + 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==} + + reserved-identifiers@1.2.0: + resolution: {integrity: sha512-yE7KUfFvaBFzGPs5H3Ops1RevfUEsDc5Iz65rOwWg4lE8HJSYtle77uul3+573457oHvBKuHYDl/xqUkKpEEdw==} + engines: {node: '>=18'} + + 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==} + + rolldown@1.1.5: + resolution: {integrity: sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + + satteri@0.9.5: + resolution: {integrity: sha512-ZuWVl+vnM64y+/TtX8Kosv2c00W+hLQiiwnEL6H0UKVVrxFqMw4D2CJHHQaouVd89OAhtBBfjWLqhKi3TVUV4w==} + + sax@1.6.0: + resolution: {integrity: sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==} + engines: {node: '>=11.0.0'} + + semver@7.8.5: + resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==} + engines: {node: '>=10'} + hasBin: true + + set-cookie-parser@3.1.0: + resolution: {integrity: sha512-kjnC1DXBHcxaOaOXBHBeRtltsDG2nUiUni+jP92M9gYdW12rsmx92UsfpH7o5tDRs7I1ZZPSQJQGv3UaRfCiuw==} + + sharp@0.35.3: + resolution: {integrity: sha512-ej0zVHuZGHCiABXcNxeYhpRnPNPAcvbG8RMdBAhDAxLKkCRVSpK3Iyu7qbqw3JMzoj0REeM6f3tJLtVwl0023Q==} + engines: {node: '>=20.9.0'} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + + shiki@4.3.1: + resolution: {integrity: sha512-oR+qDVi2OjX1tmDpyv+3KviX01KzO6Af+0NNnKnsp9491UEGz2YpxTuJboS/6VhYpTdqzmuJBuiTlrAWWJAssw==} + 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.7.0: + resolution: {integrity: sha512-aqVvWoyO21L23mb+drl4RmMXbf6N7FdHjAhTRA9ZBL7apWBgfWC16KjrASI+1p9GAroljyMHj6fK67i0UiTNvQ==} + 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==} + + string-byte-length@3.0.1: + resolution: {integrity: sha512-yJ8vP0HMwZ54CcA8S8mKoXbkezpZHANFtmafFo8lGxZThCQcAwRHjdFabuSLgOzxj9OFJcmssmiAvmcOK4O2Hw==} + engines: {node: '>=18.18.0'} + + string-byte-slice@3.0.1: + resolution: {integrity: sha512-GWv2K4lYyd2+AhmKH3BV+OVx62xDX+99rSLfKpaqFiQU7uOMaUY1tDjdrRD4gsrCr9lTyjMgjna7tZcCOw+Smg==} + engines: {node: '>=18.18.0'} + + stringify-entities@4.0.4: + resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} + + stringify-object@6.0.0: + resolution: {integrity: sha512-6f94vIED6vmJJfh3lyVsVWxCYSfI5uM+16ntED/Ql37XIyV6kj0mRAAiTeMMc/QLYIaizC3bUprQ8pQnDDrKfA==} + engines: {node: '>=20'} + + style-mod@4.1.3: + resolution: {integrity: sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==} + + style-to-js@1.1.21: + resolution: {integrity: sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==} + + style-to-object@1.0.14: + resolution: {integrity: sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==} + + super-regex@1.1.0: + resolution: {integrity: sha512-WHkws2ZflZe41zj6AolvvmaTrWds/VuyeYr9iPVv/oQeaIoVxMKaushfFWpOGDT+GuBrM/sVqF8KUCYQlSSTdQ==} + engines: {node: '>=18'} + + svgo@4.0.2: + resolution: {integrity: sha512-ekx94z1rRc5LDi6oSUaeRnYhd0UOJxdtQCL2rF8xpWxD3TPAsISWOrxezqGovqS38GRZOdpDfvQe3ts6F7nsng==} + engines: {node: '>=16'} + hasBin: true + + swrv@1.2.0: + resolution: {integrity: sha512-lH/g4UcNyj+7lzK4eRGT4C68Q4EhQ6JtM9otPRIASfhhzfLWtbZPHcMuhuba7S9YVYuxkMUGImwMyGpfbkH07A==} + peerDependencies: + vue: '>=3.2.26 < 4' + + tabbable@6.5.0: + resolution: {integrity: sha512-wieBHXygIm7OyQOu5hQlkk62/WyCFYGlWg7L6/ZCUZwx0o398Zkn4pVmMyfYhfMG8kGrj/Krt8eIk6UKC6VzwA==} + + tagged-tag@1.0.0: + resolution: {integrity: sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==} + engines: {node: '>=20'} + + tailwind-merge@3.5.0: + resolution: {integrity: sha512-I8K9wewnVDkL1NTGoqWmVEIlUcB9gFriAEkXkfCjX5ib8ezGxtR3xD7iZIxrfArjEsH7F1CHD4RFUtxefdqV/A==} + + tailwindcss@4.3.2: + resolution: {integrity: sha512-WtctNNSH8A9jlMIqxzuYumOHU5uGZyRv0Q5svQl+oEPy5w84YpBxdb7MdqyiSPQge5jTJ6zFQLq0PFygdccSBA==} + + time-span@5.1.0: + resolution: {integrity: sha512-75voc/9G4rDIJleOo4jPvN4/YC4GRZrY8yy1uU4lwrB3XEQbWve8zXoO5No4eFrGcTAMYyoY67p8jRQdtA1HbA==} + engines: {node: '>=12'} + + tiny-inflate@1.0.3: + resolution: {integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==} + + tinyclip@0.1.15: + resolution: {integrity: sha512-uo33abH+Ays0xYaDysoBt494Hb3hsEczMpcC0MwFl773pazORx4fmvKhclhR1wonUbB6vvpRsvVMwnhfqeMc+A==} + engines: {node: ^16.14.0 || >= 17.3.0} + + tinyexec@1.2.4: + resolution: {integrity: sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==} + engines: {node: '>=18'} + + tinyglobby@0.2.17: + resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} + engines: {node: '>=12.0.0'} + + trim-lines@3.0.1: + resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} + + trough@2.2.0: + resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==} + + truncate-json@3.0.1: + resolution: {integrity: sha512-QVsbr1WhGLq2F0oDyYbqtOXcf3gcnL8C9H5EX8bBwAr8ZWvWGJzukpPrDrWgJMrNtgDbo74BIjI4kJu3q2xQWw==} + engines: {node: '>=18.18.0'} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + type-fest@4.41.0: + resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} + engines: {node: '>=16'} + + type-fest@5.8.0: + resolution: {integrity: sha512-YGYEVz3Fm5iy/AybuA0oyNFq7H4CgQNfRp/qfe8nurE1kuCeNm3/vfm9X4Mtl+qLyaKJUh5xrFZwogr41SMjYA==} + engines: {node: '>=20'} + + ufo@1.6.4: + resolution: {integrity: sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==} + + ultrahtml@1.7.0: + resolution: {integrity: sha512-2xRd0VHoAQE4M+vF/DvFFB7pUV0ZxTW1TLi7lHQWnF/Sb5TPeEUV/l+hxcNnGO00ZXGnR0voCMmYRKQf+rvJ2g==} + + uncrypto@0.1.3: + resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==} + + undici-types@7.18.2: + resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} + + unhead@2.1.15: + resolution: {integrity: sha512-MCt5T90mCWyr3Z6pUCdM9lVRXoMoVBlL7z7U4CYVIiaDiuzad/UCfLuMqz5MeNmpZUgoBCQnrucJimU7EZR+XA==} + + 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 + + url-extras@0.1.0: + resolution: {integrity: sha512-8tzwTeXFPuX/5PHuCDQE5Dd9Ts4rwoq2t9aIT+HS4iAVpmj5l4Ao7Q+BuuFjvWRqrLswBhQDk8O96ZicgCqQqw==} + engines: {node: '>=20'} + + 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@8.1.4: + resolution: {integrity: sha512-bTT9PsdWO+MQMNG9ZXIP/qM9wGh37DFxTV/sPq9cFpHr3w4jkgef032PkAL9jAqhk3Nz8NQw3O8n6/xFkqO4QQ==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + '@vitejs/devtools': ^0.3.0 + esbuild: ^0.27.0 || ^0.28.0 + jiti: '>=1.21.0' + less: ^4.0.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + '@vitejs/devtools': + optional: true + esbuild: + optional: true + jiti: + optional: true + less: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + 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 + + vue-component-type-helpers@3.3.7: + resolution: {integrity: sha512-Skkhw9agYSgsWqv7bxSOGJZa9SaiJbZVGdXuFWnrzKaQYHnw9qbjD630rw6RyMqDbp54nfLCLw5SZA55if7JLg==} + + vue-demi@0.14.10: + resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==} + engines: {node: '>=12'} + hasBin: true + peerDependencies: + '@vue/composition-api': ^1.0.0-rc.1 + vue: ^3.0.0-0 || ^2.6.0 + peerDependenciesMeta: + '@vue/composition-api': + optional: true + + vue-sonner@1.3.2: + resolution: {integrity: sha512-UbZ48E9VIya3ToiRHAZUbodKute/z/M1iT8/3fU8zEbwBRE11AKuHikssv18LMk2gTTr6eMQT4qf6JoLHWuj/A==} + + vue@3.5.39: + resolution: {integrity: sha512-xmZCYabFGcirU8r0fTuvl/LICc1OU620rnqepaJDL/a141ZigkG7AyaxQLdqJ02ZRYzWe6YPaDHeQx7MfknQfA==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + w3c-keyname@2.2.8: + resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==} + + web-namespaces@2.0.1: + resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==} + + web-worker@1.5.0: + resolution: {integrity: sha512-RiMReJrTAiA+mBjGONMnjVDP2u3p9R1vkcGz6gDIrOMT3oGuYwX2WRMYI9ipkphSuE5XKEhydbhNEJh4NY9mlw==} + + xxhash-wasm@1.1.0: + resolution: {integrity: sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==} + + yaml@2.9.0: + resolution: {integrity: sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==} + engines: {node: '>= 14.6'} + hasBin: true + + 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: + + '@ai-sdk/gateway@3.0.13(zod@4.4.3)': + dependencies: + '@ai-sdk/provider': 3.0.2 + '@ai-sdk/provider-utils': 4.0.5(zod@4.4.3) + '@vercel/oidc': 3.1.0 + zod: 4.4.3 + + '@ai-sdk/provider-utils@4.0.5(zod@4.4.3)': + dependencies: + '@ai-sdk/provider': 3.0.2 + '@standard-schema/spec': 1.1.0 + eventsource-parser: 3.1.0 + zod: 4.4.3 + + '@ai-sdk/provider@3.0.2': + dependencies: + json-schema: 0.4.0 + + '@ai-sdk/vue@3.0.33(vue@3.5.39)(zod@4.4.3)': + dependencies: + '@ai-sdk/provider-utils': 4.0.5(zod@4.4.3) + ai: 6.0.33(zod@4.4.3) + swrv: 1.2.0(vue@3.5.39) + vue: 3.5.39 + transitivePeerDependencies: + - zod + + '@astrojs/compiler-binding-darwin-arm64@0.3.1': + optional: true + + '@astrojs/compiler-binding-darwin-x64@0.3.1': + optional: true + + '@astrojs/compiler-binding-linux-arm64-gnu@0.3.1': + optional: true + + '@astrojs/compiler-binding-linux-arm64-musl@0.3.1': + optional: true + + '@astrojs/compiler-binding-linux-x64-gnu@0.3.1': + optional: true + + '@astrojs/compiler-binding-linux-x64-musl@0.3.1': + optional: true + + '@astrojs/compiler-binding-wasm32-wasi@0.3.1(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)': + dependencies: + '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2) + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' + optional: true + + '@astrojs/compiler-binding-win32-arm64-msvc@0.3.1': + optional: true + + '@astrojs/compiler-binding-win32-x64-msvc@0.3.1': + optional: true + + '@astrojs/compiler-binding@0.3.1(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)': + optionalDependencies: + '@astrojs/compiler-binding-darwin-arm64': 0.3.1 + '@astrojs/compiler-binding-darwin-x64': 0.3.1 + '@astrojs/compiler-binding-linux-arm64-gnu': 0.3.1 + '@astrojs/compiler-binding-linux-arm64-musl': 0.3.1 + '@astrojs/compiler-binding-linux-x64-gnu': 0.3.1 + '@astrojs/compiler-binding-linux-x64-musl': 0.3.1 + '@astrojs/compiler-binding-wasm32-wasi': 0.3.1(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2) + '@astrojs/compiler-binding-win32-arm64-msvc': 0.3.1 + '@astrojs/compiler-binding-win32-x64-msvc': 0.3.1 + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' + + '@astrojs/compiler-rs@0.3.1(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)': + dependencies: + '@astrojs/compiler-binding': 0.3.1(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2) + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' + + '@astrojs/internal-helpers@0.10.1': + dependencies: + '@types/hast': 3.0.5 + '@types/mdast': 4.0.4 + js-yaml: 4.3.0 + picomatch: 4.0.5 + retext-smartypants: 6.2.0 + shiki: 4.3.1 + smol-toml: 1.7.0 + unified: 11.0.5 + + '@astrojs/markdown-remark@7.2.1': + dependencies: + '@astrojs/internal-helpers': 0.10.1 + '@astrojs/prism': 4.0.2 + github-slugger: 2.0.0 + hast-util-from-html: 2.0.3 + hast-util-to-text: 4.0.2 + 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 + 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/markdown-satteri@0.3.4': + dependencies: + '@astrojs/internal-helpers': 0.10.1 + '@astrojs/prism': 4.0.2 + github-slugger: 2.0.0 + hast-util-from-html: 2.0.3 + satteri: 0.9.5 + + '@astrojs/mdx@7.0.3(@astrojs/markdown-satteri@0.3.4)(astro@7.0.9(@astrojs/markdown-remark@7.2.1)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)(@types/node@24.13.3)(yaml@2.9.0))': + dependencies: + '@astrojs/internal-helpers': 0.10.1 + '@astrojs/markdown-remark': 7.2.1 + '@mdx-js/mdx': 3.1.1 + acorn: 8.17.0 + astro: 7.0.9(@astrojs/markdown-remark@7.2.1)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)(@types/node@24.13.3)(yaml@2.9.0) + es-module-lexer: 2.3.1 + 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 + optionalDependencies: + '@astrojs/markdown-satteri': 0.3.4 + transitivePeerDependencies: + - supports-color + + '@astrojs/prism@4.0.2': + dependencies: + prismjs: 1.30.0 + + '@astrojs/sitemap@3.7.3': + dependencies: + sitemap: 9.0.1 + stream-replace-string: 2.0.0 + zod: 4.4.3 + + '@astrojs/starlight@0.41.3(@astrojs/markdown-remark@7.2.1)(astro@7.0.9(@astrojs/markdown-remark@7.2.1)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)(@types/node@24.13.3)(yaml@2.9.0))': + dependencies: + '@astrojs/markdown-satteri': 0.3.4 + '@astrojs/mdx': 7.0.3(@astrojs/markdown-satteri@0.3.4)(astro@7.0.9(@astrojs/markdown-remark@7.2.1)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)(@types/node@24.13.3)(yaml@2.9.0)) + '@astrojs/sitemap': 3.7.3 + '@pagefind/default-ui': 1.5.2 + '@types/hast': 3.0.5 + '@types/js-yaml': 4.0.9 + '@types/mdast': 4.0.4 + astro: 7.0.9(@astrojs/markdown-remark@7.2.1)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)(@types/node@24.13.3)(yaml@2.9.0) + astro-expressive-code: 0.44.0(astro@7.0.9(@astrojs/markdown-remark@7.2.1)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)(@types/node@24.13.3)(yaml@2.9.0)) + bcp-47: 2.1.1 + 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.3.6 + js-yaml: 4.3.0 + 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 + satteri: 0.9.5 + ultrahtml: 1.7.0 + unified: 11.0.5 + unist-util-visit: 5.1.0 + vfile: 6.0.3 + optionalDependencies: + '@astrojs/markdown-remark': 7.2.1 + transitivePeerDependencies: + - supports-color + - typescript + + '@astrojs/telemetry@3.3.3': + dependencies: + ci-info: 4.4.0 + dset: 3.1.4 + is-docker: 4.0.0 + package-manager-detector: 1.7.0 + + '@babel/helper-string-parser@7.29.7': {} + + '@babel/helper-validator-identifier@7.29.7': {} + + '@babel/parser@7.29.7': + dependencies: + '@babel/types': 7.29.7 + + '@babel/types@7.29.7': + dependencies: + '@babel/helper-string-parser': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + + '@bruits/satteri-darwin-arm64@0.9.5': + optional: true + + '@bruits/satteri-darwin-x64@0.9.5': + optional: true + + '@bruits/satteri-linux-arm64-gnu@0.9.5': + optional: true + + '@bruits/satteri-linux-arm64-musl@0.9.5': + optional: true + + '@bruits/satteri-linux-x64-gnu@0.9.5': + optional: true + + '@bruits/satteri-linux-x64-musl@0.9.5': + optional: true + + '@bruits/satteri-wasm32-wasi@0.9.5': + dependencies: + '@emnapi/core': 1.11.1 + '@emnapi/runtime': 1.11.1 + '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) + optional: true + + '@bruits/satteri-win32-arm64-msvc@0.9.5': + optional: true + + '@bruits/satteri-win32-x64-msvc@0.9.5': + optional: true + + '@capsizecss/unpack@4.0.1': + dependencies: + fontkitten: 1.0.3 + + '@clack/core@1.4.3': + dependencies: + fast-wrap-ansi: 0.2.2 + sisteransi: 1.0.5 + + '@clack/prompts@1.7.0': + dependencies: + '@clack/core': 1.4.3 + fast-string-width: 3.0.2 + fast-wrap-ansi: 0.2.2 + sisteransi: 1.0.5 + + '@codemirror/autocomplete@6.20.3': + dependencies: + '@codemirror/language': 6.12.4 + '@codemirror/state': 6.7.1 + '@codemirror/view': 6.43.6 + '@lezer/common': 1.5.2 + + '@codemirror/commands@6.10.4': + dependencies: + '@codemirror/language': 6.12.4 + '@codemirror/state': 6.7.1 + '@codemirror/view': 6.43.6 + '@lezer/common': 1.5.2 + + '@codemirror/lang-css@6.3.1': + dependencies: + '@codemirror/autocomplete': 6.20.3 + '@codemirror/language': 6.12.4 + '@codemirror/state': 6.7.1 + '@lezer/common': 1.5.2 + '@lezer/css': 1.3.4 + + '@codemirror/lang-html@6.4.11': + dependencies: + '@codemirror/autocomplete': 6.20.3 + '@codemirror/lang-css': 6.3.1 + '@codemirror/lang-javascript': 6.2.5 + '@codemirror/language': 6.12.4 + '@codemirror/state': 6.7.1 + '@codemirror/view': 6.43.6 + '@lezer/common': 1.5.2 + '@lezer/css': 1.3.4 + '@lezer/html': 1.3.13 + + '@codemirror/lang-javascript@6.2.5': + dependencies: + '@codemirror/autocomplete': 6.20.3 + '@codemirror/language': 6.12.4 + '@codemirror/lint': 6.9.7 + '@codemirror/state': 6.7.1 + '@codemirror/view': 6.43.6 + '@lezer/common': 1.5.2 + '@lezer/javascript': 1.5.4 + + '@codemirror/lang-json@6.0.2': + dependencies: + '@codemirror/language': 6.12.4 + '@lezer/json': 1.0.3 + + '@codemirror/lang-xml@6.1.0': + dependencies: + '@codemirror/autocomplete': 6.20.3 + '@codemirror/language': 6.12.4 + '@codemirror/state': 6.7.1 + '@codemirror/view': 6.43.6 + '@lezer/common': 1.5.2 + '@lezer/xml': 1.0.6 + + '@codemirror/lang-yaml@6.1.3': + dependencies: + '@codemirror/autocomplete': 6.20.3 + '@codemirror/language': 6.12.4 + '@codemirror/state': 6.7.1 + '@lezer/common': 1.5.2 + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.10 + '@lezer/yaml': 1.0.4 + + '@codemirror/language@6.12.4': + dependencies: + '@codemirror/state': 6.7.1 + '@codemirror/view': 6.43.6 + '@lezer/common': 1.5.2 + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.10 + style-mod: 4.1.3 + + '@codemirror/lint@6.9.7': + dependencies: + '@codemirror/state': 6.7.1 + '@codemirror/view': 6.43.6 + crelt: 1.0.7 + + '@codemirror/state@6.7.1': + dependencies: + '@marijn/find-cluster-break': 1.0.3 + + '@codemirror/view@6.43.6': + dependencies: + '@codemirror/state': 6.7.1 + crelt: 1.0.7 + style-mod: 4.1.3 + w3c-keyname: 2.2.8 + + '@ctrl/tinycolor@4.2.0': {} + + '@emnapi/core@1.11.1': + dependencies: + '@emnapi/wasi-threads': 1.2.2 + tslib: 2.8.1 + optional: true + + '@emnapi/runtime@1.11.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@emnapi/runtime@1.11.2': + dependencies: + tslib: 2.8.1 + optional: true + + '@emnapi/wasi-threads@1.2.2': + dependencies: + tslib: 2.8.1 + optional: true + + '@esbuild/aix-ppc64@0.28.1': + optional: true + + '@esbuild/android-arm64@0.28.1': + optional: true + + '@esbuild/android-arm@0.28.1': + optional: true + + '@esbuild/android-x64@0.28.1': + optional: true + + '@esbuild/darwin-arm64@0.28.1': + optional: true + + '@esbuild/darwin-x64@0.28.1': + optional: true + + '@esbuild/freebsd-arm64@0.28.1': + optional: true + + '@esbuild/freebsd-x64@0.28.1': + optional: true + + '@esbuild/linux-arm64@0.28.1': + optional: true + + '@esbuild/linux-arm@0.28.1': + optional: true + + '@esbuild/linux-ia32@0.28.1': + optional: true + + '@esbuild/linux-loong64@0.28.1': + optional: true + + '@esbuild/linux-mips64el@0.28.1': + optional: true + + '@esbuild/linux-ppc64@0.28.1': + optional: true + + '@esbuild/linux-riscv64@0.28.1': + optional: true + + '@esbuild/linux-s390x@0.28.1': + optional: true + + '@esbuild/linux-x64@0.28.1': + optional: true + + '@esbuild/netbsd-arm64@0.28.1': + optional: true + + '@esbuild/netbsd-x64@0.28.1': + optional: true + + '@esbuild/openbsd-arm64@0.28.1': + optional: true + + '@esbuild/openbsd-x64@0.28.1': + optional: true + + '@esbuild/openharmony-arm64@0.28.1': + optional: true + + '@esbuild/sunos-x64@0.28.1': + optional: true + + '@esbuild/win32-arm64@0.28.1': + optional: true + + '@esbuild/win32-ia32@0.28.1': + optional: true + + '@esbuild/win32-x64@0.28.1': + optional: true + + '@expressive-code/core@0.44.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.19 + postcss-nested: 6.2.0(postcss@8.5.19) + unist-util-visit: 5.1.0 + unist-util-visit-parents: 6.0.2 + + '@expressive-code/plugin-frames@0.44.0': + dependencies: + '@expressive-code/core': 0.44.0 + + '@expressive-code/plugin-shiki@0.44.0': + dependencies: + '@expressive-code/core': 0.44.0 + shiki: 4.3.1 + + '@expressive-code/plugin-text-markers@0.44.0': + dependencies: + '@expressive-code/core': 0.44.0 + + '@floating-ui/core@1.8.0': + dependencies: + '@floating-ui/utils': 0.2.12 + + '@floating-ui/dom@1.8.0': + dependencies: + '@floating-ui/core': 1.8.0 + '@floating-ui/utils': 0.2.12 + + '@floating-ui/utils@0.2.10': {} + + '@floating-ui/utils@0.2.12': {} + + '@floating-ui/vue@1.1.11(vue@3.5.39)': + dependencies: + '@floating-ui/dom': 1.8.0 + '@floating-ui/utils': 0.2.12 + vue-demi: 0.14.10(vue@3.5.39) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + + '@floating-ui/vue@1.1.9(vue@3.5.39)': + dependencies: + '@floating-ui/dom': 1.8.0 + '@floating-ui/utils': 0.2.10 + vue-demi: 0.14.10(vue@3.5.39) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + + '@headlessui/tailwindcss@0.2.2(tailwindcss@4.3.2)': + dependencies: + tailwindcss: 4.3.2 + + '@headlessui/vue@1.7.23(vue@3.5.39)': + dependencies: + '@tanstack/vue-virtual': 3.13.32(vue@3.5.39) + vue: 3.5.39 + + '@img/colour@1.1.0': + optional: true + + '@img/sharp-darwin-arm64@0.35.3': + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.3.2 + optional: true + + '@img/sharp-darwin-x64@0.35.3': + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.3.2 + optional: true + + '@img/sharp-freebsd-wasm32@0.35.3': + dependencies: + '@img/sharp-wasm32': 0.35.3 + optional: true + + '@img/sharp-libvips-darwin-arm64@1.3.2': + optional: true + + '@img/sharp-libvips-darwin-x64@1.3.2': + optional: true + + '@img/sharp-libvips-linux-arm64@1.3.2': + optional: true + + '@img/sharp-libvips-linux-arm@1.3.2': + optional: true + + '@img/sharp-libvips-linux-ppc64@1.3.2': + optional: true + + '@img/sharp-libvips-linux-riscv64@1.3.2': + optional: true + + '@img/sharp-libvips-linux-s390x@1.3.2': + optional: true + + '@img/sharp-libvips-linux-x64@1.3.2': + optional: true + + '@img/sharp-libvips-linuxmusl-arm64@1.3.2': + optional: true + + '@img/sharp-libvips-linuxmusl-x64@1.3.2': + optional: true + + '@img/sharp-linux-arm64@0.35.3': + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.3.2 + optional: true + + '@img/sharp-linux-arm@0.35.3': + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.3.2 + optional: true + + '@img/sharp-linux-ppc64@0.35.3': + optionalDependencies: + '@img/sharp-libvips-linux-ppc64': 1.3.2 + optional: true + + '@img/sharp-linux-riscv64@0.35.3': + optionalDependencies: + '@img/sharp-libvips-linux-riscv64': 1.3.2 + optional: true + + '@img/sharp-linux-s390x@0.35.3': + optionalDependencies: + '@img/sharp-libvips-linux-s390x': 1.3.2 + optional: true + + '@img/sharp-linux-x64@0.35.3': + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.3.2 + optional: true + + '@img/sharp-linuxmusl-arm64@0.35.3': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.3.2 + optional: true + + '@img/sharp-linuxmusl-x64@0.35.3': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.3.2 + optional: true + + '@img/sharp-wasm32@0.35.3': + dependencies: + '@emnapi/runtime': 1.11.2 + optional: true + + '@img/sharp-webcontainers-wasm32@0.35.3': + dependencies: + '@img/sharp-wasm32': 0.35.3 + optional: true + + '@img/sharp-win32-arm64@0.35.3': + optional: true + + '@img/sharp-win32-ia32@0.35.3': + optional: true + + '@img/sharp-win32-x64@0.35.3': + optional: true + + '@internationalized/date@3.12.2': + dependencies: + '@swc/helpers': 0.5.23 + + '@internationalized/number@3.6.7': + dependencies: + '@swc/helpers': 0.5.23 + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@lezer/common@1.5.2': {} + + '@lezer/css@1.3.4': + dependencies: + '@lezer/common': 1.5.2 + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.10 + + '@lezer/highlight@1.2.3': + dependencies: + '@lezer/common': 1.5.2 + + '@lezer/html@1.3.13': + dependencies: + '@lezer/common': 1.5.2 + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.10 + + '@lezer/javascript@1.5.4': + dependencies: + '@lezer/common': 1.5.2 + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.10 + + '@lezer/json@1.0.3': + dependencies: + '@lezer/common': 1.5.2 + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.10 + + '@lezer/lr@1.4.10': + dependencies: + '@lezer/common': 1.5.2 + + '@lezer/xml@1.0.6': + dependencies: + '@lezer/common': 1.5.2 + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.10 + + '@lezer/yaml@1.0.4': + dependencies: + '@lezer/common': 1.5.2 + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.10 + + '@marijn/find-cluster-break@1.0.3': {} + + '@mdx-js/mdx@3.1.1': + dependencies: + '@types/estree': 1.0.9 + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.5 + '@types/mdx': 2.0.14 + acorn: 8.17.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.17.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 + + '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': + dependencies: + '@emnapi/core': 1.11.1 + '@emnapi/runtime': 1.11.1 + '@tybys/wasm-util': 0.10.3 + optional: true + + '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)': + dependencies: + '@emnapi/core': 1.11.1 + '@emnapi/runtime': 1.11.2 + '@tybys/wasm-util': 0.10.3 + optional: true + + '@opentelemetry/api@1.9.0': {} + + '@oslojs/encoding@1.1.0': {} + + '@oxc-project/types@0.139.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 + + '@phosphor-icons/core@2.1.1': {} + + '@playwright/test@1.59.1': + dependencies: + playwright: 1.59.1 + + '@redocly/cli@2.39.0': {} + + '@replit/codemirror-css-color-picker@6.3.0(@codemirror/language@6.12.4)(@codemirror/state@6.7.1)(@codemirror/view@6.43.6)': + dependencies: + '@codemirror/language': 6.12.4 + '@codemirror/state': 6.7.1 + '@codemirror/view': 6.43.6 + + '@rolldown/binding-android-arm64@1.1.5': + optional: true + + '@rolldown/binding-darwin-arm64@1.1.5': + optional: true + + '@rolldown/binding-darwin-x64@1.1.5': + optional: true + + '@rolldown/binding-freebsd-x64@1.1.5': + optional: true + + '@rolldown/binding-linux-arm-gnueabihf@1.1.5': + optional: true + + '@rolldown/binding-linux-arm64-gnu@1.1.5': + optional: true + + '@rolldown/binding-linux-arm64-musl@1.1.5': + optional: true + + '@rolldown/binding-linux-ppc64-gnu@1.1.5': + optional: true + + '@rolldown/binding-linux-s390x-gnu@1.1.5': + optional: true + + '@rolldown/binding-linux-x64-gnu@1.1.5': + optional: true + + '@rolldown/binding-linux-x64-musl@1.1.5': + optional: true + + '@rolldown/binding-openharmony-arm64@1.1.5': + optional: true + + '@rolldown/binding-wasm32-wasi@1.1.5': + dependencies: + '@emnapi/core': 1.11.1 + '@emnapi/runtime': 1.11.1 + '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) + optional: true + + '@rolldown/binding-win32-arm64-msvc@1.1.5': + optional: true + + '@rolldown/binding-win32-x64-msvc@1.1.5': + optional: true + + '@rolldown/pluginutils@1.0.1': {} + + '@rollup/pluginutils@5.4.0': + dependencies: + '@types/estree': 1.0.9 + estree-walker: 2.0.2 + picomatch: 4.0.5 + + '@scalar/agent-chat@0.12.19(tailwindcss@4.3.2)(zod@4.4.3)': + dependencies: + '@ai-sdk/vue': 3.0.33(vue@3.5.39)(zod@4.4.3) + '@scalar/api-client': 3.13.4(tailwindcss@4.3.2) + '@scalar/components': 0.27.6(tailwindcss@4.3.2) + '@scalar/helpers': 0.9.0 + '@scalar/icons': 0.7.3 + '@scalar/json-magic': 0.12.17 + '@scalar/openapi-types': 0.9.1 + '@scalar/schemas': 0.7.2 + '@scalar/themes': 0.16.2 + '@scalar/types': 0.16.2 + '@scalar/use-toasts': 0.10.2 + '@scalar/validation': 0.6.0 + '@scalar/workspace-store': 0.55.4 + '@vueuse/core': 13.9.0(vue@3.5.39) + ai: 6.0.33(zod@4.4.3) + js-base64: 3.9.1 + neverpanic: 0.0.8 + truncate-json: 3.0.1 + vue: 3.5.39 + transitivePeerDependencies: + - '@vue/composition-api' + - async-validator + - axios + - change-case + - drauu + - idb-keyval + - jwt-decode + - nprogress + - qrcode + - sortablejs + - supports-color + - tailwindcss + - typescript + - universal-cookie + - zod + + '@scalar/api-client@3.13.4(tailwindcss@4.3.2)': + dependencies: + '@headlessui/tailwindcss': 0.2.2(tailwindcss@4.3.2) + '@headlessui/vue': 1.7.23(vue@3.5.39) + '@scalar/blocks': 0.1.5(tailwindcss@4.3.2) + '@scalar/components': 0.27.6(tailwindcss@4.3.2) + '@scalar/helpers': 0.9.0 + '@scalar/icons': 0.7.3 + '@scalar/oas-utils': 0.19.5 + '@scalar/openapi-types': 0.9.1 + '@scalar/sidebar': 0.9.30(tailwindcss@4.3.2) + '@scalar/snippetz': 0.9.21 + '@scalar/themes': 0.16.2 + '@scalar/typebox': 0.1.3 + '@scalar/types': 0.16.2 + '@scalar/use-codemirror': 0.14.12 + '@scalar/use-hooks': 0.4.7 + '@scalar/use-toasts': 0.10.2 + '@scalar/workspace-store': 0.55.4 + '@vueuse/core': 13.9.0(vue@3.5.39) + '@vueuse/integrations': 13.9.0(focus-trap@7.8.0)(fuse.js@7.5.0)(vue@3.5.39) + focus-trap: 7.8.0 + fuse.js: 7.5.0 + js-base64: 3.9.1 + jsonc-parser: 3.3.1 + nanoid: 5.1.16 + pretty-ms: 9.3.0 + radix-vue: 1.9.17(vue@3.5.39) + set-cookie-parser: 3.1.0 + vue: 3.5.39 + yaml: 2.9.0 + zod: 4.4.3 + transitivePeerDependencies: + - '@vue/composition-api' + - async-validator + - axios + - change-case + - drauu + - idb-keyval + - jwt-decode + - nprogress + - qrcode + - sortablejs + - supports-color + - tailwindcss + - typescript + - universal-cookie + + '@scalar/api-reference@1.62.6(tailwindcss@4.3.2)(zod@4.4.3)': + dependencies: + '@headlessui/vue': 1.7.23(vue@3.5.39) + '@scalar/agent-chat': 0.12.19(tailwindcss@4.3.2)(zod@4.4.3) + '@scalar/api-client': 3.13.4(tailwindcss@4.3.2) + '@scalar/blocks': 0.1.5(tailwindcss@4.3.2) + '@scalar/code-highlight': 0.4.1 + '@scalar/components': 0.27.6(tailwindcss@4.3.2) + '@scalar/helpers': 0.9.0 + '@scalar/icons': 0.7.3 + '@scalar/oas-utils': 0.19.5 + '@scalar/schemas': 0.7.2 + '@scalar/sidebar': 0.9.30(tailwindcss@4.3.2) + '@scalar/snippetz': 0.9.21 + '@scalar/themes': 0.16.2 + '@scalar/types': 0.16.2 + '@scalar/use-hooks': 0.4.7 + '@scalar/use-toasts': 0.10.2 + '@scalar/validation': 0.6.0 + '@scalar/workspace-store': 0.55.4 + '@unhead/vue': 2.1.15(vue@3.5.39) + '@vueuse/core': 13.9.0(vue@3.5.39) + fuse.js: 7.5.0 + microdiff: 1.5.0 + nanoid: 5.1.16 + vue: 3.5.39 + yaml: 2.9.0 + transitivePeerDependencies: + - '@vue/composition-api' + - async-validator + - axios + - change-case + - drauu + - idb-keyval + - jwt-decode + - nprogress + - qrcode + - sortablejs + - supports-color + - tailwindcss + - typescript + - universal-cookie + - zod + + '@scalar/asyncapi-upgrader@0.1.2': + dependencies: + '@scalar/helpers': 0.9.0 + + '@scalar/blocks@0.1.5(tailwindcss@4.3.2)': + dependencies: + '@scalar/components': 0.27.6(tailwindcss@4.3.2) + '@scalar/helpers': 0.9.0 + '@scalar/icons': 0.7.3 + '@scalar/snippetz': 0.9.21 + '@scalar/themes': 0.16.2 + '@scalar/types': 0.16.2 + '@scalar/workspace-store': 0.55.4 + '@types/har-format': 1.2.16 + js-base64: 3.9.1 + vue: 3.5.39 + transitivePeerDependencies: + - '@vue/composition-api' + - supports-color + - tailwindcss + - typescript + + '@scalar/code-highlight@0.4.1': + dependencies: + hast-util-to-text: 4.0.2 + highlight.js: 11.11.1 + lowlight: 3.3.0 + rehype-external-links: 3.0.0 + rehype-format: 5.0.1 + rehype-parse: 9.0.1 + rehype-raw: 7.0.0 + rehype-sanitize: 6.0.0 + rehype-stringify: 10.0.1 + remark-gfm: 4.0.1 + remark-parse: 11.0.0 + remark-rehype: 11.1.2 + remark-stringify: 11.0.0 + unified: 11.0.5 + unist-util-visit: 5.1.0 + transitivePeerDependencies: + - supports-color + + '@scalar/components@0.27.6(tailwindcss@4.3.2)': + dependencies: + '@floating-ui/utils': 0.2.10 + '@floating-ui/vue': 1.1.9(vue@3.5.39) + '@headlessui/tailwindcss': 0.2.2(tailwindcss@4.3.2) + '@headlessui/vue': 1.7.23(vue@3.5.39) + '@scalar/code-highlight': 0.4.1 + '@scalar/helpers': 0.9.0 + '@scalar/icons': 0.7.3 + '@scalar/themes': 0.16.2 + '@scalar/use-hooks': 0.4.7 + '@vueuse/core': 13.9.0(vue@3.5.39) + cva: 1.0.0-beta.4 + radix-vue: 1.9.17(vue@3.5.39) + vue: 3.5.39 + vue-component-type-helpers: 3.3.7 + transitivePeerDependencies: + - '@vue/composition-api' + - supports-color + - tailwindcss + - typescript + + '@scalar/helpers@0.9.0': {} + + '@scalar/icons@0.7.3': + dependencies: + '@phosphor-icons/core': 2.1.1 + '@types/node': 24.13.3 + chalk: 5.6.2 + vue: 3.5.39 + transitivePeerDependencies: + - typescript + + '@scalar/json-magic@0.12.17': + dependencies: + '@scalar/helpers': 0.9.0 + pathe: 2.0.3 + yaml: 2.9.0 + + '@scalar/oas-utils@0.19.5': + dependencies: + '@scalar/helpers': 0.9.0 + '@scalar/themes': 0.16.2 + '@scalar/types': 0.16.2 + '@scalar/workspace-store': 0.55.4 + flatted: 3.4.2 + vue: 3.5.39 + yaml: 2.9.0 + transitivePeerDependencies: + - typescript + + '@scalar/openapi-types@0.9.1': {} + + '@scalar/openapi-upgrader@0.2.9': + dependencies: + '@scalar/openapi-types': 0.9.1 + + '@scalar/schemas@0.7.2': + dependencies: + '@scalar/helpers': 0.9.0 + '@scalar/validation': 0.6.0 + + '@scalar/sidebar@0.9.30(tailwindcss@4.3.2)': + dependencies: + '@scalar/components': 0.27.6(tailwindcss@4.3.2) + '@scalar/helpers': 0.9.0 + '@scalar/icons': 0.7.3 + '@scalar/themes': 0.16.2 + '@scalar/use-hooks': 0.4.7 + '@scalar/workspace-store': 0.55.4 + vue: 3.5.39 + transitivePeerDependencies: + - '@vue/composition-api' + - supports-color + - tailwindcss + - typescript + + '@scalar/snippetz@0.9.21': + dependencies: + '@scalar/helpers': 0.9.0 + '@scalar/types': 0.16.2 + js-base64: 3.9.1 + stringify-object: 6.0.0 + + '@scalar/themes@0.16.2': + dependencies: + nanoid: 5.1.16 + + '@scalar/typebox@0.1.3': {} + + '@scalar/types@0.16.2': + dependencies: + '@scalar/helpers': 0.9.0 + nanoid: 5.1.16 + type-fest: 5.8.0 + zod: 4.4.3 + + '@scalar/use-codemirror@0.14.12': + dependencies: + '@codemirror/autocomplete': 6.20.3 + '@codemirror/commands': 6.10.4 + '@codemirror/lang-css': 6.3.1 + '@codemirror/lang-html': 6.4.11 + '@codemirror/lang-json': 6.0.2 + '@codemirror/lang-xml': 6.1.0 + '@codemirror/lang-yaml': 6.1.3 + '@codemirror/language': 6.12.4 + '@codemirror/lint': 6.9.7 + '@codemirror/state': 6.7.1 + '@codemirror/view': 6.43.6 + '@lezer/common': 1.5.2 + '@lezer/highlight': 1.2.3 + '@replit/codemirror-css-color-picker': 6.3.0(@codemirror/language@6.12.4)(@codemirror/state@6.7.1)(@codemirror/view@6.43.6) + vue: 3.5.39 + transitivePeerDependencies: + - typescript + + '@scalar/use-hooks@0.4.7': + dependencies: + '@scalar/use-toasts': 0.10.2 + '@scalar/validation': 0.6.0 + '@vueuse/core': 13.9.0(vue@3.5.39) + cva: 1.0.0-beta.4 + tailwind-merge: 3.5.0 + vue: 3.5.39 + transitivePeerDependencies: + - typescript + + '@scalar/use-toasts@0.10.2': + dependencies: + vue: 3.5.39 + vue-sonner: 1.3.2 + transitivePeerDependencies: + - typescript + + '@scalar/validation@0.6.0': {} + + '@scalar/workspace-store@0.55.4': + dependencies: + '@scalar/asyncapi-upgrader': 0.1.2 + '@scalar/helpers': 0.9.0 + '@scalar/json-magic': 0.12.17 + '@scalar/openapi-upgrader': 0.2.9 + '@scalar/schemas': 0.7.2 + '@scalar/snippetz': 0.9.21 + '@scalar/typebox': 0.1.3 + '@scalar/types': 0.16.2 + '@scalar/validation': 0.6.0 + js-base64: 3.9.1 + type-fest: 5.8.0 + vue: 3.5.39 + yaml: 2.9.0 + transitivePeerDependencies: + - typescript + + '@shikijs/core@4.3.1': + dependencies: + '@shikijs/primitive': 4.3.1 + '@shikijs/types': 4.3.1 + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.5 + hast-util-to-html: 9.0.5 + + '@shikijs/engine-javascript@4.3.1': + dependencies: + '@shikijs/types': 4.3.1 + '@shikijs/vscode-textmate': 10.0.2 + oniguruma-to-es: 4.3.6 + + '@shikijs/engine-oniguruma@4.3.1': + dependencies: + '@shikijs/types': 4.3.1 + '@shikijs/vscode-textmate': 10.0.2 + + '@shikijs/langs@4.3.1': + dependencies: + '@shikijs/types': 4.3.1 + + '@shikijs/primitive@4.3.1': + dependencies: + '@shikijs/types': 4.3.1 + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.5 + + '@shikijs/themes@4.3.1': + dependencies: + '@shikijs/types': 4.3.1 + + '@shikijs/types@4.3.1': + dependencies: + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.5 + + '@shikijs/vscode-textmate@10.0.2': {} + + '@standard-schema/spec@1.1.0': {} + + '@swc/helpers@0.5.23': + dependencies: + tslib: 2.8.1 + + '@tanstack/virtual-core@3.17.4': {} + + '@tanstack/vue-virtual@3.13.32(vue@3.5.39)': + dependencies: + '@tanstack/virtual-core': 3.17.4 + vue: 3.5.39 + + '@tybys/wasm-util@0.10.3': + dependencies: + tslib: 2.8.1 + optional: true + + '@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.9': {} + + '@types/har-format@1.2.16': {} + + '@types/hast@3.0.5': + 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.14': {} + + '@types/ms@2.1.0': {} + + '@types/nlcst@2.0.3': + dependencies: + '@types/unist': 3.0.3 + + '@types/node@24.13.3': + dependencies: + undici-types: 7.18.2 + + '@types/sax@1.2.7': + dependencies: + '@types/node': 24.13.3 + + '@types/unist@2.0.11': {} + + '@types/unist@3.0.3': {} + + '@types/web-bluetooth@0.0.20': {} + + '@types/web-bluetooth@0.0.21': {} + + '@ungap/structured-clone@1.3.3': {} + + '@unhead/vue@2.1.15(vue@3.5.39)': + dependencies: + hookable: 6.1.1 + unhead: 2.1.15 + vue: 3.5.39 + + '@vercel/oidc@3.1.0': {} + + '@vue/compiler-core@3.5.39': + dependencies: + '@babel/parser': 7.29.7 + '@vue/shared': 3.5.39 + entities: 7.0.1 + estree-walker: 2.0.2 + source-map-js: 1.2.1 + + '@vue/compiler-dom@3.5.39': + dependencies: + '@vue/compiler-core': 3.5.39 + '@vue/shared': 3.5.39 + + '@vue/compiler-sfc@3.5.39': + dependencies: + '@babel/parser': 7.29.7 + '@vue/compiler-core': 3.5.39 + '@vue/compiler-dom': 3.5.39 + '@vue/compiler-ssr': 3.5.39 + '@vue/shared': 3.5.39 + estree-walker: 2.0.2 + magic-string: 0.30.21 + postcss: 8.5.19 + source-map-js: 1.2.1 + + '@vue/compiler-ssr@3.5.39': + dependencies: + '@vue/compiler-dom': 3.5.39 + '@vue/shared': 3.5.39 + + '@vue/reactivity@3.5.39': + dependencies: + '@vue/shared': 3.5.39 + + '@vue/runtime-core@3.5.39': + dependencies: + '@vue/reactivity': 3.5.39 + '@vue/shared': 3.5.39 + + '@vue/runtime-dom@3.5.39': + dependencies: + '@vue/reactivity': 3.5.39 + '@vue/runtime-core': 3.5.39 + '@vue/shared': 3.5.39 + csstype: 3.2.3 + + '@vue/server-renderer@3.5.39(vue@3.5.39)': + dependencies: + '@vue/compiler-ssr': 3.5.39 + '@vue/shared': 3.5.39 + vue: 3.5.39 + + '@vue/shared@3.5.39': {} + + '@vueuse/core@10.11.1(vue@3.5.39)': + dependencies: + '@types/web-bluetooth': 0.0.20 + '@vueuse/metadata': 10.11.1 + '@vueuse/shared': 10.11.1(vue@3.5.39) + vue-demi: 0.14.10(vue@3.5.39) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + + '@vueuse/core@13.9.0(vue@3.5.39)': + dependencies: + '@types/web-bluetooth': 0.0.21 + '@vueuse/metadata': 13.9.0 + '@vueuse/shared': 13.9.0(vue@3.5.39) + vue: 3.5.39 + + '@vueuse/integrations@13.9.0(focus-trap@7.8.0)(fuse.js@7.5.0)(vue@3.5.39)': + dependencies: + '@vueuse/core': 13.9.0(vue@3.5.39) + '@vueuse/shared': 13.9.0(vue@3.5.39) + vue: 3.5.39 + optionalDependencies: + focus-trap: 7.8.0 + fuse.js: 7.5.0 + + '@vueuse/metadata@10.11.1': {} + + '@vueuse/metadata@13.9.0': {} + + '@vueuse/shared@10.11.1(vue@3.5.39)': + dependencies: + vue-demi: 0.14.10(vue@3.5.39) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + + '@vueuse/shared@13.9.0(vue@3.5.39)': + dependencies: + vue: 3.5.39 + + acorn-jsx@5.3.2(acorn@8.17.0): + dependencies: + acorn: 8.17.0 + + acorn@8.17.0: {} + + ai@6.0.33(zod@4.4.3): + dependencies: + '@ai-sdk/gateway': 3.0.13(zod@4.4.3) + '@ai-sdk/provider': 3.0.2 + '@ai-sdk/provider-utils': 4.0.5(zod@4.4.3) + '@opentelemetry/api': 1.9.0 + zod: 4.4.3 + + am-i-vibing@0.4.0: + dependencies: + process-ancestry: 0.1.0 + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.2 + + arg@5.0.2: {} + + argparse@2.0.1: {} + + aria-hidden@1.2.6: + dependencies: + tslib: 2.8.1 + + aria-query@5.3.2: {} + + array-iterate@2.0.1: {} + + astring@1.9.0: {} + + astro-expressive-code@0.44.0(astro@7.0.9(@astrojs/markdown-remark@7.2.1)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)(@types/node@24.13.3)(yaml@2.9.0)): + dependencies: + astro: 7.0.9(@astrojs/markdown-remark@7.2.1)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)(@types/node@24.13.3)(yaml@2.9.0) + rehype-expressive-code: 0.44.0 + url-extras: 0.1.0 + + astro@7.0.9(@astrojs/markdown-remark@7.2.1)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)(@types/node@24.13.3)(yaml@2.9.0): + dependencies: + '@astrojs/compiler-rs': 0.3.1(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2) + '@astrojs/internal-helpers': 0.10.1 + '@astrojs/markdown-satteri': 0.3.4 + '@astrojs/telemetry': 3.3.3 + '@capsizecss/unpack': 4.0.1 + '@clack/prompts': 1.7.0 + '@oslojs/encoding': 1.1.0 + '@rollup/pluginutils': 5.4.0 + am-i-vibing: 0.4.0 + 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.1 + diff: 8.0.4 + dset: 3.1.4 + es-module-lexer: 2.3.1 + esbuild: 0.28.1 + 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.3.0 + jsonc-parser: 3.3.1 + magic-string: 0.30.21 + magicast: 0.5.3 + mrmime: 2.0.1 + neotraverse: 0.6.18 + obug: 2.1.3 + p-limit: 7.3.0 + p-queue: 9.3.1 + package-manager-detector: 1.7.0 + piccolore: 0.1.3 + picomatch: 4.0.5 + semver: 7.8.5 + shiki: 4.3.1 + smol-toml: 1.7.0 + svgo: 4.0.2 + tinyclip: 0.1.15 + tinyexec: 1.2.4 + tinyglobby: 0.2.17 + ultrahtml: 1.7.0 + unifont: 0.7.4 + unstorage: 1.17.5 + vite: 8.1.4(@types/node@24.13.3)(esbuild@0.28.1)(yaml@2.9.0) + vitefu: 1.1.3(vite@8.1.4(@types/node@24.13.3)(esbuild@0.28.1)(yaml@2.9.0)) + xxhash-wasm: 1.1.0 + yargs-parser: 22.0.0 + zod: 4.4.3 + optionalDependencies: + '@astrojs/markdown-remark': 7.2.1 + sharp: 0.35.3(@types/node@24.13.3) + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@emnapi/core' + - '@emnapi/runtime' + - '@netlify/blobs' + - '@planetscale/database' + - '@types/node' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - '@vitejs/devtools' + - aws4fetch + - db0 + - idb-keyval + - ioredis + - jiti + - less + - rollup + - sass + - sass-embedded + - stylus + - sugarss + - terser + - tsx + - uploadthing + - yaml + + axobject-query@4.1.0: {} + + bail@2.0.2: {} + + bcp-47-match@2.0.3: {} + + bcp-47@2.1.1: + dependencies: + is-alphabetical: 2.0.1 + is-alphanumerical: 2.0.1 + is-decimal: 2.0.1 + + boolbase@1.0.0: {} + + ccount@2.0.1: {} + + chalk@5.6.2: {} + + 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: {} + + convert-hrtime@5.0.0: {} + + cookie-es@1.2.3: {} + + cookie@1.1.1: {} + + crelt@1.0.7: {} + + 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 + + csstype@3.2.3: {} + + cva@1.0.0-beta.4: + dependencies: + clsx: 2.1.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: {} + + devalue@5.8.1: {} + + 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: {} + + entities@7.0.1: {} + + es-module-lexer@2.3.1: {} + + 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.17.0 + esast-util-from-estree: 2.0.0 + vfile-message: 4.0.3 + + esbuild@0.28.1: + optionalDependencies: + '@esbuild/aix-ppc64': 0.28.1 + '@esbuild/android-arm': 0.28.1 + '@esbuild/android-arm64': 0.28.1 + '@esbuild/android-x64': 0.28.1 + '@esbuild/darwin-arm64': 0.28.1 + '@esbuild/darwin-x64': 0.28.1 + '@esbuild/freebsd-arm64': 0.28.1 + '@esbuild/freebsd-x64': 0.28.1 + '@esbuild/linux-arm': 0.28.1 + '@esbuild/linux-arm64': 0.28.1 + '@esbuild/linux-ia32': 0.28.1 + '@esbuild/linux-loong64': 0.28.1 + '@esbuild/linux-mips64el': 0.28.1 + '@esbuild/linux-ppc64': 0.28.1 + '@esbuild/linux-riscv64': 0.28.1 + '@esbuild/linux-s390x': 0.28.1 + '@esbuild/linux-x64': 0.28.1 + '@esbuild/netbsd-arm64': 0.28.1 + '@esbuild/netbsd-x64': 0.28.1 + '@esbuild/openbsd-arm64': 0.28.1 + '@esbuild/openbsd-x64': 0.28.1 + '@esbuild/openharmony-arm64': 0.28.1 + '@esbuild/sunos-x64': 0.28.1 + '@esbuild/win32-arm64': 0.28.1 + '@esbuild/win32-ia32': 0.28.1 + '@esbuild/win32-x64': 0.28.1 + + 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: {} + + eventsource-parser@3.1.0: {} + + expressive-code@0.44.0: + dependencies: + '@expressive-code/core': 0.44.0 + '@expressive-code/plugin-frames': 0.44.0 + '@expressive-code/plugin-shiki': 0.44.0 + '@expressive-code/plugin-text-markers': 0.44.0 + + extend@3.0.2: {} + + fast-deep-equal@3.1.3: {} + + 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.2: + dependencies: + fast-string-width: 3.0.2 + + fdir@6.5.0(picomatch@4.0.5): + optionalDependencies: + picomatch: 4.0.5 + + flatted@3.4.2: {} + + flattie@1.1.1: {} + + focus-trap@7.8.0: + dependencies: + tabbable: 6.5.0 + + fontace@0.4.1: + dependencies: + fontkitten: 1.0.3 + + fontkitten@1.0.3: + dependencies: + tiny-inflate: 1.0.3 + + fsevents@2.3.2: + optional: true + + fsevents@2.3.3: + optional: true + + function-timeout@1.0.2: {} + + fuse.js@7.5.0: {} + + get-own-enumerable-keys@1.0.0: {} + + get-tsconfig@5.0.0-beta.4: + dependencies: + resolve-pkg-maps: 1.0.0 + + github-slugger@2.0.0: {} + + guess-json-indent@3.0.1: {} + + 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.5 + hast-util-is-element: 3.0.0 + + hast-util-format@1.1.0: + dependencies: + '@types/hast': 3.0.5 + 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.5 + 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.5 + '@types/unist': 3.0.3 + devlop: 1.1.0 + hastscript: 9.0.1 + property-information: 7.2.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.5 + + hast-util-is-body-ok-link@3.0.1: + dependencies: + '@types/hast': 3.0.5 + + hast-util-is-element@3.0.0: + dependencies: + '@types/hast': 3.0.5 + + hast-util-minify-whitespace@1.0.1: + dependencies: + '@types/hast': 3.0.5 + 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.5 + + hast-util-phrasing@3.0.1: + dependencies: + '@types/hast': 3.0.5 + 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.5 + '@types/unist': 3.0.3 + '@ungap/structured-clone': 1.3.3 + 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-sanitize@5.0.2: + dependencies: + '@types/hast': 3.0.5 + '@ungap/structured-clone': 1.3.3 + unist-util-position: 5.0.0 + + hast-util-select@6.0.4: + dependencies: + '@types/hast': 3.0.5 + '@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.2.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.5 + 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.2.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.5 + '@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.2.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.5 + '@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.2.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.5 + comma-separated-tokens: 2.0.3 + devlop: 1.1.0 + property-information: 7.2.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.5 + + hast-util-to-text@4.0.2: + dependencies: + '@types/hast': 3.0.5 + '@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.5 + + hastscript@9.0.1: + dependencies: + '@types/hast': 3.0.5 + comma-separated-tokens: 2.0.3 + hast-util-parse-selector: 4.0.0 + property-information: 7.2.0 + space-separated-tokens: 2.0.2 + + highlight.js@11.11.1: {} + + hookable@6.1.1: {} + + 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.3.6: {} + + identifier-regex@1.1.0: + dependencies: + reserved-identifiers: 1.2.0 + + inline-style-parser@0.2.7: {} + + iron-webcrypto@1.2.1: {} + + is-absolute-url@4.0.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@4.0.0: {} + + is-hexadecimal@2.0.1: {} + + is-identifier@1.1.0: + dependencies: + identifier-regex: 1.1.0 + super-regex: 1.1.0 + + is-obj@3.0.0: {} + + is-plain-obj@4.1.0: {} + + is-regexp@3.1.0: {} + + js-base64@3.9.1: {} + + js-yaml@4.3.0: + dependencies: + argparse: 2.0.1 + + json-schema@0.4.0: {} + + jsonc-parser@3.3.1: {} + + klona@2.0.6: {} + + lightningcss-android-arm64@1.32.0: + optional: true + + lightningcss-darwin-arm64@1.32.0: + optional: true + + lightningcss-darwin-x64@1.32.0: + optional: true + + lightningcss-freebsd-x64@1.32.0: + optional: true + + lightningcss-linux-arm-gnueabihf@1.32.0: + optional: true + + lightningcss-linux-arm64-gnu@1.32.0: + optional: true + + lightningcss-linux-arm64-musl@1.32.0: + optional: true + + lightningcss-linux-x64-gnu@1.32.0: + optional: true + + lightningcss-linux-x64-musl@1.32.0: + optional: true + + lightningcss-win32-arm64-msvc@1.32.0: + optional: true + + lightningcss-win32-x64-msvc@1.32.0: + optional: true + + lightningcss@1.32.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.32.0 + lightningcss-darwin-arm64: 1.32.0 + lightningcss-darwin-x64: 1.32.0 + lightningcss-freebsd-x64: 1.32.0 + lightningcss-linux-arm-gnueabihf: 1.32.0 + lightningcss-linux-arm64-gnu: 1.32.0 + lightningcss-linux-arm64-musl: 1.32.0 + lightningcss-linux-x64-gnu: 1.32.0 + lightningcss-linux-x64-musl: 1.32.0 + lightningcss-win32-arm64-msvc: 1.32.0 + lightningcss-win32-x64-msvc: 1.32.0 + + longest-streak@3.1.0: {} + + lowlight@3.3.0: + dependencies: + '@types/hast': 3.0.5 + devlop: 1.1.0 + highlight.js: 11.11.1 + + lru-cache@11.5.2: {} + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + magicast@0.5.3: + dependencies: + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 + source-map-js: 1.2.1 + + make-asynchronous@1.1.0: + dependencies: + p-event: 6.0.1 + type-fest: 4.41.0 + web-worker: 1.5.0 + + 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.5 + '@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.5 + '@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.5 + '@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.5 + '@types/mdast': 4.0.4 + '@ungap/structured-clone': 1.3.3 + 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: {} + + microdiff@1.5.0: {} + + 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.17.0 + acorn-jsx: 5.3.2(acorn@8.17.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.16: {} + + nanoid@5.1.16: {} + + neotraverse@0.6.18: {} + + neverpanic@0.0.8: {} + + 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.3: {} + + 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-event@6.0.1: + dependencies: + p-timeout: 6.1.4 + + p-limit@7.3.0: + dependencies: + yocto-queue: 1.2.2 + + p-queue@9.3.1: + dependencies: + eventemitter3: 5.0.4 + p-timeout: 7.0.1 + + p-timeout@6.1.4: {} + + p-timeout@7.0.1: {} + + package-manager-detector@1.7.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 + + parse-ms@4.0.0: {} + + parse5@7.3.0: + dependencies: + entities: 6.0.1 + + pathe@2.0.3: {} + + piccolore@0.1.3: {} + + picocolors@1.1.1: {} + + picomatch@2.3.2: {} + + picomatch@4.0.5: {} + + playwright-core@1.59.1: {} + + playwright@1.59.1: + dependencies: + playwright-core: 1.59.1 + optionalDependencies: + fsevents: 2.3.2 + + postcss-nested@6.2.0(postcss@8.5.19): + dependencies: + postcss: 8.5.19 + postcss-selector-parser: 6.1.4 + + postcss-selector-parser@6.1.4: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss@8.5.19: + dependencies: + nanoid: 3.3.16 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + pretty-ms@9.3.0: + dependencies: + parse-ms: 4.0.0 + + prismjs@1.30.0: {} + + process-ancestry@0.1.0: {} + + property-information@7.2.0: {} + + radix-vue@1.9.17(vue@3.5.39): + dependencies: + '@floating-ui/dom': 1.8.0 + '@floating-ui/vue': 1.1.11(vue@3.5.39) + '@internationalized/date': 3.12.2 + '@internationalized/number': 3.6.7 + '@tanstack/vue-virtual': 3.13.32(vue@3.5.39) + '@vueuse/core': 10.11.1(vue@3.5.39) + '@vueuse/shared': 10.11.1(vue@3.5.39) + aria-hidden: 1.2.6 + defu: 6.1.7 + fast-deep-equal: 3.1.3 + nanoid: 5.1.16 + vue: 3.5.39 + transitivePeerDependencies: + - '@vue/composition-api' + + 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.17.0): + dependencies: + acorn: 8.17.0 + acorn-jsx: 5.3.2(acorn@8.17.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.44.0: + dependencies: + expressive-code: 0.44.0 + + rehype-external-links@3.0.0: + dependencies: + '@types/hast': 3.0.5 + '@ungap/structured-clone': 1.3.3 + hast-util-is-element: 3.0.0 + is-absolute-url: 4.0.1 + space-separated-tokens: 2.0.2 + unist-util-visit: 5.1.0 + + rehype-format@5.0.1: + dependencies: + '@types/hast': 3.0.5 + hast-util-format: 1.1.0 + + rehype-parse@9.0.1: + dependencies: + '@types/hast': 3.0.5 + hast-util-from-html: 2.0.3 + unified: 11.0.5 + + rehype-raw@7.0.0: + dependencies: + '@types/hast': 3.0.5 + 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.5 + hast-util-to-estree: 3.1.3 + transitivePeerDependencies: + - supports-color + + rehype-sanitize@6.0.0: + dependencies: + '@types/hast': 3.0.5 + hast-util-sanitize: 5.0.2 + + rehype-stringify@10.0.1: + dependencies: + '@types/hast': 3.0.5 + hast-util-to-html: 9.0.5 + unified: 11.0.5 + + rehype@13.0.2: + dependencies: + '@types/hast': 3.0.5 + 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.5 + '@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 + + reserved-identifiers@1.2.0: {} + + 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 + + rolldown@1.1.5: + dependencies: + '@oxc-project/types': 0.139.0 + '@rolldown/pluginutils': 1.0.1 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.1.5 + '@rolldown/binding-darwin-arm64': 1.1.5 + '@rolldown/binding-darwin-x64': 1.1.5 + '@rolldown/binding-freebsd-x64': 1.1.5 + '@rolldown/binding-linux-arm-gnueabihf': 1.1.5 + '@rolldown/binding-linux-arm64-gnu': 1.1.5 + '@rolldown/binding-linux-arm64-musl': 1.1.5 + '@rolldown/binding-linux-ppc64-gnu': 1.1.5 + '@rolldown/binding-linux-s390x-gnu': 1.1.5 + '@rolldown/binding-linux-x64-gnu': 1.1.5 + '@rolldown/binding-linux-x64-musl': 1.1.5 + '@rolldown/binding-openharmony-arm64': 1.1.5 + '@rolldown/binding-wasm32-wasi': 1.1.5 + '@rolldown/binding-win32-arm64-msvc': 1.1.5 + '@rolldown/binding-win32-x64-msvc': 1.1.5 + + satteri@0.9.5: + dependencies: + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.5 + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + optionalDependencies: + '@bruits/satteri-darwin-arm64': 0.9.5 + '@bruits/satteri-darwin-x64': 0.9.5 + '@bruits/satteri-linux-arm64-gnu': 0.9.5 + '@bruits/satteri-linux-arm64-musl': 0.9.5 + '@bruits/satteri-linux-x64-gnu': 0.9.5 + '@bruits/satteri-linux-x64-musl': 0.9.5 + '@bruits/satteri-wasm32-wasi': 0.9.5 + '@bruits/satteri-win32-arm64-msvc': 0.9.5 + '@bruits/satteri-win32-x64-msvc': 0.9.5 + + sax@1.6.0: {} + + semver@7.8.5: {} + + set-cookie-parser@3.1.0: {} + + sharp@0.35.3(@types/node@24.13.3): + dependencies: + '@img/colour': 1.1.0 + detect-libc: 2.1.2 + semver: 7.8.5 + optionalDependencies: + '@img/sharp-darwin-arm64': 0.35.3 + '@img/sharp-darwin-x64': 0.35.3 + '@img/sharp-freebsd-wasm32': 0.35.3 + '@img/sharp-libvips-darwin-arm64': 1.3.2 + '@img/sharp-libvips-darwin-x64': 1.3.2 + '@img/sharp-libvips-linux-arm': 1.3.2 + '@img/sharp-libvips-linux-arm64': 1.3.2 + '@img/sharp-libvips-linux-ppc64': 1.3.2 + '@img/sharp-libvips-linux-riscv64': 1.3.2 + '@img/sharp-libvips-linux-s390x': 1.3.2 + '@img/sharp-libvips-linux-x64': 1.3.2 + '@img/sharp-libvips-linuxmusl-arm64': 1.3.2 + '@img/sharp-libvips-linuxmusl-x64': 1.3.2 + '@img/sharp-linux-arm': 0.35.3 + '@img/sharp-linux-arm64': 0.35.3 + '@img/sharp-linux-ppc64': 0.35.3 + '@img/sharp-linux-riscv64': 0.35.3 + '@img/sharp-linux-s390x': 0.35.3 + '@img/sharp-linux-x64': 0.35.3 + '@img/sharp-linuxmusl-arm64': 0.35.3 + '@img/sharp-linuxmusl-x64': 0.35.3 + '@img/sharp-webcontainers-wasm32': 0.35.3 + '@img/sharp-win32-arm64': 0.35.3 + '@img/sharp-win32-ia32': 0.35.3 + '@img/sharp-win32-x64': 0.35.3 + '@types/node': 24.13.3 + optional: true + + shiki@4.3.1: + dependencies: + '@shikijs/core': 4.3.1 + '@shikijs/engine-javascript': 4.3.1 + '@shikijs/engine-oniguruma': 4.3.1 + '@shikijs/langs': 4.3.1 + '@shikijs/themes': 4.3.1 + '@shikijs/types': 4.3.1 + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.5 + + sisteransi@1.0.5: {} + + sitemap@9.0.1: + dependencies: + '@types/node': 24.13.3 + '@types/sax': 1.2.7 + arg: 5.0.2 + sax: 1.6.0 + + smol-toml@1.7.0: {} + + source-map-js@1.2.1: {} + + source-map@0.7.6: {} + + space-separated-tokens@2.0.2: {} + + stream-replace-string@2.0.0: {} + + string-byte-length@3.0.1: {} + + string-byte-slice@3.0.1: {} + + stringify-entities@4.0.4: + dependencies: + character-entities-html4: 2.1.0 + character-entities-legacy: 3.0.0 + + stringify-object@6.0.0: + dependencies: + get-own-enumerable-keys: 1.0.0 + is-identifier: 1.1.0 + is-obj: 3.0.0 + is-regexp: 3.1.0 + + style-mod@4.1.3: {} + + 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 + + super-regex@1.1.0: + dependencies: + function-timeout: 1.0.2 + make-asynchronous: 1.1.0 + time-span: 5.1.0 + + svgo@4.0.2: + 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 + + swrv@1.2.0(vue@3.5.39): + dependencies: + vue: 3.5.39 + + tabbable@6.5.0: {} + + tagged-tag@1.0.0: {} + + tailwind-merge@3.5.0: {} + + tailwindcss@4.3.2: {} + + time-span@5.1.0: + dependencies: + convert-hrtime: 5.0.0 + + tiny-inflate@1.0.3: {} + + tinyclip@0.1.15: {} + + tinyexec@1.2.4: {} + + tinyglobby@0.2.17: + dependencies: + fdir: 6.5.0(picomatch@4.0.5) + picomatch: 4.0.5 + + trim-lines@3.0.1: {} + + trough@2.2.0: {} + + truncate-json@3.0.1: + dependencies: + guess-json-indent: 3.0.1 + string-byte-length: 3.0.1 + string-byte-slice: 3.0.1 + + tslib@2.8.1: {} + + type-fest@4.41.0: {} + + type-fest@5.8.0: + dependencies: + tagged-tag: 1.0.0 + + ufo@1.6.4: {} + + ultrahtml@1.7.0: {} + + uncrypto@0.1.3: {} + + undici-types@7.18.2: {} + + unhead@2.1.15: + dependencies: + hookable: 6.1.1 + + 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.5.2 + node-fetch-native: 1.6.7 + ofetch: 1.5.1 + ufo: 1.6.4 + + url-extras@0.1.0: {} + + 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@8.1.4(@types/node@24.13.3)(esbuild@0.28.1)(yaml@2.9.0): + dependencies: + lightningcss: 1.32.0 + picomatch: 4.0.5 + postcss: 8.5.19 + rolldown: 1.1.5 + tinyglobby: 0.2.17 + optionalDependencies: + '@types/node': 24.13.3 + esbuild: 0.28.1 + fsevents: 2.3.3 + yaml: 2.9.0 + + vitefu@1.1.3(vite@8.1.4(@types/node@24.13.3)(esbuild@0.28.1)(yaml@2.9.0)): + optionalDependencies: + vite: 8.1.4(@types/node@24.13.3)(esbuild@0.28.1)(yaml@2.9.0) + + vue-component-type-helpers@3.3.7: {} + + vue-demi@0.14.10(vue@3.5.39): + dependencies: + vue: 3.5.39 + + vue-sonner@1.3.2: {} + + vue@3.5.39: + dependencies: + '@vue/compiler-dom': 3.5.39 + '@vue/compiler-sfc': 3.5.39 + '@vue/runtime-dom': 3.5.39 + '@vue/server-renderer': 3.5.39(vue@3.5.39) + '@vue/shared': 3.5.39 + + w3c-keyname@2.2.8: {} + + web-namespaces@2.0.1: {} + + web-worker@1.5.0: {} + + xxhash-wasm@1.1.0: {} + + yaml@2.9.0: {} + + yargs-parser@22.0.0: {} + + yocto-queue@1.2.2: {} + + zod@4.4.3: {} + + zwitch@2.0.4: {} diff --git a/public/favicon.svg b/public/favicon.svg new file mode 100644 index 0000000..6749fb1 --- /dev/null +++ b/public/favicon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/guides/legacy-batches.html b/public/guides/legacy-batches.html new file mode 100644 index 0000000..c4a4626 --- /dev/null +++ b/public/guides/legacy-batches.html @@ -0,0 +1,2 @@ + +Legacy batches diff --git a/public/identity-access.html b/public/identity-access.html new file mode 100644 index 0000000..0574973 --- /dev/null +++ b/public/identity-access.html @@ -0,0 +1,2 @@ + +Identity Access API diff --git a/public/ledger-core.html b/public/ledger-core.html new file mode 100644 index 0000000..1c87c8d --- /dev/null +++ b/public/ledger-core.html @@ -0,0 +1,2 @@ + +Ledger Core API diff --git a/public/workbench.html b/public/workbench.html new file mode 100644 index 0000000..5b9caf3 --- /dev/null +++ b/public/workbench.html @@ -0,0 +1,2 @@ + +Workbench API diff --git a/redocly.yaml b/redocly.yaml new file mode 100644 index 0000000..195319f --- /dev/null +++ b/redocly.yaml @@ -0,0 +1,7 @@ +extends: + - recommended +rules: + no-server-example.com: off + operation-description: off + operation-summary: error + security-defined: error diff --git a/scripts/build-docs.mjs b/scripts/build-docs.mjs new file mode 100644 index 0000000..74ec6e8 --- /dev/null +++ b/scripts/build-docs.mjs @@ -0,0 +1,21 @@ +import { writeFileSync } from 'node:fs'; +import { spawnSync } from 'node:child_process'; + +const contracts = [ + 'identity-access.public.v1.yaml', + 'ledger-core.public.v1.yaml', + 'workbench.public.v1.yaml', +]; +for (const source of contracts) run('node_modules/@redocly/cli/bin/cli.js', ['lint', `openapi/${source}`]); +run('node_modules/astro/bin/astro.mjs', ['build']); + +const revision = spawnSync('git', ['rev-parse', 'HEAD'], { encoding: 'utf8' }).stdout.trim() || 'unknown'; +writeFileSync('dist/build-info.json', `${JSON.stringify({ revision, generated_at: new Date().toISOString() }, null, 2)}\n`); + +function run(module, args) { + const result = spawnSync(process.execPath, [module, ...args], { + stdio: 'inherit', + env: { ...process.env, REDOCLY_SUPPRESS_UPDATE_NOTICE: 'true', ASTRO_TELEMETRY_DISABLED: '1' }, + }); + if (result.status !== 0) throw new Error(`${module} ${args.join(' ')} failed`); +} diff --git a/scripts/check-contracts.mjs b/scripts/check-contracts.mjs new file mode 100644 index 0000000..e091956 --- /dev/null +++ b/scripts/check-contracts.mjs @@ -0,0 +1,62 @@ +import { createHash } from 'node:crypto'; +import { readFileSync } from 'node:fs'; +import { parse } from 'yaml'; + +const lock = JSON.parse(readFileSync('sources.lock.json', 'utf8')); +const expectedContracts = new Map([ + ['identity-access.public.v1.yaml', { + owner: 'mavulahq/identity-access', + source: 'contracts/openapi/identity-access.public.v1.yaml', + }], + ['ledger-core.public.v1.yaml', { + owner: 'mavulahq/ledger-core', + source: 'contracts/openapi/ledger-core.public.v1.yaml', + }], + ['workbench.public.v1.yaml', { + owner: 'mavulahq/workbench', + source: 'contracts/openapi/workbench.public.v1.yaml', + }], +]); +if (lock.version !== 1 || !Array.isArray(lock.contracts) || lock.contracts.length !== 3) { + throw new Error('sources.lock.json must declare the three v1 owner contracts'); +} +for (const contract of lock.contracts) { + const expected = expectedContracts.get(contract.file); + if (!expected || contract.owner !== expected.owner || contract.source !== expected.source) { + throw new Error(`${contract.file} has invalid owner contract provenance`); + } + const source = readFileSync(`openapi/${contract.file}`, 'utf8'); + const document = parse(source); + const digest = createHash('sha256').update(source).digest('hex'); + if (digest !== contract.sha256) throw new Error(`${contract.file} does not match its owner digest`); + if (document.openapi !== '3.1.0') throw new Error(`${contract.file} must use OpenAPI 3.1.0`); + for (const [route, pathItem] of Object.entries(document.paths ?? {})) { + if (/\/internal\/|\/interaction|\/health$|\/metrics$|\/auth\/login/.test(route)) { + throw new Error(`${contract.file} exposes non-public route ${route}`); + } + for (const method of ['get', 'post', 'put', 'patch', 'delete']) { + const operation = pathItem?.[method]; + if (!operation) continue; + if (!operation.operationId || !operation.summary) { + throw new Error(`${contract.file} ${method.toUpperCase()} ${route} must declare operationId and summary`); + } + if (contract.file !== 'identity-access.public.v1.yaml') { + const permissions = operation['x-mavula-permissions']; + if (!Array.isArray(permissions) || permissions.length === 0) { + throw new Error(`${contract.file} ${method.toUpperCase()} ${route} must declare permissions`); + } + } + } + } +} + +const guideFiles = [ + 'src/content/docs/v1/getting-started/quickstart.mdx', + 'src/content/docs/v1/getting-started/authentication.mdx', + 'src/content/docs/v1/guides/account-lifecycle.mdx', + 'src/content/docs/v1/guides/financial-adjustments.mdx', + 'src/content/docs/v1/guides/payment-jobs.mdx', + 'src/content/docs/v1/guides/legacy-batches.mdx', +]; +for (const file of guideFiles) readFileSync(file, 'utf8'); +console.log('developer-docs owner digests, public boundaries and use-case coverage are valid'); diff --git a/scripts/guardian.mjs b/scripts/guardian.mjs index 5e47769..17ee9be 100644 --- a/scripts/guardian.mjs +++ b/scripts/guardian.mjs @@ -7,7 +7,13 @@ const required = [ '.agents/AGENTS.md', '.agents/skills/mavula-review/SKILL.md', '.agents/skills/mavula-review/agents/openai.yaml', '.github/CODEOWNERS', '.github/PULL_REQUEST_TEMPLATE.md', '.github/workflows/guardian.yml', - 'LICENSE', 'README.md', 'package.json', + '.github/workflows/required-ci.yml', '.github/workflows/pages.yml', + 'LICENSE', 'README.md', 'package.json', 'sources.lock.json', 'redocly.yaml', + 'astro.config.mjs', 'src/content.config.ts', 'src/styles/custom.css', + 'src/content/docs/index.mdx', 'src/content/docs/v1/guides/legacy-batches.mdx', + 'src/pages/v1/api/[api].astro', 'examples/postman/MAVULA-API-v1.postman_collection.json', + 'openapi/identity-access.public.v1.yaml', 'openapi/ledger-core.public.v1.yaml', + 'openapi/workbench.public.v1.yaml', ]; for (const file of required) if (!existsSync(file)) failures.push(`${file} is required`); const pkg = JSON.parse(readFileSync('package.json', 'utf8')); diff --git a/sources.lock.json b/sources.lock.json new file mode 100644 index 0000000..6b860c4 --- /dev/null +++ b/sources.lock.json @@ -0,0 +1,23 @@ +{ + "version": 1, + "contracts": [ + { + "file": "identity-access.public.v1.yaml", + "owner": "mavulahq/identity-access", + "source": "contracts/openapi/identity-access.public.v1.yaml", + "sha256": "a126f53455b05bd8377fa12b81f814ae5d677acbbb0e8df33a706a5a0cf60a38" + }, + { + "file": "ledger-core.public.v1.yaml", + "owner": "mavulahq/ledger-core", + "source": "contracts/openapi/ledger-core.public.v1.yaml", + "sha256": "115cda1bff1aaea6a7aaad81577a0918e4ced2ec222cefc4081433a08778f2a1" + }, + { + "file": "workbench.public.v1.yaml", + "owner": "mavulahq/workbench", + "source": "contracts/openapi/workbench.public.v1.yaml", + "sha256": "1b6e8a3fdb3c882c87932e6966612ea71706902adabd5f6ddd3bf356762e95d9" + } + ] +} diff --git a/src/content.config.ts b/src/content.config.ts new file mode 100644 index 0000000..6a7b7a0 --- /dev/null +++ b/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/src/content/docs/index.mdx b/src/content/docs/index.mdx new file mode 100644 index 0000000..35b897d --- /dev/null +++ b/src/content/docs/index.mdx @@ -0,0 +1,35 @@ +--- +title: MAVULA Developer Docs +description: Build regulated financial operations on MAVULA public APIs. +template: splash +hero: + tagline: Integrate institutional identity, controlled ledger operations, payment jobs and legacy batch workflows through versioned public contracts. + actions: + - text: Start with API v1 + link: /v1/getting-started/quickstart/ + icon: right-arrow + variant: primary + - text: Explore API reference + link: /v1/api/ledger-core/ + icon: open-book + variant: minimal +--- + +## One platform, explicit ownership + +| Surface | Use it for | Contract owner | +| --- | --- | --- | +| **Identity Access** | OAuth 2.0, OpenID Connect and effective operator identity | `mavulahq/identity-access` | +| **Ledger Core** | Accounts, maker-checker controls, financial configuration and projections | `mavulahq/ledger-core` | +| **Workbench** | Payment jobs, operational status and legacy batch orchestration | `mavulahq/workbench` | + +All examples target API v1. Internal callbacks, health probes and observability endpoints are intentionally excluded from the public reference. + +## Choose a workflow + +- [Create and inspect an account](/developer-docs/v1/guides/account-setup/) +- [Control an account lifecycle](/developer-docs/v1/guides/account-lifecycle/) +- [Submit a reversible financial adjustment](/developer-docs/v1/guides/financial-adjustments/) +- [Operate payment jobs](/developer-docs/v1/guides/payment-jobs/) +- [Generate and deliver regulatory exports](/developer-docs/v1/guides/legacy-batches/) + diff --git a/src/content/docs/v1/concepts/errors.mdx b/src/content/docs/v1/concepts/errors.mdx new file mode 100644 index 0000000..5eaa757 --- /dev/null +++ b/src/content/docs/v1/concepts/errors.mdx @@ -0,0 +1,29 @@ +--- +title: Errors +description: Interpret public API failures and choose a safe recovery action. +--- + +Error bodies expose a stable HTTP status and message. Use the HTTP status for control flow and retain the correlation ID for investigation. + +| Status | Category | Typical cause | Recovery | +| --- | --- | --- | --- | +| `400` | Invalid request | Missing field, malformed identifier, unsupported transition | Correct and submit with a new idempotency key | +| `401` | Authentication | Missing, invalid or expired token | Obtain a valid token; do not replay credentials in logs | +| `403` | Authorization | Missing permission, wrong role, self-approval | Use an authorized distinct principal | +| `404` | Not found | Resource absent or outside tenant boundary | Verify tenant context and identifier | +| `409` | Conflict | State changed or idempotency fingerprint differs | Read current state; do not retry blindly | +| `429` | Rate limited | Request budget exceeded | Respect `Retry-After` | +| `5xx` | Service failure | Temporary processing or dependency failure | Retry eligible requests with the same key | + +## Example + +```json +{ + "statusCode": 409, + "message": "idempotency key is already bound to a different request", + "error": "Conflict" +} +``` + +Never expose access tokens, client secrets, personal data or full financial payloads in an issue. Supply timestamps, operation IDs, resource IDs and correlation IDs. + diff --git a/src/content/docs/v1/concepts/idempotency.mdx b/src/content/docs/v1/concepts/idempotency.mdx new file mode 100644 index 0000000..c1714dd --- /dev/null +++ b/src/content/docs/v1/concepts/idempotency.mdx @@ -0,0 +1,25 @@ +--- +title: Idempotency and retries +description: Prevent duplicate effects across network failures and asynchronous processing. +--- + +An idempotency key identifies one logical mutation within its tenant and operation boundary. The server persists a receipt that binds the key to the request fingerprint and result. + +## Correct use + +```text +first attempt: POST /api/accounts + key A + payload P +timed-out retry: POST /api/accounts + key A + payload P +new command: POST /api/accounts + key B + payload Q +``` + +Changing the method, path or body while reusing a key produces a conflict. Generating a new key after an ambiguous timeout risks creating a duplicate command. + +## Durable receipts + +Receipts allow a retried request to return the original accepted or completed result after a process restart. For asynchronous jobs, the receipt identifies the same job; clients must then follow the job or batch status resource. + +## Retry budget + +Use exponential backoff with jitter and a finite attempt count. Preserve the correlation ID across the end-to-end business flow. A later manual retry after investigation may use a new correlation ID, but it must not reuse an idempotency key for a different command. + diff --git a/src/content/docs/v1/concepts/projections.mdx b/src/content/docs/v1/concepts/projections.mdx new file mode 100644 index 0000000..e76746a --- /dev/null +++ b/src/content/docs/v1/concepts/projections.mdx @@ -0,0 +1,20 @@ +--- +title: Projections +description: Read derived views while preserving financial ownership and consistency expectations. +--- + +Projections are read models derived from committed domain events. API v1 exposes loan activity, ledger activity and product publication views together with projection checkpoints. + +## Consistency model + +A successful command may become visible in a projection after a short delay. The command response or authoritative aggregate remains the source for immediate confirmation; projections support operational search and reporting. + +Read `/api/projections/status` to inspect the last processed event and lag for each projection. Alerting should consider sustained lag, not a single transient value. + +## Safe consumption + +- Store the returned projection version or last event identifier when incremental reconciliation matters. +- Do not post financial entries from a projection record. +- Re-read by entity ID when a list result may have been produced before a recent command. +- Treat a projection payload as a versioned public representation, not the internal event stream. + diff --git a/src/content/docs/v1/concepts/tenant-isolation.mdx b/src/content/docs/v1/concepts/tenant-isolation.mdx new file mode 100644 index 0000000..e2d927b --- /dev/null +++ b/src/content/docs/v1/concepts/tenant-isolation.mdx @@ -0,0 +1,25 @@ +--- +title: Tenant isolation +description: Understand how identity context and row-level security isolate institutional data. +--- + +The authenticated identity establishes the tenant boundary. Application authorization and PostgreSQL row-level security enforce that boundary independently. + +## Request path + +1. Identity Access validates credentials and issues a tenant-bound token. +2. The API validates token signature, issuer, audience and expiry. +3. Effective roles and permissions are resolved for that tenant. +4. The database transaction receives the tenant context. +5. Row-level security filters reads and rejects cross-tenant writes. + +Identifiers are not authorization. Knowing another tenant's account, request or batch identifier must not make it readable. + +## Integration rules + +- Use one tenant-bound credential per institutional context. +- Never cache data without including the effective tenant in the cache key. +- Do not accept a tenant identifier from an untrusted client and forward it as authorization context. +- Treat `404` for a known identifier as potentially intentional boundary protection. +- Propagate correlation IDs, not credentials, across logs and support workflows. + diff --git a/src/content/docs/v1/getting-started/authentication.mdx b/src/content/docs/v1/getting-started/authentication.mdx new file mode 100644 index 0000000..f1e4939 --- /dev/null +++ b/src/content/docs/v1/getting-started/authentication.mdx @@ -0,0 +1,84 @@ +--- +title: Authentication +description: Select and implement the correct OAuth 2.0 flow for operators and institutional services. +--- + +import { Aside, Tabs, TabItem } from '@astrojs/starlight/components'; + +Identity Access publishes OpenID Provider metadata at `/.well-known/openid-configuration` and signing keys at `/jwks`. Validate token issuer, audience, signature and expiry on every protected boundary. + +## Choose a grant + +| Grant | Principal | Use case | +| --- | --- | --- | +| Authorization code with PKCE | Human operator | Browser or native operator interface | +| Client credentials | Institutional service | Backend-to-backend automation | +| Refresh token | Existing operator session | Rotate access tokens without repeating sign-in | + +### Authorization code with PKCE + +Generate a random `code_verifier`, derive its SHA-256 `code_challenge`, then redirect the operator to `/auth`. The `state` and `nonce` values must be unique and verified on return. + +```text +GET https://identity.mavula.dev/auth + ?response_type=code + &client_id=operator-console + &redirect_uri=https%3A%2F%2Fops.example.com%2Fcallback + &scope=openid%20profile%20finance.read%20finance.write + &code_challenge=BASE64URL_SHA256_VERIFIER + &code_challenge_method=S256 + &state=RANDOM_STATE + &nonce=RANDOM_NONCE +``` + +Exchange the returned code once: + +```bash +curl -sS -X POST https://identity.mavula.dev/token \ + -H 'Content-Type: application/x-www-form-urlencoded' \ + --data-urlencode 'grant_type=authorization_code' \ + --data-urlencode 'client_id=operator-console' \ + --data-urlencode 'code=AUTHORIZATION_CODE' \ + --data-urlencode 'redirect_uri=https://ops.example.com/callback' \ + --data-urlencode 'code_verifier=ORIGINAL_CODE_VERIFIER' +``` + +### Client credentials + + + + ```bash + curl -sS -X POST https://identity.mavula.dev/token \ + -H 'Content-Type: application/x-www-form-urlencoded' \ + --data-urlencode 'grant_type=client_credentials' \ + --data-urlencode 'client_id=YOUR_CLIENT_ID' \ + --data-urlencode 'client_secret=YOUR_CLIENT_SECRET' \ + --data-urlencode 'scope=internal.worker' + ``` + + + ```ts + const body = new URLSearchParams({ + grant_type: 'client_credentials', + client_id: process.env.MAVULA_CLIENT_ID!, + client_secret: process.env.MAVULA_CLIENT_SECRET!, + scope: 'internal.worker', + }); + const response = await fetch('https://identity.mavula.dev/token', { + method: 'POST', headers: { 'content-type': 'application/x-www-form-urlencoded' }, body, + }); + if (!response.ok) throw new Error(`token request failed: ${response.status}`); + const tokens = await response.json(); + ``` + + + +Client credentials represent an approved internal worker identity. They do not replace operator authorization for Ledger Core or compliance operations. + +## Refresh and revoke + +Refresh tokens are rotated. Persist the replacement atomically and discard the previous value. Send tokens that must no longer be used to `/token/revocation`. + + diff --git a/src/content/docs/v1/getting-started/quickstart.mdx b/src/content/docs/v1/getting-started/quickstart.mdx new file mode 100644 index 0000000..af439c1 --- /dev/null +++ b/src/content/docs/v1/getting-started/quickstart.mdx @@ -0,0 +1,62 @@ +--- +title: Quickstart +description: Exchange an operator authorization code, create an account and read its balance. +--- + +import { Aside, Steps } from '@astrojs/starlight/components'; + +This flow uses OAuth 2.0 authorization code with PKCE for an institutional operator. Complete the authorization redirect described in [Authentication](../authentication/) before exchanging the code. + + + +1. **Exchange the authorization code** + + ```bash + curl -sS -X POST https://identity.mavula.dev/token \ + -H 'Content-Type: application/x-www-form-urlencoded' \ + --data-urlencode 'grant_type=authorization_code' \ + --data-urlencode 'client_id=operator-console' \ + --data-urlencode 'code=AUTHORIZATION_CODE' \ + --data-urlencode 'redirect_uri=https://ops.example.com/callback' \ + --data-urlencode 'code_verifier=ORIGINAL_CODE_VERIFIER' + ``` + +2. **Inspect the effective identity** + + ```bash + curl -sS https://identity.mavula.dev/api/v1/me \ + -H "Authorization: Bearer $MAVULA_ACCESS_TOKEN" + ``` + + Confirm the returned tenant, roles and permissions before sending financial commands. + +3. **Create an account** + + ```bash + curl -sS -X POST https://ledger.mavula.dev/api/accounts \ + -H "Authorization: Bearer $MAVULA_ACCESS_TOKEN" \ + -H 'Content-Type: application/json' \ + -H 'Idempotency-Key: 76b05d81-c975-4daf-b054-72b2eb3a749a' \ + -H 'X-Correlation-ID: 406d8359-a53a-4d2a-a908-628798ece3b3' \ + -d '{"customer_id":"customer_001","product_id":"current_account_mzn","name":"Operating account","currency":"MZN"}' + ``` + +4. **Read the balance** + + ```bash + curl -sS https://ledger.mavula.dev/api/accounts/ACCOUNT_ID/balance \ + -H "Authorization: Bearer $MAVULA_ACCESS_TOKEN" \ + -H 'X-Correlation-ID: 406d8359-a53a-4d2a-a908-628798ece3b3' + ``` + + + + + +## Next steps + +- [Configure operator roles](../roles-permissions/) +- [Apply retry and idempotency rules](../request-reliability/) +- [Control account lifecycle changes](../../guides/account-lifecycle/) diff --git a/src/content/docs/v1/getting-started/request-reliability.mdx b/src/content/docs/v1/getting-started/request-reliability.mdx new file mode 100644 index 0000000..1337328 --- /dev/null +++ b/src/content/docs/v1/getting-started/request-reliability.mdx @@ -0,0 +1,41 @@ +--- +title: Request reliability +description: Correlate requests and retry mutations without creating duplicate financial effects. +--- + +## Required headers + +| Header | Applies to | Requirement | +| --- | --- | --- | +| `Authorization` | Protected operations | Bearer access token | +| `Idempotency-Key` | Mutating operations | Stable UUID for one logical command | +| `X-Correlation-ID` | Every integration call | Stable trace identifier across service boundaries | +| `Content-Type` | Requests with a body | `application/json` or the media type required by the endpoint | + +Generate a new idempotency key for each logical command. Reuse the same key only when retrying the same method, path and payload. + +## Retry policy + +| Result | Retry | Action | +| --- | --- | --- | +| Network timeout before response | Yes | Retry with the same idempotency key | +| `429` | Yes | Respect `Retry-After` and add jitter | +| `500`, `502`, `503`, `504` | Yes | Exponential backoff with a bounded attempt count | +| `400`, `401`, `403`, `404`, `409` | No | Correct credentials, payload, state or key usage | +| Accepted asynchronous job | Poll | Read the status resource; do not resubmit | + +## Example retry loop + +```ts +const retryable = new Set([429, 500, 502, 503, 504]); +for (let attempt = 0; attempt < 4; attempt += 1) { + const response = await fetch(url, { method: 'POST', headers, body }); + if (response.ok) return response.json(); + if (!retryable.has(response.status)) throw await response.json(); + await new Promise((resolve) => setTimeout(resolve, 250 * 2 ** attempt + Math.random() * 100)); +} +throw new Error('retry budget exhausted'); +``` + +See [Idempotency and retries](../concepts/idempotency/) for receipt and conflict semantics. + diff --git a/src/content/docs/v1/getting-started/roles-permissions.mdx b/src/content/docs/v1/getting-started/roles-permissions.mdx new file mode 100644 index 0000000..cc8023a --- /dev/null +++ b/src/content/docs/v1/getting-started/roles-permissions.mdx @@ -0,0 +1,30 @@ +--- +title: Roles and permissions +description: Map institutional duties to the minimum public API permissions. +--- + +Authorization follows least privilege and separation of duties. A role grants a bounded set of permissions; an API operation declares its required permission in `x-mavula-permissions` in the public OpenAPI contract. + +## Minimum operator roles + +| Role | Typical responsibility | Core permissions | +| --- | --- | --- | +| `operations_viewer` | Read operational and financial state | `finance.read` | +| `operations_maker` | Submit controlled changes | `finance.read`, `finance.write` | +| `operations_checker` | Approve or reject controlled changes | `finance.read`, `finance.approve` | +| `compliance_officer` | Review and generate regulated outputs | `finance.read`, `compliance.manage` | +| `platform_administrator` | Manage tenant configuration and access | Explicit administrative permissions only | +| `service_integration` | Execute a specific machine workflow | Narrow scopes for one integration | + +## Maker-checker rule + +The principal that submits an account lifecycle or financial adjustment request cannot approve the same request. Approval must use a different authenticated operator with `finance.approve`. + +## Verify access at runtime + +```bash +curl -sS https://identity.mavula.dev/api/v1/me \ + -H "Authorization: Bearer $MAVULA_ACCESS_TOKEN" +``` + +Treat a `403` as an authorization decision. Do not retry it automatically or exchange it for a more privileged service credential. diff --git a/src/content/docs/v1/guides/account-lifecycle.mdx b/src/content/docs/v1/guides/account-lifecycle.mdx new file mode 100644 index 0000000..868e507 --- /dev/null +++ b/src/content/docs/v1/guides/account-lifecycle.mdx @@ -0,0 +1,105 @@ +--- +title: Control an account lifecycle +description: Submit freeze, unfreeze and close requests with maker-checker approval. +--- + +import { Aside, Tabs, TabItem } from '@astrojs/starlight/components'; + +
+
+

Create an account

Create the account that will be managed by the lifecycle workflow.

+

Submit a transition

An operations_maker records a request in PENDING_APPROVAL.

+

Approve separately

A different operations_checker approves or rejects the request.

+

Verify state

Read the request and account to confirm the applied transition.

+
+
+

Role matrix

+
+
operations_makerCreate accountsSubmit lifecycle requestsRead own requests
+
operations_checkerReview pending requestsApprove or reject requestsRead all requests
+
+ +

Submit a freeze request

+ + + ```bash + curl -sS -X POST https://ledger.mavula.dev/api/accounts/ACCOUNT_ID/status-transitions \ + -H "Authorization: Bearer $MAKER_TOKEN" \ + -H 'Content-Type: application/json' \ + -H 'Idempotency-Key: 7f2b1e3a-4c2d-4d63-9b1a-2f7b6c0d5e91' \ + -H 'X-Correlation-ID: 0f3c8d7a-6e1b-4a98-8d7f-9c1a2b3d4e5f' \ + -d '{"transition":"FREEZE","reason":"Suspected fraud"}' + ``` + + + ```ts + const response = await fetch(`${ledgerUrl}/api/accounts/${accountId}/status-transitions`, { + method: 'POST', + headers: { + authorization: `Bearer ${makerToken}`, + 'content-type': 'application/json', + 'idempotency-key': crypto.randomUUID(), + 'x-correlation-id': crypto.randomUUID(), + }, + body: JSON.stringify({ transition: 'FREEZE', reason: 'Suspected fraud' }), + }); + ``` + + + ```python + response = requests.post( + f"{ledger_url}/api/accounts/{account_id}/status-transitions", + headers={"Authorization": f"Bearer {maker_token}", "Idempotency-Key": str(uuid.uuid4()), "X-Correlation-ID": str(uuid.uuid4())}, + json={"transition": "FREEZE", "reason": "Suspected fraud"}, timeout=10, + ) + response.raise_for_status() + ``` + + + ```java + HttpRequest request = HttpRequest.newBuilder(URI.create(ledgerUrl + "/api/accounts/" + accountId + "/status-transitions")) + .header("Authorization", "Bearer " + makerToken) + .header("Content-Type", "application/json") + .header("Idempotency-Key", UUID.randomUUID().toString()) + .header("X-Correlation-ID", UUID.randomUUID().toString()) + .POST(HttpRequest.BodyPublishers.ofString("{\"transition\":\"FREEZE\",\"reason\":\"Suspected fraud\"}")) + .build(); + ``` + + + ```go + body := strings.NewReader(`{"transition":"FREEZE","reason":"Suspected fraud"}`) + req, _ := http.NewRequest(http.MethodPost, ledgerURL+"/api/accounts/"+accountID+"/status-transitions", body) + req.Header.Set("Authorization", "Bearer "+makerToken) + req.Header.Set("Content-Type", "application/json") + req.Header.Set("Idempotency-Key", uuid.NewString()) + req.Header.Set("X-Correlation-ID", uuid.NewString()) + ``` + + +
+
+ +## Approve as a different operator + +```bash +curl -sS -X POST https://ledger.mavula.dev/api/account-lifecycle-requests/REQUEST_ID/approve \ + -H "Authorization: Bearer $CHECKER_TOKEN" \ + -H 'Content-Type: application/json' \ + -H 'Idempotency-Key: a65e192f-aa5f-4dc9-a111-baf6136595a0' \ + -d '{"reason":"Evidence reviewed"}' +``` + + + +## Failure handling + +| HTTP status | Meaning | Resolution | +| --- | --- | --- | +| `400` | Invalid transition or malformed body | Validate transition and reason | +| `403` | Missing permission or self-approval | Use a distinct checker with `finance.approve` | +| `404` | Account or request not found in the tenant | Verify identifiers and tenant context | +| `409` | Idempotency or state conflict | Reuse the key only for an identical retry; refresh current state | + diff --git a/src/content/docs/v1/guides/account-setup.mdx b/src/content/docs/v1/guides/account-setup.mdx new file mode 100644 index 0000000..64bd3cf --- /dev/null +++ b/src/content/docs/v1/guides/account-setup.mdx @@ -0,0 +1,42 @@ +--- +title: Create and inspect an account +description: Create a tenant-scoped account and read its balance and statement. +--- + +import { Steps } from '@astrojs/starlight/components'; + +Required permission: `finance.write` to create, `finance.read` to inspect. + + + +1. **Create the account** + + ```bash + curl -sS -X POST https://ledger.mavula.dev/api/accounts \ + -H "Authorization: Bearer $MAVULA_ACCESS_TOKEN" \ + -H 'Content-Type: application/json' \ + -H 'Idempotency-Key: 56a1f534-9054-4dcf-82cb-55ebc102da18' \ + -H 'X-Correlation-ID: 9ab719e7-7aa6-4cc5-9d03-01eef511262b' \ + -d '{"customer_id":"customer_001","product_id":"current_account_mzn","name":"Operating account","currency":"MZN"}' + ``` + +2. **Read the current balance** + + ```bash + curl -sS https://ledger.mavula.dev/api/accounts/ACCOUNT_ID/balance \ + -H "Authorization: Bearer $MAVULA_ACCESS_TOKEN" + ``` + +3. **Page through the statement** + + ```bash + curl -sS 'https://ledger.mavula.dev/api/accounts/ACCOUNT_ID/statement?limit=100' \ + -H "Authorization: Bearer $MAVULA_ACCESS_TOKEN" + ``` + + When `next_cursor` is present, send it as `cursor` on the next request. A statement entry includes its direction, amount, currency, resulting balance and posting timestamp. + + + +Monetary amounts are decimal strings. Never parse them with binary floating-point arithmetic. + diff --git a/src/content/docs/v1/guides/configuration.mdx b/src/content/docs/v1/guides/configuration.mdx new file mode 100644 index 0000000..e40545f --- /dev/null +++ b/src/content/docs/v1/guides/configuration.mdx @@ -0,0 +1,36 @@ +--- +title: Configure products, rules and workflows +description: Manage tenant financial configuration through versioned public resources. +--- + +Configuration APIs are tenant-scoped. Apply changes first in a non-production tenant and retain the correlation ID used for each mutation. + +## Generate jurisdiction defaults + +```bash +curl -sS -X POST https://ledger.mavula.dev/api/products/config/generate \ + -H "Authorization: Bearer $MAVULA_ACCESS_TOKEN" \ + -H 'Content-Type: application/json' \ + -H 'Idempotency-Key: 4cb0de72-2805-4490-8e47-df403c118275' \ + -d '{"jurisdiction":"MZ"}' +``` + +## Configuration surfaces + +| Resource | Operations | Use | +| --- | --- | --- | +| Products | list, read, upsert | Define financial product behavior | +| Product rules | list, create, update, delete, seed defaults | Apply ordered conditions and actions | +| Entity schemas | list, create, import, export, preset | Define validated business data shapes | +| Workflows | list, create, read, execute, preset | Compose controlled actions around named triggers | + +Rules include a condition, action, priority, enabled state and optional applicability list. Workflow steps execute in their declared order and accept an explicit context object. + +## Change discipline + +1. Export or read the current configuration. +2. Validate the proposed change against the OpenAPI schema. +3. Use a unique idempotency and correlation identifier. +4. Read the resulting resource and version. +5. Verify downstream projections before exposing the change operationally. + diff --git a/src/content/docs/v1/guides/financial-adjustments.mdx b/src/content/docs/v1/guides/financial-adjustments.mdx new file mode 100644 index 0000000..bf0e9fb --- /dev/null +++ b/src/content/docs/v1/guides/financial-adjustments.mdx @@ -0,0 +1,34 @@ +--- +title: Control a financial adjustment +description: Reverse or correct a posted financial effect through maker-checker approval. +--- + +Financial history is not edited in place. Submit a `REVERSAL` or `CORRECTION` against a transaction or journal entry, then have a different operator approve it. + +## Submit a reversal + +```bash +curl -sS -X POST https://ledger.mavula.dev/api/financial-adjustment-requests \ + -H "Authorization: Bearer $MAKER_TOKEN" \ + -H 'Content-Type: application/json' \ + -H 'Idempotency-Key: 7b0491f2-eb4c-42b2-b77d-acadd27c571b' \ + -H 'X-Correlation-ID: 2d94d70b-77fa-4a58-af9f-d49c6849632f' \ + -d '{"target_type":"JOURNAL_ENTRY","target_id":"journal_001","adjustment_type":"REVERSAL","reason":"Duplicate posting"}' +``` + +## Approve or reject + +```bash +curl -sS -X POST https://ledger.mavula.dev/api/financial-adjustment-requests/REQUEST_ID/approve \ + -H "Authorization: Bearer $CHECKER_TOKEN" \ + -H 'Content-Type: application/json' \ + -H 'Idempotency-Key: 147598a5-10ee-49cc-b6e5-e5415bb65844' \ + -d '{"reason":"Source documents verified"}' +``` + +Use `/reject` with a required reason when the evidence is insufficient. After approval, read the request until its applied or failed state is visible, then reconcile the resulting statement entries. + +## Correction payloads + +A correction may carry lending and journal details defined by the public schema. Validate debit and credit totals, account currency and source references before submission. Never retry with changed correction lines under the same idempotency key. + diff --git a/src/content/docs/v1/guides/legacy-batches.mdx b/src/content/docs/v1/guides/legacy-batches.mdx new file mode 100644 index 0000000..45b58bb --- /dev/null +++ b/src/content/docs/v1/guides/legacy-batches.mdx @@ -0,0 +1,55 @@ +--- +title: Run legacy and regulatory batches +description: Generate regulatory exports, validate legacy imports and retain durable receipts. +--- + +import { Aside, Steps } from '@astrojs/starlight/components'; + +Workbench orchestrates auditable batch requests. Legacy imports are staged and validated only; they do not mutate financial state in API v1. + +## Regulatory export + + + +1. **Request the export** + + ```bash + curl -sS -X POST https://workbench.mavula.dev/api/regulatory-exports \ + -H "Authorization: Bearer $COMPLIANCE_TOKEN" \ + -H 'Content-Type: application/json' \ + -H 'Idempotency-Key: 0e03ef93-09e0-413f-b49a-e59f93fa881f' \ + -H 'X-Correlation-ID: bd351e46-e436-4dd2-b9de-75e940629961' \ + -d '{"period_from":"2026-06-01","period_to":"2026-06-30","legal_basis_code":"MZ-AML-14-2023-ART-43","retention_until":"2036-06-30"}' + ``` + +2. **Read the durable batch receipt** + + Use `GET /api/legacy-batches/{batchId}`. The receipt survives worker retries and process restarts. + +3. **Download the artifact** + + Use `GET /api/legacy-batches/{batchId}/artifact` only after the batch reports a completed state. Verify the response media type and checksum before delivery. + +4. **Record authority delivery** + + ```bash + curl -sS -X POST https://workbench.mavula.dev/api/regulatory-exports/BATCH_ID/delivery \ + -H "Authorization: Bearer $COMPLIANCE_TOKEN" \ + -H 'Content-Type: application/json' \ + -H 'Idempotency-Key: 076a329b-84f5-4f58-99ef-04ac14f3a343' \ + -d '{"authority_reference":"BM-2026-000184","delivered_at":"2026-07-10T09:30:00Z"}' + ``` + + + +## Validate a legacy import + +Submit the file metadata and import parameters to `POST /api/legacy-imports`. Inspect deterministic validation failures at `GET /api/legacy-batches/{batchId}/rejections`. + + + +## Recovery + +List batches to locate a lost client receipt, then read the specific batch. Retry a timed-out submission with the original idempotency key and identical payload. Never create a second export merely because the client did not receive the first response. diff --git a/src/content/docs/v1/guides/payment-jobs.mdx b/src/content/docs/v1/guides/payment-jobs.mdx new file mode 100644 index 0000000..0a35fd5 --- /dev/null +++ b/src/content/docs/v1/guides/payment-jobs.mdx @@ -0,0 +1,37 @@ +--- +title: Operate payment jobs +description: Submit external payment processing work and follow its asynchronous status. +--- + +Workbench accepts payment jobs and delegates durable process state to the settlement domain. Job acceptance is not settlement completion. + +## Submit a job + +```bash +curl -sS -X POST https://workbench.mavula.dev/api/jobs \ + -H "Authorization: Bearer $MAVULA_ACCESS_TOKEN" \ + -H 'Content-Type: application/json' \ + -H 'Idempotency-Key: bfe8b575-2137-4a86-a210-cc2182130aed' \ + -H 'X-Correlation-ID: fd662f62-19c7-4f92-941f-64667437e6f9' \ + -d '{"queue":"payments","type":"PAYMENT_CAPTURE","max_attempts":3,"payload":{"idempotency_key":"payment_capture_20260715_001","correlation_id":"fd662f62-19c7-4f92-941f-64667437e6f9","rail":"mpesa","amount":{"currency":"MZN","valueMinor":250000},"payer":{"accountRef":"customer_001","phoneNumber":"+258840000001"},"payee":{"accountRef":"merchant_001"}}}' +``` + +Persist the returned job identifier and poll the status resource: + +```bash +curl -sS https://workbench.mavula.dev/api/jobs/JOB_ID \ + -H "Authorization: Bearer $MAVULA_ACCESS_TOKEN" +``` + +## Operational states + +| State | Meaning | Client action | +| --- | --- | --- | +| Accepted or queued | Work is durable and awaiting execution | Poll with bounded backoff | +| Active | Provider interaction or reconciliation is in progress | Continue polling | +| Completed | Process reached its terminal successful state | Reconcile the resulting domain state | +| Failed | Retry policy was exhausted or input cannot proceed | Read failure details; correct before resubmission | +| Expired | Process exceeded its permitted execution window | Investigate provider state before retrying | +| Compensation required | Automated completion is unsafe | Escalate to an authorized operator | + +Do not infer a ledger posting from a payment process state. Ledger Core remains the owner of financial postings and invariants. diff --git a/src/content/docs/v1/index.mdx b/src/content/docs/v1/index.mdx new file mode 100644 index 0000000..e10a325 --- /dev/null +++ b/src/content/docs/v1/index.mdx @@ -0,0 +1,30 @@ +--- +title: API v1 overview +description: Public integration boundaries and operational expectations for MAVULA API v1. +--- + +MAVULA API v1 separates identity, financial state and asynchronous operations into explicit service boundaries. Obtain an access token from Identity Access, call Ledger Core for financial domain operations, and use Workbench for operational jobs and legacy batches. + +## Service map + +| API | Base URL | Interaction model | +| --- | --- | --- | +| Identity Access | `https://identity.mavula.dev` | OAuth 2.0 and OpenID Connect | +| Ledger Core | `https://ledger.mavula.dev` | Synchronous commands and reads | +| Workbench | `https://workbench.mavula.dev` | Asynchronous jobs and operational reads | + +Tenant scope is derived from the authenticated identity. Do not send a tenant selector in the URL or body unless a specific operation schema requires it. + +## Integration contract + +Every protected request uses a bearer token. Mutating requests also use `Idempotency-Key`; all requests should send `X-Correlation-ID`. Monetary values are decimal strings and currencies are ISO 4217 uppercase codes. + +```http +Authorization: Bearer eyJ... +Idempotency-Key: 76b05d81-c975-4daf-b054-72b2eb3a749a +X-Correlation-ID: 406d8359-a53a-4d2a-a908-628798ece3b3 +Content-Type: application/json +``` + +Start with the [quickstart](./getting-started/quickstart/) or select a workflow from the sidebar. + diff --git a/src/content/docs/v1/resources/code-examples.mdx b/src/content/docs/v1/resources/code-examples.mdx new file mode 100644 index 0000000..b0d8ee0 --- /dev/null +++ b/src/content/docs/v1/resources/code-examples.mdx @@ -0,0 +1,31 @@ +--- +title: Code examples +description: Reusable request patterns and a Postman collection for MAVULA API v1. +--- + +The guides include executable fragments for curl, TypeScript, Python, Java and Go. All clients should centralize token acquisition, correlation IDs, idempotency keys, bounded retries and structured error handling. + +## Client checklist + +| Concern | Implementation | +| --- | --- | +| Secrets | Runtime secret store or environment injection | +| HTTP timeout | Explicit connect and response deadlines | +| Money | Decimal or arbitrary-precision type; serialize as a string | +| Retries | Bounded exponential backoff with jitter | +| Mutations | Stable idempotency key per logical command | +| Tracing | Propagate `X-Correlation-ID` | +| Logs | Redact bearer tokens, secrets and regulated personal data | + +## Postman + +The repository includes a versioned collection at [`examples/postman/MAVULA-API-v1.postman_collection.json`](https://github.com/mavulahq/developer-docs/blob/main/examples/postman/MAVULA-API-v1.postman_collection.json). Define `identity_base_url`, `ledger_base_url`, `workbench_base_url`, `client_id`, `client_secret` and `access_token` in a private Postman environment. + +## Reference contracts + +- [Identity Access OpenAPI](/developer-docs/openapi/identity-access.public.v1.yaml) +- [Ledger Core OpenAPI](/developer-docs/openapi/ledger-core.public.v1.yaml) +- [Workbench OpenAPI](/developer-docs/openapi/workbench.public.v1.yaml) + +Use these contracts to generate clients in your preferred language. Pin the downloaded contract digest in regulated build pipelines. + diff --git a/src/content/docs/v1/resources/limitations.mdx b/src/content/docs/v1/resources/limitations.mdx new file mode 100644 index 0000000..e467000 --- /dev/null +++ b/src/content/docs/v1/resources/limitations.mdx @@ -0,0 +1,16 @@ +--- +title: Current limitations +description: Explicit boundaries of the currently published MAVULA API v1 surface. +--- + +API v1 documents implemented public interfaces only. The following boundaries are intentional: + +- Legacy imports are staged and validated but do not mutate financial state. +- Payment process state does not directly create ledger postings. +- Internal callbacks, health probes, metrics and administrative runtime endpoints are excluded. +- The documentation site does not provide a live request console or retain credentials. +- Projection reads are eventually consistent and are not a substitute for authoritative command results. +- SDK packages are not yet published; examples use standard language HTTP clients. + +Proposed events or interfaces remain outside the public reference until their ownership, idempotency, failure behavior and compatibility guarantees are approved. + diff --git a/src/pages/openapi/identity-access.public.v1.yaml.ts b/src/pages/openapi/identity-access.public.v1.yaml.ts new file mode 100644 index 0000000..1e4edb5 --- /dev/null +++ b/src/pages/openapi/identity-access.public.v1.yaml.ts @@ -0,0 +1,7 @@ +import { readFileSync } from 'node:fs'; + +const source = readFileSync(new URL('../../../openapi/identity-access.public.v1.yaml', import.meta.url), 'utf8'); + +export function GET() { + return new Response(source, { headers: { 'content-type': 'application/yaml; charset=utf-8' } }); +} diff --git a/src/pages/openapi/ledger-core.public.v1.yaml.ts b/src/pages/openapi/ledger-core.public.v1.yaml.ts new file mode 100644 index 0000000..5cb5bf7 --- /dev/null +++ b/src/pages/openapi/ledger-core.public.v1.yaml.ts @@ -0,0 +1,7 @@ +import { readFileSync } from 'node:fs'; + +const source = readFileSync(new URL('../../../openapi/ledger-core.public.v1.yaml', import.meta.url), 'utf8'); + +export function GET() { + return new Response(source, { headers: { 'content-type': 'application/yaml; charset=utf-8' } }); +} diff --git a/src/pages/openapi/workbench.public.v1.yaml.ts b/src/pages/openapi/workbench.public.v1.yaml.ts new file mode 100644 index 0000000..18e3a11 --- /dev/null +++ b/src/pages/openapi/workbench.public.v1.yaml.ts @@ -0,0 +1,7 @@ +import { readFileSync } from 'node:fs'; + +const source = readFileSync(new URL('../../../openapi/workbench.public.v1.yaml', import.meta.url), 'utf8'); + +export function GET() { + return new Response(source, { headers: { 'content-type': 'application/yaml; charset=utf-8' } }); +} diff --git a/src/pages/v1/api/[api].astro b/src/pages/v1/api/[api].astro new file mode 100644 index 0000000..a8663d1 --- /dev/null +++ b/src/pages/v1/api/[api].astro @@ -0,0 +1,66 @@ +--- +import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro'; +import '@scalar/api-reference/style.css'; + +export function getStaticPaths() { + return [ + { + params: { api: 'identity-access' }, + props: { + title: 'Identity Access API', + description: 'OAuth 2.0, OpenID Connect discovery and effective institutional identity.', + file: 'identity-access.public.v1.yaml', + }, + }, + { + params: { api: 'ledger-core' }, + props: { + title: 'Ledger Core API', + description: 'Accounts, controlled financial operations, configuration and projections.', + file: 'ledger-core.public.v1.yaml', + }, + }, + { + params: { api: 'workbench' }, + props: { + title: 'Workbench API', + description: 'Operational jobs, payment processing status and legacy batch orchestration.', + file: 'workbench.public.v1.yaml', + }, + }, + ]; +} + +const { title, description, file } = Astro.props; +const specUrl = `${import.meta.env.BASE_URL}/openapi/${file}`; +--- + + +
+
+
+
+ + diff --git a/src/styles/custom.css b/src/styles/custom.css new file mode 100644 index 0000000..0fef050 --- /dev/null +++ b/src/styles/custom.css @@ -0,0 +1,97 @@ +:root { + --sl-font: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; + --sl-font-mono: "SFMono-Regular", Consolas, "Liberation Mono", monospace; + --sl-color-accent-low: #fff1e8; + --sl-color-accent: #ef5b0c; + --sl-color-accent-high: #8d2d00; + --sl-color-white: #071a45; + --sl-color-gray-1: #18284d; + --sl-color-gray-2: #405071; + --sl-color-gray-3: #68748b; + --sl-color-gray-4: #a7afbe; + --sl-color-gray-5: #dbe0e8; + --sl-color-gray-6: #eef1f5; + --sl-color-black: #ffffff; + --sl-nav-height: 4.25rem; + --sl-sidebar-width: 15rem; + --sl-content-width: 58rem; + --sl-text-h1: 2.25rem; + --sl-text-h2: 1.45rem; + --sl-text-h3: 1.08rem; +} + +:root[data-theme='dark'] { + --sl-color-accent-low: #54230b; + --sl-color-accent: #ff7a2f; + --sl-color-accent-high: #ffd4bc; + --sl-color-white: #f7f9fc; + --sl-color-gray-1: #dfe5ef; + --sl-color-gray-2: #b9c2d2; + --sl-color-gray-3: #8792a7; + --sl-color-gray-4: #526078; + --sl-color-gray-5: #2b3850; + --sl-color-gray-6: #17233a; + --sl-color-black: #071225; +} + +html { letter-spacing: 0; } +body { background: var(--sl-color-black); } +.header { border-bottom: 1px solid var(--sl-color-gray-5); box-shadow: none; } +.site-title { color: #071a45; font-weight: 750; gap: .55rem; } +:root[data-theme='dark'] .site-title { color: #f7f9fc; } +.site-title::before { + content: 'M.'; + display: inline-grid; + place-items: center; + width: 2.25rem; + height: 2.25rem; + border: 2px solid currentColor; + border-radius: .45rem; + font-size: 1rem; + font-weight: 800; +} +.sidebar-pane { border-inline-end: 1px solid var(--sl-color-gray-5); } +.sidebar-content { padding-top: 1.25rem; } +.sidebar-content summary { font-size: .72rem; text-transform: uppercase; letter-spacing: 0; color: var(--sl-color-gray-3); } +.sidebar-content a { border-radius: 4px; font-size: .88rem; } +.sidebar-content a[aria-current='page'] { color: var(--sl-color-accent); background: var(--sl-color-accent-low); font-weight: 650; } +.main-pane { min-width: 0; } +.content-panel { padding-top: 2.5rem; } +.sl-markdown-content h1, .sl-markdown-content h2, .sl-markdown-content h3 { letter-spacing: 0; color: var(--sl-color-white); } +.sl-markdown-content h1 { line-height: 1.12; } +.sl-markdown-content p, .sl-markdown-content li { line-height: 1.65; } +.sl-markdown-content code:not(pre code) { border-radius: 3px; padding: .15rem .35rem; } +.sl-markdown-content table { display: table; width: 100%; font-size: .86rem; } +.sl-markdown-content th { background: var(--sl-color-gray-6); color: var(--sl-color-white); } +.sl-markdown-content th, .sl-markdown-content td { border-color: var(--sl-color-gray-5); padding: .7rem .8rem; } +.expressive-code { border: 1px solid var(--sl-color-gray-5); border-radius: 6px; box-shadow: none; } +.starlight-aside { border-radius: 6px; } +.hero { padding-block: 3rem 2rem; } +.hero h1 { max-width: 15ch; } +.hero .tagline { max-width: 47rem; } +.action.primary { border-radius: 4px; background: var(--sl-color-accent); border-color: var(--sl-color-accent); } +.action.minimal { border-radius: 4px; } + +.workflow-grid { display: grid; grid-template-columns: minmax(15rem, .8fr) minmax(22rem, 1.4fr); gap: 2rem; align-items: start; } +.workflow-steps { counter-reset: workflow; border-inline-end: 1px solid var(--sl-color-gray-5); padding-inline-end: 1.75rem; } +.workflow-step { counter-increment: workflow; position: relative; padding: 0 0 2rem 3rem; } +.workflow-step::before { content: counter(workflow); position: absolute; inset: 0 auto auto 0; display: grid; place-items: center; width: 1.75rem; height: 1.75rem; border-radius: 50%; background: var(--sl-color-accent); color: white; font-weight: 700; } +.workflow-step:not(:last-child)::after { content: ''; position: absolute; left: .85rem; top: 2rem; bottom: .25rem; border-left: 1px dashed var(--sl-color-gray-4); } +.workflow-step h3 { margin: 0 0 .35rem; font-size: 1rem; } +.workflow-step p { margin: 0; color: var(--sl-color-gray-2); font-size: .9rem; } +.role-matrix { display: grid; grid-template-columns: 1fr 1fr; border: 1px solid var(--sl-color-gray-5); border-radius: 5px; overflow: hidden; margin-bottom: 1.5rem; } +.role-matrix > div { padding: .8rem 1rem; } +.role-matrix > div + div { border-inline-start: 1px solid var(--sl-color-gray-5); } +.role-matrix strong { display: block; margin-bottom: .4rem; color: var(--sl-color-white); } +.role-matrix span { display: block; font-size: .86rem; color: var(--sl-color-gray-2); } +.api-shell { min-height: calc(100vh - var(--sl-nav-height)); border-top: 1px solid var(--sl-color-gray-5); } +#api-reference { min-height: 75vh; } + +@media (max-width: 800px) { + :root { --sl-text-h1: 1.85rem; } + .workflow-grid { grid-template-columns: 1fr; } + .workflow-steps { border-inline-end: 0; border-bottom: 1px solid var(--sl-color-gray-5); padding-inline-end: 0; } + .role-matrix { grid-template-columns: 1fr; } + .role-matrix > div + div { border-inline-start: 0; border-top: 1px solid var(--sl-color-gray-5); } + .sl-markdown-content table { display: block; overflow-x: auto; } +} diff --git a/test/contracts.test.mjs b/test/contracts.test.mjs new file mode 100644 index 0000000..64855f4 --- /dev/null +++ b/test/contracts.test.mjs @@ -0,0 +1,53 @@ +import test from 'node:test'; +import assert from 'node:assert/strict'; +import { readFileSync } from 'node:fs'; + +test('all published operations use unique operationId values', () => { + const operationIds = []; + for (const file of ['identity-access', 'ledger-core', 'workbench']) { + const source = readFileSync(`openapi/${file}.public.v1.yaml`, 'utf8'); + operationIds.push(...[...source.matchAll(/^\s+operationId: (\S+)$/gm)].map((match) => match[1])); + } + assert.equal(new Set(operationIds).size, operationIds.length); + assert.equal(operationIds.length, 57); +}); + +test('legacy batch guide preserves validation-only and durable recovery boundaries', () => { + const guide = readFileSync('src/content/docs/v1/guides/legacy-batches.mdx', 'utf8'); + const workbench = readFileSync('openapi/workbench.public.v1.yaml', 'utf8'); + assert.match(guide, /imports are staged and validated only/i); + assert.match(guide, /durable batch receipt/i); + assert.match(guide, /do not mutate financial state/i); + for (const route of ['/api/regulatory-exports', '/api/legacy-imports', '/api/legacy-batches/{batchId}/artifact']) { + assert.ok(workbench.includes(route), `missing documented route ${route}`); + } +}); + +test('portal covers identity, financial controls, payments and reliability', () => { + const files = [ + 'src/content/docs/v1/getting-started/authentication.mdx', + 'src/content/docs/v1/guides/account-lifecycle.mdx', + 'src/content/docs/v1/guides/financial-adjustments.mdx', + 'src/content/docs/v1/guides/payment-jobs.mdx', + 'src/content/docs/v1/concepts/idempotency.mdx', + ]; + const content = files.map((file) => readFileSync(file, 'utf8')).join('\n'); + for (const expectation of ['internal.worker', 'operations_maker', 'REVERSAL', 'PAYMENT_CAPTURE', 'idempotency key']) { + assert.match(content, new RegExp(expectation, 'i')); + } +}); + +test('published examples use canonical hosts and contract payload names', () => { + const files = [ + 'src/content/docs/v1/getting-started/quickstart.mdx', + 'src/content/docs/v1/getting-started/roles-permissions.mdx', + 'src/content/docs/v1/guides/payment-jobs.mdx', + 'src/content/docs/v1/guides/legacy-batches.mdx', + 'examples/postman/MAVULA-API-v1.postman_collection.json', + ]; + const content = files.map((file) => readFileSync(file, 'utf8')).join('\n'); + assert.doesNotMatch(content, /https:\/\/(?:identity|ledger|workbench)\.mavula\.io/); + for (const expectation of ['mavula.dev', 'compliance.manage', 'valueMinor', 'period_from', 'authority_reference']) { + assert.match(content, new RegExp(expectation, 'i')); + } +}); diff --git a/test/e2e/docs.spec.ts b/test/e2e/docs.spec.ts new file mode 100644 index 0000000..e09291c --- /dev/null +++ b/test/e2e/docs.spec.ts @@ -0,0 +1,27 @@ +import { expect, test } from '@playwright/test'; + +test('financial controls guide renders the complete maker-checker workflow', async ({ page }, testInfo) => { + await page.goto('/developer-docs/v1/guides/account-lifecycle/'); + await expect(page.getByRole('heading', { level: 1, name: 'Control an account lifecycle' })).toBeVisible(); + await expect(page.getByText('operations_maker', { exact: true }).first()).toBeVisible(); + await expect(page.getByRole('tab', { name: 'Java' })).toBeVisible(); + await expect(page.getByText('Self-approval is rejected')).toBeVisible(); + const overflow = await page.evaluate(() => document.documentElement.scrollWidth - window.innerWidth); + expect(overflow).toBeLessThanOrEqual(1); + await page.screenshot({ path: testInfo.outputPath('financial-controls.png'), fullPage: true }); +}); + +test('local Scalar reference loads the owner OpenAPI contract', async ({ page }, testInfo) => { + await page.goto('/developer-docs/v1/api/ledger-core/'); + await expect(page.getByRole('heading', { level: 1, name: 'Ledger Core API', exact: true })).toBeVisible(); + await expect.poll(async () => page.locator('#api-reference').innerText(), { timeout: 20_000 }).toContain('/api/accounts'); + await expect(page.getByRole('button', { name: 'Ask AI' })).toHaveCount(0); + await page.screenshot({ path: testInfo.outputPath('ledger-reference.png'), fullPage: false }); +}); + +test('published OpenAPI remains directly downloadable', async ({ request }) => { + const response = await request.get('/developer-docs/openapi/workbench.public.v1.yaml'); + expect(response.ok()).toBeTruthy(); + expect(response.headers()['content-type']).toMatch(/^(application|text)\/yaml/); + expect(await response.text()).toContain('/api/regulatory-exports:'); +}); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..bcbf8b5 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "astro/tsconfigs/strict" +}