From f62b17ca67a768580e33948cf340efedffa74151 Mon Sep 17 00:00:00 2001
From: Estandar <143508382+EstandarMustaq@users.noreply.github.com>
Date: Wed, 15 Jul 2026 16:08:11 +0200
Subject: [PATCH 1/5] feat: publish versioned public api reference
---
.github/workflows/pages.yml | 34 ++++
.github/workflows/required-ci.yml | 19 ++
README.md | 18 ++
openapi/identity-access.public.v1.yaml | 96 ++++++++++
openapi/ledger-core.public.v1.yaml | 254 +++++++++++++++++++++++++
openapi/workbench.public.v1.yaml | 64 +++++++
package.json | 8 +-
pnpm-lock.yaml | 24 +++
redocly.yaml | 7 +
scripts/build-docs.mjs | 32 ++++
scripts/check-contracts.mjs | 20 ++
scripts/guardian.mjs | 3 +-
sources.lock.json | 23 +++
test/contracts.test.mjs | 13 ++
14 files changed, 613 insertions(+), 2 deletions(-)
create mode 100644 .github/workflows/pages.yml
create mode 100644 .github/workflows/required-ci.yml
create mode 100644 openapi/identity-access.public.v1.yaml
create mode 100644 openapi/ledger-core.public.v1.yaml
create mode 100644 openapi/workbench.public.v1.yaml
create mode 100644 pnpm-lock.yaml
create mode 100644 redocly.yaml
create mode 100644 scripts/build-docs.mjs
create mode 100644 scripts/check-contracts.mjs
create mode 100644 sources.lock.json
create mode 100644 test/contracts.test.mjs
diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml
new file mode 100644
index 0000000..5a21b6f
--- /dev/null
+++ b/.github/workflows/pages.yml
@@ -0,0 +1,34 @@
+name: Publish API Reference
+on:
+ push: { branches: [main] }
+ workflow_dispatch: {}
+permissions:
+ contents: read
+ pages: write
+ id-token: write
+concurrency:
+ group: pages
+ cancel-in-progress: true
+jobs:
+ build:
+ 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 build
+ - uses: actions/upload-pages-artifact@v4
+ with: { path: dist }
+ deploy:
+ environment:
+ name: github-pages
+ url: ${{ steps.deployment.outputs.page_url }}
+ runs-on: ubuntu-latest
+ needs: build
+ steps:
+ - name: Deploy
+ id: deployment
+ uses: actions/deploy-pages@v4
diff --git a/.github/workflows/required-ci.yml b/.github/workflows/required-ci.yml
new file mode 100644
index 0000000..d631473
--- /dev/null
+++ b/.github/workflows/required-ci.yml
@@ -0,0 +1,19 @@
+name: Required CI
+on:
+ pull_request: {}
+ push: { branches: [main] }
+permissions: { contents: read }
+jobs:
+ required:
+ 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
diff --git a/README.md b/README.md
index 6c2e27a..683b269 100644
--- a/README.md
+++ b/README.md
@@ -6,6 +6,24 @@ The repository publishes approved Identity Access, Ledger Core and Workbench
interfaces. Internal callbacks, health checks and observability endpoints are
excluded from the public reference.
+## 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
+```
+
## License
AGPL-3.0-only. MAVULA names and marks remain reserved.
diff --git a/openapi/identity-access.public.v1.yaml b/openapi/identity-access.public.v1.yaml
new file mode 100644
index 0000000..41efcb7
--- /dev/null
+++ b/openapi/identity-access.public.v1.yaml
@@ -0,0 +1,96 @@
+openapi: 3.1.0
+info:
+ title: MAVULA Identity Access API
+ version: 1.0.0
+ description: Institutional OAuth 2.0 and OpenID Connect authorization surface.
+servers:
+ - url: https://identity.mavula.dev
+security: []
+paths:
+ /.well-known/openid-configuration:
+ get:
+ operationId: getOpenIdConfiguration
+ tags: [Discovery]
+ responses:
+ '200': { description: OpenID Provider metadata }
+ /jwks:
+ get:
+ operationId: getJsonWebKeySet
+ tags: [Discovery]
+ responses:
+ '200': { description: Public PS256 signing keys }
+ /auth:
+ get:
+ operationId: authorize
+ tags: [OAuth2]
+ parameters:
+ - { in: query, name: client_id, required: true, schema: { type: string } }
+ - { in: query, name: redirect_uri, required: true, schema: { type: string, format: uri } }
+ - { in: query, name: response_type, required: true, schema: { const: code } }
+ - { in: query, name: scope, required: true, schema: { type: string } }
+ - { in: query, name: state, required: true, schema: { type: string } }
+ - { in: query, name: code_challenge, required: true, schema: { type: string } }
+ - { in: query, name: code_challenge_method, required: true, schema: { const: S256 } }
+ responses:
+ '302': { description: Authorization redirect }
+ /token:
+ post:
+ operationId: exchangeToken
+ tags: [OAuth2]
+ requestBody:
+ required: true
+ content:
+ application/x-www-form-urlencoded:
+ schema: { type: object, additionalProperties: true }
+ responses:
+ '200':
+ description: OAuth token response
+ content:
+ application/json:
+ schema: { $ref: '#/components/schemas/TokenResponse' }
+ '400': { $ref: '#/components/responses/OAuthError' }
+ /token/revocation:
+ post:
+ operationId: revokeToken
+ tags: [OAuth2]
+ requestBody:
+ required: true
+ content:
+ application/x-www-form-urlencoded:
+ schema: { type: object, required: [token], properties: { token: { type: string } } }
+ responses:
+ '200': { description: Revocation accepted }
+ /api/v1/me:
+ get:
+ operationId: getEffectiveOperatorIdentity
+ tags: [Identity]
+ security: [{ bearerAuth: [] }]
+ responses:
+ '200': { description: 'Effective tenant, institution, branch, roles and permissions' }
+ '401': { $ref: '#/components/responses/Unauthorized' }
+components:
+ securitySchemes:
+ bearerAuth: { type: http, scheme: bearer, bearerFormat: JWT }
+ oauth2:
+ type: oauth2
+ flows:
+ authorizationCode:
+ authorizationUrl: /auth
+ tokenUrl: /token
+ scopes: { openid: Authenticate operator, profile: Read effective identity }
+ clientCredentials:
+ tokenUrl: /token
+ scopes: { internal.worker: Invoke protected service callbacks }
+ schemas:
+ TokenResponse:
+ type: object
+ required: [access_token, token_type, expires_in]
+ properties:
+ access_token: { type: string }
+ token_type: { const: Bearer }
+ expires_in: { type: integer }
+ refresh_token: { type: string }
+ scope: { type: string }
+ responses:
+ OAuthError: { description: OAuth 2.0 error response }
+ Unauthorized: { description: Bearer token is missing or invalid }
diff --git a/openapi/ledger-core.public.v1.yaml b/openapi/ledger-core.public.v1.yaml
new file mode 100644
index 0000000..6edb7e2
--- /dev/null
+++ b/openapi/ledger-core.public.v1.yaml
@@ -0,0 +1,254 @@
+openapi: 3.1.0
+info:
+ title: MAVULA Ledger Core API
+ version: 1.0.0
+ description: Tenant-scoped accounts, financial controls, configuration and projection APIs.
+servers:
+ - url: https://ledger.mavula.dev
+security: [{ bearerAuth: [] }]
+paths:
+ /api/accounts:
+ get: { operationId: listAccounts, tags: [Accounts], responses: { '200': { description: Accounts } } }
+ post:
+ operationId: createAccount
+ tags: [Accounts]
+ parameters: [{ $ref: '#/components/parameters/IdempotencyKey' }]
+ requestBody: { $ref: '#/components/requestBodies/JsonObject' }
+ responses: { '201': { description: Account created }, '400': { $ref: '#/components/responses/BadRequest' }, '409': { $ref: '#/components/responses/Conflict' } }
+ /api/accounts/{accountId}:
+ get:
+ operationId: getAccount
+ tags: [Accounts]
+ parameters: [{ $ref: '#/components/parameters/AccountId' }]
+ responses: { '200': { description: Account }, '404': { $ref: '#/components/responses/NotFound' } }
+ /api/accounts/{accountId}/balance:
+ get:
+ operationId: getAccountBalance
+ tags: [Accounts]
+ parameters: [{ $ref: '#/components/parameters/AccountId' }]
+ responses: { '200': { description: Account balance } }
+ /api/accounts/{accountId}/statement:
+ get:
+ operationId: getAccountStatement
+ tags: [Accounts]
+ 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 } }
+ responses: { '200': { description: Paginated statement } }
+ /api/accounts/{accountId}/status-transitions:
+ post:
+ operationId: submitAccountStatusTransition
+ tags: [Account lifecycle]
+ parameters: [{ $ref: '#/components/parameters/AccountId' }, { $ref: '#/components/parameters/IdempotencyKey' }]
+ requestBody: { $ref: '#/components/requestBodies/JsonObject' }
+ responses: { '201': { description: Lifecycle request submitted }, '409': { $ref: '#/components/responses/Conflict' } }
+ /api/account-lifecycle-requests:
+ get: { operationId: listAccountLifecycleRequests, tags: [Account lifecycle], responses: { '200': { description: Lifecycle requests } } }
+ /api/account-lifecycle-requests/{requestId}:
+ get:
+ operationId: getAccountLifecycleRequest
+ tags: [Account lifecycle]
+ parameters: [{ $ref: '#/components/parameters/RequestId' }]
+ responses: { '200': { description: Lifecycle request }, '404': { $ref: '#/components/responses/NotFound' } }
+ /api/account-lifecycle-requests/{requestId}/approve:
+ post:
+ operationId: approveAccountLifecycleRequest
+ tags: [Account lifecycle]
+ parameters: [{ $ref: '#/components/parameters/RequestId' }, { $ref: '#/components/parameters/IdempotencyKey' }]
+ requestBody: { $ref: '#/components/requestBodies/JsonObject' }
+ responses: { '201': { description: Lifecycle request approved }, '403': { $ref: '#/components/responses/Forbidden' }, '409': { $ref: '#/components/responses/Conflict' } }
+ /api/account-lifecycle-requests/{requestId}/reject:
+ post:
+ operationId: rejectAccountLifecycleRequest
+ tags: [Account lifecycle]
+ parameters: [{ $ref: '#/components/parameters/RequestId' }, { $ref: '#/components/parameters/IdempotencyKey' }]
+ requestBody: { $ref: '#/components/requestBodies/JsonObject' }
+ responses: { '201': { description: Lifecycle request rejected }, '403': { $ref: '#/components/responses/Forbidden' }, '409': { $ref: '#/components/responses/Conflict' } }
+ /api/financial-adjustment-requests:
+ get: { operationId: listFinancialAdjustmentRequests, tags: [Financial adjustments], responses: { '200': { description: Adjustment requests } } }
+ post:
+ operationId: submitFinancialAdjustmentRequest
+ tags: [Financial adjustments]
+ parameters: [{ $ref: '#/components/parameters/IdempotencyKey' }]
+ requestBody: { $ref: '#/components/requestBodies/JsonObject' }
+ responses: { '201': { description: Adjustment request submitted }, '409': { $ref: '#/components/responses/Conflict' } }
+ /api/financial-adjustment-requests/{requestId}:
+ get:
+ operationId: getFinancialAdjustmentRequest
+ tags: [Financial adjustments]
+ parameters: [{ $ref: '#/components/parameters/RequestId' }]
+ responses: { '200': { description: Adjustment request }, '404': { $ref: '#/components/responses/NotFound' } }
+ /api/financial-adjustment-requests/{requestId}/approve:
+ post:
+ operationId: approveFinancialAdjustmentRequest
+ tags: [Financial adjustments]
+ parameters: [{ $ref: '#/components/parameters/RequestId' }, { $ref: '#/components/parameters/IdempotencyKey' }]
+ requestBody: { $ref: '#/components/requestBodies/JsonObject' }
+ responses: { '201': { description: Adjustment applied }, '403': { $ref: '#/components/responses/Forbidden' }, '409': { $ref: '#/components/responses/Conflict' } }
+ /api/financial-adjustment-requests/{requestId}/reject:
+ post:
+ operationId: rejectFinancialAdjustmentRequest
+ tags: [Financial adjustments]
+ parameters: [{ $ref: '#/components/parameters/RequestId' }, { $ref: '#/components/parameters/IdempotencyKey' }]
+ requestBody: { $ref: '#/components/requestBodies/JsonObject' }
+ responses: { '201': { description: Adjustment rejected }, '403': { $ref: '#/components/responses/Forbidden' }, '409': { $ref: '#/components/responses/Conflict' } }
+ /api/products:
+ get: { operationId: listProducts, tags: [Configuration], responses: { '200': { description: Products } } }
+ post:
+ operationId: upsertProduct
+ tags: [Configuration]
+ parameters: [{ $ref: '#/components/parameters/IdempotencyKey' }]
+ requestBody: { $ref: '#/components/requestBodies/JsonObject' }
+ responses: { '201': { description: Product configuration stored }, '409': { $ref: '#/components/responses/Conflict' } }
+ /api/products/config:
+ get: { operationId: getProductConfiguration, tags: [Configuration], responses: { '200': { description: Tenant product configuration } } }
+ /api/products/config/generate:
+ post:
+ operationId: generateProductConfiguration
+ tags: [Configuration]
+ parameters: [{ $ref: '#/components/parameters/IdempotencyKey' }]
+ requestBody: { $ref: '#/components/requestBodies/JsonObject' }
+ responses: { '201': { description: Configuration generated }, '409': { $ref: '#/components/responses/Conflict' } }
+ /api/products/{productId}:
+ get:
+ operationId: getProduct
+ tags: [Configuration]
+ parameters: [{ $ref: '#/components/parameters/ProductId' }]
+ responses: { '200': { description: Product }, '404': { $ref: '#/components/responses/NotFound' } }
+ /api/products/{productId}/rules:
+ get:
+ operationId: listRules
+ tags: [Rules]
+ parameters: [{ $ref: '#/components/parameters/ProductId' }]
+ responses: { '200': { description: Rules } }
+ post:
+ operationId: createRule
+ tags: [Rules]
+ parameters: [{ $ref: '#/components/parameters/ProductId' }, { $ref: '#/components/parameters/IdempotencyKey' }]
+ requestBody: { $ref: '#/components/requestBodies/JsonObject' }
+ responses: { '201': { description: Rule created }, '409': { $ref: '#/components/responses/Conflict' } }
+ /api/products/{productId}/rules/defaults:
+ post:
+ operationId: seedDefaultRules
+ tags: [Rules]
+ parameters: [{ $ref: '#/components/parameters/ProductId' }, { $ref: '#/components/parameters/IdempotencyKey' }]
+ responses: { '201': { description: Default rules created }, '409': { $ref: '#/components/responses/Conflict' } }
+ /api/products/{productId}/rules/{ruleId}:
+ put:
+ operationId: updateRule
+ tags: [Rules]
+ parameters: [{ $ref: '#/components/parameters/ProductId' }, { in: path, name: ruleId, required: true, schema: { type: string } }, { $ref: '#/components/parameters/IdempotencyKey' }]
+ requestBody: { $ref: '#/components/requestBodies/JsonObject' }
+ responses: { '200': { description: Rule updated }, '409': { $ref: '#/components/responses/Conflict' } }
+ delete:
+ operationId: deleteRule
+ tags: [Rules]
+ parameters: [{ $ref: '#/components/parameters/ProductId' }, { in: path, name: ruleId, required: true, schema: { type: string } }, { $ref: '#/components/parameters/IdempotencyKey' }]
+ responses: { '200': { description: Rule deleted }, '409': { $ref: '#/components/responses/Conflict' } }
+ /api/schemas:
+ get: { operationId: listSchemas, tags: [Schemas], responses: { '200': { description: Schemas } } }
+ post:
+ operationId: createSchema
+ tags: [Schemas]
+ parameters: [{ $ref: '#/components/parameters/IdempotencyKey' }]
+ requestBody: { $ref: '#/components/requestBodies/JsonObject' }
+ responses: { '201': { description: Schema created }, '409': { $ref: '#/components/responses/Conflict' } }
+ /api/schemas/import:
+ post:
+ operationId: importSchema
+ tags: [Schemas]
+ parameters: [{ $ref: '#/components/parameters/IdempotencyKey' }]
+ requestBody: { $ref: '#/components/requestBodies/JsonObject' }
+ responses: { '201': { description: Schema imported }, '409': { $ref: '#/components/responses/Conflict' } }
+ /api/schemas/presets/business-registration:
+ post:
+ operationId: createBusinessRegistrationSchema
+ tags: [Schemas]
+ parameters: [{ $ref: '#/components/parameters/IdempotencyKey' }]
+ responses: { '201': { description: Preset schema created }, '409': { $ref: '#/components/responses/Conflict' } }
+ /api/schemas/{schemaId}:
+ get:
+ operationId: getSchema
+ tags: [Schemas]
+ parameters: [{ in: path, name: schemaId, required: true, schema: { type: string } }]
+ responses: { '200': { description: Schema }, '404': { $ref: '#/components/responses/NotFound' } }
+ /api/schemas/{schemaId}/export:
+ get:
+ operationId: exportSchema
+ tags: [Schemas]
+ parameters: [{ in: path, name: schemaId, required: true, schema: { type: string } }]
+ responses: { '200': { description: Portable schema definition } }
+ /api/workflows:
+ get: { operationId: listWorkflows, tags: [Workflows], responses: { '200': { description: Workflows } } }
+ post:
+ operationId: createWorkflow
+ tags: [Workflows]
+ parameters: [{ $ref: '#/components/parameters/IdempotencyKey' }]
+ requestBody: { $ref: '#/components/requestBodies/JsonObject' }
+ responses: { '201': { description: Workflow created }, '409': { $ref: '#/components/responses/Conflict' } }
+ /api/workflows/trigger/{trigger}:
+ get:
+ operationId: listWorkflowsByTrigger
+ tags: [Workflows]
+ parameters: [{ in: path, name: trigger, required: true, schema: { type: string } }]
+ responses: { '200': { description: Matching workflows } }
+ /api/workflows/presets/loan-approval-notification:
+ post:
+ operationId: createLoanApprovalNotificationWorkflow
+ tags: [Workflows]
+ parameters: [{ $ref: '#/components/parameters/IdempotencyKey' }]
+ responses: { '201': { description: Preset workflow created }, '409': { $ref: '#/components/responses/Conflict' } }
+ /api/workflows/presets/monthly-fee-charge:
+ post:
+ operationId: createMonthlyFeeChargeWorkflow
+ tags: [Workflows]
+ parameters: [{ $ref: '#/components/parameters/IdempotencyKey' }]
+ responses: { '201': { description: Preset workflow created }, '409': { $ref: '#/components/responses/Conflict' } }
+ /api/workflows/{workflowId}:
+ get:
+ operationId: getWorkflow
+ tags: [Workflows]
+ parameters: [{ in: path, name: workflowId, required: true, schema: { type: string } }]
+ responses: { '200': { description: Workflow }, '404': { $ref: '#/components/responses/NotFound' } }
+ /api/workflows/{workflowId}/execute:
+ post:
+ operationId: executeWorkflow
+ tags: [Workflows]
+ parameters: [{ in: path, name: workflowId, required: true, schema: { type: string } }, { $ref: '#/components/parameters/IdempotencyKey' }]
+ requestBody: { $ref: '#/components/requestBodies/JsonObject' }
+ responses: { '201': { description: Workflow execution completed }, '409': { $ref: '#/components/responses/Conflict' } }
+ /api/projections/status:
+ get: { operationId: getProjectionStatus, tags: [Projections], responses: { '200': { description: Projection checkpoints } } }
+ /api/projections/loan-activity:
+ get: { operationId: listLoanActivity, tags: [Projections], responses: { '200': { description: Loan activity projections } } }
+ /api/projections/loan-activity/{loanId}:
+ get: { operationId: getLoanActivity, tags: [Projections], parameters: [{ in: path, name: loanId, required: true, schema: { type: string } }], responses: { '200': { description: Loan activity projection } } }
+ /api/projections/ledger-activity:
+ get: { operationId: listLedgerActivity, tags: [Projections], responses: { '200': { description: Ledger activity projections } } }
+ /api/projections/ledger-activity/{journalEntryId}:
+ get: { operationId: getLedgerActivity, tags: [Projections], parameters: [{ in: path, name: journalEntryId, required: true, schema: { type: string } }], responses: { '200': { description: Ledger activity projection } } }
+ /api/projections/product-publications:
+ get: { operationId: listProductPublications, tags: [Projections], responses: { '200': { description: Product publication projections } } }
+ /api/projections/product-publications/{productId}:
+ get: { operationId: getProductPublication, tags: [Projections], parameters: [{ $ref: '#/components/parameters/ProductId' }], responses: { '200': { description: Product publication projection } } }
+components:
+ securitySchemes:
+ bearerAuth: { type: http, scheme: bearer, bearerFormat: JWT }
+ parameters:
+ IdempotencyKey: { in: header, name: Idempotency-Key, required: true, schema: { type: string, minLength: 16, 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 } }
+ requestBodies:
+ JsonObject:
+ required: true
+ content: { application/json: { schema: { type: object, additionalProperties: true } } }
+ responses:
+ BadRequest: { description: Request contract or Idempotency-Key is invalid }
+ Unauthorized: { description: Bearer token is missing or invalid }
+ Forbidden: { description: 'Permission, maker-checker or tenant policy denied the operation' }
+ NotFound: { description: Tenant-scoped resource was not found }
+ Conflict: { description: State conflict or Idempotency-Key reuse conflict }
diff --git a/openapi/workbench.public.v1.yaml b/openapi/workbench.public.v1.yaml
new file mode 100644
index 0000000..b06b88e
--- /dev/null
+++ b/openapi/workbench.public.v1.yaml
@@ -0,0 +1,64 @@
+openapi: 3.1.0
+info:
+ title: MAVULA Workbench API
+ version: 1.0.0
+ description: Authenticated job submission and operational status surface.
+servers:
+ - url: https://workbench.mavula.dev
+security: [{ bearerAuth: [] }]
+paths:
+ /api/jobs:
+ post:
+ operationId: createJob
+ tags: [Jobs]
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema: { $ref: '#/components/schemas/CreateJob' }
+ responses:
+ '201': { description: Job accepted }
+ '400': { $ref: '#/components/responses/BadRequest' }
+ '401': { $ref: '#/components/responses/Unauthorized' }
+ '403': { $ref: '#/components/responses/Forbidden' }
+ /api/jobs/{jobId}:
+ get:
+ operationId: getJob
+ tags: [Jobs]
+ parameters:
+ - { in: path, name: jobId, required: true, schema: { type: string } }
+ responses:
+ '200': { description: Tenant-scoped job status }
+ '404': { description: Job not found }
+ /api/status:
+ get:
+ operationId: getPlatformStatus
+ tags: [Status]
+ responses: { '200': { description: Worker runtime status } }
+ /api/status/queues:
+ get:
+ operationId: getQueueStatus
+ tags: [Status]
+ responses: { '200': { description: Tenant-safe queue status } }
+ /api/status/schedules:
+ get:
+ operationId: getScheduleStatus
+ tags: [Status]
+ responses: { '200': { description: Registered schedules } }
+components:
+ securitySchemes:
+ bearerAuth: { type: http, scheme: bearer, bearerFormat: JWT }
+ schemas:
+ CreateJob:
+ type: object
+ required: [type, payload]
+ properties:
+ type: { type: string }
+ queue: { type: string }
+ payload: { type: object, additionalProperties: true }
+ max_attempts: { type: integer, minimum: 1 }
+ idempotency_key: { type: string }
+ responses:
+ BadRequest: { description: Request contract is invalid }
+ Unauthorized: { description: Bearer token is missing or invalid }
+ Forbidden: { description: Required permission or tenant boundary is not satisfied }
diff --git a/package.json b/package.json
index 5e4b963..518ea7e 100644
--- a/package.json
+++ b/package.json
@@ -7,5 +7,11 @@
"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": {
+ "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"
+ },
+ "devDependencies": { "@redocly/cli": "2.39.0" }
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
new file mode 100644
index 0000000..31c1717
--- /dev/null
+++ b/pnpm-lock.yaml
@@ -0,0 +1,24 @@
+lockfileVersion: '9.0'
+
+settings:
+ autoInstallPeers: true
+ excludeLinksFromLockfile: false
+
+importers:
+
+ .:
+ devDependencies:
+ '@redocly/cli':
+ specifier: 2.39.0
+ version: 2.39.0
+
+packages:
+
+ '@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
+
+snapshots:
+
+ '@redocly/cli@2.39.0': {}
diff --git a/redocly.yaml b/redocly.yaml
new file mode 100644
index 0000000..6901eb0
--- /dev/null
+++ b/redocly.yaml
@@ -0,0 +1,7 @@
+extends:
+ - recommended
+rules:
+ no-server-example.com: off
+ operation-description: off
+ operation-summary: off
+ security-defined: error
diff --git a/scripts/build-docs.mjs b/scripts/build-docs.mjs
new file mode 100644
index 0000000..5ad0889
--- /dev/null
+++ b/scripts/build-docs.mjs
@@ -0,0 +1,32 @@
+import { mkdirSync, rmSync, writeFileSync } from 'node:fs';
+import { spawnSync } from 'node:child_process';
+
+const contracts = [
+ ['identity-access.public.v1.yaml', 'identity-access.html'],
+ ['ledger-core.public.v1.yaml', 'ledger-core.html'],
+ ['workbench.public.v1.yaml', 'workbench.html'],
+];
+rmSync('dist', { recursive: true, force: true });
+mkdirSync('dist', { recursive: true });
+for (const [source, output] of contracts) {
+ run(['lint', `openapi/${source}`]);
+ run(['build-docs', `openapi/${source}`, '--output', `dist/${output}`]);
+}
+writeFileSync('dist/index.html', `
+
+MAVULA API ReferenceMAVULA API Reference
Versioned institutional finance interfaces.
`);
+
+function run(args) {
+ const executable = process.platform === 'win32' ? 'redocly.cmd' : 'redocly';
+ const result = spawnSync(executable, args, { stdio: 'inherit', shell: process.platform === 'win32' });
+ if (result.status !== 0) throw new Error(`redocly ${args.join(' ')} failed`);
+}
diff --git a/scripts/check-contracts.mjs b/scripts/check-contracts.mjs
new file mode 100644
index 0000000..0609bf3
--- /dev/null
+++ b/scripts/check-contracts.mjs
@@ -0,0 +1,20 @@
+import { createHash } from 'node:crypto';
+import { readFileSync } from 'node:fs';
+
+const lock = JSON.parse(readFileSync('sources.lock.json', 'utf8'));
+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 source = readFileSync(`openapi/${contract.file}`, 'utf8');
+ const digest = createHash('sha256').update(source).digest('hex');
+ if (digest !== contract.sha256) throw new Error(`${contract.file} does not match its owner digest`);
+ if (!source.startsWith('openapi: 3.1.0')) throw new Error(`${contract.file} must use OpenAPI 3.1.0`);
+ const paths = [...source.matchAll(/^ (\/[^:]+):$/gm)].map((match) => match[1]);
+ for (const route of paths) {
+ if (/\/internal\/|\/interaction|\/health$|\/metrics$|\/auth\/login/.test(route)) {
+ throw new Error(`${contract.file} exposes non-public route ${route}`);
+ }
+ }
+}
+console.log('developer-docs owner contract digests and public boundaries are valid');
diff --git a/scripts/guardian.mjs b/scripts/guardian.mjs
index 5e47769..bbe8152 100644
--- a/scripts/guardian.mjs
+++ b/scripts/guardian.mjs
@@ -7,7 +7,8 @@ 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',
];
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..bfb79d9
--- /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": "4f2d1fc99a5cdbc978d1076688ec28eb8330697ce2298ede6cb2173c6ced0312"
+ },
+ {
+ "file": "ledger-core.public.v1.yaml",
+ "owner": "mavulahq/ledger-core",
+ "source": "contracts/openapi/ledger-core.public.v1.yaml",
+ "sha256": "9dcd05f603df109c40e00c411a2299da8672b84a22fc521da1b68034263179e3"
+ },
+ {
+ "file": "workbench.public.v1.yaml",
+ "owner": "mavulahq/workbench",
+ "source": "contracts/openapi/workbench.public.v1.yaml",
+ "sha256": "4323f267c259759abc342721f5624600461e8db8b1ee9e9c3ad0ea6741e5e57a"
+ }
+ ]
+}
diff --git a/test/contracts.test.mjs b/test/contracts.test.mjs
new file mode 100644
index 0000000..493e287
--- /dev/null
+++ b/test/contracts.test.mjs
@@ -0,0 +1,13 @@
+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.ok(operationIds.length > 20);
+});
From 48b5e6a359c3bb15f2307f910edfcb096a3361ce Mon Sep 17 00:00:00 2001
From: Estandar <143508382+EstandarMustaq@users.noreply.github.com>
Date: Wed, 15 Jul 2026 16:29:19 +0200
Subject: [PATCH 2/5] chore: sync licensed owner contracts
---
openapi/identity-access.public.v1.yaml | 1 +
openapi/ledger-core.public.v1.yaml | 1 +
openapi/workbench.public.v1.yaml | 1 +
sources.lock.json | 6 +++---
4 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/openapi/identity-access.public.v1.yaml b/openapi/identity-access.public.v1.yaml
index 41efcb7..9be8614 100644
--- a/openapi/identity-access.public.v1.yaml
+++ b/openapi/identity-access.public.v1.yaml
@@ -3,6 +3,7 @@ info:
title: MAVULA Identity Access API
version: 1.0.0
description: Institutional OAuth 2.0 and OpenID Connect authorization surface.
+ license: { name: GNU Affero General Public License v3.0 only, identifier: AGPL-3.0-only }
servers:
- url: https://identity.mavula.dev
security: []
diff --git a/openapi/ledger-core.public.v1.yaml b/openapi/ledger-core.public.v1.yaml
index 6edb7e2..9c8cd69 100644
--- a/openapi/ledger-core.public.v1.yaml
+++ b/openapi/ledger-core.public.v1.yaml
@@ -3,6 +3,7 @@ info:
title: MAVULA Ledger Core API
version: 1.0.0
description: Tenant-scoped accounts, financial controls, configuration and projection APIs.
+ license: { name: GNU Affero General Public License v3.0 only, identifier: AGPL-3.0-only }
servers:
- url: https://ledger.mavula.dev
security: [{ bearerAuth: [] }]
diff --git a/openapi/workbench.public.v1.yaml b/openapi/workbench.public.v1.yaml
index b06b88e..64c340d 100644
--- a/openapi/workbench.public.v1.yaml
+++ b/openapi/workbench.public.v1.yaml
@@ -3,6 +3,7 @@ info:
title: MAVULA Workbench API
version: 1.0.0
description: Authenticated job submission and operational status surface.
+ license: { name: GNU Affero General Public License v3.0 only, identifier: AGPL-3.0-only }
servers:
- url: https://workbench.mavula.dev
security: [{ bearerAuth: [] }]
diff --git a/sources.lock.json b/sources.lock.json
index bfb79d9..7b6a197 100644
--- a/sources.lock.json
+++ b/sources.lock.json
@@ -5,19 +5,19 @@
"file": "identity-access.public.v1.yaml",
"owner": "mavulahq/identity-access",
"source": "contracts/openapi/identity-access.public.v1.yaml",
- "sha256": "4f2d1fc99a5cdbc978d1076688ec28eb8330697ce2298ede6cb2173c6ced0312"
+ "sha256": "b7baa4c0846429ceb3834e15522861408bf432b0f6f23289ae03253491155ae3"
},
{
"file": "ledger-core.public.v1.yaml",
"owner": "mavulahq/ledger-core",
"source": "contracts/openapi/ledger-core.public.v1.yaml",
- "sha256": "9dcd05f603df109c40e00c411a2299da8672b84a22fc521da1b68034263179e3"
+ "sha256": "bd38bb863b2d3bf346f24670ff9cce70e737811f51f8e12f50d7fcade025bf50"
},
{
"file": "workbench.public.v1.yaml",
"owner": "mavulahq/workbench",
"source": "contracts/openapi/workbench.public.v1.yaml",
- "sha256": "4323f267c259759abc342721f5624600461e8db8b1ee9e9c3ad0ea6741e5e57a"
+ "sha256": "618bf289f0d293e615ea73321dd1ca7c24593967f1c52b9614ad1aa26f2edadf"
}
]
}
From 26f6b05613ddb1d9e36bc217f8b4c2e53b274cbd Mon Sep 17 00:00:00 2001
From: Estandar <143508382+EstandarMustaq@users.noreply.github.com>
Date: Thu, 16 Jul 2026 22:38:19 +0200
Subject: [PATCH 3/5] RFC-0002: publish legacy batch documentation (#2)
* docs: publish legacy batch integration guide
* docs: build complete public API portal (#3)
---
.gitignore | 4 +
README.md | 12 +-
astro.config.mjs | 80 +
.../MAVULA-API-v1.postman_collection.json | 76 +
openapi/identity-access.public.v1.yaml | 219 +-
openapi/ledger-core.public.v1.yaml | 881 ++-
openapi/workbench.public.v1.yaml | 395 +-
package.json | 13 +-
playwright.config.ts | 24 +
pnpm-lock.yaml | 5875 ++++++++++++++++-
public/favicon.svg | 4 +
redocly.yaml | 2 +-
scripts/build-docs.mjs | 41 +-
scripts/check-contracts.mjs | 23 +-
scripts/guardian.mjs | 5 +
sources.lock.json | 6 +-
src/content.config.ts | 7 +
src/content/docs/index.mdx | 35 +
src/content/docs/v1/concepts/errors.mdx | 29 +
src/content/docs/v1/concepts/idempotency.mdx | 25 +
src/content/docs/v1/concepts/projections.mdx | 20 +
.../docs/v1/concepts/tenant-isolation.mdx | 25 +
.../v1/getting-started/authentication.mdx | 83 +
.../docs/v1/getting-started/quickstart.mdx | 61 +
.../getting-started/request-reliability.mdx | 41 +
.../v1/getting-started/roles-permissions.mdx | 31 +
.../docs/v1/guides/account-lifecycle.mdx | 105 +
src/content/docs/v1/guides/account-setup.mdx | 42 +
src/content/docs/v1/guides/configuration.mdx | 36 +
.../docs/v1/guides/financial-adjustments.mdx | 34 +
src/content/docs/v1/guides/legacy-batches.mdx | 56 +
src/content/docs/v1/guides/payment-jobs.mdx | 38 +
src/content/docs/v1/index.mdx | 30 +
.../docs/v1/resources/code-examples.mdx | 31 +
src/content/docs/v1/resources/limitations.mdx | 16 +
src/pages/[legacy].html.astro | 11 +
src/pages/guides/legacy-batches.html.astro | 3 +
.../openapi/identity-access.public.v1.yaml.ts | 7 +
.../openapi/ledger-core.public.v1.yaml.ts | 7 +
src/pages/openapi/workbench.public.v1.yaml.ts | 7 +
src/pages/v1/api/[api].astro | 66 +
src/styles/custom.css | 97 +
test/contracts.test.mjs | 27 +-
test/e2e/docs.spec.ts | 27 +
tsconfig.json | 3 +
45 files changed, 8497 insertions(+), 163 deletions(-)
create mode 100644 astro.config.mjs
create mode 100644 examples/postman/MAVULA-API-v1.postman_collection.json
create mode 100644 playwright.config.ts
create mode 100644 public/favicon.svg
create mode 100644 src/content.config.ts
create mode 100644 src/content/docs/index.mdx
create mode 100644 src/content/docs/v1/concepts/errors.mdx
create mode 100644 src/content/docs/v1/concepts/idempotency.mdx
create mode 100644 src/content/docs/v1/concepts/projections.mdx
create mode 100644 src/content/docs/v1/concepts/tenant-isolation.mdx
create mode 100644 src/content/docs/v1/getting-started/authentication.mdx
create mode 100644 src/content/docs/v1/getting-started/quickstart.mdx
create mode 100644 src/content/docs/v1/getting-started/request-reliability.mdx
create mode 100644 src/content/docs/v1/getting-started/roles-permissions.mdx
create mode 100644 src/content/docs/v1/guides/account-lifecycle.mdx
create mode 100644 src/content/docs/v1/guides/account-setup.mdx
create mode 100644 src/content/docs/v1/guides/configuration.mdx
create mode 100644 src/content/docs/v1/guides/financial-adjustments.mdx
create mode 100644 src/content/docs/v1/guides/legacy-batches.mdx
create mode 100644 src/content/docs/v1/guides/payment-jobs.mdx
create mode 100644 src/content/docs/v1/index.mdx
create mode 100644 src/content/docs/v1/resources/code-examples.mdx
create mode 100644 src/content/docs/v1/resources/limitations.mdx
create mode 100644 src/pages/[legacy].html.astro
create mode 100644 src/pages/guides/legacy-batches.html.astro
create mode 100644 src/pages/openapi/identity-access.public.v1.yaml.ts
create mode 100644 src/pages/openapi/ledger-core.public.v1.yaml.ts
create mode 100644 src/pages/openapi/workbench.public.v1.yaml.ts
create mode 100644 src/pages/v1/api/[api].astro
create mode 100644 src/styles/custom.css
create mode 100644 test/e2e/docs.spec.ts
create mode 100644 tsconfig.json
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 683b269..03d3ec3 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,15 @@
-# 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`
@@ -22,8 +26,12 @@ 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..c12fb94
--- /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.io" },
+ { "key": "ledger_base_url", "value": "https://ledger.mavula.io" },
+ { "key": "workbench_base_url", "value": "https://workbench.mavula.io" },
+ { "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
index 9be8614..7434d0f 100644
--- a/openapi/identity-access.public.v1.yaml
+++ b/openapi/identity-access.public.v1.yaml
@@ -2,47 +2,98 @@ openapi: 3.1.0
info:
title: MAVULA Identity Access API
version: 1.0.0
- description: Institutional OAuth 2.0 and OpenID Connect authorization surface.
- license: { name: GNU Affero General Public License v3.0 only, identifier: AGPL-3.0-only }
+ 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 }
+ '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 PS256 signing keys }
+ '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, schema: { type: string } }
- - { in: query, name: redirect_uri, required: true, schema: { type: string, format: uri } }
+ - { 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, schema: { type: string } }
- - { in: query, name: state, required: true, schema: { type: string } }
+ - { 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: Authorization redirect }
+ '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: { type: object, additionalProperties: true }
+ 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
@@ -50,24 +101,44 @@ paths:
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: { type: object, required: [token], properties: { token: { type: string } } }
+ 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: [{ bearerAuth: [] }]
+ security: [{ oauth2: [profile] }, { bearerAuth: [] }]
responses:
- '200': { description: 'Effective tenant, institution, branch, roles and permissions' }
+ '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:
@@ -78,20 +149,132 @@ components:
authorizationCode:
authorizationUrl: /auth
tokenUrl: /token
- scopes: { openid: Authenticate operator, profile: Read effective identity }
+ 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 }
+ 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 }
+ 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 error response }
- Unauthorized: { description: Bearer token is missing or invalid }
+ 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
index 9c8cd69..91d0e56 100644
--- a/openapi/ledger-core.public.v1.yaml
+++ b/openapi/ledger-core.public.v1.yaml
@@ -2,254 +2,947 @@ openapi: 3.1.0
info:
title: MAVULA Ledger Core API
version: 1.0.0
- description: Tenant-scoped accounts, financial controls, configuration and projection APIs.
- license: { name: GNU Affero General Public License v3.0 only, identifier: AGPL-3.0-only }
+ 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, tags: [Accounts], responses: { '200': { description: 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]
- parameters: [{ $ref: '#/components/parameters/IdempotencyKey' }]
- requestBody: { $ref: '#/components/requestBodies/JsonObject' }
- responses: { '201': { description: Account created }, '400': { $ref: '#/components/responses/BadRequest' }, '409': { $ref: '#/components/responses/Conflict' } }
+ 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 }, '404': { $ref: '#/components/responses/NotFound' } }
+ 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 } }
+ 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 } }
- responses: { '200': { description: Paginated statement } }
+ - { 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]
- parameters: [{ $ref: '#/components/parameters/AccountId' }, { $ref: '#/components/parameters/IdempotencyKey' }]
- requestBody: { $ref: '#/components/requestBodies/JsonObject' }
- responses: { '201': { description: Lifecycle request submitted }, '409': { $ref: '#/components/responses/Conflict' } }
+ 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, tags: [Account lifecycle], responses: { '200': { description: 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 }, '404': { $ref: '#/components/responses/NotFound' } }
+ 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]
- parameters: [{ $ref: '#/components/parameters/RequestId' }, { $ref: '#/components/parameters/IdempotencyKey' }]
- requestBody: { $ref: '#/components/requestBodies/JsonObject' }
- responses: { '201': { description: Lifecycle request approved }, '403': { $ref: '#/components/responses/Forbidden' }, '409': { $ref: '#/components/responses/Conflict' } }
+ 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]
- parameters: [{ $ref: '#/components/parameters/RequestId' }, { $ref: '#/components/parameters/IdempotencyKey' }]
- requestBody: { $ref: '#/components/requestBodies/JsonObject' }
- responses: { '201': { description: Lifecycle request rejected }, '403': { $ref: '#/components/responses/Forbidden' }, '409': { $ref: '#/components/responses/Conflict' } }
+ 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, tags: [Financial adjustments], responses: { '200': { description: 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]
- parameters: [{ $ref: '#/components/parameters/IdempotencyKey' }]
- requestBody: { $ref: '#/components/requestBodies/JsonObject' }
- responses: { '201': { description: Adjustment request submitted }, '409': { $ref: '#/components/responses/Conflict' } }
+ 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 }, '404': { $ref: '#/components/responses/NotFound' } }
+ 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]
- parameters: [{ $ref: '#/components/parameters/RequestId' }, { $ref: '#/components/parameters/IdempotencyKey' }]
- requestBody: { $ref: '#/components/requestBodies/JsonObject' }
- responses: { '201': { description: Adjustment applied }, '403': { $ref: '#/components/responses/Forbidden' }, '409': { $ref: '#/components/responses/Conflict' } }
+ 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]
- parameters: [{ $ref: '#/components/parameters/RequestId' }, { $ref: '#/components/parameters/IdempotencyKey' }]
- requestBody: { $ref: '#/components/requestBodies/JsonObject' }
- responses: { '201': { description: Adjustment rejected }, '403': { $ref: '#/components/responses/Forbidden' }, '409': { $ref: '#/components/responses/Conflict' } }
+ 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, tags: [Configuration], responses: { '200': { description: 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]
- parameters: [{ $ref: '#/components/parameters/IdempotencyKey' }]
- requestBody: { $ref: '#/components/requestBodies/JsonObject' }
- responses: { '201': { description: Product configuration stored }, '409': { $ref: '#/components/responses/Conflict' } }
+ 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, tags: [Configuration], responses: { '200': { description: Tenant product configuration } } }
+ 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]
- parameters: [{ $ref: '#/components/parameters/IdempotencyKey' }]
- requestBody: { $ref: '#/components/requestBodies/JsonObject' }
- responses: { '201': { description: Configuration generated }, '409': { $ref: '#/components/responses/Conflict' } }
+ 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 }, '404': { $ref: '#/components/responses/NotFound' } }
+ 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 } }
+ 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]
- parameters: [{ $ref: '#/components/parameters/ProductId' }, { $ref: '#/components/parameters/IdempotencyKey' }]
- requestBody: { $ref: '#/components/requestBodies/JsonObject' }
- responses: { '201': { description: Rule created }, '409': { $ref: '#/components/responses/Conflict' } }
+ 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]
- parameters: [{ $ref: '#/components/parameters/ProductId' }, { $ref: '#/components/parameters/IdempotencyKey' }]
- responses: { '201': { description: Default rules created }, '409': { $ref: '#/components/responses/Conflict' } }
+ 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]
- parameters: [{ $ref: '#/components/parameters/ProductId' }, { in: path, name: ruleId, required: true, schema: { type: string } }, { $ref: '#/components/parameters/IdempotencyKey' }]
- requestBody: { $ref: '#/components/requestBodies/JsonObject' }
- responses: { '200': { description: Rule updated }, '409': { $ref: '#/components/responses/Conflict' } }
+ 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]
- parameters: [{ $ref: '#/components/parameters/ProductId' }, { in: path, name: ruleId, required: true, schema: { type: string } }, { $ref: '#/components/parameters/IdempotencyKey' }]
- responses: { '200': { description: Rule deleted }, '409': { $ref: '#/components/responses/Conflict' } }
+ 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, tags: [Schemas], responses: { '200': { description: 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]
- parameters: [{ $ref: '#/components/parameters/IdempotencyKey' }]
- requestBody: { $ref: '#/components/requestBodies/JsonObject' }
- responses: { '201': { description: Schema created }, '409': { $ref: '#/components/responses/Conflict' } }
+ 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]
- parameters: [{ $ref: '#/components/parameters/IdempotencyKey' }]
- requestBody: { $ref: '#/components/requestBodies/JsonObject' }
- responses: { '201': { description: Schema imported }, '409': { $ref: '#/components/responses/Conflict' } }
+ 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]
- parameters: [{ $ref: '#/components/parameters/IdempotencyKey' }]
- responses: { '201': { description: Preset schema created }, '409': { $ref: '#/components/responses/Conflict' } }
+ 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]
- parameters: [{ in: path, name: schemaId, required: true, schema: { type: string } }]
- responses: { '200': { description: Schema }, '404': { $ref: '#/components/responses/NotFound' } }
+ 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]
- parameters: [{ in: path, name: schemaId, required: true, schema: { type: string } }]
- responses: { '200': { description: Portable schema definition } }
+ 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, tags: [Workflows], responses: { '200': { description: 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]
- parameters: [{ $ref: '#/components/parameters/IdempotencyKey' }]
- requestBody: { $ref: '#/components/requestBodies/JsonObject' }
- responses: { '201': { description: Workflow created }, '409': { $ref: '#/components/responses/Conflict' } }
+ 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 } }
+ 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]
- parameters: [{ $ref: '#/components/parameters/IdempotencyKey' }]
- responses: { '201': { description: Preset workflow created }, '409': { $ref: '#/components/responses/Conflict' } }
+ 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]
- parameters: [{ $ref: '#/components/parameters/IdempotencyKey' }]
- responses: { '201': { description: Preset workflow created }, '409': { $ref: '#/components/responses/Conflict' } }
+ 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]
- parameters: [{ in: path, name: workflowId, required: true, schema: { type: string } }]
- responses: { '200': { description: Workflow }, '404': { $ref: '#/components/responses/NotFound' } }
+ 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]
- parameters: [{ in: path, name: workflowId, required: true, schema: { type: string } }, { $ref: '#/components/parameters/IdempotencyKey' }]
- requestBody: { $ref: '#/components/requestBodies/JsonObject' }
- responses: { '201': { description: Workflow execution completed }, '409': { $ref: '#/components/responses/Conflict' } }
+ 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, tags: [Projections], responses: { '200': { description: Projection checkpoints } } }
+ 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, tags: [Projections], responses: { '200': { description: Loan activity projections } } }
+ 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, tags: [Projections], parameters: [{ in: path, name: loanId, required: true, schema: { type: string } }], responses: { '200': { description: Loan activity projection } } }
+ 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, tags: [Projections], responses: { '200': { description: Ledger activity projections } } }
+ 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, tags: [Projections], parameters: [{ in: path, name: journalEntryId, required: true, schema: { type: string } }], responses: { '200': { description: Ledger activity projection } } }
+ 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, tags: [Projections], responses: { '200': { description: Product publication projections } } }
+ 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, tags: [Projections], parameters: [{ $ref: '#/components/parameters/ProductId' }], responses: { '200': { description: Product publication projection } } }
+ 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, schema: { type: string, minLength: 16, maxLength: 128, pattern: '^[A-Za-z0-9._:-]+$' } }
+ 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:
- JsonObject:
+ 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: { type: object, additionalProperties: 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 }
- Unauthorized: { description: Bearer token is missing or invalid }
- Forbidden: { description: 'Permission, maker-checker or tenant policy denied the operation' }
- NotFound: { description: Tenant-scoped resource was not found }
- Conflict: { description: State conflict or Idempotency-Key reuse conflict }
+ 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
index 64c340d..7cd1255 100644
--- a/openapi/workbench.public.v1.yaml
+++ b/openapi/workbench.public.v1.yaml
@@ -2,64 +2,433 @@ openapi: 3.1.0
info:
title: MAVULA Workbench API
version: 1.0.0
- description: Authenticated job submission and operational status surface.
- license: { name: GNU Affero General Public License v3.0 only, identifier: AGPL-3.0-only }
+ 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 }
+ '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 }
- '404': { description: Job not found }
+ '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]
- responses: { '200': { description: Worker runtime 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]
- responses: { '200': { description: Tenant-safe queue 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]
- responses: { '200': { description: Registered schedules } }
+ 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 }
+ 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 }
- idempotency_key: { type: string }
+ 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:
- BadRequest: { description: Request contract is invalid }
- Unauthorized: { description: Bearer token is missing or invalid }
- Forbidden: { description: Required permission or tenant boundary is not satisfied }
+ 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 518ea7e..c17b038 100644
--- a/package.json
+++ b/package.json
@@ -8,10 +8,19 @@
"packageManager": "pnpm@10.33.0",
"engines": { "node": "22.22.3", "pnpm": "10.33.0" },
"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": "node --test test/*.test.mjs",
+ "test:e2e": "playwright test"
},
- "devDependencies": { "@redocly/cli": "2.39.0" }
+ "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"
+ }
}
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
index 31c1717..8b7d0a5 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -8,17 +8,5888 @@ 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)
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
-snapshots:
+ '@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
- '@redocly/cli@2.39.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/redocly.yaml b/redocly.yaml
index 6901eb0..195319f 100644
--- a/redocly.yaml
+++ b/redocly.yaml
@@ -3,5 +3,5 @@ extends:
rules:
no-server-example.com: off
operation-description: off
- operation-summary: off
+ operation-summary: error
security-defined: error
diff --git a/scripts/build-docs.mjs b/scripts/build-docs.mjs
index 5ad0889..74ec6e8 100644
--- a/scripts/build-docs.mjs
+++ b/scripts/build-docs.mjs
@@ -1,32 +1,21 @@
-import { mkdirSync, rmSync, writeFileSync } from 'node:fs';
+import { writeFileSync } from 'node:fs';
import { spawnSync } from 'node:child_process';
const contracts = [
- ['identity-access.public.v1.yaml', 'identity-access.html'],
- ['ledger-core.public.v1.yaml', 'ledger-core.html'],
- ['workbench.public.v1.yaml', 'workbench.html'],
+ 'identity-access.public.v1.yaml',
+ 'ledger-core.public.v1.yaml',
+ 'workbench.public.v1.yaml',
];
-rmSync('dist', { recursive: true, force: true });
-mkdirSync('dist', { recursive: true });
-for (const [source, output] of contracts) {
- run(['lint', `openapi/${source}`]);
- run(['build-docs', `openapi/${source}`, '--output', `dist/${output}`]);
-}
-writeFileSync('dist/index.html', `
-
-MAVULA API ReferenceMAVULA API Reference
Versioned institutional finance interfaces.
`);
+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(args) {
- const executable = process.platform === 'win32' ? 'redocly.cmd' : 'redocly';
- const result = spawnSync(executable, args, { stdio: 'inherit', shell: process.platform === 'win32' });
- if (result.status !== 0) throw new Error(`redocly ${args.join(' ')} failed`);
+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
index 0609bf3..71e5829 100644
--- a/scripts/check-contracts.mjs
+++ b/scripts/check-contracts.mjs
@@ -16,5 +16,26 @@ for (const contract of lock.contracts) {
throw new Error(`${contract.file} exposes non-public route ${route}`);
}
}
+ const operationIds = [...source.matchAll(/\boperationId:\s*([A-Za-z][A-Za-z0-9]*)/g)].map((match) => match[1]);
+ const summaries = [...source.matchAll(/\bsummary:\s*[^\n,}]+/g)];
+ if (operationIds.length === 0 || summaries.length < operationIds.length) {
+ throw new Error(`${contract.file} must describe every public operation`);
+ }
+ if (contract.file !== 'identity-access.public.v1.yaml') {
+ const permissionDeclarations = [...source.matchAll(/x-mavula-permissions:/g)].length;
+ if (permissionDeclarations < operationIds.length) {
+ throw new Error(`${contract.file} must declare permissions for every public operation`);
+ }
+ }
}
-console.log('developer-docs owner contract digests and public boundaries are valid');
+
+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 bbe8152..17ee9be 100644
--- a/scripts/guardian.mjs
+++ b/scripts/guardian.mjs
@@ -9,6 +9,11 @@ const required = [
'.github/PULL_REQUEST_TEMPLATE.md', '.github/workflows/guardian.yml',
'.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
index 7b6a197..6b860c4 100644
--- a/sources.lock.json
+++ b/sources.lock.json
@@ -5,19 +5,19 @@
"file": "identity-access.public.v1.yaml",
"owner": "mavulahq/identity-access",
"source": "contracts/openapi/identity-access.public.v1.yaml",
- "sha256": "b7baa4c0846429ceb3834e15522861408bf432b0f6f23289ae03253491155ae3"
+ "sha256": "a126f53455b05bd8377fa12b81f814ae5d677acbbb0e8df33a706a5a0cf60a38"
},
{
"file": "ledger-core.public.v1.yaml",
"owner": "mavulahq/ledger-core",
"source": "contracts/openapi/ledger-core.public.v1.yaml",
- "sha256": "bd38bb863b2d3bf346f24670ff9cce70e737811f51f8e12f50d7fcade025bf50"
+ "sha256": "115cda1bff1aaea6a7aaad81577a0918e4ced2ec222cefc4081433a08778f2a1"
},
{
"file": "workbench.public.v1.yaml",
"owner": "mavulahq/workbench",
"source": "contracts/openapi/workbench.public.v1.yaml",
- "sha256": "618bf289f0d293e615ea73321dd1ca7c24593967f1c52b9614ad1aa26f2edadf"
+ "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..465586b
--- /dev/null
+++ b/src/content/docs/v1/getting-started/authentication.mdx
@@ -0,0 +1,83 @@
+---
+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.io/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.io/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.io/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=finance.read finance.write'
+ ```
+
+
+ ```ts
+ const body = new URLSearchParams({
+ grant_type: 'client_credentials',
+ client_id: process.env.MAVULA_CLIENT_ID!,
+ client_secret: process.env.MAVULA_CLIENT_SECRET!,
+ scope: 'finance.read finance.write',
+ });
+ const response = await fetch('https://identity.mavula.io/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();
+ ```
+
+
+
+## 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..97c34ec
--- /dev/null
+++ b/src/content/docs/v1/getting-started/quickstart.mdx
@@ -0,0 +1,61 @@
+---
+title: Quickstart
+description: Obtain a service token, create an account and read its balance.
+---
+
+import { Aside, Steps } from '@astrojs/starlight/components';
+
+This flow uses the OAuth 2.0 client credentials grant for a trusted institutional backend.
+
+
+
+1. **Request a token**
+
+ ```bash
+ curl -sS -X POST https://identity.mavula.io/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=openid finance.read finance.write'
+ ```
+
+2. **Inspect the effective identity**
+
+ ```bash
+ curl -sS https://identity.mavula.io/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.io/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.io/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..fb14165
--- /dev/null
+++ b/src/content/docs/v1/getting-started/roles-permissions.mdx
@@ -0,0 +1,31 @@
+---
+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.read`, `compliance.write` |
+| `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.io/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..01f6289
--- /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.io/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.io/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..615e068
--- /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.io/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.io/api/accounts/ACCOUNT_ID/balance \
+ -H "Authorization: Bearer $MAVULA_ACCESS_TOKEN"
+ ```
+
+3. **Page through the statement**
+
+ ```bash
+ curl -sS 'https://ledger.mavula.io/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..a817325
--- /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.io/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..c563ddf
--- /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.io/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.io/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..9e03cbb
--- /dev/null
+++ b/src/content/docs/v1/guides/legacy-batches.mdx
@@ -0,0 +1,56 @@
+---
+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.io/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 '{"report_type":"TRANSACTION_ACTIVITY","period_start":"2026-06-01","period_end":"2026-06-30","format":"CSV"}'
+ ```
+
+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.io/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":"BANCO_DE_MOCAMBIQUE","delivered_at":"2026-07-10T09:30:00Z","reference":"BM-2026-000184"}'
+ ```
+
+
+
+## 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..9592c9e
--- /dev/null
+++ b/src/content/docs/v1/guides/payment-jobs.mdx
@@ -0,0 +1,38 @@
+---
+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.io/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 '{"type":"PAYMENT_PROCESS","payload":{"tenant_id":"tenant_001","idempotency_key":"payment_001","correlation_id":"fd662f62-19c7-4f92-941f-64667437e6f9","rail":"BANK_TRANSFER","amount":"2500.00","payer":{"account_id":"account_001"},"payee":{"bank_account":"000123456789"}}}'
+```
+
+Persist the returned job identifier and poll the status resource:
+
+```bash
+curl -sS https://workbench.mavula.io/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..2cb871d
--- /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.io` | OAuth 2.0 and OpenID Connect |
+| Ledger Core | `https://ledger.mavula.io` | Synchronous commands and reads |
+| Workbench | `https://workbench.mavula.io` | 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/[legacy].html.astro b/src/pages/[legacy].html.astro
new file mode 100644
index 0000000..c45fa4d
--- /dev/null
+++ b/src/pages/[legacy].html.astro
@@ -0,0 +1,11 @@
+---
+export function getStaticPaths() {
+ return [
+ { params: { legacy: 'identity-access' }, props: { destination: '/developer-docs/v1/api/identity-access/' } },
+ { params: { legacy: 'ledger-core' }, props: { destination: '/developer-docs/v1/api/ledger-core/' } },
+ { params: { legacy: 'workbench' }, props: { destination: '/developer-docs/v1/api/workbench/' } },
+ ];
+}
+
+return Astro.redirect(Astro.props.destination, 301);
+---
diff --git a/src/pages/guides/legacy-batches.html.astro b/src/pages/guides/legacy-batches.html.astro
new file mode 100644
index 0000000..9c857a1
--- /dev/null
+++ b/src/pages/guides/legacy-batches.html.astro
@@ -0,0 +1,3 @@
+---
+return Astro.redirect('/developer-docs/v1/guides/legacy-batches/', 301);
+---
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
index 493e287..0fa3bb9 100644
--- a/test/contracts.test.mjs
+++ b/test/contracts.test.mjs
@@ -9,5 +9,30 @@ test('all published operations use unique operationId values', () => {
operationIds.push(...[...source.matchAll(/^\s+operationId: (\S+)$/gm)].map((match) => match[1]));
}
assert.equal(new Set(operationIds).size, operationIds.length);
- assert.ok(operationIds.length > 20);
+ 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 ['client_credentials', 'operations_maker', 'REVERSAL', 'PAYMENT_PROCESS', 'idempotency key']) {
+ 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"
+}
From f63121fd57388b2b6b3b2716fcf6be9b28ccb970 Mon Sep 17 00:00:00 2001
From: Estandar <143508382+EstandarMustaq@users.noreply.github.com>
Date: Thu, 16 Jul 2026 22:46:56 +0200
Subject: [PATCH 4/5] ci: harden Pages deployment permissions
---
.github/workflows/pages.yml | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml
index 5a21b6f..b3caff5 100644
--- a/.github/workflows/pages.yml
+++ b/.github/workflows/pages.yml
@@ -4,13 +4,12 @@ on:
workflow_dispatch: {}
permissions:
contents: read
- pages: write
- id-token: write
concurrency:
group: pages
cancel-in-progress: true
jobs:
build:
+ if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
@@ -23,6 +22,10 @@ jobs:
- uses: actions/upload-pages-artifact@v4
with: { path: dist }
deploy:
+ if: github.ref == 'refs/heads/main'
+ permissions:
+ pages: write
+ id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
From 8da132cf9b375ab5d5cd9b3b2269a9be888c5f24 Mon Sep 17 00:00:00 2001
From: Estandar <143508382+EstandarMustaq@users.noreply.github.com>
Date: Thu, 16 Jul 2026 23:04:06 +0200
Subject: [PATCH 5/5] fix: align portal guides with public contracts
---
.github/workflows/pages.yml | 3 ++
.../MAVULA-API-v1.postman_collection.json | 6 +--
package.json | 3 +-
pnpm-lock.yaml | 3 ++
public/guides/legacy-batches.html | 2 +
public/identity-access.html | 2 +
public/ledger-core.html | 2 +
public/workbench.html | 2 +
scripts/check-contracts.mjs | 47 ++++++++++++++-----
.../v1/getting-started/authentication.mdx | 15 +++---
.../docs/v1/getting-started/quickstart.mdx | 27 ++++++-----
.../v1/getting-started/roles-permissions.mdx | 5 +-
.../docs/v1/guides/account-lifecycle.mdx | 4 +-
src/content/docs/v1/guides/account-setup.mdx | 6 +--
src/content/docs/v1/guides/configuration.mdx | 2 +-
.../docs/v1/guides/financial-adjustments.mdx | 4 +-
src/content/docs/v1/guides/legacy-batches.mdx | 9 ++--
src/content/docs/v1/guides/payment-jobs.mdx | 7 ++-
src/content/docs/v1/index.mdx | 6 +--
src/pages/[legacy].html.astro | 11 -----
src/pages/guides/legacy-batches.html.astro | 3 --
test/contracts.test.mjs | 17 ++++++-
22 files changed, 111 insertions(+), 75 deletions(-)
create mode 100644 public/guides/legacy-batches.html
create mode 100644 public/identity-access.html
create mode 100644 public/ledger-core.html
create mode 100644 public/workbench.html
delete mode 100644 src/pages/[legacy].html.astro
delete mode 100644 src/pages/guides/legacy-batches.html.astro
diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml
index b3caff5..d9a0339 100644
--- a/.github/workflows/pages.yml
+++ b/.github/workflows/pages.yml
@@ -18,6 +18,9 @@ jobs:
- 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: dist }
diff --git a/examples/postman/MAVULA-API-v1.postman_collection.json b/examples/postman/MAVULA-API-v1.postman_collection.json
index c12fb94..fbb37de 100644
--- a/examples/postman/MAVULA-API-v1.postman_collection.json
+++ b/examples/postman/MAVULA-API-v1.postman_collection.json
@@ -5,9 +5,9 @@
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
"variable": [
- { "key": "identity_base_url", "value": "https://identity.mavula.io" },
- { "key": "ledger_base_url", "value": "https://ledger.mavula.io" },
- { "key": "workbench_base_url", "value": "https://workbench.mavula.io" },
+ { "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": "" }
diff --git a/package.json b/package.json
index c17b038..2907cfa 100644
--- a/package.json
+++ b/package.json
@@ -21,6 +21,7 @@
"@playwright/test": "1.59.1",
"@redocly/cli": "2.39.0",
"@scalar/api-reference": "1.62.6",
- "astro": "7.0.9"
+ "astro": "7.0.9",
+ "yaml": "2.9.0"
}
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 8b7d0a5..fae5c27 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -23,6 +23,9 @@ importers:
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:
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/scripts/check-contracts.mjs b/scripts/check-contracts.mjs
index 71e5829..e091956 100644
--- a/scripts/check-contracts.mjs
+++ b/scripts/check-contracts.mjs
@@ -1,30 +1,51 @@
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 (!source.startsWith('openapi: 3.1.0')) throw new Error(`${contract.file} must use OpenAPI 3.1.0`);
- const paths = [...source.matchAll(/^ (\/[^:]+):$/gm)].map((match) => match[1]);
- for (const route of paths) {
+ 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}`);
}
- }
- const operationIds = [...source.matchAll(/\boperationId:\s*([A-Za-z][A-Za-z0-9]*)/g)].map((match) => match[1]);
- const summaries = [...source.matchAll(/\bsummary:\s*[^\n,}]+/g)];
- if (operationIds.length === 0 || summaries.length < operationIds.length) {
- throw new Error(`${contract.file} must describe every public operation`);
- }
- if (contract.file !== 'identity-access.public.v1.yaml') {
- const permissionDeclarations = [...source.matchAll(/x-mavula-permissions:/g)].length;
- if (permissionDeclarations < operationIds.length) {
- throw new Error(`${contract.file} must declare permissions for every public operation`);
+ 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`);
+ }
+ }
}
}
}
diff --git a/src/content/docs/v1/getting-started/authentication.mdx b/src/content/docs/v1/getting-started/authentication.mdx
index 465586b..f1e4939 100644
--- a/src/content/docs/v1/getting-started/authentication.mdx
+++ b/src/content/docs/v1/getting-started/authentication.mdx
@@ -20,7 +20,7 @@ Identity Access publishes OpenID Provider metadata at `/.well-known/openid-confi
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.io/auth
+GET https://identity.mavula.dev/auth
?response_type=code
&client_id=operator-console
&redirect_uri=https%3A%2F%2Fops.example.com%2Fcallback
@@ -34,7 +34,7 @@ GET https://identity.mavula.io/auth
Exchange the returned code once:
```bash
-curl -sS -X POST https://identity.mavula.io/token \
+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' \
@@ -48,12 +48,12 @@ curl -sS -X POST https://identity.mavula.io/token \
```bash
- curl -sS -X POST https://identity.mavula.io/token \
+ 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=finance.read finance.write'
+ --data-urlencode 'scope=internal.worker'
```
@@ -62,9 +62,9 @@ curl -sS -X POST https://identity.mavula.io/token \
grant_type: 'client_credentials',
client_id: process.env.MAVULA_CLIENT_ID!,
client_secret: process.env.MAVULA_CLIENT_SECRET!,
- scope: 'finance.read finance.write',
+ scope: 'internal.worker',
});
- const response = await fetch('https://identity.mavula.io/token', {
+ 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}`);
@@ -73,6 +73,8 @@ curl -sS -X POST https://identity.mavula.io/token \
+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`.
@@ -80,4 +82,3 @@ Refresh tokens are rotated. Persist the replacement atomically and discard the p
-
diff --git a/src/content/docs/v1/getting-started/quickstart.mdx b/src/content/docs/v1/getting-started/quickstart.mdx
index 97c34ec..af439c1 100644
--- a/src/content/docs/v1/getting-started/quickstart.mdx
+++ b/src/content/docs/v1/getting-started/quickstart.mdx
@@ -1,29 +1,30 @@
---
title: Quickstart
-description: Obtain a service token, create an account and read its balance.
+description: Exchange an operator authorization code, create an account and read its balance.
---
import { Aside, Steps } from '@astrojs/starlight/components';
-This flow uses the OAuth 2.0 client credentials grant for a trusted institutional backend.
+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. **Request a token**
+1. **Exchange the authorization code**
```bash
- curl -sS -X POST https://identity.mavula.io/token \
+ 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=openid finance.read finance.write'
+ --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.io/api/v1/me \
+ curl -sS https://identity.mavula.dev/api/v1/me \
-H "Authorization: Bearer $MAVULA_ACCESS_TOKEN"
```
@@ -32,7 +33,7 @@ This flow uses the OAuth 2.0 client credentials grant for a trusted institutiona
3. **Create an account**
```bash
- curl -sS -X POST https://ledger.mavula.io/api/accounts \
+ 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' \
@@ -43,15 +44,15 @@ This flow uses the OAuth 2.0 client credentials grant for a trusted institutiona
4. **Read the balance**
```bash
- curl -sS https://ledger.mavula.io/api/accounts/ACCOUNT_ID/balance \
+ 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'
```
-