@spine-event-engine/server 2.0.0-snapshot.24 → 2.0.0-snapshot.25
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/README.md +38 -11
- package/REFERENCE.md +201 -130
- package/dist/agent/agent-acceptance-receipts.d.ts +69 -0
- package/dist/agent/agent-acceptance-receipts.d.ts.map +1 -0
- package/dist/agent/agent-acceptance-receipts.js +198 -0
- package/dist/agent/agent-acceptance-receipts.js.map +1 -0
- package/dist/agent/agent-execution-capacity.d.ts +37 -9
- package/dist/agent/agent-execution-capacity.d.ts.map +1 -1
- package/dist/agent/agent-execution-capacity.js +73 -15
- package/dist/agent/agent-execution-capacity.js.map +1 -1
- package/dist/agent/agent-history.d.ts +15 -10
- package/dist/agent/agent-history.d.ts.map +1 -1
- package/dist/agent/agent-history.js +26 -14
- package/dist/agent/agent-history.js.map +1 -1
- package/dist/agent/agent-live-ai-audit.d.ts +95 -0
- package/dist/agent/agent-live-ai-audit.d.ts.map +1 -0
- package/dist/agent/agent-live-ai-audit.js +290 -0
- package/dist/agent/agent-live-ai-audit.js.map +1 -0
- package/dist/agent/agent-live-ai-runtime.d.ts +300 -0
- package/dist/agent/agent-live-ai-runtime.d.ts.map +1 -0
- package/dist/agent/agent-live-ai-runtime.js +611 -0
- package/dist/agent/agent-live-ai-runtime.js.map +1 -0
- package/dist/agent/agent-live-audit.d.ts +67 -0
- package/dist/agent/agent-live-audit.d.ts.map +1 -0
- package/dist/agent/agent-live-audit.js +121 -0
- package/dist/agent/agent-live-audit.js.map +1 -0
- package/dist/agent/agent-live-budget.d.ts +84 -0
- package/dist/agent/agent-live-budget.d.ts.map +1 -0
- package/dist/agent/agent-live-budget.js +161 -0
- package/dist/agent/agent-live-budget.js.map +1 -0
- package/dist/agent/agent-live-fault.d.ts +18 -0
- package/dist/agent/agent-live-fault.d.ts.map +1 -0
- package/dist/agent/{agent-execution-fault.js → agent-live-fault.js} +7 -7
- package/dist/agent/agent-live-fault.js.map +1 -0
- package/dist/agent/agent-live-inputs.d.ts +74 -0
- package/dist/agent/agent-live-inputs.d.ts.map +1 -0
- package/dist/{bus/saved-dispatcher-binding.js → agent/agent-live-inputs.js} +2 -14
- package/dist/agent/agent-live-inputs.js.map +1 -0
- package/dist/agent/agent-live-interaction-events.d.ts +46 -0
- package/dist/agent/agent-live-interaction-events.d.ts.map +1 -0
- package/dist/agent/agent-live-interaction-events.js +104 -0
- package/dist/agent/agent-live-interaction-events.js.map +1 -0
- package/dist/agent/agent-live-mcp-controls.d.ts +129 -0
- package/dist/agent/agent-live-mcp-controls.d.ts.map +1 -0
- package/dist/agent/agent-live-mcp-controls.js +228 -0
- package/dist/agent/agent-live-mcp-controls.js.map +1 -0
- package/dist/agent/agent-live-mcp-host.d.ts +88 -0
- package/dist/agent/agent-live-mcp-host.d.ts.map +1 -0
- package/dist/agent/{agent-mcp-host.js → agent-live-mcp-host.js} +1 -1
- package/dist/agent/agent-live-mcp-host.js.map +1 -0
- package/dist/agent/{agent-mcp-runtime.d.ts → agent-live-mcp-runtime.d.ts} +6 -6
- package/dist/agent/agent-live-mcp-runtime.d.ts.map +1 -0
- package/dist/agent/{agent-mcp-runtime.js → agent-live-mcp-runtime.js} +13 -42
- package/dist/agent/agent-live-mcp-runtime.js.map +1 -0
- package/dist/agent/agent-live-read-runtime.d.ts +61 -0
- package/dist/agent/agent-live-read-runtime.d.ts.map +1 -0
- package/dist/agent/agent-live-read-runtime.js +121 -0
- package/dist/agent/agent-live-read-runtime.js.map +1 -0
- package/dist/agent/agent-model-selection.d.ts +21 -34
- package/dist/agent/agent-model-selection.d.ts.map +1 -1
- package/dist/agent/agent-model-selection.js +61 -78
- package/dist/agent/agent-model-selection.js.map +1 -1
- package/dist/bus/command-bus.d.ts +14 -18
- package/dist/bus/command-bus.d.ts.map +1 -1
- package/dist/bus/command-bus.js +31 -48
- package/dist/bus/command-bus.js.map +1 -1
- package/dist/bus/event-bus.d.ts +17 -4
- package/dist/bus/event-bus.d.ts.map +1 -1
- package/dist/bus/event-bus.js +42 -12
- package/dist/bus/event-bus.js.map +1 -1
- package/dist/context/bounded-context.d.ts +140 -87
- package/dist/context/bounded-context.d.ts.map +1 -1
- package/dist/context/bounded-context.js +702 -329
- package/dist/context/bounded-context.js.map +1 -1
- package/dist/context/entity-inbox.d.ts +7 -2
- package/dist/context/entity-inbox.d.ts.map +1 -1
- package/dist/context/entity-inbox.js +22 -13
- package/dist/context/entity-inbox.js.map +1 -1
- package/dist/context/local-inbox-handoff.d.ts +34 -34
- package/dist/context/local-inbox-handoff.d.ts.map +1 -1
- package/dist/context/local-inbox-handoff.js +108 -150
- package/dist/context/local-inbox-handoff.js.map +1 -1
- package/dist/context/projection-handoff.d.ts +2 -2
- package/dist/context/projection-handoff.d.ts.map +1 -1
- package/dist/context/projection-handoff.js +10 -8
- package/dist/context/projection-handoff.js.map +1 -1
- package/dist/context/tenant-index.d.ts +36 -31
- package/dist/context/tenant-index.d.ts.map +1 -1
- package/dist/context/tenant-index.js +123 -125
- package/dist/context/tenant-index.js.map +1 -1
- package/dist/context/tenant-unknown-error.d.ts +33 -0
- package/dist/context/tenant-unknown-error.d.ts.map +1 -0
- package/dist/context/tenant-unknown-error.js +75 -0
- package/dist/context/tenant-unknown-error.js.map +1 -0
- package/dist/delivery/agent-delivery-scope.d.ts +66 -0
- package/dist/delivery/agent-delivery-scope.d.ts.map +1 -0
- package/dist/delivery/agent-delivery-scope.js +44 -0
- package/dist/delivery/agent-delivery-scope.js.map +1 -0
- package/dist/delivery/delivery-builder.d.ts +25 -1
- package/dist/delivery/delivery-builder.d.ts.map +1 -1
- package/dist/delivery/delivery-builder.js +89 -0
- package/dist/delivery/delivery-builder.js.map +1 -1
- package/dist/delivery/delivery-monitor.d.ts +1 -1
- package/dist/delivery/delivery-monitor.js +1 -1
- package/dist/delivery/delivery-run-control.d.ts +6 -0
- package/dist/delivery/delivery-run-control.d.ts.map +1 -1
- package/dist/delivery/delivery-run-control.js +10 -0
- package/dist/delivery/delivery-run-control.js.map +1 -1
- package/dist/delivery/delivery-supervisor.d.ts.map +1 -1
- package/dist/delivery/delivery-supervisor.js +28 -4
- package/dist/delivery/delivery-supervisor.js.map +1 -1
- package/dist/delivery/delivery-tenant.d.ts +17 -0
- package/dist/delivery/delivery-tenant.d.ts.map +1 -0
- package/dist/delivery/delivery-tenant.js +50 -0
- package/dist/delivery/delivery-tenant.js.map +1 -0
- package/dist/delivery/delivery.d.ts +96 -2
- package/dist/delivery/delivery.d.ts.map +1 -1
- package/dist/delivery/delivery.js +693 -53
- package/dist/delivery/delivery.js.map +1 -1
- package/dist/delivery/inbox-records.d.ts.map +1 -1
- package/dist/delivery/inbox-records.js +9 -16
- package/dist/delivery/inbox-records.js.map +1 -1
- package/dist/delivery/inbox-storage.d.ts +6 -0
- package/dist/delivery/inbox-storage.d.ts.map +1 -1
- package/dist/delivery/inbox-storage.js +43 -6
- package/dist/delivery/inbox-storage.js.map +1 -1
- package/dist/delivery/inbox.d.ts.map +1 -1
- package/dist/delivery/inbox.js +3 -2
- package/dist/delivery/inbox.js.map +1 -1
- package/dist/delivery/reception-observation.d.ts +12 -4
- package/dist/delivery/reception-observation.d.ts.map +1 -1
- package/dist/delivery/reception-observation.js +14 -3
- package/dist/delivery/reception-observation.js.map +1 -1
- package/dist/delivery/sharded-work-registry.d.ts +6 -0
- package/dist/delivery/sharded-work-registry.d.ts.map +1 -1
- package/dist/delivery/sharded-work-registry.js +41 -4
- package/dist/delivery/sharded-work-registry.js.map +1 -1
- package/dist/entity/entity-storage-descriptor.d.ts.map +1 -1
- package/dist/entity/entity-storage-descriptor.js +7 -4
- package/dist/entity/entity-storage-descriptor.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/integration/external-messages.d.ts.map +1 -1
- package/dist/integration/external-messages.js +9 -15
- package/dist/integration/external-messages.js.map +1 -1
- package/dist/integration/integration-broker.d.ts.map +1 -1
- package/dist/integration/integration-broker.js +112 -6
- package/dist/integration/integration-broker.js.map +1 -1
- package/dist/integration/third-party-context.d.ts.map +1 -1
- package/dist/integration/third-party-context.js +7 -10
- package/dist/integration/third-party-context.js.map +1 -1
- package/dist/repository/primitive-id.js +26 -11
- package/dist/repository/primitive-id.js.map +1 -1
- package/dist/repository/repository.d.ts +32 -60
- package/dist/repository/repository.d.ts.map +1 -1
- package/dist/repository/repository.js +1446 -1787
- package/dist/repository/repository.js.map +1 -1
- package/dist/runtime/runtime.d.ts +13 -0
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +18 -0
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/runtime/signal-metadata.d.ts.map +1 -1
- package/dist/runtime/signal-metadata.js +6 -6
- package/dist/runtime/signal-metadata.js.map +1 -1
- package/dist/runtime/signal-publisher.d.ts +0 -6
- package/dist/runtime/signal-publisher.d.ts.map +1 -1
- package/dist/runtime/signal-publisher.js +1 -9
- package/dist/runtime/signal-publisher.js.map +1 -1
- package/dist/runtime/standalone-handler-runtime.d.ts +0 -7
- package/dist/runtime/standalone-handler-runtime.d.ts.map +1 -1
- package/dist/runtime/standalone-handler-runtime.js +13 -99
- package/dist/runtime/standalone-handler-runtime.js.map +1 -1
- package/dist/server/managed-delivery-gate.d.ts +34 -0
- package/dist/server/managed-delivery-gate.d.ts.map +1 -0
- package/dist/server/managed-delivery-gate.js +70 -0
- package/dist/server/managed-delivery-gate.js.map +1 -0
- package/dist/server/managed-server-application.d.ts.map +1 -1
- package/dist/server/managed-server-application.js +7 -4
- package/dist/server/managed-server-application.js.map +1 -1
- package/dist/server/server-environment.d.ts +203 -25
- package/dist/server/server-environment.d.ts.map +1 -1
- package/dist/server/server-environment.js +661 -133
- package/dist/server/server-environment.js.map +1 -1
- package/dist/server/server-log.d.ts +7 -0
- package/dist/server/server-log.d.ts.map +1 -1
- package/dist/server/server-log.js +14 -1
- package/dist/server/server-log.js.map +1 -1
- package/dist/server/server.d.ts +18 -32
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +50 -204
- package/dist/server/server.js.map +1 -1
- package/dist/services/spine-services.d.ts +1 -1
- package/dist/services/spine-services.d.ts.map +1 -1
- package/dist/services/spine-services.js +236 -335
- package/dist/services/spine-services.js.map +1 -1
- package/dist/stand/event-origin-filter.js +3 -3
- package/dist/stand/event-origin-filter.js.map +1 -1
- package/dist/stand/stand.d.ts +14 -0
- package/dist/stand/stand.d.ts.map +1 -1
- package/dist/stand/stand.js +53 -9
- package/dist/stand/stand.js.map +1 -1
- package/dist/stand/subscription-observer.d.ts.map +1 -1
- package/dist/stand/subscription-observer.js +54 -40
- package/dist/stand/subscription-observer.js.map +1 -1
- package/dist/stand/subscription-registry.d.ts +6 -2
- package/dist/stand/subscription-registry.d.ts.map +1 -1
- package/dist/stand/subscription-registry.js +15 -11
- package/dist/stand/subscription-registry.js.map +1 -1
- package/dist/stand/subscription-runtime.d.ts +5 -3
- package/dist/stand/subscription-runtime.d.ts.map +1 -1
- package/dist/stand/subscription-runtime.js +52 -9
- package/dist/stand/subscription-runtime.js.map +1 -1
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +4 -3
- package/dist/testing/index.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +14 -14
- package/dist/agent/agent-admission.d.ts +0 -80
- package/dist/agent/agent-admission.d.ts.map +0 -1
- package/dist/agent/agent-admission.js +0 -127
- package/dist/agent/agent-admission.js.map +0 -1
- package/dist/agent/agent-ai-runtime.d.ts +0 -76
- package/dist/agent/agent-ai-runtime.d.ts.map +0 -1
- package/dist/agent/agent-ai-runtime.js +0 -1269
- package/dist/agent/agent-ai-runtime.js.map +0 -1
- package/dist/agent/agent-execution-fault.d.ts +0 -18
- package/dist/agent/agent-execution-fault.d.ts.map +0 -1
- package/dist/agent/agent-execution-fault.js.map +0 -1
- package/dist/agent/agent-execution-session.d.ts +0 -103
- package/dist/agent/agent-execution-session.d.ts.map +0 -1
- package/dist/agent/agent-execution-session.js +0 -238
- package/dist/agent/agent-execution-session.js.map +0 -1
- package/dist/agent/agent-interaction-audit.d.ts +0 -58
- package/dist/agent/agent-interaction-audit.d.ts.map +0 -1
- package/dist/agent/agent-interaction-audit.js +0 -114
- package/dist/agent/agent-interaction-audit.js.map +0 -1
- package/dist/agent/agent-interaction-events.d.ts +0 -40
- package/dist/agent/agent-interaction-events.d.ts.map +0 -1
- package/dist/agent/agent-interaction-events.js +0 -129
- package/dist/agent/agent-interaction-events.js.map +0 -1
- package/dist/agent/agent-mcp-budget.d.ts +0 -125
- package/dist/agent/agent-mcp-budget.d.ts.map +0 -1
- package/dist/agent/agent-mcp-budget.js +0 -566
- package/dist/agent/agent-mcp-budget.js.map +0 -1
- package/dist/agent/agent-mcp-host.d.ts +0 -125
- package/dist/agent/agent-mcp-host.d.ts.map +0 -1
- package/dist/agent/agent-mcp-host.js.map +0 -1
- package/dist/agent/agent-mcp-runtime.d.ts.map +0 -1
- package/dist/agent/agent-mcp-runtime.js.map +0 -1
- package/dist/agent/agent-read-runtime.d.ts +0 -70
- package/dist/agent/agent-read-runtime.d.ts.map +0 -1
- package/dist/agent/agent-read-runtime.js +0 -320
- package/dist/agent/agent-read-runtime.js.map +0 -1
- package/dist/agent/agent-revisions.d.ts +0 -35
- package/dist/agent/agent-revisions.d.ts.map +0 -1
- package/dist/agent/agent-revisions.js +0 -133
- package/dist/agent/agent-revisions.js.map +0 -1
- package/dist/agent/agent-scheduler.d.ts +0 -99
- package/dist/agent/agent-scheduler.d.ts.map +0 -1
- package/dist/agent/agent-scheduler.js +0 -398
- package/dist/agent/agent-scheduler.js.map +0 -1
- package/dist/bus/saved-dispatcher-binding.d.ts +0 -53
- package/dist/bus/saved-dispatcher-binding.d.ts.map +0 -1
- package/dist/bus/saved-dispatcher-binding.js.map +0 -1
- package/dist/delivery/delivery-run-coordinator.d.ts +0 -218
- package/dist/delivery/delivery-run-coordinator.d.ts.map +0 -1
- package/dist/delivery/delivery-run-coordinator.js +0 -609
- package/dist/delivery/delivery-run-coordinator.js.map +0 -1
- package/dist/delivery/parked-delivery-obligations.d.ts +0 -182
- package/dist/delivery/parked-delivery-obligations.d.ts.map +0 -1
- package/dist/delivery/parked-delivery-obligations.js +0 -390
- package/dist/delivery/parked-delivery-obligations.js.map +0 -1
- package/dist/server/environment-attachment.d.ts +0 -356
- package/dist/server/environment-attachment.d.ts.map +0 -1
- package/dist/server/environment-attachment.js +0 -2062
- package/dist/server/environment-attachment.js.map +0 -1
- package/dist/server/environment-delivery-records.d.ts +0 -77
- package/dist/server/environment-delivery-records.d.ts.map +0 -1
- package/dist/server/environment-delivery-records.js +0 -282
- package/dist/server/environment-delivery-records.js.map +0 -1
- package/dist/server/environment-delivery-worker.d.ts +0 -161
- package/dist/server/environment-delivery-worker.d.ts.map +0 -1
- package/dist/server/environment-delivery-worker.js +0 -973
- package/dist/server/environment-delivery-worker.js.map +0 -1
package/README.md
CHANGED
|
@@ -27,9 +27,10 @@ this shape appropriate for tests and hosts that manage shutdown themselves.
|
|
|
27
27
|
<!-- docs-snippet-path: packages/server/test/server/server-environment.test.ts -->
|
|
28
28
|
|
|
29
29
|
```ts
|
|
30
|
-
import { BoundedContext, Server } from "@spine-event-engine/server";
|
|
30
|
+
import { BoundedContext, Server, ServerEnvironment } from "@spine-event-engine/server";
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
await ServerEnvironment.instance().completeSetup();
|
|
33
|
+
const context = await BoundedContext.singleTenant("Tasks").build();
|
|
33
34
|
const running = await new Server({ contexts: [context], port: 0 }).start();
|
|
34
35
|
try {
|
|
35
36
|
// Native Command, Query, and Subscription services are now listening.
|
|
@@ -39,10 +40,29 @@ try {
|
|
|
39
40
|
```
|
|
40
41
|
|
|
41
42
|
Add generated entities with `BoundedContext.add(...)` and use
|
|
42
|
-
`
|
|
43
|
+
`build()` to assemble the context and load generated repositories when configured. A
|
|
43
44
|
context is single-tenant or multitenant by construction; select that mode
|
|
44
45
|
before registering application handlers and storage.
|
|
45
46
|
|
|
47
|
+
`build()` prepares the current model storage and awaits the first subscription
|
|
48
|
+
registry pass. Set `createStorageStructures: false` or
|
|
49
|
+
`startSubscriptionMonitoring: false` in `build({...})` to defer either phase
|
|
50
|
+
independently until the first valid input. Complete environment setup explicitly
|
|
51
|
+
before building, even when both phases are deferred.
|
|
52
|
+
Starting monitoring still prepares its shared subscription registry when model
|
|
53
|
+
structure creation is deferred; it does not prepare every tenant's Entity storage structures.
|
|
54
|
+
An eager required-phase failure stops accepting new input and triggers environment
|
|
55
|
+
cleanup. A lazy first-input failure rejects that input and can be retried.
|
|
56
|
+
After build, `context.runtime.createStorageStructures(...tenantIds)` explicitly
|
|
57
|
+
creates declared structures; `checkStructureCompatibility(...tenantIds)` checks
|
|
58
|
+
them without creating structures. With no IDs, a multitenant context traverses
|
|
59
|
+
its current tenant index in pages; a single-tenant context prepares its neutral
|
|
60
|
+
destination. `startSubscriptionMonitoring()` starts the initial registry pass
|
|
61
|
+
without preparing every tenant's Entity structures. The environment offers the
|
|
62
|
+
same operations across completed, open contexts, selecting matching multitenant
|
|
63
|
+
contexts for explicit IDs. Database-backed providers require an existing
|
|
64
|
+
database; these operations do not provision one or register tenants.
|
|
65
|
+
|
|
46
66
|
## Give an Entity an application service
|
|
47
67
|
|
|
48
68
|
Spine normally constructs an Entity with its ID, state, version, and lifecycle
|
|
@@ -66,7 +86,7 @@ const builder = BoundedContext.singleTenant("Assignments")
|
|
|
66
86
|
});
|
|
67
87
|
```
|
|
68
88
|
|
|
69
|
-
|
|
89
|
+
Await `builder.build()` to assemble the context. The callback runs for each
|
|
70
90
|
fresh or restored Entity object, not just once per ID. It also works for
|
|
71
91
|
Aggregates and Projections, including Projection rebuilds. Return a fresh
|
|
72
92
|
instance synchronously and pass the supplied options unchanged. Application
|
|
@@ -187,6 +207,13 @@ override. Single-tenant execution uses `SINGLE_TENANT`, even when the request
|
|
|
187
207
|
omits a tenant field. A named tenant cannot query a single-tenant context: that
|
|
188
208
|
fails before reading. See the [query contract](REFERENCE.md#handler-routing-and-operations)
|
|
189
209
|
for the complete tenant rules and empty-result behavior.
|
|
210
|
+
For a multitenant receiving context, explicitly register each accepted tenant
|
|
211
|
+
through `context.tenantIndex.keep(tenantId)` or the configured directory.
|
|
212
|
+
Provider-backed indexes may only confirm existing membership: fixed SQL catalogs
|
|
213
|
+
cannot add tenants, and the Datastore index requires native namespace metadata.
|
|
214
|
+
Use an application-managed `TenantIndex` to register tenants before provider
|
|
215
|
+
data exists or to add tenants dynamically.
|
|
216
|
+
Unknown tenants fail before reads or handlers run; input never registers them.
|
|
190
217
|
|
|
191
218
|
Use `EntityQuery.all(...)` when every predicate must match and
|
|
192
219
|
`EntityQuery.either(...)` when any branch may match.
|
|
@@ -201,7 +228,7 @@ state are declared in Proto and its handlers use generated registration.
|
|
|
201
228
|
|
|
202
229
|
An Agent can read its recorded interactions and emitted domain Events through
|
|
203
230
|
its repository. See the [Agent execution reference](REFERENCE.md#agent-execution)
|
|
204
|
-
for history methods, paging, and
|
|
231
|
+
for history methods, paging, and live execution behavior.
|
|
205
232
|
|
|
206
233
|
Declare the Agent ID and state in Proto, with `option (entity).kind = ENTITY;`
|
|
207
234
|
on the state. The [Support example](https://github.com/SpineEventEngine/spine-ts/blob/master/examples/support/README.md) includes
|
|
@@ -271,16 +298,16 @@ class SupportDraftAgent extends Agent<SupportTicketId, typeof SupportDraftStateS
|
|
|
271
298
|
<!-- prettier-ignore-end -->
|
|
272
299
|
|
|
273
300
|
Configure the registry outside the Entity. The Bounded Context requires persisted System
|
|
274
|
-
Events, and the Agent registration supplies its
|
|
275
|
-
|
|
276
|
-
assembles these settings with the generated handler registry.
|
|
277
|
-
`
|
|
278
|
-
|
|
301
|
+
Events, and the Agent registration supplies its permitted capabilities. The
|
|
302
|
+
[example Bounded Context factory](https://github.com/SpineEventEngine/spine-ts/blob/master/examples/support/src/index.ts)
|
|
303
|
+
assembles these settings with the generated handler registry. Supply the registry
|
|
304
|
+
through `ServerEnvironment.when(type).use({ ai: registry })` as a default, or
|
|
305
|
+
`BoundedContextBuilder.withAi(registry)` for one Bounded Context.
|
|
279
306
|
|
|
280
307
|
Posting a Command awaits acceptance. Model work and the resulting domain Event
|
|
281
308
|
arrive asynchronously afterward. The handling operation can await a model without
|
|
282
309
|
keeping a database transaction open. See the [Agent execution reference](REFERENCE.md#agent-execution)
|
|
283
|
-
for defaults
|
|
310
|
+
for defaults and retained history.
|
|
284
311
|
|
|
285
312
|
## Native lifecycle and routing
|
|
286
313
|
|
package/REFERENCE.md
CHANGED
|
@@ -33,7 +33,7 @@ versioned registries are rejected and must be regenerated.
|
|
|
33
33
|
Generated standalone handlers extend `AbstractAssignee`, `AbstractCommander`,
|
|
34
34
|
`AbstractEventReactor`, or `AbstractEventSubscriber`. Register instances with
|
|
35
35
|
`addAssignee()`, `addCommandDispatcher()`, or `addEventDispatcher()` as their
|
|
36
|
-
role requires, then use `
|
|
36
|
+
role requires, then use `build()` to load generated receiver metadata and
|
|
37
37
|
match the exact constructor. Assignees consume Commands and produce Events;
|
|
38
38
|
commanders consume Commands, Events, or rejections and produce Commands;
|
|
39
39
|
reactors consume Events or rejections and may produce Events; subscribers
|
|
@@ -139,7 +139,8 @@ valid event with no interested external receptor is simply not delivered.
|
|
|
139
139
|
## Server environment facilities
|
|
140
140
|
|
|
141
141
|
`ServerEnvironment.instance()` is a process-wide singleton. Production
|
|
142
|
-
resolution requires
|
|
142
|
+
resolution requires the complete application schema registry; storage defaults to
|
|
143
|
+
in-memory when `storageFactory` is omitted:
|
|
143
144
|
|
|
144
145
|
```ts
|
|
145
146
|
import { EnvironmentType, ServerEnvironment } from "@spine-event-engine/server";
|
|
@@ -153,9 +154,52 @@ ServerEnvironment.when(EnvironmentType.Production).use({
|
|
|
153
154
|
storageFactory,
|
|
154
155
|
typeRegistry,
|
|
155
156
|
});
|
|
157
|
+
await ServerEnvironment.instance().completeSetup();
|
|
156
158
|
```
|
|
157
159
|
|
|
158
|
-
`
|
|
160
|
+
Call `completeSetup()` explicitly before building any Bounded Context. It
|
|
161
|
+
checks the storage connection, initializes integration transport, and opens the
|
|
162
|
+
shared Delivery. Concurrent callers join one setup attempt; a failed attempt
|
|
163
|
+
closes acquired facilities and prevents context assembly. Building a context
|
|
164
|
+
does not start setup. The environment logs an INFO message after each successful
|
|
165
|
+
phase without implying that every Entity model has been prepared.
|
|
166
|
+
|
|
167
|
+
`BoundedContextBuilder.build({ createStorageStructures, startSubscriptionMonitoring })`
|
|
168
|
+
awaits both model preparation and the first subscription reconciliation by
|
|
169
|
+
default. Each option can be set to `false` independently. A deferred phase runs
|
|
170
|
+
before the first valid Command, Event, query, subscription operation, or Inbox
|
|
171
|
+
replay for the receiving context; lazy multitenant preparation selects only that
|
|
172
|
+
input's currently registered tenant. A failed lazy attempt rejects its current
|
|
173
|
+
input and can be retried by a later input. Monitoring requires the shared
|
|
174
|
+
subscription registry, so `startSubscriptionMonitoring: true` prepares that
|
|
175
|
+
registry even when `createStorageStructures: false`; it does not prepare all
|
|
176
|
+
tenant Entity families. An eager required preparation or initial monitoring
|
|
177
|
+
failure stops accepting new input and triggers attempt-all cleanup.
|
|
178
|
+
After a successful first pass, a failed periodic reconciliation logs a WARN
|
|
179
|
+
with the context name and bounded error name or code, leaves unaffected observers active,
|
|
180
|
+
and retries on the existing ten-second schedule. Closing the context cancels
|
|
181
|
+
the timer and drains an admitted pass before detaching observers.
|
|
182
|
+
|
|
183
|
+
`context.runtime.createStorageStructures(...tenantIds)` and
|
|
184
|
+
`context.runtime.checkStructureCompatibility(...tenantIds)` prepare declared
|
|
185
|
+
Record, Entity, history, and Agent audit structures through the configured
|
|
186
|
+
provider. The check is read-only; a successful provider check also satisfies
|
|
187
|
+
later creation readiness. Explicit IDs must be registered in the context's
|
|
188
|
+
effective tenant index. With no IDs, a multitenant context traverses its current
|
|
189
|
+
index in finite pages; a single-tenant context prepares its neutral destination
|
|
190
|
+
without registering a synthetic tenant. `context.runtime.startSubscriptionMonitoring()`
|
|
191
|
+
performs the first registry pass independently of per-tenant Entity preparation.
|
|
192
|
+
The environment's no-argument structure methods include both kinds of completed,
|
|
193
|
+
open context. With explicit IDs, they select only matching multitenant contexts,
|
|
194
|
+
respect each `withTenantIndex` override, and reject an ID absent from all current
|
|
195
|
+
indexes before provider work. They validate every supplied ID before preparing
|
|
196
|
+
any structures. Database-backed providers require an existing database; these
|
|
197
|
+
calls do not provision one or register a tenant. Required explicit provider or initial-monitor
|
|
198
|
+
failure stops new input and triggers automatic cleanup. Unknown or malformed IDs,
|
|
199
|
+
directory lookup failure, and local API misuse reject only that operation;
|
|
200
|
+
lazy first-input provider failures remain request-local and retryable.
|
|
201
|
+
|
|
202
|
+
`storageFactory` supplies records and events to every context. `typeRegistry` is the complete
|
|
159
203
|
application schema universe used by `ThirdPartyContext` to encode outgoing
|
|
160
204
|
imported events. An optional `integrationChannelFactory` overrides the
|
|
161
205
|
process-wide private
|
|
@@ -164,6 +208,26 @@ contexts share one in-memory factory, including in production. Local and test
|
|
|
164
208
|
environments default storage in memory and use the core registry only as a
|
|
165
209
|
fallback; those defaults are not production configuration.
|
|
166
210
|
|
|
211
|
+
`tenantIndex` selects a live application membership directory. When omitted,
|
|
212
|
+
the environment uses its storage factory's native catalog where available, or
|
|
213
|
+
a transient in-memory index for a custom factory without a catalog. The
|
|
214
|
+
transient index lasts only for this environment instance. `contains()` checks
|
|
215
|
+
membership without preparing storage; `keep()` makes a registration visible to
|
|
216
|
+
later reads and may reject for a read-only catalog. PostgreSQL and MySQL
|
|
217
|
+
catalogs expose only configured tenant entries: `keep()` is idempotent for
|
|
218
|
+
those entries and rejects unknown IDs. A dynamic SQL tenant resolver does not
|
|
219
|
+
register or enumerate tenants. Single-tenant contexts do not insert a synthetic
|
|
220
|
+
member into this directory.
|
|
221
|
+
|
|
222
|
+
Multitenant receiving contexts check current index membership before Command,
|
|
223
|
+
Event, query, direct repository/history, and subscription work. Inbox persistence
|
|
224
|
+
and later replay check separately, so removing a tenant prevents saved work from
|
|
225
|
+
restoring it. Input does not call `keep()` implicitly. A confirmed missing member
|
|
226
|
+
raises `TenantUnknownError` with the complete tenant ID and context name; native
|
|
227
|
+
services return `NotFound` with a structured `spine.base.Error` detail whose type
|
|
228
|
+
is `TENANT_UNKNOWN`. Lookup failures remain operational errors. Single-tenant
|
|
229
|
+
work does not consult the directory.
|
|
230
|
+
|
|
167
231
|
To override the default channel factory, add
|
|
168
232
|
`integrationChannelFactory: customFactory` to the same settings object.
|
|
169
233
|
|
|
@@ -265,8 +329,8 @@ callbacks receive that scope as their third argument while they run.
|
|
|
265
329
|
|
|
266
330
|
For contexts registered with one `Server`, the target Entity's type URL selects
|
|
267
331
|
its context. No context name or network request is required. The Server rejects
|
|
268
|
-
duplicate Entity type registrations before
|
|
269
|
-
|
|
332
|
+
duplicate Entity type registrations before opening the listener, identifying
|
|
333
|
+
the type and both contexts. Contexts used without a
|
|
270
334
|
Server retain local querying; separate Servers do not share query routes.
|
|
271
335
|
|
|
272
336
|
Cross-context targets must declare `query` or `full` visibility. This applies
|
|
@@ -282,9 +346,11 @@ partition in a multitenant destination. The query never replaces the tenant to
|
|
|
282
346
|
suit the target. A valid query with no matching record keeps its ordinary empty
|
|
283
347
|
result (`undefined` from `findById()`). Reads remain eventually consistent.
|
|
284
348
|
|
|
285
|
-
Routes are available before
|
|
286
|
-
|
|
287
|
-
|
|
349
|
+
Routes are available before ordinary Inbox work resumes. An accepted Agent
|
|
350
|
+
interaction never resumes after interruption; a fresh signal starts fresh work.
|
|
351
|
+
Server shutdown drains admitted handlers across contexts before closing any
|
|
352
|
+
target read-side; failed startup validation participates in context and
|
|
353
|
+
resource cleanup.
|
|
288
354
|
|
|
289
355
|
```ts
|
|
290
356
|
import type { Message } from "@bufbuild/protobuf";
|
|
@@ -506,7 +572,7 @@ const repository = new Repository<typeof ApprovalCoordinator>({
|
|
|
506
572
|
schema: CoordinationStateSchema,
|
|
507
573
|
handlers: handlers as EntityHandlersMetadata<ApprovalCoordinator, typeof CoordinationStateSchema>,
|
|
508
574
|
});
|
|
509
|
-
const context = BoundedContext.singleTenant("Projects").add(repository).build();
|
|
575
|
+
const context = await BoundedContext.singleTenant("Projects").add(repository).build();
|
|
510
576
|
await context.commandBus().post(
|
|
511
577
|
SignalEnvelopes.command({
|
|
512
578
|
context: create(CommandContextSchema),
|
|
@@ -521,7 +587,7 @@ The generated record declares `ApproveProjectSchema` as the input and
|
|
|
521
587
|
manual decorator materialization, constructs the output-bearing metadata.
|
|
522
588
|
Application builds emit the record to
|
|
523
589
|
`generated/handler/generated-handler-registry.js`; those applications use
|
|
524
|
-
`
|
|
590
|
+
`build()` with their compiled package root.
|
|
525
591
|
|
|
526
592
|
One `@Where({ eventField, equals })` equality filter may narrow an event- or
|
|
527
593
|
rejection-consuming `@Subscribe`, `@React`, or `@Command` handler after type
|
|
@@ -531,18 +597,24 @@ repeated declarations fail closed. It is not an alternative routing mechanism.
|
|
|
531
597
|
Configure logging through `ServerEnvironment` when assembling the server. The
|
|
532
598
|
server installs that logger into its runtime components, where warnings and
|
|
533
599
|
failures carry operation context. Durable facts belong in events or storage.
|
|
534
|
-
|
|
535
|
-
path, so handler effects must be
|
|
600
|
+
Ordinary Aggregate, Process Manager, and Projection Inbox replay sends persisted
|
|
601
|
+
accepted work through the normal handler path, so those handler effects must be
|
|
602
|
+
replay-safe. An accepted Agent interaction is recorded by its receipt and is
|
|
603
|
+
never re-executed after interruption.
|
|
536
604
|
|
|
537
605
|
## Context assembly and entities
|
|
538
606
|
|
|
539
607
|
Create a context with `BoundedContext.singleTenant(name)` or
|
|
540
608
|
`BoundedContext.multitenant(name)`. Names are immutable. Use
|
|
541
|
-
`
|
|
609
|
+
`ServerEnvironment.when(type).use({ storageFactory: factory })` before explicit
|
|
610
|
+
environment setup to supply record/event storage to all contexts.
|
|
611
|
+
`withTenantIndex(index)` selects a different live membership directory for one
|
|
612
|
+
context; `context.tenantIndex` and `ServerEnvironment.instance().tenantIndex`
|
|
613
|
+
return the configured objects. Closing a context does not close either index.
|
|
542
614
|
`withGeneratedRegistryRoot(root)` enables framework discovery of the generated
|
|
543
615
|
handler registry for classes registered with `add(EntityClass)`;
|
|
544
|
-
`
|
|
545
|
-
explicit `Repository` registration. A built context contains `CommandBus`,
|
|
616
|
+
`build()` asynchronously performs that discovery and assembly, including
|
|
617
|
+
explicit `Repository` registration. Await it before using the context. A built context contains `CommandBus`,
|
|
546
618
|
`EventBus`, `Stand`, repositories, and its storage lifecycle.
|
|
547
619
|
Trusted server-side code can call `context.getRepository(EntityClass)` to obtain
|
|
548
620
|
the already registered repository for that exact constructor. The lookup does
|
|
@@ -654,24 +726,24 @@ start a new autonomous Entity loop.
|
|
|
654
726
|
### Configuration
|
|
655
727
|
|
|
656
728
|
Register a factory-created `AiRegistry`, enable `persistSystemEvents()`, and
|
|
657
|
-
configure `
|
|
729
|
+
configure `ai.models` for each Agent repository. Use
|
|
658
730
|
an empty `models` array when that Agent has no model calls. Readiness requires
|
|
659
|
-
indexed Agent history and
|
|
731
|
+
indexed Agent history and atomic live Agent commits from the selected provider.
|
|
660
732
|
The [Support Bounded Context](../../examples/support/src/index.ts) uses generated
|
|
661
733
|
registration with these options.
|
|
662
734
|
|
|
663
735
|
Configuration has these scopes:
|
|
664
736
|
|
|
665
|
-
| Scope | Setting
|
|
666
|
-
| --------------- |
|
|
667
|
-
|
|
|
668
|
-
| Bounded Context | `BoundedContextBuilder.withAi(registry)`
|
|
669
|
-
| Repository | `ai.defaultModels`
|
|
670
|
-
| Repository | `ai.allowedModels`
|
|
671
|
-
| Repository | `ai.resolveModel`
|
|
672
|
-
| Repository | `ai.authorizeSelection`
|
|
673
|
-
| Repository | `ai.invocationLimits`
|
|
674
|
-
| Instance | `this.ai.select(kind, ref)`
|
|
737
|
+
| Scope | Setting | Effect |
|
|
738
|
+
| --------------- | ------------------------------------------ | ---------------------------------------------------------------- |
|
|
739
|
+
| Environment | `ServerEnvironment.when(type).use({ ai })` | Default registry for Bounded Contexts. |
|
|
740
|
+
| Bounded Context | `BoundedContextBuilder.withAi(registry)` | Overrides environment AI for one Bounded Context. |
|
|
741
|
+
| Repository | `ai.defaultModels` | Generation and decision defaults before the registry's defaults. |
|
|
742
|
+
| Repository | `ai.allowedModels` | Deployment references the Agent may use. |
|
|
743
|
+
| Repository | `ai.resolveModel` | Optional accepted-source choice before the Agent handler. |
|
|
744
|
+
| Repository | `ai.authorizeSelection` | Authorizes explicit choices and staged preference changes. |
|
|
745
|
+
| Repository | `ai.invocationLimits` | Limits that can narrow the registry's whole-signal limits. |
|
|
746
|
+
| Instance | `this.ai.select(kind, ref)` | A saved preference applied to later accepted signals. |
|
|
675
747
|
|
|
676
748
|
A prebuilt Bounded Context already has its registry; adding it to a server does not
|
|
677
749
|
reconfigure it. An instance preference takes precedence over its repository
|
|
@@ -687,7 +759,7 @@ signal; `undefined` preserves it. This allows an Agent without a configured
|
|
|
687
759
|
default to start after a deployment is appended to the bound registry. The
|
|
688
760
|
runtime checks repository allowlists, capabilities and `authorizeSelection`
|
|
689
761
|
before saving the selection and connection identity. A saved selection is reused
|
|
690
|
-
|
|
762
|
+
for the current signal. Resolver and authorization callbacks receive linked cancellation
|
|
691
763
|
and the smaller of the invocation deadline and registry hook timeout. An
|
|
692
764
|
effective `this.ai.select()` change, including reset to inheritance, is
|
|
693
765
|
authorized before the Entity transition and preference Events commit; a no-op
|
|
@@ -702,60 +774,30 @@ See [adapter configuration](../ai-vercel-ax/README.md).
|
|
|
702
774
|
|
|
703
775
|
### Acceptance and completion
|
|
704
776
|
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
Bounded Contexts using
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
starts, recovery continues with the saved deadline and counts. The same deadline
|
|
713
|
-
bounds an awaited application handler. Expiry or Bounded Context shutdown ends that wait
|
|
714
|
-
and prevents late handler results from changing Entity state or emitting signals;
|
|
715
|
-
it cannot stop arbitrary application JavaScript or undo external effects.
|
|
716
|
-
|
|
717
|
-
Newly accepted work supplies its repository and tenant to prompt discovery.
|
|
718
|
-
Periodic discovery reads tenant pages and constructs repository scopes as they
|
|
719
|
-
are needed. It retains at most one page of 16 tenants, four periodic scan scopes,
|
|
720
|
-
and 64 scopes awaiting a prompt scan. A turn requests at most one tenant page
|
|
721
|
-
and reads at most four pending-work pages. It does not load the complete tenant
|
|
722
|
-
catalog or retain a scan position for every tenant.
|
|
723
|
-
|
|
724
|
-
A sweep finishes before another begins. The next starts no earlier than five
|
|
725
|
-
seconds after the preceding sweep started, measured by `Time`; longer sweeps
|
|
726
|
-
restart after completion. This lets discovery reach tenants near the end of a
|
|
727
|
-
large catalog and find later admissions on the next sweep. Periodic scans keep
|
|
728
|
-
their turn during new arrivals, including while execution capacity is full.
|
|
729
|
-
A pending catalog request does not block prompt scans of known scopes.
|
|
730
|
-
|
|
731
|
-
Bounded Context shutdown stops waiting for discovery reads even if a provider ignores
|
|
732
|
-
cancellation. Late results cannot submit work or restart scanning. Built-in
|
|
733
|
-
adapters use their available cancellation and timeout controls; detaching the
|
|
734
|
-
scheduler does not guarantee cancellation of an already issued native request.
|
|
777
|
+
An accepted signal and recipient are admitted through ordinary Delivery. A
|
|
778
|
+
typed receipt prevents a duplicate signal from starting the same Agent turn.
|
|
779
|
+
Within one process, live capacity serializes turns for one Agent instance and
|
|
780
|
+
permits different instances up to configured limits. The shared registry's
|
|
781
|
+
capacity applies across Bounded Contexts using that registry. A waiting signal
|
|
782
|
+
stays in the ordinary Inbox until capacity can admit it; capacity release wakes
|
|
783
|
+
the ordinary Delivery worker. There is no Agent-specific discovery scheduler.
|
|
735
784
|
|
|
736
785
|
The signal's matching handlers share one Entity draft. Each handler can await
|
|
737
|
-
`this.ai.invoke()` through the protected Spine facade. Calls in one handler
|
|
738
|
-
be sequential and finish before it returns. Requests, results and
|
|
739
|
-
validation failures are saved as
|
|
740
|
-
state, Version,
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
normal EventBus. The Agent does not track Event recipients, retry a failed handoff,
|
|
753
|
-
or replay Event delivery after restart. Immutable Agent history remains readable
|
|
754
|
-
independently of EventBus delivery. Saved outgoing Commands retain their original
|
|
755
|
-
IDs and recipient bindings for recovery without rerunning the producing handler
|
|
756
|
-
or model. Generated repository and standalone Command receivers provide the
|
|
757
|
-
required binding metadata; matching raw custom Command dispatchers without it
|
|
758
|
-
are rejected.
|
|
786
|
+
`this.ai.invoke()` through the protected Spine facade. Calls in one handler
|
|
787
|
+
must be sequential and finish before it returns. Requests, results, and
|
|
788
|
+
validation failures are saved as audited history while work progresses. The
|
|
789
|
+
final accepted state, Version, preference changes, and Agent history use an
|
|
790
|
+
atomic live Agent commit. Outgoing Commands enter ordinary command delivery;
|
|
791
|
+
there is no saved Agent-private list to finish after a restart. Emitted domain Events
|
|
792
|
+
enter immutable Agent history before normal EventBus publication. A no-op or
|
|
793
|
+
preference-only turn can commit without a state Version increase. Waiting for a
|
|
794
|
+
provider does not hold a database transaction open.
|
|
795
|
+
|
|
796
|
+
An admitted turn uses a current session and cancellation guard. Shutdown drains
|
|
797
|
+
tracked work and prevents late results from changing Entity state or emitting
|
|
798
|
+
signals. It cannot undo external effects already performed by application code.
|
|
799
|
+
A restarted process can read retained receipts and audit history, but it does
|
|
800
|
+
not replay a model response or re-enter an interrupted Agent handler.
|
|
759
801
|
|
|
760
802
|
### Retained history
|
|
761
803
|
|
|
@@ -775,7 +817,7 @@ persistent provider when records must survive process termination.
|
|
|
775
817
|
All methods return newest entries first. A request supplies positive `pageSize`
|
|
776
818
|
and an optional opaque cursor; `nextCursor` continues toward older entries.
|
|
777
819
|
There is no fixed 100-item or page-byte ceiling. Reads made during a handler count
|
|
778
|
-
toward any configured invocation limits for recorded reads
|
|
820
|
+
toward any configured invocation limits for recorded reads. Ordering
|
|
779
821
|
uses the full Spine `Time` timestamp, category and existing record ID. There is
|
|
780
822
|
no repository-managed history counter. Cursors cannot be transferred across
|
|
781
823
|
Agents, tenants, categories or conversations.
|
|
@@ -795,19 +837,15 @@ For a trusted application bridge, `context.getRepository(AgentClass)` returns
|
|
|
795
837
|
the registered Agent `Repository`, which exposes
|
|
796
838
|
`agentHistory(id, scope)` with the same four history methods and page contracts.
|
|
797
839
|
The scope is explicit: pass `{}` in a single-tenant Bounded Context or
|
|
798
|
-
`{ tenantId }` in a multitenant Bounded Context.
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
Agent claim time, the execution becomes `terminated` with one
|
|
808
|
-
`AgentInvocationTerminated` System Event carrying `MODEL_USE_DENIED`. No Agent
|
|
809
|
-
handler runs and no application-domain result Event is emitted. Callback
|
|
810
|
-
exceptions and infrastructure failures remain distinct from this denial.
|
|
840
|
+
`{ tenantId }` in a multitenant Bounded Context. Reads use indexed storage
|
|
841
|
+
without restoring an Agent. The application bridge must authorize access;
|
|
842
|
+
actor metadata does not grant read permission.
|
|
843
|
+
|
|
844
|
+
If a selected model's `authorizeUse` callback explicitly returns `false`
|
|
845
|
+
before the handler, the turn records one `AgentInvocationTerminated` System
|
|
846
|
+
Event carrying `MODEL_USE_DENIED`. No handler runs, no application-domain
|
|
847
|
+
result Event is invented, and other failures remain distinct. Applications
|
|
848
|
+
may correlate this fact with the original source through paged Agent history.
|
|
811
849
|
|
|
812
850
|
## Signals, validation, and rejection behavior
|
|
813
851
|
|
|
@@ -815,8 +853,10 @@ exceptions and infrastructure failures remain distinct from this denial.
|
|
|
815
853
|
before dispatcher or repository handler code runs. It raises the framework's
|
|
816
854
|
command-validation failure, which `SpineServices` maps to
|
|
817
855
|
`COMMAND_VALIDATION_ERROR` with a packed `spine.validation.ValidationError`.
|
|
818
|
-
Entity transition validation failures map to
|
|
819
|
-
`COMMAND_STATE_TRANSITION_VALIDATION_FAILED` with the same detail type.
|
|
856
|
+
Entity transition validation failures that escape service processing map to
|
|
857
|
+
`COMMAND_STATE_TRANSITION_VALIDATION_FAILED` with the same detail type. Managed
|
|
858
|
+
reception of ordinary Entity work sends post-handler transition rejection to `DeliveryMonitor`;
|
|
859
|
+
its default action acknowledges the failed input without storing invalid state.
|
|
820
860
|
Framework-created runtime command and event metadata uses fresh Node secure
|
|
821
861
|
UUIDs; fixed IDs belong only to existing source envelopes retained through the
|
|
822
862
|
normal origin chain.
|
|
@@ -1021,7 +1061,9 @@ delivery, global update ordering, nor cluster-complete notification delivery.
|
|
|
1021
1061
|
## Delivery and environment
|
|
1022
1062
|
|
|
1023
1063
|
`Inbox`, `InboxStorage`, `ShardIndex`, and `ShardedWorkRegistry` provide the
|
|
1024
|
-
local durable-row abstraction.
|
|
1064
|
+
local durable-row abstraction. Inbox and shard storage require a single-tenant
|
|
1065
|
+
Delivery storage context shared by all tenants; the packed signal supplies
|
|
1066
|
+
the dispatch tenant. Read limits are 1–1000; work leases are
|
|
1025
1067
|
1000–2147483647 ms. Framework replay supports command handling, projection
|
|
1026
1068
|
updates, and process-manager reactions. Callbacks are at-least-once/replay-safe:
|
|
1027
1069
|
lost renewal can prevent stale finalization but cannot undo a callback already
|
|
@@ -1059,24 +1101,53 @@ without an atomic compare-and-delete guarantee from this client. Pending,
|
|
|
1059
1101
|
retryable, non-delivered, and still-protected rows are skipped by cleanup. There
|
|
1060
1102
|
is no additional retention configuration, timer, or scheduler.
|
|
1061
1103
|
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
use the public builder chain:
|
|
1104
|
+
Configure one Delivery strategy for the environment before setup. It maps
|
|
1105
|
+
targets to shards across all contexts; the default is one shard. For example:
|
|
1065
1106
|
|
|
1066
1107
|
```ts
|
|
1067
|
-
import {
|
|
1108
|
+
import {
|
|
1109
|
+
BoundedContext,
|
|
1110
|
+
EnvironmentType,
|
|
1111
|
+
ServerEnvironment,
|
|
1112
|
+
UniformAcrossAllShards,
|
|
1113
|
+
} from "@spine-event-engine/server";
|
|
1068
1114
|
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1115
|
+
ServerEnvironment.when(EnvironmentType.Local).use({
|
|
1116
|
+
deliveryStrategy: UniformAcrossAllShards.forNumber(3),
|
|
1117
|
+
});
|
|
1118
|
+
await ServerEnvironment.instance().completeSetup();
|
|
1119
|
+
const context = await BoundedContext.singleTenant("Tasks").build();
|
|
1072
1120
|
```
|
|
1073
1121
|
|
|
1074
1122
|
Aggregate commands and Process Manager or Agent commands/events derive their target shard
|
|
1075
1123
|
internally and persist their envelope in the target Entity Inbox before any
|
|
1076
|
-
handler runs.
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1124
|
+
handler runs. Projection input uses the same environment Delivery and shared
|
|
1125
|
+
Inbox, with its separate recipient identity.
|
|
1126
|
+
|
|
1127
|
+
Local posting waits for the result of that signal's delivery attempt. For an
|
|
1128
|
+
Agent, successful acceptance and Inbox acknowledgement let posting finish while
|
|
1129
|
+
the live handler continues. If Agent execution capacity is unavailable, the input
|
|
1130
|
+
stays pending and the local call reports the existing command-posting error.
|
|
1131
|
+
|
|
1132
|
+
With remote Delivery and its environment supervisor, posting completes after the
|
|
1133
|
+
remote Inbox accepts the input and the shard notification is submitted. Processing
|
|
1134
|
+
may still be pending on another process. For example, importing an Event can return
|
|
1135
|
+
while another process holds its shard; the Projection update arrives after that
|
|
1136
|
+
process can dispatch the Event. Reception alone does not acknowledge delivery,
|
|
1137
|
+
create an Agent acceptance receipt, or prove that a handler ran.
|
|
1138
|
+
|
|
1139
|
+
A rejected remote receive operation rejects posting. If a local notification
|
|
1140
|
+
observer fails after reception succeeds, the failure is logged and the existing
|
|
1141
|
+
notifications and safety scan can find the pending work. The environment selects
|
|
1142
|
+
this behavior from its installed supervision; contexts have no attachment step or
|
|
1143
|
+
completion switch. Supplying custom ports without a source does not install remote
|
|
1144
|
+
supervision. Explicit `Delivery.run()` still returns the actual run result,
|
|
1145
|
+
including `SKIPPED` when another process is handling the shard.
|
|
1146
|
+
For ordinary Entity Inbox work, post-handler output and transition validation
|
|
1147
|
+
failures reach the reception monitor. Pre-handler input and routing errors and
|
|
1148
|
+
storage failures remain outside that monitor. Accepted Agent work has already
|
|
1149
|
+
acknowledged its Inbox row and does not enter this reception action. A detached
|
|
1150
|
+
run that throws emits a contained terminal error without exposing its message.
|
|
1080
1151
|
|
|
1081
1152
|
`DeliveryBuilder` constructs a controlled `Delivery`; `DeliverySupervisor`
|
|
1082
1153
|
receives `{ source, delivery, onMessage }`, manages bounded shard notifications
|
|
@@ -1141,33 +1212,33 @@ work, and then closes buses, subscriptions, Stands, and repository bindings.
|
|
|
1141
1212
|
Cleanup failures are aggregated and may be retried. A committed Entity Event,
|
|
1142
1213
|
reactor or Process Manager Event, and System Event receives one first-publication
|
|
1143
1214
|
attempt; a contained failure is logged and does not schedule publication again.
|
|
1144
|
-
Persisted System Events use a
|
|
1215
|
+
Persisted System Events use a storage group derived from their System Context
|
|
1216
|
+
name and role, separate from domain Event history. Command acceptance
|
|
1145
1217
|
alone does not promise recipient completion. Processing retries for Inbox rows
|
|
1146
1218
|
and acknowledgement recovery remain separate Delivery behavior.
|
|
1147
1219
|
|
|
1148
1220
|
`Environment` resolves the Node `local` or `production` profile once from
|
|
1149
1221
|
`NODE_ENV`. `ServerEnvironment` resolves configured facilities once for that
|
|
1150
|
-
profile and exposes its `storageFactory`,
|
|
1151
|
-
`
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
environment: attachment supervisors and their source reads belong to that facility.
|
|
1222
|
+
profile and exposes its `storageFactory`, `tenantIndex`, `nodeId`, and
|
|
1223
|
+
`close()` lifecycle. A healthy close with active contexts rejects without
|
|
1224
|
+
teardown; after required startup failure, close joins automatic cleanup and
|
|
1225
|
+
reports the original cause plus cleanup failures. After explicit
|
|
1226
|
+
`completeSetup()`, its `delivery` property
|
|
1227
|
+
is the usable shared public `Delivery` facade. A Bounded Context cannot build
|
|
1228
|
+
before setup, and a server does not start setup on the application's behalf.
|
|
1229
|
+
Neither API authenticates requests or supplies remote topology or a deployment
|
|
1230
|
+
policy.
|
|
1231
|
+
|
|
1232
|
+
`ServerEnvironmentDelivery` supplies an optional remote facility with `open()`,
|
|
1233
|
+
`inbox`, and `workRegistry` ports. Setup opens it once before creating the
|
|
1234
|
+
shared Delivery; failure closes acquired facilities. Its optional `source`
|
|
1235
|
+
supports remote shard snapshots and notifications through the environment's
|
|
1236
|
+
single supervisor. Local Delivery uses the environment's configured storage
|
|
1237
|
+
factory for its shared Inbox and work registry; the default factory is in-memory.
|
|
1238
|
+
Contexts register recipients with the same Delivery and never close that shared
|
|
1239
|
+
facility individually. Environment shutdown stops intake, drains local admitted
|
|
1240
|
+
work, then closes shared Delivery and configured facilities. Pending remote rows
|
|
1241
|
+
do not make a closing context wait indefinitely for other processes to finish.
|
|
1171
1242
|
|
|
1172
1243
|
## Signal identity and Aggregate semantics
|
|
1173
1244
|
|