@spine-event-engine/server 2.0.0-snapshot.26 → 2.0.0-snapshot.29

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