@spine-event-engine/server 2.0.0-snapshot.26 → 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 (110) hide show
  1. package/README.md +56 -8
  2. package/REFERENCE.md +151 -39
  3. package/dist/agent/agent-live-ai-runtime.d.ts +1 -1
  4. package/dist/agent/agent-live-ai-runtime.js +1 -1
  5. package/dist/agent/agent-live-budget.d.ts +1 -1
  6. package/dist/agent/agent-live-budget.js +1 -1
  7. package/dist/agent/agent-live-read-runtime.d.ts +1 -1
  8. package/dist/agent/agent-live-read-runtime.js +1 -1
  9. package/dist/browser/browser-admission.d.ts +47 -0
  10. package/dist/browser/browser-admission.d.ts.map +1 -0
  11. package/dist/browser/browser-admission.js +200 -0
  12. package/dist/browser/browser-admission.js.map +1 -0
  13. package/dist/browser/browser-server.d.ts +14 -7
  14. package/dist/browser/browser-server.d.ts.map +1 -1
  15. package/dist/browser/browser-server.js +462 -129
  16. package/dist/browser/browser-server.js.map +1 -1
  17. package/dist/browser/index.d.ts +1 -1
  18. package/dist/browser/index.d.ts.map +1 -1
  19. package/dist/browser/options.d.ts +48 -2
  20. package/dist/browser/options.d.ts.map +1 -1
  21. package/dist/bus/command-bus.d.ts +6 -1
  22. package/dist/bus/command-bus.d.ts.map +1 -1
  23. package/dist/bus/command-bus.js +6 -1
  24. package/dist/bus/command-bus.js.map +1 -1
  25. package/dist/bus/event-bus.d.ts +6 -1
  26. package/dist/bus/event-bus.d.ts.map +1 -1
  27. package/dist/bus/event-bus.js +6 -1
  28. package/dist/bus/event-bus.js.map +1 -1
  29. package/dist/context/bounded-context.d.ts +30 -28
  30. package/dist/context/bounded-context.d.ts.map +1 -1
  31. package/dist/context/bounded-context.js +136 -82
  32. package/dist/context/bounded-context.js.map +1 -1
  33. package/dist/context/entity-inbox.d.ts +12 -17
  34. package/dist/context/entity-inbox.d.ts.map +1 -1
  35. package/dist/context/entity-inbox.js +106 -119
  36. package/dist/context/entity-inbox.js.map +1 -1
  37. package/dist/context/local-inbox-handoff.d.ts +13 -13
  38. package/dist/context/local-inbox-handoff.d.ts.map +1 -1
  39. package/dist/context/local-inbox-handoff.js +60 -32
  40. package/dist/context/local-inbox-handoff.js.map +1 -1
  41. package/dist/context/persistent-tenant-index.d.ts +81 -0
  42. package/dist/context/persistent-tenant-index.d.ts.map +1 -0
  43. package/dist/context/persistent-tenant-index.js +270 -0
  44. package/dist/context/persistent-tenant-index.js.map +1 -0
  45. package/dist/context/projection-handoff.d.ts +9 -9
  46. package/dist/context/projection-handoff.d.ts.map +1 -1
  47. package/dist/context/projection-handoff.js +31 -23
  48. package/dist/context/projection-handoff.js.map +1 -1
  49. package/dist/context/tenant-index.d.ts +7 -6
  50. package/dist/context/tenant-index.d.ts.map +1 -1
  51. package/dist/context/tenant-index.js +2 -188
  52. package/dist/context/tenant-index.js.map +1 -1
  53. package/dist/context/tenant-unknown-error.d.ts +2 -2
  54. package/dist/context/tenant-unknown-error.d.ts.map +1 -1
  55. package/dist/context/tenant-unknown-error.js +4 -1
  56. package/dist/context/tenant-unknown-error.js.map +1 -1
  57. package/dist/delivery/delivery-supervisor.d.ts.map +1 -1
  58. package/dist/delivery/delivery-supervisor.js +12 -3
  59. package/dist/delivery/delivery-supervisor.js.map +1 -1
  60. package/dist/delivery/delivery.d.ts +4 -3
  61. package/dist/delivery/delivery.d.ts.map +1 -1
  62. package/dist/delivery/delivery.js +82 -34
  63. package/dist/delivery/delivery.js.map +1 -1
  64. package/dist/delivery/reception-observation.d.ts +3 -3
  65. package/dist/delivery/reception-observation.js +2 -2
  66. package/dist/index.d.ts +4 -1
  67. package/dist/index.d.ts.map +1 -1
  68. package/dist/index.js +2 -0
  69. package/dist/index.js.map +1 -1
  70. package/dist/repository/command-routing.d.ts +1 -1
  71. package/dist/repository/command-routing.js +1 -1
  72. package/dist/repository/event-routing.d.ts +1 -1
  73. package/dist/repository/event-routing.js +1 -1
  74. package/dist/repository/repository.d.ts +23 -31
  75. package/dist/repository/repository.d.ts.map +1 -1
  76. package/dist/repository/repository.js +244 -218
  77. package/dist/repository/repository.js.map +1 -1
  78. package/dist/repository/state-update-routing.d.ts +1 -1
  79. package/dist/repository/state-update-routing.js +1 -1
  80. package/dist/runtime/signal-publisher.d.ts +23 -8
  81. package/dist/runtime/signal-publisher.d.ts.map +1 -1
  82. package/dist/runtime/signal-publisher.js +11 -8
  83. package/dist/runtime/signal-publisher.js.map +1 -1
  84. package/dist/server/node-coordinator.d.ts.map +1 -1
  85. package/dist/server/node-coordinator.js +220 -54
  86. package/dist/server/node-coordinator.js.map +1 -1
  87. package/dist/server/server-environment.d.ts +6 -5
  88. package/dist/server/server-environment.d.ts.map +1 -1
  89. package/dist/server/server-environment.js +13 -9
  90. package/dist/server/server-environment.js.map +1 -1
  91. package/dist/server/server.js +1 -0
  92. package/dist/server/server.js.map +1 -1
  93. package/dist/services/app-query-execution.js +2 -2
  94. package/dist/services/app-query-execution.js.map +1 -1
  95. package/dist/services/native-operation.d.ts +34 -0
  96. package/dist/services/native-operation.d.ts.map +1 -0
  97. package/dist/services/native-operation.js +77 -0
  98. package/dist/services/native-operation.js.map +1 -0
  99. package/dist/services/spine-services.d.ts +6 -0
  100. package/dist/services/spine-services.d.ts.map +1 -1
  101. package/dist/services/spine-services.js +128 -30
  102. package/dist/services/spine-services.js.map +1 -1
  103. package/dist/services/trusted-reader-ingress.d.ts +23 -5
  104. package/dist/services/trusted-reader-ingress.d.ts.map +1 -1
  105. package/dist/services/trusted-reader-ingress.js +18 -5
  106. package/dist/services/trusted-reader-ingress.js.map +1 -1
  107. package/dist/stand/stand.d.ts +1 -1
  108. package/dist/stand/stand.js +1 -1
  109. package/dist/tsconfig.tsbuildinfo +1 -1
  110. package/package.json +16 -14
@@ -36,7 +36,7 @@ import { snapshotTrustedReader, } from "@spine-event-engine/core/spi/trusted-rea
36
36
  import { Code, ConnectError } from "@connectrpc/connect";
37
37
  import { EventDispatcherOriginSchemas } from "../bus/event-dispatcher-origin-schemas.js";
38
38
  import { receptionObservation } from "../delivery/reception-observation.js";
39
- import { commitFenced, withDeliveryCommitFence } from "./commit-fence.js";
39
+ import { commitFenced, withDeliveryCommitFence, withoutDeliveryCommitFence, } from "./commit-fence.js";
40
40
  import { AgentHistoryReads, } from "../agent/agent-history.js";
41
41
  import { AgentLiveAiRuntime } from "../agent/agent-live-ai-runtime.js";
42
42
  import { AgentLiveAudit } from "../agent/agent-live-audit.js";
@@ -690,19 +690,19 @@ export const repositoryAccess = Object.freeze({
690
690
  });
691
691
  },
692
692
  /**
693
- * Looks up the Aggregate or Process Manager inbox replay target.
693
+ * Looks up the Aggregate or Process Manager Inbox delivery target.
694
694
  *
695
695
  * @param repository Repository to inspect.
696
- * @returns Its replay target, when registered.
696
+ * @returns Its delivery target, when registered.
697
697
  */
698
698
  entityInboxTarget(repository) {
699
699
  return repositoryEntityInboxTargets.get(repository);
700
700
  },
701
701
  /**
702
- * Looks up the Projection inbox replay target.
702
+ * Looks up the Projection Inbox delivery target.
703
703
  *
704
704
  * @param repository Repository to inspect.
705
- * @returns Its replay target, when registered.
705
+ * @returns Its delivery target, when registered.
706
706
  */
707
707
  projectionInboxTarget(repository) {
708
708
  return repositoryProjectionInboxTargets.get(repository);
@@ -1067,7 +1067,8 @@ class AggregateExecutionSupport {
1067
1067
  return Object.freeze([produced]);
1068
1068
  }
1069
1069
  /**
1070
- * Stores Aggregate state and diagnostic and delivery Events in one atomic commit.
1070
+ * Writes Aggregate state, diagnostic history, and produced Events through the configured
1071
+ * commit storage. Atomicity depends on that storage implementation.
1071
1072
  *
1072
1073
  * @param loaded Aggregate and commit storage to update.
1073
1074
  * @param entityId Aggregate identifier.
@@ -1141,7 +1142,7 @@ class AggregateExecutionSupport {
1141
1142
  await loaded.events.append(clone(EventSchema, event));
1142
1143
  }
1143
1144
  /**
1144
- * Completes persistence before scheduling best-effort stored-Event dispatch.
1145
+ * Completes persistence and one handoff attempt for each produced Event.
1145
1146
  *
1146
1147
  * @param loaded Aggregate and commit storage to update.
1147
1148
  * @param entityId Aggregate identifier.
@@ -1149,14 +1150,14 @@ class AggregateExecutionSupport {
1149
1150
  * @param dispatch Publishes one committed Event.
1150
1151
  * @param onPersisted Runs after durable persistence.
1151
1152
  * @param diagnostics Events to retain in diagnostic history with this commit.
1152
- * @returns A deferred follow-up that dispatches the Events.
1153
+ * @returns Completion after the Event handoff attempts settle.
1153
1154
  */
1154
1155
  async persistAggregateAndDispatch(loaded, entityId, events, dispatch, onPersisted, diagnostics = events) {
1155
1156
  const committed = await this.persistAggregateUpdate(loaded, entityId, events, diagnostics);
1156
1157
  if (!committed)
1157
- return () => Promise.resolve();
1158
+ return;
1158
1159
  await onPersisted();
1159
- return async () => {
1160
+ await withoutDeliveryCommitFence(async () => {
1160
1161
  await Promise.all(events.map(async (event) => {
1161
1162
  try {
1162
1163
  await dispatch(event);
@@ -1165,7 +1166,7 @@ class AggregateExecutionSupport {
1165
1166
  this.#runtime.publisher.reportFailure("event", event, error);
1166
1167
  }
1167
1168
  }));
1168
- };
1169
+ });
1169
1170
  }
1170
1171
  /**
1171
1172
  * Restores an Aggregate or creates one with initial state and version zero.
@@ -1225,27 +1226,27 @@ class AggregateCommandExecution {
1225
1226
  /**
1226
1227
  * Validates the Command and executes its assignee when registered.
1227
1228
  *
1228
- * @param replayedRoute Accepted route from durable inbox replay, when present.
1229
- * @returns A deferred dispatch follow-up, or `undefined` without an assignee.
1229
+ * @param deliveredRoute Accepted route from durable inbox delivery, when present.
1230
+ * @returns Completion after processing and outgoing handoff attempts.
1230
1231
  */
1231
- async run(replayedRoute) {
1232
+ async run(deliveredRoute) {
1232
1233
  void RepositorySignals.requireCommandId(this.#command);
1233
- const intake = await this.#readIntake(replayedRoute);
1234
+ const intake = await this.#readIntake(deliveredRoute);
1234
1235
  if (intake === undefined)
1235
1236
  return undefined;
1236
- return this.#runAssignee(intake);
1237
+ await this.#runAssignee(intake);
1237
1238
  }
1238
1239
  /**
1239
1240
  * Decodes the Command and selects its registered assignee.
1240
1241
  *
1241
- * @param replayedRoute Accepted inbox route, when present.
1242
+ * @param deliveredRoute Accepted inbox route, when present.
1242
1243
  * @returns Decoded message and route with an assignee, or `undefined`.
1243
1244
  */
1244
- async #readIntake(replayedRoute) {
1245
+ async #readIntake(deliveredRoute) {
1245
1246
  const commandMessage = EntityInvocation.requireSignalMessage(this.#command.message, "command");
1246
1247
  const commandSchema = RepositoryRoutes.schemaForTypeUrl(this.#routing.commandSchemas, commandMessage.typeUrl, "command");
1247
1248
  const message = EntityInvocation.unpackRequired(commandMessage, commandSchema, "command");
1248
- const route = replayedRoute ?? (await this.#repository.routeCommand(this.#command));
1249
+ const route = deliveredRoute ?? (await this.#repository.routeCommand(this.#command));
1249
1250
  const assignee = this.#routing.commandReadiness?.findCommandAssignee(route.messageFullTypeName);
1250
1251
  return assignee === undefined ? undefined : Object.freeze({ message, route, assignee });
1251
1252
  }
@@ -1253,7 +1254,7 @@ class AggregateCommandExecution {
1253
1254
  * Invokes the assignee, persists its Events, or publishes a declared rejection.
1254
1255
  *
1255
1256
  * @param intake Decoded Command, target route, and assignee.
1256
- * @returns A deferred Event follow-up or a rejection follow-up.
1257
+ * @returns Completion after processing and outgoing handoff attempts.
1257
1258
  */
1258
1259
  async #runAssignee(intake) {
1259
1260
  const loaded = await this.#support.loadAggregate(intake.route.entityId);
@@ -1263,23 +1264,24 @@ class AggregateCommandExecution {
1263
1264
  produced = await this.#invokeAssignee(loaded.entity, intake.assignee.handler, intake.message, EntityInvocation.commandHandlerContext(this.#command), this.#command.context?.actorContext);
1264
1265
  }
1265
1266
  catch (error) {
1266
- return this.#postAssigneeRejection(intake, error);
1267
+ await this.#postAssigneeRejection(intake, error);
1268
+ return undefined;
1267
1269
  }
1268
1270
  const events = this.#bindProducedEvents(this.#support.normalizeProducedSignals(produced), intake.route.entityId, RepositoryEntities.priorVersion(loaded.current));
1269
- return this.#persistAssigneeResult(loaded, intake.route.entityId, events);
1271
+ await this.#persistAssigneeResult(loaded, intake.route.entityId, events);
1270
1272
  }
1271
1273
  /**
1272
1274
  * Publishes a declared rejection from the invoked Aggregate assignee.
1273
1275
  *
1274
1276
  * @param intake Assignee and target route for the rejected Command.
1275
1277
  * @param error Handler failure to classify and publish.
1276
- * @returns A rejection follow-up when one is created.
1278
+ * @returns Completion after the rejection Event handoff attempt.
1277
1279
  */
1278
- #postAssigneeRejection(intake, error) {
1280
+ async #postAssigneeRejection(intake, error) {
1279
1281
  if (!RejectionThrowable.is(error))
1280
1282
  throw error;
1281
1283
  RepositorySignals.requireDeclaredRejection(intake.assignee.handler, error);
1282
- return RepositorySignals.postRejectionEvent(this.#runtime, this.#repository, this.#command, intake.route.entityId, error);
1284
+ await RepositorySignals.postRejectionEvent(this.#runtime, this.#repository, this.#command, intake.route.entityId, error);
1283
1285
  }
1284
1286
  /**
1285
1287
  * Publishes a best-effort Command dispatch diagnostic.
@@ -1295,11 +1297,11 @@ class AggregateCommandExecution {
1295
1297
  * @param loaded Aggregate and commit storage.
1296
1298
  * @param entityId Target Aggregate identifier.
1297
1299
  * @param events Bound Events from the assignee.
1298
- * @returns A deferred committed-Event dispatch follow-up.
1300
+ * @returns Completion after committed Event handoff attempts.
1299
1301
  */
1300
- #persistAssigneeResult(loaded, entityId, events) {
1302
+ async #persistAssigneeResult(loaded, entityId, events) {
1301
1303
  const committedVersion = loaded.version + 1n;
1302
- return this.#support.persistAggregateAndDispatch(loaded, entityId, events, (event) => this.#runtime.publisher.publishCommittedEvent(event), () => {
1304
+ await this.#support.persistAggregateAndDispatch(loaded, entityId, events, (event) => this.#runtime.publisher.publishCommittedEvent(event), () => {
1303
1305
  if (!RepositoryEntities.repositoryChanged(loaded.entity))
1304
1306
  return;
1305
1307
  EntityStateChangePublisher.command(this.#runtime, this.#repository, this.#command, entityId, loaded.oldState, loaded.current === undefined
@@ -1489,10 +1491,9 @@ class AggregateEventExecution {
1489
1491
  await this.#support.appendDiagnosticEvent(loaded, entityId, source);
1490
1492
  return;
1491
1493
  }
1492
- const dispatch = await this.#support.persistAggregateAndDispatch(loaded, entityId, produced, (event) => this.#runtime.publisher.publishReactorEvent(event), () => {
1494
+ await this.#support.persistAggregateAndDispatch(loaded, entityId, produced, (event) => this.#runtime.publisher.publishReactorEvent(event), () => {
1493
1495
  this.#publishStateChange(loaded, entityId);
1494
1496
  }, [source, ...produced]);
1495
- void dispatch();
1496
1497
  }
1497
1498
  /**
1498
1499
  * Publishes an Entity state-change System Event when the Aggregate changed.
@@ -1675,7 +1676,7 @@ class ProjectionEventExecution {
1675
1676
  * Delivers an accepted Event for one Projection target.
1676
1677
  *
1677
1678
  * @param entityId Target Projection identifier.
1678
- * @param acceptedRoute Route accepted before replay.
1679
+ * @param acceptedRoute Route accepted before deliver.
1679
1680
  * @returns Completion after target delivery.
1680
1681
  */
1681
1682
  async runTarget(entityId, acceptedRoute) {
@@ -2911,27 +2912,29 @@ class ProcessManagerCommandExecution {
2911
2912
  /**
2912
2913
  * Invokes the registered Command handler and commits its results.
2913
2914
  *
2914
- * @param replayedRoute Accepted route from durable inbox replay, when present.
2915
- * @returns A deferred Command follow-up, rejection follow-up, or `undefined`.
2915
+ * @param deliveredRoute Accepted route from durable inbox delivery, when present.
2916
+ * @returns Completion after processing and outgoing handoff attempts.
2916
2917
  */
2917
- async run(replayedRoute) {
2918
+ async run(deliveredRoute) {
2918
2919
  RepositorySignals.requireCommandId(this.#command);
2919
- const intake = await this.#readIntake(replayedRoute);
2920
+ const intake = await this.#readIntake(deliveredRoute);
2920
2921
  if (intake === undefined)
2921
2922
  return undefined;
2922
2923
  const tenantOptions = RepositoryTenants.commandStandOptions(this.#runtime.context, this.#command);
2923
2924
  const loaded = await this.#support.load(intake.route.entityId, tenantOptions);
2924
2925
  await this.#publishDispatch(loaded, intake.route.entityId);
2926
+ let produced;
2925
2927
  try {
2926
- const produced = await this.#invoke(loaded.entity, intake.assignee, intake.message, tenantOptions.tenantId);
2927
- return await this.#commitAndPublish(loaded, tenantOptions, intake, produced);
2928
+ produced = await this.#invoke(loaded.entity, intake.assignee, intake.message, tenantOptions.tenantId);
2928
2929
  }
2929
2930
  catch (error) {
2930
2931
  if (!RejectionThrowable.is(error))
2931
2932
  throw error;
2932
2933
  RepositorySignals.requireDeclaredRejection(intake.assignee.handler, error);
2933
- return RepositorySignals.postRejectionEvent(this.#runtime, this.#repository, this.#command, intake.route.entityId, error);
2934
+ await RepositorySignals.postRejectionEvent(this.#runtime, this.#repository, this.#command, intake.route.entityId, error);
2935
+ return undefined;
2934
2936
  }
2937
+ await this.#commitAndPublish(loaded, tenantOptions, intake, produced);
2935
2938
  }
2936
2939
  /**
2937
2940
  * Persists required Agent dispatch history before the handler runs.
@@ -2961,14 +2964,14 @@ class ProcessManagerCommandExecution {
2961
2964
  /**
2962
2965
  * Decodes a registered Command and finds its assignee.
2963
2966
  *
2964
- * @param replayedRoute Accepted inbox route, when present.
2967
+ * @param deliveredRoute Accepted inbox route, when present.
2965
2968
  * @returns Decoded Command, route, and assignee, or `undefined`.
2966
2969
  */
2967
- async #readIntake(replayedRoute) {
2970
+ async #readIntake(deliveredRoute) {
2968
2971
  const commandMessage = EntityInvocation.requireSignalMessage(this.#command.message, "command");
2969
2972
  const commandSchema = RepositoryRoutes.schemaForTypeUrl(this.#routing.commandSchemas, commandMessage.typeUrl, "command");
2970
2973
  const message = EntityInvocation.unpackRequired(commandMessage, commandSchema, "command");
2971
- const route = replayedRoute ?? (await this.#repository.routeCommand(this.#command));
2974
+ const route = deliveredRoute ?? (await this.#repository.routeCommand(this.#command));
2972
2975
  const assignee = this.#routing.commandReadiness?.findCommandAssignee(route.messageFullTypeName);
2973
2976
  return assignee === undefined ? undefined : Object.freeze({ assignee, message, route });
2974
2977
  }
@@ -2979,7 +2982,7 @@ class ProcessManagerCommandExecution {
2979
2982
  * @param tenantOptions Stand tenant selection.
2980
2983
  * @param intake Assignee and target route.
2981
2984
  * @param producedSignals Validated handler results.
2982
- * @returns Deferred Command publication when Commands were produced.
2985
+ * @returns Completion after produced-signal handoff attempts.
2983
2986
  */
2984
2987
  async #commitAndPublish(loaded, tenantOptions, intake, producedSignals) {
2985
2988
  const commands = this.#commandOutputs(intake.assignee, producedSignals);
@@ -2988,12 +2991,10 @@ class ProcessManagerCommandExecution {
2988
2991
  if (!committed)
2989
2992
  return undefined;
2990
2993
  this.#publishChangedState(loaded, intake.route.entityId);
2991
- this.#postEvents(events);
2992
- return commands.length === 0
2993
- ? undefined
2994
- : async () => {
2995
- await this.#postCommands(commands, this.#command);
2996
- };
2994
+ await withoutDeliveryCommitFence(async () => {
2995
+ await this.#postEvents(events);
2996
+ await this.#postCommands(commands, this.#command);
2997
+ });
2997
2998
  }
2998
2999
  /**
2999
3000
  * Binds substitution results as Commands and requires nonempty output.
@@ -3156,15 +3157,15 @@ class ProcessManagerCommandExecution {
3156
3157
  }
3157
3158
  }
3158
3159
  /**
3159
- * Schedules publication of produced Events.
3160
+ * Publishes the Process Manager Command's produced Events after its commit.
3160
3161
  *
3161
3162
  * @param events Bound Events to publish.
3163
+ * @returns Completion after each Event handoff attempt.
3162
3164
  */
3163
- #postEvents(events) {
3164
- for (const event of events) {
3165
- // spine-log-boundary: server.repository_event_follow_up
3166
- void this.#runtime.publisher.publishReactorEvent(event);
3167
- }
3165
+ async #postEvents(events) {
3166
+ await Promise.all(events.map((event) => {
3167
+ return this.#runtime.publisher.publishReactorEvent(event);
3168
+ }));
3168
3169
  }
3169
3170
  }
3170
3171
  /**
@@ -3204,16 +3205,16 @@ class ProcessManagerEventExecution {
3204
3205
  }
3205
3206
  this.#validateSourceEventIdForFollowUps(intake);
3206
3207
  if (intake.route.entityIds.length === 1) {
3207
- await InboxHandoff.handoffPmEvent(this.#repository, this.#runtime, this.#event, intake.route.entityIds[0]);
3208
+ await InboxHandoff.handoffEntityEvent(this.#repository, this.#runtime, this.#event, intake.route.entityIds[0]);
3208
3209
  return;
3209
3210
  }
3210
- await InboxHandoff.handoffPmEvents(this.#repository, this.#runtime, this.#event, intake.route.entityIds);
3211
+ await InboxHandoff.handoffEntityEvents(this.#repository, this.#runtime, this.#event, intake.route.entityIds);
3211
3212
  }
3212
3213
  /**
3213
3214
  * Delivers a routed Event for one target under the duplicate-dispatch guard.
3214
3215
  *
3215
3216
  * @param entityId Target Entity identifier.
3216
- * @param acceptedRoute Route accepted before replay.
3217
+ * @param acceptedRoute Route accepted before deliver.
3217
3218
  * @returns Completion after guarded target execution.
3218
3219
  */
3219
3220
  async runTarget(entityId, acceptedRoute) {
@@ -3267,8 +3268,10 @@ class ProcessManagerEventExecution {
3267
3268
  if (!committed)
3268
3269
  return;
3269
3270
  this.#publishChangedState(loaded, entityId);
3270
- this.#postEvents(events);
3271
- this.#postCommands(commands);
3271
+ await withoutDeliveryCommitFence(async () => {
3272
+ await this.#postEvents(events);
3273
+ await this.#postCommands(commands);
3274
+ });
3272
3275
  }
3273
3276
  /**
3274
3277
  * Publishes a state-change System Event when the Entity changed.
@@ -3446,23 +3449,24 @@ class ProcessManagerEventExecution {
3446
3449
  * Publishes each produced Command in handler order.
3447
3450
  *
3448
3451
  * @param commands Bound Commands to publish.
3452
+ * @returns Completion after each Command handoff attempt.
3449
3453
  */
3450
- #postCommands(commands) {
3454
+ async #postCommands(commands) {
3451
3455
  for (const command of commands) {
3452
3456
  // spine-log-boundary: server.process_manager_command_follow_up
3453
- void this.#runtime.publisher.publishCommand(command);
3457
+ await this.#runtime.publisher.publishCommand(command);
3454
3458
  }
3455
3459
  }
3456
3460
  /**
3457
- * Schedules publication of produced Events.
3461
+ * Publishes the Process Manager Event's produced Events after its commit.
3458
3462
  *
3459
3463
  * @param events Bound Events to publish.
3464
+ * @returns Completion after each Event handoff attempt.
3460
3465
  */
3461
- #postEvents(events) {
3462
- for (const event of events) {
3463
- // spine-log-boundary: server.process_manager_event_follow_up
3464
- void this.#runtime.publisher.publishReactorEvent(event);
3465
- }
3466
+ async #postEvents(events) {
3467
+ await Promise.all(events.map((event) => {
3468
+ return this.#runtime.publisher.publishReactorEvent(event);
3469
+ }));
3466
3470
  }
3467
3471
  }
3468
3472
  /**
@@ -4132,18 +4136,18 @@ const RepositorySignals = {
4132
4136
  });
4133
4137
  },
4134
4138
  /**
4135
- * Builds a rejection Event and returns a best-effort publication follow-up.
4139
+ * Builds a rejection Event and awaits one publication attempt.
4136
4140
  *
4137
4141
  * @param runtime Context signal and publication services.
4138
4142
  * @param repository Repository of the rejected Command.
4139
4143
  * @param command Command rejected by its handler.
4140
4144
  * @param entityId Target Entity identifier.
4141
4145
  * @param rejection Declared handler rejection.
4142
- * @returns Deferred rejection Event publication.
4146
+ * @returns Completion after the rejection handoff attempt settles.
4143
4147
  */
4144
- postRejectionEvent(runtime, repository, command, entityId, rejection) {
4148
+ async postRejectionEvent(runtime, repository, command, entityId, rejection) {
4145
4149
  const event = this.rejectionEvent(runtime, repository, command, entityId, rejection);
4146
- return async () => {
4150
+ await withoutDeliveryCommitFence(async () => {
4147
4151
  try {
4148
4152
  // spine-log-boundary: server.repository_rejection_follow_up
4149
4153
  await runtime.publisher.publishRejectionEvent(event);
@@ -4151,7 +4155,7 @@ const RepositorySignals = {
4151
4155
  catch (error) {
4152
4156
  runtime.publisher.reportFailure("event", event, error);
4153
4157
  }
4154
- };
4158
+ });
4155
4159
  },
4156
4160
  /**
4157
4161
  * Creates the original declared rejection envelope without publishing it.
@@ -4738,13 +4742,13 @@ const RepositoryTenants = {
4738
4742
  return RepositoryTenants.require(tenantId);
4739
4743
  },
4740
4744
  /**
4741
- * Validates an Event tenant before Process Manager inbox handoff.
4745
+ * Validates an Event tenant before Entity Inbox handoff.
4742
4746
  *
4743
4747
  * @param context Bounded context storage mode.
4744
- * @param event Event entering Process Manager delivery.
4748
+ * @param event Event entering Entity Inbox delivery.
4745
4749
  * @returns Validated tenant, or `undefined` for single-tenant contexts.
4746
4750
  */
4747
- requirePmEventTenant(context, event) {
4751
+ requireEntityEventTenant(context, event) {
4748
4752
  if (!context.multitenant) {
4749
4753
  return undefined;
4750
4754
  }
@@ -7254,7 +7258,7 @@ const InboxMessages = {
7254
7258
  }
7255
7259
  }
7256
7260
  if (entityId === undefined) {
7257
- throw new Error("Entity Inbox replay stored target ID is incompatible with the repository.");
7261
+ throw new Error("Entity Inbox delivery stored target ID is incompatible with the repository.");
7258
7262
  }
7259
7263
  return RepositoryRoutes.readRouteId(entityId, idField, "command");
7260
7264
  },
@@ -7266,7 +7270,7 @@ const InboxMessages = {
7266
7270
  */
7267
7271
  readInboxCommand(message) {
7268
7272
  if (message.label !== "HANDLE_COMMAND") {
7269
- throw new Error(`Entity Inbox replay does not handle "${message.label}" messages.`);
7273
+ throw new Error(`Entity Inbox delivery does not handle "${message.label}" messages.`);
7270
7274
  }
7271
7275
  const command = message.signal === undefined ? undefined : AnyPacker.tryUnpack(message.signal, CommandSchema);
7272
7276
  if (command === undefined) {
@@ -7275,13 +7279,13 @@ const InboxMessages = {
7275
7279
  return command;
7276
7280
  },
7277
7281
  /**
7278
- * Reads an Event labeled for a Process Manager reaction.
7282
+ * Reads an Event labeled for an Entity reaction.
7279
7283
  *
7280
7284
  * @param message Stored Inbox message to validate and unpack.
7281
7285
  * @returns The stored Event envelope.
7282
7286
  */
7283
- readPmInboxEvent(message) {
7284
- return InboxMessages.readStoredEvent(message, "REACT_UPON_EVENT", "Entity Inbox replay", "Entity Inbox replay requires a readable stored event.");
7287
+ readEntityInboxEvent(message) {
7288
+ return InboxMessages.readStoredEvent(message, "REACT_UPON_EVENT", "Entity Inbox delivery", "Entity Inbox delivery requires a readable stored event.");
7285
7289
  },
7286
7290
  /**
7287
7291
  * Reads an Event labeled for a Projection update.
@@ -7290,20 +7294,20 @@ const InboxMessages = {
7290
7294
  * @returns The stored Event envelope.
7291
7295
  */
7292
7296
  readProjectionInboxEvent(message) {
7293
- return InboxMessages.readStoredEvent(message, "UPDATE_SUBSCRIBER", "Projection inbox replay", "Projection inbox replay requires a readable stored event.");
7297
+ return InboxMessages.readStoredEvent(message, "UPDATE_SUBSCRIBER", "Projection inbox delivery", "Projection inbox delivery requires a readable stored event.");
7294
7298
  },
7295
7299
  /**
7296
7300
  * Validates an Inbox operation label and decodes its stored Event bytes.
7297
7301
  *
7298
7302
  * @param message Stored Inbox message to inspect.
7299
7303
  * @param expectedLabel Operation label required by the caller.
7300
- * @param replayName Human-readable operation name used in label errors.
7304
+ * @param deliverName Human-readable operation name used in label errors.
7301
7305
  * @param unreadableMessage Error text used when Event decoding fails.
7302
7306
  * @returns The stored Event envelope.
7303
7307
  */
7304
- readStoredEvent(message, expectedLabel, replayName, unreadableMessage) {
7308
+ readStoredEvent(message, expectedLabel, deliverName, unreadableMessage) {
7305
7309
  if (message.label !== expectedLabel) {
7306
- throw new Error(`${replayName} does not handle "${message.label}" messages.`);
7310
+ throw new Error(`${deliverName} does not handle "${message.label}" messages.`);
7307
7311
  }
7308
7312
  const signal = message.signal === undefined
7309
7313
  ? undefined
@@ -7322,7 +7326,7 @@ Object.freeze(InboxMessages);
7322
7326
  /**
7323
7327
  * Validates and dispatches stored Inbox signals to their recorded Entity targets.
7324
7328
  */
7325
- const InboxReplay = {
7329
+ const InboxDelivery = {
7326
7330
  /**
7327
7331
  * Dispatches a stored Aggregate Command after checking its tenant and payload.
7328
7332
  *
@@ -7330,44 +7334,66 @@ const InboxReplay = {
7330
7334
  * @param routing Registered handlers and message schemas.
7331
7335
  * @param message Stored Inbox message with the recorded target.
7332
7336
  * @param deliveryTenantId Tenant selected by delivery in a multitenant context.
7333
- * @returns Any follow-up work that must wait for Inbox completion.
7337
+ * @returns Completion after processing and outgoing handoff attempts.
7334
7338
  */
7335
- async replayAggregateCommand(repository, routing, message, deliveryTenantId) {
7339
+ async deliverAggregateCommand(repository, routing, message, deliveryTenantId) {
7336
7340
  const runtime = repositoryRuntimes.get(repository);
7337
7341
  if (runtime === undefined) {
7338
- throw new Error("Aggregate inbox replay requires a bound repository runtime.");
7342
+ throw new Error("Aggregate inbox delivery requires a bound repository runtime.");
7339
7343
  }
7340
7344
  if (message.label !== "HANDLE_COMMAND") {
7341
- throw new Error(`Aggregate inbox replay does not handle "${message.label}" messages.`);
7345
+ throw new Error(`Aggregate inbox delivery does not handle "${message.label}" messages.`);
7342
7346
  }
7343
7347
  const command = InboxMessages.readInboxCommand(message);
7344
- InboxReplay.validateReplayTenant(runtime.context, deliveryTenantId, command);
7345
- InboxReplay.validateReplayedCommandPayload(routing, command);
7346
- const route = InboxReplay.replayCommandRoute(repository, routing, message, command);
7347
- return await new AggregateCommandExecution(repository, routing, runtime, command).run(route);
7348
+ InboxDelivery.validateDeliveryTenant(runtime.context, deliveryTenantId, command);
7349
+ InboxDelivery.validateDeliveredCommandPayload(routing, command);
7350
+ const route = InboxDelivery.deliverCommandRoute(repository, routing, message, command);
7351
+ await new AggregateCommandExecution(repository, routing, runtime, command).run(route);
7348
7352
  },
7349
7353
  /**
7350
- * Routes Process Manager Command or Event replay by its stored operation label.
7354
+ * Delivers a stored Event to the recorded Aggregate target.
7355
+ *
7356
+ * @param repository Aggregate repository receiving the Event.
7357
+ * @param routing Registered Event handlers and message schemas.
7358
+ * @param message Stored Inbox row with the recorded target.
7359
+ * @param deliveryTenantId Tenant selected by delivery in a multitenant context.
7360
+ * @returns Completion after the guarded reactor and outgoing handoff attempts.
7361
+ */
7362
+ async deliverAggregateEvent(repository, routing, message, deliveryTenantId) {
7363
+ const runtime = repositoryRuntimes.get(repository);
7364
+ if (runtime === undefined) {
7365
+ throw new Error("Aggregate inbox delivery requires a bound repository runtime.");
7366
+ }
7367
+ const event = InboxMessages.readEntityInboxEvent(message);
7368
+ InboxDelivery.validateEventTenant(runtime.context, deliveryTenantId, event);
7369
+ InboxDelivery.validateDeliveredEventPayload(routing, event, "Aggregate inbox delivery requires a readable event payload.");
7370
+ const route = InboxDelivery.deliverEventRoute(repository, routing, message, event, "Aggregate inbox delivery");
7371
+ const [entityId] = route.entityIds;
7372
+ await DispatchGuards.guardedEntityEventDispatch(repository, runtime, event, entityId, () => new AggregateEventExecution(repository, routing, runtime, event).runTarget(entityId, route));
7373
+ },
7374
+ /**
7375
+ * Routes Process Manager Command or Event deliver by its stored operation label.
7351
7376
  *
7352
7377
  * @param repository Process Manager repository receiving the signal.
7353
7378
  * @param routing Registered handlers and message schemas.
7354
7379
  * @param message Stored Inbox message with the recorded target.
7355
7380
  * @param deliveryTenantId Tenant selected by delivery in a multitenant context.
7356
- * @returns Any Command follow-up work that must wait for Inbox completion.
7381
+ * @returns Completion after processing and outgoing handoff attempts.
7357
7382
  */
7358
- async replayPmInbox(repository, routing, message, deliveryTenantId) {
7383
+ async deliverPmInbox(repository, routing, message, deliveryTenantId) {
7359
7384
  if (repository.entityFamily === "agent") {
7360
- await InboxReplay.replayAgentInbox(repository, routing, message, deliveryTenantId);
7385
+ await InboxDelivery.deliverAgentInbox(repository, routing, message, deliveryTenantId);
7361
7386
  return undefined;
7362
7387
  }
7363
7388
  if (message.label === "HANDLE_COMMAND") {
7364
- return await InboxReplay.replayProcessManagerCommand(repository, routing, message, deliveryTenantId);
7389
+ await InboxDelivery.deliverProcessManagerCommand(repository, routing, message, deliveryTenantId);
7390
+ return;
7365
7391
  }
7366
7392
  if (message.label === "REACT_UPON_EVENT") {
7367
- await InboxReplay.replayProcessManagerEvent(repository, routing, message, deliveryTenantId);
7393
+ await InboxDelivery.deliverProcessManagerEvent(repository, routing, message, deliveryTenantId);
7368
7394
  return undefined;
7369
7395
  }
7370
- throw new Error(`Entity Inbox replay does not handle "${message.label}" messages.`);
7396
+ throw new Error(`Entity Inbox delivery does not handle "${message.label}" messages.`);
7371
7397
  },
7372
7398
  /**
7373
7399
  * Persists selected Agent work before the normal Inbox acknowledges delivery.
@@ -7378,17 +7404,17 @@ const InboxReplay = {
7378
7404
  * @param deliveryTenantId Tenant selected by delivery.
7379
7405
  * @returns When the fenced repository operation completes.
7380
7406
  */
7381
- async replayAgentInbox(repository, routing, message, deliveryTenantId) {
7407
+ async deliverAgentInbox(repository, routing, message, deliveryTenantId) {
7382
7408
  const runtime = repositoryRuntimes.get(repository);
7383
7409
  if (runtime === undefined)
7384
- throw new Error("Agent Inbox replay requires a bound runtime.");
7410
+ throw new Error("Agent Inbox delivery requires a bound runtime.");
7385
7411
  if (message.label === "HANDLE_COMMAND") {
7386
- await InboxReplay.replayAgentCommand(repository, routing, runtime, message, deliveryTenantId);
7412
+ await InboxDelivery.deliverAgentCommand(repository, routing, runtime, message, deliveryTenantId);
7387
7413
  return;
7388
7414
  }
7389
7415
  if (message.label !== "REACT_UPON_EVENT")
7390
- throw new Error(`Agent Inbox replay does not handle "${message.label}" messages.`);
7391
- await InboxReplay.replayAgentEvent(repository, routing, runtime, message, deliveryTenantId);
7416
+ throw new Error(`Agent Inbox delivery does not handle "${message.label}" messages.`);
7417
+ await InboxDelivery.deliverAgentEvent(repository, routing, runtime, message, deliveryTenantId);
7392
7418
  },
7393
7419
  /**
7394
7420
  * Admits a Command using its stored target and registered assignee.
@@ -7400,15 +7426,15 @@ const InboxReplay = {
7400
7426
  * @param tenantId Delivery tenant.
7401
7427
  * @returns When the fenced repository operation completes.
7402
7428
  */
7403
- async replayAgentCommand(repository, routing, runtime, message, tenantId) {
7429
+ async deliverAgentCommand(repository, routing, runtime, message, tenantId) {
7404
7430
  const command = InboxMessages.readInboxCommand(message);
7405
- InboxReplay.validateReplayTenant(runtime.context, tenantId, command);
7406
- InboxReplay.validateReplayedCommandPayload(routing, command);
7407
- const route = InboxReplay.replayCommandRoute(repository, routing, message, command);
7431
+ InboxDelivery.validateDeliveryTenant(runtime.context, tenantId, command);
7432
+ InboxDelivery.validateDeliveredCommandPayload(routing, command);
7433
+ const route = InboxDelivery.deliverCommandRoute(repository, routing, message, command);
7408
7434
  const assignee = routing.commandReadiness?.findCommandAssignee(route.messageFullTypeName);
7409
7435
  if (assignee === undefined)
7410
7436
  throw new Error("Agent Command has no selected assignee.");
7411
- await InboxReplay.admitAgent(repository, runtime, message, tenantId, route.entityId, { case: "command", value: command }, [assignee.registeredHandler]);
7437
+ await InboxDelivery.admitAgent(repository, runtime, message, tenantId, route.entityId, { case: "command", value: command }, [assignee.registeredHandler]);
7412
7438
  },
7413
7439
  /**
7414
7440
  * Admits matching Event handlers from the stored target without rerouting.
@@ -7420,15 +7446,15 @@ const InboxReplay = {
7420
7446
  * @param tenantId Delivery tenant.
7421
7447
  * @returns When the fenced repository operation completes.
7422
7448
  */
7423
- async replayAgentEvent(repository, routing, runtime, message, tenantId) {
7424
- const event = InboxMessages.readPmInboxEvent(message);
7425
- InboxReplay.validatePmReplayTenant(runtime.context, tenantId, event);
7426
- InboxReplay.validateReplayedEventPayload(routing, event, "Agent Inbox replay requires an Event payload.");
7427
- const route = InboxReplay.replayEventRoute(repository, routing, message, event, "Agent Inbox replay");
7428
- const handlers = InboxReplay.agentEventHandlers(routing, route.messageFullTypeName, event);
7449
+ async deliverAgentEvent(repository, routing, runtime, message, tenantId) {
7450
+ const event = InboxMessages.readEntityInboxEvent(message);
7451
+ InboxDelivery.validateEventTenant(runtime.context, tenantId, event);
7452
+ InboxDelivery.validateDeliveredEventPayload(routing, event, "Agent Inbox delivery requires an Event payload.");
7453
+ const route = InboxDelivery.deliverEventRoute(repository, routing, message, event, "Agent Inbox delivery");
7454
+ const handlers = InboxDelivery.agentEventHandlers(routing, route.messageFullTypeName, event);
7429
7455
  if (handlers.length === 0)
7430
7456
  return;
7431
- await InboxReplay.admitAgent(repository, runtime, message, tenantId, route.entityIds[0], { case: "event", value: event }, handlers);
7457
+ await InboxDelivery.admitAgent(repository, runtime, message, tenantId, route.entityIds[0], { case: "event", value: event }, handlers);
7432
7458
  },
7433
7459
  /**
7434
7460
  * Restores selected Event and Command reactions from the original payload.
@@ -7467,14 +7493,14 @@ const InboxReplay = {
7467
7493
  if (deliverySignal === undefined)
7468
7494
  throw new Error("Agent admission requires delivery scope.");
7469
7495
  const cancellation = AbortSignal.any([deliverySignal, runtime.agentSignal]);
7470
- const key = InboxReplay.capacityKeyFor(repository, input.context, input.id.key(entityId));
7496
+ const key = InboxDelivery.capacityKeyFor(repository, input.context, input.id.key(entityId));
7471
7497
  const reservation = runtime.reserveAgent(key, cancellation);
7472
7498
  if (reservation === undefined) {
7473
7499
  runtime.deferAgent(message, tenantId);
7474
7500
  AgentDeliveryScope.record({ kind: "deferred" });
7475
7501
  return;
7476
7502
  }
7477
- await InboxReplay.admitReservedAgent({
7503
+ await InboxDelivery.admitReservedAgent({
7478
7504
  repository,
7479
7505
  runtime,
7480
7506
  context: input.context,
@@ -7516,13 +7542,13 @@ const InboxReplay = {
7516
7542
  async admitReservedAgent(input) {
7517
7543
  const { repository, runtime, context, message, signal, reservation } = input;
7518
7544
  try {
7519
- const accepted = await InboxReplay.acceptAgentReceipt(runtime, context, repository, message, signal);
7545
+ const accepted = await InboxDelivery.acceptAgentReceipt(runtime, context, repository, message, signal);
7520
7546
  if (!accepted) {
7521
7547
  reservation.release();
7522
7548
  AgentDeliveryScope.record({ kind: "duplicate" });
7523
7549
  return;
7524
7550
  }
7525
- InboxReplay.recordAcceptedAgent(input);
7551
+ InboxDelivery.recordAcceptedAgent(input);
7526
7552
  }
7527
7553
  catch (error) {
7528
7554
  reservation.release();
@@ -7547,7 +7573,7 @@ const InboxReplay = {
7547
7573
  },
7548
7574
  run: (fence, checkSession) => {
7549
7575
  const cancellation = AbortSignal.any([fence, runtime.agentSignal]);
7550
- const checkAgentSession = InboxReplay.agentSessionGuard(cancellation, checkSession);
7576
+ const checkAgentSession = InboxDelivery.agentSessionGuard(cancellation, checkSession);
7551
7577
  return reservation.run(() => withDeliveryCommitFence(checkAgentSession, () => new AgentLiveRunner(repository, runtime, tenantId, entityId, invocation, handlers, cancellation, checkAgentSession).run()));
7552
7578
  },
7553
7579
  });
@@ -7576,8 +7602,8 @@ const InboxReplay = {
7576
7602
  */
7577
7603
  acceptAgentReceipt(runtime, context, repository, message, signal) {
7578
7604
  const source = signal.case === "command"
7579
- ? { kind: "command", id: InboxReplay.requireAgentCommandId(signal.value) }
7580
- : { kind: "event", id: InboxReplay.requireAgentEventId(signal.value) };
7605
+ ? { kind: "command", id: InboxDelivery.requireAgentCommandId(signal.value) }
7606
+ : { kind: "event", id: InboxDelivery.requireAgentEventId(signal.value) };
7581
7607
  return runtime.agentReceipts.accept(context, {
7582
7608
  stateType: repository.stateSchema.typeName,
7583
7609
  recipientId: message.inboxId.targetId,
@@ -7612,18 +7638,18 @@ const InboxReplay = {
7612
7638
  * @param routing Registered handlers and message schemas.
7613
7639
  * @param message Stored Inbox message with the recorded target.
7614
7640
  * @param deliveryTenantId Tenant selected by delivery in a multitenant context.
7615
- * @returns Any follow-up work that must wait for Inbox completion.
7641
+ * @returns Completion after processing and outgoing handoff attempts.
7616
7642
  */
7617
- async replayProcessManagerCommand(repository, routing, message, deliveryTenantId) {
7643
+ async deliverProcessManagerCommand(repository, routing, message, deliveryTenantId) {
7618
7644
  const runtime = repositoryRuntimes.get(repository);
7619
7645
  if (runtime === undefined) {
7620
- throw new Error("Entity Inbox replay requires a bound repository runtime.");
7646
+ throw new Error("Entity Inbox delivery requires a bound repository runtime.");
7621
7647
  }
7622
7648
  const command = InboxMessages.readInboxCommand(message);
7623
- InboxReplay.validateReplayTenant(runtime.context, deliveryTenantId, command);
7624
- InboxReplay.validateReplayedCommandPayload(routing, command);
7625
- const route = InboxReplay.replayCommandRoute(repository, routing, message, command);
7626
- return await new ProcessManagerCommandExecution(repository, routing, runtime, command).run(route);
7649
+ InboxDelivery.validateDeliveryTenant(runtime.context, deliveryTenantId, command);
7650
+ InboxDelivery.validateDeliveredCommandPayload(routing, command);
7651
+ const route = InboxDelivery.deliverCommandRoute(repository, routing, message, command);
7652
+ await new ProcessManagerCommandExecution(repository, routing, runtime, command).run(route);
7627
7653
  },
7628
7654
  /**
7629
7655
  * Dispatches a validated Event to the Process Manager target recorded in its Inbox.
@@ -7634,15 +7660,15 @@ const InboxReplay = {
7634
7660
  * @param deliveryTenantId Tenant selected by delivery in a multitenant context.
7635
7661
  * @returns Completion of dispatch to the recorded target.
7636
7662
  */
7637
- async replayProcessManagerEvent(repository, routing, message, deliveryTenantId) {
7663
+ async deliverProcessManagerEvent(repository, routing, message, deliveryTenantId) {
7638
7664
  const runtime = repositoryRuntimes.get(repository);
7639
7665
  if (runtime === undefined) {
7640
- throw new Error("Entity Inbox replay requires a bound repository runtime.");
7666
+ throw new Error("Entity Inbox delivery requires a bound repository runtime.");
7641
7667
  }
7642
- const event = InboxMessages.readPmInboxEvent(message);
7643
- InboxReplay.validatePmReplayTenant(runtime.context, deliveryTenantId, event);
7644
- InboxReplay.validateReplayedEventPayload(routing, event, "Entity Inbox replay requires a readable event payload.");
7645
- const route = InboxReplay.replayEventRoute(repository, routing, message, event, "Entity Inbox replay");
7668
+ const event = InboxMessages.readEntityInboxEvent(message);
7669
+ InboxDelivery.validateEventTenant(runtime.context, deliveryTenantId, event);
7670
+ InboxDelivery.validateDeliveredEventPayload(routing, event, "Entity Inbox delivery requires a readable event payload.");
7671
+ const route = InboxDelivery.deliverEventRoute(repository, routing, message, event, "Entity Inbox delivery");
7646
7672
  const [entityId] = route.entityIds;
7647
7673
  await new ProcessManagerEventExecution(repository, routing, runtime, event).runTarget(entityId, route);
7648
7674
  },
@@ -7655,34 +7681,34 @@ const InboxReplay = {
7655
7681
  * @param deliveryTenantId Tenant selected by delivery in a multitenant context.
7656
7682
  * @returns Completion of dispatch to the recorded target.
7657
7683
  */
7658
- async replayProjectionEvent(repository, routing, message, deliveryTenantId) {
7684
+ async deliverProjectionEvent(repository, routing, message, deliveryTenantId) {
7659
7685
  const runtime = repositoryRuntimes.get(repository);
7660
7686
  if (runtime === undefined) {
7661
- throw new Error("Projection inbox replay requires a bound repository runtime.");
7687
+ throw new Error("Projection inbox delivery requires a bound repository runtime.");
7662
7688
  }
7663
7689
  const event = InboxMessages.readProjectionInboxEvent(message);
7664
- InboxReplay.validateProjectionReplayTenant(runtime.context, deliveryTenantId, event);
7665
- InboxReplay.validateReplayedEventPayload(routing, event);
7666
- const route = InboxReplay.replayEventRoute(repository, routing, message, event, "Projection inbox replay");
7690
+ InboxDelivery.validateProjectionDeliveryTenant(runtime.context, deliveryTenantId, event);
7691
+ InboxDelivery.validateDeliveredEventPayload(routing, event);
7692
+ const route = InboxDelivery.deliverEventRoute(repository, routing, message, event, "Projection inbox delivery");
7667
7693
  const [entityId] = route.entityIds;
7668
7694
  await new ProjectionEventExecution(repository, routing, runtime, event).runTarget(entityId, route);
7669
7695
  },
7670
7696
  /**
7671
- * Routes a Projection Inbox message to domain Event or Entity-state update replay.
7697
+ * Routes a Projection Inbox message to domain Event or Entity-state update deliver.
7672
7698
  *
7673
7699
  * @param repository Projection repository receiving the update.
7674
7700
  * @param routing Registered subscribers and message schemas.
7675
7701
  * @param message Stored Projection Inbox message.
7676
7702
  * @param deliveryTenantId Tenant selected by delivery in a multitenant context.
7677
- * @returns Completion of the selected replay operation.
7703
+ * @returns Completion of the selected deliver operation.
7678
7704
  */
7679
- async replayProjectionMessage(repository, routing, message, deliveryTenantId) {
7705
+ async deliverProjectionMessage(repository, routing, message, deliveryTenantId) {
7680
7706
  const event = InboxMessages.readProjectionInboxEvent(message);
7681
7707
  if (event.message?.typeUrl === TypeUrls.derive(EntityLog.EntityStateChangedSchema)) {
7682
- await InboxReplay.replayProjectionStateUpdate(repository, routing, message, event, deliveryTenantId);
7708
+ await InboxDelivery.deliverProjectionStateUpdate(repository, routing, message, event, deliveryTenantId);
7683
7709
  return;
7684
7710
  }
7685
- await InboxReplay.replayProjectionEvent(repository, routing, message, deliveryTenantId);
7711
+ await InboxDelivery.deliverProjectionEvent(repository, routing, message, deliveryTenantId);
7686
7712
  },
7687
7713
  /**
7688
7714
  * Dispatches an Entity-state update to the Projection target recorded in its Inbox.
@@ -7694,12 +7720,12 @@ const InboxReplay = {
7694
7720
  * @param deliveryTenantId Tenant selected by delivery in a multitenant context.
7695
7721
  * @returns Completion of state-subscriber dispatch to the recorded target.
7696
7722
  */
7697
- async replayProjectionStateUpdate(repository, routing, message, event, deliveryTenantId) {
7723
+ async deliverProjectionStateUpdate(repository, routing, message, event, deliveryTenantId) {
7698
7724
  const runtime = repositoryRuntimes.get(repository);
7699
7725
  if (runtime === undefined)
7700
- throw new Error("Projection inbox replay requires a bound repository runtime.");
7701
- InboxReplay.validateProjectionReplayTenant(runtime.context, deliveryTenantId, event);
7702
- const route = InboxReplay.replayStateUpdateRoute(repository, routing, message, event);
7726
+ throw new Error("Projection inbox delivery requires a bound repository runtime.");
7727
+ InboxDelivery.validateProjectionDeliveryTenant(runtime.context, deliveryTenantId, event);
7728
+ const route = InboxDelivery.deliverStateUpdateRoute(repository, routing, message, event);
7703
7729
  const [entityId] = route.entityIds;
7704
7730
  const subscribers = route.subscribers;
7705
7731
  await ProjectionEventExecution.runStateTarget(repository, routing, runtime, event, entityId, route, subscribers);
@@ -7708,9 +7734,9 @@ const InboxReplay = {
7708
7734
  * Validates a stored Command against its schema and implicit identifier requirements.
7709
7735
  *
7710
7736
  * @param routing Registered Command schemas.
7711
- * @param command Envelope whose payload must remain valid on replay.
7737
+ * @param command Envelope whose payload must remain valid on deliver.
7712
7738
  */
7713
- validateReplayedCommandPayload(routing, command) {
7739
+ validateDeliveredCommandPayload(routing, command) {
7714
7740
  const commandMessage = EntityInvocation.requireSignalMessage(command.message, "command");
7715
7741
  const commandSchema = RepositoryRoutes.schemaForTypeUrl(routing.commandSchemas, commandMessage.typeUrl, "command");
7716
7742
  const payload = AnyPacker.tryUnpack(commandMessage, commandSchema);
@@ -7735,10 +7761,10 @@ const InboxReplay = {
7735
7761
  * Unpacks and validates a stored Event against its registered schema.
7736
7762
  *
7737
7763
  * @param routing Registered Event schemas.
7738
- * @param event Envelope whose payload must remain valid on replay.
7764
+ * @param event Envelope whose payload must remain valid on deliver.
7739
7765
  * @param invalidPayloadMessage Error text used when the payload cannot be unpacked.
7740
7766
  */
7741
- validateReplayedEventPayload(routing, event, invalidPayloadMessage = "Projection inbox replay requires a readable event payload.") {
7767
+ validateDeliveredEventPayload(routing, event, invalidPayloadMessage = "Projection inbox delivery requires a readable event payload.") {
7742
7768
  const eventMessage = EntityInvocation.requireSignalMessage(event.message, "event");
7743
7769
  const eventSchema = RepositoryRoutes.schemaForTypeUrl(routing.eventSchemas, eventMessage.typeUrl, "event");
7744
7770
  const payload = AnyPacker.tryUnpack(eventMessage, eventSchema);
@@ -7748,69 +7774,69 @@ const InboxReplay = {
7748
7774
  Validate.check(eventSchema, payload);
7749
7775
  },
7750
7776
  /**
7751
- * Checks that a replayed Command's tenant matches its delivery tenant.
7777
+ * Checks that a delivered Command's tenant matches its delivery tenant.
7752
7778
  *
7753
7779
  * @param context Context name and tenant mode; single-tenant contexts need no check.
7754
7780
  * @param deliveryTenantId Tenant selected by Inbox delivery.
7755
7781
  * @param command Stored Command containing the original actor context.
7756
7782
  */
7757
- validateReplayTenant(context, deliveryTenantId, command) {
7783
+ validateDeliveryTenant(context, deliveryTenantId, command) {
7758
7784
  if (!context.multitenant) {
7759
7785
  return;
7760
7786
  }
7761
7787
  if (deliveryTenantId === undefined) {
7762
- throw new Error(`Multitenant Entity Inbox replay for "${context.name}" requires tenantId.`);
7788
+ throw new Error(`Multitenant Entity Inbox delivery for "${context.name}" requires tenantId.`);
7763
7789
  }
7764
7790
  const envelopeTenantId = RepositoryTenants.readCommandTenant(command);
7765
7791
  if (envelopeTenantId === undefined) {
7766
- throw new Error("Entity Inbox replay requires stored command tenant metadata.");
7792
+ throw new Error("Entity Inbox delivery requires stored command tenant metadata.");
7767
7793
  }
7768
7794
  if (!RepositoryTenants.equal(envelopeTenantId, deliveryTenantId)) {
7769
- throw new Error("Entity Inbox replay stored command tenant does not match.");
7795
+ throw new Error("Entity Inbox delivery stored command tenant does not match.");
7770
7796
  }
7771
7797
  },
7772
7798
  /**
7773
- * Checks that a replayed Projection Event's tenant matches its delivery tenant.
7799
+ * Checks that a delivered Projection Event's tenant matches its delivery tenant.
7774
7800
  *
7775
7801
  * @param context Context name and tenant mode; single-tenant contexts need no check.
7776
7802
  * @param deliveryTenantId Tenant selected by Inbox delivery.
7777
7803
  * @param event Stored Event containing the original tenant metadata.
7778
7804
  */
7779
- validateProjectionReplayTenant(context, deliveryTenantId, event) {
7805
+ validateProjectionDeliveryTenant(context, deliveryTenantId, event) {
7780
7806
  if (!context.multitenant) {
7781
7807
  return;
7782
7808
  }
7783
7809
  if (deliveryTenantId === undefined) {
7784
- throw new Error(`Multitenant projection inbox replay for "${context.name}" requires tenantId.`);
7810
+ throw new Error(`Multitenant projection inbox delivery for "${context.name}" requires tenantId.`);
7785
7811
  }
7786
7812
  const envelopeTenantId = RepositoryTenants.readEventTenant(event);
7787
7813
  if (envelopeTenantId === undefined) {
7788
- throw new Error("Projection inbox replay requires stored event tenant metadata.");
7814
+ throw new Error("Projection inbox delivery requires stored event tenant metadata.");
7789
7815
  }
7790
7816
  if (!RepositoryTenants.equal(envelopeTenantId, deliveryTenantId)) {
7791
- throw new Error("Projection inbox replay stored event tenant does not match.");
7817
+ throw new Error("Projection inbox delivery stored event tenant does not match.");
7792
7818
  }
7793
7819
  },
7794
7820
  /**
7795
- * Checks that a replayed Process Manager Event's tenant matches its delivery tenant.
7821
+ * Checks that a delivered Entity Event's tenant matches its delivery tenant.
7796
7822
  *
7797
7823
  * @param context Context name and tenant mode; single-tenant contexts need no check.
7798
7824
  * @param deliveryTenantId Tenant selected by Inbox delivery.
7799
7825
  * @param event Stored Event containing the original tenant metadata.
7800
7826
  */
7801
- validatePmReplayTenant(context, deliveryTenantId, event) {
7827
+ validateEventTenant(context, deliveryTenantId, event) {
7802
7828
  if (!context.multitenant) {
7803
7829
  return;
7804
7830
  }
7805
7831
  if (deliveryTenantId === undefined) {
7806
- throw new Error(`Multitenant Entity Inbox replay for "${context.name}" requires tenantId.`);
7832
+ throw new Error(`Multitenant Entity Inbox delivery for "${context.name}" requires tenantId.`);
7807
7833
  }
7808
7834
  const envelopeTenantId = RepositoryTenants.readEventTenant(event);
7809
7835
  if (envelopeTenantId === undefined) {
7810
- throw new Error("Entity Inbox replay requires stored event tenant metadata.");
7836
+ throw new Error("Entity Inbox delivery requires stored event tenant metadata.");
7811
7837
  }
7812
7838
  if (!RepositoryTenants.equal(envelopeTenantId, deliveryTenantId)) {
7813
- throw new Error("Entity Inbox replay stored event tenant does not match.");
7839
+ throw new Error("Entity Inbox delivery stored event tenant does not match.");
7814
7840
  }
7815
7841
  },
7816
7842
  /**
@@ -7822,10 +7848,10 @@ const InboxReplay = {
7822
7848
  * @param command Stored Command used to identify the registered handler schema.
7823
7849
  * @returns A deferred route to the recorded Entity identifier.
7824
7850
  */
7825
- replayCommandRoute(repository, routing, message, command) {
7851
+ deliverCommandRoute(repository, routing, message, command) {
7826
7852
  const expectedTargetTypeUrl = TypeUrls.derive(repository.stateSchema);
7827
7853
  if (message.inboxId.targetTypeUrl !== expectedTargetTypeUrl) {
7828
- throw new Error("Entity Inbox replay stored target type does not match the routed repository.");
7854
+ throw new Error("Entity Inbox delivery stored target type does not match the routed repository.");
7829
7855
  }
7830
7856
  const commandMessage = EntityInvocation.requireSignalMessage(command.message, "command");
7831
7857
  const schema = RepositoryRoutes.schemaForTypeUrl(routing.commandSchemas, commandMessage.typeUrl, "command");
@@ -7842,13 +7868,13 @@ const InboxReplay = {
7842
7868
  * @param routing Registered Event schemas.
7843
7869
  * @param message Inbox message recording the target type and identifier.
7844
7870
  * @param event Stored Event used to identify the registered handler schema.
7845
- * @param replayName Operation name used when reporting a target-type mismatch.
7871
+ * @param deliverName Operation name used when reporting a target-type mismatch.
7846
7872
  * @returns A deferred route containing exactly the recorded target identifier.
7847
7873
  */
7848
- replayEventRoute(repository, routing, message, event, replayName) {
7874
+ deliverEventRoute(repository, routing, message, event, deliverName) {
7849
7875
  const expectedTargetTypeUrl = TypeUrls.derive(repository.stateSchema);
7850
7876
  if (message.inboxId.targetTypeUrl !== expectedTargetTypeUrl) {
7851
- throw new Error(`${replayName} stored target type does not match the routed repository.`);
7877
+ throw new Error(`${deliverName} stored target type does not match the routed repository.`);
7852
7878
  }
7853
7879
  const eventMessage = EntityInvocation.requireSignalMessage(event.message, "event");
7854
7880
  const schema = RepositoryRoutes.schemaForTypeUrl(routing.eventSchemas, eventMessage.typeUrl, "event");
@@ -7869,15 +7895,15 @@ const InboxReplay = {
7869
7895
  * @param event Stored Entity-state update envelope.
7870
7896
  * @returns A deferred route with the unpacked state and matching subscribers.
7871
7897
  */
7872
- replayStateUpdateRoute(repository, routing, message, event) {
7898
+ deliverStateUpdateRoute(repository, routing, message, event) {
7873
7899
  const expectedTargetTypeUrl = TypeUrls.derive(repository.stateSchema);
7874
7900
  if (message.inboxId.targetTypeUrl !== expectedTargetTypeUrl) {
7875
- throw new Error("Projection inbox replay stored target type does not match the routed repository.");
7901
+ throw new Error("Projection inbox delivery stored target type does not match the routed repository.");
7876
7902
  }
7877
- const update = RepositoryRoutes.decodeStateUpdate(event, routing.stateSchemas, "Projection inbox replay");
7903
+ const update = RepositoryRoutes.decodeStateUpdate(event, routing.stateSchemas, "Projection inbox delivery");
7878
7904
  if (update === undefined ||
7879
7905
  (routing.stateSubscriptions.get(update.schema.typeName)?.length ?? 0) === 0) {
7880
- throw new Error("Projection inbox replay requires a readable stored Entity state update.");
7906
+ throw new Error("Projection inbox delivery requires a readable stored Entity state update.");
7881
7907
  }
7882
7908
  const { schema, state } = update;
7883
7909
  const entityId = InboxMessages.targetEntityId(message.inboxId.targetId, repository.idField);
@@ -7886,7 +7912,7 @@ const InboxReplay = {
7886
7912
  entityIds,
7887
7913
  messageFullTypeName: schema.typeName,
7888
7914
  state,
7889
- subscribers: InboxReplay.stateSubscribers(routing, schema, event),
7915
+ subscribers: InboxDelivery.stateSubscribers(routing, schema, event),
7890
7916
  invocation: "deferred",
7891
7917
  });
7892
7918
  },
@@ -7903,7 +7929,7 @@ const InboxReplay = {
7903
7929
  return Object.freeze(candidates.filter((subscriber) => (subscriber.handler.origin === "external") === (event.context?.external === true)));
7904
7930
  },
7905
7931
  };
7906
- Object.freeze(InboxReplay);
7932
+ Object.freeze(InboxDelivery);
7907
7933
  /**
7908
7934
  * Records routed signals in the appropriate Entity or Projection Inbox.
7909
7935
  */
@@ -7914,7 +7940,7 @@ const InboxHandoff = {
7914
7940
  * @param repository Repository supplying the Command route and Entity type.
7915
7941
  * @param runtime Inbox, storage, tenant mode, and delivery strategy.
7916
7942
  * @param command Command envelope to retain and deliver.
7917
- * @returns Completion of Inbox receipt and its selected delivery operation.
7943
+ * @returns Completion after Inbox receipt and eligible delivery scheduling.
7918
7944
  * @param acceptedRoute Recipient route saved when the signal was accepted.
7919
7945
  */
7920
7946
  async handoffEntityCommand(repository, runtime, command, acceptedRoute) {
@@ -7942,7 +7968,7 @@ const InboxHandoff = {
7942
7968
  * @param runtime Projection Inbox, storage, and tenant mode.
7943
7969
  * @param event Event envelope to retain and deliver.
7944
7970
  * @param entityId Routed Projection identifier.
7945
- * @returns Completion of Inbox receipt and delivery.
7971
+ * @returns Completion after Inbox receipt and eligible delivery scheduling.
7946
7972
  */
7947
7973
  async handoffProjectionEvent(repository, runtime, event, entityId) {
7948
7974
  const eventId = RepositorySignals.requireEventId(event);
@@ -7963,53 +7989,53 @@ const InboxHandoff = {
7963
7989
  }, deliveryTenantId);
7964
7990
  },
7965
7991
  /**
7966
- * Delivers an Event to one Process Manager target using its Entity Inbox.
7992
+ * Delivers an Event to one Entity target using its Inbox.
7967
7993
  *
7968
- * @param repository Repository supplying the Process Manager type and ID descriptor.
7994
+ * @param repository Repository supplying the Entity type and ID descriptor.
7969
7995
  * @param runtime Entity Inbox, storage, tenant mode, and delivery strategy.
7970
7996
  * @param event Event envelope to retain and deliver.
7971
- * @param entityId Routed Process Manager identifier.
7972
- * @returns Completion of Inbox receipt and its selected delivery operation.
7997
+ * @param entityId Routed Entity identifier.
7998
+ * @returns Completion after Inbox receipt and eligible delivery scheduling.
7973
7999
  */
7974
- async handoffPmEvent(repository, runtime, event, entityId) {
8000
+ async handoffEntityEvent(repository, runtime, event, entityId) {
7975
8001
  const eventId = RepositorySignals.requireEventId(event);
7976
8002
  const keepUntil = new Date(Time.currentTimeMillis() + inboxDedupMs);
7977
- const deliveryTenantId = RepositoryTenants.requirePmEventTenant(runtime.context, event);
8003
+ const deliveryTenantId = RepositoryTenants.requireEntityEventTenant(runtime.context, event);
7978
8004
  const delivery = serverEnvironmentAccess.coreDelivery(ServerEnvironment.instance());
7979
- await runtime.entityInbox.receive(delivery, InboxHandoff.pmEventInboxInput(repository, eventId.value, event, entityId, keepUntil), deliveryTenantId);
8005
+ await runtime.entityInbox.receive(delivery, InboxHandoff.entityEventInboxInput(repository, eventId.value, event, entityId, keepUntil), deliveryTenantId);
7980
8006
  },
7981
8007
  /**
7982
- * Delivers an Event to all routed Process Manager targets through batch receipt.
8008
+ * Delivers an Event to all routed Entity targets through batch receipt.
7983
8009
  *
7984
- * @param repository Repository supplying the Process Manager type and ID descriptor.
8010
+ * @param repository Repository supplying the Entity type and ID descriptor.
7985
8011
  * @param runtime Entity Inbox, storage, tenant mode, and delivery strategy.
7986
8012
  * @param event Event envelope shared by the target deliveries.
7987
- * @param entityIds Routed Process Manager identifiers.
7988
- * @returns Completion of batch receipt and its selected delivery operation.
8013
+ * @param entityIds Routed Entity identifiers.
8014
+ * @returns Completion after batch Inbox receipts and eligible delivery scheduling.
7989
8015
  */
7990
- async handoffPmEvents(repository, runtime, event, entityIds) {
8016
+ async handoffEntityEvents(repository, runtime, event, entityIds) {
7991
8017
  const eventId = RepositorySignals.requireEventId(event);
7992
8018
  const keepUntil = new Date(Time.currentTimeMillis() + inboxDedupMs);
7993
- const deliveryTenantId = RepositoryTenants.requirePmEventTenant(runtime.context, event);
8019
+ const deliveryTenantId = RepositoryTenants.requireEntityEventTenant(runtime.context, event);
7994
8020
  const delivery = serverEnvironmentAccess.coreDelivery(ServerEnvironment.instance());
7995
8021
  for (let start = 0; start < entityIds.length; start += 1_000) {
7996
8022
  const inputs = entityIds
7997
8023
  .slice(start, start + 1_000)
7998
- .map((entityId) => InboxHandoff.pmEventInboxInput(repository, eventId.value, event, entityId, keepUntil));
8024
+ .map((entityId) => InboxHandoff.entityEventInboxInput(repository, eventId.value, event, entityId, keepUntil));
7999
8025
  await runtime.entityInbox.receiveAll(delivery, inputs, deliveryTenantId);
8000
8026
  }
8001
8027
  },
8002
8028
  /**
8003
- * Builds a pending Process Manager Event delivery for a single target.
8029
+ * Builds a pending Entity Event delivery for a single target.
8004
8030
  *
8005
8031
  * @param repository Repository supplying the target type and ID descriptor.
8006
8032
  * @param signalId Identifier of the original Event.
8007
8033
  * @param event Event envelope to pack without repeating validation.
8008
- * @param entityId Routed Process Manager identifier.
8034
+ * @param entityId Routed Entity identifier.
8009
8035
  * @param keepUntil Duplicate-retention deadline for this receipt.
8010
8036
  * @returns Input for Entity Inbox receipt.
8011
8037
  */
8012
- pmEventInboxInput(repository, signalId, event, entityId, keepUntil) {
8038
+ entityEventInboxInput(repository, signalId, event, entityId, keepUntil) {
8013
8039
  return {
8014
8040
  inboxId: {
8015
8041
  targetId: InboxMessages.inboxTargetId(entityId, repository.idField),
@@ -8025,7 +8051,7 @@ const InboxHandoff = {
8025
8051
  };
8026
8052
  Object.freeze(InboxHandoff);
8027
8053
  /**
8028
- * Connects bus dispatchers and Inbox replay to repository execution.
8054
+ * Connects bus dispatchers and Inbox delivery to repository execution.
8029
8055
  */
8030
8056
  const RepositoryDispatch = {
8031
8057
  /**
@@ -8126,7 +8152,7 @@ const RepositoryDispatch = {
8126
8152
  : RepositoryDispatch.dispatchRepositoryStateUpdate(repository, routing, event, route);
8127
8153
  },
8128
8154
  /**
8129
- * Creates replay access for an Aggregate or Process Manager with signal handlers.
8155
+ * Creates deliver access for an Aggregate or Process Manager with signal handlers.
8130
8156
  *
8131
8157
  * @param repository Repository providing signal routes and Entity identity.
8132
8158
  * @param routing Registered handlers and message schemas.
@@ -8143,19 +8169,17 @@ const RepositoryDispatch = {
8143
8169
  targetTypeUrl: TypeUrls.derive(repository.stateSchema),
8144
8170
  labels: Object.freeze([
8145
8171
  ...(routing.commandSchemas.length === 0 ? [] : ["HANDLE_COMMAND"]),
8146
- ...((repository.entityFamily === "process-manager" ||
8147
- repository.entityFamily === "agent") &&
8148
- routing.eventSchemas.length > 0
8149
- ? ["REACT_UPON_EVENT"]
8150
- : []),
8172
+ ...(routing.eventSchemas.length > 0 ? ["REACT_UPON_EVENT"] : []),
8151
8173
  ]),
8152
- replay: (message, deliveryTenantId) => repository.entityFamily === "aggregate"
8153
- ? InboxReplay.replayAggregateCommand(repository, routing, message, deliveryTenantId)
8154
- : InboxReplay.replayPmInbox(repository, routing, message, deliveryTenantId),
8174
+ deliver: (message, deliveryTenantId) => repository.entityFamily === "aggregate"
8175
+ ? message.label === "REACT_UPON_EVENT"
8176
+ ? InboxDelivery.deliverAggregateEvent(repository, routing, message, deliveryTenantId)
8177
+ : InboxDelivery.deliverAggregateCommand(repository, routing, message, deliveryTenantId)
8178
+ : InboxDelivery.deliverPmInbox(repository, routing, message, deliveryTenantId),
8155
8179
  });
8156
8180
  },
8157
8181
  /**
8158
- * Creates replay access for a Projection with Event or state subscribers.
8182
+ * Creates deliver access for a Projection with Event or state subscribers.
8159
8183
  *
8160
8184
  * @param repository Repository providing Projection identity and Event routes.
8161
8185
  * @param routing Registered Event and state subscribers.
@@ -8168,7 +8192,7 @@ const RepositoryDispatch = {
8168
8192
  }
8169
8193
  return Object.freeze({
8170
8194
  targetTypeUrl: TypeUrls.derive(repository.stateSchema),
8171
- replay: (message, deliveryTenantId) => InboxReplay.replayProjectionMessage(repository, routing, message, deliveryTenantId),
8195
+ deliver: (message, deliveryTenantId) => InboxDelivery.deliverProjectionMessage(repository, routing, message, deliveryTenantId),
8172
8196
  });
8173
8197
  },
8174
8198
  /**
@@ -8206,7 +8230,7 @@ const RepositoryDispatch = {
8206
8230
  const route = acceptedRoute ?? (await repository.routeEvent(event));
8207
8231
  switch (repository.entityFamily) {
8208
8232
  case "aggregate":
8209
- await RepositoryDispatch.dispatchAggregateEvent(repository, routing, runtime, event, route);
8233
+ await RepositoryDispatch.dispatchAggregateEvent(repository, runtime, event, route);
8210
8234
  return;
8211
8235
  case "process-manager":
8212
8236
  case "agent":
@@ -8221,17 +8245,19 @@ const RepositoryDispatch = {
8221
8245
  * Dispatches an Event to each routed Aggregate with its configured duplicate guard.
8222
8246
  *
8223
8247
  * @param repository Aggregate repository receiving the Event.
8224
- * @param routing Registered Aggregate Event handlers and schemas.
8225
8248
  * @param runtime Bound storage, publisher, and tenant context.
8226
8249
  * @param event Event envelope to dispatch.
8227
8250
  * @param route Accepted route listing target Aggregate identifiers.
8228
8251
  * @returns Completion of all target dispatches in route order.
8229
8252
  */
8230
- async dispatchAggregateEvent(repository, routing, runtime, event, route) {
8231
- const execution = new AggregateEventExecution(repository, routing, runtime, event);
8232
- for (const entityId of route.entityIds) {
8233
- await DispatchGuards.guardedEntityEventDispatch(repository, runtime, event, entityId, () => execution.runTarget(entityId, route));
8253
+ async dispatchAggregateEvent(repository, runtime, event, route) {
8254
+ if (route.entityIds.length === 0)
8255
+ return;
8256
+ if (route.entityIds.length === 1) {
8257
+ await InboxHandoff.handoffEntityEvent(repository, runtime, event, route.entityIds[0]);
8258
+ return;
8234
8259
  }
8260
+ await InboxHandoff.handoffEntityEvents(repository, runtime, event, route.entityIds);
8235
8261
  },
8236
8262
  /**
8237
8263
  * Delivers a routed Entity-state update to each target Projection Inbox.