@alneas/eaos-server 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +41 -0
- package/LICENSE +21 -0
- package/README.ja.md +49 -0
- package/README.md +46 -2
- package/dist/agentic/agent-jobs.d.ts +333 -0
- package/dist/agentic/agent-jobs.js +15 -0
- package/dist/agentic/agent-jobs.js.map +1 -0
- package/dist/agentic/agent-node.d.ts +40 -0
- package/dist/agentic/agent-node.js +7 -0
- package/dist/agentic/agent-node.js.map +1 -0
- package/dist/agentic/agent-runner.d.ts +33 -0
- package/dist/agentic/agent-runner.js +7 -0
- package/dist/agentic/agent-runner.js.map +1 -0
- package/dist/agentic/ai-broker.d.ts +169 -0
- package/dist/agentic/ai-broker.js +8 -0
- package/dist/agentic/ai-broker.js.map +1 -0
- package/dist/agentic/atomic-checkpointer.d.ts +137 -0
- package/dist/agentic/atomic-checkpointer.js +9 -0
- package/dist/agentic/atomic-checkpointer.js.map +1 -0
- package/dist/agentic/autonomous-worker.d.ts +122 -0
- package/dist/agentic/autonomous-worker.js +10 -0
- package/dist/agentic/autonomous-worker.js.map +1 -0
- package/dist/agentic/event-bridge.d.ts +350 -0
- package/dist/agentic/event-bridge.js +9 -0
- package/dist/agentic/event-bridge.js.map +1 -0
- package/dist/agentic/executor.d.ts +91 -0
- package/dist/agentic/executor.js +12 -0
- package/dist/agentic/executor.js.map +1 -0
- package/dist/agentic/graph-projection.d.ts +119 -0
- package/dist/agentic/graph-projection.js +7 -0
- package/dist/agentic/graph-projection.js.map +1 -0
- package/dist/agentic/graph.d.ts +524 -0
- package/dist/agentic/graph.js +7 -0
- package/dist/agentic/graph.js.map +1 -0
- package/dist/agentic/index.d.ts +28 -0
- package/dist/agentic/index.js +87 -0
- package/dist/agentic/index.js.map +1 -0
- package/dist/agentic/local-runner.d.ts +106 -0
- package/dist/agentic/local-runner.js +7 -0
- package/dist/agentic/local-runner.js.map +1 -0
- package/dist/agentic/remote-executor.d.ts +67 -0
- package/dist/agentic/remote-executor.js +8 -0
- package/dist/agentic/remote-executor.js.map +1 -0
- package/dist/agentic/types.d.ts +157 -0
- package/dist/agentic/types.js +7 -0
- package/dist/agentic/types.js.map +1 -0
- package/dist/agentic/workflow-catalog.d.ts +152 -0
- package/dist/agentic/workflow-catalog.js +7 -0
- package/dist/agentic/workflow-catalog.js.map +1 -0
- package/dist/agentic/workflow-compiler.d.ts +44 -0
- package/dist/agentic/workflow-compiler.js +8 -0
- package/dist/agentic/workflow-compiler.js.map +1 -0
- package/dist/agentic/workflow-coordinator.d.ts +170 -0
- package/dist/agentic/workflow-coordinator.js +8 -0
- package/dist/agentic/workflow-coordinator.js.map +1 -0
- package/dist/agentic/workflow-manager.d.ts +91 -0
- package/dist/agentic/workflow-manager.js +7 -0
- package/dist/agentic/workflow-manager.js.map +1 -0
- package/dist/agentic/workflow-registry.d.ts +334 -0
- package/dist/agentic/workflow-registry.js +7 -0
- package/dist/agentic/workflow-registry.js.map +1 -0
- package/dist/artifacts-CteHmCMI.d.ts +614 -0
- package/dist/auth-hooks/api-key.d.ts +75 -0
- package/dist/auth-hooks/api-key.js +7 -0
- package/dist/auth-hooks/api-key.js.map +1 -0
- package/dist/auth-hooks/index.d.ts +80 -0
- package/dist/auth-hooks/index.js +28 -0
- package/dist/auth-hooks/index.js.map +1 -0
- package/dist/browser-auth/account-memberships.d.ts +213 -0
- package/dist/browser-auth/account-memberships.js +13 -0
- package/dist/browser-auth/account-memberships.js.map +1 -0
- package/dist/browser-auth/index.d.ts +8 -0
- package/dist/browser-auth/index.js +59 -0
- package/dist/browser-auth/index.js.map +1 -0
- package/dist/browser-auth/kratos-session.d.ts +37 -0
- package/dist/browser-auth/kratos-session.js +7 -0
- package/dist/browser-auth/kratos-session.js.map +1 -0
- package/dist/browser-auth/platform-session.d.ts +120 -0
- package/dist/browser-auth/platform-session.js +7 -0
- package/dist/browser-auth/platform-session.js.map +1 -0
- package/dist/browser-auth/public-memberships.d.ts +22 -0
- package/dist/browser-auth/public-memberships.js +7 -0
- package/dist/browser-auth/public-memberships.js.map +1 -0
- package/dist/cache/index.d.ts +181 -0
- package/dist/cache/index.js +197 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/chunk-32746UQZ.js +131 -0
- package/dist/chunk-32746UQZ.js.map +1 -0
- package/dist/chunk-3NLSWP2Y.js +223 -0
- package/dist/chunk-3NLSWP2Y.js.map +1 -0
- package/dist/chunk-3P4XTTQH.js +346 -0
- package/dist/chunk-3P4XTTQH.js.map +1 -0
- package/dist/chunk-3VITSHN3.js +15 -0
- package/dist/chunk-3VITSHN3.js.map +1 -0
- package/dist/chunk-46UWPEW2.js +226 -0
- package/dist/chunk-46UWPEW2.js.map +1 -0
- package/dist/chunk-4BARRLJR.js +180 -0
- package/dist/chunk-4BARRLJR.js.map +1 -0
- package/dist/chunk-4VORUFKR.js +45 -0
- package/dist/chunk-4VORUFKR.js.map +1 -0
- package/dist/chunk-55D4ERWO.js +1 -0
- package/dist/chunk-55D4ERWO.js.map +1 -0
- package/dist/chunk-5TBBZIND.js +18 -0
- package/dist/chunk-5TBBZIND.js.map +1 -0
- package/dist/chunk-5WOZWPZA.js +211 -0
- package/dist/chunk-5WOZWPZA.js.map +1 -0
- package/dist/chunk-6CBVZ6CT.js +168 -0
- package/dist/chunk-6CBVZ6CT.js.map +1 -0
- package/dist/chunk-6XZXYNJR.js +74 -0
- package/dist/chunk-6XZXYNJR.js.map +1 -0
- package/dist/chunk-753HWDSC.js +222 -0
- package/dist/chunk-753HWDSC.js.map +1 -0
- package/dist/chunk-7AHSS7SO.js +81 -0
- package/dist/chunk-7AHSS7SO.js.map +1 -0
- package/dist/chunk-7FTJN4SA.js +1 -0
- package/dist/chunk-7FTJN4SA.js.map +1 -0
- package/dist/chunk-AVDMLTPF.js +24 -0
- package/dist/chunk-AVDMLTPF.js.map +1 -0
- package/dist/chunk-BKAHUEIT.js +95 -0
- package/dist/chunk-BKAHUEIT.js.map +1 -0
- package/dist/chunk-CJ7OFEF7.js +134 -0
- package/dist/chunk-CJ7OFEF7.js.map +1 -0
- package/dist/chunk-EJKWDZIU.js +111 -0
- package/dist/chunk-EJKWDZIU.js.map +1 -0
- package/dist/chunk-F2J6IQ6I.js +247 -0
- package/dist/chunk-F2J6IQ6I.js.map +1 -0
- package/dist/chunk-F3O7CELI.js +23 -0
- package/dist/chunk-F3O7CELI.js.map +1 -0
- package/dist/chunk-F4IITPGX.js +221 -0
- package/dist/chunk-F4IITPGX.js.map +1 -0
- package/dist/chunk-FD6VC2NA.js +66 -0
- package/dist/chunk-FD6VC2NA.js.map +1 -0
- package/dist/chunk-FRRRWAHO.js +14 -0
- package/dist/chunk-FRRRWAHO.js.map +1 -0
- package/dist/chunk-HCKAGLLB.js +17 -0
- package/dist/chunk-HCKAGLLB.js.map +1 -0
- package/dist/chunk-HVC7FG6B.js +191 -0
- package/dist/chunk-HVC7FG6B.js.map +1 -0
- package/dist/chunk-HXFVOR7Z.js +496 -0
- package/dist/chunk-HXFVOR7Z.js.map +1 -0
- package/dist/chunk-IJWYS2PF.js +122 -0
- package/dist/chunk-IJWYS2PF.js.map +1 -0
- package/dist/chunk-INCHXAFK.js +1395 -0
- package/dist/chunk-INCHXAFK.js.map +1 -0
- package/dist/chunk-JT6BRGQM.js +1 -0
- package/dist/chunk-JT6BRGQM.js.map +1 -0
- package/dist/chunk-L6PMAEMB.js +115 -0
- package/dist/chunk-L6PMAEMB.js.map +1 -0
- package/dist/chunk-LOUGW6MU.js +126 -0
- package/dist/chunk-LOUGW6MU.js.map +1 -0
- package/dist/chunk-LYPZPE53.js +129 -0
- package/dist/chunk-LYPZPE53.js.map +1 -0
- package/dist/chunk-NNCCN7JP.js +186 -0
- package/dist/chunk-NNCCN7JP.js.map +1 -0
- package/dist/chunk-PBC3MZUL.js +212 -0
- package/dist/chunk-PBC3MZUL.js.map +1 -0
- package/dist/chunk-R4ADP2DC.js +20 -0
- package/dist/chunk-R4ADP2DC.js.map +1 -0
- package/dist/chunk-RHN4Y6VS.js +44 -0
- package/dist/chunk-RHN4Y6VS.js.map +1 -0
- package/dist/chunk-SDJNYPYK.js +770 -0
- package/dist/chunk-SDJNYPYK.js.map +1 -0
- package/dist/chunk-UGNTCOVR.js +28 -0
- package/dist/chunk-UGNTCOVR.js.map +1 -0
- package/dist/chunk-VC2PCK2S.js +31 -0
- package/dist/chunk-VC2PCK2S.js.map +1 -0
- package/dist/chunk-VF5YDZJC.js +305 -0
- package/dist/chunk-VF5YDZJC.js.map +1 -0
- package/dist/chunk-VISRDVTK.js +675 -0
- package/dist/chunk-VISRDVTK.js.map +1 -0
- package/dist/chunk-W6O3LVBY.js +102 -0
- package/dist/chunk-W6O3LVBY.js.map +1 -0
- package/dist/chunk-WFEAKJLR.js +47 -0
- package/dist/chunk-WFEAKJLR.js.map +1 -0
- package/dist/chunk-XIEY2OF4.js +67 -0
- package/dist/chunk-XIEY2OF4.js.map +1 -0
- package/dist/chunk-XITLHDG3.js +37 -0
- package/dist/chunk-XITLHDG3.js.map +1 -0
- package/dist/chunk-XMWPYZWZ.js +61 -0
- package/dist/chunk-XMWPYZWZ.js.map +1 -0
- package/dist/chunk-XUP6CNOM.js +34 -0
- package/dist/chunk-XUP6CNOM.js.map +1 -0
- package/dist/chunk-YABTQZDJ.js +25 -0
- package/dist/chunk-YABTQZDJ.js.map +1 -0
- package/dist/chunk-YMHVRBUU.js +199 -0
- package/dist/chunk-YMHVRBUU.js.map +1 -0
- package/dist/chunk-YMJ7BRKU.js +510 -0
- package/dist/chunk-YMJ7BRKU.js.map +1 -0
- package/dist/chunk-ZC3XWU7B.js +28 -0
- package/dist/chunk-ZC3XWU7B.js.map +1 -0
- package/dist/chunk-ZHMTD5KV.js +90 -0
- package/dist/chunk-ZHMTD5KV.js.map +1 -0
- package/dist/chunk-ZWZDLOE7.js +160 -0
- package/dist/chunk-ZWZDLOE7.js.map +1 -0
- package/dist/db-package/db/local-first-sqlite-adapter.d.ts +432 -0
- package/dist/db-package/db/local-first-sqlite-adapter.js +7 -0
- package/dist/db-package/db/local-first-sqlite-adapter.js.map +1 -0
- package/dist/db-package/index.d.ts +7 -0
- package/dist/db-package/index.js +16 -0
- package/dist/db-package/index.js.map +1 -0
- package/dist/db-package/migration/aggregator.d.ts +86 -0
- package/dist/db-package/migration/aggregator.js +7 -0
- package/dist/db-package/migration/aggregator.js.map +1 -0
- package/dist/db-package/migration/index.d.ts +3 -0
- package/dist/db-package/migration/index.js +8 -0
- package/dist/db-package/migration/index.js.map +1 -0
- package/dist/engine.d.ts +205 -0
- package/dist/engine.js +20 -0
- package/dist/engine.js.map +1 -0
- package/dist/entitlements/index.d.ts +313 -0
- package/dist/entitlements/index.js +23 -0
- package/dist/entitlements/index.js.map +1 -0
- package/dist/execution/chat.d.ts +7 -0
- package/dist/execution/chat.js +7 -0
- package/dist/execution/chat.js.map +1 -0
- package/dist/execution/index.d.ts +342 -0
- package/dist/execution/index.js +66 -0
- package/dist/execution/index.js.map +1 -0
- package/dist/execution/tool-agent.d.ts +7 -0
- package/dist/execution/tool-agent.js +8 -0
- package/dist/execution/tool-agent.js.map +1 -0
- package/dist/extensions/index.d.ts +172 -0
- package/dist/extensions/index.js +95 -0
- package/dist/extensions/index.js.map +1 -0
- package/dist/health/index.d.ts +35 -0
- package/dist/health/index.js +7 -0
- package/dist/health/index.js.map +1 -0
- package/dist/index.d.ts +43 -0
- package/dist/index.js +161 -0
- package/dist/index.js.map +1 -0
- package/dist/lifecycle/index.d.ts +133 -0
- package/dist/lifecycle/index.js +13 -0
- package/dist/lifecycle/index.js.map +1 -0
- package/dist/lifecycle-engine/backend-migration.d.ts +2 -0
- package/dist/lifecycle-engine/backend-migration.js +11 -0
- package/dist/lifecycle-engine/backend-migration.js.map +1 -0
- package/dist/lifecycle-engine/baseline.d.ts +2 -0
- package/dist/lifecycle-engine/baseline.js +9 -0
- package/dist/lifecycle-engine/baseline.js.map +1 -0
- package/dist/lifecycle-engine/index.d.ts +1497 -0
- package/dist/lifecycle-engine/index.js +41 -0
- package/dist/lifecycle-engine/index.js.map +1 -0
- package/dist/lifecycle-engine/platform/artifacts.d.ts +4 -0
- package/dist/lifecycle-engine/platform/artifacts.js +7 -0
- package/dist/lifecycle-engine/platform/artifacts.js.map +1 -0
- package/dist/lifecycle-engine/platform/control-plane.d.ts +12 -0
- package/dist/lifecycle-engine/platform/control-plane.js +2 -0
- package/dist/lifecycle-engine/platform/control-plane.js.map +1 -0
- package/dist/lifecycle-engine/platform/database-router.d.ts +118 -0
- package/dist/lifecycle-engine/platform/database-router.js +7 -0
- package/dist/lifecycle-engine/platform/database-router.js.map +1 -0
- package/dist/lifecycle-engine/platform/deployment-placements.d.ts +464 -0
- package/dist/lifecycle-engine/platform/deployment-placements.js +16 -0
- package/dist/lifecycle-engine/platform/deployment-placements.js.map +1 -0
- package/dist/lifecycle-engine/platform/deployment.d.ts +4 -0
- package/dist/lifecycle-engine/platform/deployment.js +17 -0
- package/dist/lifecycle-engine/platform/deployment.js.map +1 -0
- package/dist/lifecycle-engine/platform/index.d.ts +737 -0
- package/dist/lifecycle-engine/platform/index.js +60 -0
- package/dist/lifecycle-engine/platform/index.js.map +1 -0
- package/dist/lifecycle-engine/platform/runtime.d.ts +80 -0
- package/dist/lifecycle-engine/platform/runtime.js +11 -0
- package/dist/lifecycle-engine/platform/runtime.js.map +1 -0
- package/dist/lifecycle-engine/platform/site-publication.d.ts +102 -0
- package/dist/lifecycle-engine/platform/site-publication.js +7 -0
- package/dist/lifecycle-engine/platform/site-publication.js.map +1 -0
- package/dist/lifecycle-engine/platform/user-directory.d.ts +139 -0
- package/dist/lifecycle-engine/platform/user-directory.js +13 -0
- package/dist/lifecycle-engine/platform/user-directory.js.map +1 -0
- package/dist/mcp.d.ts +92 -0
- package/dist/mcp.js +10 -0
- package/dist/mcp.js.map +1 -0
- package/dist/middleware/auth.d.ts +118 -0
- package/dist/middleware/auth.js +7 -0
- package/dist/middleware/auth.js.map +1 -0
- package/dist/middleware/error-handler.d.ts +35 -0
- package/dist/middleware/error-handler.js +7 -0
- package/dist/middleware/error-handler.js.map +1 -0
- package/dist/middleware/module-guard.d.ts +33 -0
- package/dist/middleware/module-guard.js +7 -0
- package/dist/middleware/module-guard.js.map +1 -0
- package/dist/platform-admin/index.d.ts +37 -0
- package/dist/platform-admin/index.js +11 -0
- package/dist/platform-admin/index.js.map +1 -0
- package/dist/platform-admin/store.d.ts +346 -0
- package/dist/platform-admin/store.js +7 -0
- package/dist/platform-admin/store.js.map +1 -0
- package/dist/plugin-data/annotations.d.ts +6 -0
- package/dist/plugin-data/annotations.js +12 -0
- package/dist/plugin-data/annotations.js.map +1 -0
- package/dist/plugin-data/atomic-context.d.ts +41 -0
- package/dist/plugin-data/atomic-context.js +9 -0
- package/dist/plugin-data/atomic-context.js.map +1 -0
- package/dist/plugin-data/atomic.d.ts +6 -0
- package/dist/plugin-data/atomic.js +26 -0
- package/dist/plugin-data/atomic.js.map +1 -0
- package/dist/plugin-data/audit.d.ts +6 -0
- package/dist/plugin-data/audit.js +12 -0
- package/dist/plugin-data/audit.js.map +1 -0
- package/dist/plugin-data/commands.d.ts +6 -0
- package/dist/plugin-data/commands.js +8 -0
- package/dist/plugin-data/commands.js.map +1 -0
- package/dist/plugin-data/composite.d.ts +6 -0
- package/dist/plugin-data/composite.js +8 -0
- package/dist/plugin-data/composite.js.map +1 -0
- package/dist/plugin-data/delivery.d.ts +6 -0
- package/dist/plugin-data/delivery.js +16 -0
- package/dist/plugin-data/delivery.js.map +1 -0
- package/dist/plugin-data/index.d.ts +2798 -0
- package/dist/plugin-data/index.js +102 -0
- package/dist/plugin-data/index.js.map +1 -0
- package/dist/plugin-data/json-documents.d.ts +6 -0
- package/dist/plugin-data/json-documents.js +16 -0
- package/dist/plugin-data/json-documents.js.map +1 -0
- package/dist/plugin-data/outbox.d.ts +6 -0
- package/dist/plugin-data/outbox.js +16 -0
- package/dist/plugin-data/outbox.js.map +1 -0
- package/dist/plugin-data/scoped-records.d.ts +6 -0
- package/dist/plugin-data/scoped-records.js +10 -0
- package/dist/plugin-data/scoped-records.js.map +1 -0
- package/dist/plugin-sdk.d.ts +41 -0
- package/dist/plugin-sdk.js +10 -0
- package/dist/plugin-sdk.js.map +1 -0
- package/dist/sql-lifecycle/index.d.ts +138 -0
- package/dist/sql-lifecycle/index.js +167 -0
- package/dist/sql-lifecycle/index.js.map +1 -0
- package/dist/storage/index.d.ts +2 -0
- package/dist/storage/index.js +13 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/s3-compatible.d.ts +139 -0
- package/dist/storage/s3-compatible.js +11 -0
- package/dist/storage/s3-compatible.js.map +1 -0
- package/dist/tenant.d.ts +108 -0
- package/dist/tenant.js +9 -0
- package/dist/tenant.js.map +1 -0
- package/dist/workspace-context.d.ts +119 -0
- package/dist/workspace-context.js +9 -0
- package/dist/workspace-context.js.map +1 -0
- package/docs/api.md +30560 -0
- package/docs/db/README.md +49 -0
- package/docs/db/docs/api.md +1613 -0
- package/docs/db/docs/guide.md +47 -0
- package/docs/entitlements.md +60 -0
- package/docs/guide.md +92 -0
- package/docs/index.md +57 -0
- package/docs/ja/db/README.md +46 -0
- package/docs/ja/db/docs/guide.md +53 -0
- package/docs/ja/guide.md +46 -0
- package/docs/ja/lifecycle/README.md +46 -0
- package/docs/ja/lifecycle/docs/guide.md +45 -0
- package/docs/ja/storage/README.md +46 -0
- package/docs/ja/storage/docs/guide.md +43 -0
- package/docs/lifecycle/README.md +49 -0
- package/docs/lifecycle/docs/api.md +3770 -0
- package/docs/lifecycle/docs/baseline.md +50 -0
- package/docs/lifecycle/docs/guide.md +47 -0
- package/docs/storage/README.md +49 -0
- package/docs/storage/docs/api.md +470 -0
- package/docs/storage/docs/guide.md +47 -0
- package/package.json +354 -4
|
@@ -0,0 +1,2798 @@
|
|
|
1
|
+
import * as _alneas_eaos_core from '@alneas/eaos-core';
|
|
2
|
+
import { OutboxDispatcherOptions, OutboxDispatcher, OutboxStore, WorkflowEventSink, OutboxEventInput, OutboxEvent } from '@alneas/eaos-core';
|
|
3
|
+
import * as hono_types from 'hono/types';
|
|
4
|
+
import * as _alneas_eaos_core_plugin_sdk from '@alneas/eaos-core/plugin-sdk';
|
|
5
|
+
import { PluginStoragePolicy, PluginManifest, McpToolDefinition } from '@alneas/eaos-core/plugin-sdk';
|
|
6
|
+
import { Context, Hono } from 'hono';
|
|
7
|
+
import { JsonDocumentContract, DataContractCatalog, DataContractBinding } from '@alneas/eaos-server/lifecycle-engine';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Minimum tenant-owned aggregate state with an append-only in-record operation history.
|
|
11
|
+
*
|
|
12
|
+
* @see RecordCommandService for canonical host integration.
|
|
13
|
+
*/
|
|
14
|
+
interface CommandState {
|
|
15
|
+
/**
|
|
16
|
+
* Tenant identity bound by the trusted principal; never selected as an authorization grant from request data.
|
|
17
|
+
*/
|
|
18
|
+
tenantId: string;
|
|
19
|
+
/**
|
|
20
|
+
* In-record operation/actor/ISO-time history appended for accepted writes; maximum history length is enforced by the service.
|
|
21
|
+
*/
|
|
22
|
+
history: {
|
|
23
|
+
/**
|
|
24
|
+
* Declared accepted write operation appended by RecordCommandService.
|
|
25
|
+
*/
|
|
26
|
+
operation: string;
|
|
27
|
+
/**
|
|
28
|
+
* Verified user ID whose accepted write created this history entry.
|
|
29
|
+
*/
|
|
30
|
+
actorId: string;
|
|
31
|
+
/**
|
|
32
|
+
* Trusted UTC ISO operation timestamp.
|
|
33
|
+
*/
|
|
34
|
+
at: string;
|
|
35
|
+
}[];
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Tenant/record/revision envelope returned after an admitted aggregate operation.
|
|
39
|
+
* @typeParam T - Cloned reducer response data or resulting state payload.
|
|
40
|
+
*
|
|
41
|
+
* @see RecordCommandService for canonical host integration.
|
|
42
|
+
*/
|
|
43
|
+
interface CommandResponse<T> {
|
|
44
|
+
/**
|
|
45
|
+
* Tenant identity bound by the trusted principal; never selected as an authorization grant from request data.
|
|
46
|
+
*/
|
|
47
|
+
tenantId: string;
|
|
48
|
+
/**
|
|
49
|
+
* Logical aggregate ID selected by the trusted definition.
|
|
50
|
+
*/
|
|
51
|
+
recordId: string;
|
|
52
|
+
/**
|
|
53
|
+
* Observed aggregate revision; new or unstored reads may use 0, while accepted writes advance it by one.
|
|
54
|
+
*/
|
|
55
|
+
revision: number;
|
|
56
|
+
/**
|
|
57
|
+
* Cloned reducer result, or the resulting aggregate state when the reducer returns undefined.
|
|
58
|
+
*/
|
|
59
|
+
data: T;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Host persistence, transaction and live authorization ports for aggregate command execution.
|
|
63
|
+
* @typeParam T - Tenant-owned aggregate state required by the store and reducer transaction.
|
|
64
|
+
*
|
|
65
|
+
* @see RecordCommandService for canonical host integration.
|
|
66
|
+
*/
|
|
67
|
+
interface CommandHost<T extends CommandState> {
|
|
68
|
+
/**
|
|
69
|
+
* Optional durable tenant record store; used when transaction is absent.
|
|
70
|
+
*/
|
|
71
|
+
store?: PluginRecordStore<T>;
|
|
72
|
+
/**
|
|
73
|
+
* Runs aggregate reads, CAS and final permission checks through one real connection-bound transaction.
|
|
74
|
+
*
|
|
75
|
+
* Trusted connection-bound store; all reads, CAS and final authorization share one transaction.
|
|
76
|
+
* May expose an unstored projection at revision 0; the first write creates revision 1.
|
|
77
|
+
* @param principal - Verified current principal owning the transaction.
|
|
78
|
+
* @param work - Async service work receiving the joined record store; do not retain that store after completion.
|
|
79
|
+
* @typeParam R - Value resolved by the transaction/connection callback.
|
|
80
|
+
* @returns The callback result after commit; rejection rolls back joined writes.
|
|
81
|
+
* @throws Rejects propagated host persistence, validation or callback failures.
|
|
82
|
+
|
|
83
|
+
* @example
|
|
84
|
+
* ```typescript
|
|
85
|
+
* import type { CommandHost, CommandState, PluginPrincipal } from '@alneas/eaos-server/plugin-data';
|
|
86
|
+
* export async function readAggregate(host: CommandHost<CommandState>, principal: PluginPrincipal, recordId: string) {
|
|
87
|
+
* if (!host.transaction) throw new Error("Joined transaction port required");
|
|
88
|
+
* return host.transaction(principal, store => store.read(principal.tenantId, recordId));
|
|
89
|
+
* }
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
92
|
+
transaction?<R>(principal: PluginPrincipal, work: (store: PluginRecordStore<T>) => Promise<R>): Promise<R>;
|
|
93
|
+
/**
|
|
94
|
+
* Checks current lifecycle and permission for the operation and complete returned aggregate.
|
|
95
|
+
*
|
|
96
|
+
* Must check live activation and access to the entire returned aggregate, including referenced resources.
|
|
97
|
+
* @param p - Verified principal copied for this check.
|
|
98
|
+
* @param operation - Declared operation name.
|
|
99
|
+
* @param input - Schema input (initial admission occurs before schema validation).
|
|
100
|
+
* @param current - Optional copied current aggregate including all referenced-resource access.
|
|
101
|
+
* @returns Exactly true to admit; false denies with PluginError 403.
|
|
102
|
+
* @throws Rejects propagated host persistence, validation or callback failures.
|
|
103
|
+
|
|
104
|
+
* @example
|
|
105
|
+
* ```typescript
|
|
106
|
+
* import type { CommandHost, CommandState, PluginPrincipal } from '@alneas/eaos-server/plugin-data';
|
|
107
|
+
* export async function canOperate(host: CommandHost<CommandState>, principal: PluginPrincipal, operation: string, input: unknown, current: Readonly<CommandState>) {
|
|
108
|
+
* return await host.authorize(principal, operation, input, current) === true;
|
|
109
|
+
* }
|
|
110
|
+
* ```
|
|
111
|
+
*/
|
|
112
|
+
authorize(p: PluginPrincipal, operation: string, input: unknown, current?: Readonly<T>): Promise<boolean>;
|
|
113
|
+
/**
|
|
114
|
+
* Optional trusted clock used for operation history timestamps; defaults to new Date().
|
|
115
|
+
|
|
116
|
+
* @returns A valid Date whose toISOString value becomes the operation timestamp.
|
|
117
|
+
* @throws Callback failures propagate to the owning operation; transactional writes roll back when the host boundary rejects.
|
|
118
|
+
*/
|
|
119
|
+
now?: () => Date;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Private mutable reducer context supplied after command and resource validation.
|
|
123
|
+
* @typeParam T - Private mutable aggregate state supplied to the reducer.
|
|
124
|
+
*
|
|
125
|
+
* @see RecordCommandService for canonical host integration.
|
|
126
|
+
*/
|
|
127
|
+
interface CommandContext<T> {
|
|
128
|
+
/**
|
|
129
|
+
* Cloned verified principal for this admitted reducer invocation.
|
|
130
|
+
*/
|
|
131
|
+
principal: PluginPrincipal;
|
|
132
|
+
/**
|
|
133
|
+
* Declared operation being executed.
|
|
134
|
+
*/
|
|
135
|
+
operation: string;
|
|
136
|
+
/**
|
|
137
|
+
* Cloned schema-validated operation input.
|
|
138
|
+
*/
|
|
139
|
+
args: Record<string, any>;
|
|
140
|
+
/**
|
|
141
|
+
* Private mutable aggregate snapshot; persist through the owning service rather than writing the store directly.
|
|
142
|
+
*/
|
|
143
|
+
state: T;
|
|
144
|
+
/**
|
|
145
|
+
* Trusted UTC ISO operation timestamp.
|
|
146
|
+
*/
|
|
147
|
+
at: string;
|
|
148
|
+
/**
|
|
149
|
+
* Logical aggregate ID resolved for this command.
|
|
150
|
+
*/
|
|
151
|
+
recordId: string;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Executes schema-validated aggregate reducers through tenant isolation, live admission and revision-predicated persistence.
|
|
155
|
+
*
|
|
156
|
+
* Plugin-owned reducers may change their private snapshot only; irreversible external effects must be queued durably.
|
|
157
|
+
* @typeParam T - Tenant-owned aggregate state with tenantId and appendable operation history.
|
|
158
|
+
*
|
|
159
|
+
* @remarks
|
|
160
|
+
* Requires server Ajv/formats and a real host store or connection-bound transaction. Reducers mutate only their private cloned snapshot; queue irreversible external effects durably. Transactional hosts keep reads, write/CAS and final admission in one commit boundary; plain stores do not add a transaction. No command deduplication or automatic retry is added.
|
|
161
|
+
*
|
|
162
|
+
* @example
|
|
163
|
+
* ```typescript
|
|
164
|
+
* import { RecordCommandService, type CommandState, type CommandHost } from '@alneas/eaos-server/plugin-data';
|
|
165
|
+
* export function connectAggregate<T extends CommandState>(host: CommandHost<T>, definition: ConstructorParameters<typeof RecordCommandService<T>>[1]) { return new RecordCommandService(host, definition); }
|
|
166
|
+
* ```
|
|
167
|
+
*/
|
|
168
|
+
declare class RecordCommandService<T extends CommandState> {
|
|
169
|
+
private readonly host;
|
|
170
|
+
private readonly definition;
|
|
171
|
+
private readonly validators;
|
|
172
|
+
/**
|
|
173
|
+
* Compiles the declared operation schemas and binds real host persistence/admission capabilities.
|
|
174
|
+
* @param host - Live authorization and durable store or transaction; transaction takes precedence when provided.
|
|
175
|
+
* @param definition - Plugin schemas, write-operation allowlist, record-ID resolver, initial-state factory, reducer and invariant validator.
|
|
176
|
+
* @throws Throws for absent durable store/transaction or live authorization and for invalid strict Ajv schemas.
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* ```typescript
|
|
180
|
+
* import { RecordCommandService, type CommandState, type CommandHost } from '@alneas/eaos-server/plugin-data';
|
|
181
|
+
* export function connectAggregate<T extends CommandState>(host: CommandHost<T>, definition: ConstructorParameters<typeof RecordCommandService<T>>[1]) { return new RecordCommandService(host, definition); }
|
|
182
|
+
* ```
|
|
183
|
+
*/
|
|
184
|
+
constructor(host: CommandHost<T>, definition: {
|
|
185
|
+
/**
|
|
186
|
+
* Strict noncoercing JSON Schemas indexed by accepted operation names.
|
|
187
|
+
*/
|
|
188
|
+
schemas: Record<string, object>;
|
|
189
|
+
/**
|
|
190
|
+
* Explicit operation names that persist state, require matching revision and append history.
|
|
191
|
+
*/
|
|
192
|
+
writes: readonly string[];
|
|
193
|
+
/**
|
|
194
|
+
* Optional pure resolver from admitted input to a nonblank record scope up to 256 characters; omitted uses state.
|
|
195
|
+
|
|
196
|
+
* @param input - Cloned schema-admitted input.
|
|
197
|
+
* @returns Nonblank logical record ID up to 256 characters; omitted resolver defaults to state.
|
|
198
|
+
* @throws Callback failures propagate to the owning operation; transactional writes roll back when the host boundary rejects.
|
|
199
|
+
*/
|
|
200
|
+
recordId?: (input: Record<string, any>) => string;
|
|
201
|
+
/**
|
|
202
|
+
* Create a tenant/record-bound unstored aggregate snapshot when no row exists.
|
|
203
|
+
|
|
204
|
+
* @param tenantId - Verified tenant ID owning the aggregate.
|
|
205
|
+
* @param recordId - Resolved logical record ID.
|
|
206
|
+
* @returns A new private unstored tenant-owned state with initialized history.
|
|
207
|
+
* @throws Callback failures propagate to the owning operation; transactional writes roll back when the host boundary rejects.
|
|
208
|
+
*/
|
|
209
|
+
initial: (tenantId: string, recordId: string) => T;
|
|
210
|
+
/**
|
|
211
|
+
* Async plugin reducer receiving private state/input and verified context; mutate only that snapshot and queue external effects durably.
|
|
212
|
+
|
|
213
|
+
* @param context - Private mutable state, cloned principal/input and trusted operation time.
|
|
214
|
+
* @returns Optional domain response data; undefined selects the resulting state for response data.
|
|
215
|
+
* @throws Callback failures propagate to the owning operation; transactional writes roll back when the host boundary rejects.
|
|
216
|
+
*/
|
|
217
|
+
reduce: (context: CommandContext<T>) => Promise<unknown>;
|
|
218
|
+
/**
|
|
219
|
+
* Synchronous aggregate invariant assertion before/after writes; throw to reject invalid state.
|
|
220
|
+
|
|
221
|
+
* @param state - Private aggregate state whose tenant/history/domain invariants must hold.
|
|
222
|
+
* @returns Completes without a value when invariants pass; throw to reject before persistence.
|
|
223
|
+
* @throws Callback failures propagate to the owning operation; transactional writes roll back when the host boundary rejects.
|
|
224
|
+
*/
|
|
225
|
+
validate: (state: T) => void;
|
|
226
|
+
});
|
|
227
|
+
/**
|
|
228
|
+
* Validates and admits one aggregate operation, running a reducer against a private current snapshot.
|
|
229
|
+
* @param principal - Host-authenticated current tenant/user context; structural validation alone proves no membership.
|
|
230
|
+
* @param operation - Declared schema key; membership in definition.writes selects persistence.
|
|
231
|
+
* @param input - Operation-schema input; writes require a safe integer revision matching the current snapshot, including 0 for a new/unstored aggregate.
|
|
232
|
+
* @returns A tenant/record/revision envelope with cloned reducer data, or resulting state when the reducer returns undefined; read-only reducers do not persist mutations.
|
|
233
|
+
* @throws Rejects malformed principal (401), denied live admission (403), schema/scope errors (400), stale revision/capacity/CAS conflict (409), invalid foreign records/reducer scope, and propagated reducer/invariant/clock/store/transaction failures.
|
|
234
|
+
*
|
|
235
|
+
* @remarks
|
|
236
|
+
* Record ID defaults to state and must be nonblank/up to 256 characters. Writes append actor/UTC history and reject over 5000 entries or 8 MiB JSON state. Host transaction projections may start at revision 0. Rejections can follow partial plain-store/adapter effects; callers must reload before retrying uncertain outcomes.
|
|
237
|
+
*
|
|
238
|
+
* @example
|
|
239
|
+
* ```typescript
|
|
240
|
+
* import { RecordCommandService, type CommandState, type PluginPrincipal } from '@alneas/eaos-server/plugin-data';
|
|
241
|
+
* export function executeAggregate<T extends CommandState>(service: RecordCommandService<T>, principal: PluginPrincipal, operation: string, input: unknown) { return service.execute(principal, operation, input); }
|
|
242
|
+
* ```
|
|
243
|
+
*/
|
|
244
|
+
execute(principal: PluginPrincipal, operation: string, input: unknown): Promise<CommandResponse<any>>;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Version-1 hash-linked journal event storing payload hashes and optional command receipt identity.
|
|
249
|
+
*
|
|
250
|
+
* @see appendAtomicAudit for canonical host integration.
|
|
251
|
+
*/
|
|
252
|
+
interface AtomicAuditEvent {
|
|
253
|
+
/**
|
|
254
|
+
* Persisted journal schema version; must be 1.
|
|
255
|
+
*/
|
|
256
|
+
version: 1;
|
|
257
|
+
/**
|
|
258
|
+
* Tenant identity bound by the trusted principal; never selected as an authorization grant from request data.
|
|
259
|
+
*/
|
|
260
|
+
tenantId: string;
|
|
261
|
+
/**
|
|
262
|
+
* Positive monotonically increasing journal position within the tenant/namespace.
|
|
263
|
+
*/
|
|
264
|
+
sequence: number;
|
|
265
|
+
/**
|
|
266
|
+
* Trusted operation label recorded for this admitted command.
|
|
267
|
+
*/
|
|
268
|
+
operation: string;
|
|
269
|
+
/**
|
|
270
|
+
* Verified actor identity at append time.
|
|
271
|
+
*/
|
|
272
|
+
actorId: string;
|
|
273
|
+
/**
|
|
274
|
+
* UTC ISO append timestamp.
|
|
275
|
+
*/
|
|
276
|
+
at: string;
|
|
277
|
+
/**
|
|
278
|
+
* Hash of JSON-normalized command input; no input payload bytes are stored here.
|
|
279
|
+
*/
|
|
280
|
+
inputHash: string;
|
|
281
|
+
/**
|
|
282
|
+
* Hash of JSON-normalized command result; undefined is normalized to null.
|
|
283
|
+
*/
|
|
284
|
+
resultHash: string;
|
|
285
|
+
/**
|
|
286
|
+
* Optional immutable command receipt key, otherwise null.
|
|
287
|
+
*/
|
|
288
|
+
commandKey: string | null;
|
|
289
|
+
/**
|
|
290
|
+
* Previous journal event hash, or null for the first event.
|
|
291
|
+
*/
|
|
292
|
+
previousHash: string | null;
|
|
293
|
+
/**
|
|
294
|
+
* Canonical hash of the other event fields; not an external signature.
|
|
295
|
+
*/
|
|
296
|
+
hash: string;
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Append a hash-linked immutable audit event and CAS-update its head in the current transaction.
|
|
300
|
+
* @param tx - Live atomic session shared with the domain command.
|
|
301
|
+
* @param p - Verified tenant/user principal.
|
|
302
|
+
* @param operation - Trusted nonempty operation label of at most 240 characters.
|
|
303
|
+
* @param input - Input whose JSON-normalized hash is recorded; payload bytes are not stored in the audit event.
|
|
304
|
+
* @param result - Result whose JSON-normalized hash is recorded; undefined is normalized to null.
|
|
305
|
+
* @param commandKey - Optional command/ receipt key linking command input/result evidence; defaults to null.
|
|
306
|
+
* @returns The appended version-1 event with sequence and integrity hash.
|
|
307
|
+
* @throws Rejects invalid principals/labels/receipt keys, corrupt head/previous event, sequence capacity or transaction failures.
|
|
308
|
+
* @remarks Requires the caller's existing transaction and current authorization. Hash continuity is not an external trust anchor; real business payloads remain outside audit events.
|
|
309
|
+
* @example
|
|
310
|
+
* import { appendAtomicAudit } from '@alneas/eaos-server/plugin-data'
|
|
311
|
+
* export function audit(tx: Parameters<typeof appendAtomicAudit>[0], p: Parameters<typeof appendAtomicAudit>[1], input: unknown, result: unknown) { return appendAtomicAudit(tx, p, 'example-operation', input, result) }
|
|
312
|
+
*/
|
|
313
|
+
declare function appendAtomicAudit(tx: AtomicSession, p: PluginPrincipal, operation: string, input: unknown, result: unknown, commandKey?: string | null): Promise<{
|
|
314
|
+
hash: string;
|
|
315
|
+
version: 1;
|
|
316
|
+
tenantId: string;
|
|
317
|
+
sequence: number;
|
|
318
|
+
operation: string;
|
|
319
|
+
actorId: string;
|
|
320
|
+
at: string;
|
|
321
|
+
inputHash: string;
|
|
322
|
+
resultHash: string;
|
|
323
|
+
commandKey: string | null;
|
|
324
|
+
previousHash: string | null;
|
|
325
|
+
}>;
|
|
326
|
+
/**
|
|
327
|
+
* Read and verify one bounded page of immutable tenant audit events.
|
|
328
|
+
* @param tx - Live tenant-scoped atomic session.
|
|
329
|
+
* @param p - Verified principal whose tenant must match each event.
|
|
330
|
+
* @param afterSequence - Exclusive nonnegative sequence; defaults to 0.
|
|
331
|
+
* @param limit - Integer page size from 1 to 100; defaults to 50.
|
|
332
|
+
* @returns Verified events and a continuation sequence or null when no further row was observed.
|
|
333
|
+
* @throws Rejects invalid pagination, event identity/version/revision/hash mismatches or store failures.
|
|
334
|
+
* @remarks Caller enforces current resource permission before and after reading. One page does not verify full chain continuity or an external trust anchor.
|
|
335
|
+
* @example
|
|
336
|
+
* import { readAtomicAudit } from '@alneas/eaos-server/plugin-data'
|
|
337
|
+
* export function auditPage(tx: Parameters<typeof readAtomicAudit>[0], p: Parameters<typeof readAtomicAudit>[1]) { return readAtomicAudit(tx, p, 0, 50) }
|
|
338
|
+
*/
|
|
339
|
+
declare function readAtomicAudit(tx: AtomicSession, p: PluginPrincipal, afterSequence?: number, limit?: number): Promise<{
|
|
340
|
+
events: AtomicAuditEvent[];
|
|
341
|
+
nextSequence: number | null;
|
|
342
|
+
}>;
|
|
343
|
+
/**
|
|
344
|
+
* Verify a bounded audit chain, its head and linked command receipts within the current tenant transaction.
|
|
345
|
+
* @param tx - Live atomic session containing the journal and receipts.
|
|
346
|
+
* @param p - Verified tenant/user principal with host-admitted audit access.
|
|
347
|
+
* @returns Tenant identity, verified event count/head hash and explicit externalTrustAnchor=false.
|
|
348
|
+
* @throws Rejects more than 10000 events, discontinuous sequence/hash links, receipt mismatches, corrupt head/tail or store failures.
|
|
349
|
+
* @remarks Integrity verification cannot prove an external actor has not rewritten the entire journal. Larger histories need the host's reviewed archival verifier.
|
|
350
|
+
* @example
|
|
351
|
+
* import { verifyAtomicAudit } from '@alneas/eaos-server/plugin-data'
|
|
352
|
+
* export function verifyJournal(tx: Parameters<typeof verifyAtomicAudit>[0], p: Parameters<typeof verifyAtomicAudit>[1]) { return verifyAtomicAudit(tx, p) }
|
|
353
|
+
*/
|
|
354
|
+
declare function verifyAtomicAudit(tx: AtomicSession, p: PluginPrincipal): Promise<{
|
|
355
|
+
tenantId: string;
|
|
356
|
+
status: "verified";
|
|
357
|
+
count: number;
|
|
358
|
+
headHash: string | null;
|
|
359
|
+
coverage: "atomic-journal-v1";
|
|
360
|
+
externalTrustAnchor: false;
|
|
361
|
+
}>;
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Insert or replay one immutable Outbox event inside the same transaction as its domain write.
|
|
365
|
+
* @param tx - Live tenant-scoped atomic session.
|
|
366
|
+
* @param input - Canonical event input with stable tenant, topic and idempotency identity.
|
|
367
|
+
* @typeParam T - JSON-serializable event payload type.
|
|
368
|
+
* @returns A cloned new event or the matching existing event.
|
|
369
|
+
* @throws Rejects invalid event input, conflicting idempotency input or transaction failures.
|
|
370
|
+
* @remarks Does not deliver externally; the host scheduler and idempotent handler process the committed event later.
|
|
371
|
+
* @example
|
|
372
|
+
* import { enqueueOutboxEvent } from '@alneas/eaos-server/plugin-data'
|
|
373
|
+
* export function enqueue<T>(tx: Parameters<typeof enqueueOutboxEvent>[0], input: Parameters<typeof enqueueOutboxEvent<T>>[1]) { return enqueueOutboxEvent(tx, input) }
|
|
374
|
+
*/
|
|
375
|
+
declare function enqueueOutboxEvent<T>(tx: AtomicSession, input: OutboxEventInput<T>): Promise<OutboxEvent<T>>;
|
|
376
|
+
/**
|
|
377
|
+
* Bind workflow event append operations to the caller's current atomic transaction.
|
|
378
|
+
* @param tx - Live session containing the same domain CAS operation.
|
|
379
|
+
* @param topicPrefix - Trusted nonempty topic prefix; defaults to workflow and admits letters/digits/underscore/dot/colon/slash/hyphen.
|
|
380
|
+
* @returns A WorkflowEventSink that enqueues copied envelopes in the existing Outbox.
|
|
381
|
+
* @throws Invalid session/prefix throws at construction; appended event validation/idempotency/store failures reject.
|
|
382
|
+
* @remarks The sink owns no commit boundary and performs no external transport; use it only while the parent transaction is active.
|
|
383
|
+
* @example
|
|
384
|
+
* import { createAtomicWorkflowEventSink, type AtomicRepository, type PluginPrincipal } from '@alneas/eaos-server/plugin-data'
|
|
385
|
+
* import type { WorkflowEventEnvelope } from '@alneas/eaos-core'
|
|
386
|
+
* export function appendWorkflow<T>(repository: AtomicRepository, principal: PluginPrincipal, event: WorkflowEventEnvelope<T>) {
|
|
387
|
+
* return repository.run(principal, session => createAtomicWorkflowEventSink(session).append(event))
|
|
388
|
+
* }
|
|
389
|
+
*/
|
|
390
|
+
declare function createAtomicWorkflowEventSink(tx: AtomicSession, topicPrefix?: string): WorkflowEventSink;
|
|
391
|
+
/**
|
|
392
|
+
* Principal, repository and stale-claim settings for durable Outbox transitions.
|
|
393
|
+
*
|
|
394
|
+
* @see createAtomicOutboxStore for canonical host integration.
|
|
395
|
+
*/
|
|
396
|
+
interface AtomicOutboxStoreOptions {
|
|
397
|
+
/**
|
|
398
|
+
* Real atomic repository for durable tenant-scoped Outbox transitions.
|
|
399
|
+
*/
|
|
400
|
+
repository: AtomicRepository;
|
|
401
|
+
/**
|
|
402
|
+
* Verified fixed tenant/user scope copied at construction; replace the store when identity changes.
|
|
403
|
+
*/
|
|
404
|
+
principal: PluginPrincipal;
|
|
405
|
+
/**
|
|
406
|
+
* Claim staleness threshold in milliseconds; defaults to 300000 and must be finite and at least 1000.
|
|
407
|
+
*/
|
|
408
|
+
staleAfterMs?: number;
|
|
409
|
+
/**
|
|
410
|
+
* Optional dispatcher clock; createAtomicOutboxDispatcher forwards it, while standalone store.claim uses its explicit now parameter.
|
|
411
|
+
|
|
412
|
+
* @returns The trusted current Date when used by createAtomicOutboxDispatcher; standalone store.claim receives an explicit Date.
|
|
413
|
+
* @throws Callback failures propagate to the owning operation; transactional writes roll back when the host boundary rejects.
|
|
414
|
+
*/
|
|
415
|
+
now?: () => Date;
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* Bind durable Outbox claim/result transitions to one verified principal and atomic repository.
|
|
419
|
+
* @param options - Repository/principal plus optional staleAfterMs (default 300000, minimum 1000) and clock.
|
|
420
|
+
* @returns An OutboxStore using CAS claim tokens for publication/failure transitions.
|
|
421
|
+
* @throws Invalid stale timeout throws; claims reject batch sizes outside 1–100, scope mismatches, nonadvancing pages or scan capacity above 30000; result writes reject changed claim tokens.
|
|
422
|
+
* @remarks Stale claims can be reclaimed, so external handlers must tolerate duplicate delivery. No global scheduler or external exactly-once guarantee is provided.
|
|
423
|
+
* @example
|
|
424
|
+
* import { createAtomicOutboxStore } from '@alneas/eaos-server/plugin-data'
|
|
425
|
+
* export function store(options: Parameters<typeof createAtomicOutboxStore>[0]) { return createAtomicOutboxStore(options) }
|
|
426
|
+
*/
|
|
427
|
+
declare function createAtomicOutboxStore(options: AtomicOutboxStoreOptions): OutboxStore;
|
|
428
|
+
/**
|
|
429
|
+
* Existing dispatcher options combined with the canonical atomic tenant Outbox store.
|
|
430
|
+
*
|
|
431
|
+
* @see createAtomicOutboxDispatcher for canonical host integration.
|
|
432
|
+
*/
|
|
433
|
+
interface AtomicOutboxDispatcherOptions extends Omit<OutboxDispatcherOptions, 'store'>, AtomicOutboxStoreOptions {
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Compose the existing OutboxDispatcher with the tenant-scoped atomic Outbox store.
|
|
437
|
+
* @param options - Dispatcher handlers/time/retry settings plus the atomic repository and principal.
|
|
438
|
+
* @returns An OutboxDispatcher instance; construction alone does not start a worker loop.
|
|
439
|
+
* @throws Invalid store/dispatcher configuration throws; later dispatch rejects according to its host handlers and store.
|
|
440
|
+
* @remarks Host scheduling and handler idempotency remain explicit; no parallel transport or global singleton is introduced.
|
|
441
|
+
* @example
|
|
442
|
+
* import { createAtomicOutboxDispatcher } from '@alneas/eaos-server/plugin-data'
|
|
443
|
+
* export function dispatcher(options: Parameters<typeof createAtomicOutboxDispatcher>[0]) { return createAtomicOutboxDispatcher(options) }
|
|
444
|
+
*/
|
|
445
|
+
declare function createAtomicOutboxDispatcher(options: AtomicOutboxDispatcherOptions): OutboxDispatcher;
|
|
446
|
+
/**
|
|
447
|
+
* Reset one failed tenant event to pending while retaining its immutable identity.
|
|
448
|
+
* @param tx - Live session entered after explicit host recovery authorization.
|
|
449
|
+
* @param tenantId - Verified tenant identity required to match the stored event.
|
|
450
|
+
* @param id - Existing failed event ID, nonempty and at most 256 characters.
|
|
451
|
+
* @param availableAt - Parseable retry timestamp; defaults to the current ISO time.
|
|
452
|
+
* @returns The requeued event with claim/error fields cleared.
|
|
453
|
+
* @throws Rejects invalid identifiers/timestamps, missing/nonfailed/foreign events or CAS failures.
|
|
454
|
+
* @remarks Does not perform delivery or authorize recovery. A prior uncertain external effect may already exist; handlers must deduplicate by the retained identity.
|
|
455
|
+
* @example
|
|
456
|
+
* import { requeueOutboxEvent } from '@alneas/eaos-server/plugin-data'
|
|
457
|
+
* export function requeue(tx: Parameters<typeof requeueOutboxEvent>[0], tenantId: string, id: string) { return requeueOutboxEvent(tx, tenantId, id) }
|
|
458
|
+
*/
|
|
459
|
+
declare function requeueOutboxEvent(tx: AtomicSession, tenantId: string, id: string, availableAt?: string): Promise<OutboxEvent>;
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Host record storage and live resource authorization, optionally joined to a shared atomic repository.
|
|
463
|
+
* @typeParam T - Tenant-owned stored record payload.
|
|
464
|
+
*
|
|
465
|
+
* @see ScopedRecordService for canonical host integration.
|
|
466
|
+
*/
|
|
467
|
+
interface ScopedRecordHost<T> {
|
|
468
|
+
/**
|
|
469
|
+
* Host record store with real tenant scoping and revision-predicated writes.
|
|
470
|
+
*/
|
|
471
|
+
store: PluginRecordStore<T>;
|
|
472
|
+
/**
|
|
473
|
+
* Checks current plugin activation and resource permission before exposing or persisting records.
|
|
474
|
+
* @param principal - Verified current principal.
|
|
475
|
+
* @param operation - Declared operation name.
|
|
476
|
+
* @param input - Operation input, list criteria or created payload appropriate to the check.
|
|
477
|
+
* @param current - Optional copied current record; absence requires operation-level admission.
|
|
478
|
+
* @returns Exactly true to admit the operation/record; false denies or filters the record during lists.
|
|
479
|
+
* @throws Rejects propagated host persistence, validation or callback failures.
|
|
480
|
+
|
|
481
|
+
* @example
|
|
482
|
+
* ```typescript
|
|
483
|
+
* import type { ScopedRecordHost, PluginPrincipal } from '@alneas/eaos-server/plugin-data';
|
|
484
|
+
* export async function admitted(host: ScopedRecordHost<{ title: string }>, principal: PluginPrincipal, operation: string, input: unknown, current?: unknown) {
|
|
485
|
+
* return await host.authorize(principal, operation, input, current) === true;
|
|
486
|
+
* }
|
|
487
|
+
* ```
|
|
488
|
+
*/
|
|
489
|
+
authorize(principal: PluginPrincipal, operation: string, input: unknown, current?: unknown): Promise<boolean>;
|
|
490
|
+
/**
|
|
491
|
+
* Optional trusted operation clock; defaults to new Date().
|
|
492
|
+
|
|
493
|
+
* @returns A valid Date used for the current CRUD/domain operation timestamp.
|
|
494
|
+
* @throws Callback failures propagate to the owning operation; transactional writes roll back when the host boundary rejects.
|
|
495
|
+
*/
|
|
496
|
+
now?: () => Date;
|
|
497
|
+
/**
|
|
498
|
+
* Optional existing atomic repository joining ordinary CRUD, workflow commands, reservations and audit in one commit boundary.
|
|
499
|
+
*
|
|
500
|
+
* Ordinary CRUD and workflow commands share the provided transaction boundary.
|
|
501
|
+
*/
|
|
502
|
+
repository?: AtomicRepository;
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* Plugin-owned schemas, CRUD reducers, filtering and transactional identity/composition rules.
|
|
506
|
+
* @typeParam T - Stored record payload with stable tenantId/id.
|
|
507
|
+
* @typeParam S - Decoded record view extending T with a positive CAS revision.
|
|
508
|
+
*
|
|
509
|
+
* @see ScopedRecordService for canonical host integration.
|
|
510
|
+
*/
|
|
511
|
+
interface ScopedRecordDefinition<T extends {
|
|
512
|
+
tenantId: string;
|
|
513
|
+
id: string;
|
|
514
|
+
}, S extends T & {
|
|
515
|
+
revision: number;
|
|
516
|
+
}> {
|
|
517
|
+
/**
|
|
518
|
+
* Explicit per-operation JSON Schemas compiled with coercion disabled.
|
|
519
|
+
*/
|
|
520
|
+
schemas: Record<string, object>;
|
|
521
|
+
/**
|
|
522
|
+
* Exact list/get/create/update/archive operation names used for shared dispatch.
|
|
523
|
+
*/
|
|
524
|
+
operations: {
|
|
525
|
+
/**
|
|
526
|
+
* Host operation name for bounded or keyset-paged authorized record listing.
|
|
527
|
+
*/
|
|
528
|
+
list: string;
|
|
529
|
+
/**
|
|
530
|
+
* Host operation name for reading one authorized record.
|
|
531
|
+
*/
|
|
532
|
+
get: string;
|
|
533
|
+
/**
|
|
534
|
+
* Host operation name for creating one tenant record.
|
|
535
|
+
*/
|
|
536
|
+
create: string;
|
|
537
|
+
/**
|
|
538
|
+
* Host operation name for revision-predicated record patching.
|
|
539
|
+
*/
|
|
540
|
+
update: string;
|
|
541
|
+
/**
|
|
542
|
+
* Host operation name for the plugin-owned retained-data archive transition.
|
|
543
|
+
*/
|
|
544
|
+
archive: string;
|
|
545
|
+
};
|
|
546
|
+
/**
|
|
547
|
+
* Response property under which admitted records are returned.
|
|
548
|
+
*/
|
|
549
|
+
listKey: string;
|
|
550
|
+
/**
|
|
551
|
+
* Trusted domain label used in validation/conflict errors.
|
|
552
|
+
*/
|
|
553
|
+
label: string;
|
|
554
|
+
/**
|
|
555
|
+
* Enable filtered keyset scanning when the host store supplies listPage; otherwise a supplied cursor is rejected.
|
|
556
|
+
*
|
|
557
|
+
* Enable complete filtered paging when the store supplies listPage.
|
|
558
|
+
*/
|
|
559
|
+
pagination?: boolean;
|
|
560
|
+
/**
|
|
561
|
+
* Additional auxiliary record prefixes omitted from business CRUD results.
|
|
562
|
+
*
|
|
563
|
+
* Plugin-owned auxiliary keys must not appear as business records.
|
|
564
|
+
*/
|
|
565
|
+
excludedIdPrefixes?: readonly string[];
|
|
566
|
+
/**
|
|
567
|
+
* Optional composite identity reservation rules; require a shared transaction for concurrent enforcement.
|
|
568
|
+
*
|
|
569
|
+
* Transactional reservations enforce composite business identities across concurrent writers.
|
|
570
|
+
*/
|
|
571
|
+
unique?: readonly {
|
|
572
|
+
/**
|
|
573
|
+
* Trusted uniqueness constraint label matching lowercase letter followed by up to 60 lowercase letters/digits/underscore/hyphen characters.
|
|
574
|
+
*/
|
|
575
|
+
name: string;
|
|
576
|
+
/**
|
|
577
|
+
* Nonempty ordered stored field keys; every active value must be a nonblank string.
|
|
578
|
+
*/
|
|
579
|
+
fields: readonly (keyof T & string)[];
|
|
580
|
+
/** Trusted domain predicate; false releases this record's reservation.
|
|
581
|
+
* @param record - Cloned current record; this predicate must be pure.
|
|
582
|
+
* @returns True to reserve the composite identity, false to release it; nonboolean results reject.
|
|
583
|
+
* @throws Callback failures propagate to the owning operation; transactional writes roll back when the host boundary rejects.
|
|
584
|
+
*/ when?: (record: T) => boolean;
|
|
585
|
+
}[];
|
|
586
|
+
/**
|
|
587
|
+
* Fields searched by the generic case-insensitive query filter.
|
|
588
|
+
*/
|
|
589
|
+
searchableFields?: readonly (keyof S & string)[];
|
|
590
|
+
/**
|
|
591
|
+
* Optional synchronous domain filter applied in addition to standard criteria and live record authorization.
|
|
592
|
+
|
|
593
|
+
* @param input - Schema-admitted list criteria.
|
|
594
|
+
* @param value - Decoded scoped record being considered.
|
|
595
|
+
* @returns True to retain this candidate before the additional search/live-record permission checks.
|
|
596
|
+
* @throws Callback failures propagate to the owning operation; transactional writes roll back when the host boundary rejects.
|
|
597
|
+
*/
|
|
598
|
+
filter?: (input: Record<string, any>, value: S) => boolean;
|
|
599
|
+
/**
|
|
600
|
+
* Creates a new tenant-owned domain payload from admitted inputs.
|
|
601
|
+
* @param input - Schema-validated create input.
|
|
602
|
+
* @param principal - Verified current tenant principal.
|
|
603
|
+
* @param at - Trusted UTC ISO operation timestamp.
|
|
604
|
+
* @returns The new payload with stable id and matching tenantId; no persistence is performed by this reducer.
|
|
605
|
+
* @throws Reducer errors propagate; do not perform irreversible external effects.
|
|
606
|
+
|
|
607
|
+
* @example
|
|
608
|
+
* ```typescript
|
|
609
|
+
* import type { ScopedRecordDefinition, PluginPrincipal } from '@alneas/eaos-server/plugin-data';
|
|
610
|
+
* type Stored = { tenantId: string; id: string; archived: boolean };
|
|
611
|
+
* type View = Stored & { revision: number };
|
|
612
|
+
* export function reduceCreate(definition: ScopedRecordDefinition<Stored, View>, principal: PluginPrincipal, admittedInput: Record<string, unknown>) {
|
|
613
|
+
* return definition.create(admittedInput, principal, new Date().toISOString());
|
|
614
|
+
* }
|
|
615
|
+
* ```
|
|
616
|
+
*/
|
|
617
|
+
create(input: Record<string, any>, principal: PluginPrincipal, at: string): T;
|
|
618
|
+
/**
|
|
619
|
+
* Mutates only the private record snapshot with the admitted patch.
|
|
620
|
+
* @param value - Mutable current decoded revisioned record; preserve tenantId/id.
|
|
621
|
+
* @param patch - Schema-admitted patch fields.
|
|
622
|
+
* @param at - Trusted UTC ISO operation timestamp.
|
|
623
|
+
* @returns Completes without a value; the owning service performs CAS persistence.
|
|
624
|
+
* @throws Reducer errors propagate and roll back joined transactional work.
|
|
625
|
+
|
|
626
|
+
* @example
|
|
627
|
+
* ```typescript
|
|
628
|
+
* import type { ScopedRecordDefinition } from '@alneas/eaos-server/plugin-data';
|
|
629
|
+
* type Stored = { tenantId: string; id: string; archived: boolean };
|
|
630
|
+
* type View = Stored & { revision: number };
|
|
631
|
+
* export function reduceUpdate(definition: ScopedRecordDefinition<Stored, View>, snapshot: View, admittedPatch: Record<string, unknown>) {
|
|
632
|
+
* const next = structuredClone(snapshot);
|
|
633
|
+
* definition.update(next, admittedPatch, new Date().toISOString());
|
|
634
|
+
* return next; // The owning service still performs revision-checked persistence.
|
|
635
|
+
* }
|
|
636
|
+
* ```
|
|
637
|
+
*/
|
|
638
|
+
update(value: S, patch: Record<string, unknown>, at: string): void;
|
|
639
|
+
/**
|
|
640
|
+
* Mutates the private record snapshot to the plugin's archive state.
|
|
641
|
+
* @param value - Mutable current record; preserve stable tenantId/id.
|
|
642
|
+
* @param at - Trusted UTC ISO operation timestamp.
|
|
643
|
+
* @param input - Optional schema-admitted archive command input.
|
|
644
|
+
* @param principal - Optional verified current principal supplied by the service.
|
|
645
|
+
* @returns Completes without a value; archive retains data according to the plugin reducer.
|
|
646
|
+
* @throws Reducer errors propagate; do not perform irreversible external effects.
|
|
647
|
+
|
|
648
|
+
* @example
|
|
649
|
+
* ```typescript
|
|
650
|
+
* import type { ScopedRecordDefinition, PluginPrincipal } from '@alneas/eaos-server/plugin-data';
|
|
651
|
+
* type Stored = { tenantId: string; id: string; archived: boolean };
|
|
652
|
+
* type View = Stored & { revision: number };
|
|
653
|
+
* export function reduceArchive(definition: ScopedRecordDefinition<Stored, View>, snapshot: View, principal: PluginPrincipal, admittedInput: Record<string, unknown>) {
|
|
654
|
+
* const next = structuredClone(snapshot);
|
|
655
|
+
* definition.archive(next, new Date().toISOString(), admittedInput, principal);
|
|
656
|
+
* return next; // No persistence is performed by this reducer call.
|
|
657
|
+
* }
|
|
658
|
+
* ```
|
|
659
|
+
*/
|
|
660
|
+
archive(value: S, at: string, input?: Record<string, any>, principal?: PluginPrincipal): void;
|
|
661
|
+
/**
|
|
662
|
+
* Additional plugin-owned mutation reducers persisted through the same CAS path; never perform irreversible external effects here.
|
|
663
|
+
*
|
|
664
|
+
* Plugin-owned durable workflow commands. Each command is validated by its
|
|
665
|
+
* declared schema, receives the current revision, and is persisted through
|
|
666
|
+
* the same tenant-scoped CAS path as update/archive.
|
|
667
|
+
|
|
668
|
+
* @param value - Private mutable revisioned record; preserve stable tenant/id.
|
|
669
|
+
* @param input - Schema-admitted custom command input.
|
|
670
|
+
* @param at - Trusted ISO operation timestamp.
|
|
671
|
+
* @param principal - Verified current principal.
|
|
672
|
+
* @returns Completes without a value after mutating the private snapshot; the owning service performs CAS persistence.
|
|
673
|
+
* @throws Callback failures propagate to the owning operation; transactional writes roll back when the host boundary rejects.
|
|
674
|
+
*/
|
|
675
|
+
custom?: Record<string, (value: S, input: Record<string, any>, at: string, principal: PluginPrincipal) => void>;
|
|
676
|
+
/**
|
|
677
|
+
* Optional async owning-domain composition inside the shared transaction before final authorization; not an external side-effect hook.
|
|
678
|
+
*
|
|
679
|
+
* Owning domain composition inside the existing transaction, before final live authorization. Never use for external effects.
|
|
680
|
+
|
|
681
|
+
* @param principal - Verified current principal.
|
|
682
|
+
* @param operation - Declared mutation operation.
|
|
683
|
+
* @param input - Schema-admitted command input.
|
|
684
|
+
* @param current - Cloned resulting decoded record; do not mutate service state through this copy.
|
|
685
|
+
* @param previous - Optional prior decoded record, absent on create.
|
|
686
|
+
* @returns Resolves without a value after owning-domain composition inside the same transaction; no external effects.
|
|
687
|
+
* @throws Callback failures propagate to the owning operation; transactional writes roll back when the host boundary rejects.
|
|
688
|
+
*/
|
|
689
|
+
afterWrite?: (principal: PluginPrincipal, operation: string, input: Record<string, any>, current: S, previous?: S) => Promise<void>;
|
|
690
|
+
}
|
|
691
|
+
/**
|
|
692
|
+
* Derive a stable atomic reservation key for a named composite business identity.
|
|
693
|
+
* @param name - Trusted lowercase uniqueness label of at most 61 characters.
|
|
694
|
+
* @param values - Nonempty tuple of nonblank string values in canonical field order.
|
|
695
|
+
* @returns unique/ followed by a canonical content hash.
|
|
696
|
+
* @throws Invalid declarations throw Error; nonstring/blank identity values throw PluginError 409.
|
|
697
|
+
* @remarks Derivation alone reserves nothing; concurrent uniqueness requires CAS reservations in the enclosing atomic transaction.
|
|
698
|
+
* @example
|
|
699
|
+
* import { uniqueRecordKey } from '@alneas/eaos-server/plugin-data'
|
|
700
|
+
* const key = uniqueRecordKey('external-id', ['example'])
|
|
701
|
+
*/
|
|
702
|
+
declare function uniqueRecordKey(name: string, values: readonly unknown[]): string;
|
|
703
|
+
/**
|
|
704
|
+
* Applies schema-validated record CRUD and workflow commands through tenant checks, live admission and optimistic revisions.
|
|
705
|
+
*
|
|
706
|
+
* Shared tenant-scoped CRUD/CAS boundary for small plugin-owned master records.
|
|
707
|
+
* @typeParam T - Stored tenant-owned record payload containing stable tenantId and id.
|
|
708
|
+
* @typeParam S - Decoded public record view extending T with a positive CAS revision.
|
|
709
|
+
*
|
|
710
|
+
* @remarks
|
|
711
|
+
* Use a real atomic repository for unique identity reservations, owning-domain composition and command/audit receipts. Repository execution joins CRUD/domain writes and final authorization in one transaction; plain stores do not gain those guarantees. Domain reducers must not perform irreversible external effects. Auxiliary audit/command/event/unique keys are excluded from business results as configured.
|
|
712
|
+
*
|
|
713
|
+
* @example
|
|
714
|
+
* ```typescript
|
|
715
|
+
* import { ScopedRecordService, type ScopedRecordHost, type ScopedRecordDefinition } from '@alneas/eaos-server/plugin-data';
|
|
716
|
+
* type Row = { tenantId: string; id: string; title: string };
|
|
717
|
+
* type RevisionedRow = Row & { revision: number };
|
|
718
|
+
* export function connectRecords(host: ScopedRecordHost<Row>, definition: ScopedRecordDefinition<Row, RevisionedRow>) { return new ScopedRecordService(host, definition); }
|
|
719
|
+
* ```
|
|
720
|
+
*/
|
|
721
|
+
declare class ScopedRecordService<T extends {
|
|
722
|
+
tenantId: string;
|
|
723
|
+
id: string;
|
|
724
|
+
}, S extends T & {
|
|
725
|
+
revision: number;
|
|
726
|
+
}> {
|
|
727
|
+
private readonly host;
|
|
728
|
+
private readonly definition;
|
|
729
|
+
private readonly atomicSession?;
|
|
730
|
+
private readonly validators;
|
|
731
|
+
/**
|
|
732
|
+
* Compiles strict noncoercing command schemas for one trusted record definition.
|
|
733
|
+
* @param host - Durable tenant-scoped store, live authorization, optional clock and shared atomic repository.
|
|
734
|
+
* @param definition - Plugin-owned operation names, schemas, reducers, paging and identity rules.
|
|
735
|
+
* @param atomicSession - Optional already active internal session used for joined composition/uniqueness; its lifetime must not exceed the enclosing repository callback.
|
|
736
|
+
* @throws Throws when durable store or live authorization is missing, or strict schema compilation fails.
|
|
737
|
+
*
|
|
738
|
+
* @example
|
|
739
|
+
* ```typescript
|
|
740
|
+
* import { ScopedRecordService, type ScopedRecordHost, type ScopedRecordDefinition } from '@alneas/eaos-server/plugin-data';
|
|
741
|
+
* type Row = { tenantId: string; id: string; title: string };
|
|
742
|
+
* type RevisionedRow = Row & { revision: number };
|
|
743
|
+
* export function connectRecords(host: ScopedRecordHost<Row>, definition: ScopedRecordDefinition<Row, RevisionedRow>) { return new ScopedRecordService(host, definition); }
|
|
744
|
+
* ```
|
|
745
|
+
*/
|
|
746
|
+
constructor(host: ScopedRecordHost<T>, definition: ScopedRecordDefinition<T, S>, atomicSession?: AtomicSession | undefined);
|
|
747
|
+
private allow;
|
|
748
|
+
/**
|
|
749
|
+
* Exposes the same live tenant/permission check to a plugin's read-only
|
|
750
|
+
* domain previews. Preview operations do not persist records, but they must
|
|
751
|
+
* still be authorized through the host before invoking domain logic.
|
|
752
|
+
*/
|
|
753
|
+
protected authorizeOperation(principal: PluginPrincipal, operation: string, input: unknown, current?: S): Promise<void>;
|
|
754
|
+
protected currentTime(): Date;
|
|
755
|
+
private excluded;
|
|
756
|
+
private decode;
|
|
757
|
+
private load;
|
|
758
|
+
private matches;
|
|
759
|
+
/** Read all authorized records for plugin-owned reports; providers must support keyset paging. */
|
|
760
|
+
protected readAllAuthorized(principal: PluginPrincipal, operation: string, input: unknown, accept: (value: S) => boolean): Promise<S[]>;
|
|
761
|
+
private readAllFromStore;
|
|
762
|
+
private reserveUnique;
|
|
763
|
+
/**
|
|
764
|
+
* Dispatches one admitted record operation and optionally joins it to durable command/audit receipt handling.
|
|
765
|
+
* @param principal - Verified current tenant/user principal; host authorization is rechecked throughout the operation.
|
|
766
|
+
* @param operation - Declared list/get/create/update/archive or plugin custom reducer key.
|
|
767
|
+
* @param input - Operation-schema input; mutations require matching record revision and optional durable commandId when declared.
|
|
768
|
+
* @returns List operations return the configured listKey with scoped records and paging metadata; get/mutations return a decoded revisioned record. Paged results may be incomplete and carry nextCursor/mayHaveMore.
|
|
769
|
+
* @throws Rejects invalid principal (401), denied/revoked admission (403), schema/operation errors (400), missing/excluded record (404), stale revision/uniqueness/CAS conflict or missing required transactional capability (409), foreign/corrupt records, and propagated domain/store/clock/callback failures.
|
|
770
|
+
*
|
|
771
|
+
* @remarks
|
|
772
|
+
* Pagination scans at most 10000 rows per request, selecting authorized/filter-matching records. Without paging, filtering applies only to the bounded store result. Repository writes with declared commandId replay the stored identical result; other repository writes append audit. Recheck live resource permission before replay, and reload uncertain plain-store outcomes rather than retrying blindly.
|
|
773
|
+
*
|
|
774
|
+
* @example
|
|
775
|
+
* ```typescript
|
|
776
|
+
* import { ScopedRecordService, type PluginPrincipal } from '@alneas/eaos-server/plugin-data';
|
|
777
|
+
* export function dispatch<T extends {tenantId: string; id: string}, S extends T & {revision: number}>(service: ScopedRecordService<T, S>, principal: PluginPrincipal, operation: string, input: unknown) { return service.execute(principal, operation, input); }
|
|
778
|
+
* ```
|
|
779
|
+
*/
|
|
780
|
+
execute(principal: PluginPrincipal, operation: string, input: unknown): Promise<unknown>;
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
/**
|
|
784
|
+
* Minimal verified-principal operation dispatch contract shared by bounded composite services.
|
|
785
|
+
*
|
|
786
|
+
* @see createCompositePluginService for canonical host integration.
|
|
787
|
+
*/
|
|
788
|
+
interface PluginOperationService {
|
|
789
|
+
/**
|
|
790
|
+
* Executes one service-owned operation using host-verified identity and operation input.
|
|
791
|
+
* @param principal - Verified current tenant principal.
|
|
792
|
+
* @param operation - Declared service operation name.
|
|
793
|
+
* @param input - Operation input whose schema/permission must be checked by the owning service.
|
|
794
|
+
* @returns The owner's operation result; no composite layer adds authentication or transactions.
|
|
795
|
+
* @throws Rejects owning-service schema, authorization, persistence or domain failures.
|
|
796
|
+
|
|
797
|
+
* @example
|
|
798
|
+
* ```typescript
|
|
799
|
+
* import type { PluginOperationService, PluginPrincipal } from '@alneas/eaos-server/plugin-data';
|
|
800
|
+
* export async function executeAdmitted(service: PluginOperationService, principal: PluginPrincipal, operation: string, input: unknown) {
|
|
801
|
+
* // The owning service validates input and live resource permission.
|
|
802
|
+
* return service.execute(principal, operation, input);
|
|
803
|
+
* }
|
|
804
|
+
* ```
|
|
805
|
+
*/
|
|
806
|
+
execute(principal: PluginPrincipal, operation: string, input: unknown): Promise<unknown>;
|
|
807
|
+
}
|
|
808
|
+
/**
|
|
809
|
+
* Route explicitly owned operations to their bounded service instances.
|
|
810
|
+
* @param services - Trusted service instances keyed by owner name.
|
|
811
|
+
* @param operationOwners - Explicit operation-to-owner mapping copied at construction.
|
|
812
|
+
* @returns A principal-aware execute service forwarding to the declared owner.
|
|
813
|
+
* @throws Unknown declared owners throw at construction; unknown operations reject with PluginError 400 and owner errors propagate.
|
|
814
|
+
* @remarks Does not authenticate principals or add authorization/transactions; each owner service retains its actual boundaries.
|
|
815
|
+
* @example
|
|
816
|
+
* import { createCompositePluginService } from '@alneas/eaos-server/plugin-data'
|
|
817
|
+
* export function composite(services: Parameters<typeof createCompositePluginService>[0]) { return createCompositePluginService(services, { list: 'records' }) }
|
|
818
|
+
*/
|
|
819
|
+
declare function createCompositePluginService(services: Readonly<Record<string, PluginOperationService>>, operationOwners: Readonly<Record<string, string>>): PluginOperationService;
|
|
820
|
+
|
|
821
|
+
/**
|
|
822
|
+
* Apply canonical document validation to every existing host persistence path while retaining other host methods.
|
|
823
|
+
* @param host - Host with optional record store, repository and/or transaction callback.
|
|
824
|
+
* @param documents - Trusted canonical JSON document definitions.
|
|
825
|
+
* @typeParam T - Stored JSON payload shape.
|
|
826
|
+
* @typeParam H - Concrete host shape whose existing methods and persistence capabilities are retained.
|
|
827
|
+
* @returns A proxy with wrapped persistence capabilities and other functions bound to the original host.
|
|
828
|
+
* @throws Invalid document contracts throw during wrapper creation; subsequent validation and underlying host failures propagate.
|
|
829
|
+
* @remarks Does not replace transaction ownership or live authorization. Inputs are copied for validation; unrelated host methods keep their original receiver.
|
|
830
|
+
* @example
|
|
831
|
+
* import { createValidatedRecordHost } from '@alneas/eaos-server/plugin-data'
|
|
832
|
+
* export function validated<T>(host: Parameters<typeof createValidatedRecordHost<T, { store?: import('@alneas/eaos-server/plugin-data').PluginRecordStore<T> }>>[0], documents: Parameters<typeof createValidatedRecordHost>[1]) { return createValidatedRecordHost(host, documents) }
|
|
833
|
+
*/
|
|
834
|
+
declare function createValidatedRecordHost<T, H extends {
|
|
835
|
+
/**
|
|
836
|
+
* Optional existing tenant/CAS store wrapped with canonical payload checks.
|
|
837
|
+
*/
|
|
838
|
+
store?: PluginRecordStore<T>;
|
|
839
|
+
/**
|
|
840
|
+
* Optional existing atomic repository wrapped without adding a second transaction.
|
|
841
|
+
*/
|
|
842
|
+
repository?: AtomicRepository;
|
|
843
|
+
/**
|
|
844
|
+
* Optional real aggregate transaction; its callback receives a validated connection-bound store.
|
|
845
|
+
|
|
846
|
+
* @param principal - Verified current principal.
|
|
847
|
+
* @param work - Async service work on the validated connection-bound store.
|
|
848
|
+
* @typeParam R - Callback result resolved by the host transaction.
|
|
849
|
+
* @returns The callback result after host commit; underlying transaction/rejection semantics are preserved.
|
|
850
|
+
* @throws Callback failures propagate to the owning operation; transactional writes roll back when the host boundary rejects.
|
|
851
|
+
*/
|
|
852
|
+
transaction?: <R>(principal: PluginPrincipal, work: (store: PluginRecordStore<T>) => Promise<R>) => Promise<R>;
|
|
853
|
+
}>(host: H, documents: readonly JsonDocumentContract[]): H;
|
|
854
|
+
/**
|
|
855
|
+
* Resolve canonical payload document contracts for one verified Data Contract table/namespace binding.
|
|
856
|
+
* @param catalog - Trusted resolved Data Contract catalog.
|
|
857
|
+
* @param binding - Contract identity, table, namespace and optional declared document IDs.
|
|
858
|
+
* @returns All matching payload document contracts for the bound table/namespace, possibly empty.
|
|
859
|
+
* @throws Rejects missing/mismatched bindings, a table without id/revision/payload envelope fields or unavailable/duplicate requested document IDs.
|
|
860
|
+
* @remarks Validates requested document selection but returns every matching namespace document, not only the requested-ID subset.
|
|
861
|
+
* @example
|
|
862
|
+
* import { recordDocuments } from '@alneas/eaos-server/plugin-data'
|
|
863
|
+
* export function documents(catalog: Parameters<typeof recordDocuments>[0], binding: Parameters<typeof recordDocuments>[1]) { return recordDocuments(catalog, binding) }
|
|
864
|
+
*/
|
|
865
|
+
declare function recordDocuments(catalog: DataContractCatalog, binding: DataContractBinding & {
|
|
866
|
+
/**
|
|
867
|
+
* Optional explicit nonempty unique document IDs to verify against the bound namespace; all matching namespace documents are returned.
|
|
868
|
+
*/
|
|
869
|
+
jsonDocuments?: readonly string[];
|
|
870
|
+
}): JsonDocumentContract[];
|
|
871
|
+
/**
|
|
872
|
+
* Compile closed payload schemas and route records by longest canonical prefix without coercion or remote loading.
|
|
873
|
+
* @param documents - Nonempty trusted document list; each binds column payload to a closed object schema.
|
|
874
|
+
* @returns A synchronous (tenantId, record) assertion that accepts only matching identity, revision, immutability and schema.
|
|
875
|
+
* @throws Rejects absent/open/ambiguous contracts at construction; assertions reject invalid IDs/revisions, unmatched routes, immutable replacements, schema or embedded-tenant mismatch.
|
|
876
|
+
* @remarks Does not write records or prove live authorization; document definitions are cloned before compilation.
|
|
877
|
+
* @example
|
|
878
|
+
* import { createRecordDocumentValidator } from '@alneas/eaos-server/plugin-data'
|
|
879
|
+
* export function validator(documents: Parameters<typeof createRecordDocumentValidator>[0]) { return createRecordDocumentValidator(documents) }
|
|
880
|
+
*/
|
|
881
|
+
declare function createRecordDocumentValidator(documents: readonly JsonDocumentContract[]): (tenantId: string, record: PluginRecord<unknown>) => void;
|
|
882
|
+
/**
|
|
883
|
+
* Validate canonical documents on host-store reads and writes while retaining its transaction semantics.
|
|
884
|
+
* @param store - Existing host record store with real tenant/CAS behavior.
|
|
885
|
+
* @param documents - Trusted canonical payload contracts to clone and enforce.
|
|
886
|
+
* @typeParam T - JSON payload shape retained by the wrapped store.
|
|
887
|
+
* @returns A wrapped store retaining optional listPage/delete capabilities when supplied.
|
|
888
|
+
* @throws Invalid contracts throw at creation; operations reject mismatched IDs, invalid revision transitions/payloads and immutable deletion, with underlying errors propagated.
|
|
889
|
+
* @remarks Does not add a transaction or independent authorization. Host returned list rows must still be correctly tenant-scoped.
|
|
890
|
+
* @example
|
|
891
|
+
* import { createValidatedRecordStore } from '@alneas/eaos-server/plugin-data'
|
|
892
|
+
* export function store<T>(store: Parameters<typeof createValidatedRecordStore<T>>[0], documents: Parameters<typeof createValidatedRecordStore>[1]) { return createValidatedRecordStore(store, documents) }
|
|
893
|
+
*/
|
|
894
|
+
declare function createValidatedRecordStore<T>(store: PluginRecordStore<T>, documents: readonly JsonDocumentContract[]): PluginRecordStore<T>;
|
|
895
|
+
/**
|
|
896
|
+
* Validate canonical document payloads inside the host repository's existing commit boundary.
|
|
897
|
+
* @param repository - Real tenant-scoped atomic repository.
|
|
898
|
+
* @param documents - Trusted canonical payload contracts copied for validation.
|
|
899
|
+
* @returns A repository with validating, expiring sessions and retained joined-SQL capability bindings.
|
|
900
|
+
* @throws Invalid contracts throw; work rejects wrong IDs/revisions/scopes, invalid batch order/length, expired sessions or payload/underlying repository failures.
|
|
901
|
+
* @remarks Does not open a second transaction or authorize operations. Wrapper capabilities expire after the work callback and are removed in finally.
|
|
902
|
+
* @example
|
|
903
|
+
* import { createValidatedAtomicRepository } from '@alneas/eaos-server/plugin-data'
|
|
904
|
+
* export function repository(repository: Parameters<typeof createValidatedAtomicRepository>[0], documents: Parameters<typeof createValidatedAtomicRepository>[1]) { return createValidatedAtomicRepository(repository, documents) }
|
|
905
|
+
*/
|
|
906
|
+
declare function createValidatedAtomicRepository(repository: AtomicRepository, documents: readonly JsonDocumentContract[]): AtomicRepository;
|
|
907
|
+
|
|
908
|
+
/**
|
|
909
|
+
* Pinned owning-document scope hash and admitted anchor/check IDs; authorization is supplied by its owner.
|
|
910
|
+
*
|
|
911
|
+
*
|
|
912
|
+
* The owning plugin authorizes and pins the document before entering this transaction.
|
|
913
|
+
* @see documentAnnotations for canonical host integration.
|
|
914
|
+
*/
|
|
915
|
+
interface AnnotationTarget {
|
|
916
|
+
/**
|
|
917
|
+
* Trusted 64-character document-scope hash pinned by the owning plugin.
|
|
918
|
+
*/
|
|
919
|
+
scope: string;
|
|
920
|
+
/**
|
|
921
|
+
* Exact anchor IDs valid for newly created reader comments.
|
|
922
|
+
*/
|
|
923
|
+
anchorIds: readonly string[];
|
|
924
|
+
/**
|
|
925
|
+
* Exact reading-check IDs admitted for this pinned document.
|
|
926
|
+
*/
|
|
927
|
+
checkIds: readonly string[];
|
|
928
|
+
}
|
|
929
|
+
/**
|
|
930
|
+
* Document-scoped reader comment with author-controlled resolution and private/shared visibility.
|
|
931
|
+
*
|
|
932
|
+
* @see documentAnnotations for canonical host integration.
|
|
933
|
+
*/
|
|
934
|
+
interface ReaderComment {
|
|
935
|
+
/**
|
|
936
|
+
* Generated comment UUID; physical storage also prefixes the pinned document and visibility scope.
|
|
937
|
+
*/
|
|
938
|
+
id: string;
|
|
939
|
+
/**
|
|
940
|
+
* Pinned valid document anchor, or null for a document-wide comment.
|
|
941
|
+
*/
|
|
942
|
+
anchorId: string | null;
|
|
943
|
+
/**
|
|
944
|
+
* Nonblank trimmed comment text; outer schema limits input to 4000 characters.
|
|
945
|
+
*/
|
|
946
|
+
body: string;
|
|
947
|
+
/**
|
|
948
|
+
* private scopes rows to the actor hash; shared scopes them to the authorized document audience.
|
|
949
|
+
*/
|
|
950
|
+
visibility: 'private' | 'shared';
|
|
951
|
+
/**
|
|
952
|
+
* Authenticated creator; only this actor may change resolution.
|
|
953
|
+
*/
|
|
954
|
+
authorId: string;
|
|
955
|
+
/**
|
|
956
|
+
* Trusted ISO timestamp supplied by the owning command.
|
|
957
|
+
*/
|
|
958
|
+
createdAt: string;
|
|
959
|
+
/**
|
|
960
|
+
* Author-controlled resolution flag, updated using the stored CAS revision.
|
|
961
|
+
*/
|
|
962
|
+
resolved: boolean;
|
|
963
|
+
}
|
|
964
|
+
/**
|
|
965
|
+
* Supported reader annotation operation names; this list itself grants no document access.
|
|
966
|
+
*
|
|
967
|
+
* @see documentAnnotations for canonical usage.
|
|
968
|
+
*/
|
|
969
|
+
declare const annotationOperations: readonly ["get_annotations", "set_check", "add_comment", "resolve_comment"];
|
|
970
|
+
/**
|
|
971
|
+
* Compose closed annotation operation schemas from the owning document's trusted target fields.
|
|
972
|
+
* @param target - Trusted JSON Schema property map for the owning document identity; those keys are required on every operation.
|
|
973
|
+
* @returns Schemas for get_annotations, set_check, add_comment and resolve_comment.
|
|
974
|
+
* @remarks Schema generation does not authorize or execute annotations; the owner validates input and pins the exact document before transaction work.
|
|
975
|
+
* @example
|
|
976
|
+
* import { annotationSchemas } from '@alneas/eaos-server/plugin-data'
|
|
977
|
+
* const schemas = annotationSchemas({ documentId: { type: 'string', minLength: 1 } })
|
|
978
|
+
*/
|
|
979
|
+
declare function annotationSchemas(target: Record<string, unknown>): {
|
|
980
|
+
get_annotations: {
|
|
981
|
+
type: string;
|
|
982
|
+
additionalProperties: boolean;
|
|
983
|
+
required: string[];
|
|
984
|
+
properties: {
|
|
985
|
+
[x: string]: unknown;
|
|
986
|
+
};
|
|
987
|
+
};
|
|
988
|
+
set_check: {
|
|
989
|
+
type: string;
|
|
990
|
+
additionalProperties: boolean;
|
|
991
|
+
required: string[];
|
|
992
|
+
properties: {
|
|
993
|
+
[x: string]: unknown;
|
|
994
|
+
};
|
|
995
|
+
};
|
|
996
|
+
add_comment: {
|
|
997
|
+
type: string;
|
|
998
|
+
additionalProperties: boolean;
|
|
999
|
+
required: string[];
|
|
1000
|
+
properties: {
|
|
1001
|
+
[x: string]: unknown;
|
|
1002
|
+
};
|
|
1003
|
+
};
|
|
1004
|
+
resolve_comment: {
|
|
1005
|
+
type: string;
|
|
1006
|
+
additionalProperties: boolean;
|
|
1007
|
+
required: string[];
|
|
1008
|
+
properties: {
|
|
1009
|
+
[x: string]: unknown;
|
|
1010
|
+
};
|
|
1011
|
+
};
|
|
1012
|
+
};
|
|
1013
|
+
/**
|
|
1014
|
+
* Read or mutate document checks/comments within an already authorized atomic document command.
|
|
1015
|
+
* @param tx - Live tenant-scoped atomic session inside the owner's atomicCommand.
|
|
1016
|
+
* @param p - Verified document reader principal.
|
|
1017
|
+
* @param target - Pinned document scope hash and its admitted anchor/check IDs.
|
|
1018
|
+
* @param operation - One of annotationOperations.
|
|
1019
|
+
* @param a - Input already validated against the selected annotation schema.
|
|
1020
|
+
* @param now - Trusted ISO timestamp used for newly created comments.
|
|
1021
|
+
* @returns Operation-specific checks, comment or page data with CAS revisions and optional scoped cursor.
|
|
1022
|
+
* @throws Rejects invalid scope/cursors, unknown checks/anchors/operations, comment ownership violations, missing comments, capacity or CAS conflicts.
|
|
1023
|
+
* @remarks Does not enforce the outer schema or own authorization/transaction/table creation. The owner must authorize the exact document and wrap write operations in atomicCommand; private/shared visibility is scoped by user and document hash.
|
|
1024
|
+
* @example
|
|
1025
|
+
* import { documentAnnotations } from '@alneas/eaos-server/plugin-data'
|
|
1026
|
+
* export function readComments(tx: Parameters<typeof documentAnnotations>[0], p: Parameters<typeof documentAnnotations>[1], target: Parameters<typeof documentAnnotations>[2], now: string) { return documentAnnotations(tx, p, target, 'get_annotations', { visibility: 'private' }, now) }
|
|
1027
|
+
*/
|
|
1028
|
+
declare function documentAnnotations(tx: AtomicSession, p: PluginPrincipal, target: AnnotationTarget, operation: string, a: Record<string, any>, now: string): Promise<{
|
|
1029
|
+
revision: number;
|
|
1030
|
+
canResolve: boolean;
|
|
1031
|
+
/**
|
|
1032
|
+
* Generated comment UUID; physical storage also prefixes the pinned document and visibility scope.
|
|
1033
|
+
*/
|
|
1034
|
+
id: string;
|
|
1035
|
+
/**
|
|
1036
|
+
* Pinned valid document anchor, or null for a document-wide comment.
|
|
1037
|
+
*/
|
|
1038
|
+
anchorId: string | null;
|
|
1039
|
+
/**
|
|
1040
|
+
* Nonblank trimmed comment text; outer schema limits input to 4000 characters.
|
|
1041
|
+
*/
|
|
1042
|
+
body: string;
|
|
1043
|
+
/**
|
|
1044
|
+
* private scopes rows to the actor hash; shared scopes them to the authorized document audience.
|
|
1045
|
+
*/
|
|
1046
|
+
visibility: "private" | "shared";
|
|
1047
|
+
/**
|
|
1048
|
+
* Authenticated creator; only this actor may change resolution.
|
|
1049
|
+
*/
|
|
1050
|
+
authorId: string;
|
|
1051
|
+
/**
|
|
1052
|
+
* Trusted ISO timestamp supplied by the owning command.
|
|
1053
|
+
*/
|
|
1054
|
+
createdAt: string;
|
|
1055
|
+
/**
|
|
1056
|
+
* Author-controlled resolution flag, updated using the stored CAS revision.
|
|
1057
|
+
*/
|
|
1058
|
+
resolved: boolean;
|
|
1059
|
+
} | {
|
|
1060
|
+
cursor?: string | undefined;
|
|
1061
|
+
checkIds: readonly string[];
|
|
1062
|
+
checks: Record<string, boolean>;
|
|
1063
|
+
revision: number;
|
|
1064
|
+
comments: {
|
|
1065
|
+
revision: number;
|
|
1066
|
+
canResolve: boolean;
|
|
1067
|
+
/**
|
|
1068
|
+
* Generated comment UUID; physical storage also prefixes the pinned document and visibility scope.
|
|
1069
|
+
*/
|
|
1070
|
+
id: string;
|
|
1071
|
+
/**
|
|
1072
|
+
* Pinned valid document anchor, or null for a document-wide comment.
|
|
1073
|
+
*/
|
|
1074
|
+
anchorId: string | null;
|
|
1075
|
+
/**
|
|
1076
|
+
* Nonblank trimmed comment text; outer schema limits input to 4000 characters.
|
|
1077
|
+
*/
|
|
1078
|
+
body: string;
|
|
1079
|
+
/**
|
|
1080
|
+
* private scopes rows to the actor hash; shared scopes them to the authorized document audience.
|
|
1081
|
+
*/
|
|
1082
|
+
visibility: "private" | "shared";
|
|
1083
|
+
/**
|
|
1084
|
+
* Authenticated creator; only this actor may change resolution.
|
|
1085
|
+
*/
|
|
1086
|
+
authorId: string;
|
|
1087
|
+
/**
|
|
1088
|
+
* Trusted ISO timestamp supplied by the owning command.
|
|
1089
|
+
*/
|
|
1090
|
+
createdAt: string;
|
|
1091
|
+
/**
|
|
1092
|
+
* Author-controlled resolution flag, updated using the stored CAS revision.
|
|
1093
|
+
*/
|
|
1094
|
+
resolved: boolean;
|
|
1095
|
+
}[];
|
|
1096
|
+
} | {
|
|
1097
|
+
checks: {
|
|
1098
|
+
[x: string]: boolean;
|
|
1099
|
+
};
|
|
1100
|
+
revision: number;
|
|
1101
|
+
}>;
|
|
1102
|
+
|
|
1103
|
+
/**
|
|
1104
|
+
* Immutable staged artifact identity, content hash and size returned by the host builder.
|
|
1105
|
+
*
|
|
1106
|
+
* @see ArtifactDeliveryService for canonical host integration.
|
|
1107
|
+
*/
|
|
1108
|
+
interface DeliveryArtifact {
|
|
1109
|
+
/**
|
|
1110
|
+
* Immutable host artifact key, at most 1000 characters.
|
|
1111
|
+
*/
|
|
1112
|
+
key: string;
|
|
1113
|
+
/**
|
|
1114
|
+
* Lowercase 64-character SHA-256 for the staged artifact.
|
|
1115
|
+
*/
|
|
1116
|
+
contentHash: string;
|
|
1117
|
+
/**
|
|
1118
|
+
* Positive safe-integer artifact size in bytes.
|
|
1119
|
+
*/
|
|
1120
|
+
bytes: number;
|
|
1121
|
+
}
|
|
1122
|
+
/**
|
|
1123
|
+
* Exact target/content/approval identity requested for one public channel delivery.
|
|
1124
|
+
*
|
|
1125
|
+
* @see ArtifactDeliveryService for canonical host integration.
|
|
1126
|
+
*/
|
|
1127
|
+
interface DeliveryRequest {
|
|
1128
|
+
/**
|
|
1129
|
+
* Stable delivery job identity within its tenant repository.
|
|
1130
|
+
*/
|
|
1131
|
+
jobId: string;
|
|
1132
|
+
/**
|
|
1133
|
+
* Host-defined publication channel serialized against other unfinished delivery work.
|
|
1134
|
+
*/
|
|
1135
|
+
channel: string;
|
|
1136
|
+
/**
|
|
1137
|
+
* publish stages an artifact; withdraw starts at activation/withdrawal without a build.
|
|
1138
|
+
*/
|
|
1139
|
+
kind: 'publish' | 'withdraw';
|
|
1140
|
+
/**
|
|
1141
|
+
* Exact host-owned public destination metadata bound to the approval request.
|
|
1142
|
+
*/
|
|
1143
|
+
target: Record<string, unknown>;
|
|
1144
|
+
/**
|
|
1145
|
+
* Reviewed source-content SHA-256; the host verifies exact target/hash/approval binding.
|
|
1146
|
+
*/
|
|
1147
|
+
contentHash: string;
|
|
1148
|
+
/**
|
|
1149
|
+
* Exact host approval request admitting this public delivery; reader access alone is insufficient.
|
|
1150
|
+
*/
|
|
1151
|
+
approvalRequestId: string;
|
|
1152
|
+
}
|
|
1153
|
+
/**
|
|
1154
|
+
* Durable delivery phase, worker ownership and retry state for one approved publication/withdrawal.
|
|
1155
|
+
*
|
|
1156
|
+
* @see ArtifactDeliveryService for canonical host integration.
|
|
1157
|
+
*/
|
|
1158
|
+
interface DeliveryJob extends DeliveryRequest {
|
|
1159
|
+
/**
|
|
1160
|
+
* Authenticated user who enqueued the approved request.
|
|
1161
|
+
*/
|
|
1162
|
+
requestedBy: string;
|
|
1163
|
+
/**
|
|
1164
|
+
* Trusted UTC ISO enqueue time.
|
|
1165
|
+
*/
|
|
1166
|
+
createdAt: string;
|
|
1167
|
+
/**
|
|
1168
|
+
* queued/running/failed/done/cancelled state retained with CAS revisions.
|
|
1169
|
+
*/
|
|
1170
|
+
state: 'queued' | 'running' | 'failed' | 'done' | 'cancelled';
|
|
1171
|
+
/**
|
|
1172
|
+
* Last durable build/activate/purge/cancel/done phase; uncertain external effects are retried idempotently.
|
|
1173
|
+
*/
|
|
1174
|
+
phase: 'build' | 'activate' | 'purge' | 'cancel' | 'done';
|
|
1175
|
+
/**
|
|
1176
|
+
* Number of worker claims; incremented when a new run owns the job.
|
|
1177
|
+
*/
|
|
1178
|
+
attempts: number;
|
|
1179
|
+
/**
|
|
1180
|
+
* Worker ownership token; recovery requires proving prior workers drained rather than waiting for expiry.
|
|
1181
|
+
*/
|
|
1182
|
+
token?: string;
|
|
1183
|
+
/**
|
|
1184
|
+
* Optional immutable build artifact used by the activation stage.
|
|
1185
|
+
*/
|
|
1186
|
+
artifact?: DeliveryArtifact;
|
|
1187
|
+
/**
|
|
1188
|
+
* Sanitized failure notice; sensitive host details remain in host-owned logs.
|
|
1189
|
+
*/
|
|
1190
|
+
error?: string;
|
|
1191
|
+
}
|
|
1192
|
+
/**
|
|
1193
|
+
* Host publication approval, immutable artifact and idempotent external delivery capabilities.
|
|
1194
|
+
*
|
|
1195
|
+
* @see ArtifactDeliveryService for canonical host integration.
|
|
1196
|
+
*/
|
|
1197
|
+
interface DeliveryPorts {
|
|
1198
|
+
/**
|
|
1199
|
+
* Verify public publication/withdrawal approval for the exact target and content.
|
|
1200
|
+
*
|
|
1201
|
+
* Verify explicit PUBLIC publication (or withdrawal) permission, exact target/hash and approval. Ordinary reader access is insufficient.
|
|
1202
|
+
* @param p - Verified principal requiring explicit public publication/withdrawal permission.
|
|
1203
|
+
* @param job - Pinned request/job with exact approved target/contentHash/approvalRequestId.
|
|
1204
|
+
* @returns Exactly true only when public permission and exact binding/approval remain valid.
|
|
1205
|
+
* @throws Rejects host permission, artifact, delivery or worker-control failures; external effects may already be partially complete.
|
|
1206
|
+
|
|
1207
|
+
* @example
|
|
1208
|
+
* ```typescript
|
|
1209
|
+
* import type { DeliveryPorts, DeliveryRequest, PluginPrincipal } from '@alneas/eaos-server/plugin-data';
|
|
1210
|
+
* export async function verifyReviewed(ports: DeliveryPorts, principal: PluginPrincipal, job: DeliveryRequest) {
|
|
1211
|
+
* // The host binds permission and external effects to this exact job.
|
|
1212
|
+
* return ports.verify(principal, job);
|
|
1213
|
+
* }
|
|
1214
|
+
* ```
|
|
1215
|
+
*/
|
|
1216
|
+
verify(p: PluginPrincipal, job: DeliveryRequest): Promise<boolean>;
|
|
1217
|
+
/**
|
|
1218
|
+
* Build and stage an immutable artifact outside the database transaction.
|
|
1219
|
+
*
|
|
1220
|
+
* Build and stage an immutable artifact outside a DB transaction. Must be idempotent for jobId.
|
|
1221
|
+
* @param p - Verified current principal.
|
|
1222
|
+
* @param job - Durable job carrying the stable jobId idempotency identity.
|
|
1223
|
+
* @returns An immutable staged artifact key, lowercase hash and positive safe byte size.
|
|
1224
|
+
* @throws Rejects host permission, artifact, delivery or worker-control failures; external effects may already be partially complete.
|
|
1225
|
+
|
|
1226
|
+
* @example
|
|
1227
|
+
* ```typescript
|
|
1228
|
+
* import type { DeliveryPorts, DeliveryJob, PluginPrincipal } from '@alneas/eaos-server/plugin-data';
|
|
1229
|
+
* export async function buildReviewed(ports: DeliveryPorts, principal: PluginPrincipal, job: DeliveryJob) {
|
|
1230
|
+
* // The host binds permission and external effects to this exact job.
|
|
1231
|
+
* return ports.build(principal, job);
|
|
1232
|
+
* }
|
|
1233
|
+
* ```
|
|
1234
|
+
*/
|
|
1235
|
+
build(p: PluginPrincipal, job: DeliveryJob): Promise<DeliveryArtifact>;
|
|
1236
|
+
/**
|
|
1237
|
+
* Apply or withdraw the exact public channel version idempotently.
|
|
1238
|
+
*
|
|
1239
|
+
* Atomic, idempotent channel update/withdrawal. Serialize with other host publishers; key=jobId.
|
|
1240
|
+
* @param p - Verified current principal.
|
|
1241
|
+
* @param job - Exact pinned publish/withdraw job, including staged artifact when publishing.
|
|
1242
|
+
* @returns Resolves without a value after the idempotent channel switch/withdrawal.
|
|
1243
|
+
* @throws Rejects host permission, artifact, delivery or worker-control failures; external effects may already be partially complete.
|
|
1244
|
+
|
|
1245
|
+
* @example
|
|
1246
|
+
* ```typescript
|
|
1247
|
+
* import type { DeliveryPorts, DeliveryJob, PluginPrincipal } from '@alneas/eaos-server/plugin-data';
|
|
1248
|
+
* export async function activateReviewed(ports: DeliveryPorts, principal: PluginPrincipal, job: DeliveryJob) {
|
|
1249
|
+
* // The host binds permission and external effects to this exact job.
|
|
1250
|
+
* await ports.activate(principal, job);
|
|
1251
|
+
* }
|
|
1252
|
+
* ```
|
|
1253
|
+
*/
|
|
1254
|
+
activate(p: PluginPrincipal, job: DeliveryJob): Promise<void>;
|
|
1255
|
+
/**
|
|
1256
|
+
* Invalidate the delivered channel idempotently before recording completion.
|
|
1257
|
+
*
|
|
1258
|
+
* Idempotent CDN invalidation; completion is recorded only after success.
|
|
1259
|
+
* @param p - Verified current principal.
|
|
1260
|
+
* @param job - Exact job channel/version requiring invalidation.
|
|
1261
|
+
* @returns Resolves without a value only after actual idempotent invalidation succeeds.
|
|
1262
|
+
* @throws Rejects host permission, artifact, delivery or worker-control failures; external effects may already be partially complete.
|
|
1263
|
+
|
|
1264
|
+
* @example
|
|
1265
|
+
* ```typescript
|
|
1266
|
+
* import type { DeliveryPorts, DeliveryJob, PluginPrincipal } from '@alneas/eaos-server/plugin-data';
|
|
1267
|
+
* export async function purgeReviewed(ports: DeliveryPorts, principal: PluginPrincipal, job: DeliveryJob) {
|
|
1268
|
+
* // The host binds permission and external effects to this exact job.
|
|
1269
|
+
* await ports.purge(principal, job);
|
|
1270
|
+
* }
|
|
1271
|
+
* ```
|
|
1272
|
+
*/
|
|
1273
|
+
purge(p: PluginPrincipal, job: DeliveryJob): Promise<void>;
|
|
1274
|
+
/**
|
|
1275
|
+
* Reconcile uncertain job effects and purge only this job's owned version.
|
|
1276
|
+
*
|
|
1277
|
+
* Reconcile any uncertain activation for this job and purge it, idempotently. Never remove a newer publisher's version.
|
|
1278
|
+
* @param p - Verified current principal admitted for cancellation.
|
|
1279
|
+
* @param job - Pinned job whose uncertain effects need reconciliation.
|
|
1280
|
+
* @returns Resolves without a value after idempotent reconciliation/purge of only this owned version; never remove newer publications.
|
|
1281
|
+
* @throws Rejects host permission, artifact, delivery or worker-control failures; external effects may already be partially complete.
|
|
1282
|
+
|
|
1283
|
+
* @example
|
|
1284
|
+
* ```typescript
|
|
1285
|
+
* import type { DeliveryPorts, DeliveryJob, PluginPrincipal } from '@alneas/eaos-server/plugin-data';
|
|
1286
|
+
* export async function cancelReviewed(ports: DeliveryPorts, principal: PluginPrincipal, job: DeliveryJob) {
|
|
1287
|
+
* if (!ports.cancel) throw new Error("Required recovery port unavailable");
|
|
1288
|
+
* // The host binds permission and external effects to this exact job.
|
|
1289
|
+
* await ports.cancel(principal, job);
|
|
1290
|
+
* }
|
|
1291
|
+
* ```
|
|
1292
|
+
*/
|
|
1293
|
+
cancel?(p: PluginPrincipal, job: DeliveryJob): Promise<void>;
|
|
1294
|
+
/**
|
|
1295
|
+
* Prove prior workers for this job token can no longer perform effects.
|
|
1296
|
+
* @param p - Verified principal admitted for recovery.
|
|
1297
|
+
* @param job - Exact running job revision/token whose prior workers must be stopped.
|
|
1298
|
+
* @returns Exactly true only when prior workers cannot perform further effects; false/absence prevents recovery.
|
|
1299
|
+
* @throws Rejects host permission, artifact, delivery or worker-control failures; external effects may already be partially complete.
|
|
1300
|
+
|
|
1301
|
+
* @example
|
|
1302
|
+
* ```typescript
|
|
1303
|
+
* import type { DeliveryPorts, DeliveryJob, PluginPrincipal } from '@alneas/eaos-server/plugin-data';
|
|
1304
|
+
* export async function drainedReviewed(ports: DeliveryPorts, principal: PluginPrincipal, job: DeliveryJob) {
|
|
1305
|
+
* if (!ports.drained) throw new Error("Required recovery port unavailable");
|
|
1306
|
+
* // The host binds permission and external effects to this exact job.
|
|
1307
|
+
* return ports.drained(principal, job);
|
|
1308
|
+
* }
|
|
1309
|
+
* ```
|
|
1310
|
+
*/
|
|
1311
|
+
drained?(p: PluginPrincipal, job: DeliveryJob): Promise<boolean>;
|
|
1312
|
+
}
|
|
1313
|
+
/**
|
|
1314
|
+
* Supported durable delivery command names; each requires live host resource/publication authorization.
|
|
1315
|
+
*
|
|
1316
|
+
* @see ArtifactDeliveryService for canonical usage.
|
|
1317
|
+
*/
|
|
1318
|
+
declare const deliveryOperations: readonly ["enqueue_delivery", "get_delivery", "run_delivery", "recover_delivery", "cancel_delivery"];
|
|
1319
|
+
/**
|
|
1320
|
+
* Closed schema for a new approved delivery request with stable command/job/target/content identities.
|
|
1321
|
+
*
|
|
1322
|
+
* @see ArtifactDeliveryService for canonical usage.
|
|
1323
|
+
*/
|
|
1324
|
+
declare const enqueueDeliverySchema: {
|
|
1325
|
+
type: string;
|
|
1326
|
+
additionalProperties: boolean;
|
|
1327
|
+
required: string[];
|
|
1328
|
+
properties: {
|
|
1329
|
+
commandId: {
|
|
1330
|
+
type: string;
|
|
1331
|
+
pattern: string;
|
|
1332
|
+
};
|
|
1333
|
+
jobId: {
|
|
1334
|
+
type: string;
|
|
1335
|
+
pattern: string;
|
|
1336
|
+
};
|
|
1337
|
+
channel: {
|
|
1338
|
+
type: string;
|
|
1339
|
+
pattern: string;
|
|
1340
|
+
};
|
|
1341
|
+
kind: {
|
|
1342
|
+
enum: string[];
|
|
1343
|
+
};
|
|
1344
|
+
target: {
|
|
1345
|
+
type: string;
|
|
1346
|
+
maxProperties: number;
|
|
1347
|
+
additionalProperties: boolean;
|
|
1348
|
+
};
|
|
1349
|
+
contentHash: {
|
|
1350
|
+
type: string;
|
|
1351
|
+
pattern: string;
|
|
1352
|
+
};
|
|
1353
|
+
approvalRequestId: {
|
|
1354
|
+
type: string;
|
|
1355
|
+
pattern: string;
|
|
1356
|
+
};
|
|
1357
|
+
};
|
|
1358
|
+
};
|
|
1359
|
+
/**
|
|
1360
|
+
* Closed schema selecting an existing delivery job by its stable identifier.
|
|
1361
|
+
*
|
|
1362
|
+
* @see ArtifactDeliveryService for canonical usage.
|
|
1363
|
+
*/
|
|
1364
|
+
declare const deliveryJobSchema: {
|
|
1365
|
+
type: string;
|
|
1366
|
+
additionalProperties: boolean;
|
|
1367
|
+
required: string[];
|
|
1368
|
+
properties: {
|
|
1369
|
+
jobId: {
|
|
1370
|
+
type: string;
|
|
1371
|
+
pattern: string;
|
|
1372
|
+
};
|
|
1373
|
+
};
|
|
1374
|
+
};
|
|
1375
|
+
/**
|
|
1376
|
+
* Closed schema requiring the exact job revision for explicit drained-worker recovery.
|
|
1377
|
+
*
|
|
1378
|
+
* @see ArtifactDeliveryService for canonical usage.
|
|
1379
|
+
*/
|
|
1380
|
+
declare const recoverDeliverySchema: {
|
|
1381
|
+
type: string;
|
|
1382
|
+
additionalProperties: boolean;
|
|
1383
|
+
required: string[];
|
|
1384
|
+
properties: {
|
|
1385
|
+
jobId: {
|
|
1386
|
+
type: string;
|
|
1387
|
+
pattern: string;
|
|
1388
|
+
};
|
|
1389
|
+
revision: {
|
|
1390
|
+
type: string;
|
|
1391
|
+
minimum: number;
|
|
1392
|
+
maximum: number;
|
|
1393
|
+
};
|
|
1394
|
+
};
|
|
1395
|
+
};
|
|
1396
|
+
/**
|
|
1397
|
+
* Coordinates durable approved publication/withdrawal jobs with channel ownership and resumable idempotent host effects.
|
|
1398
|
+
*
|
|
1399
|
+
* @remarks
|
|
1400
|
+
* Requires a real atomic repository and host public-approval/build/channel/purge ports. Channel locks serialize unfinished jobs per tenant/repository. External build/activate/purge/cancel run outside database transactions; a failed reply can follow a completed external effect. Ports must deduplicate by stable jobId. Recovery requires proof that previous workers drained, never an elapsed lease alone.
|
|
1401
|
+
*
|
|
1402
|
+
* @example
|
|
1403
|
+
* ```typescript
|
|
1404
|
+
* import { ArtifactDeliveryService } from '@alneas/eaos-server/plugin-data';
|
|
1405
|
+
* export function connectDelivery(options: ConstructorParameters<typeof ArtifactDeliveryService>[0]) { return new ArtifactDeliveryService(options); }
|
|
1406
|
+
* ```
|
|
1407
|
+
*/
|
|
1408
|
+
declare class ArtifactDeliveryService {
|
|
1409
|
+
private readonly options;
|
|
1410
|
+
/**
|
|
1411
|
+
* Binds the host atomic delivery ledger, public publication ports and live operation authorization.
|
|
1412
|
+
* @param options - Real atomic repository, idempotent host delivery ports and current operation/resource authorization; construction does not validate or execute those ports.
|
|
1413
|
+
*
|
|
1414
|
+
* @example
|
|
1415
|
+
* ```typescript
|
|
1416
|
+
* import { ArtifactDeliveryService } from '@alneas/eaos-server/plugin-data';
|
|
1417
|
+
* export function connectDelivery(options: ConstructorParameters<typeof ArtifactDeliveryService>[0]) { return new ArtifactDeliveryService(options); }
|
|
1418
|
+
* ```
|
|
1419
|
+
*/
|
|
1420
|
+
constructor(options: {
|
|
1421
|
+
/**
|
|
1422
|
+
* Real atomic delivery ledger used for jobs, channel ownership and enqueue command receipts.
|
|
1423
|
+
*/
|
|
1424
|
+
repository: AtomicRepository;
|
|
1425
|
+
/**
|
|
1426
|
+
* Host public-approval, artifact, channel, purge and recovery adapters with stable jobId idempotency.
|
|
1427
|
+
*/
|
|
1428
|
+
ports: DeliveryPorts;
|
|
1429
|
+
/**
|
|
1430
|
+
* Live operation/resource permission callback; exactly true admits, false denies; schema validation follows initial admission.
|
|
1431
|
+
* @param p - Verified current tenant/user principal.
|
|
1432
|
+
* @param operation - Declared operation name.
|
|
1433
|
+
* @param input - Operation input to validate and authorize at the owning service boundary.
|
|
1434
|
+
* @param resource - Optional current delivery job/resource when available.
|
|
1435
|
+
* @returns Exactly true to admit the current operation; false denies.
|
|
1436
|
+
* @throws Rejects underlying service, authorization or persistence failures.
|
|
1437
|
+
|
|
1438
|
+
* @example
|
|
1439
|
+
* ```typescript
|
|
1440
|
+
* import type { ArtifactDeliveryService, PluginPrincipal } from '@alneas/eaos-server/plugin-data';
|
|
1441
|
+
* export async function canEnqueue(options: ConstructorParameters<typeof ArtifactDeliveryService>[0], principal: PluginPrincipal, input: unknown) {
|
|
1442
|
+
* return await options.authorize(principal, "enqueue_delivery", input) === true;
|
|
1443
|
+
* }
|
|
1444
|
+
* ```
|
|
1445
|
+
*/
|
|
1446
|
+
authorize(p: PluginPrincipal, operation: string, input: unknown, resource?: unknown): Promise<boolean>;
|
|
1447
|
+
});
|
|
1448
|
+
private allow;
|
|
1449
|
+
private verify;
|
|
1450
|
+
/**
|
|
1451
|
+
* Enqueues, reads, runs, cancels or explicitly recovers one durable approved delivery job.
|
|
1452
|
+
* @param p - Verified current tenant principal; operation/resource admission is rechecked before transitions.
|
|
1453
|
+
* @param op - One of deliveryOperations; each input is checked by its closed schema.
|
|
1454
|
+
* @param a - jobId for every operation; enqueue additionally needs commandId/channel/kind/target/contentHash/approvalRequestId, and recovery needs the exact running job revision.
|
|
1455
|
+
* @returns The durable AtomicRow<DeliveryJob>, possibly an existing identical enqueue receipt or already terminal job; query get_delivery for current state after receipt replay.
|
|
1456
|
+
* @throws Rejects invalid principal/input (401/400), denied live/public approval (403), absent job (404), busy channel/worker, stale recovery or unavailable cancellation port (409), invalid built artifact and propagated repository/port failures; effects may already have occurred.
|
|
1457
|
+
*
|
|
1458
|
+
* @remarks
|
|
1459
|
+
* Publish starts at build, withdrawal at activate; completion follows successful purge. Cancellation requires a reconciliation port and never removes a newer host version. Completed jobs require a new withdrawal job instead of cancellation. Recovery requires exact revision and drained(old token), marks failed and clears ownership for retry. Failure retains the last durable phase and a sanitized error, while the original host error may reject the call.
|
|
1460
|
+
*
|
|
1461
|
+
* @example
|
|
1462
|
+
* ```typescript
|
|
1463
|
+
* import { ArtifactDeliveryService, type PluginPrincipal } from '@alneas/eaos-server/plugin-data';
|
|
1464
|
+
* export function readDelivery(service: ArtifactDeliveryService, principal: PluginPrincipal, jobId: string) { return service.execute(principal, 'get_delivery', { jobId }); }
|
|
1465
|
+
* ```
|
|
1466
|
+
*/
|
|
1467
|
+
execute(p: PluginPrincipal, op: string, a: {
|
|
1468
|
+
/**
|
|
1469
|
+
* Stable job ID required by every delivery operation; 1–80 letters/digits/underscore/hyphen characters.
|
|
1470
|
+
*/
|
|
1471
|
+
jobId: string;
|
|
1472
|
+
/**
|
|
1473
|
+
* Exact current positive running-job revision required only for explicit drained-worker recovery.
|
|
1474
|
+
*/
|
|
1475
|
+
revision?: number;
|
|
1476
|
+
/**
|
|
1477
|
+
* Stable enqueue idempotency ID; identical input replays the original receipt and conflicting reuse rejects.
|
|
1478
|
+
*/
|
|
1479
|
+
commandId?: string;
|
|
1480
|
+
} & Partial<DeliveryRequest>): Promise<any>;
|
|
1481
|
+
}
|
|
1482
|
+
|
|
1483
|
+
/**
|
|
1484
|
+
* Bind a service under the trusted context symbol for copied static MCP tool definitions.
|
|
1485
|
+
* @param service - Host-created service instance used by each copied tool handler.
|
|
1486
|
+
* @param tools - Static tool definitions whose handlers consume the service context symbol.
|
|
1487
|
+
* @param key - Trusted symbol agreed by the binder and operation handler.
|
|
1488
|
+
* @typeParam TService - Concrete host-created service type retained in the symbol binding.
|
|
1489
|
+
* @returns New tool objects with wrappers that preserve other context fields and override the service symbol.
|
|
1490
|
+
* @remarks Does not resolve identity or grant permission. Tool execution still requires verified principal context and live host admission.
|
|
1491
|
+
* @example
|
|
1492
|
+
* import { createMcpToolBinder } from '@alneas/eaos-server/plugin-data'
|
|
1493
|
+
* export function bindTools<T>(service: T, tools: Parameters<typeof createMcpToolBinder>[1], key: symbol) { return createMcpToolBinder(service, tools, key) }
|
|
1494
|
+
*/
|
|
1495
|
+
declare function createMcpToolBinder<TService>(service: TService, tools: readonly _alneas_eaos_core_plugin_sdk.McpToolDefinition[], key: symbol): _alneas_eaos_core_plugin_sdk.McpToolDefinition[];
|
|
1496
|
+
/**
|
|
1497
|
+
* Create a static operation handler that dispatches through a host-bound service instance.
|
|
1498
|
+
* @param operation - Trusted operation name selected by the manifest author.
|
|
1499
|
+
* @param key - Service-binding symbol used by createMcpToolBinder.
|
|
1500
|
+
* @typeParam TService - Host service exposing the principal-aware execute contract.
|
|
1501
|
+
* @returns An async handler accepting tool arguments and trusted principal/service context.
|
|
1502
|
+
* @throws The returned handler rejects when the service is absent or has no execute method; service failures propagate.
|
|
1503
|
+
* @remarks The incoming context must already contain a verified PluginPrincipal. This helper neither authenticates a request nor verifies live resource access.
|
|
1504
|
+
* @example
|
|
1505
|
+
* import { createMcpOperationHandler } from '@alneas/eaos-server/plugin-data'
|
|
1506
|
+
* const key = Symbol('service')
|
|
1507
|
+
* const handler = createMcpOperationHandler('list', key)
|
|
1508
|
+
*/
|
|
1509
|
+
declare function createMcpOperationHandler<TService extends {
|
|
1510
|
+
/**
|
|
1511
|
+
* Service operation dispatch contract; callers must supply host-verified principal context and perform live admission.
|
|
1512
|
+
* @param principal - Verified current tenant/user principal.
|
|
1513
|
+
* @param operation - Declared operation name.
|
|
1514
|
+
* @param input - Operation input to validate and authorize at the owning service boundary.
|
|
1515
|
+
* @returns The service operation result; authorization and validation stay owner-controlled.
|
|
1516
|
+
* @throws Rejects underlying service, authorization or persistence failures.
|
|
1517
|
+
*/
|
|
1518
|
+
execute(principal: PluginPrincipal, operation: string, input: unknown): Promise<unknown>;
|
|
1519
|
+
}>(operation: string, key: symbol): (args: unknown, context?: Record<PropertyKey, unknown>) => Promise<unknown>;
|
|
1520
|
+
/**
|
|
1521
|
+
* Structurally verified tenant/user identity supplied by a trusted host authentication boundary.
|
|
1522
|
+
*
|
|
1523
|
+
* @see createPluginRouter for canonical host integration.
|
|
1524
|
+
*/
|
|
1525
|
+
interface PluginPrincipal {
|
|
1526
|
+
/**
|
|
1527
|
+
* Tenant identity bound by the trusted principal; never selected as an authorization grant from request data.
|
|
1528
|
+
*/
|
|
1529
|
+
tenantId: string;
|
|
1530
|
+
/**
|
|
1531
|
+
* Authenticated actor identity supplied by the host.
|
|
1532
|
+
*/
|
|
1533
|
+
userId: string;
|
|
1534
|
+
/**
|
|
1535
|
+
* Current host-verified role names; structural validation alone does not grant permission.
|
|
1536
|
+
*/
|
|
1537
|
+
roles: readonly string[];
|
|
1538
|
+
}
|
|
1539
|
+
/**
|
|
1540
|
+
* Logical record identity, CAS revision and JSON payload envelope.
|
|
1541
|
+
* @typeParam T - Stored JSON payload shape; compile-time typing does not itself validate data.
|
|
1542
|
+
*
|
|
1543
|
+
* @see createSqlRecordStore for canonical host integration.
|
|
1544
|
+
*/
|
|
1545
|
+
interface PluginRecord<T> {
|
|
1546
|
+
/**
|
|
1547
|
+
* Logical tenant/namespace-scoped record identity.
|
|
1548
|
+
*/
|
|
1549
|
+
id: string;
|
|
1550
|
+
/**
|
|
1551
|
+
* CAS revision for the stored envelope; persisted records start at 1 unless a documented host projection uses 0.
|
|
1552
|
+
*/
|
|
1553
|
+
revision: number;
|
|
1554
|
+
/**
|
|
1555
|
+
* Stored JSON payload whose runtime validation depends on the configured document contracts.
|
|
1556
|
+
*/
|
|
1557
|
+
value: T;
|
|
1558
|
+
}
|
|
1559
|
+
/**
|
|
1560
|
+
* Host record persistence contract requiring tenant predicates and atomic revision-predicated writes.
|
|
1561
|
+
*
|
|
1562
|
+
* Providers must enforce tenant keys and atomic compare-and-swap, never read/update without the revision predicate.
|
|
1563
|
+
* @typeParam T - Stored payload shape shared by all scoped persistence operations.
|
|
1564
|
+
*
|
|
1565
|
+
* @see createSqlRecordStore for canonical host integration.
|
|
1566
|
+
*/
|
|
1567
|
+
interface PluginRecordStore<T> {
|
|
1568
|
+
/**
|
|
1569
|
+
* Reads one record within the exact tenant and logical namespace.
|
|
1570
|
+
* @param tenantId - Verified tenant ID supplied by the host.
|
|
1571
|
+
* @param id - Logical record ID within this store.
|
|
1572
|
+
* @returns The matching envelope or null when absent.
|
|
1573
|
+
* @throws Rejects propagated host persistence, validation or callback failures.
|
|
1574
|
+
|
|
1575
|
+
* @example
|
|
1576
|
+
* ```typescript
|
|
1577
|
+
* import type { PluginRecordStore, PluginPrincipal } from '@alneas/eaos-server/plugin-data';
|
|
1578
|
+
* export async function readTitle(store: PluginRecordStore<{ title: string }>, principal: PluginPrincipal, id: string) {
|
|
1579
|
+
* const record = await store.read(principal.tenantId, id);
|
|
1580
|
+
* return record?.value.title ?? null;
|
|
1581
|
+
* }
|
|
1582
|
+
* ```
|
|
1583
|
+
*/
|
|
1584
|
+
read(tenantId: string, id: string): Promise<PluginRecord<T> | null>;
|
|
1585
|
+
/**
|
|
1586
|
+
* Reads a bounded set of envelopes from one tenant and namespace.
|
|
1587
|
+
* @param tenantId - Verified tenant ID.
|
|
1588
|
+
* @param limit - Required provider-supported maximum row count; canonical SQL stores accept integers 1–100.
|
|
1589
|
+
* @returns Scoped envelopes, possibly empty; filtering this bounded set does not prove completeness.
|
|
1590
|
+
* @throws Rejects propagated host persistence, validation or callback failures.
|
|
1591
|
+
|
|
1592
|
+
* @example
|
|
1593
|
+
* ```typescript
|
|
1594
|
+
* import type { PluginRecordStore, PluginPrincipal } from '@alneas/eaos-server/plugin-data';
|
|
1595
|
+
* export async function firstPage(store: PluginRecordStore<{ title: string }>, principal: PluginPrincipal) {
|
|
1596
|
+
* return store.list(principal.tenantId, 20);
|
|
1597
|
+
* }
|
|
1598
|
+
* ```
|
|
1599
|
+
*/
|
|
1600
|
+
list(tenantId: string, limit: number): Promise<PluginRecord<T>[]>;
|
|
1601
|
+
/**
|
|
1602
|
+
* Reads a stable ID-ordered page after an optional exclusive logical record ID.
|
|
1603
|
+
*
|
|
1604
|
+
* Optional stable ID keyset paging; after is an exclusive logical record ID.
|
|
1605
|
+
* @param tenantId - Verified tenant ID.
|
|
1606
|
+
* @param limit - Required bounded page size; canonical SQL stores accept 1–100.
|
|
1607
|
+
* @param after - Optional exclusive logical record ID; omitted starts the page.
|
|
1608
|
+
* @returns Scoped envelopes in increasing logical-ID order; fewer than limit indicates the end.
|
|
1609
|
+
* @throws Rejects propagated host persistence, validation or callback failures.
|
|
1610
|
+
|
|
1611
|
+
* @example
|
|
1612
|
+
* ```typescript
|
|
1613
|
+
* import type { PluginRecordStore, PluginPrincipal } from '@alneas/eaos-server/plugin-data';
|
|
1614
|
+
* export async function nextPage(store: PluginRecordStore<{ title: string }>, principal: PluginPrincipal, after: string) {
|
|
1615
|
+
* if (!store.listPage) throw new Error("Keyset paging not supported");
|
|
1616
|
+
* return store.listPage(principal.tenantId, 20, after);
|
|
1617
|
+
* }
|
|
1618
|
+
* ```
|
|
1619
|
+
*/
|
|
1620
|
+
listPage?(tenantId: string, limit: number, after?: string): Promise<PluginRecord<T>[]>;
|
|
1621
|
+
/**
|
|
1622
|
+
* Creates a previously absent tenant record with its initial stored revision.
|
|
1623
|
+
* @param tenantId - Verified tenant ID owning the new record.
|
|
1624
|
+
* @param record - New logical envelope; canonical validated/atomic stores require revision 1.
|
|
1625
|
+
* @returns Resolves without a value after durable creation.
|
|
1626
|
+
* @throws Rejects duplicate identity, invalid document/payload/revision or persistence failure.
|
|
1627
|
+
|
|
1628
|
+
* @example
|
|
1629
|
+
* ```typescript
|
|
1630
|
+
* import type { PluginRecordStore, PluginPrincipal } from '@alneas/eaos-server/plugin-data';
|
|
1631
|
+
* export async function createTitle(store: PluginRecordStore<{ title: string }>, principal: PluginPrincipal, id: string, title: string) {
|
|
1632
|
+
* // Live create permission must be checked before persistence.
|
|
1633
|
+
* await store.create(principal.tenantId, { id, revision: 1, value: { title } });
|
|
1634
|
+
* }
|
|
1635
|
+
* ```
|
|
1636
|
+
*/
|
|
1637
|
+
create(tenantId: string, record: PluginRecord<T>): Promise<void>;
|
|
1638
|
+
/**
|
|
1639
|
+
* Replaces a tenant record only when its stored revision matches the expected value.
|
|
1640
|
+
* @param tenantId - Verified tenant ID.
|
|
1641
|
+
* @param record - Next envelope whose revision must be expectedRevision+1.
|
|
1642
|
+
* @param expectedRevision - Positive previously observed CAS revision.
|
|
1643
|
+
* @returns True when one row is replaced; false for stale rows in plain SQL stores. Atomic adapters reject CAS conflicts instead of returning false.
|
|
1644
|
+
* @throws Rejects invalid revision/document/payload or provider failure; atomic adapters also reject stale CAS.
|
|
1645
|
+
|
|
1646
|
+
* @example
|
|
1647
|
+
* ```typescript
|
|
1648
|
+
* import type { PluginRecordStore, PluginPrincipal } from '@alneas/eaos-server/plugin-data';
|
|
1649
|
+
* export async function replaceTitle(store: PluginRecordStore<{ title: string }>, principal: PluginPrincipal, id: string, expectedRevision: number, title: string) {
|
|
1650
|
+
* return store.replace(principal.tenantId, { id, revision: expectedRevision + 1, value: { title } }, expectedRevision);
|
|
1651
|
+
* }
|
|
1652
|
+
* ```
|
|
1653
|
+
*/
|
|
1654
|
+
replace(tenantId: string, record: PluginRecord<T>, expectedRevision: number): Promise<boolean>;
|
|
1655
|
+
/**
|
|
1656
|
+
* Optionally deletes one scoped envelope with an optional revision predicate.
|
|
1657
|
+
* @param tenantId - Verified tenant ID.
|
|
1658
|
+
* @param id - Logical record ID.
|
|
1659
|
+
* @param expectedRevision - Optional expected CAS revision; omit only when unconditional scoped deletion is intended.
|
|
1660
|
+
* @returns Whether a row was deleted; immutable document wrappers reject instead.
|
|
1661
|
+
* @throws Rejects immutable document deletion or host persistence failure.
|
|
1662
|
+
|
|
1663
|
+
* @example
|
|
1664
|
+
* ```typescript
|
|
1665
|
+
* import type { PluginRecordStore, PluginPrincipal } from '@alneas/eaos-server/plugin-data';
|
|
1666
|
+
* export async function deleteReviewed(store: PluginRecordStore<{ title: string }>, principal: PluginPrincipal, id: string, expectedRevision: number) {
|
|
1667
|
+
* if (!store.delete) throw new Error("Deletion not supported");
|
|
1668
|
+
* return store.delete(principal.tenantId, id, expectedRevision);
|
|
1669
|
+
* }
|
|
1670
|
+
* ```
|
|
1671
|
+
*/
|
|
1672
|
+
delete?(tenantId: string, id: string, expectedRevision?: number): Promise<boolean>;
|
|
1673
|
+
}
|
|
1674
|
+
/**
|
|
1675
|
+
* Carries an intentional sanitized plugin HTTP error status while preserving the caller-provided message.
|
|
1676
|
+
*
|
|
1677
|
+
* @remarks
|
|
1678
|
+
* createPluginRouter returns this message/status to HTTP callers; exclude secrets, provider details and business payloads from messages.
|
|
1679
|
+
*
|
|
1680
|
+
* @example
|
|
1681
|
+
* ```typescript
|
|
1682
|
+
* import { PluginError } from '@alneas/eaos-server/plugin-data';
|
|
1683
|
+
* const unavailable = new PluginError(404, 'Record unavailable');
|
|
1684
|
+
* ```
|
|
1685
|
+
*/
|
|
1686
|
+
declare class PluginError extends Error {
|
|
1687
|
+
readonly status: 400 | 401 | 403 | 404 | 409 | 410;
|
|
1688
|
+
/**
|
|
1689
|
+
* Creates an intentional plugin failure with one supported client-facing HTTP status.
|
|
1690
|
+
* @param status - Supported bad-input/authentication/permission/missing/conflict/gone HTTP status.
|
|
1691
|
+
* @param message - Safe public error description exposed by createPluginRouter.
|
|
1692
|
+
*
|
|
1693
|
+
* @example
|
|
1694
|
+
* ```typescript
|
|
1695
|
+
* import { PluginError } from '@alneas/eaos-server/plugin-data';
|
|
1696
|
+
* const denied = new PluginError(403, 'Record access denied');
|
|
1697
|
+
* ```
|
|
1698
|
+
*/
|
|
1699
|
+
constructor(status: 400 | 401 | 403 | 404 | 409 | 410, message: string);
|
|
1700
|
+
}
|
|
1701
|
+
/**
|
|
1702
|
+
* Check the structural presence of a nonblank tenant/user identity and string role list.
|
|
1703
|
+
* @param p - Principal from a trusted authentication resolver.
|
|
1704
|
+
* @returns No value; normal completion means the principal has the required shape.
|
|
1705
|
+
* @throws Throws PluginError 401 for malformed principal fields.
|
|
1706
|
+
* @remarks Shape validation is not authentication, membership verification or resource authorization.
|
|
1707
|
+
* @example
|
|
1708
|
+
* import { assertPrincipal } from '@alneas/eaos-server/plugin-data'
|
|
1709
|
+
* assertPrincipal({ tenantId: 'example-tenant', userId: 'example-user', roles: [] })
|
|
1710
|
+
*/
|
|
1711
|
+
declare function assertPrincipal(p: PluginPrincipal): void;
|
|
1712
|
+
/**
|
|
1713
|
+
* Hono variables carrying the principal resolved by the trusted plugin router.
|
|
1714
|
+
*
|
|
1715
|
+
* @see createPluginRouter for canonical host integration.
|
|
1716
|
+
*/
|
|
1717
|
+
type PluginHttpEnv = {
|
|
1718
|
+
/**
|
|
1719
|
+
* Hono variables populated by the trusted principal resolver before operation routes run.
|
|
1720
|
+
*/
|
|
1721
|
+
Variables: {
|
|
1722
|
+
/**
|
|
1723
|
+
* Verified principal resolved for this request; still subject to current service authorization.
|
|
1724
|
+
*/
|
|
1725
|
+
principal: PluginPrincipal;
|
|
1726
|
+
};
|
|
1727
|
+
};
|
|
1728
|
+
/**
|
|
1729
|
+
* Host-owned request-body bound for the shared authenticated plugin router.
|
|
1730
|
+
*
|
|
1731
|
+
* @see createPluginRouter for canonical host integration.
|
|
1732
|
+
*/
|
|
1733
|
+
interface PluginRouterOptions {
|
|
1734
|
+
/**
|
|
1735
|
+
* Request body size in bytes; defaults to 131072 and must be an integer from 1024 to 8388608.
|
|
1736
|
+
*
|
|
1737
|
+
* Trusted host bound, never request-controlled. Default 128KiB.
|
|
1738
|
+
*/ maxBodyBytes?: number;
|
|
1739
|
+
}
|
|
1740
|
+
/**
|
|
1741
|
+
* Create a bounded Hono router that resolves a verified principal for every request.
|
|
1742
|
+
* @param resolvePrincipal - Async host callback returning the authenticated principal or null; host owns current session validation.
|
|
1743
|
+
* @param options - Trusted body bound, default 128 KiB; accepted integer range is 1024 bytes through 8 MiB.
|
|
1744
|
+
* @returns A Hono router with body limits, scoped principal context and sanitized generic failure responses.
|
|
1745
|
+
* @throws Invalid body limits throw at construction. Request-time missing/malformed principals produce 401; unexpected failures become sanitized 500 responses.
|
|
1746
|
+
* @remarks Does not supply CSRF/Origin protection or per-resource authorization; compose those at the host/service boundary.
|
|
1747
|
+
* @example
|
|
1748
|
+
* import { createPluginRouter } from '@alneas/eaos-server/plugin-data'
|
|
1749
|
+
* export function routes(resolvePrincipal: Parameters<typeof createPluginRouter>[0]) { return createPluginRouter(resolvePrincipal) }
|
|
1750
|
+
*/
|
|
1751
|
+
declare function createPluginRouter(resolvePrincipal: (c: Context) => Promise<PluginPrincipal | null>, options?: PluginRouterOptions): Hono<PluginHttpEnv, hono_types.BlankSchema, "/">;
|
|
1752
|
+
type StandardPluginService = {
|
|
1753
|
+
/**
|
|
1754
|
+
* Principal-aware operation dispatcher shared by HTTP and MCP; the concrete service owns schema checks and current resource permission.
|
|
1755
|
+
* @param principal - Verified current tenant/user principal.
|
|
1756
|
+
* @param operation - Declared operation name.
|
|
1757
|
+
* @param input - Operation input to validate and authorize at the owning service boundary.
|
|
1758
|
+
* @returns The service operation result; authorization and validation stay owner-controlled.
|
|
1759
|
+
* @throws Rejects underlying service, authorization or persistence failures.
|
|
1760
|
+
*/
|
|
1761
|
+
execute(principal: PluginPrincipal, operation: string, input: Record<string, any>): Promise<unknown>;
|
|
1762
|
+
};
|
|
1763
|
+
/**
|
|
1764
|
+
* Compose a service-backed authenticated operation router and bound static MCP tools.
|
|
1765
|
+
* @param manifest - Plugin metadata whose capabilities remain subject to host admission.
|
|
1766
|
+
* @param ServiceClass - Trusted service constructor invoked once with options.
|
|
1767
|
+
* @param bindTools - Synchronous tool binder invoked with that same service instance.
|
|
1768
|
+
* @param options - Real store, authorization and other service configuration.
|
|
1769
|
+
* @param resolvePrincipal - Async trusted request-to-principal resolver; required.
|
|
1770
|
+
* @param configureRoutes - Optional synchronous callback adding routes using the same service instance.
|
|
1771
|
+
* @param routerOptions - Optional host-owned request body bound.
|
|
1772
|
+
* @typeParam TOptions - Host service configuration passed unchanged to the constructor.
|
|
1773
|
+
* @typeParam TService - Principal-aware service implementation shared by HTTP and MCP.
|
|
1774
|
+
* @returns Manifest fields plus createRoutes() and bound MCP definitions.
|
|
1775
|
+
* @throws Missing principal resolver or constructor/router/binder/configuration failures propagate.
|
|
1776
|
+
* @remarks Mounting the server does not activate tenants. HTTP and MCP hosts must enforce their current lifecycle/resource admission; static tool binding alone does not do that.
|
|
1777
|
+
* @example
|
|
1778
|
+
* import { createStandardPluginServer } from '@alneas/eaos-server/plugin-data'
|
|
1779
|
+
* export function bindServer(...args: Parameters<typeof createStandardPluginServer>) { return createStandardPluginServer(...args) }
|
|
1780
|
+
*/
|
|
1781
|
+
declare function createStandardPluginServer<TOptions, TService extends StandardPluginService>(manifest: PluginManifest, ServiceClass: new (options: TOptions) => TService, bindTools: (service: TService) => McpToolDefinition[], options: TOptions, resolvePrincipal: (c: Context) => Promise<PluginPrincipal | null>, configureRoutes?: (routes: ReturnType<typeof createPluginRouter>, service: TService) => void, routerOptions?: PluginRouterOptions): {
|
|
1782
|
+
createRoutes: () => Hono<PluginHttpEnv, hono_types.BlankSchema, "/">;
|
|
1783
|
+
mcp: {
|
|
1784
|
+
tools: McpToolDefinition[];
|
|
1785
|
+
};
|
|
1786
|
+
entitlement?: _alneas_eaos_core.PluginEntitlement;
|
|
1787
|
+
id: string;
|
|
1788
|
+
name: string;
|
|
1789
|
+
version: string;
|
|
1790
|
+
description: string;
|
|
1791
|
+
icon: string;
|
|
1792
|
+
category: string;
|
|
1793
|
+
recommended?: boolean;
|
|
1794
|
+
targets: _alneas_eaos_core.ClientTarget[];
|
|
1795
|
+
dependencies: string[];
|
|
1796
|
+
optionalDependencies?: string[];
|
|
1797
|
+
tier: "public" | "standard" | "pro" | "corporate" | "free" | "premium";
|
|
1798
|
+
industries: string[];
|
|
1799
|
+
contracts: string[];
|
|
1800
|
+
subscribes: string[];
|
|
1801
|
+
publishes: string[];
|
|
1802
|
+
navigation: _alneas_eaos_core.TargetNavigationConfig;
|
|
1803
|
+
schema: _alneas_eaos_core.SchemaConfig;
|
|
1804
|
+
extensions?: _alneas_eaos_core.PluginExtensionConfig[];
|
|
1805
|
+
api: _alneas_eaos_core.ApiConfig;
|
|
1806
|
+
secrets?: _alneas_eaos_core.PluginSecretRequirement[];
|
|
1807
|
+
settings?: _alneas_eaos_core.PluginSettingConfig[];
|
|
1808
|
+
agentCapabilities?: _alneas_eaos_core.AgentCapabilitiesConfig;
|
|
1809
|
+
i18n?: _alneas_eaos_core.PluginI18nConfig;
|
|
1810
|
+
docs?: _alneas_eaos_core.PluginDocConfig;
|
|
1811
|
+
goExtension?: _alneas_eaos_core.GoExtensionConfig;
|
|
1812
|
+
};
|
|
1813
|
+
/**
|
|
1814
|
+
* Read a JSON object request body with explicit content-type and shape checks.
|
|
1815
|
+
* @param c - Hono request context, normally protected by the plugin router body limit.
|
|
1816
|
+
* @returns Parsed nonnull object payload; arrays and primitives are rejected.
|
|
1817
|
+
* @throws Rejects non-JSON content types and malformed/nonobject JSON with PluginError 400.
|
|
1818
|
+
* @remarks This helper does not enforce a body-size bound, tenant identity or operation schema on its own.
|
|
1819
|
+
* @example
|
|
1820
|
+
* import { jsonBody } from '@alneas/eaos-server/plugin-data'
|
|
1821
|
+
* export async function readRequest(c: Parameters<typeof jsonBody>[0]) { return jsonBody(c) }
|
|
1822
|
+
*/
|
|
1823
|
+
declare function jsonBody(c: Context): Promise<Record<string, any>>;
|
|
1824
|
+
/**
|
|
1825
|
+
* Reject top-level object keys not present in an explicit operation allowlist.
|
|
1826
|
+
* @param value - Object whose own enumerable string keys are inspected.
|
|
1827
|
+
* @param keys - Trusted allowed top-level key names.
|
|
1828
|
+
* @returns No value when all existing keys are allowed.
|
|
1829
|
+
* @throws Throws PluginError 400 when an unknown key is present.
|
|
1830
|
+
* @remarks Does not require listed keys to exist or validate nested fields.
|
|
1831
|
+
* @example
|
|
1832
|
+
* import { exactKeys } from '@alneas/eaos-server/plugin-data'
|
|
1833
|
+
* exactKeys({ title: 'Example' }, ['title'])
|
|
1834
|
+
*/
|
|
1835
|
+
declare function exactKeys(value: object, keys: string[]): void;
|
|
1836
|
+
/**
|
|
1837
|
+
* Validate bounded nonblank string input while preserving the original whitespace.
|
|
1838
|
+
* @param value - Untrusted value to validate.
|
|
1839
|
+
* @param name - Trusted field label used in the failure message.
|
|
1840
|
+
* @param max - Maximum JavaScript string length; defaults to 256.
|
|
1841
|
+
* @returns The original string without trimming.
|
|
1842
|
+
* @throws Throws PluginError 400 if input is not a string, trims to empty or exceeds max.
|
|
1843
|
+
* @example
|
|
1844
|
+
* import { textInput } from '@alneas/eaos-server/plugin-data'
|
|
1845
|
+
* const title = textInput('Example', 'title', 80)
|
|
1846
|
+
*/
|
|
1847
|
+
declare function textInput(value: unknown, name: string, max?: number): string;
|
|
1848
|
+
/**
|
|
1849
|
+
* Require a positive safe-integer revision without coercing string inputs.
|
|
1850
|
+
* @param value - Untrusted revision value.
|
|
1851
|
+
* @returns The positive safe-integer revision.
|
|
1852
|
+
* @throws Throws PluginError 400 for nonintegers, numeric strings, zero, negatives or unsafe integers.
|
|
1853
|
+
* @example
|
|
1854
|
+
* import { revisionInput } from '@alneas/eaos-server/plugin-data'
|
|
1855
|
+
* const revision = revisionInput(1)
|
|
1856
|
+
*/
|
|
1857
|
+
declare function revisionInput(value: unknown): number;
|
|
1858
|
+
/**
|
|
1859
|
+
* Parameterized SQL transport whose host owns tenant session, transaction and provider binding behavior.
|
|
1860
|
+
*
|
|
1861
|
+
* @see createSqlRecordStore for canonical host integration.
|
|
1862
|
+
*/
|
|
1863
|
+
interface RecordSqlDriver {
|
|
1864
|
+
/**
|
|
1865
|
+
* SQL placeholder/driver dialect selected by trusted host configuration.
|
|
1866
|
+
*/
|
|
1867
|
+
dialect: 'sqlite' | 'postgres' | 'oracle';
|
|
1868
|
+
/**
|
|
1869
|
+
* Executes trusted parameterized SQL through the host-selected tenant session or transport.
|
|
1870
|
+
*
|
|
1871
|
+
* Bind arrays are positional. Host owns transaction/commit, Oracle CLOB bindings and authenticated tenant session.
|
|
1872
|
+
* @param tenantId - Verified tenant context for host routing/session setup; it is not an independent permission proof.
|
|
1873
|
+
* @param sql - Trusted SQL containing explicit tenant predicates; never untrusted SQL text.
|
|
1874
|
+
* @param bindings - Positional binds in SQL placeholder order; host handles Oracle CLOB/session details.
|
|
1875
|
+
* @returns Optional row data and affected-row count; CAS callers require accurate affectedRows.
|
|
1876
|
+
* @throws Rejects propagated host persistence, validation or callback failures.
|
|
1877
|
+
|
|
1878
|
+
* @example
|
|
1879
|
+
* ```typescript
|
|
1880
|
+
* import type { RecordSqlDriver, PluginPrincipal } from '@alneas/eaos-server/plugin-data';
|
|
1881
|
+
* export async function queryTenant(driver: RecordSqlDriver, principal: PluginPrincipal, trustedSql: string, bindings: unknown[]) {
|
|
1882
|
+
* // The host supplies dialect-correct SQL with explicit tenant predicates.
|
|
1883
|
+
* const result = await driver.execute(principal.tenantId, trustedSql, bindings);
|
|
1884
|
+
* return result.rows ?? [];
|
|
1885
|
+
* }
|
|
1886
|
+
* ```
|
|
1887
|
+
*/
|
|
1888
|
+
execute(tenantId: string, sql: string, bindings: unknown[]): Promise<{
|
|
1889
|
+
/**
|
|
1890
|
+
* Optional SQL result rows using host provider object-column names.
|
|
1891
|
+
*/
|
|
1892
|
+
rows?: Record<string, unknown>[];
|
|
1893
|
+
/**
|
|
1894
|
+
* Accurate DML row count; required by revision-predicated replace.
|
|
1895
|
+
*/
|
|
1896
|
+
affectedRows?: number;
|
|
1897
|
+
}>;
|
|
1898
|
+
}
|
|
1899
|
+
/**
|
|
1900
|
+
* Manifest namespace, payload limits and optional canonical JSON document validation for SQL records.
|
|
1901
|
+
*
|
|
1902
|
+
* @see createSqlRecordStore for canonical host integration.
|
|
1903
|
+
*/
|
|
1904
|
+
interface SqlRecordStoreOptions {
|
|
1905
|
+
/**
|
|
1906
|
+
* Optional trusted logical namespace encoded into physical IDs for a shared table.
|
|
1907
|
+
*
|
|
1908
|
+
* Logical namespace encoded into the trusted physical id for a shared foundation table.
|
|
1909
|
+
*/
|
|
1910
|
+
namespace?: string;
|
|
1911
|
+
/**
|
|
1912
|
+
* Declared payload/object/history limits; does not configure or authorize a provider.
|
|
1913
|
+
*
|
|
1914
|
+
* Payload/object/history policy declared by the plugin manifest.
|
|
1915
|
+
*/
|
|
1916
|
+
storagePolicy?: PluginStoragePolicy;
|
|
1917
|
+
/**
|
|
1918
|
+
* Canonical closed payload contracts copied and enforced by the wrapper.
|
|
1919
|
+
*/
|
|
1920
|
+
documents?: readonly JsonDocumentContract[];
|
|
1921
|
+
}
|
|
1922
|
+
/**
|
|
1923
|
+
* Bind JSON record persistence to a trusted table, namespace and host SQL driver.
|
|
1924
|
+
* @param table - Trusted lowercase table identifier, never a request-selected name.
|
|
1925
|
+
* @param driver - Tenant-aware SQL transport; host owns transactions, Oracle binding/session cleanup and current authorization.
|
|
1926
|
+
* @param options - Optional namespace, payload policy and canonical JSON document contracts.
|
|
1927
|
+
* @typeParam T - Stored JSON payload type; runtime shape is enforced only when canonical document contracts are supplied.
|
|
1928
|
+
* @returns A record store with tenant predicates, keyset reads and revision-predicated replace/delete operations.
|
|
1929
|
+
* @throws Rejects invalid table/namespace/document bindings. Operations propagate provider errors, reject invalid limits/revisions/payloads and map duplicate keys to PluginError 409.
|
|
1930
|
+
* @remarks Does not create/migrate tables or add a shared transaction around separate calls. Driver affected-row reporting is required for CAS correctness; hosts enforce live authorization.
|
|
1931
|
+
* @example
|
|
1932
|
+
* import { createSqlRecordStore } from '@alneas/eaos-server/plugin-data'
|
|
1933
|
+
* export function records(driver: Parameters<typeof createSqlRecordStore>[1]) { return createSqlRecordStore<{ title: string }>('example_records', driver) }
|
|
1934
|
+
*/
|
|
1935
|
+
declare function createSqlRecordStore<T>(table: string, driver: RecordSqlDriver, options?: SqlRecordStoreOptions): PluginRecordStore<T>;
|
|
1936
|
+
/**
|
|
1937
|
+
* Structural subset of the D1 prepared-statement API used by the record adapter.
|
|
1938
|
+
*
|
|
1939
|
+
* @see createCloudflareD1Driver for canonical host integration.
|
|
1940
|
+
*/
|
|
1941
|
+
interface CloudflareD1PreparedStatement {
|
|
1942
|
+
/**
|
|
1943
|
+
* Binds positional query values to a prepared Worker D1 statement.
|
|
1944
|
+
* @param values - Positional values in SQL placeholder order.
|
|
1945
|
+
* @returns The bound prepared statement used for all/run.
|
|
1946
|
+
* @throws Provider binding errors throw synchronously.
|
|
1947
|
+
|
|
1948
|
+
* @example
|
|
1949
|
+
* ```typescript
|
|
1950
|
+
* import type { CloudflareD1Binding } from '@alneas/eaos-server/plugin-data';
|
|
1951
|
+
* export async function readProjection(db: CloudflareD1Binding, tenantId: string) {
|
|
1952
|
+
* const statement = db.prepare("SELECT ? AS tenant_id").bind(tenantId);
|
|
1953
|
+
* return (await statement.all<{ tenant_id: string }>()).results ?? [];
|
|
1954
|
+
* }
|
|
1955
|
+
* ```
|
|
1956
|
+
*/
|
|
1957
|
+
bind(...values: unknown[]): CloudflareD1PreparedStatement;
|
|
1958
|
+
/**
|
|
1959
|
+
* Executes a prepared D1 read and resolves its structural query result.
|
|
1960
|
+
* @typeParam T - Returned query row shape; defaults to a string-keyed unknown-value record.
|
|
1961
|
+
* @returns Optional typed results and provider change metadata.
|
|
1962
|
+
* @throws Rejects provider query failures.
|
|
1963
|
+
|
|
1964
|
+
* @example
|
|
1965
|
+
* ```typescript
|
|
1966
|
+
* import type { CloudflareD1Binding } from '@alneas/eaos-server/plugin-data';
|
|
1967
|
+
* export async function projection(db: CloudflareD1Binding, tenantId: string) {
|
|
1968
|
+
* const result = await db.prepare("SELECT ? AS tenant_id").bind(tenantId).all<{ tenant_id: string }>();
|
|
1969
|
+
* return result.results ?? [];
|
|
1970
|
+
* }
|
|
1971
|
+
* ```
|
|
1972
|
+
*/
|
|
1973
|
+
all<T = Record<string, unknown>>(): Promise<{
|
|
1974
|
+
/**
|
|
1975
|
+
* Optional query rows with the caller-selected row shape.
|
|
1976
|
+
*/
|
|
1977
|
+
results?: T[];
|
|
1978
|
+
/**
|
|
1979
|
+
* Optional provider execution metadata.
|
|
1980
|
+
*/
|
|
1981
|
+
meta?: {
|
|
1982
|
+
/**
|
|
1983
|
+
* Optional provider affected-row count; record driver normalizes absence to 0.
|
|
1984
|
+
*/
|
|
1985
|
+
changes?: number;
|
|
1986
|
+
};
|
|
1987
|
+
}>;
|
|
1988
|
+
/**
|
|
1989
|
+
* Executes a prepared D1 write and resolves provider change metadata.
|
|
1990
|
+
* @returns Optional meta.changes affected-row metadata.
|
|
1991
|
+
* @throws Rejects provider execution failures.
|
|
1992
|
+
|
|
1993
|
+
* @example
|
|
1994
|
+
* ```typescript
|
|
1995
|
+
* import type { CloudflareD1Binding } from '@alneas/eaos-server/plugin-data';
|
|
1996
|
+
* export async function executeReviewed(db: CloudflareD1Binding, trustedTenantDml: string, bindings: unknown[]) {
|
|
1997
|
+
* // Supply parameterized DML whose bindings include the authorized tenant.
|
|
1998
|
+
* const result = await db.prepare(trustedTenantDml).bind(...bindings).run();
|
|
1999
|
+
* return result.meta?.changes ?? 0;
|
|
2000
|
+
* }
|
|
2001
|
+
* ```
|
|
2002
|
+
*/
|
|
2003
|
+
run(): Promise<{
|
|
2004
|
+
/**
|
|
2005
|
+
* Optional provider execution metadata.
|
|
2006
|
+
*/
|
|
2007
|
+
meta?: {
|
|
2008
|
+
/**
|
|
2009
|
+
* Optional provider affected-row count; record driver normalizes absence to 0.
|
|
2010
|
+
*/
|
|
2011
|
+
changes?: number;
|
|
2012
|
+
};
|
|
2013
|
+
}>;
|
|
2014
|
+
}
|
|
2015
|
+
/**
|
|
2016
|
+
* Trusted Worker D1 binding supplied by the host runtime.
|
|
2017
|
+
*
|
|
2018
|
+
* @see createCloudflareD1Driver for canonical host integration.
|
|
2019
|
+
*/
|
|
2020
|
+
interface CloudflareD1Binding {
|
|
2021
|
+
/**
|
|
2022
|
+
* Prepares trusted parameterized SQL on the installed Worker D1 binding.
|
|
2023
|
+
* @param query - Trusted SQL text; caller must bind tenant predicates.
|
|
2024
|
+
* @returns A statement exposing bind/all/run.
|
|
2025
|
+
* @throws Provider preparation errors throw synchronously.
|
|
2026
|
+
|
|
2027
|
+
* @example
|
|
2028
|
+
* ```typescript
|
|
2029
|
+
* import type { CloudflareD1Binding } from '@alneas/eaos-server/plugin-data';
|
|
2030
|
+
* export async function tenantProjection(db: CloudflareD1Binding, tenantId: string) {
|
|
2031
|
+
* const statement = db.prepare("SELECT ? AS tenant_id");
|
|
2032
|
+
* return (await statement.bind(tenantId).all()).results ?? [];
|
|
2033
|
+
* }
|
|
2034
|
+
* ```
|
|
2035
|
+
*/
|
|
2036
|
+
prepare(query: string): CloudflareD1PreparedStatement;
|
|
2037
|
+
}
|
|
2038
|
+
/**
|
|
2039
|
+
* Explicit Worker or HTTP transport configuration for the server-side D1 record driver.
|
|
2040
|
+
*
|
|
2041
|
+
* @see createCloudflareD1Driver for canonical host integration.
|
|
2042
|
+
*/
|
|
2043
|
+
interface CloudflareD1DriverOptions {
|
|
2044
|
+
/**
|
|
2045
|
+
* Optional trusted Worker D1 binding; takes precedence over HTTP credentials when valid.
|
|
2046
|
+
*
|
|
2047
|
+
* Direct Cloudflare Workers D1 binding (`env.DB`), when running inside a Worker.
|
|
2048
|
+
*/
|
|
2049
|
+
binding?: CloudflareD1Binding;
|
|
2050
|
+
/**
|
|
2051
|
+
* Cloudflare account identity required by HTTP mode.
|
|
2052
|
+
*
|
|
2053
|
+
* Cloudflare Account ID for remote D1 HTTP API access (e.g. from OCI server or CLI).
|
|
2054
|
+
*/
|
|
2055
|
+
accountId?: string;
|
|
2056
|
+
/**
|
|
2057
|
+
* Cloudflare D1 database identity required by HTTP mode.
|
|
2058
|
+
*
|
|
2059
|
+
* Cloudflare D1 Database UUID for remote D1 HTTP API access.
|
|
2060
|
+
*/
|
|
2061
|
+
databaseId?: string;
|
|
2062
|
+
/**
|
|
2063
|
+
* Sensitive host API token required by HTTP mode; never expose to browser entries or docs examples.
|
|
2064
|
+
*
|
|
2065
|
+
* Cloudflare API Token with D1:Edit permission for remote D1 HTTP API access.
|
|
2066
|
+
*/
|
|
2067
|
+
apiToken?: string;
|
|
2068
|
+
/**
|
|
2069
|
+
* Optional trusted fetch implementation; defaults to globalThis.fetch.
|
|
2070
|
+
*
|
|
2071
|
+
* Optional custom fetch implementation for D1 HTTP API calls.
|
|
2072
|
+
*/
|
|
2073
|
+
fetch?: typeof globalThis.fetch;
|
|
2074
|
+
/**
|
|
2075
|
+
* Trusted HTTP API base; defaults to https://api.cloudflare.com/client/v4.
|
|
2076
|
+
*
|
|
2077
|
+
* Optional Cloudflare API base URL override (defaults to `https://api.cloudflare.com/client/v4`).
|
|
2078
|
+
*/
|
|
2079
|
+
apiBaseUrl?: string;
|
|
2080
|
+
/**
|
|
2081
|
+
* Optional trusted table name; when supplied the first query runs CREATE TABLE IF NOT EXISTS. Omit when schema lifecycle is independently managed.
|
|
2082
|
+
*
|
|
2083
|
+
* Optional table name (e.g. `'eaos_customer_records'`) to auto-create via `CREATE TABLE IF NOT EXISTS` on first query.
|
|
2084
|
+
*/
|
|
2085
|
+
autoBootstrapTable?: string;
|
|
2086
|
+
}
|
|
2087
|
+
/**
|
|
2088
|
+
* Create a SQLite-dialect record driver using a Worker D1 binding or the explicit Cloudflare HTTP query endpoint.
|
|
2089
|
+
* @param options - Trusted binding or complete account/database/token credentials; an available binding takes precedence over HTTP configuration.
|
|
2090
|
+
* @returns A RecordSqlDriver whose execute method uses the selected D1 transport.
|
|
2091
|
+
* @throws Rejects absent transport or invalid bootstrap table name; query/HTTP failures propagate and duplicate-key failures are normalized.
|
|
2092
|
+
* @remarks The execute tenantId is not an independent authorization boundary; SQL callers must bind tenant predicates. autoBootstrapTable optionally executes CREATE TABLE on the first query; omit it when schemas are managed separately. Credentials and custom fetch/base URL are trusted server configuration.
|
|
2093
|
+
* @example
|
|
2094
|
+
* import { createCloudflareD1Driver } from '@alneas/eaos-server/plugin-data'
|
|
2095
|
+
* export function d1(options: Parameters<typeof createCloudflareD1Driver>[0]) { return createCloudflareD1Driver(options) }
|
|
2096
|
+
*/
|
|
2097
|
+
declare function createCloudflareD1Driver(options: CloudflareD1DriverOptions): RecordSqlDriver;
|
|
2098
|
+
/**
|
|
2099
|
+
* Resolve a manifest-owned storage table and optional canonical namespace/document bindings.
|
|
2100
|
+
* @param manifest - Trusted plugin schema with one owned table or an explicit shared-storage binding.
|
|
2101
|
+
* @param driver - Host SQL transport used by the resulting store.
|
|
2102
|
+
* @param catalog - Required trusted Data Contract catalog for shared-storage bindings.
|
|
2103
|
+
* @typeParam T - Stored payload shape retained by the record store.
|
|
2104
|
+
* @returns The tenant-predicated record store for the declared table/namespace.
|
|
2105
|
+
* @throws Rejects absent catalog, invalid storage binding or a legacy declaration without exactly one owned table; store validation failures propagate.
|
|
2106
|
+
* @remarks Does not install schemas or activate a feature; migration and live authorization remain host responsibilities.
|
|
2107
|
+
* @example
|
|
2108
|
+
* import { createPluginRecordStore } from '@alneas/eaos-server/plugin-data'
|
|
2109
|
+
* export function pluginRecords(manifest: Parameters<typeof createPluginRecordStore>[0], driver: Parameters<typeof createPluginRecordStore>[1], catalog: Parameters<typeof createPluginRecordStore>[2]) { return createPluginRecordStore(manifest, driver, catalog) }
|
|
2110
|
+
*/
|
|
2111
|
+
declare function createPluginRecordStore<T>(manifest: Pick<PluginManifest, 'schema'>, driver: RecordSqlDriver, catalog?: DataContractCatalog): PluginRecordStore<T>;
|
|
2112
|
+
|
|
2113
|
+
/**
|
|
2114
|
+
* Tenant-scoped logical row and its CAS revision at the time of reading/writing.
|
|
2115
|
+
* @typeParam T - JSON row payload shape; defaults to unknown.
|
|
2116
|
+
*
|
|
2117
|
+
* @see createAtomicRepository for canonical host integration.
|
|
2118
|
+
*/
|
|
2119
|
+
interface AtomicRow<T = unknown> {
|
|
2120
|
+
/**
|
|
2121
|
+
* Logical tenant/namespace-scoped record identity.
|
|
2122
|
+
*/
|
|
2123
|
+
id: string;
|
|
2124
|
+
/**
|
|
2125
|
+
* CAS revision for the stored envelope; persisted records start at 1 unless a documented host projection uses 0.
|
|
2126
|
+
*/
|
|
2127
|
+
revision: number;
|
|
2128
|
+
/**
|
|
2129
|
+
* Stored JSON payload whose runtime validation depends on the configured document contracts.
|
|
2130
|
+
*/
|
|
2131
|
+
value: T;
|
|
2132
|
+
}
|
|
2133
|
+
/**
|
|
2134
|
+
* Temporary tenant/namespace-bound session valid only inside its repository work callback.
|
|
2135
|
+
*
|
|
2136
|
+
* @see createAtomicRepository for canonical host integration.
|
|
2137
|
+
*/
|
|
2138
|
+
interface AtomicSession {
|
|
2139
|
+
/**
|
|
2140
|
+
* Performs one scoped read inside the active repository transaction.
|
|
2141
|
+
* @param id - Logical row ID; 1–240 supported record-key characters.
|
|
2142
|
+
* @typeParam T - JSON payload type read or persisted by this session operation.
|
|
2143
|
+
* @returns The scoped envelope or null when absent.
|
|
2144
|
+
* @throws Rejects expired session, invalid IDs/revisions/limits, document/payload errors, duplicate/create or CAS conflict and provider failures as applicable.
|
|
2145
|
+
|
|
2146
|
+
* @example
|
|
2147
|
+
* ```typescript
|
|
2148
|
+
* import type { AtomicRepository, PluginPrincipal } from '@alneas/eaos-server/plugin-data';
|
|
2149
|
+
* export async function readTitle(repository: AtomicRepository, principal: PluginPrincipal, id: string) {
|
|
2150
|
+
* return repository.run(principal, async session => {
|
|
2151
|
+
* const row = await session.get<{ title: string }>(id);
|
|
2152
|
+
* return row?.value.title ?? null;
|
|
2153
|
+
* });
|
|
2154
|
+
* }
|
|
2155
|
+
* ```
|
|
2156
|
+
*/
|
|
2157
|
+
get<T>(id: string): Promise<AtomicRow<T> | null>;
|
|
2158
|
+
/**
|
|
2159
|
+
* Performs ordered batch reads inside the active repository transaction.
|
|
2160
|
+
*
|
|
2161
|
+
* Batch reads preserve tenant scope and input order; missing rows are null.
|
|
2162
|
+
* @param ids - Logical IDs in desired output order; duplicates retain their positions.
|
|
2163
|
+
* @typeParam T - JSON payload type read or persisted by this session operation.
|
|
2164
|
+
* @returns One envelope or null per input ID in the same order.
|
|
2165
|
+
* @throws Rejects expired session, invalid IDs/revisions/limits, document/payload errors, duplicate/create or CAS conflict and provider failures as applicable.
|
|
2166
|
+
|
|
2167
|
+
* @example
|
|
2168
|
+
* ```typescript
|
|
2169
|
+
* import type { AtomicRepository, PluginPrincipal } from '@alneas/eaos-server/plugin-data';
|
|
2170
|
+
* export async function readTitles(repository: AtomicRepository, principal: PluginPrincipal, ids: string[]) {
|
|
2171
|
+
* return repository.run(principal, async session => {
|
|
2172
|
+
* if (!session.getMany) throw new Error("Batch reads not supported");
|
|
2173
|
+
* return session.getMany<{ title: string }>(ids);
|
|
2174
|
+
* });
|
|
2175
|
+
* }
|
|
2176
|
+
* ```
|
|
2177
|
+
*/
|
|
2178
|
+
getMany?<T>(ids: string[]): Promise<(AtomicRow<T> | null)[]>;
|
|
2179
|
+
/**
|
|
2180
|
+
* Performs transactional batch CAS writes inside the active repository transaction.
|
|
2181
|
+
*
|
|
2182
|
+
* Every item uses CAS in the enclosing transaction; any failure rolls back all items.
|
|
2183
|
+
* @param changes - Unique logical-ID/value/expected changes; expected=0 creates and positive expected performs exact CAS.
|
|
2184
|
+
* @typeParam T - JSON payload type read or persisted by this session operation.
|
|
2185
|
+
* @returns Next-revision envelopes in input order; any failure must reject the enclosing transaction.
|
|
2186
|
+
* @throws Rejects expired session, invalid IDs/revisions/limits, document/payload errors, duplicate/create or CAS conflict and provider failures as applicable.
|
|
2187
|
+
|
|
2188
|
+
* @example
|
|
2189
|
+
* ```typescript
|
|
2190
|
+
* import type { AtomicRepository, PluginPrincipal } from '@alneas/eaos-server/plugin-data';
|
|
2191
|
+
* export async function createPair(repository: AtomicRepository, principal: PluginPrincipal) {
|
|
2192
|
+
* return repository.run(principal, async session => {
|
|
2193
|
+
* if (!session.putMany) throw new Error("Batch writes not supported");
|
|
2194
|
+
* return session.putMany([{ id: "examples/first", value: { title: "First" }, expected: 0 }, { id: "examples/second", value: { title: "Second" }, expected: 0 }]);
|
|
2195
|
+
* });
|
|
2196
|
+
* }
|
|
2197
|
+
* ```
|
|
2198
|
+
*/
|
|
2199
|
+
putMany?<T>(changes: {
|
|
2200
|
+
/**
|
|
2201
|
+
* Unique logical record key within this batch and tenant namespace.
|
|
2202
|
+
*/
|
|
2203
|
+
id: string;
|
|
2204
|
+
/**
|
|
2205
|
+
* JSON payload to validate against configured policy/document contracts.
|
|
2206
|
+
*/
|
|
2207
|
+
value: T;
|
|
2208
|
+
/**
|
|
2209
|
+
* Expected safe CAS revision; 0 creates, positive values replace exactly that revision.
|
|
2210
|
+
*/
|
|
2211
|
+
expected: number;
|
|
2212
|
+
}[]): Promise<AtomicRow<T>[]>;
|
|
2213
|
+
/**
|
|
2214
|
+
* Performs a bounded scoped keyset read inside the active repository transaction.
|
|
2215
|
+
*
|
|
2216
|
+
* Empty prefix reads the repository's own tenant/namespace, never another tenant.
|
|
2217
|
+
* @param prefix - Logical prefix; empty stays within this repository tenant/namespace.
|
|
2218
|
+
* @param after - Optional exclusive logical ID; defaults to the start of the prefix range.
|
|
2219
|
+
* @param limit - Integer page size 1–101; defaults to 100.
|
|
2220
|
+
* @typeParam T - JSON payload type read or persisted by this session operation.
|
|
2221
|
+
* @returns Envelopes in stable logical-ID order within the prefix.
|
|
2222
|
+
* @throws Rejects expired session, invalid IDs/revisions/limits, document/payload errors, duplicate/create or CAS conflict and provider failures as applicable.
|
|
2223
|
+
|
|
2224
|
+
* @example
|
|
2225
|
+
* ```typescript
|
|
2226
|
+
* import type { AtomicRepository, PluginPrincipal } from '@alneas/eaos-server/plugin-data';
|
|
2227
|
+
* export async function firstPage(repository: AtomicRepository, principal: PluginPrincipal) {
|
|
2228
|
+
* return repository.run(principal, session => session.list<{ title: string }>("examples/", "", 20));
|
|
2229
|
+
* }
|
|
2230
|
+
* ```
|
|
2231
|
+
*/
|
|
2232
|
+
list<T>(prefix: string, after?: string, limit?: number): Promise<AtomicRow<T>[]>;
|
|
2233
|
+
/**
|
|
2234
|
+
* Performs one create-or-CAS write inside the active repository transaction.
|
|
2235
|
+
*
|
|
2236
|
+
* expected=0 creates; otherwise atomically replaces exactly the expected revision.
|
|
2237
|
+
* @param id - Logical row ID.
|
|
2238
|
+
* @param value - JSON payload admitted by configured limits/contracts.
|
|
2239
|
+
* @param expected - Safe integer expected revision from 0 to MAX_SAFE_INTEGER-1; 0 creates, otherwise exact CAS.
|
|
2240
|
+
* @typeParam T - JSON payload type read or persisted by this session operation.
|
|
2241
|
+
* @returns A cloned-payload envelope with revision expected+1.
|
|
2242
|
+
* @throws Rejects expired session, invalid IDs/revisions/limits, document/payload errors, duplicate/create or CAS conflict and provider failures as applicable.
|
|
2243
|
+
|
|
2244
|
+
* @example
|
|
2245
|
+
* ```typescript
|
|
2246
|
+
* import type { AtomicRepository, PluginPrincipal } from '@alneas/eaos-server/plugin-data';
|
|
2247
|
+
* export async function createTitle(repository: AtomicRepository, principal: PluginPrincipal, id: string, title: string) {
|
|
2248
|
+
* return repository.run(principal, session => session.put(id, { title }, 0));
|
|
2249
|
+
* }
|
|
2250
|
+
* ```
|
|
2251
|
+
*/
|
|
2252
|
+
put<T>(id: string, value: T, expected: number): Promise<AtomicRow<T>>;
|
|
2253
|
+
}
|
|
2254
|
+
/**
|
|
2255
|
+
* Host-admitted transactional entrypoint that scopes all session operations to one verified principal.
|
|
2256
|
+
*
|
|
2257
|
+
* @see createAtomicRepository for canonical host integration.
|
|
2258
|
+
*/
|
|
2259
|
+
interface AtomicRepository {
|
|
2260
|
+
/**
|
|
2261
|
+
* Runs work in one verified tenant transaction whose session expires when work settles.
|
|
2262
|
+
* @param principal - Verified tenant/user principal; repository structure checks do not prove live permission.
|
|
2263
|
+
* @param work - Async domain work; never let session or joined SQL capabilities escape its lifetime.
|
|
2264
|
+
* @typeParam T - Value resolved by the transaction/connection callback.
|
|
2265
|
+
* @returns The callback result after successful commit; work/commit failure rejects and triggers rollback.
|
|
2266
|
+
* @throws Rejects propagated host persistence, validation or callback failures.
|
|
2267
|
+
|
|
2268
|
+
* @example
|
|
2269
|
+
* ```typescript
|
|
2270
|
+
* import type { AtomicRepository, PluginPrincipal } from '@alneas/eaos-server/plugin-data';
|
|
2271
|
+
* export async function updateTitle(repository: AtomicRepository, principal: PluginPrincipal, id: string, title: string) {
|
|
2272
|
+
* return repository.run(principal, async session => {
|
|
2273
|
+
* const current = await session.get<{ title: string }>(id);
|
|
2274
|
+
* if (!current) throw new Error("Record unavailable");
|
|
2275
|
+
* return session.put(id, { title }, current.revision);
|
|
2276
|
+
* });
|
|
2277
|
+
* }
|
|
2278
|
+
* ```
|
|
2279
|
+
*/
|
|
2280
|
+
run<T>(principal: PluginPrincipal, work: (session: AtomicSession) => Promise<T>): Promise<T>;
|
|
2281
|
+
}
|
|
2282
|
+
/**
|
|
2283
|
+
* Connection-bound SQL operations sharing the enclosing commit/rollback boundary.
|
|
2284
|
+
*
|
|
2285
|
+
* @see createAtomicRepository for canonical host integration.
|
|
2286
|
+
*/
|
|
2287
|
+
interface AtomicSqlConnection {
|
|
2288
|
+
/**
|
|
2289
|
+
* Executes one trusted SQL statement on the exact connection owning the enclosing transaction.
|
|
2290
|
+
* @param sql - Trusted parameterized SQL with tenant/namespace predicates.
|
|
2291
|
+
* @param binds - Positional bind values in placeholder order.
|
|
2292
|
+
* @returns Optional query rows and an accurate affected-row count.
|
|
2293
|
+
* @throws Rejects propagated host persistence, validation or callback failures.
|
|
2294
|
+
|
|
2295
|
+
* @example
|
|
2296
|
+
* ```typescript
|
|
2297
|
+
* import type { AtomicSqlDriver, PluginPrincipal } from '@alneas/eaos-server/plugin-data';
|
|
2298
|
+
* export async function queryJoined(driver: AtomicSqlDriver, principal: PluginPrincipal, trustedTenantSql: string, bindings: unknown[]) {
|
|
2299
|
+
* return driver.transaction(principal, async connection => {
|
|
2300
|
+
* return (await connection.execute(trustedTenantSql, bindings)).rows ?? [];
|
|
2301
|
+
* });
|
|
2302
|
+
* }
|
|
2303
|
+
* ```
|
|
2304
|
+
*/
|
|
2305
|
+
execute(sql: string, binds: unknown[]): Promise<{
|
|
2306
|
+
/**
|
|
2307
|
+
* Optional object rows from SELECT execution on this connection.
|
|
2308
|
+
*/
|
|
2309
|
+
rows?: Record<string, unknown>[];
|
|
2310
|
+
/**
|
|
2311
|
+
* Accurate affected-row count for scalar execution or one count per ordered batch bind row.
|
|
2312
|
+
*/
|
|
2313
|
+
affectedRows: number;
|
|
2314
|
+
}>;
|
|
2315
|
+
/**
|
|
2316
|
+
* Optionally executes ordered bind batches on the same transaction connection.
|
|
2317
|
+
* @param sql - Trusted parameterized DML.
|
|
2318
|
+
* @param binds - Ordered positional bind rows.
|
|
2319
|
+
* @returns An affectedRows count for every bind row in input order; missing/wrong counts must fail CAS.
|
|
2320
|
+
* @throws Rejects propagated host persistence, validation or callback failures.
|
|
2321
|
+
|
|
2322
|
+
* @example
|
|
2323
|
+
* ```typescript
|
|
2324
|
+
* import type { AtomicSqlDriver, PluginPrincipal } from '@alneas/eaos-server/plugin-data';
|
|
2325
|
+
* export async function batchReviewed(driver: AtomicSqlDriver, principal: PluginPrincipal, trustedTenantDml: string, binds: unknown[][]) {
|
|
2326
|
+
* return driver.transaction(principal, async connection => {
|
|
2327
|
+
* if (!connection.executeMany) throw new Error("Batch DML not supported");
|
|
2328
|
+
* return (await connection.executeMany(trustedTenantDml, binds)).affectedRows;
|
|
2329
|
+
* });
|
|
2330
|
+
* }
|
|
2331
|
+
* ```
|
|
2332
|
+
*/
|
|
2333
|
+
executeMany?(sql: string, binds: unknown[][]): Promise<{
|
|
2334
|
+
/**
|
|
2335
|
+
* Accurate affected-row count for scalar execution or one count per ordered batch bind row.
|
|
2336
|
+
*/
|
|
2337
|
+
affectedRows: number[];
|
|
2338
|
+
}>;
|
|
2339
|
+
}
|
|
2340
|
+
/**
|
|
2341
|
+
* Provider transaction boundary required for envelope CAS, domain writes and durable journal atomicity.
|
|
2342
|
+
*
|
|
2343
|
+
* @see createAtomicRepository for canonical host integration.
|
|
2344
|
+
*/
|
|
2345
|
+
interface AtomicSqlDriver {
|
|
2346
|
+
/**
|
|
2347
|
+
* SQL placeholder/driver dialect selected by trusted host configuration.
|
|
2348
|
+
*/
|
|
2349
|
+
dialect: 'sqlite' | 'oracle' | 'postgres';
|
|
2350
|
+
/**
|
|
2351
|
+
* Acquires one transaction connection, commits success and rolls back rejection.
|
|
2352
|
+
*
|
|
2353
|
+
* Same connection for every statement; commits on success, rolls back on rejection.
|
|
2354
|
+
* @param principal - Verified tenant/user principal used for host session admission.
|
|
2355
|
+
* @param work - Async work on the same connection for every domain/CAS/audit statement.
|
|
2356
|
+
* @typeParam T - Value resolved by the transaction/connection callback.
|
|
2357
|
+
* @returns The callback result after commit; all joined writes roll back on failure.
|
|
2358
|
+
* @throws Rejects propagated host persistence, validation or callback failures.
|
|
2359
|
+
|
|
2360
|
+
* @example
|
|
2361
|
+
* ```typescript
|
|
2362
|
+
* import type { AtomicSqlDriver, PluginPrincipal } from '@alneas/eaos-server/plugin-data';
|
|
2363
|
+
* export async function readJoined(driver: AtomicSqlDriver, principal: PluginPrincipal, trustedTenantSql: string, bindings: unknown[]) {
|
|
2364
|
+
* return driver.transaction(principal, async connection => {
|
|
2365
|
+
* const result = await connection.execute(trustedTenantSql, bindings);
|
|
2366
|
+
* return result.rows ?? [];
|
|
2367
|
+
* });
|
|
2368
|
+
* }
|
|
2369
|
+
* ```
|
|
2370
|
+
*/
|
|
2371
|
+
transaction<T>(principal: PluginPrincipal, work: (connection: AtomicSqlConnection) => Promise<T>): Promise<T>;
|
|
2372
|
+
}
|
|
2373
|
+
/**
|
|
2374
|
+
* Expose SQL execution on the exact active transaction that owns envelope CAS and receipts.
|
|
2375
|
+
* @param session - Currently active repository session carrying a trusted SQL capability binding.
|
|
2376
|
+
* @param principal - Verified principal matching both tenant and user of the joined transaction.
|
|
2377
|
+
* @returns The bound driver dialect and an execute(tenantId, sql, binds) method using the existing connection.
|
|
2378
|
+
* @throws Throws for malformed/mismatched principals, missing/expired transaction bindings or a foreign execute tenant; driver failures propagate.
|
|
2379
|
+
* @remarks Never retain or use the executor after the parent transaction callback returns. It does not open another transaction or authorize arbitrary SQL.
|
|
2380
|
+
* @example
|
|
2381
|
+
* import { joinedAtomicSqlExecutor, type AtomicRepository, type PluginPrincipal } from '@alneas/eaos-server/plugin-data'
|
|
2382
|
+
* export function queryJoined(repository: AtomicRepository, principal: PluginPrincipal, statement: string, binds: unknown[]) {
|
|
2383
|
+
* // The host supplies trusted SQL and verifies resource permission before entry.
|
|
2384
|
+
* return repository.run(principal, session => joinedAtomicSqlExecutor(session, principal).execute(principal.tenantId, statement, binds))
|
|
2385
|
+
* }
|
|
2386
|
+
*/
|
|
2387
|
+
declare function joinedAtomicSqlExecutor(session: AtomicSession, principal: PluginPrincipal): {
|
|
2388
|
+
dialect: "sqlite" | "oracle" | "postgres";
|
|
2389
|
+
/**
|
|
2390
|
+
* Executes trusted SQL on this session's still-active joined connection.
|
|
2391
|
+
* @param tenantId - Must match the verified tenant bound to the original session.
|
|
2392
|
+
* @param sql - Trusted parameterized SQL with explicit tenant predicates.
|
|
2393
|
+
* @param binds - Positional bind values in placeholder order.
|
|
2394
|
+
* @returns Query rows and affected-row metadata from the existing transaction.
|
|
2395
|
+
* @throws Rejects expired/mismatched bindings, foreign tenant or underlying SQL failure.
|
|
2396
|
+
* @see joinedAtomicSqlExecutor for scoped usage that does not retain this capability.
|
|
2397
|
+
*/
|
|
2398
|
+
execute(tenantId: string, sql: string, binds: unknown[]): Promise<{
|
|
2399
|
+
/**
|
|
2400
|
+
* Optional object rows from SELECT execution on this connection.
|
|
2401
|
+
*/
|
|
2402
|
+
rows?: Record<string, unknown>[];
|
|
2403
|
+
/**
|
|
2404
|
+
* Accurate affected-row count for scalar execution or one count per ordered batch bind row.
|
|
2405
|
+
*/
|
|
2406
|
+
affectedRows: number;
|
|
2407
|
+
}>;
|
|
2408
|
+
};
|
|
2409
|
+
/**
|
|
2410
|
+
* Compute the canonical JSON SHA-256 used by atomic commands and scoped cursors.
|
|
2411
|
+
* @param value - Canonical-JSON-compatible value to hash.
|
|
2412
|
+
* @returns Lowercase hexadecimal SHA-256.
|
|
2413
|
+
* @throws Canonical serialization rejects unsupported or invalid values.
|
|
2414
|
+
* @remarks A hash binds content; it is not a signature or external trust anchor.
|
|
2415
|
+
* @example
|
|
2416
|
+
* import { atomicHash } from '@alneas/eaos-server/plugin-data'
|
|
2417
|
+
* const hash = atomicHash({ id: 'example' })
|
|
2418
|
+
*/
|
|
2419
|
+
declare function atomicHash(value: unknown): string;
|
|
2420
|
+
/**
|
|
2421
|
+
* Replay or atomically record one principal/operation-scoped command result in an existing transaction.
|
|
2422
|
+
* @param tx - Live tenant-scoped atomic session enclosing the actual domain work.
|
|
2423
|
+
* @param p - Verified principal whose user ID scopes the command receipt.
|
|
2424
|
+
* @param operation - Trusted operation name included in the receipt key.
|
|
2425
|
+
* @param input - Complete command input with a commandId of 1–80 letters/digits/underscore/hyphen.
|
|
2426
|
+
* @param work - Async domain callback run only for a new command; must remain inside the same transaction.
|
|
2427
|
+
* @typeParam T - JSON-serializable domain result stored and returned by the command receipt.
|
|
2428
|
+
* @returns The existing identical receipt result or the newly computed result.
|
|
2429
|
+
* @throws Rejects malformed command IDs, input reuse with a different hash, CAS/audit failures and propagated work errors.
|
|
2430
|
+
* @remarks Caller performs live resource authorization before replay as well as execution. Domain writes, receipt and audit share the existing transaction; irreversible external effects must be durably queued, not performed inside work.
|
|
2431
|
+
* @example
|
|
2432
|
+
* import { atomicCommand, type AtomicRepository, type AtomicSession, type PluginPrincipal } from '@alneas/eaos-server/plugin-data'
|
|
2433
|
+
* export function command<T>(repository: AtomicRepository, principal: PluginPrincipal, input: { commandId: string }, work: (session: AtomicSession) => Promise<T>) {
|
|
2434
|
+
* // The host performs live resource admission before replay or new execution.
|
|
2435
|
+
* return repository.run(principal, session => atomicCommand(session, principal, 'example-operation', input, () => work(session)))
|
|
2436
|
+
* }
|
|
2437
|
+
*/
|
|
2438
|
+
declare function atomicCommand<T>(tx: AtomicSession, p: PluginPrincipal, operation: string, input: {
|
|
2439
|
+
/**
|
|
2440
|
+
* Stable nonempty 1–80 character command ID scoped by actor and operation; identical full input replays the stored result.
|
|
2441
|
+
*/
|
|
2442
|
+
commandId: string;
|
|
2443
|
+
}, work: () => Promise<T>): Promise<T>;
|
|
2444
|
+
/**
|
|
2445
|
+
* Encode an exclusive record position bound to the canonical hash of its query scope.
|
|
2446
|
+
* @param scope - Tenant/user/operation/filter scope defined by the caller.
|
|
2447
|
+
* @param after - Exclusive logical record ID to resume after.
|
|
2448
|
+
* @returns Base64url cursor containing the scope hash and position.
|
|
2449
|
+
* @throws Unsupported canonical scope values or JSON serialization failures propagate.
|
|
2450
|
+
* @remarks Encoding is not encryption or a signature; the reader validates scope and record-key grammar.
|
|
2451
|
+
* @example
|
|
2452
|
+
* import { recordCursor } from '@alneas/eaos-server/plugin-data'
|
|
2453
|
+
* const cursor = recordCursor(['example-tenant', 'list'], 'record-1')
|
|
2454
|
+
*/
|
|
2455
|
+
declare function recordCursor(scope: unknown, after: string): string;
|
|
2456
|
+
/**
|
|
2457
|
+
* Decode a cursor only when its scope hash and logical record key match the current query.
|
|
2458
|
+
* @param scope - Current tenant/user/operation/filter scope.
|
|
2459
|
+
* @param cursor - Optional base64url cursor; omission returns the initial empty position.
|
|
2460
|
+
* @returns Validated exclusive record ID, or an empty string for no cursor.
|
|
2461
|
+
* @throws Throws PluginError 400 for invalid encoding/JSON, changed scope or invalid record keys.
|
|
2462
|
+
* @example
|
|
2463
|
+
* import { parseRecordCursor } from '@alneas/eaos-server/plugin-data'
|
|
2464
|
+
* const after = parseRecordCursor(['example-tenant', 'list'])
|
|
2465
|
+
*/
|
|
2466
|
+
declare function parseRecordCursor(scope: unknown, cursor?: string): string;
|
|
2467
|
+
/**
|
|
2468
|
+
* Canonical namespace, JSON payload policy and optional document contracts for the atomic envelope table.
|
|
2469
|
+
*
|
|
2470
|
+
*
|
|
2471
|
+
* Plugin-owned table; tenant cannot be selected through individual row operations.
|
|
2472
|
+
* @see createAtomicRepository for canonical host integration.
|
|
2473
|
+
*/
|
|
2474
|
+
interface AtomicRepositoryOptions {
|
|
2475
|
+
/**
|
|
2476
|
+
* Optional trusted logical namespace encoded into physical IDs for a shared table.
|
|
2477
|
+
*/
|
|
2478
|
+
namespace?: string;
|
|
2479
|
+
/**
|
|
2480
|
+
* Declared payload/object/history limits; does not configure or authorize a provider.
|
|
2481
|
+
*/
|
|
2482
|
+
storagePolicy?: PluginStoragePolicy;
|
|
2483
|
+
/**
|
|
2484
|
+
* Canonical closed payload contracts copied and enforced by the wrapper.
|
|
2485
|
+
*/
|
|
2486
|
+
documents?: readonly JsonDocumentContract[];
|
|
2487
|
+
}
|
|
2488
|
+
/**
|
|
2489
|
+
* Create tenant/namespace-scoped CAS sessions on a trusted transactional SQL driver.
|
|
2490
|
+
* @param table - Trusted lowercase table identifier for envelope persistence.
|
|
2491
|
+
* @param driver - Driver that commits the callback result or rolls back all statements on rejection.
|
|
2492
|
+
* @param options - Optional namespace, payload policy and canonical document contracts.
|
|
2493
|
+
* @returns Repository whose run callback receives a temporary session valid only until the callback settles.
|
|
2494
|
+
* @throws Rejects invalid table/driver/namespace/document bindings; operations reject expired sessions, invalid IDs/revisions/payloads, duplicate keys and CAS conflicts.
|
|
2495
|
+
* @remarks Does not create tables. Driver transaction atomicity, connection cleanup and live authorization remain host-owned. Batch writes use the same transaction; session capabilities expire in finally. list supports limits 1–101; getMany preserves input order and missing nulls.
|
|
2496
|
+
* @example
|
|
2497
|
+
* import { createAtomicRepository } from '@alneas/eaos-server/plugin-data'
|
|
2498
|
+
* export function repository(driver: Parameters<typeof createAtomicRepository>[1]) { return createAtomicRepository('example_records', driver) }
|
|
2499
|
+
*/
|
|
2500
|
+
declare function createAtomicRepository(table: string, driver: AtomicSqlDriver, options?: AtomicRepositoryOptions): AtomicRepository;
|
|
2501
|
+
/**
|
|
2502
|
+
* Adapt one active atomic session to the standard record-store boundary for exactly one tenant.
|
|
2503
|
+
* @param session - Live session obtained inside repository.run.
|
|
2504
|
+
* @param principal - Verified principal defining the only admitted tenant.
|
|
2505
|
+
* @typeParam T - JSON payload shape retained by the adapted store.
|
|
2506
|
+
* @returns A read/list/listPage/create/replace store backed by that same session.
|
|
2507
|
+
* @throws Malformed principals throw immediately; foreign tenant, invalid revision transitions or expired/CAS session failures reject operations.
|
|
2508
|
+
* @remarks Does not begin or commit a transaction and does not expose deletion. Replacement conflicts reject rather than returning false.
|
|
2509
|
+
* @example
|
|
2510
|
+
* import { createAtomicRecordStore, type AtomicRepository, type PluginPrincipal } from '@alneas/eaos-server/plugin-data'
|
|
2511
|
+
* export function readRecord<T>(repository: AtomicRepository, principal: PluginPrincipal, id: string) {
|
|
2512
|
+
* return repository.run(principal, session => createAtomicRecordStore<T>(session, principal).read(principal.tenantId, id))
|
|
2513
|
+
* }
|
|
2514
|
+
*/
|
|
2515
|
+
declare function createAtomicRecordStore<T>(session: AtomicSession, principal: PluginPrincipal): PluginRecordStore<T>;
|
|
2516
|
+
/**
|
|
2517
|
+
* Resolve manifest storage metadata to an atomic repository with canonical document enforcement.
|
|
2518
|
+
* @param manifest - Trusted schema with shared-storage binding or exactly one owned table.
|
|
2519
|
+
* @param driver - Trusted transactional SQL driver.
|
|
2520
|
+
* @param catalog - Required Data Contract catalog when shared storage is declared.
|
|
2521
|
+
* @returns Atomic repository for the manifest-selected table/namespace.
|
|
2522
|
+
* @throws Rejects absent/mismatched catalogs, ambiguous owned tables or invalid repository bindings.
|
|
2523
|
+
* @remarks Does not install/enable storage contracts; host lifecycle and admission are separate.
|
|
2524
|
+
* @example
|
|
2525
|
+
* import { createPluginAtomicRepository } from '@alneas/eaos-server/plugin-data'
|
|
2526
|
+
* export function repository(manifest: Parameters<typeof createPluginAtomicRepository>[0], driver: Parameters<typeof createPluginAtomicRepository>[1], catalog: Parameters<typeof createPluginAtomicRepository>[2]) { return createPluginAtomicRepository(manifest, driver, catalog) }
|
|
2527
|
+
*/
|
|
2528
|
+
declare function createPluginAtomicRepository(manifest: Pick<PluginManifest, 'schema'>, driver: AtomicSqlDriver, catalog?: DataContractCatalog): AtomicRepository;
|
|
2529
|
+
/**
|
|
2530
|
+
* Structural synchronous SQLite database API; lifecycle and physical migrations remain host-owned.
|
|
2531
|
+
*
|
|
2532
|
+
*
|
|
2533
|
+
* Structural Bun SQLite connection. The host owns the database and migration application.
|
|
2534
|
+
* @see createSqliteAtomicDriver for canonical host integration.
|
|
2535
|
+
*/
|
|
2536
|
+
interface SqliteAtomicDatabase {
|
|
2537
|
+
/**
|
|
2538
|
+
* Executes trusted SQLite control SQL on the host-owned connection.
|
|
2539
|
+
* @param sql - Trusted transaction/control SQL text.
|
|
2540
|
+
* @returns The native database execution result.
|
|
2541
|
+
* @throws SQLite control failures throw synchronously.
|
|
2542
|
+
|
|
2543
|
+
* @example
|
|
2544
|
+
* ```typescript
|
|
2545
|
+
* import type { SqliteAtomicDatabase } from '@alneas/eaos-server/plugin-data';
|
|
2546
|
+
* export function enforceForeignKeys(db: SqliteAtomicDatabase) {
|
|
2547
|
+
* db.exec("PRAGMA foreign_keys = ON");
|
|
2548
|
+
* }
|
|
2549
|
+
* ```
|
|
2550
|
+
*/
|
|
2551
|
+
exec(sql: string): unknown;
|
|
2552
|
+
/**
|
|
2553
|
+
* Prepares trusted parameterized SQLite SQL on the host-owned connection.
|
|
2554
|
+
* @param sql - Trusted SQL text with explicit tenant predicates.
|
|
2555
|
+
* @returns A statement exposing synchronous all/run methods.
|
|
2556
|
+
* @throws Preparation errors throw synchronously.
|
|
2557
|
+
|
|
2558
|
+
* @example
|
|
2559
|
+
* ```typescript
|
|
2560
|
+
* import type { SqliteAtomicDatabase } from '@alneas/eaos-server/plugin-data';
|
|
2561
|
+
* export function tenantProjection(db: SqliteAtomicDatabase, tenantId: string) {
|
|
2562
|
+
* return db.query("SELECT ? AS tenant_id").all(tenantId);
|
|
2563
|
+
* }
|
|
2564
|
+
* ```
|
|
2565
|
+
*/
|
|
2566
|
+
query(sql: string): {
|
|
2567
|
+
/**
|
|
2568
|
+
* Synchronously execute the prepared query with positional values and return all rows.
|
|
2569
|
+
* @param values - Positional prepared-statement values.
|
|
2570
|
+
* @returns All prepared-query rows in provider order.
|
|
2571
|
+
* @throws Provider execution/binding errors throw synchronously.
|
|
2572
|
+
|
|
2573
|
+
* @example
|
|
2574
|
+
* ```typescript
|
|
2575
|
+
* import type { SqliteAtomicDatabase } from '@alneas/eaos-server/plugin-data';
|
|
2576
|
+
* export function projectedRows(db: SqliteAtomicDatabase, tenantId: string) {
|
|
2577
|
+
* const statement = db.query("SELECT ? AS tenant_id");
|
|
2578
|
+
* return statement.all(tenantId);
|
|
2579
|
+
* }
|
|
2580
|
+
* ```
|
|
2581
|
+
*/
|
|
2582
|
+
all(...values: any[]): unknown[];
|
|
2583
|
+
/**
|
|
2584
|
+
* Synchronously execute the prepared DML with positional values and return its change count.
|
|
2585
|
+
* @param values - Positional prepared-statement values.
|
|
2586
|
+
* @returns Native DML change-count metadata.
|
|
2587
|
+
* @throws Provider execution/binding errors throw synchronously.
|
|
2588
|
+
|
|
2589
|
+
* @example
|
|
2590
|
+
* ```typescript
|
|
2591
|
+
* import type { SqliteAtomicDatabase } from '@alneas/eaos-server/plugin-data';
|
|
2592
|
+
* export function executeReviewed(db: SqliteAtomicDatabase, trustedTenantDml: string, bindings: unknown[]) {
|
|
2593
|
+
* return db.query(trustedTenantDml).run(...bindings).changes;
|
|
2594
|
+
* }
|
|
2595
|
+
* ```
|
|
2596
|
+
*/
|
|
2597
|
+
run(...values: any[]): {
|
|
2598
|
+
/**
|
|
2599
|
+
* Number of rows affected by this prepared DML execution.
|
|
2600
|
+
*/
|
|
2601
|
+
changes: number;
|
|
2602
|
+
};
|
|
2603
|
+
};
|
|
2604
|
+
}
|
|
2605
|
+
/**
|
|
2606
|
+
* Serialize BEGIN IMMEDIATE transactions on a host-owned SQLite connection.
|
|
2607
|
+
* @param db - Structural SQLite database whose schema and connection lifetime are owned by the host.
|
|
2608
|
+
* @returns SQLite transaction driver with one connection-local promise queue.
|
|
2609
|
+
* @throws BEGIN/statement/COMMIT/ROLLBACK errors and callback failures reject; a rollback failure can replace the original error.
|
|
2610
|
+
* @remarks Queueing is per driver instance, not cross-process coordination. Do not nest repository transactions on the same connection; close the database only after all operations finish.
|
|
2611
|
+
* @example
|
|
2612
|
+
* import { createSqliteAtomicDriver } from '@alneas/eaos-server/plugin-data'
|
|
2613
|
+
* export function driver(db: Parameters<typeof createSqliteAtomicDriver>[0]) { return createSqliteAtomicDriver(db) }
|
|
2614
|
+
*/
|
|
2615
|
+
declare function createSqliteAtomicDriver(db: SqliteAtomicDatabase): AtomicSqlDriver;
|
|
2616
|
+
/**
|
|
2617
|
+
* Host Oracle connection subset used with autocommit disabled and explicit commit/rollback.
|
|
2618
|
+
*
|
|
2619
|
+
* @see createOracleAtomicDriver for canonical host integration.
|
|
2620
|
+
*/
|
|
2621
|
+
interface OracleAtomicConnection {
|
|
2622
|
+
/**
|
|
2623
|
+
* Executes one parameterized Oracle statement without autocommit.
|
|
2624
|
+
* @param sql - Trusted parameterized SQL.
|
|
2625
|
+
* @param binds - Ordered bind values, including explicit CLOB bindings for large payloads.
|
|
2626
|
+
* @param options - Provider options requiring autoCommit=false and object row format, with optional per-column fetch types.
|
|
2627
|
+
* @returns Optional object rows and rowsAffected count.
|
|
2628
|
+
* @throws Rejects Oracle execution/binding failures.
|
|
2629
|
+
|
|
2630
|
+
* @example
|
|
2631
|
+
* ```typescript
|
|
2632
|
+
* import type { OracleAtomicHost, OracleAtomicConnection } from '@alneas/eaos-server/plugin-data';
|
|
2633
|
+
* export async function queryTenant(host: OracleAtomicHost, tenantId: string, trustedTenantSql: string, binds: unknown[], options: Parameters<OracleAtomicConnection["execute"]>[2]) {
|
|
2634
|
+
* return host.withTenantConnection("PLUGIN_RECORDS", async connection => {
|
|
2635
|
+
* return (await connection.execute(trustedTenantSql, binds, options)).rows ?? [];
|
|
2636
|
+
* }, { tenantId });
|
|
2637
|
+
* }
|
|
2638
|
+
* ```
|
|
2639
|
+
*/
|
|
2640
|
+
execute(sql: string, binds: unknown[], options: {
|
|
2641
|
+
/**
|
|
2642
|
+
* Must be false so the host transaction explicitly commits or rolls back all joined work.
|
|
2643
|
+
*/
|
|
2644
|
+
autoCommit: false;
|
|
2645
|
+
/**
|
|
2646
|
+
* Actual Oracle object-row output constant supplied by the installed driver.
|
|
2647
|
+
*/
|
|
2648
|
+
outFormat: number;
|
|
2649
|
+
/**
|
|
2650
|
+
* Optional column-name to explicit fetch-type settings, including PAYLOAD string extraction.
|
|
2651
|
+
*/
|
|
2652
|
+
fetchInfo?: Record<string, {
|
|
2653
|
+
/**
|
|
2654
|
+
* Actual installed Oracle provider type constant; no global conversion settings are changed.
|
|
2655
|
+
*/
|
|
2656
|
+
type: unknown;
|
|
2657
|
+
}>;
|
|
2658
|
+
}): Promise<{
|
|
2659
|
+
/**
|
|
2660
|
+
* Optional Oracle object rows returned by a query.
|
|
2661
|
+
*/
|
|
2662
|
+
rows?: Record<string, unknown>[];
|
|
2663
|
+
/**
|
|
2664
|
+
* Optional scalar DML affected-row count; adapter normalizes absence to 0.
|
|
2665
|
+
*/
|
|
2666
|
+
rowsAffected?: number;
|
|
2667
|
+
}>;
|
|
2668
|
+
/**
|
|
2669
|
+
* Executes ordered Oracle bind batches without autocommit.
|
|
2670
|
+
* @param sql - Trusted parameterized DML.
|
|
2671
|
+
* @param binds - Ordered positional bind rows.
|
|
2672
|
+
* @param options - Provider options requiring autoCommit=false and dmlRowCounts=true.
|
|
2673
|
+
* @returns Per-bind-row DML counts; adapters reject missing/invalid lengths or counts.
|
|
2674
|
+
* @throws Rejects Oracle batch/binding failures.
|
|
2675
|
+
|
|
2676
|
+
* @example
|
|
2677
|
+
* ```typescript
|
|
2678
|
+
* import type { OracleAtomicHost } from '@alneas/eaos-server/plugin-data';
|
|
2679
|
+
* export async function batchReviewed(host: OracleAtomicHost, tenantId: string, trustedTenantDml: string, binds: unknown[][]) {
|
|
2680
|
+
* return host.withTenantConnection("PLUGIN_RECORDS", async connection => {
|
|
2681
|
+
* if (!connection.executeMany) throw new Error("Batch DML not supported");
|
|
2682
|
+
* try {
|
|
2683
|
+
* const result = await connection.executeMany(trustedTenantDml, binds, { autoCommit: false, dmlRowCounts: true });
|
|
2684
|
+
* await connection.commit();
|
|
2685
|
+
* return result.dmlRowCounts;
|
|
2686
|
+
* } catch (error) { await connection.rollback(); throw error; }
|
|
2687
|
+
* }, { tenantId });
|
|
2688
|
+
* }
|
|
2689
|
+
* ```
|
|
2690
|
+
*/
|
|
2691
|
+
executeMany?(sql: string, binds: unknown[][], options: {
|
|
2692
|
+
/**
|
|
2693
|
+
* Must be false so the host transaction explicitly commits or rolls back all joined work.
|
|
2694
|
+
*/
|
|
2695
|
+
autoCommit: false;
|
|
2696
|
+
/**
|
|
2697
|
+
* Requested per-row batch counts (true in options), or returned per-bind-row counts in the result.
|
|
2698
|
+
*/
|
|
2699
|
+
dmlRowCounts: true;
|
|
2700
|
+
}): Promise<{
|
|
2701
|
+
/**
|
|
2702
|
+
* Requested per-row batch counts (true in options), or returned per-bind-row counts in the result.
|
|
2703
|
+
*/
|
|
2704
|
+
dmlRowCounts?: number[];
|
|
2705
|
+
}>;
|
|
2706
|
+
/**
|
|
2707
|
+
* Explicitly commits the current Oracle transaction.
|
|
2708
|
+
* @returns Resolves without a value after provider commit completes.
|
|
2709
|
+
* @throws Rejects provider commit failure.
|
|
2710
|
+
|
|
2711
|
+
* @example
|
|
2712
|
+
* ```typescript
|
|
2713
|
+
* import type { OracleAtomicConnection } from '@alneas/eaos-server/plugin-data';
|
|
2714
|
+
* export async function commitOwned(connection: OracleAtomicConnection) {
|
|
2715
|
+
* // Only the owner of this transaction chooses its completion outcome.
|
|
2716
|
+
* await connection.commit();
|
|
2717
|
+
* }
|
|
2718
|
+
* ```
|
|
2719
|
+
*/
|
|
2720
|
+
commit(): Promise<void>;
|
|
2721
|
+
/**
|
|
2722
|
+
* Explicitly rolls back the current Oracle transaction.
|
|
2723
|
+
* @returns Resolves without a value after provider rollback completes.
|
|
2724
|
+
* @throws Rejects provider rollback failure.
|
|
2725
|
+
|
|
2726
|
+
* @example
|
|
2727
|
+
* ```typescript
|
|
2728
|
+
* import type { OracleAtomicConnection } from '@alneas/eaos-server/plugin-data';
|
|
2729
|
+
* export async function rollbackOwned(connection: OracleAtomicConnection) {
|
|
2730
|
+
* // Only the owner of this transaction chooses its completion outcome.
|
|
2731
|
+
* await connection.rollback();
|
|
2732
|
+
* }
|
|
2733
|
+
* ```
|
|
2734
|
+
*/
|
|
2735
|
+
rollback(): Promise<void>;
|
|
2736
|
+
}
|
|
2737
|
+
/**
|
|
2738
|
+
* Trusted tenant Oracle connection acquisition and cleanup boundary.
|
|
2739
|
+
*
|
|
2740
|
+
* @see createOracleAtomicDriver for canonical host integration.
|
|
2741
|
+
*/
|
|
2742
|
+
interface OracleAtomicHost {
|
|
2743
|
+
/**
|
|
2744
|
+
* Acquires a verified tenant Oracle connection and cleans up its host session after work.
|
|
2745
|
+
* @param domain - Trusted connection domain; this adapter uses PLUGIN_RECORDS.
|
|
2746
|
+
* @param callback - Async work receiving the single admitted connection.
|
|
2747
|
+
* @param context - Verified tenant/user session context; must not come from raw request authority.
|
|
2748
|
+
* @typeParam T - Value resolved by the transaction/connection callback.
|
|
2749
|
+
* @returns The callback result after host session cleanup and connection release.
|
|
2750
|
+
* @throws Rejects acquisition, admission, callback or cleanup failures.
|
|
2751
|
+
|
|
2752
|
+
* @example
|
|
2753
|
+
* ```typescript
|
|
2754
|
+
* import type { OracleAtomicHost } from '@alneas/eaos-server/plugin-data';
|
|
2755
|
+
* export async function inspectTenant(host: OracleAtomicHost, tenantId: string, userId: string, inspect: (connection: Parameters<Parameters<OracleAtomicHost["withTenantConnection"]>[1]>[0]) => Promise<unknown>) {
|
|
2756
|
+
* return host.withTenantConnection("PLUGIN_RECORDS", inspect, { tenantId, userId });
|
|
2757
|
+
* }
|
|
2758
|
+
* ```
|
|
2759
|
+
*/
|
|
2760
|
+
withTenantConnection<T>(domain: string, callback: (connection: OracleAtomicConnection) => Promise<T>, context: {
|
|
2761
|
+
/**
|
|
2762
|
+
* Verified concrete tenant admitted by the host session boundary.
|
|
2763
|
+
*/
|
|
2764
|
+
tenantId: string;
|
|
2765
|
+
/**
|
|
2766
|
+
* Optional verified actor ID attached to the Oracle session.
|
|
2767
|
+
*/
|
|
2768
|
+
userId?: string;
|
|
2769
|
+
}): Promise<T>;
|
|
2770
|
+
}
|
|
2771
|
+
/**
|
|
2772
|
+
* Run atomic envelope SQL on a host-provided tenant Oracle connection with explicit commit/rollback.
|
|
2773
|
+
* @param host - Trusted connection provider admitting PLUGIN_RECORDS operations for the verified tenant/user.
|
|
2774
|
+
* @param types - Actual Oracle object-format/string/CLOB constants; no global provider settings are changed.
|
|
2775
|
+
* @returns Oracle transaction driver with optional batch execution and scalar fallback for large strings.
|
|
2776
|
+
* @throws Connection/statement/commit/rollback errors and invalid batch row counts reject; rollback failures may replace the original failure.
|
|
2777
|
+
* @remarks Host owns session authorization, tenant cleanup and connection release. Strings over 4000 characters use explicit CLOB bindings; no production connection is opened at construction.
|
|
2778
|
+
* @example
|
|
2779
|
+
* import { createOracleAtomicDriver } from '@alneas/eaos-server/plugin-data'
|
|
2780
|
+
* export function driver(host: Parameters<typeof createOracleAtomicDriver>[0], types: Parameters<typeof createOracleAtomicDriver>[1]) { return createOracleAtomicDriver(host, types) }
|
|
2781
|
+
*/
|
|
2782
|
+
declare function createOracleAtomicDriver(host: OracleAtomicHost, types: {
|
|
2783
|
+
/**
|
|
2784
|
+
* Actual installed Oracle object-row output format constant.
|
|
2785
|
+
*/
|
|
2786
|
+
objectFormat: number;
|
|
2787
|
+
/**
|
|
2788
|
+
* Actual Oracle string fetch type for JSON PAYLOAD extraction.
|
|
2789
|
+
*/
|
|
2790
|
+
stringType: unknown;
|
|
2791
|
+
/**
|
|
2792
|
+
* Actual Oracle CLOB type used for strings longer than 4000 characters.
|
|
2793
|
+
*/
|
|
2794
|
+
clobType: unknown;
|
|
2795
|
+
}): AtomicSqlDriver;
|
|
2796
|
+
|
|
2797
|
+
export { ArtifactDeliveryService, PluginError, RecordCommandService, ScopedRecordService, annotationOperations, annotationSchemas, appendAtomicAudit, assertPrincipal, atomicCommand, atomicHash, createAtomicOutboxDispatcher, createAtomicOutboxStore, createAtomicRecordStore, createAtomicRepository, createAtomicWorkflowEventSink, createCloudflareD1Driver, createCompositePluginService, createMcpOperationHandler, createMcpToolBinder, createOracleAtomicDriver, createPluginAtomicRepository, createPluginRecordStore, createPluginRouter, createRecordDocumentValidator, createSqlRecordStore, createSqliteAtomicDriver, createStandardPluginServer, createValidatedAtomicRepository, createValidatedRecordHost, createValidatedRecordStore, deliveryJobSchema, deliveryOperations, documentAnnotations, enqueueDeliverySchema, enqueueOutboxEvent, exactKeys, joinedAtomicSqlExecutor, jsonBody, parseRecordCursor, readAtomicAudit, recordCursor, recordDocuments, recoverDeliverySchema, requeueOutboxEvent, revisionInput, textInput, uniqueRecordKey, verifyAtomicAudit };
|
|
2798
|
+
export type { AnnotationTarget, AtomicAuditEvent, AtomicOutboxDispatcherOptions, AtomicOutboxStoreOptions, AtomicRepository, AtomicRepositoryOptions, AtomicRow, AtomicSession, AtomicSqlConnection, AtomicSqlDriver, CloudflareD1Binding, CloudflareD1DriverOptions, CloudflareD1PreparedStatement, CommandContext, CommandHost, CommandResponse, CommandState, DeliveryArtifact, DeliveryJob, DeliveryPorts, DeliveryRequest, OracleAtomicConnection, OracleAtomicHost, PluginHttpEnv, PluginOperationService, PluginPrincipal, PluginRecord, PluginRecordStore, PluginRouterOptions, ReaderComment, RecordSqlDriver, ScopedRecordDefinition, ScopedRecordHost, SqlRecordStoreOptions, SqliteAtomicDatabase };
|