@spine-event-engine/server 2.0.0-snapshot.25 → 2.0.0-snapshot.26
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 +49 -9
- package/REFERENCE.md +339 -22
- package/dist/agent/agent-history.d.ts +19 -3
- package/dist/agent/agent-history.d.ts.map +1 -1
- package/dist/agent/agent-history.js +41 -10
- package/dist/agent/agent-history.js.map +1 -1
- package/dist/agent/agent-live-read-runtime.d.ts +12 -1
- package/dist/agent/agent-live-read-runtime.d.ts.map +1 -1
- package/dist/agent/agent-live-read-runtime.js +5 -4
- package/dist/agent/agent-live-read-runtime.js.map +1 -1
- package/dist/browser/browser-server.d.ts +163 -0
- package/dist/browser/browser-server.d.ts.map +1 -1
- package/dist/browser/browser-server.js +579 -188
- package/dist/browser/browser-server.js.map +1 -1
- package/dist/browser/durable-subscription-bindings.d.ts +5 -0
- package/dist/browser/durable-subscription-bindings.d.ts.map +1 -1
- package/dist/browser/durable-subscription-bindings.js +226 -38
- package/dist/browser/durable-subscription-bindings.js.map +1 -1
- package/dist/browser/options.d.ts +5 -0
- package/dist/browser/options.d.ts.map +1 -1
- package/dist/bus/command-bus.d.ts +3 -0
- package/dist/bus/command-bus.d.ts.map +1 -1
- package/dist/bus/command-bus.js +69 -9
- package/dist/bus/command-bus.js.map +1 -1
- package/dist/bus/command-errors.d.ts +20 -4
- package/dist/bus/command-errors.d.ts.map +1 -1
- package/dist/bus/command-errors.js +47 -7
- package/dist/bus/command-errors.js.map +1 -1
- package/dist/bus/event-bus.d.ts +3 -0
- package/dist/bus/event-bus.d.ts.map +1 -1
- package/dist/bus/event-bus.js +130 -8
- package/dist/bus/event-bus.js.map +1 -1
- package/dist/context/bounded-context.d.ts +29 -11
- package/dist/context/bounded-context.d.ts.map +1 -1
- package/dist/context/bounded-context.js +147 -186
- package/dist/context/bounded-context.js.map +1 -1
- package/dist/entity/entity.d.ts +59 -0
- package/dist/entity/entity.d.ts.map +1 -1
- package/dist/entity/entity.js +60 -0
- package/dist/entity/entity.js.map +1 -1
- package/dist/handler/app-query-handler.d.ts +60 -0
- package/dist/handler/app-query-handler.d.ts.map +1 -0
- package/dist/handler/app-query-handler.js +23 -0
- package/dist/handler/app-query-handler.js.map +1 -0
- package/dist/handler/generated-registry-discovery.d.ts +6 -0
- package/dist/handler/generated-registry-discovery.d.ts.map +1 -1
- package/dist/handler/generated-registry-discovery.js +71 -2
- package/dist/handler/generated-registry-discovery.js.map +1 -1
- package/dist/handler/handler-decorators.d.ts +8 -29
- package/dist/handler/handler-decorators.d.ts.map +1 -1
- package/dist/handler/handler-decorators.js +33 -210
- package/dist/handler/handler-decorators.js.map +1 -1
- package/dist/handler/spine-metadata-inventory.d.ts +99 -0
- package/dist/handler/spine-metadata-inventory.d.ts.map +1 -0
- package/dist/handler/spine-metadata-inventory.js +162 -0
- package/dist/handler/spine-metadata-inventory.js.map +1 -0
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/repository/repository.d.ts +44 -1
- package/dist/repository/repository.d.ts.map +1 -1
- package/dist/repository/repository.js +368 -88
- package/dist/repository/repository.js.map +1 -1
- package/dist/server/managed-server-application.d.ts +12 -11
- package/dist/server/managed-server-application.d.ts.map +1 -1
- package/dist/server/managed-server-application.js +41 -25
- package/dist/server/managed-server-application.js.map +1 -1
- package/dist/server/node-coordinator.d.ts +18 -5
- package/dist/server/node-coordinator.d.ts.map +1 -1
- package/dist/server/node-coordinator.js +554 -84
- package/dist/server/node-coordinator.js.map +1 -1
- package/dist/server/reserved-spine-rpc-paths.json +1 -0
- package/dist/server/server-environment.d.ts +17 -0
- package/dist/server/server-environment.d.ts.map +1 -1
- package/dist/server/server-environment.js +77 -16
- package/dist/server/server-environment.js.map +1 -1
- package/dist/server/server.d.ts +45 -0
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +111 -3
- package/dist/server/server.js.map +1 -1
- package/dist/services/app-query-execution.d.ts +53 -0
- package/dist/services/app-query-execution.d.ts.map +1 -0
- package/dist/services/app-query-execution.js +408 -0
- package/dist/services/app-query-execution.js.map +1 -0
- package/dist/services/query-reader.d.ts +32 -7
- package/dist/services/query-reader.d.ts.map +1 -1
- package/dist/services/query-reader.js +22 -2
- package/dist/services/query-reader.js.map +1 -1
- package/dist/services/read-request-status.d.ts +65 -0
- package/dist/services/read-request-status.d.ts.map +1 -0
- package/dist/services/read-request-status.js +151 -0
- package/dist/services/read-request-status.js.map +1 -0
- package/dist/services/spine-services.d.ts +36 -7
- package/dist/services/spine-services.d.ts.map +1 -1
- package/dist/services/spine-services.js +900 -168
- package/dist/services/spine-services.js.map +1 -1
- package/dist/services/trusted-reader-ingress.d.ts +92 -0
- package/dist/services/trusted-reader-ingress.d.ts.map +1 -0
- package/dist/services/trusted-reader-ingress.js +89 -0
- package/dist/services/trusted-reader-ingress.js.map +1 -0
- package/dist/spi/handler-registry.d.ts +2 -0
- package/dist/spi/handler-registry.d.ts.map +1 -1
- package/dist/spi/handler-registry.js +1 -1
- package/dist/spi/handler-registry.js.map +1 -1
- package/dist/stand/read-side-filter-engine.d.ts +46 -0
- package/dist/stand/read-side-filter-engine.d.ts.map +1 -0
- package/dist/stand/read-side-filter-engine.js +356 -0
- package/dist/stand/read-side-filter-engine.js.map +1 -0
- package/dist/stand/read-side-filter.d.ts +247 -0
- package/dist/stand/read-side-filter.d.ts.map +1 -0
- package/dist/stand/read-side-filter.js +39 -0
- package/dist/stand/read-side-filter.js.map +1 -0
- package/dist/stand/read-side-message.d.ts +66 -0
- package/dist/stand/read-side-message.d.ts.map +1 -0
- package/dist/stand/read-side-message.js +167 -0
- package/dist/stand/read-side-message.js.map +1 -0
- package/dist/stand/stand-direct-delivery.d.ts +161 -0
- package/dist/stand/stand-direct-delivery.d.ts.map +1 -0
- package/dist/stand/stand-direct-delivery.js +210 -0
- package/dist/stand/stand-direct-delivery.js.map +1 -0
- package/dist/stand/stand.d.ts +80 -42
- package/dist/stand/stand.d.ts.map +1 -1
- package/dist/stand/stand.js +410 -54
- package/dist/stand/stand.js.map +1 -1
- package/dist/stand/subscription-observer.d.ts.map +1 -1
- package/dist/stand/subscription-observer.js +103 -0
- package/dist/stand/subscription-observer.js.map +1 -1
- package/dist/stand/subscription-read-filters.d.ts +40 -0
- package/dist/stand/subscription-read-filters.d.ts.map +1 -0
- package/dist/stand/subscription-read-filters.js +91 -0
- package/dist/stand/subscription-read-filters.js.map +1 -0
- package/dist/stand/subscription-reader-binding.d.ts +20 -0
- package/dist/stand/subscription-reader-binding.d.ts.map +1 -0
- package/dist/stand/subscription-reader-binding.js +56 -0
- package/dist/stand/subscription-reader-binding.js.map +1 -0
- package/dist/stand/subscription-records.d.ts +30 -3
- package/dist/stand/subscription-records.d.ts.map +1 -1
- package/dist/stand/subscription-records.js +61 -16
- package/dist/stand/subscription-records.js.map +1 -1
- package/dist/stand/subscription-registry.d.ts +49 -14
- package/dist/stand/subscription-registry.d.ts.map +1 -1
- package/dist/stand/subscription-registry.js +150 -31
- package/dist/stand/subscription-registry.js.map +1 -1
- package/dist/stand/subscription-runtime.d.ts +7 -2
- package/dist/stand/subscription-runtime.d.ts.map +1 -1
- package/dist/stand/subscription-runtime.js +131 -25
- package/dist/stand/subscription-runtime.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +14 -14
package/README.md
CHANGED
|
@@ -14,7 +14,8 @@ pnpm add @spine-event-engine/server@snapshot
|
|
|
14
14
|
```
|
|
15
15
|
|
|
16
16
|
Use Node.js in ESM mode. Before adding entities, generate your application
|
|
17
|
-
model and handler
|
|
17
|
+
model and handler metadata with `@spine-event-engine/proto-tools`, then import
|
|
18
|
+
`generated/spine-bootstrap.js` before assembly. The small
|
|
18
19
|
example below has no entity handlers, so it is useful for proving that native
|
|
19
20
|
assembly, listener startup, and cleanup work locally.
|
|
20
21
|
|
|
@@ -78,14 +79,16 @@ import { TaskAssignment, type AssignmentWeightService } from "../src/index.js";
|
|
|
78
79
|
|
|
79
80
|
// Create shared services before starting the context.
|
|
80
81
|
const weights: AssignmentWeightService = { weightFor: () => 2 };
|
|
81
|
-
const builder = BoundedContext.singleTenant("Assignments")
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
onCreate: (options) => new TaskAssignment(options, weights),
|
|
86
|
-
});
|
|
82
|
+
const builder = BoundedContext.singleTenant("Assignments").add(TaskAssignment, {
|
|
83
|
+
// Forward Spine's options and add the service required by the constructor.
|
|
84
|
+
onCreate: (options) => new TaskAssignment(options, weights),
|
|
85
|
+
});
|
|
87
86
|
```
|
|
88
87
|
|
|
88
|
+
The application's `src/index.js` imports its generated `spine-bootstrap.js`
|
|
89
|
+
before assembly, so `add(TaskAssignment)` finds the passive metadata for that
|
|
90
|
+
exact class.
|
|
91
|
+
|
|
89
92
|
Await `builder.build()` to assemble the context. The callback runs for each
|
|
90
93
|
fresh or restored Entity object, not just once per ID. It also works for
|
|
91
94
|
Aggregates and Projections, including Projection rebuilds. Return a fresh
|
|
@@ -202,6 +205,28 @@ Bounded Contexts causes a startup error.
|
|
|
202
205
|
The [Orders example](https://github.com/SpineEventEngine/spine-ts/blob/master/examples/orders/README.md#cross-context-order-review)
|
|
203
206
|
shows this in an Event handler and includes a runnable integration test.
|
|
204
207
|
|
|
208
|
+
Application queries use generated `_queries.proto` request/response companions.
|
|
209
|
+
Pass concrete `AppQueryHandler<Q, R>` instances in `ServerOptions.appQueries`;
|
|
210
|
+
generated metadata alone never enables a route. On direct app-node ingress,
|
|
211
|
+
`QueryService.Execute` validates the wire envelope and Q before dispatch.
|
|
212
|
+
Native and browser Gateways forward Execute to the app node; `ClientRequest.query(generatedQ)`
|
|
213
|
+
returns the wire `Response` and zero or one decoded paired results. Application code calls
|
|
214
|
+
`server.query(generatedQ, executionContext)` and receives the paired generated R.
|
|
215
|
+
The trusted execution context supplies the current `actorContext`, optional
|
|
216
|
+
verified principal and authority facts, and an optional cancellation signal.
|
|
217
|
+
For a Process Manager or Agent, inject a Server-bound query function through the
|
|
218
|
+
repository's `onCreate` callback and use `currentActorContext` only inside an
|
|
219
|
+
active handler. That actor metadata does not prove authentication. Source reads
|
|
220
|
+
from an application query use registered query-visible Entity routes and enforce
|
|
221
|
+
the destination's tenant membership; a handler that performs no source read has
|
|
222
|
+
no destination tenant to check. Direct calls do not run Server output filters.
|
|
223
|
+
|
|
224
|
+
The [typed callback example](REFERENCE.md#services-reads-and-lifecycle) shows
|
|
225
|
+
the repository `onCreate` injection and active handler call. The actor/tenant
|
|
226
|
+
snapshot supplies no verified principal or provider facts; the
|
|
227
|
+
[scoped integration test](https://github.com/SpineEventEngine/spine-ts/blob/master/packages/server/test/entity/process-manager-querying.test.ts) shows
|
|
228
|
+
the complete repository setup.
|
|
229
|
+
|
|
205
230
|
Queries preserve the handler's actor and effective tenant; there is no tenant
|
|
206
231
|
override. Single-tenant execution uses `SINGLE_TENANT`, even when the request
|
|
207
232
|
omits a tenant field. A named tenant cannot query a single-tenant context: that
|
|
@@ -300,7 +325,7 @@ class SupportDraftAgent extends Agent<SupportTicketId, typeof SupportDraftStateS
|
|
|
300
325
|
Configure the registry outside the Entity. The Bounded Context requires persisted System
|
|
301
326
|
Events, and the Agent registration supplies its permitted capabilities. The
|
|
302
327
|
[example Bounded Context factory](https://github.com/SpineEventEngine/spine-ts/blob/master/examples/support/src/index.ts)
|
|
303
|
-
assembles these settings with
|
|
328
|
+
assembles these settings with generated passive handler metadata. Supply the AI registry
|
|
304
329
|
through `ServerEnvironment.when(type).use({ ai: registry })` as a default, or
|
|
305
330
|
`BoundedContextBuilder.withAi(registry)` for one Bounded Context.
|
|
306
331
|
|
|
@@ -364,7 +389,7 @@ field. Event routing uses a compatible producer ID when available and otherwise
|
|
|
364
389
|
uses the Event's declared first field. State-update routing selects the first
|
|
365
390
|
state field compatible with the Entity ID.
|
|
366
391
|
|
|
367
|
-
## Browser gateway
|
|
392
|
+
## Browser gateway setup
|
|
368
393
|
|
|
369
394
|
The server root has no browser options and does not load auth. To host a
|
|
370
395
|
browser-facing Gateway, install the optional auth peer and import the browser
|
|
@@ -386,6 +411,21 @@ and backend forwarding. Authenticated durable bindings are browser-host
|
|
|
386
411
|
infrastructure, not native `Server` state. See the [browser/auth extension guide](https://github.com/SpineEventEngine/spine-ts/blob/master/docs/BROWSER_CLIENT_AUTH_EXTENSION_GUIDE.md)
|
|
387
412
|
before exposing a backend to a browser.
|
|
388
413
|
|
|
414
|
+
## Native reader admission
|
|
415
|
+
|
|
416
|
+
Native authentication is configured through `ServerOptions.services.readerAdmission`.
|
|
417
|
+
Use `direct` to authenticate native callers or `forwarded` to verify reader
|
|
418
|
+
assertions from an authenticated gateway. For browser forwarding, supply the
|
|
419
|
+
corresponding issuer as `BrowserServerOptions.forwardingProof`. Configure both
|
|
420
|
+
ends; the backend does not trust an actor ID or incoming identity header by
|
|
421
|
+
itself. With neither admission adapter configured, the native server remains
|
|
422
|
+
public and supplies no authenticated principal or authority facts.
|
|
423
|
+
|
|
424
|
+
Subscription activation and cancellation also check the admitted principal
|
|
425
|
+
against the stored reader binding. A different principal cannot reuse a
|
|
426
|
+
subscription even with the same ActorContext. See [native reader admission](REFERENCE.md#native-reader-admission)
|
|
427
|
+
for adapter signatures, public admission, and managed application configuration.
|
|
428
|
+
|
|
389
429
|
## Limits
|
|
390
430
|
|
|
391
431
|
This package does not create an identity provider, browser session store,
|
package/REFERENCE.md
CHANGED
|
@@ -585,9 +585,8 @@ await context.commandBus().post(
|
|
|
585
585
|
The generated record declares `ApproveProjectSchema` as the input and
|
|
586
586
|
`ScheduleProjectSchema` as the emitted Command schema; registry ingestion, not
|
|
587
587
|
manual decorator materialization, constructs the output-bearing metadata.
|
|
588
|
-
Application builds emit the record to
|
|
589
|
-
`generated/
|
|
590
|
-
`build()` with their compiled package root.
|
|
588
|
+
Application builds emit the record to `generated/spine-metadata.js` and import
|
|
589
|
+
`generated/spine-bootstrap.js` before `build()` selects registered classes.
|
|
591
590
|
|
|
592
591
|
One `@Where({ eventField, equals })` equality filter may narrow an event- or
|
|
593
592
|
rejection-consuming `@Subscribe`, `@React`, or `@Command` handler after type
|
|
@@ -611,9 +610,9 @@ environment setup to supply record/event storage to all contexts.
|
|
|
611
610
|
`withTenantIndex(index)` selects a different live membership directory for one
|
|
612
611
|
context; `context.tenantIndex` and `ServerEnvironment.instance().tenantIndex`
|
|
613
612
|
return the configured objects. Closing a context does not close either index.
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
613
|
+
The application imports its generated `spine-bootstrap.js` before registering
|
|
614
|
+
classes with `add(EntityClass)`; `build()` then selects passive descriptions
|
|
615
|
+
by exact constructor and performs assembly, including
|
|
617
616
|
explicit `Repository` registration. Await it before using the context. A built context contains `CommandBus`,
|
|
618
617
|
`EventBus`, `Stand`, repositories, and its storage lifecycle.
|
|
619
618
|
Trusted server-side code can call `context.getRepository(EntityClass)` to obtain
|
|
@@ -631,13 +630,12 @@ registry shapes with an instruction to regenerate.
|
|
|
631
630
|
Each built context also has one `StandSubscriptionRegistry`. By default the
|
|
632
631
|
builder creates a storage-backed registry from the resolved context
|
|
633
632
|
`StorageFactory` (including the `ServerEnvironment` factory used for a builder
|
|
634
|
-
added to a server). It stores one `spine.client.SubscriptionRecord` under each
|
|
633
|
+
added to a server). Its physical `StorageGroup` derives from the logical Bounded Context name, so two contexts using one factory keep distinct definitions. An injected `StorageSubscriptionRegistry` takes an explicit group as its third constructor argument and prepares its captured factory and context. It stores one `spine.client.SubscriptionRecord` under each
|
|
635
634
|
explicit `SubscriptionId`. A complete custom implementation can instead be
|
|
636
635
|
supplied with `withSubscriptionRegistry(registry)`; responsibility transfers to
|
|
637
636
|
the builder on the first build attempt.
|
|
638
637
|
|
|
639
|
-
`SubscriptionService` streams are live
|
|
640
|
-
ordering, or completeness contracts. A standalone Server defaults to the
|
|
638
|
+
`SubscriptionService` streams are live notifications. Each subscriber receives its admitted filtered updates in order, but there is no replay, exactly-once, or cluster-wide completeness guarantee. A standalone Server defaults to the
|
|
641
639
|
persistent registry. In a group of managed server replicas, the framework starts
|
|
642
640
|
and closes each child Server and accepts only every context's actual
|
|
643
641
|
`InMemorySubscriptionRegistry`; a persistent or custom registry is rejected
|
|
@@ -645,7 +643,12 @@ and the assembled child is closed before READY. Durable logical bindings remain
|
|
|
645
643
|
Gateway-only. The Coordinator fans each logical definition to ready children,
|
|
646
644
|
merges updates, propagates cancellation, and carries no subscription payload on
|
|
647
645
|
parent/child IPC. A late or replacement child synchronizes retained definitions
|
|
648
|
-
before it is eligible for normal requests.
|
|
646
|
+
before it is eligible for normal requests. The Coordinator resolves the same
|
|
647
|
+
`subscriptionQueueCapacity` before binding its HTTP/2 listener. Its activation
|
|
648
|
+
ACK is separate from the update queue, which reserves one active DATA update
|
|
649
|
+
plus the configured waiting count for each logical subscriber. Overflow closes
|
|
650
|
+
that subscriber's relay and aborts its child streams.
|
|
651
|
+
Active definitions attach their
|
|
649
652
|
child streams before admission; subscribed but inactive definitions do not
|
|
650
653
|
block readiness. Each child observes application-configured remote/shared
|
|
651
654
|
Delivery directly. During DRAINING, new unary and shard admission stops while
|
|
@@ -678,12 +681,21 @@ completed cycle. This is best-effort per-node convergence, not a
|
|
|
678
681
|
cluster-completeness, replay, ordering, gap-repair, or exactly-once guarantee.
|
|
679
682
|
|
|
680
683
|
The registry accepts only a generated `SubscriptionId` for activate, get, and
|
|
681
|
-
delete. `create(subscription)` returns `{ kind: "created", entry }` or
|
|
684
|
+
delete. `create(subscription, reader?)` returns `{ kind: "created", entry }` or
|
|
682
685
|
`{ kind: "existing", entry }`; the latter requires byte-equivalent canonical
|
|
683
|
-
content and
|
|
684
|
-
`activate(id)` returns `activated`,
|
|
685
|
-
`
|
|
686
|
-
durable records fail closed.
|
|
686
|
+
content and the same reader binding. A different definition or binding with the
|
|
687
|
+
same ID throws `StandConflictError`. `activate(id, reader?)` returns `activated`,
|
|
688
|
+
`active`, `missing`, `expired`, or `denied`. `delete(id, reader?)` returns `deleted`,
|
|
689
|
+
`missing`, or `denied`. Blank IDs or topics and malformed durable records fail closed.
|
|
690
|
+
|
|
691
|
+
Service requests always supply the admitted principal ID or an explicit anonymous
|
|
692
|
+
binding. When supplied, the registry checks the binding again after every failed
|
|
693
|
+
compare-and-set, before changing a reread record. The omitted argument is for
|
|
694
|
+
trusted internal lifecycle work; it is not a way to admit an unauthenticated RPC.
|
|
695
|
+
Reader identity is stored atomically with the subscription definition and phase.
|
|
696
|
+
Attributes, authority facts, and credentials are not part of the stored identity.
|
|
697
|
+
A missing legacy binding is not anonymous and cannot be claimed by a caller;
|
|
698
|
+
the client must create a new subscription.
|
|
687
699
|
|
|
688
700
|
Entries and nested subscriptions returned by create, activate, get, and
|
|
689
701
|
snapshot are clone-safe views. Protobuf byte arrays remain mutable runtime
|
|
@@ -840,6 +852,11 @@ The scope is explicit: pass `{}` in a single-tenant Bounded Context or
|
|
|
840
852
|
`{ tenantId }` in a multitenant Bounded Context. Reads use indexed storage
|
|
841
853
|
without restoring an Agent. The application bridge must authorize access;
|
|
842
854
|
actor metadata does not grant read permission.
|
|
855
|
+
For a trusted in-process caller, the scope can also include detached
|
|
856
|
+
`actorContext`, a verified `reader` with principal and authority facts, and a
|
|
857
|
+
`signal`. Read-side filters receive those facts for that history call; omitting
|
|
858
|
+
`reader` leaves principal and authority facts absent. The bridge supplies
|
|
859
|
+
verified facts explicitly and cannot derive them from `actorContext`.
|
|
843
860
|
|
|
844
861
|
If a selected model's `authorizeUse` callback explicitly returns `false`
|
|
845
862
|
before the handler, the turn records one `AgentInvocationTerminated` System
|
|
@@ -849,10 +866,15 @@ may correlate this fact with the original source through paged Agent history.
|
|
|
849
866
|
|
|
850
867
|
## Signals, validation, and rejection behavior
|
|
851
868
|
|
|
852
|
-
`CommandBus`
|
|
853
|
-
before
|
|
854
|
-
|
|
855
|
-
`
|
|
869
|
+
`CommandBus` checks the nonempty Command ID, nondefault message and context,
|
|
870
|
+
and declared payload constraints before admission or dispatcher code runs.
|
|
871
|
+
Annotated packed messages use generated Proto modules registered in the process.
|
|
872
|
+
`SpineServices` reports invalid Commands in an error Ack with type
|
|
873
|
+
`spine.core.CommandValidationError`, numeric `INVALID_COMMAND` code, and a
|
|
874
|
+
packed `spine.validation.ValidationError`. Unsupported Commands use the same
|
|
875
|
+
enum type and numeric `UNSUPPORTED_COMMAND` code.
|
|
876
|
+
Technical validator failures use a sanitized `COMMAND_POST_ERROR` Ack without
|
|
877
|
+
constraint details; they are distinct from invalid Command input.
|
|
856
878
|
Entity transition validation failures that escape service processing map to
|
|
857
879
|
`COMMAND_STATE_TRANSITION_VALIDATION_FAILED` with the same detail type. Managed
|
|
858
880
|
reception of ordinary Entity work sends post-handler transition rejection to `DeliveryMonitor`;
|
|
@@ -871,6 +893,8 @@ an internal diagnostic, not a retry guarantee.
|
|
|
871
893
|
Every domain context has an internal paired System Context. Domain events use
|
|
872
894
|
the domain `EventBus` and domain `EventStore`. System events use only the
|
|
873
895
|
System Context `EventBus`, so they never enter the domain EventStore.
|
|
896
|
+
Each EventBus validates the Event envelope and domain payload before admission,
|
|
897
|
+
storage, or delivery.
|
|
874
898
|
`persistSystemEvents()` enables the paired System Context's separate storage.
|
|
875
899
|
Bounded Contexts with Agents must enable it. For other Bounded Contexts it is optional; without
|
|
876
900
|
it, the bus validates, dispatches and notifies without appending. Schemas may come from an external dispatcher or
|
|
@@ -887,6 +911,204 @@ work to stop using dependencies, then closes contexts. Caller-managed `start()`
|
|
|
887
911
|
does not close global process facilities; close `ServerEnvironment.instance()`
|
|
888
912
|
separately when used. The final run-managed `run()` close closes its environment.
|
|
889
913
|
|
|
914
|
+
`ServerOptions.appQueries` selects concrete generated `AppQueryHandler<Q, R>`
|
|
915
|
+
instances by exact constructor metadata before listening. Duplicate Q routes
|
|
916
|
+
or missing metadata fail startup. On direct app-node ingress,
|
|
917
|
+
`QueryService.Execute` validates a complete AppQuery envelope and Q, then
|
|
918
|
+
returns one packed paired R. Native and browser Gateways and managed Coordinators
|
|
919
|
+
forward Execute to an app node; `ClientRequest.query(generatedQ)` decodes its paired R.
|
|
920
|
+
The internal
|
|
921
|
+
`Server.query(generatedQ, executionContext)` accepts a generated Q and returns
|
|
922
|
+
its paired generated R, using a detached request and the effective actor,
|
|
923
|
+
verified reader facts, and cancellation signal supplied by the current
|
|
924
|
+
framework invocation. `ProcessManager.currentActorContext` and
|
|
925
|
+
`Agent.currentActorContext` expose only the current signal's detached actor and
|
|
926
|
+
tenant during a handler; neither establishes a verified principal. Constructor
|
|
927
|
+
injection can bind the query function to a Server. Scoped Entity reads require
|
|
928
|
+
query/full visibility and destination tenant membership. Direct calls do not
|
|
929
|
+
cross the Server's gRPC output-filter boundary.
|
|
930
|
+
|
|
931
|
+
`ReadSideFilter<typeof MessageSchema>` declares a typed policy for a registered
|
|
932
|
+
Proto message. Its protected constructor takes the generated schema and optional
|
|
933
|
+
`{ nested: true }`; `filter(message, context)` receives a detached mutable value
|
|
934
|
+
and may return the same type or `null` to remove that occurrence. The context
|
|
935
|
+
separates actor metadata from verified reader facts and identifies the current
|
|
936
|
+
operation, plus a detached containing message and field for nested calls.
|
|
937
|
+
Read-only packed bytes remain available to Buf decoding through a detached
|
|
938
|
+
`value.slice()` passed to `fromBinary`.
|
|
939
|
+
Call `addReadSideFilter(filter)` on a `BoundedContextBuilder` before `build()` to apply it to that
|
|
940
|
+
Bounded Context's outward Entity reads and retained histories. Pass `readSideFilters`
|
|
941
|
+
to `new Server(...)` to apply policies to Entity Query and App Query results
|
|
942
|
+
leaving that Server over gRPC. The same instance can be installed in both
|
|
943
|
+
places; each boundary invokes it once. Direct `Server.query()` runs BC source
|
|
944
|
+
policies but does not cross the Server output boundary. An Entity root returned
|
|
945
|
+
as `null` is omitted without another storage read; an App Query root returned
|
|
946
|
+
as `null` produces OK with zero outer `AppQueryResponse.message` entries. A
|
|
947
|
+
non-null response whose child field is absent remains one response entry.
|
|
948
|
+
History removals retain the
|
|
949
|
+
original continuation. Retained storage, hydration, and replay remain raw.
|
|
950
|
+
Direct Stand and retained-history callbacks identify the producing Bounded
|
|
951
|
+
Context. Protected history called from a handler carries its current signal
|
|
952
|
+
actor; an out-of-handler diagnostic read has no actor or authenticated reader.
|
|
953
|
+
Native SubscriptionService delivery filters already matched Entity states and
|
|
954
|
+
Event payloads through the producing Bounded Context policy and then the
|
|
955
|
+
Server policy. The `subscription` operation includes the original Topic and
|
|
956
|
+
admitted subscription; its context carries the current verified reader facts,
|
|
957
|
+
effective tenant, actor metadata, producing Bounded Context, and cancellation
|
|
958
|
+
signal. Removing a state emits `no_longer_matching` with its original Entity
|
|
959
|
+
ID; removing every Event payload suppresses that data batch. ACKs and existing
|
|
960
|
+
removal controls remain unchanged. Policy failures end only that reader stream
|
|
961
|
+
with a sanitized technical status.
|
|
962
|
+
|
|
963
|
+
The operation describes the call that produced the value. `query` includes the
|
|
964
|
+
actual Query and, during an App Query child read, the enclosing AppQuery. `app-query`
|
|
965
|
+
identifies the final application result. `direct` identifies either a typed
|
|
966
|
+
Stand state read by type URL and Entity ID, a caller-supplied RecordQuery, or a
|
|
967
|
+
normalized query plan. `history` distinguishes an Entity state-at timestamp,
|
|
968
|
+
Entity state/Event history depth, and an Agent view with its page request and
|
|
969
|
+
optional cursor. Direct callers supply actor metadata, verified reader facts,
|
|
970
|
+
and cancellation separately; they cannot override the operation.
|
|
971
|
+
Direct subscription delivery uses `kind: "direct"` with
|
|
972
|
+
`operation.subscription.typeUrl`, distinct from a one-off Stand read's
|
|
973
|
+
`operation.read`.
|
|
974
|
+
|
|
975
|
+
This filter uses the generated Project state and can be installed on the Bounded
|
|
976
|
+
Context builder that contains its Repository:
|
|
977
|
+
|
|
978
|
+
<!-- docs-snippet-path: packages/server/test/server/app-query-execution.test.ts -->
|
|
979
|
+
|
|
980
|
+
```ts
|
|
981
|
+
import {
|
|
982
|
+
type BoundedContextBuilder,
|
|
983
|
+
ReadSideFilter,
|
|
984
|
+
type ReadSideContext,
|
|
985
|
+
} from "@spine-event-engine/server";
|
|
986
|
+
import {
|
|
987
|
+
type ProjectOverviewState,
|
|
988
|
+
ProjectOverviewStateSchema,
|
|
989
|
+
} from "../../test-fixtures/generated/repository-routing/project_states_pb.js";
|
|
990
|
+
|
|
991
|
+
/**
|
|
992
|
+
* Replaces a project name in all ordinary Entity Query results.
|
|
993
|
+
*/
|
|
994
|
+
class PublicProjectName extends ReadSideFilter<typeof ProjectOverviewStateSchema> {
|
|
995
|
+
/**
|
|
996
|
+
* Registers the filter for project overview state.
|
|
997
|
+
*/
|
|
998
|
+
constructor() {
|
|
999
|
+
super(ProjectOverviewStateSchema);
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
/**
|
|
1003
|
+
* Replaces the name only for ordinary Entity Query responses.
|
|
1004
|
+
*
|
|
1005
|
+
* @param state Project overview returned by the read side.
|
|
1006
|
+
* @param context Describes the read operation and verified reader.
|
|
1007
|
+
* @returns The project overview with its name replaced for ordinary Entity Queries.
|
|
1008
|
+
*/
|
|
1009
|
+
filter(state: ProjectOverviewState, context: ReadSideContext): ProjectOverviewState {
|
|
1010
|
+
if (context.operation.kind === "query") state.name = "Public project";
|
|
1011
|
+
return state;
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
const projectPolicy = new PublicProjectName();
|
|
1016
|
+
|
|
1017
|
+
/**
|
|
1018
|
+
* Registers the project name policy in its supplying Bounded Context.
|
|
1019
|
+
*
|
|
1020
|
+
* @param builder Configures the project Bounded Context.
|
|
1021
|
+
* @returns The builder with the read policy installed.
|
|
1022
|
+
*/
|
|
1023
|
+
function installProjectPolicy(builder: BoundedContextBuilder): BoundedContextBuilder {
|
|
1024
|
+
return builder.addReadSideFilter(projectPolicy);
|
|
1025
|
+
}
|
|
1026
|
+
```
|
|
1027
|
+
|
|
1028
|
+
The repository `onCreate` callback can inject `(q, context) => server.query(q, context)`
|
|
1029
|
+
into a Process Manager or Agent. Within an active handler, pass a generated Q
|
|
1030
|
+
with `{ actorContext: this.currentActorContext }`; the actor/tenant snapshot
|
|
1031
|
+
does not supply verified principal or provider facts. The
|
|
1032
|
+
[scoped integration test](https://github.com/SpineEventEngine/spine-ts/blob/master/packages/server/test/entity/process-manager-querying.test.ts) includes
|
|
1033
|
+
the full callback and handler invocation.
|
|
1034
|
+
|
|
1035
|
+
This example uses the generated Project query and the current Process Manager
|
|
1036
|
+
scope; pass `scopedOnCreate(server)` as the repository's `onCreate` callback.
|
|
1037
|
+
Ordinary generation and bootstrap register the decorated handler description:
|
|
1038
|
+
|
|
1039
|
+
<!-- docs-snippet-path: packages/server/test/entity/process-manager-querying.test.ts -->
|
|
1040
|
+
|
|
1041
|
+
```ts
|
|
1042
|
+
import { create } from "@bufbuild/protobuf";
|
|
1043
|
+
import {
|
|
1044
|
+
Assign,
|
|
1045
|
+
ProcessManager,
|
|
1046
|
+
type EntityOptions,
|
|
1047
|
+
type Server,
|
|
1048
|
+
type ServerQueryExecutionContext,
|
|
1049
|
+
} from "@spine-event-engine/server";
|
|
1050
|
+
import { ProcessManagerStateSchema } from "../../test-fixtures/generated/entity-metadata/visibility_pb.js";
|
|
1051
|
+
import { ProjectIdSchema } from "../../test-fixtures/generated/repository-routing/project_identifiers_pb.js";
|
|
1052
|
+
import {
|
|
1053
|
+
type ProjectCreated as ProjectionEvent,
|
|
1054
|
+
ProjectCreatedSchema as ProjectionEventSchema,
|
|
1055
|
+
} from "../../test-fixtures/generated/repository-routing/project_events_pb.js";
|
|
1056
|
+
import { type CreateReviewProject } from "../../test-fixtures/generated/validation-refusal/project_commands_pb.js";
|
|
1057
|
+
import {
|
|
1058
|
+
type GetProjectOverview_Query,
|
|
1059
|
+
type GetProjectOverview_Response,
|
|
1060
|
+
} from "../../test-fixtures/generated/repository-routing/project_queries_pb.js";
|
|
1061
|
+
import { GetProjectOverview } from "../../test-fixtures/generated/repository-routing/project_queries_app_query.js";
|
|
1062
|
+
|
|
1063
|
+
/**
|
|
1064
|
+
* Runs a typed App Query from an active Process Manager handler.
|
|
1065
|
+
*/
|
|
1066
|
+
class ScopedAppQueryManager extends ProcessManager<string, typeof ProcessManagerStateSchema> {
|
|
1067
|
+
/**
|
|
1068
|
+
* Captures the scoped query callback supplied during repository construction.
|
|
1069
|
+
*
|
|
1070
|
+
* @param options Configures this Process Manager instance.
|
|
1071
|
+
* @param ask Executes a generated App Query with trusted handler context.
|
|
1072
|
+
*/
|
|
1073
|
+
constructor(
|
|
1074
|
+
options: EntityOptions<string, typeof ProcessManagerStateSchema>,
|
|
1075
|
+
private readonly ask: (
|
|
1076
|
+
query: GetProjectOverview_Query,
|
|
1077
|
+
context: ServerQueryExecutionContext,
|
|
1078
|
+
) => Promise<GetProjectOverview_Response>,
|
|
1079
|
+
) {
|
|
1080
|
+
super(options);
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
/**
|
|
1084
|
+
* Reads the current project overview while handling the creation Command.
|
|
1085
|
+
*
|
|
1086
|
+
* @param command Project creation request being assigned.
|
|
1087
|
+
* @returns Event carrying the selected overview name.
|
|
1088
|
+
*/
|
|
1089
|
+
@Assign
|
|
1090
|
+
async assign(command: CreateReviewProject): Promise<ProjectionEvent> {
|
|
1091
|
+
const result = await this.ask(
|
|
1092
|
+
create(GetProjectOverview.querySchema, {
|
|
1093
|
+
project: create(ProjectIdSchema, { value: command.id }),
|
|
1094
|
+
}),
|
|
1095
|
+
{ actorContext: this.currentActorContext },
|
|
1096
|
+
);
|
|
1097
|
+
return create(ProjectionEventSchema, {
|
|
1098
|
+
id: command.id,
|
|
1099
|
+
name: result.project?.name ?? "",
|
|
1100
|
+
});
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
/**
|
|
1105
|
+
* Injects the Server's typed App Query route into new Process Manager instances.
|
|
1106
|
+
*/
|
|
1107
|
+
export const scopedOnCreate =
|
|
1108
|
+
(server: Server) => (options: EntityOptions<string, typeof ProcessManagerStateSchema>) =>
|
|
1109
|
+
new ScopedAppQueryManager(options, (q, context) => server.query(q, context));
|
|
1110
|
+
```
|
|
1111
|
+
|
|
890
1112
|
`Stand` registers entity state for point/list reads, updates current state, and
|
|
891
1113
|
offers in-process subscriptions. The legacy-named local reset/replay helper
|
|
892
1114
|
`catchUpReadSide(options?)` clears every registered Projection state and replays
|
|
@@ -917,8 +1139,57 @@ authoritative queries from current state and Entity subscriptions observe
|
|
|
917
1139
|
committed `EntityStateChanged` messages on the paired System Context EventBus,
|
|
918
1140
|
so a direct Stand write alone does not produce a subscription update. Consumer
|
|
919
1141
|
callback failures are isolated from post-commit observation and other
|
|
920
|
-
consumers.
|
|
921
|
-
|
|
1142
|
+
consumers. Native subscription updates enter the existing bounded delivery
|
|
1143
|
+
queue before asynchronous read policies run; a full queue closes that stream.
|
|
1144
|
+
For a surviving Event, policy replaces only its domain payload and retains the original envelope.
|
|
1145
|
+
Direct `Stand.subscribe(schema, { next, error }, options)` applies only its
|
|
1146
|
+
producing Bounded Context's read policies, independently for each local
|
|
1147
|
+
subscriber. `next` receives either `{ kind: "state", state, previousState? }`
|
|
1148
|
+
or `{ kind: "removal", noLongerMatching: true }`; both retain the original type
|
|
1149
|
+
URL, Entity ID, version, and tenant metadata. A removed prior state is omitted
|
|
1150
|
+
from a surviving current state. `error` receives one terminal local policy,
|
|
1151
|
+
callback, or capacity fault. There is no raw callback overload. Options accept
|
|
1152
|
+
trusted `reader` facts, `actorContext` metadata, tenant, and cancellation;
|
|
1153
|
+
`ServerEnvironmentSettings.subscriptionQueueCapacity` sets the waiting count
|
|
1154
|
+
for direct and server-served subscriptions. Configure it before constructing
|
|
1155
|
+
the Stand or Bounded Context. It defaults to 100 waiting updates in addition to
|
|
1156
|
+
one active update; zero allows the active update with no waiting updates. Filter calls
|
|
1157
|
+
and `next` completion are sequential per subscriber. Overflow closes only that
|
|
1158
|
+
subscriber, clears waiting updates, invalidates the active result, and reports
|
|
1159
|
+
`StandSubscriptionCapacityError`; committed writes and other subscribers
|
|
1160
|
+
continue. Unsubscribe, cancellation, and Stand close invalidate outstanding
|
|
1161
|
+
results without waiting for a nonsettling policy. A producer does not await
|
|
1162
|
+
asynchronous policy or observer completion, although CPU-heavy synchronous
|
|
1163
|
+
policy work still runs on the producer's Node event loop.
|
|
1164
|
+
Direct subscribers do not cross a Server output-filter boundary. The package
|
|
1165
|
+
does not guarantee cluster-complete observations, subscription replay,
|
|
1166
|
+
event-gap repair, or exactly-once effects.
|
|
1167
|
+
|
|
1168
|
+
This typed local observer handles visible states, removals, and terminal faults.
|
|
1169
|
+
Configure `subscriptionQueueCapacity: 250` through `ServerEnvironment.when(...).use(...)`
|
|
1170
|
+
before creating the Stand to allow 250 waiting updates beyond the active one:
|
|
1171
|
+
|
|
1172
|
+
<!-- docs-snippet-path: packages/server/test/stand/stand-direct-subscription.test.ts -->
|
|
1173
|
+
|
|
1174
|
+
```ts
|
|
1175
|
+
import { type Stand, type StandSubscription } from "@spine-event-engine/server";
|
|
1176
|
+
import { ProjectOverviewStateSchema } from "../../test-fixtures/generated/repository-routing/project_states_pb.js";
|
|
1177
|
+
|
|
1178
|
+
export function observeProjects(
|
|
1179
|
+
stand: Stand,
|
|
1180
|
+
onState: (name: string) => void,
|
|
1181
|
+
onRemoval: (id: unknown) => void,
|
|
1182
|
+
onError: (error: Error) => void,
|
|
1183
|
+
): StandSubscription {
|
|
1184
|
+
return stand.subscribe(ProjectOverviewStateSchema, {
|
|
1185
|
+
next(update) {
|
|
1186
|
+
if (update.kind === "state") onState(update.state.name);
|
|
1187
|
+
else onRemoval(update.id);
|
|
1188
|
+
},
|
|
1189
|
+
error: onError,
|
|
1190
|
+
});
|
|
1191
|
+
}
|
|
1192
|
+
```
|
|
922
1193
|
|
|
923
1194
|
### Native and managed hosting
|
|
924
1195
|
|
|
@@ -988,6 +1259,48 @@ gRPC-Web transport message accepted by the public listener, so the effective
|
|
|
988
1259
|
inbound limit is the stricter applicable limit. `writeMaxBytes` limits public
|
|
989
1260
|
transport responses independently.
|
|
990
1261
|
|
|
1262
|
+
### Native reader admission
|
|
1263
|
+
|
|
1264
|
+
Configure app-node admission at `ServerOptions.services.readerAdmission`:
|
|
1265
|
+
|
|
1266
|
+
- `direct.authenticate({ service, method, value, headers, peer })` authenticates
|
|
1267
|
+
a direct native request. It returns verified `{ principal, authorityFacts }`,
|
|
1268
|
+
an empty object for deliberate public access, or `undefined` to deny access.
|
|
1269
|
+
The request value contains canonical Proto bytes; `peer` is the Connect
|
|
1270
|
+
`HandlerContext` for that invocation.
|
|
1271
|
+
- `forwarded.verify(bytes, proof, peer)` verifies an assertion from a trusted
|
|
1272
|
+
forwarding peer. It must authenticate that peer and validate the supplied
|
|
1273
|
+
proof over the exact bytes. `BrowserServerOptions.forwardingProof.issue(bytes)`
|
|
1274
|
+
supplies the corresponding gateway adapter.
|
|
1275
|
+
|
|
1276
|
+
Admission completes before service validation, routing, or subscription mutation.
|
|
1277
|
+
Principal IDs and authority facts are copied per invocation. `principal.attributes`
|
|
1278
|
+
remains a string map; `authorityFacts` accepts finite JSON values, including
|
|
1279
|
+
arrays and nested objects. ActorContext remains separate from authentication.
|
|
1280
|
+
Neither the framework nor these ports promise live provider information.
|
|
1281
|
+
|
|
1282
|
+
With no admission adapters, native requests remain public. Internal identity
|
|
1283
|
+
headers are still rejected without a configured verifier. With a forwarding
|
|
1284
|
+
verifier but no direct adapter, a request without a forwarding assertion is
|
|
1285
|
+
rejected as unauthenticated. An application that also permits public direct
|
|
1286
|
+
requests can explicitly return an empty reader from its direct adapter.
|
|
1287
|
+
Malformed assertions and denied authentication return `UNAUTHENTICATED`;
|
|
1288
|
+
unexpected adapter faults return sanitized `INTERNAL`. Explicit cancellation,
|
|
1289
|
+
availability, and permission statuses retain their meaning.
|
|
1290
|
+
|
|
1291
|
+
`ManagedServerApplication` accepts `readerAdmission` for its Coordinator listener
|
|
1292
|
+
and `forwardingProof` for Coordinator-to-child requests. Configure the receiving
|
|
1293
|
+
child Servers with their verifier as well. Each hop verifies its incoming
|
|
1294
|
+
assertion and issues a new proof for the actual outgoing operation and payload.
|
|
1295
|
+
Loopback placement alone does not authenticate a forwarding peer.
|
|
1296
|
+
|
|
1297
|
+
Authenticated forwarding now requires an issuer; configure both gateway and
|
|
1298
|
+
receiving node when updating an existing authenticated deployment. The native
|
|
1299
|
+
Server root still does not load the optional auth package. The forwarding ports
|
|
1300
|
+
do not make a JVM endpoint understand the TS internal reader assertion.
|
|
1301
|
+
|
|
1302
|
+
### Browser hosting
|
|
1303
|
+
|
|
991
1304
|
For `BrowserServer` from `@spine-event-engine/server/browser`, origins must be unique canonical HTTP(S) origins with no path, query,
|
|
992
1305
|
fragment, or trailing slash. Requests without an allowed exact `Origin` receive
|
|
993
1306
|
403 before RPC handling. Allowed responses include credentialed exact-origin
|
|
@@ -1050,7 +1363,11 @@ never returns private native data through public subscription responses.
|
|
|
1050
1363
|
The durable registry preserves one approved `GatewayAuthenticatedSubscription`
|
|
1051
1364
|
per public subscription through a process restart. It validates the record ID,
|
|
1052
1365
|
full Subscription, and expiry before use. The trusted Actor and Tenant remain
|
|
1053
|
-
inside the stored Topic
|
|
1366
|
+
inside the stored Topic; a stable principal ID is stored beside it. Activate and
|
|
1367
|
+
Cancel check the newly admitted reader and Actor/Tenant before stream effects
|
|
1368
|
+
or record mutation. Changed authority facts do not change the principal ID.
|
|
1369
|
+
An explicit anonymous binding remains distinct from missing legacy identity;
|
|
1370
|
+
records with missing identity cannot be claimed by a caller. Create assigns
|
|
1054
1371
|
the public ID directly; no quota, reservation, fingerprint, or lease is
|
|
1055
1372
|
persisted. Cleanup remains bounded and restart-safe at the record level. It
|
|
1056
1373
|
cleans the backend definition before deleting its record. It is not a cleaner
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ConversationHistoryRead, HistoryPage, HistoryRead } from "@spine-event-engine/ai";
|
|
2
|
-
import type { Event } from "@spine-event-engine/proto";
|
|
2
|
+
import type { ActorContext, Event } from "@spine-event-engine/proto";
|
|
3
3
|
import { type AgentHistoryEntry, type ConversationRecord } from "@spine-event-engine/proto/agent";
|
|
4
4
|
import { type AgentHistoryPage, type AgentHistoryStorage, type AgentHistoryView } from "@spine-event-engine/storage/provider";
|
|
5
5
|
/**
|
|
@@ -30,9 +30,10 @@ export interface AgentHistoryScope {
|
|
|
30
30
|
* @param request Public read request.
|
|
31
31
|
* @param live Loads the current provider page only when needed.
|
|
32
32
|
* @param maxBytes Optional response-byte ceiling for this read.
|
|
33
|
+
* @param present Applies outward policy after accounting for provider bytes.
|
|
33
34
|
* @returns The current complete provider page.
|
|
34
35
|
*/
|
|
35
|
-
export type AgentHistoryReadInterceptor = (scope: AgentHistoryScope, request: HistoryRead, live: () => Promise<AgentHistoryPage>, maxBytes: number | undefined) => Promise<
|
|
36
|
+
export type AgentHistoryReadInterceptor = (scope: AgentHistoryScope, request: HistoryRead, live: () => Promise<AgentHistoryPage>, maxBytes: number | undefined, present: (page: AgentHistoryPage) => Promise<HistoryPage<AgentHistoryEntry>>) => Promise<HistoryPage<AgentHistoryEntry>>;
|
|
36
37
|
/**
|
|
37
38
|
* Repository binding for an Agent's mandatory indexed history.
|
|
38
39
|
*
|
|
@@ -65,6 +66,20 @@ export interface AgentHistoryBinding<Id> {
|
|
|
65
66
|
* @returns Its result after all work settles.
|
|
66
67
|
*/
|
|
67
68
|
readonly onAdmit?: (onRead: () => Promise<HistoryPage<AgentHistoryEntry>>) => Promise<HistoryPage<AgentHistoryEntry>>;
|
|
69
|
+
/**
|
|
70
|
+
* Captures active signal metadata before the protected read can await.
|
|
71
|
+
* @returns Detached actor context when a handler supplies one.
|
|
72
|
+
*/
|
|
73
|
+
readonly captureActor?: () => ActorContext | undefined;
|
|
74
|
+
/**
|
|
75
|
+
* Transforms outward domain records after provider read and before read completion.
|
|
76
|
+
* @param page Retained provider entries and original continuation.
|
|
77
|
+
* @param view Requested history category.
|
|
78
|
+
* @param request Captured page request.
|
|
79
|
+
* @param actorContext Actor metadata from the active handler, when present.
|
|
80
|
+
* @returns Visible entries with the original continuation.
|
|
81
|
+
*/
|
|
82
|
+
readonly filterPage?: (page: HistoryPage<AgentHistoryEntry>, view: AgentHistoryView, request: HistoryRead, actorContext?: ActorContext) => Promise<HistoryPage<AgentHistoryEntry>>;
|
|
68
83
|
}
|
|
69
84
|
/**
|
|
70
85
|
* Internal accessors shared by the Agent base and repository runtime.
|
|
@@ -134,9 +149,10 @@ export interface AgentHistoryReadAccess {
|
|
|
134
149
|
* @param binding Exact Agent repository and tenant storage scope.
|
|
135
150
|
* @param view Indexed history view.
|
|
136
151
|
* @param request Public page request.
|
|
152
|
+
* @param actorContext Actor metadata captured at invocation.
|
|
137
153
|
* @returns Retained entries and opaque continuation.
|
|
138
154
|
*/
|
|
139
|
-
readBound<Id>(binding: AgentHistoryBinding<Id>, view: AgentHistoryView, request: HistoryRead): Promise<HistoryPage<AgentHistoryEntry>>;
|
|
155
|
+
readBound<Id>(binding: AgentHistoryBinding<Id>, view: AgentHistoryView, request: HistoryRead, actorContext?: ActorContext): Promise<HistoryPage<AgentHistoryEntry>>;
|
|
140
156
|
/**
|
|
141
157
|
* Persists a genuine framework System Event.
|
|
142
158
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-history.d.ts","sourceRoot":"","sources":["../../src/agent/agent-history.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,uBAAuB,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAChG,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"agent-history.d.ts","sourceRoot":"","sources":["../../src/agent/agent-history.ts"],"names":[],"mappings":"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"}
|