@spine-event-engine/server 2.0.0-snapshot.25 → 2.0.0-snapshot.28

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.
Files changed (207) hide show
  1. package/README.md +104 -16
  2. package/REFERENCE.md +486 -57
  3. package/dist/agent/agent-history.d.ts +19 -3
  4. package/dist/agent/agent-history.d.ts.map +1 -1
  5. package/dist/agent/agent-history.js +41 -10
  6. package/dist/agent/agent-history.js.map +1 -1
  7. package/dist/agent/agent-live-ai-runtime.d.ts +1 -1
  8. package/dist/agent/agent-live-ai-runtime.js +1 -1
  9. package/dist/agent/agent-live-budget.d.ts +1 -1
  10. package/dist/agent/agent-live-budget.js +1 -1
  11. package/dist/agent/agent-live-read-runtime.d.ts +13 -2
  12. package/dist/agent/agent-live-read-runtime.d.ts.map +1 -1
  13. package/dist/agent/agent-live-read-runtime.js +6 -5
  14. package/dist/agent/agent-live-read-runtime.js.map +1 -1
  15. package/dist/browser/browser-admission.d.ts +47 -0
  16. package/dist/browser/browser-admission.d.ts.map +1 -0
  17. package/dist/browser/browser-admission.js +200 -0
  18. package/dist/browser/browser-admission.js.map +1 -0
  19. package/dist/browser/browser-server.d.ts +171 -1
  20. package/dist/browser/browser-server.d.ts.map +1 -1
  21. package/dist/browser/browser-server.js +1027 -303
  22. package/dist/browser/browser-server.js.map +1 -1
  23. package/dist/browser/durable-subscription-bindings.d.ts +5 -0
  24. package/dist/browser/durable-subscription-bindings.d.ts.map +1 -1
  25. package/dist/browser/durable-subscription-bindings.js +226 -38
  26. package/dist/browser/durable-subscription-bindings.js.map +1 -1
  27. package/dist/browser/index.d.ts +1 -1
  28. package/dist/browser/index.d.ts.map +1 -1
  29. package/dist/browser/options.d.ts +53 -2
  30. package/dist/browser/options.d.ts.map +1 -1
  31. package/dist/bus/command-bus.d.ts +9 -1
  32. package/dist/bus/command-bus.d.ts.map +1 -1
  33. package/dist/bus/command-bus.js +75 -10
  34. package/dist/bus/command-bus.js.map +1 -1
  35. package/dist/bus/command-errors.d.ts +20 -4
  36. package/dist/bus/command-errors.d.ts.map +1 -1
  37. package/dist/bus/command-errors.js +47 -7
  38. package/dist/bus/command-errors.js.map +1 -1
  39. package/dist/bus/event-bus.d.ts +9 -1
  40. package/dist/bus/event-bus.d.ts.map +1 -1
  41. package/dist/bus/event-bus.js +136 -9
  42. package/dist/bus/event-bus.js.map +1 -1
  43. package/dist/context/bounded-context.d.ts +59 -39
  44. package/dist/context/bounded-context.d.ts.map +1 -1
  45. package/dist/context/bounded-context.js +277 -262
  46. package/dist/context/bounded-context.js.map +1 -1
  47. package/dist/context/entity-inbox.d.ts +12 -17
  48. package/dist/context/entity-inbox.d.ts.map +1 -1
  49. package/dist/context/entity-inbox.js +106 -119
  50. package/dist/context/entity-inbox.js.map +1 -1
  51. package/dist/context/local-inbox-handoff.d.ts +13 -13
  52. package/dist/context/local-inbox-handoff.d.ts.map +1 -1
  53. package/dist/context/local-inbox-handoff.js +60 -32
  54. package/dist/context/local-inbox-handoff.js.map +1 -1
  55. package/dist/context/persistent-tenant-index.d.ts +81 -0
  56. package/dist/context/persistent-tenant-index.d.ts.map +1 -0
  57. package/dist/context/persistent-tenant-index.js +270 -0
  58. package/dist/context/persistent-tenant-index.js.map +1 -0
  59. package/dist/context/projection-handoff.d.ts +9 -9
  60. package/dist/context/projection-handoff.d.ts.map +1 -1
  61. package/dist/context/projection-handoff.js +31 -23
  62. package/dist/context/projection-handoff.js.map +1 -1
  63. package/dist/context/tenant-index.d.ts +7 -6
  64. package/dist/context/tenant-index.d.ts.map +1 -1
  65. package/dist/context/tenant-index.js +2 -188
  66. package/dist/context/tenant-index.js.map +1 -1
  67. package/dist/context/tenant-unknown-error.d.ts +2 -2
  68. package/dist/context/tenant-unknown-error.d.ts.map +1 -1
  69. package/dist/context/tenant-unknown-error.js +4 -1
  70. package/dist/context/tenant-unknown-error.js.map +1 -1
  71. package/dist/delivery/delivery-supervisor.d.ts.map +1 -1
  72. package/dist/delivery/delivery-supervisor.js +12 -3
  73. package/dist/delivery/delivery-supervisor.js.map +1 -1
  74. package/dist/delivery/delivery.d.ts +4 -3
  75. package/dist/delivery/delivery.d.ts.map +1 -1
  76. package/dist/delivery/delivery.js +82 -34
  77. package/dist/delivery/delivery.js.map +1 -1
  78. package/dist/delivery/reception-observation.d.ts +3 -3
  79. package/dist/delivery/reception-observation.js +2 -2
  80. package/dist/entity/entity.d.ts +59 -0
  81. package/dist/entity/entity.d.ts.map +1 -1
  82. package/dist/entity/entity.js +60 -0
  83. package/dist/entity/entity.js.map +1 -1
  84. package/dist/handler/app-query-handler.d.ts +60 -0
  85. package/dist/handler/app-query-handler.d.ts.map +1 -0
  86. package/dist/handler/app-query-handler.js +23 -0
  87. package/dist/handler/app-query-handler.js.map +1 -0
  88. package/dist/handler/generated-registry-discovery.d.ts +6 -0
  89. package/dist/handler/generated-registry-discovery.d.ts.map +1 -1
  90. package/dist/handler/generated-registry-discovery.js +71 -2
  91. package/dist/handler/generated-registry-discovery.js.map +1 -1
  92. package/dist/handler/handler-decorators.d.ts +8 -29
  93. package/dist/handler/handler-decorators.d.ts.map +1 -1
  94. package/dist/handler/handler-decorators.js +33 -210
  95. package/dist/handler/handler-decorators.js.map +1 -1
  96. package/dist/handler/spine-metadata-inventory.d.ts +99 -0
  97. package/dist/handler/spine-metadata-inventory.d.ts.map +1 -0
  98. package/dist/handler/spine-metadata-inventory.js +162 -0
  99. package/dist/handler/spine-metadata-inventory.js.map +1 -0
  100. package/dist/index.d.ts +9 -4
  101. package/dist/index.d.ts.map +1 -1
  102. package/dist/index.js +6 -2
  103. package/dist/index.js.map +1 -1
  104. package/dist/repository/command-routing.d.ts +1 -1
  105. package/dist/repository/command-routing.js +1 -1
  106. package/dist/repository/event-routing.d.ts +1 -1
  107. package/dist/repository/event-routing.js +1 -1
  108. package/dist/repository/repository.d.ts +61 -26
  109. package/dist/repository/repository.d.ts.map +1 -1
  110. package/dist/repository/repository.js +612 -306
  111. package/dist/repository/repository.js.map +1 -1
  112. package/dist/repository/state-update-routing.d.ts +1 -1
  113. package/dist/repository/state-update-routing.js +1 -1
  114. package/dist/runtime/signal-publisher.d.ts +23 -8
  115. package/dist/runtime/signal-publisher.d.ts.map +1 -1
  116. package/dist/runtime/signal-publisher.js +11 -8
  117. package/dist/runtime/signal-publisher.js.map +1 -1
  118. package/dist/server/managed-server-application.d.ts +12 -11
  119. package/dist/server/managed-server-application.d.ts.map +1 -1
  120. package/dist/server/managed-server-application.js +41 -25
  121. package/dist/server/managed-server-application.js.map +1 -1
  122. package/dist/server/node-coordinator.d.ts +18 -5
  123. package/dist/server/node-coordinator.d.ts.map +1 -1
  124. package/dist/server/node-coordinator.js +744 -108
  125. package/dist/server/node-coordinator.js.map +1 -1
  126. package/dist/server/reserved-spine-rpc-paths.json +1 -0
  127. package/dist/server/server-environment.d.ts +23 -5
  128. package/dist/server/server-environment.d.ts.map +1 -1
  129. package/dist/server/server-environment.js +89 -24
  130. package/dist/server/server-environment.js.map +1 -1
  131. package/dist/server/server.d.ts +45 -0
  132. package/dist/server/server.d.ts.map +1 -1
  133. package/dist/server/server.js +112 -3
  134. package/dist/server/server.js.map +1 -1
  135. package/dist/services/app-query-execution.d.ts +53 -0
  136. package/dist/services/app-query-execution.d.ts.map +1 -0
  137. package/dist/services/app-query-execution.js +408 -0
  138. package/dist/services/app-query-execution.js.map +1 -0
  139. package/dist/services/native-operation.d.ts +34 -0
  140. package/dist/services/native-operation.d.ts.map +1 -0
  141. package/dist/services/native-operation.js +77 -0
  142. package/dist/services/native-operation.js.map +1 -0
  143. package/dist/services/query-reader.d.ts +32 -7
  144. package/dist/services/query-reader.d.ts.map +1 -1
  145. package/dist/services/query-reader.js +22 -2
  146. package/dist/services/query-reader.js.map +1 -1
  147. package/dist/services/read-request-status.d.ts +65 -0
  148. package/dist/services/read-request-status.d.ts.map +1 -0
  149. package/dist/services/read-request-status.js +151 -0
  150. package/dist/services/read-request-status.js.map +1 -0
  151. package/dist/services/spine-services.d.ts +42 -7
  152. package/dist/services/spine-services.d.ts.map +1 -1
  153. package/dist/services/spine-services.js +1005 -175
  154. package/dist/services/spine-services.js.map +1 -1
  155. package/dist/services/trusted-reader-ingress.d.ts +110 -0
  156. package/dist/services/trusted-reader-ingress.d.ts.map +1 -0
  157. package/dist/services/trusted-reader-ingress.js +102 -0
  158. package/dist/services/trusted-reader-ingress.js.map +1 -0
  159. package/dist/spi/handler-registry.d.ts +2 -0
  160. package/dist/spi/handler-registry.d.ts.map +1 -1
  161. package/dist/spi/handler-registry.js +1 -1
  162. package/dist/spi/handler-registry.js.map +1 -1
  163. package/dist/stand/read-side-filter-engine.d.ts +46 -0
  164. package/dist/stand/read-side-filter-engine.d.ts.map +1 -0
  165. package/dist/stand/read-side-filter-engine.js +356 -0
  166. package/dist/stand/read-side-filter-engine.js.map +1 -0
  167. package/dist/stand/read-side-filter.d.ts +247 -0
  168. package/dist/stand/read-side-filter.d.ts.map +1 -0
  169. package/dist/stand/read-side-filter.js +39 -0
  170. package/dist/stand/read-side-filter.js.map +1 -0
  171. package/dist/stand/read-side-message.d.ts +66 -0
  172. package/dist/stand/read-side-message.d.ts.map +1 -0
  173. package/dist/stand/read-side-message.js +167 -0
  174. package/dist/stand/read-side-message.js.map +1 -0
  175. package/dist/stand/stand-direct-delivery.d.ts +161 -0
  176. package/dist/stand/stand-direct-delivery.d.ts.map +1 -0
  177. package/dist/stand/stand-direct-delivery.js +210 -0
  178. package/dist/stand/stand-direct-delivery.js.map +1 -0
  179. package/dist/stand/stand.d.ts +81 -43
  180. package/dist/stand/stand.d.ts.map +1 -1
  181. package/dist/stand/stand.js +411 -55
  182. package/dist/stand/stand.js.map +1 -1
  183. package/dist/stand/subscription-observer.d.ts.map +1 -1
  184. package/dist/stand/subscription-observer.js +103 -0
  185. package/dist/stand/subscription-observer.js.map +1 -1
  186. package/dist/stand/subscription-read-filters.d.ts +40 -0
  187. package/dist/stand/subscription-read-filters.d.ts.map +1 -0
  188. package/dist/stand/subscription-read-filters.js +91 -0
  189. package/dist/stand/subscription-read-filters.js.map +1 -0
  190. package/dist/stand/subscription-reader-binding.d.ts +20 -0
  191. package/dist/stand/subscription-reader-binding.d.ts.map +1 -0
  192. package/dist/stand/subscription-reader-binding.js +56 -0
  193. package/dist/stand/subscription-reader-binding.js.map +1 -0
  194. package/dist/stand/subscription-records.d.ts +30 -3
  195. package/dist/stand/subscription-records.d.ts.map +1 -1
  196. package/dist/stand/subscription-records.js +61 -16
  197. package/dist/stand/subscription-records.js.map +1 -1
  198. package/dist/stand/subscription-registry.d.ts +49 -14
  199. package/dist/stand/subscription-registry.d.ts.map +1 -1
  200. package/dist/stand/subscription-registry.js +150 -31
  201. package/dist/stand/subscription-registry.js.map +1 -1
  202. package/dist/stand/subscription-runtime.d.ts +7 -2
  203. package/dist/stand/subscription-runtime.d.ts.map +1 -1
  204. package/dist/stand/subscription-runtime.js +131 -25
  205. package/dist/stand/subscription-runtime.js.map +1 -1
  206. package/dist/tsconfig.tsbuildinfo +1 -1
  207. package/package.json +16 -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 registry with `@spine-event-engine/proto-tools`. The small
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
 
@@ -43,7 +44,6 @@ Add generated entities with `BoundedContext.add(...)` and use
43
44
  `build()` to assemble the context and load generated repositories when configured. A
44
45
  context is single-tenant or multitenant by construction; select that mode
45
46
  before registering application handlers and storage.
46
-
47
47
  `build()` prepares the current model storage and awaits the first subscription
48
48
  registry pass. Set `createStorageStructures: false` or
49
49
  `startSubscriptionMonitoring: false` in `build({...})` to defer either phase
@@ -78,14 +78,16 @@ import { TaskAssignment, type AssignmentWeightService } from "../src/index.js";
78
78
 
79
79
  // Create shared services before starting the context.
80
80
  const weights: AssignmentWeightService = { weightFor: () => 2 };
81
- const builder = BoundedContext.singleTenant("Assignments")
82
- .withGeneratedRegistryRoot(new URL("..", import.meta.url))
83
- .add(TaskAssignment, {
84
- // Forward Spine's options and add the service required by the constructor.
85
- onCreate: (options) => new TaskAssignment(options, weights),
86
- });
81
+ const builder = BoundedContext.singleTenant("Assignments").add(TaskAssignment, {
82
+ // Forward Spine's options and add the service required by the constructor.
83
+ onCreate: (options) => new TaskAssignment(options, weights),
84
+ });
87
85
  ```
88
86
 
87
+ The application's `src/index.js` imports its generated `spine-bootstrap.js`
88
+ before assembly, so `add(TaskAssignment)` finds the passive metadata for that
89
+ exact class.
90
+
89
91
  Await `builder.build()` to assemble the context. The callback runs for each
90
92
  fresh or restored Entity object, not just once per ID. It also works for
91
93
  Aggregates and Projections, including Projection rebuilds. Return a fresh
@@ -109,6 +111,15 @@ A failed handler leaves previous persisted state unchanged and
109
111
  suppresses produced output. An external HTTP request or other side effect may
110
112
  already have happened.
111
113
 
114
+ Repository-backed Command and Event posting resolves after recipient Inbox
115
+ writes. Delivery starts immediately and handles the stored row separately, so
116
+ successful posting does not mean the handler has completed. Restart durability
117
+ depends on the configured storage provider; custom dispatchers define their own
118
+ completion contract. A committed Entity awaits one outgoing handoff attempt for
119
+ handler-produced domain Commands and Events. A failed attempt is reported without
120
+ rerunning successful source handling. Internal diagnostic publication remains
121
+ best effort.
122
+
112
123
  Handler return declarations can use native unions for one of several results,
113
124
  or fixed tuples for several ordered results. For example,
114
125
  `CreateAccessGrant | ExtendAccessGrant` selects one Command, while
@@ -202,19 +213,63 @@ Bounded Contexts causes a startup error.
202
213
  The [Orders example](https://github.com/SpineEventEngine/spine-ts/blob/master/examples/orders/README.md#cross-context-order-review)
203
214
  shows this in an Event handler and includes a runnable integration test.
204
215
 
216
+ Application queries use generated `_queries.proto` request/response companions.
217
+ Pass concrete `AppQueryHandler<Q, R>` instances in `ServerOptions.appQueries`;
218
+ generated metadata alone never enables a route. On direct app-node ingress,
219
+ `QueryService.Execute` validates the wire envelope and Q before dispatch.
220
+ Native and browser Gateways forward Execute to the app node; `ClientRequest.query(generatedQ)`
221
+ returns the wire `Response` and zero or one decoded paired results. Application code calls
222
+ `server.query(generatedQ, executionContext)` and receives the paired generated R.
223
+ The trusted execution context supplies the current `actorContext`, optional
224
+ verified principal and authority facts, and an optional cancellation signal.
225
+ For a Process Manager or Agent, inject a Server-bound query function through the
226
+ repository's `onCreate` callback and use `currentActorContext` only inside an
227
+ active handler. That actor metadata does not prove authentication. Source reads
228
+ from an application query use registered query-visible Entity routes and enforce
229
+ the destination's tenant membership; a handler that performs no source read has
230
+ no destination tenant to check. Direct calls do not run Server output filters.
231
+
232
+ The [typed callback example](REFERENCE.md#services-reads-and-lifecycle) shows
233
+ the repository `onCreate` injection and active handler call. The actor/tenant
234
+ snapshot supplies no verified principal or provider facts; the
235
+ [scoped integration test](https://github.com/SpineEventEngine/spine-ts/blob/master/packages/server/test/entity/process-manager-querying.test.ts) shows
236
+ the complete repository setup.
237
+
205
238
  Queries preserve the handler's actor and effective tenant; there is no tenant
206
239
  override. Single-tenant execution uses `SINGLE_TENANT`, even when the request
207
240
  omits a tenant field. A named tenant cannot query a single-tenant context: that
208
241
  fails before reading. See the [query contract](REFERENCE.md#handler-routing-and-operations)
209
242
  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.
243
+ For a multitenant receiving Bounded Context, supply an application tenant directory and
244
+ register each accepted tenant through its `keep(tenantId)` method before sending
245
+ tenant-scoped work. The optional environment setting defaults to `SINGLE_TENANT`;
246
+ that mode creates no directory or provider catalog. A multitenant Bounded Context
247
+ requires an environment directory before assembly, even when `withTenantIndex()`
248
+ selects another directory for that Bounded Context. In one environment, a
249
+ single-tenant Identity Bounded Context still uses `SINGLE_TENANT` while a
250
+ multitenant Orders Bounded Context uses the configured directory.
251
+ Both public `tenantIndex` getters return `TenantIndexSetting`, so narrow against
252
+ `SINGLE_TENANT` before calling directory methods. A single-tenant Bounded Context always
253
+ returns the marker, even when its environment has a directory for other Bounded Contexts.
254
+ Provider catalogs remain available as storage-provider APIs, but environment
255
+ assembly does not infer membership from them.
256
+ `PersistentTenantIndex.create({ storageFactory, group })` stores registrations
257
+ through the selected factory. Remote providers can retain them across process
258
+ restarts; memory storage remains process-local. Its async factory prepares supported structures by
259
+ default; set `createMissingStructures: false` when the application prepares
260
+ the selected record family separately before data access. Close the index after its admitted work
261
+ finishes; it leaves the supplied storage factory open.
216
262
  Unknown tenants fail before reads or handlers run; input never registers them.
217
263
 
264
+ The [Orders application](https://github.com/SpineEventEngine/spine-ts/blob/master/examples/orders/README.md)
265
+ demonstrates this setup with memory, PostgreSQL, and Datastore. Its PostgreSQL
266
+ launch uses separate shared, Northwind, and Contoso databases, validates persisted
267
+ membership against configured routing, and prepares supported structures before
268
+ opening the listener. Orders focuses on tenant storage and has no sign-in UI.
269
+ The [Fieldnotes application](https://github.com/SpineEventEngine/spine-ts/blob/master/examples/fieldnotes/README.md)
270
+ demonstrates browser authentication and private data in a single-tenant Bounded
271
+ Context without a tenant index.
272
+
218
273
  Use `EntityQuery.all(...)` when every predicate must match and
219
274
  `EntityQuery.either(...)` when any branch may match.
220
275
 
@@ -300,7 +355,7 @@ class SupportDraftAgent extends Agent<SupportTicketId, typeof SupportDraftStateS
300
355
  Configure the registry outside the Entity. The Bounded Context requires persisted System
301
356
  Events, and the Agent registration supplies its permitted capabilities. The
302
357
  [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
358
+ assembles these settings with generated passive handler metadata. Supply the AI registry
304
359
  through `ServerEnvironment.when(type).use({ ai: registry })` as a default, or
305
360
  `BoundedContextBuilder.withAi(registry)` for one Bounded Context.
306
361
 
@@ -364,7 +419,7 @@ field. Event routing uses a compatible producer ID when available and otherwise
364
419
  uses the Event's declared first field. State-update routing selects the first
365
420
  state field compatible with the Entity ID.
366
421
 
367
- ## Browser gateway migration
422
+ ## Browser gateway setup
368
423
 
369
424
  The server root has no browser options and does not load auth. To host a
370
425
  browser-facing Gateway, install the optional auth peer and import the browser
@@ -386,6 +441,39 @@ and backend forwarding. Authenticated durable bindings are browser-host
386
441
  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
442
  before exposing a backend to a browser.
388
443
 
444
+ For a standalone Gateway, call `BrowserServer.run` with a canonical
445
+ `backend.baseUrl` (or discovery), `origins`, `sessions`, `authorize`, `contexts`,
446
+ `clock`, and explicit `bindings`. Supply `credentials` with a
447
+ `BrowserCredentialReader` to select a browser auth engine. The reader and each
448
+ `authRoutes` entry declare `csrfHeaderNames`, `credentialCookieNames`, and
449
+ `stateCookieNames`; empty arrays state that a category is unused. The Gateway
450
+ validates those names before it starts listening, then checks raw headers before
451
+ calling the reader or a route. Preflight never calls the credential reader;
452
+ permitted origins receive credentialed CORS headers covering the configured CSRF
453
+ fields and Connect protocol headers. Connect stops waiting for a reader and
454
+ does not forward its late result when the request is cancelled or its deadline
455
+ passes. The reader receives no abort signal, so its underlying work may continue.
456
+ This setup does not construct a
457
+ `ServerEnvironment` or Bounded Context. Close the returned server at shutdown.
458
+
459
+ ## Native reader admission
460
+
461
+ Native authentication is configured through `ServerOptions.services.readerAdmission`.
462
+ Use `direct` to authenticate native callers or `forwarded` to verify reader
463
+ assertions from an authenticated gateway. For browser forwarding, supply the
464
+ corresponding issuer as `BrowserServerOptions.forwardingProof`. Configure both
465
+ ends; the backend does not trust an actor ID or incoming identity header by
466
+ itself. With neither admission adapter configured, the native server remains
467
+ public and supplies no authenticated principal or authority facts.
468
+
469
+ Subscription activation and cancellation also check the admitted principal
470
+ against the stored reader binding. A different principal cannot reuse a
471
+ subscription even with the same ActorContext. The host supplies an operation
472
+ signal before authentication and closes it after unary work or the complete
473
+ Activate stream. A direct authenticator can return a separately captured
474
+ `invalidated` signal for local logout and session expiry. See [native reader admission](REFERENCE.md#native-reader-admission)
475
+ for adapter signatures, public admission, and managed application configuration.
476
+
389
477
  ## Limits
390
478
 
391
479
  This package does not create an identity provider, browser session store,