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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (300) hide show
  1. package/README.md +38 -11
  2. package/REFERENCE.md +278 -141
  3. package/dist/agent/agent-acceptance-receipts.d.ts +69 -0
  4. package/dist/agent/agent-acceptance-receipts.d.ts.map +1 -0
  5. package/dist/agent/agent-acceptance-receipts.js +198 -0
  6. package/dist/agent/agent-acceptance-receipts.js.map +1 -0
  7. package/dist/agent/agent-execution-capacity.d.ts +37 -9
  8. package/dist/agent/agent-execution-capacity.d.ts.map +1 -1
  9. package/dist/agent/agent-execution-capacity.js +73 -15
  10. package/dist/agent/agent-execution-capacity.js.map +1 -1
  11. package/dist/agent/agent-history.d.ts +15 -10
  12. package/dist/agent/agent-history.d.ts.map +1 -1
  13. package/dist/agent/agent-history.js +26 -14
  14. package/dist/agent/agent-history.js.map +1 -1
  15. package/dist/agent/agent-live-ai-audit.d.ts +95 -0
  16. package/dist/agent/agent-live-ai-audit.d.ts.map +1 -0
  17. package/dist/agent/agent-live-ai-audit.js +290 -0
  18. package/dist/agent/agent-live-ai-audit.js.map +1 -0
  19. package/dist/agent/agent-live-ai-runtime.d.ts +300 -0
  20. package/dist/agent/agent-live-ai-runtime.d.ts.map +1 -0
  21. package/dist/agent/agent-live-ai-runtime.js +611 -0
  22. package/dist/agent/agent-live-ai-runtime.js.map +1 -0
  23. package/dist/agent/agent-live-audit.d.ts +67 -0
  24. package/dist/agent/agent-live-audit.d.ts.map +1 -0
  25. package/dist/agent/agent-live-audit.js +121 -0
  26. package/dist/agent/agent-live-audit.js.map +1 -0
  27. package/dist/agent/agent-live-budget.d.ts +84 -0
  28. package/dist/agent/agent-live-budget.d.ts.map +1 -0
  29. package/dist/agent/agent-live-budget.js +161 -0
  30. package/dist/agent/agent-live-budget.js.map +1 -0
  31. package/dist/agent/agent-live-fault.d.ts +18 -0
  32. package/dist/agent/agent-live-fault.d.ts.map +1 -0
  33. package/dist/agent/{agent-execution-fault.js → agent-live-fault.js} +7 -7
  34. package/dist/agent/agent-live-fault.js.map +1 -0
  35. package/dist/agent/agent-live-inputs.d.ts +74 -0
  36. package/dist/agent/agent-live-inputs.d.ts.map +1 -0
  37. package/dist/agent/agent-live-inputs.js +15 -0
  38. package/dist/agent/agent-live-inputs.js.map +1 -0
  39. package/dist/agent/agent-live-interaction-events.d.ts +46 -0
  40. package/dist/agent/agent-live-interaction-events.d.ts.map +1 -0
  41. package/dist/agent/agent-live-interaction-events.js +104 -0
  42. package/dist/agent/agent-live-interaction-events.js.map +1 -0
  43. package/dist/agent/agent-live-mcp-controls.d.ts +129 -0
  44. package/dist/agent/agent-live-mcp-controls.d.ts.map +1 -0
  45. package/dist/agent/agent-live-mcp-controls.js +228 -0
  46. package/dist/agent/agent-live-mcp-controls.js.map +1 -0
  47. package/dist/agent/agent-live-mcp-host.d.ts +88 -0
  48. package/dist/agent/agent-live-mcp-host.d.ts.map +1 -0
  49. package/dist/agent/{agent-mcp-host.js → agent-live-mcp-host.js} +1 -1
  50. package/dist/agent/agent-live-mcp-host.js.map +1 -0
  51. package/dist/agent/{agent-mcp-runtime.d.ts → agent-live-mcp-runtime.d.ts} +6 -6
  52. package/dist/agent/agent-live-mcp-runtime.d.ts.map +1 -0
  53. package/dist/agent/{agent-mcp-runtime.js → agent-live-mcp-runtime.js} +13 -42
  54. package/dist/agent/agent-live-mcp-runtime.js.map +1 -0
  55. package/dist/agent/agent-live-read-runtime.d.ts +61 -0
  56. package/dist/agent/agent-live-read-runtime.d.ts.map +1 -0
  57. package/dist/agent/agent-live-read-runtime.js +121 -0
  58. package/dist/agent/agent-live-read-runtime.js.map +1 -0
  59. package/dist/agent/agent-model-selection.d.ts +21 -34
  60. package/dist/agent/agent-model-selection.d.ts.map +1 -1
  61. package/dist/agent/agent-model-selection.js +61 -78
  62. package/dist/agent/agent-model-selection.js.map +1 -1
  63. package/dist/bus/command-bus.d.ts +14 -18
  64. package/dist/bus/command-bus.d.ts.map +1 -1
  65. package/dist/bus/command-bus.js +31 -48
  66. package/dist/bus/command-bus.js.map +1 -1
  67. package/dist/bus/event-bus.d.ts +82 -104
  68. package/dist/bus/event-bus.d.ts.map +1 -1
  69. package/dist/bus/event-bus.js +87 -127
  70. package/dist/bus/event-bus.js.map +1 -1
  71. package/dist/context/bounded-context.d.ts +143 -91
  72. package/dist/context/bounded-context.d.ts.map +1 -1
  73. package/dist/context/bounded-context.js +753 -359
  74. package/dist/context/bounded-context.js.map +1 -1
  75. package/dist/context/entity-inbox.d.ts +7 -2
  76. package/dist/context/entity-inbox.d.ts.map +1 -1
  77. package/dist/context/entity-inbox.js +43 -20
  78. package/dist/context/entity-inbox.js.map +1 -1
  79. package/dist/context/local-inbox-handoff.d.ts +35 -34
  80. package/dist/context/local-inbox-handoff.d.ts.map +1 -1
  81. package/dist/context/local-inbox-handoff.js +123 -135
  82. package/dist/context/local-inbox-handoff.js.map +1 -1
  83. package/dist/context/projection-handoff.d.ts +2 -2
  84. package/dist/context/projection-handoff.d.ts.map +1 -1
  85. package/dist/context/projection-handoff.js +12 -8
  86. package/dist/context/projection-handoff.js.map +1 -1
  87. package/dist/context/tenant-index.d.ts +36 -31
  88. package/dist/context/tenant-index.d.ts.map +1 -1
  89. package/dist/context/tenant-index.js +123 -125
  90. package/dist/context/tenant-index.js.map +1 -1
  91. package/dist/context/tenant-unknown-error.d.ts +33 -0
  92. package/dist/context/tenant-unknown-error.d.ts.map +1 -0
  93. package/dist/context/tenant-unknown-error.js +75 -0
  94. package/dist/context/tenant-unknown-error.js.map +1 -0
  95. package/dist/delivery/agent-delivery-scope.d.ts +66 -0
  96. package/dist/delivery/agent-delivery-scope.d.ts.map +1 -0
  97. package/dist/delivery/agent-delivery-scope.js +44 -0
  98. package/dist/delivery/agent-delivery-scope.js.map +1 -0
  99. package/dist/delivery/delivery-builder.d.ts +25 -1
  100. package/dist/delivery/delivery-builder.d.ts.map +1 -1
  101. package/dist/delivery/delivery-builder.js +89 -0
  102. package/dist/delivery/delivery-builder.js.map +1 -1
  103. package/dist/delivery/delivery-monitor.d.ts +12 -9
  104. package/dist/delivery/delivery-monitor.d.ts.map +1 -1
  105. package/dist/delivery/delivery-monitor.js +15 -9
  106. package/dist/delivery/delivery-monitor.js.map +1 -1
  107. package/dist/delivery/delivery-ports.d.ts +6 -13
  108. package/dist/delivery/delivery-ports.d.ts.map +1 -1
  109. package/dist/delivery/delivery-run-control.d.ts +21 -0
  110. package/dist/delivery/delivery-run-control.d.ts.map +1 -1
  111. package/dist/delivery/delivery-run-control.js +10 -0
  112. package/dist/delivery/delivery-run-control.js.map +1 -1
  113. package/dist/delivery/delivery-supervisor.d.ts +33 -5
  114. package/dist/delivery/delivery-supervisor.d.ts.map +1 -1
  115. package/dist/delivery/delivery-supervisor.js +178 -26
  116. package/dist/delivery/delivery-supervisor.js.map +1 -1
  117. package/dist/delivery/delivery-tenant.d.ts +17 -0
  118. package/dist/delivery/delivery-tenant.d.ts.map +1 -0
  119. package/dist/delivery/delivery-tenant.js +50 -0
  120. package/dist/delivery/delivery-tenant.js.map +1 -0
  121. package/dist/delivery/delivery.d.ts +96 -2
  122. package/dist/delivery/delivery.d.ts.map +1 -1
  123. package/dist/delivery/delivery.js +803 -89
  124. package/dist/delivery/delivery.js.map +1 -1
  125. package/dist/delivery/inbox-records.d.ts.map +1 -1
  126. package/dist/delivery/inbox-records.js +9 -16
  127. package/dist/delivery/inbox-records.js.map +1 -1
  128. package/dist/delivery/inbox-storage.d.ts +14 -11
  129. package/dist/delivery/inbox-storage.d.ts.map +1 -1
  130. package/dist/delivery/inbox-storage.js +72 -78
  131. package/dist/delivery/inbox-storage.js.map +1 -1
  132. package/dist/delivery/inbox.d.ts +9 -12
  133. package/dist/delivery/inbox.d.ts.map +1 -1
  134. package/dist/delivery/inbox.js +13 -15
  135. package/dist/delivery/inbox.js.map +1 -1
  136. package/dist/delivery/reception-observation.d.ts +64 -0
  137. package/dist/delivery/reception-observation.d.ts.map +1 -0
  138. package/dist/delivery/reception-observation.js +78 -0
  139. package/dist/delivery/reception-observation.js.map +1 -0
  140. package/dist/delivery/sharded-work-registry.d.ts +6 -0
  141. package/dist/delivery/sharded-work-registry.d.ts.map +1 -1
  142. package/dist/delivery/sharded-work-registry.js +41 -4
  143. package/dist/delivery/sharded-work-registry.js.map +1 -1
  144. package/dist/entity/entity-storage-descriptor.d.ts.map +1 -1
  145. package/dist/entity/entity-storage-descriptor.js +7 -4
  146. package/dist/entity/entity-storage-descriptor.js.map +1 -1
  147. package/dist/index.d.ts +4 -2
  148. package/dist/index.d.ts.map +1 -1
  149. package/dist/index.js +2 -1
  150. package/dist/index.js.map +1 -1
  151. package/dist/integration/external-messages.d.ts.map +1 -1
  152. package/dist/integration/external-messages.js +9 -15
  153. package/dist/integration/external-messages.js.map +1 -1
  154. package/dist/integration/integration-broker.d.ts.map +1 -1
  155. package/dist/integration/integration-broker.js +112 -6
  156. package/dist/integration/integration-broker.js.map +1 -1
  157. package/dist/integration/third-party-context.d.ts.map +1 -1
  158. package/dist/integration/third-party-context.js +7 -10
  159. package/dist/integration/third-party-context.js.map +1 -1
  160. package/dist/repository/primitive-id.js +26 -11
  161. package/dist/repository/primitive-id.js.map +1 -1
  162. package/dist/repository/repository.d.ts +33 -62
  163. package/dist/repository/repository.d.ts.map +1 -1
  164. package/dist/repository/repository.js +1475 -1827
  165. package/dist/repository/repository.js.map +1 -1
  166. package/dist/runtime/runtime.d.ts +24 -0
  167. package/dist/runtime/runtime.d.ts.map +1 -1
  168. package/dist/runtime/runtime.js +31 -0
  169. package/dist/runtime/runtime.js.map +1 -1
  170. package/dist/runtime/signal-metadata.d.ts.map +1 -1
  171. package/dist/runtime/signal-metadata.js +8 -15
  172. package/dist/runtime/signal-metadata.js.map +1 -1
  173. package/dist/runtime/signal-publisher.d.ts +8 -36
  174. package/dist/runtime/signal-publisher.d.ts.map +1 -1
  175. package/dist/runtime/signal-publisher.js +68 -61
  176. package/dist/runtime/signal-publisher.js.map +1 -1
  177. package/dist/runtime/standalone-handler-runtime.d.ts +0 -7
  178. package/dist/runtime/standalone-handler-runtime.d.ts.map +1 -1
  179. package/dist/runtime/standalone-handler-runtime.js +14 -130
  180. package/dist/runtime/standalone-handler-runtime.js.map +1 -1
  181. package/dist/server/managed-delivery-gate.d.ts +34 -0
  182. package/dist/server/managed-delivery-gate.d.ts.map +1 -0
  183. package/dist/server/managed-delivery-gate.js +70 -0
  184. package/dist/server/managed-delivery-gate.js.map +1 -0
  185. package/dist/server/managed-server-application.d.ts +2 -2
  186. package/dist/server/managed-server-application.d.ts.map +1 -1
  187. package/dist/server/managed-server-application.js +471 -178
  188. package/dist/server/managed-server-application.js.map +1 -1
  189. package/dist/server/node-coordinator.d.ts +14 -0
  190. package/dist/server/node-coordinator.d.ts.map +1 -1
  191. package/dist/server/node-coordinator.js +266 -45
  192. package/dist/server/node-coordinator.js.map +1 -1
  193. package/dist/server/server-environment.d.ts +203 -25
  194. package/dist/server/server-environment.d.ts.map +1 -1
  195. package/dist/server/server-environment.js +661 -133
  196. package/dist/server/server-environment.js.map +1 -1
  197. package/dist/server/server-log.d.ts +7 -0
  198. package/dist/server/server-log.d.ts.map +1 -1
  199. package/dist/server/server-log.js +18 -1
  200. package/dist/server/server-log.js.map +1 -1
  201. package/dist/server/server.d.ts +18 -32
  202. package/dist/server/server.d.ts.map +1 -1
  203. package/dist/server/server.js +62 -203
  204. package/dist/server/server.js.map +1 -1
  205. package/dist/services/spine-services.d.ts +1 -1
  206. package/dist/services/spine-services.d.ts.map +1 -1
  207. package/dist/services/spine-services.js +399 -370
  208. package/dist/services/spine-services.js.map +1 -1
  209. package/dist/stand/event-origin-filter.d.ts +16 -0
  210. package/dist/stand/event-origin-filter.d.ts.map +1 -0
  211. package/dist/stand/event-origin-filter.js +124 -0
  212. package/dist/stand/event-origin-filter.js.map +1 -0
  213. package/dist/stand/stand.d.ts +14 -0
  214. package/dist/stand/stand.d.ts.map +1 -1
  215. package/dist/stand/stand.js +53 -9
  216. package/dist/stand/stand.js.map +1 -1
  217. package/dist/stand/subscription-observer.d.ts.map +1 -1
  218. package/dist/stand/subscription-observer.js +61 -40
  219. package/dist/stand/subscription-observer.js.map +1 -1
  220. package/dist/stand/subscription-registry.d.ts +6 -2
  221. package/dist/stand/subscription-registry.d.ts.map +1 -1
  222. package/dist/stand/subscription-registry.js +15 -11
  223. package/dist/stand/subscription-registry.js.map +1 -1
  224. package/dist/stand/subscription-runtime.d.ts +23 -4
  225. package/dist/stand/subscription-runtime.d.ts.map +1 -1
  226. package/dist/stand/subscription-runtime.js +84 -13
  227. package/dist/stand/subscription-runtime.js.map +1 -1
  228. package/dist/testing/index.d.ts.map +1 -1
  229. package/dist/testing/index.js +3 -2
  230. package/dist/testing/index.js.map +1 -1
  231. package/dist/tsconfig.tsbuildinfo +1 -1
  232. package/package.json +15 -15
  233. package/dist/agent/agent-admission.d.ts +0 -80
  234. package/dist/agent/agent-admission.d.ts.map +0 -1
  235. package/dist/agent/agent-admission.js +0 -127
  236. package/dist/agent/agent-admission.js.map +0 -1
  237. package/dist/agent/agent-ai-runtime.d.ts +0 -76
  238. package/dist/agent/agent-ai-runtime.d.ts.map +0 -1
  239. package/dist/agent/agent-ai-runtime.js +0 -1269
  240. package/dist/agent/agent-ai-runtime.js.map +0 -1
  241. package/dist/agent/agent-execution-fault.d.ts +0 -18
  242. package/dist/agent/agent-execution-fault.d.ts.map +0 -1
  243. package/dist/agent/agent-execution-fault.js.map +0 -1
  244. package/dist/agent/agent-execution-session.d.ts +0 -103
  245. package/dist/agent/agent-execution-session.d.ts.map +0 -1
  246. package/dist/agent/agent-execution-session.js +0 -238
  247. package/dist/agent/agent-execution-session.js.map +0 -1
  248. package/dist/agent/agent-interaction-audit.d.ts +0 -58
  249. package/dist/agent/agent-interaction-audit.d.ts.map +0 -1
  250. package/dist/agent/agent-interaction-audit.js +0 -114
  251. package/dist/agent/agent-interaction-audit.js.map +0 -1
  252. package/dist/agent/agent-interaction-events.d.ts +0 -40
  253. package/dist/agent/agent-interaction-events.d.ts.map +0 -1
  254. package/dist/agent/agent-interaction-events.js +0 -129
  255. package/dist/agent/agent-interaction-events.js.map +0 -1
  256. package/dist/agent/agent-mcp-budget.d.ts +0 -125
  257. package/dist/agent/agent-mcp-budget.d.ts.map +0 -1
  258. package/dist/agent/agent-mcp-budget.js +0 -566
  259. package/dist/agent/agent-mcp-budget.js.map +0 -1
  260. package/dist/agent/agent-mcp-host.d.ts +0 -125
  261. package/dist/agent/agent-mcp-host.d.ts.map +0 -1
  262. package/dist/agent/agent-mcp-host.js.map +0 -1
  263. package/dist/agent/agent-mcp-runtime.d.ts.map +0 -1
  264. package/dist/agent/agent-mcp-runtime.js.map +0 -1
  265. package/dist/agent/agent-read-runtime.d.ts +0 -70
  266. package/dist/agent/agent-read-runtime.d.ts.map +0 -1
  267. package/dist/agent/agent-read-runtime.js +0 -320
  268. package/dist/agent/agent-read-runtime.js.map +0 -1
  269. package/dist/agent/agent-revisions.d.ts +0 -35
  270. package/dist/agent/agent-revisions.d.ts.map +0 -1
  271. package/dist/agent/agent-revisions.js +0 -133
  272. package/dist/agent/agent-revisions.js.map +0 -1
  273. package/dist/agent/agent-scheduler.d.ts +0 -99
  274. package/dist/agent/agent-scheduler.d.ts.map +0 -1
  275. package/dist/agent/agent-scheduler.js +0 -398
  276. package/dist/agent/agent-scheduler.js.map +0 -1
  277. package/dist/bus/saved-dispatcher-binding.d.ts +0 -96
  278. package/dist/bus/saved-dispatcher-binding.d.ts.map +0 -1
  279. package/dist/bus/saved-dispatcher-binding.js +0 -35
  280. package/dist/bus/saved-dispatcher-binding.js.map +0 -1
  281. package/dist/delivery/delivery-run-coordinator.d.ts +0 -218
  282. package/dist/delivery/delivery-run-coordinator.d.ts.map +0 -1
  283. package/dist/delivery/delivery-run-coordinator.js +0 -609
  284. package/dist/delivery/delivery-run-coordinator.js.map +0 -1
  285. package/dist/delivery/parked-delivery-obligations.d.ts +0 -182
  286. package/dist/delivery/parked-delivery-obligations.d.ts.map +0 -1
  287. package/dist/delivery/parked-delivery-obligations.js +0 -390
  288. package/dist/delivery/parked-delivery-obligations.js.map +0 -1
  289. package/dist/server/environment-attachment.d.ts +0 -356
  290. package/dist/server/environment-attachment.d.ts.map +0 -1
  291. package/dist/server/environment-attachment.js +0 -2062
  292. package/dist/server/environment-attachment.js.map +0 -1
  293. package/dist/server/environment-delivery-records.d.ts +0 -77
  294. package/dist/server/environment-delivery-records.d.ts.map +0 -1
  295. package/dist/server/environment-delivery-records.js +0 -282
  296. package/dist/server/environment-delivery-records.js.map +0 -1
  297. package/dist/server/environment-delivery-worker.d.ts +0 -161
  298. package/dist/server/environment-delivery-worker.d.ts.map +0 -1
  299. package/dist/server/environment-delivery-worker.js +0 -673
  300. package/dist/server/environment-delivery-worker.js.map +0 -1
@@ -20,31 +20,28 @@ import { freezeRegistry, isAiModel, registryOptions } from "@spine-event-engine/
20
20
  import { TypeUrls } from "@spine-event-engine/core";
21
21
  import { EventSchema, EventContextSchema, BoundedContextNameSchema, TenantIdSchema, } from "@spine-event-engine/proto";
22
22
  import { SPI_type, internal_all, internal_type } from "@spine-event-engine/proto";
23
- import { ColumnTypes, EventStore, InMemoryStorageFactory, RecordColumn, } from "@spine-event-engine/storage";
24
- import { AgentExecutionStorageFactories, AgentHistoryStorageFactories, TenantBoundary, } from "@spine-event-engine/storage/provider";
23
+ import { ColumnTypes, EventStore, RecordColumn, } from "@spine-event-engine/storage";
24
+ import { AgentHistoryStorageFactories, EventStoreGroups, eventStoreRecordSpec, StoragePreparations, TenantBoundary, } from "@spine-event-engine/storage/provider";
25
25
  import { CommandBus, commandBusAccess } from "../bus/command-bus.js";
26
26
  import { EventBus, eventBusAccess, isSystemEventSchema, } from "../bus/event-bus.js";
27
- import { DeliveryReadiness, } from "./local-inbox-handoff.js";
27
+ import { DeliveryReadiness } from "./local-inbox-handoff.js";
28
28
  import { LocalEntityInbox } from "./entity-inbox.js";
29
29
  import { LocalProjectionInbox } from "./projection-handoff.js";
30
- import { TenantIndexes } from "./tenant-index.js";
31
- import { EffectiveTenants } from "./effective-tenant.js";
32
- import { AgentScheduler } from "../agent/agent-scheduler.js";
33
- import { AgentExecutionCapacity } from "../agent/agent-execution-capacity.js";
30
+ import { TenantAdmissions } from "./tenant-unknown-error.js";
31
+ import { AgentExecutionCapacity, } from "../agent/agent-execution-capacity.js";
32
+ import { AgentAcceptanceReceipts, agentAcceptanceReceiptGroup, agentAcceptanceReceiptSpec, } from "../agent/agent-acceptance-receipts.js";
34
33
  import { Repository, repositoryAccess, } from "../repository/repository.js";
35
34
  import { GeneratedRegistryDiscovery } from "../handler/generated-registry-discovery.js";
36
35
  import { HandlerRegistryIngestor, } from "../handler/generated-handler-registry.js";
37
36
  import { AbstractAssignee, AbstractCommander, AbstractEventReactor, AbstractEventSubscriber, } from "../handler/standalone.js";
38
37
  import { HandlerMetadataRegistry, } from "../handler/handler-metadata.js";
39
38
  import { SignalMetadata } from "../runtime/signal-metadata.js";
40
- import { Stand } from "../stand/stand.js";
39
+ import { runtimeAccess } from "../runtime/runtime.js";
40
+ import { Stand, standAccess } from "../stand/stand.js";
41
41
  import { SubscriptionRuntime, subscriptionRuntimeAccess } from "../stand/subscription-runtime.js";
42
- import { StorageSubscriptionRegistry, } from "../stand/subscription-registry.js";
43
- import { UniformAcrossAllShards } from "../delivery/delivery-builder.js";
44
- import { InboxTargets } from "../delivery/inbox.js";
45
- import { ShardIndex } from "../delivery/shard-index.js";
42
+ import { StorageSubscriptionRegistry, subscriptionRecordSpec, } from "../stand/subscription-registry.js";
46
43
  import { IntegrationBroker } from "../integration/integration-broker.js";
47
- import { ServerEnvironment } from "../server/server-environment.js";
44
+ import { ServerEnvironment, serverEnvironmentAccess } from "../server/server-environment.js";
48
45
  import { SignalPublisher } from "../runtime/signal-publisher.js";
49
46
  import { StandaloneHandlerRuntime, } from "../runtime/standalone-handler-runtime.js";
50
47
  /**
@@ -68,6 +65,38 @@ export class BoundedContextNameError extends Error {
68
65
  Object.setPrototypeOf(this, new.target.prototype);
69
66
  }
70
67
  }
68
+ /**
69
+ * Rejects an Entity state type already served by another open domain context.
70
+ */
71
+ export class DuplicateEntityStateException extends Error {
72
+ // prettier-ignore
73
+ /**
74
+ * Wire type URL of the conflicting Entity state.
75
+ */
76
+ stateType;
77
+ /**
78
+ * Name of the context that already serves the state.
79
+ */
80
+ registeredContext;
81
+ /**
82
+ * Name of the context attempting registration.
83
+ */
84
+ conflictingContext;
85
+ /**
86
+ * Creates a duplicate-state registration error.
87
+ * @param stateType Entity state wire type URL.
88
+ * @param registeredContext Existing domain context name.
89
+ * @param conflictingContext New domain context name.
90
+ */
91
+ constructor(stateType, registeredContext, conflictingContext) {
92
+ super(`Entity state "${stateType}" is already registered in "${registeredContext}"; ` +
93
+ `register it in only one open domain Bounded Context (attempted in "${conflictingContext}").`);
94
+ this.name = "DuplicateEntityStateException";
95
+ this.stateType = stateType;
96
+ this.registeredContext = registeredContext;
97
+ this.conflictingContext = conflictingContext;
98
+ }
99
+ }
71
100
  const frameworkConstructionToken = Object.freeze({
72
101
  frameworkConstructionToken: true,
73
102
  });
@@ -82,6 +111,8 @@ const contextTenantIndexes = new WeakMap();
82
111
  const contextStorageFactories = new WeakMap();
83
112
  const contextDeliveryDescriptors = new WeakMap();
84
113
  const contextSubscriptionRuntimes = new WeakMap();
114
+ const contextPreparations = new WeakMap();
115
+ const contextInputPreparations = new WeakMap();
85
116
  const contextLoggers = new WeakMap();
86
117
  const contextSignalPublishers = new WeakMap();
87
118
  const contextEventBuses = new WeakMap();
@@ -92,7 +123,9 @@ const contextClosePhases = new WeakMap();
92
123
  const contextIntegrations = new WeakMap();
93
124
  const systemEventPosters = new WeakMap();
94
125
  const builderBuilds = new WeakMap();
126
+ const explicitPreparations = new WeakMap();
95
127
  let constructBoundedContext;
128
+ let registerBoundedContext;
96
129
  let constructBoundedContextBuilder;
97
130
  let constructContextSpec;
98
131
  /**
@@ -108,22 +141,37 @@ export class BoundedContext {
108
141
  #eventEndpoint;
109
142
  #entityInbox;
110
143
  #projectionInbox;
111
- #deliveryStrategy;
144
+ #deliveryReadiness;
145
+ #stopAgentAvailability;
112
146
  #registeredRepositories = [];
113
147
  #repositoryViews = new Set();
114
148
  #storageFactory;
149
+ #environment;
115
150
  #ai;
116
151
  #stand;
117
152
  #systemStand;
118
153
  #subscriptionRuntime;
119
- #agentScheduler;
120
- #agentErrors = [];
154
+ /**
155
+ * Explicit storage and subscription preparation for this built context.
156
+ */
157
+ runtime;
158
+ #agentReceipts;
159
+ #agentController = new AbortController();
160
+ #agentReservations = new Set();
161
+ #activeReplays = new Set();
162
+ #activePreparations = new Set();
163
+ #tenantPreparations = new Map();
164
+ #preparationController = new AbortController();
165
+ #sharedPreparation;
121
166
  #closed;
122
167
  /**
123
168
  * Registers the framework-only construction hook for this module.
124
169
  */
125
170
  static {
126
171
  constructBoundedContext = (input) => new BoundedContext(input);
172
+ registerBoundedContext = (context, repositories) => {
173
+ context.#registerRepositories(repositories);
174
+ };
127
175
  }
128
176
  /**
129
177
  * Creates a Bounded Context from its prepared framework services.
@@ -140,9 +188,12 @@ export class BoundedContext {
140
188
  this.#stand = input.stand;
141
189
  this.#systemStand = input.systemStand;
142
190
  this.#subscriptionRuntime = input.subscriptionRuntime;
191
+ this.runtime = this.#createRuntime();
143
192
  this.#storageFactory = input.storageFactory;
193
+ this.#agentReceipts = new AgentAcceptanceReceipts(input.storageFactory);
194
+ this.#environment = ServerEnvironment.instance();
144
195
  this.#ai = input.ai;
145
- this.#deliveryStrategy = ContextParts.snapshotDeliveryStrategy(input.deliveryStrategy);
196
+ this.#installTenantAdmission();
146
197
  this.#commandEndpoint = Object.freeze({
147
198
  acceptedCommandTypes: () => this.#commandBus.acceptedCommandTypes(),
148
199
  post: (command) => this.#commandBus.post(command),
@@ -151,79 +202,304 @@ export class BoundedContext {
151
202
  acceptedEventTypes: () => ContextParts.exposedEventTypeUrls(this.#eventBus),
152
203
  post: (event) => ContextParts.postContextEvent(this, event),
153
204
  });
154
- const delivery = this.#createDelivery(input.storageFactory);
205
+ const delivery = this.#createDelivery(input.tenantIndex);
206
+ this.#deliveryReadiness = delivery.deliveryReadiness;
155
207
  this.#entityInbox = delivery.entityInbox;
156
208
  this.#projectionInbox = delivery.projectionInbox;
157
209
  this.#installReferences(input, delivery);
158
- this.#registerAndStart(input.repositories, delivery.tenantIndex);
159
- this.#startAgentScheduler(delivery.tenantIndex);
210
+ serverEnvironmentAccess.addContext(this.#environment, this);
160
211
  Object.freeze(this);
161
212
  }
162
213
  /**
163
- * Starts bounded indexed discovery for registered Agent repositories.
214
+ * Exposes explicit preparation for this built context.
215
+ *
216
+ * @returns Stable explicit preparation methods.
164
217
  */
165
- #startAgentScheduler(tenantIndex) {
166
- if (this.#ai === undefined)
167
- return;
168
- const repositories = [...this.#repositoryViews].filter((entry) => entry.entityFamily === "agent");
169
- if (repositories.length === 0)
170
- return;
171
- this.#agentScheduler = new AgentScheduler({
172
- repositories: repositories.length,
173
- page: (after, signal) => tenantIndex.page({
174
- count: 16,
175
- signal,
176
- ...(after === undefined ? {} : { after }),
177
- }),
178
- scope: (id, index) => {
179
- const repository = repositories[index];
180
- if (repository === undefined)
181
- throw new Error("Agent repository scope is unavailable.");
182
- return this.#agentScope(repository, tenantIndex.tenantMode === "single-tenant" ? undefined : id);
183
- },
184
- }, AgentExecutionCapacity.for(this.#ai), (error) => {
185
- if (this.#agentErrors.length < 32)
186
- this.#agentErrors.push(error);
218
+ #createRuntime() {
219
+ return Object.freeze({
220
+ createStorageStructures: (...ids) => this.#explicitStructures("create", ids),
221
+ checkStructureCompatibility: (...ids) => this.#explicitStructures("check", ids),
222
+ startSubscriptionMonitoring: () => this.#explicitMonitoring(),
187
223
  });
188
- this.#agentScheduler.start();
189
224
  }
190
225
  /**
191
- * Builds one scan scope from an accepted handoff or a catalog sweep.
226
+ * Installs live membership checks on context signal buses.
192
227
  *
193
- * @param repository Registered Agent repository.
194
- * @param tenantId Accepted tenant, absent only in a single-tenant Bounded Context.
195
- * @returns The matching indexed provider scan scope.
196
228
  */
197
- #agentScope(repository, tenantId) {
198
- const effective = EffectiveTenants.current(this.#snapshot.tenantMode === "multitenant", tenantId);
229
+ #installTenantAdmission() {
230
+ explicitPreparations.set(this, (mode, ids) => this.#prepareExplicitLocal(mode, ids));
231
+ commandBusAccess.bindEnvironment(this.#commandBus, this.#environment);
232
+ eventBusAccess.bindEnvironment(this.#eventBus, this.#environment);
233
+ eventBusAccess.bindEnvironment(this.#systemEventBus, this.#environment);
234
+ commandBusAccess.setAdmission(this.#commandBus, (command) => this.#admitTenant(command.context?.actorContext?.tenantId));
235
+ eventBusAccess.setAdmission(this.#eventBus, (event) => this.#admitTenant(ContextParts.readReplayTenant(event)));
236
+ standAccess.setAdmission(this.#stand, (tenantId) => this.#admitTenant(tenantId));
237
+ standAccess.setPublicAdmission(this.#stand, () => {
238
+ if (closingContexts.has(this) && !runtimeAccess.isRunningAdmittedWork(this.#environment))
239
+ throw new Error("Bounded Context is closing.");
240
+ });
241
+ }
242
+ /**
243
+ * Checks this context's live index before repository work.
244
+ *
245
+ * @param tenantId Captured tenant identity, when applicable.
246
+ */
247
+ async #admitTenant(tenantId) {
248
+ await TenantAdmissions.require(this.tenantIndex, this.#snapshot.name.value, this.isMultitenant, tenantId);
249
+ await this.#prepareInput(tenantId);
250
+ }
251
+ /**
252
+ * Initializes only the admitted input's complete context and tenant requirements.
253
+ * @param tenantId Captured input tenant identity, when applicable.
254
+ * @returns Completion after storage and first monitoring pass are ready.
255
+ */
256
+ async #prepareInput(tenantId) {
257
+ await this.#prepareShared("create");
258
+ await this.#prepareTenant(tenantId, "create");
259
+ if (!closingContexts.has(this))
260
+ await this.#subscriptionRuntime.start();
261
+ }
262
+ /**
263
+ * Prepares the fixed shared subscription registry layout once per context.
264
+ * @param mode Required provider preparation mode.
265
+ * @returns Shared preparation completion.
266
+ */
267
+ #prepareShared(mode) {
268
+ if (!(this.#subscriptionRuntime.registry() instanceof StorageSubscriptionRegistry))
269
+ return Promise.resolve();
270
+ if (this.#sharedPreparation !== undefined)
271
+ return this.#sharedPreparation;
272
+ const attempt = this.#trackPreparation(() => StoragePreparations.for(this.#storageFactory).prepareRecord(ContextParts.createSubscriptionStorageContext(this.#snapshot.spec), subscriptionRecordSpec, undefined, mode));
273
+ this.#sharedPreparation = attempt;
274
+ void attempt.catch(() => {
275
+ if (this.#sharedPreparation === attempt)
276
+ this.#sharedPreparation = undefined;
277
+ });
278
+ return attempt;
279
+ }
280
+ /**
281
+ * Shares one pending complete-tenant preparation without caching a stale model flag.
282
+ * @param tenantId Captured tenant identity, when applicable.
283
+ * @param mode Required provider preparation mode.
284
+ * @returns Complete tenant preparation attempt.
285
+ */
286
+ #prepareTenant(tenantId, mode) {
287
+ const context = this.#storageContextFor(tenantId);
288
+ const key = TenantBoundary.of(context).key;
289
+ const pending = this.#tenantPreparations.get(key);
290
+ if (pending !== undefined)
291
+ return pending;
292
+ const attempt = this.#trackPreparation(() => this.#prepareTenantNow(context, mode));
293
+ this.#tenantPreparations.set(key, attempt);
294
+ void attempt.then(() => this.#tenantPreparations.delete(key), () => this.#tenantPreparations.delete(key));
295
+ return attempt;
296
+ }
297
+ /**
298
+ * Prepares exact Event, Entity and Agent families for one captured destination.
299
+ * @param context Captured physical storage destination.
300
+ * @param mode Required provider preparation mode.
301
+ * @returns Completion after all declared families are ready.
302
+ */
303
+ async #prepareTenantNow(context, mode) {
304
+ const preparation = StoragePreparations.for(this.#storageFactory);
305
+ await preparation.prepareRecord(context, eventStoreRecordSpec, EventStoreGroups.forContext(context.name), mode);
306
+ const system = ContextParts.requireSystemPairing(this).system;
307
+ if (system.storesEvents) {
308
+ const systemContext = { ...context, name: system.name.value };
309
+ await preparation.prepareRecord(systemContext, eventStoreRecordSpec, EventStoreGroups.forContext(system.name.value, "system"), mode);
310
+ }
311
+ for (const repository of this.#repositoryViews)
312
+ await repositoryAccess.prepareStorage(repository, context, this.#storageFactory, mode);
313
+ if ([...this.#repositoryViews].some((repository) => repository.entityFamily === "agent"))
314
+ await preparation.prepareRecord(context, agentAcceptanceReceiptSpec, agentAcceptanceReceiptGroup, mode);
315
+ }
316
+ /**
317
+ * Captures the same tenant scope used by repository and Event storage.
318
+ * @param tenantId Complete selected tenant identity, when applicable.
319
+ * @returns A detached provider storage context.
320
+ */
321
+ #storageContextFor(tenantId) {
322
+ if (!this.isMultitenant)
323
+ return { name: this.name.value, multitenant: false };
324
+ if (tenantId === undefined)
325
+ throw new Error("Multitenant preparation requires tenantId.");
199
326
  return {
200
- id: JSON.stringify([
201
- this.#snapshot.name.value,
202
- String(TenantBoundary.from(effective).key),
203
- repository.stateFullTypeName,
204
- ]),
205
- pending: (after, count) => repositoryAccess.pendingAcceptedAgents(repository, tenantId, after, count),
206
- run: (key, signal) => repositoryAccess.runAcceptedAgent(repository, tenantId, key, signal),
327
+ name: this.name.value,
328
+ multitenant: true,
329
+ tenantId: TenantBoundary.from(tenantId).tenantId,
207
330
  };
208
331
  }
332
+ /**
333
+ * Retains an admitted preparation until closure can safely release its provider.
334
+ * @param onPrepare Complete provider preparation callback.
335
+ * @returns Tracked preparation completion.
336
+ */
337
+ #trackPreparation(onPrepare) {
338
+ const attempt = Promise.resolve().then(onPrepare);
339
+ this.#activePreparations.add(attempt);
340
+ void attempt.then(() => this.#activePreparations.delete(attempt), () => this.#activePreparations.delete(attempt));
341
+ return attempt;
342
+ }
343
+ /**
344
+ * Completes independently requested eager structure and monitor phases.
345
+ * @param options Independent build-time initialization choices.
346
+ * @returns Completion after requested phases settle.
347
+ */
348
+ async #prepareBuild(options) {
349
+ if (options.createStorageStructures !== false) {
350
+ await this.#requiredPrepare(() => this.#prepareShared("create"));
351
+ await this.#prepareCurrentTenants("create");
352
+ }
353
+ if (options.startSubscriptionMonitoring !== false) {
354
+ await this.#requiredPrepare(() => this.#prepareShared("create"));
355
+ await this.#requiredPrepare(() => this.#subscriptionRuntime.start());
356
+ }
357
+ }
358
+ /**
359
+ * Classifies a requested startup phase without changing shared lazy attempts.
360
+ * @param onPrepare Required provider or initial-monitor phase.
361
+ * @returns Completion of the requested phase.
362
+ */
363
+ async #requiredPrepare(onPrepare) {
364
+ serverEnvironmentAccess.requireAvailable(this.#environment);
365
+ try {
366
+ await onPrepare();
367
+ }
368
+ catch (error) {
369
+ serverEnvironmentAccess.failStartup(this.#environment, error);
370
+ throw error;
371
+ }
372
+ serverEnvironmentAccess.requireAvailable(this.#environment);
373
+ }
374
+ /**
375
+ * Traverses the current live index in finite pages without a tenant cap.
376
+ * @param mode Creation or read-only check.
377
+ * @returns Completion after currently listed tenants are prepared.
378
+ */
379
+ async #prepareCurrentTenants(mode) {
380
+ if (!this.isMultitenant)
381
+ return this.#requiredPrepare(() => this.#prepareTenant(undefined, mode));
382
+ let after;
383
+ do {
384
+ serverEnvironmentAccess.requireAvailable(this.#environment);
385
+ const page = await this.tenantIndex.page({
386
+ count: 64,
387
+ signal: this.#preparationController.signal,
388
+ ...(after === undefined ? {} : { after }),
389
+ });
390
+ serverEnvironmentAccess.requireAvailable(this.#environment);
391
+ for (const id of page.ids) {
392
+ serverEnvironmentAccess.requireAvailable(this.#environment);
393
+ await TenantAdmissions.require(this.tenantIndex, this.name.value, true, id);
394
+ serverEnvironmentAccess.requireAvailable(this.#environment);
395
+ await this.#requiredPrepare(() => this.#prepareTenant(id, mode));
396
+ }
397
+ after = page.hasMore ? page.after : undefined;
398
+ } while (after !== undefined);
399
+ }
400
+ /**
401
+ * Admits explicit structure work and joins fatal cleanup after local settlement.
402
+ * @param mode Creation or read-only compatibility mode.
403
+ * @param tenantIds Explicit complete tenant identities, if supplied.
404
+ * @returns Completion after the selected structures are ready.
405
+ */
406
+ async #explicitStructures(mode, tenantIds) {
407
+ const captured = tenantIds.map((id) => TenantBoundary.from(id).tenantId);
408
+ const admitted = boundedContextAccess.admitServiceRegistryOperation(this, () => this.#prepareExplicitLocal(mode, captured));
409
+ return this.#joinRequiredCleanup(admitted);
410
+ }
411
+ /**
412
+ * Runs explicit preparation while the caller holds this context's admission.
413
+ *
414
+ * @param mode Creation or read-only check.
415
+ * @param ids Captured tenant identities, when supplied.
416
+ * @returns Completion of the local preparation.
417
+ */
418
+ async #prepareExplicitLocal(mode, ids) {
419
+ const selected = await this.#selectedTenants(ids);
420
+ await this.#requiredPrepare(() => this.#prepareShared(mode));
421
+ if (selected === undefined)
422
+ return this.#prepareCurrentTenants(mode);
423
+ for (const id of selected) {
424
+ await TenantAdmissions.require(this.tenantIndex, this.name.value, this.isMultitenant, id);
425
+ await this.#requiredPrepare(() => this.#prepareTenant(id, mode));
426
+ }
427
+ }
428
+ /**
429
+ * Validates all explicit IDs before any provider preparation.
430
+ *
431
+ * @param ids Captured explicit tenant identities.
432
+ * @returns Distinct current IDs or undefined for all current tenants.
433
+ */
434
+ async #selectedTenants(ids) {
435
+ if (ids.length === 0)
436
+ return undefined;
437
+ const selected = new Map();
438
+ for (const id of ids) {
439
+ await TenantAdmissions.require(this.tenantIndex, this.name.value, this.isMultitenant, id);
440
+ const boundary = TenantBoundary.from(id);
441
+ selected.set(boundary.key, boundary.tenantId);
442
+ }
443
+ return [...selected.values()];
444
+ }
445
+ /**
446
+ * Starts the one initial monitor pass as an explicit required phase.
447
+ *
448
+ * @returns Completion after the initial pass.
449
+ */
450
+ #explicitMonitoring() {
451
+ const admitted = boundedContextAccess.admitServiceRegistryOperation(this, async () => {
452
+ await this.#requiredPrepare(() => this.#prepareShared("create"));
453
+ await this.#requiredPrepare(() => this.#subscriptionRuntime.start());
454
+ });
455
+ return this.#joinRequiredCleanup(admitted);
456
+ }
457
+ /**
458
+ * Waits for recorded fatal cleanup only after context admission settles.
459
+ *
460
+ * @param admitted Locally admitted operation.
461
+ * @returns Completion after local work or fatal cleanup.
462
+ */
463
+ async #joinRequiredCleanup(admitted) {
464
+ try {
465
+ await admitted;
466
+ }
467
+ catch (error) {
468
+ if (serverEnvironmentAccess.hasStartupFailure(this.#environment))
469
+ return serverEnvironmentAccess.awaitStartupFailure(this.#environment);
470
+ throw error;
471
+ }
472
+ }
209
473
  /**
210
474
  * Creates tenant-aware Inboxes and their shared readiness signal.
211
475
  *
212
- * @param storageFactory Provider supplying the tenant catalog.
476
+ * @param tenantIndex Effective membership index for this context.
213
477
  * @returns Inboxes, tenant index, and readiness signal.
214
478
  */
215
- #createDelivery(storageFactory) {
216
- const deliveryReadiness = new DeliveryReadiness();
217
- const tenantIndex = TenantIndexes.create({
218
- contextName: this.#snapshot.name.value,
219
- tenantMode: this.#snapshot.tenantMode,
220
- storageFactory,
221
- });
222
- const keepTenant = (tenantId) => tenantIndex.keep(tenantId);
223
- const entityInbox = new LocalEntityInbox(this.#snapshot.name.value, deliveryReadiness, keepTenant, this.#deliveryStrategy);
224
- const projectionInbox = new LocalProjectionInbox(this.#snapshot.name.value, deliveryReadiness, keepTenant);
479
+ #createDelivery(tenantIndex) {
480
+ const deliveryReadiness = this.#createReadiness();
481
+ const onAdmit = (tenantId) => this.#admitTenant(tenantId);
482
+ const entityInbox = new LocalEntityInbox(this.#snapshot.name.value, deliveryReadiness, onAdmit, this.#environment.delivery.strategy);
483
+ const projectionInbox = new LocalProjectionInbox(this.#snapshot.name.value, deliveryReadiness, onAdmit);
484
+ deliveryReadiness.configureDirect((message, tenantId) => message.label === "UPDATE_SUBSCRIBER"
485
+ ? projectionInbox.replay(message, tenantId)
486
+ : entityInbox.replay(message, tenantId));
225
487
  return { deliveryReadiness, tenantIndex, entityInbox, projectionInbox };
226
488
  }
489
+ /**
490
+ * Creates readiness for the shared Delivery and this context's Agent capacity.
491
+ * @returns Shared readiness with the Agent capacity wake installed.
492
+ */
493
+ #createReadiness() {
494
+ const readiness = new DeliveryReadiness(undefined, serverEnvironmentAccess.coreDelivery(this.#environment), (shard) => {
495
+ serverEnvironmentAccess.notifyDelivery(this.#environment, shard);
496
+ }, serverEnvironmentAccess.remoteSupervised(this.#environment));
497
+ if (this.#ai !== undefined)
498
+ this.#stopAgentAvailability = AgentExecutionCapacity.for(this.#ai).onAvailable(() => {
499
+ readiness.retryDeferred();
500
+ });
501
+ return readiness;
502
+ }
227
503
  /**
228
504
  * Installs framework references used after context construction.
229
505
  *
@@ -239,35 +515,17 @@ export class BoundedContext {
239
515
  contextTenantIndexes.set(this, delivery.tenantIndex);
240
516
  contextStorageFactories.set(this, input.storageFactory);
241
517
  contextSubscriptionRuntimes.set(this, this.#subscriptionRuntime);
518
+ contextPreparations.set(this, (options) => this.#prepareBuild(options));
519
+ contextInputPreparations.set(this, (tenantId) => this.#prepareInput(tenantId));
242
520
  contextSignalPublishers.set(this, this.#publisher);
243
521
  contextClosePhases.set(this, {
244
522
  begin: () => {
245
523
  this.#beginClose();
246
524
  },
247
525
  drain: () => this.#drainWork(),
526
+ trackReplay: (onReplay) => this.#trackReplay(onReplay),
248
527
  });
249
- contextDeliveryDescriptors.set(this, ContextParts.createDeliveryDescriptor(this.#snapshot, input.storageFactory, delivery.tenantIndex, this.#entityInbox, this.#projectionInbox, delivery.deliveryReadiness));
250
- }
251
- /**
252
- * Registers repositories and starts subscriptions, closing the tenant index on failure.
253
- *
254
- * @param repositories Prepared repositories.
255
- * @param tenantIndex Index to close if registration fails.
256
- */
257
- #registerAndStart(repositories, tenantIndex) {
258
- try {
259
- this.#registerRepositories(repositories);
260
- this.#subscriptionRuntime.start();
261
- }
262
- catch (error) {
263
- try {
264
- ContextParts.cleanupFailedContext(this, tenantIndex);
265
- }
266
- catch (cleanupError) {
267
- throw new AggregateError([error, cleanupError], "Bounded Context build failed, and tenant index cleanup also failed.");
268
- }
269
- throw error;
270
- }
528
+ contextDeliveryDescriptors.set(this, ContextParts.createDeliveryDescriptor(this.#entityInbox, this.#projectionInbox));
271
529
  }
272
530
  #registerRepositories(repositories) {
273
531
  const preparedRepositories = this.#prepareRepositories(repositories);
@@ -275,6 +533,7 @@ export class BoundedContext {
275
533
  for (const preparedRepository of preparedRepositories) {
276
534
  ContextParts.rejectRegisteredRepository(preparedRepository.repository);
277
535
  }
536
+ this.#reserveStates(preparedRepositories);
278
537
  for (const preparedRepository of preparedRepositories) {
279
538
  this.#stand.register(preparedRepository.snapshot.stateSchema, {
280
539
  columns: ContextParts.repositoryColumns(preparedRepository.snapshot),
@@ -294,6 +553,19 @@ export class BoundedContext {
294
553
  this.#failRegistration(error, preparedRepositories);
295
554
  }
296
555
  }
556
+ /**
557
+ * Reserves Entity state types before registration mutates delivery targets.
558
+ *
559
+ * @param repositories Prepared repositories for this context.
560
+ */
561
+ #reserveStates(repositories) {
562
+ for (const repository of repositories) {
563
+ const stateType = TypeUrls.derive(repository.snapshot.stateSchema);
564
+ const prior = serverEnvironmentAccess.reserveState(this.#environment, this, stateType);
565
+ if (prior !== undefined)
566
+ throw new DuplicateEntityStateException(stateType, prior.name.value, this.name.value);
567
+ }
568
+ }
297
569
  #prepareRepositories(repositories) {
298
570
  const registration = this.#repositoryRegistration();
299
571
  const preparedRepositories = [];
@@ -307,14 +579,28 @@ export class BoundedContext {
307
579
  }
308
580
  return preparedRepositories;
309
581
  }
582
+ /**
583
+ * Reserves shared-registry capacity before Agent receipt admission.
584
+ */
585
+ #reserveAgent(key, signal) {
586
+ const reservation = this.#ai === undefined
587
+ ? undefined
588
+ : AgentExecutionCapacity.for(this.#ai).reserve(key, signal);
589
+ if (reservation !== undefined) {
590
+ this.#agentReservations.add(reservation.completed);
591
+ void reservation.completed.then(() => this.#agentReservations.delete(reservation.completed), () => this.#agentReservations.delete(reservation.completed));
592
+ }
593
+ return reservation;
594
+ }
310
595
  /**
311
596
  * Builds callbacks shared by every repository prepared for this Bounded Context.
312
597
  */
313
598
  #repositoryRegistration() {
314
- const registration = {
599
+ return {
315
600
  name: ContextParts.cloneName(this.#snapshot.name),
316
601
  storageContext: ContextParts.createStorageMode(this.#snapshot.spec),
317
602
  storageFactory: this.#storageFactory,
603
+ onAdmit: (tenantId) => this.#admitTenant(tenantId),
318
604
  ...(this.#ai === undefined ? {} : { ai: this.#ai }),
319
605
  stand: this.#stand,
320
606
  entityInbox: this.#entityInbox,
@@ -326,22 +612,38 @@ export class BoundedContext {
326
612
  registerSystemEventSchema: (schema) => {
327
613
  eventBusAccess.registerSchemas(this.#systemEventBus, [schema]);
328
614
  },
329
- prepareSavedEvent: (event) => eventBusAccess.prepareSaved(this.#eventBus, event),
330
- prepareSavedCommand: (command) => commandBusAccess.prepareSaved(this.#commandBus, command),
331
- publishSavedEvent: (event, plan) => eventBusAccess.postSavedFollowUp(this.#eventBus, event, plan),
332
- publishSavedCommand: (command, plan) => commandBusAccess.postSavedFollowUp(this.#commandBus, command, plan),
333
- publishAgentSystemEvent: (event) => eventBusAccess.postFollowUp(this.#systemEventBus, event),
334
- recordAcceptedSaved: (signal) => {
335
- this.#publisher.recordAcceptedSaved(signal);
336
- },
337
- wakeAcceptedAgent: (repository, tenantId) => {
338
- this.#agentScheduler?.wake(this.#agentScope(repository, tenantId));
615
+ publishAgentEvent: (event) => this.#publishAgentEvent(event),
616
+ publishAgentSystemEvent: (event) => this.#publisher.publishSystemEvent(event),
617
+ agentReceipts: this.#agentReceipts,
618
+ agentSignal: this.#agentController.signal,
619
+ reserveAgent: (key, signal) => this.#reserveAgent(key, signal),
620
+ deferAgent: (message, tenantId) => {
621
+ this.#deferAgent(message, tenantId);
339
622
  },
340
623
  };
341
- return registration;
624
+ }
625
+ /**
626
+ * Publishes an Agent event on its selected ordinary or rejection bus.
627
+ */
628
+ #publishAgentEvent(event) {
629
+ return event.context?.rejection === undefined
630
+ ? this.#publisher.publishEvent(event)
631
+ : this.#publisher.publishRejectionEvent(event);
632
+ }
633
+ /**
634
+ * Records a deferred Agent shard for the next available capacity slot.
635
+ */
636
+ #deferAgent(message, tenantId) {
637
+ this.#deliveryReadiness.defer({
638
+ label: message.label,
639
+ targetTypeUrl: message.inboxId.targetTypeUrl,
640
+ shard: message.shard,
641
+ ...(tenantId === undefined ? {} : { tenantId }),
642
+ });
342
643
  }
343
644
  #failRegistration(error, preparedRepositories) {
344
- const closeErrors = ContextParts.closePreparedRepositories(preparedRepositories);
645
+ const uncommitted = preparedRepositories.filter(({ repository }) => !this.#repositoryViews.has(repository));
646
+ const closeErrors = ContextParts.closePreparedRepositories(uncommitted);
345
647
  if (closeErrors.length > 0) {
346
648
  throw new AggregateError([error, ...closeErrors], "Repository registration failed, and prepared repository storage cleanup also failed.");
347
649
  }
@@ -389,6 +691,14 @@ export class BoundedContext {
389
691
  get isMultitenant() {
390
692
  return this.#snapshot.tenantMode === "multitenant";
391
693
  }
694
+ /**
695
+ * Returns the live index configured for this Bounded Context.
696
+ *
697
+ * @returns The effective configured index.
698
+ */
699
+ get tenantIndex() {
700
+ return ContextParts.requireTenantIndex(this);
701
+ }
392
702
  /**
393
703
  * Returns a copy-safe specification used to build this context.
394
704
  *
@@ -478,7 +788,7 @@ export class BoundedContext {
478
788
  * - single-tenant contexts reject `tenantId`;
479
789
  * - multitenant contexts require the exact non-blank `tenantId`;
480
790
  * - process-local sequential execution on the same EventBus runtime queue as
481
- * live event intake and stored redispatch.
791
+ * live event intake.
482
792
  *
483
793
  * Unsupported boundary:
484
794
  * - Delivery jobs, schedulers, inbox lifecycle, retries, and transport
@@ -520,14 +830,8 @@ export class BoundedContext {
520
830
  });
521
831
  }
522
832
  /**
523
- * Closes this context's buses, Stand, and repository storage and runtime bindings.
524
- *
525
- * Close is idempotent and returns the same close outcome on repeated calls.
526
- * The context attempts every close hook; when any hook fails, the
527
- * returned promise rejects with an `AggregateError` after the remaining hooks
528
- * have also been attempted.
529
- *
530
- * @returns A promise that settles after all resources close.
833
+ * Closes this context's buses, Stand, repository storage, and runtime bindings.
834
+ * @returns Completion or an aggregate of close failures.
531
835
  */
532
836
  close() {
533
837
  this.#beginClose();
@@ -535,11 +839,13 @@ export class BoundedContext {
535
839
  return this.#closed;
536
840
  }
537
841
  /**
538
- * Stops admission to this context's signal and bus work.
842
+ * Stops external admission while accepted follow-ups drain.
539
843
  */
540
844
  #beginClose() {
541
845
  closingContexts.add(this);
542
- this.#agentScheduler?.stop();
846
+ this.#preparationController.abort(new Error("Bounded Context closed."));
847
+ serverEnvironmentAccess.stopRecipients(this.#environment, this);
848
+ this.#agentController.abort(new Error("Bounded Context closed."));
543
849
  this.#publisher.beginClose();
544
850
  commandBusAccess.beginClose(this.#commandBus);
545
851
  eventBusAccess.beginClose(this.#eventBus);
@@ -551,9 +857,10 @@ export class BoundedContext {
551
857
  * @returns Completion after the context's accepted work settles.
552
858
  */
553
859
  async #drainWork() {
860
+ this.#beginClose();
554
861
  const errors = [];
555
- await ContextParts.closeContextPart(() => ContextParts.closeIntegration(this), errors);
556
- await ContextParts.closeContextPart(() => ContextParts.drainContextWork(this.#commandBus, this.#eventBus, this.#systemEventBus, this.#publisher), errors);
862
+ await this.#closePart(() => ContextParts.closeIntegration(this), errors);
863
+ await this.#closePart(() => ContextParts.drainContextWork(this.#commandBus, this.#eventBus, this.#systemEventBus, this.#publisher), errors);
557
864
  if (errors.length > 0)
558
865
  throw new AggregateError(errors, "BoundedContext drain failed.");
559
866
  }
@@ -564,46 +871,154 @@ export class BoundedContext {
564
871
  */
565
872
  async #closeOnce() {
566
873
  const errors = [];
567
- await ContextParts.closeContextPart(() => this.#agentScheduler?.close(), errors);
568
- await ContextParts.closeContextPart(() => this.#drainWork(), errors);
569
- this.#publisher.finishClose();
570
- await ContextParts.closeContextPart(() => commandBusAccess.finishClose(this.#commandBus), errors);
571
- await ContextParts.closeContextPart(() => eventBusAccess.finishClose(this.#eventBus), errors);
572
- this.#subscriptionRuntime.beginClose();
573
- await ContextParts.closeContextPart(() => eventBusAccess.drain(this.#systemEventBus), errors);
574
- await ContextParts.closeContextPart(() => this.#subscriptionRuntime.drainClose(), errors);
575
- await ContextParts.closeContextPart(() => eventBusAccess.finishClose(this.#systemEventBus), errors);
576
- await ContextParts.closeContextPart(() => this.#stand.close(), errors);
577
- await ContextParts.closeContextPart(() => this.#systemStand.close(), errors);
578
- await ContextParts.closeContextPart(() => this.#subscriptionRuntime.finishClose(), errors);
579
- await ContextParts.closeContextPart(() => {
580
- ContextParts.requireTenantIndex(this).close();
581
- }, errors);
874
+ this.#stopAgentAvailability?.();
875
+ this.#stopAgentAvailability = undefined;
876
+ await this.#closePart(() => this.#drainWork(), errors);
877
+ await this.#drainAdmittedContextWork(errors);
878
+ await this.#closePart(() => this.#deliveryReadiness.close(), errors);
879
+ await this.#closePart(() => ContextParts.drainContextWork(this.#commandBus, this.#eventBus, this.#systemEventBus, this.#publisher), errors);
880
+ await this.#closePart(() => this.#agentReceipts.close(), errors);
881
+ await this.#closeBuses(errors);
882
+ await this.#closePart(() => this.#stand.close(), errors);
883
+ await this.#closePart(() => this.#systemStand.close(), errors);
884
+ await this.#closePart(() => this.#subscriptionRuntime.finishClose(), errors);
582
885
  await this.#closeRepositories(errors);
886
+ serverEnvironmentAccess.removeContext(this.#environment, this);
583
887
  if (errors.length > 0) {
584
888
  this.#closed = undefined;
585
889
  throw new AggregateError(ContextParts.flattenErrors(errors), "BoundedContext close failed.");
586
890
  }
587
891
  ContextParts.clearContextMetadata(this);
588
892
  }
893
+ /**
894
+ * Settles entered replay, local follow-ups, and reserved Agent turns.
895
+ * @param errors Collects independent close failures.
896
+ */
897
+ async #drainAdmittedContextWork(errors) {
898
+ await this.#closePart(() => Promise.allSettled([...this.#activePreparations]).then(() => undefined), errors);
899
+ await this.#closePart(() => Promise.allSettled([...this.#activeReplays]).then(() => undefined), errors);
900
+ await this.#closePart(() => this.#entityInbox.whenFollowUpsIdle(), errors);
901
+ await this.#closePart(() => Promise.allSettled([...this.#agentReservations]).then(() => undefined), errors);
902
+ }
903
+ /**
904
+ * Closes bus intake and subscription drains before the Stands.
905
+ *
906
+ * @param errors Collects independent close failures.
907
+ * @returns Completion after bounded bus close attempts.
908
+ */
909
+ async #closeBuses(errors) {
910
+ this.#publisher.finishClose();
911
+ await this.#closePart(() => commandBusAccess.finishClose(this.#commandBus), errors);
912
+ await this.#closePart(() => eventBusAccess.finishClose(this.#eventBus), errors);
913
+ this.#subscriptionRuntime.beginClose();
914
+ await this.#closePart(() => eventBusAccess.drain(this.#systemEventBus), errors);
915
+ await this.#closePart(() => this.#subscriptionRuntime.drainClose(), errors);
916
+ await this.#closePart(() => eventBusAccess.finishClose(this.#systemEventBus), errors);
917
+ }
589
918
  /**
590
919
  * Clears repository runtime registration after Stand closure.
591
920
  *
592
921
  * @param errors Failures collected during context closure.
593
922
  */
594
923
  async #closeRepositories(errors) {
595
- for (const repository of this.#repositoryViews) {
596
- await ContextParts.closeContextPart(() => {
597
- repositoryAccess.clearRuntime(repository);
924
+ const closing = [...this.#repositoryViews].map((repository) => {
925
+ return repositoryAccess.clearRuntime(repository).finally(() => {
598
926
  registeredRepositories.delete(repository);
599
- }, errors);
927
+ });
928
+ });
929
+ for (const result of await Promise.allSettled(closing)) {
930
+ if (result.status === "rejected")
931
+ errors.push(result.reason);
600
932
  }
601
933
  }
934
+ /**
935
+ * Registers an entered shared replay through its complete follow-up callback.
936
+ * @param onReplay Complete replay callback.
937
+ * @returns Completion of the captured callback.
938
+ */
939
+ #trackReplay(onReplay) {
940
+ const replay = Promise.resolve().then(onReplay);
941
+ this.#activeReplays.add(replay);
942
+ void replay.then(() => this.#activeReplays.delete(replay), () => this.#activeReplays.delete(replay));
943
+ return replay;
944
+ }
945
+ /**
946
+ * Calls a close action and collects its failure before later cleanup.
947
+ * @param work Close action.
948
+ * @param errors Collects close failures.
949
+ */
950
+ async #closePart(work, errors) {
951
+ await ContextParts.closeContextPart(work, errors);
952
+ }
602
953
  }
603
954
  /**
604
955
  * Exposes framework-only operations for built contexts and their builders.
605
956
  */
606
957
  export const boundedContextAccess = Object.freeze({
958
+ /**
959
+ * Reports whether close has started for the given context.
960
+ *
961
+ * @param context Completed context.
962
+ * @returns Whether close has started.
963
+ */
964
+ isClosing: (context) => closingContexts.has(context),
965
+ /**
966
+ * Prepares an admitted context without joining global fatal cleanup.
967
+ *
968
+ * @param context Admitted context.
969
+ * @param mode Creation or read-only check.
970
+ * @param ids Captured tenant identities.
971
+ * @returns Completion of local preparation.
972
+ */
973
+ prepareExplicit(context, mode, ids) {
974
+ const prepare = explicitPreparations.get(context);
975
+ if (prepare === undefined)
976
+ return Promise.reject(new TypeError("Preparation requires a built context."));
977
+ return prepare(mode, ids);
978
+ },
979
+ /**
980
+ * Admits a service membership and preparation chain before its first await.
981
+ *
982
+ * @param context Selected built context.
983
+ * @param tenantId Captured tenant identity, when applicable.
984
+ * @param onMembership Checks live tenant membership.
985
+ * @param onReady Performs the admitted one-shot registry mutation, if present.
986
+ * @returns Tracked completion of membership and model preparation.
987
+ */
988
+ admitServiceInput(context, tenantId, onMembership, onReady) {
989
+ if (closingContexts.has(context))
990
+ return Promise.reject(new Error("Bounded Context is closing."));
991
+ const prepare = contextInputPreparations.get(context);
992
+ const phase = contextClosePhases.get(context);
993
+ if (prepare === undefined || phase === undefined)
994
+ return Promise.reject(new TypeError("Service input requires a built context."));
995
+ return phase.trackReplay(async () => {
996
+ await onMembership();
997
+ await prepare(tenantId);
998
+ await onReady?.();
999
+ });
1000
+ },
1001
+ /**
1002
+ * Admits one shared subscription-registry operation before asynchronous lookup.
1003
+ *
1004
+ * @param context Selected built context.
1005
+ * @param onOperation Complete registry operation.
1006
+ * @returns Tracked operation completion.
1007
+ */
1008
+ admitServiceRegistryOperation(context, onOperation) {
1009
+ if (closingContexts.has(context))
1010
+ return Promise.reject(new Error("Bounded Context is closing."));
1011
+ const phase = contextClosePhases.get(context);
1012
+ if (phase === undefined)
1013
+ return Promise.reject(new TypeError("Service registry requires a built context."));
1014
+ return phase.trackReplay(onOperation);
1015
+ },
1016
+ trackReplay(context, onReplay) {
1017
+ const phase = contextClosePhases.get(context);
1018
+ if (phase === undefined)
1019
+ return Promise.reject(new TypeError("Replay requires a built context."));
1020
+ return phase.trackReplay(onReplay);
1021
+ },
607
1022
  /**
608
1023
  * Resolves a view only within the Bounded Context that issued it.
609
1024
  *
@@ -651,7 +1066,7 @@ export const boundedContextAccess = Object.freeze({
651
1066
  if (runtime === undefined) {
652
1067
  throw new TypeError("Context logger requires a built BoundedContext instance.");
653
1068
  }
654
- subscriptionRuntimeAccess.installLogger(runtime, logger);
1069
+ subscriptionRuntimeAccess.installLogger(runtime, logger, context.name.value);
655
1070
  },
656
1071
  loggerFor(context) {
657
1072
  const logger = contextLoggers.get(context);
@@ -665,12 +1080,12 @@ export const boundedContextAccess = Object.freeze({
665
1080
  value !== null &&
666
1081
  builderBuilds.has(value));
667
1082
  },
668
- build(builder, defaultStorageFactory, defaultAi) {
1083
+ build(builder) {
669
1084
  const build = builderBuilds.get(builder);
670
1085
  if (build === undefined) {
671
1086
  throw new TypeError("Builder access requires a BoundedContextBuilder instance.");
672
1087
  }
673
- return build(defaultStorageFactory, defaultAi);
1088
+ return build();
674
1089
  },
675
1090
  subscribeToEvent(context, typeUrl, subscriber) {
676
1091
  const subscribe = eventSubscribers.get(context);
@@ -747,9 +1162,8 @@ export class BoundedContextBuilder {
747
1162
  #repositories = new Set();
748
1163
  #entityTypes = new Set();
749
1164
  #generatedRepositoryOptions = new Map();
750
- #deliveryStrategy = UniformAcrossAllShards.singleShard();
751
- #storageFactory;
752
1165
  #aiRegistry;
1166
+ #tenantIndex;
753
1167
  #subscriptionRegistry;
754
1168
  #persistSystemEvents = false;
755
1169
  #generatedRegistryRoot;
@@ -768,7 +1182,7 @@ export class BoundedContextBuilder {
768
1182
  constructor(specSnapshot, token) {
769
1183
  ContextParts.requireFrameworkConstructionToken(token, "BoundedContextBuilder instances are framework-owned.");
770
1184
  this.#specSnapshot = ContextParts.cloneSpecSnapshot(specSnapshot);
771
- builderBuilds.set(this, (defaultStorageFactory, defaultAi) => this.#buildAsyncWith(defaultStorageFactory, defaultAi));
1185
+ builderBuilds.set(this, () => this.#buildAsyncWith());
772
1186
  Object.freeze(this);
773
1187
  }
774
1188
  /**
@@ -843,7 +1257,7 @@ export class BoundedContextBuilder {
843
1257
  *
844
1258
  * @param dispatcher Raw command dispatcher, or an `AbstractCommander` instance.
845
1259
  * A standalone commander requires generated receiver metadata and therefore
846
- * this builder's `buildAsync()` path. It installs its Command and Event sides
1260
+ * this builder's `build()` path. It installs its Command and Event sides
847
1261
  * exactly once.
848
1262
  *
849
1263
  * @returns This builder for further configuration.
@@ -870,7 +1284,7 @@ export class BoundedContextBuilder {
870
1284
  * Adds an event dispatcher to the context being built.
871
1285
  *
872
1286
  * @param dispatcher Raw event dispatcher, or a standalone reactor/subscriber.
873
- * Standalone receivers require generated receiver metadata and `buildAsync()`.
1287
+ * Standalone receivers require generated receiver metadata and `build()`.
874
1288
  *
875
1289
  * @returns This builder for further configuration.
876
1290
  */
@@ -887,7 +1301,7 @@ export class BoundedContextBuilder {
887
1301
  * Adds a generated standalone command assignee.
888
1302
  *
889
1303
  * The registered instance is matched by exact constructor to generated
890
- * receiver metadata when `buildAsync()` assembles the context.
1304
+ * receiver metadata when `build()` assembles the context.
891
1305
  *
892
1306
  * @param assignee Generated standalone assignee instance.
893
1307
  * @returns This builder for further configuration.
@@ -907,13 +1321,13 @@ export class BoundedContextBuilder {
907
1321
  return this;
908
1322
  }
909
1323
  /**
910
- * Sets a storage factory for event, repository-state, and Stand storage.
1324
+ * Sets a live tenant index for this Bounded Context.
911
1325
  *
912
- * @param storageFactory Creates the context's persistent storage.
913
- * @returns Returns this builder for further configuration.
1326
+ * @param tenantIndex Application membership index.
1327
+ * @returns This builder.
914
1328
  */
915
- withStorageFactory(storageFactory) {
916
- this.#storageFactory = storageFactory;
1329
+ withTenantIndex(tenantIndex) {
1330
+ this.#tenantIndex = tenantIndex;
917
1331
  return this;
918
1332
  }
919
1333
  /**
@@ -951,16 +1365,6 @@ export class BoundedContextBuilder {
951
1365
  this.#subscriptionRegistry = registry;
952
1366
  return this;
953
1367
  }
954
- /**
955
- * Sets how Entity Inbox targets are assigned to shards.
956
- *
957
- * @param strategy Selects the durable shard for Aggregate and Process Manager targets.
958
- * @returns Returns this builder for further configuration.
959
- */
960
- withDeliveryStrategy(strategy) {
961
- this.#deliveryStrategy = ContextParts.snapshotDeliveryStrategy(strategy);
962
- return this;
963
- }
964
1368
  /**
965
1369
  * Sets a trusted compiled application root for generated handler metadata.
966
1370
  *
@@ -972,49 +1376,108 @@ export class BoundedContextBuilder {
972
1376
  return this;
973
1377
  }
974
1378
  /**
975
- * Builds a context from explicitly added repositories and dispatchers.
1379
+ * Builds a context after loading generated handlers and preparing runtime resources.
976
1380
  *
977
- * @returns Returns the built context.
1381
+ * @param options Independent eager structure and subscription timing choices.
1382
+ * @returns The built context after requested initialization and integration are ready.
978
1383
  */
979
- build() {
980
- if (this.#standaloneInstances().length > 0) {
981
- throw new Error("Standalone generated handlers require buildAsync().");
1384
+ build(options = {}) {
1385
+ return this.#buildAsyncWith(options);
1386
+ }
1387
+ async #buildAsyncWith(options = {}) {
1388
+ const environment = ServerEnvironment.instance();
1389
+ const finishBuild = serverEnvironmentAccess.beginContextBuild(environment);
1390
+ let built;
1391
+ let failed = false;
1392
+ let failure;
1393
+ try {
1394
+ await serverEnvironmentAccess.awaitSetup(environment);
1395
+ built = await this.#buildAsyncReady(options, environment);
982
1396
  }
983
- ContextParts.rejectSyncEntityAssembly(this.#entityTypes);
984
- return this.#buildWith([...this.#repositories], this.#storageFactory ?? new InMemoryStorageFactory(), [], this.#aiRegistry);
1397
+ catch (error) {
1398
+ failed = true;
1399
+ failure = error;
1400
+ }
1401
+ finally {
1402
+ finishBuild();
1403
+ }
1404
+ if (serverEnvironmentAccess.hasStartupFailure(environment))
1405
+ return serverEnvironmentAccess.awaitStartupFailure(environment);
1406
+ if (failed)
1407
+ throw failure;
1408
+ if (built === undefined)
1409
+ throw new Error("Bounded Context build did not complete.");
1410
+ return built;
985
1411
  }
986
1412
  /**
987
- * Builds a context after loading generated metadata for added entity classes
988
- * and registered standalone handlers.
989
- *
990
- * Standalone assignees, commanders, reactors, and subscribers require this
991
- * asynchronous path so their exact constructors can be matched to generated
992
- * receiver metadata.
1413
+ * Loads generated metadata and finishes one asynchronous context assembly.
993
1414
  *
994
- * @returns Resolves to the built context.
1415
+ * @returns The integrated context.
995
1416
  */
996
- async buildAsync() {
997
- return this.#buildAsyncWith();
998
- }
999
- async #buildAsyncWith(defaultStorageFactory, defaultAi) {
1417
+ async #buildAsyncReady(options, environment) {
1000
1418
  const generated = await this.#loadGeneratedArtifacts([...this.#entityTypes]);
1419
+ serverEnvironmentAccess.requireAvailable(environment);
1001
1420
  const repositories = [...this.#repositories, ...generated.repositories];
1002
- const context = this.#buildWith(repositories, this.#storageFactory ?? defaultStorageFactory ?? new InMemoryStorageFactory(), generated.standalone, this.#aiRegistry ?? defaultAi);
1421
+ const context = await this.#buildWithResources(repositories, environment.storageFactory, generated.standalone, this.#aiRegistry ?? environment.ai);
1003
1422
  try {
1004
- await ContextParts.integrationReady(context);
1423
+ await this.#integrateBuiltContext(context, options, environment);
1005
1424
  }
1006
1425
  catch (error) {
1007
- try {
1008
- await context.close();
1009
- }
1010
- catch (closeError) {
1011
- throw new AggregateError([error, closeError], "BoundedContext broker open failed during cleanup.");
1012
- }
1013
- throw error;
1426
+ return this.#closeFailedBuild(context, environment, error);
1014
1427
  }
1015
1428
  return context;
1016
1429
  }
1017
- #buildWith(repositories, storageFactory, standalone = [], ai) {
1430
+ /**
1431
+ * Completes required integration and requested initialization before publication.
1432
+ * @param context Constructed context.
1433
+ * @param options Requested eager initialization phases.
1434
+ * @param environment Captured environment lifetime.
1435
+ */
1436
+ async #integrateBuiltContext(context, options, environment) {
1437
+ serverEnvironmentAccess.requireAvailable(environment);
1438
+ boundedContextAccess.installLogger(context, serverEnvironmentAccess.loggerFor(environment));
1439
+ await ContextParts.integrationReady(context).catch((error) => {
1440
+ serverEnvironmentAccess.failStartup(environment, error);
1441
+ throw error;
1442
+ });
1443
+ serverEnvironmentAccess.requireAvailable(environment);
1444
+ const prepare = contextPreparations.get(context);
1445
+ if (prepare === undefined)
1446
+ throw new Error("Context preparation is unavailable.");
1447
+ await prepare(options);
1448
+ serverEnvironmentAccess.requireAvailable(environment);
1449
+ await serverEnvironmentAccess.completeContext(environment, context);
1450
+ }
1451
+ /**
1452
+ * Releases a failed partial context before its build ticket settles.
1453
+ * @param context Context assembled before the failure.
1454
+ * @param environment Captured environment lifetime.
1455
+ * @param error Original build failure.
1456
+ * @returns Rejection retaining the original and any local cleanup failure.
1457
+ */
1458
+ async #closeFailedBuild(context, environment, error) {
1459
+ try {
1460
+ await context.close();
1461
+ }
1462
+ catch (closeError) {
1463
+ if (serverEnvironmentAccess.hasStartupFailure(environment)) {
1464
+ serverEnvironmentAccess.recordStartupCleanup(environment, closeError);
1465
+ throw error;
1466
+ }
1467
+ throw new AggregateError([error, closeError], "BoundedContext open cleanup failed.");
1468
+ }
1469
+ throw error;
1470
+ }
1471
+ /**
1472
+ * Assembles a context and cleans partial resources on failure.
1473
+ *
1474
+ * @param repositories Repositories selected for the context.
1475
+ * @param storageFactory Storage factory for the context.
1476
+ * @param standalone Generated standalone handler groups.
1477
+ * @param ai Optional AI registry.
1478
+ * @returns The assembled context.
1479
+ */
1480
+ async #buildWithResources(repositories, storageFactory, standalone, ai) {
1018
1481
  const resources = this.#subscriptionRegistry === undefined ? {} : { registry: this.#subscriptionRegistry };
1019
1482
  this.#subscriptionRegistry = undefined;
1020
1483
  const registeredRepositories = [...repositories];
@@ -1022,7 +1485,7 @@ export class BoundedContextBuilder {
1022
1485
  return this.#assembleContext(registeredRepositories, storageFactory, standalone, resources, ai);
1023
1486
  }
1024
1487
  catch (error) {
1025
- return this.#failBuild(resources, error);
1488
+ return await this.#failBuild(resources, error);
1026
1489
  }
1027
1490
  }
1028
1491
  #assembleContext(repositories, storageFactory, standalone, resources, ai) {
@@ -1041,6 +1504,10 @@ export class BoundedContextBuilder {
1041
1504
  ]);
1042
1505
  const running = this.#buildRuntime(storageFactory, buses, resources);
1043
1506
  const context = this.#createContext(repositories, storageFactory, buses, running, ai);
1507
+ resources.context = context;
1508
+ if (registerBoundedContext === undefined)
1509
+ throw new Error("Context registration is unavailable.");
1510
+ registerBoundedContext(context, repositories);
1044
1511
  ContextParts.attachIntegration(context, buses.eventBus, buses.systemSpec, ContextParts.externalEventSchemas([
1045
1512
  ...dispatchers.domain,
1046
1513
  ...(standaloneEvent === undefined ? [] : [standaloneEvent]),
@@ -1065,36 +1532,14 @@ export class BoundedContextBuilder {
1065
1532
  throw new TypeError("Agent registration requires persisted System Events.");
1066
1533
  if (!AgentHistoryStorageFactories.supports(storageFactory))
1067
1534
  throw new TypeError("Agent registration requires indexed history storage.");
1068
- if (!AgentExecutionStorageFactories.supports(storageFactory))
1069
- throw new TypeError("Agent registration requires durable execution storage.");
1070
- this.#checkAgentOutputBindings(agents);
1071
1535
  for (const repository of agents) {
1072
1536
  const config = repositoryAccess.agentConfiguration(repository);
1073
- if (config.codeRevision === undefined || config.codeRevision.trim() === "")
1074
- throw new TypeError("Agent registration requires a code revision.");
1075
1537
  if (config.ai === undefined)
1076
1538
  throw new TypeError("Agent registration requires repository capabilities.");
1077
1539
  if (config.ai.models.some((model) => !isAiModel(model)))
1078
1540
  throw new TypeError("Agent repository capabilities must be factory-created models.");
1079
1541
  }
1080
1542
  }
1081
- /**
1082
- * Rejects Agent outcomes whose raw matching dispatcher cannot bind a saved plan.
1083
- */
1084
- #checkAgentOutputBindings(agents) {
1085
- const rawEvents = new Set([...this.#eventDispatchers].flatMap((dispatcher) => dispatcher.messageSchemas().map((schema) => TypeUrls.derive(schema))));
1086
- const rawCommands = new Set([...this.#commandDispatchers].flatMap((dispatcher) => dispatcher.messageSchemas().map((schema) => TypeUrls.derive(schema))));
1087
- for (const repository of agents) {
1088
- if (repositoryAccess
1089
- .producedEventSchemas(repository)
1090
- .some((schema) => rawEvents.has(TypeUrls.derive(schema))))
1091
- throw new TypeError("Agent Event output requires a durable dispatcher binding.");
1092
- if (repositoryAccess
1093
- .producedCommandSchemas(repository)
1094
- .some((schema) => rawCommands.has(TypeUrls.derive(schema))))
1095
- throw new TypeError("Agent Command output requires a durable dispatcher binding.");
1096
- }
1097
- }
1098
1543
  #buildDispatchers(repositories) {
1099
1544
  const event = [
1100
1545
  ...ContextParts.repositoryEventDispatchers(repositories),
@@ -1135,7 +1580,7 @@ export class BoundedContextBuilder {
1135
1580
  #buildSystemBuses(storageFactory, dispatchers, resources) {
1136
1581
  const systemSpec = ContextParts.createSystemSpec(this.#specSnapshot, this.#persistSystemEvents);
1137
1582
  const systemEventStore = systemSpec.storesEvents
1138
- ? new EventStore(ContextParts.createStorageMode(systemSpec), storageFactory)
1583
+ ? new EventStore(ContextParts.createStorageMode(systemSpec), storageFactory, EventStoreGroups.forContext(systemSpec.name.value, "system"))
1139
1584
  : undefined;
1140
1585
  if (systemEventStore !== undefined)
1141
1586
  resources.systemEventStore = systemEventStore;
@@ -1172,10 +1617,7 @@ export class BoundedContextBuilder {
1172
1617
  return event;
1173
1618
  }
1174
1619
  #buildRuntime(storageFactory, buses, resources) {
1175
- const stand = new Stand({
1176
- context: ContextParts.createStorageMode(this.#specSnapshot),
1177
- storageFactory,
1178
- });
1620
+ const stand = this.#buildStand(storageFactory);
1179
1621
  resources.stand = stand;
1180
1622
  const registry = resources.registry ??
1181
1623
  new StorageSubscriptionRegistry(ContextParts.createSubscriptionStorageContext(this.#specSnapshot), storageFactory);
@@ -1184,19 +1626,50 @@ export class BoundedContextBuilder {
1184
1626
  resources.runtime = runtime;
1185
1627
  return { stand, registry, runtime };
1186
1628
  }
1629
+ /**
1630
+ * Builds the context Stand with a captured live membership directory.
1631
+ *
1632
+ * @param storageFactory Provider used for Entity records.
1633
+ * @returns Direct read-side Stand.
1634
+ */
1635
+ #buildStand(storageFactory) {
1636
+ const tenantIndex = this.#tenantIndex ?? ServerEnvironment.instance().tenantIndex;
1637
+ const stand = new Stand({
1638
+ context: ContextParts.createStorageMode(this.#specSnapshot),
1639
+ storageFactory,
1640
+ });
1641
+ standAccess.setAdmission(stand, (tenantId) => TenantAdmissions.require(tenantIndex, this.#specSnapshot.name.value, this.#specSnapshot.multitenant, tenantId));
1642
+ return stand;
1643
+ }
1187
1644
  #createContext(repositories, storageFactory, buses, running, ai) {
1188
- return ContextParts.createBoundedContext(this.#specSnapshot, storageFactory, repositories, this.#deliveryStrategy, buses, running, ai);
1645
+ return ContextParts.createBoundedContext(this.#specSnapshot, storageFactory, repositories, ServerEnvironment.instance().delivery.strategy, buses, running, ai, this.#tenantIndex ?? ServerEnvironment.instance().tenantIndex);
1189
1646
  }
1190
- #failBuild(resources, error) {
1647
+ async #failBuild(resources, error) {
1191
1648
  const cleanupErrors = [];
1192
- ContextParts.attemptCleanup(() => resources.runtime?.abortClose(), cleanupErrors);
1193
- ContextParts.attemptCleanup(() => resources.publisher?.abortAssembly(), cleanupErrors);
1194
- if (resources.runtime === undefined) {
1195
- ContextParts.attemptCleanup(() => void resources.registry?.close().catch(() => undefined), cleanupErrors);
1196
- }
1197
- ContextParts.attemptCleanup(() => void resources.stand?.close().catch(() => undefined), cleanupErrors);
1198
- ContextParts.attemptCleanup(() => void resources.systemStand?.close().catch(() => undefined), cleanupErrors);
1199
- ContextParts.cleanupBuildBuses(resources, cleanupErrors);
1649
+ if (resources.context !== undefined) {
1650
+ try {
1651
+ await resources.context.close();
1652
+ }
1653
+ catch (closeError) {
1654
+ cleanupErrors.push(closeError);
1655
+ }
1656
+ }
1657
+ else {
1658
+ ContextParts.attemptCleanup(() => resources.publisher?.abortAssembly(), cleanupErrors);
1659
+ const registry = resources.runtime ?? resources.registry;
1660
+ const closing = [registry, resources.stand, resources.systemStand];
1661
+ for (const resource of closing) {
1662
+ if (resource === undefined)
1663
+ continue;
1664
+ try {
1665
+ await resource.close();
1666
+ }
1667
+ catch (closeError) {
1668
+ cleanupErrors.push(closeError);
1669
+ }
1670
+ }
1671
+ await ContextParts.cleanupBuildBuses(resources, cleanupErrors);
1672
+ }
1200
1673
  if (cleanupErrors.length > 0) {
1201
1674
  throw new AggregateError([error, ...cleanupErrors], "Bounded Context build failed during cleanup.");
1202
1675
  }
@@ -1396,24 +1869,29 @@ const ContextParts = Object.freeze({
1396
1869
  *
1397
1870
  * @param resources Partially created resources.
1398
1871
  * @param errors Collection receiving failures.
1399
- */
1400
- cleanupBuildBuses(resources, errors) {
1401
- ContextParts.attemptCleanup(() => {
1402
- if (resources.commandBus !== undefined)
1403
- commandBusAccess.abortClose(resources.commandBus);
1404
- }, errors);
1405
- ContextParts.attemptCleanup(() => {
1406
- if (resources.systemEventBus !== undefined)
1407
- eventBusAccess.abortClose(resources.systemEventBus);
1408
- else
1409
- resources.systemEventStore?.close();
1410
- }, errors);
1411
- ContextParts.attemptCleanup(() => {
1412
- if (resources.eventBus !== undefined)
1413
- eventBusAccess.abortClose(resources.eventBus);
1414
- else
1415
- resources.eventStore?.close();
1416
- }, errors);
1872
+ * @returns Completion after all created buses and stores close.
1873
+ */
1874
+ async cleanupBuildBuses(resources, errors) {
1875
+ const closing = [];
1876
+ const { commandBus, systemEventBus, systemEventStore, eventBus, eventStore } = resources;
1877
+ if (commandBus !== undefined)
1878
+ closing.push(() => commandBus.close());
1879
+ if (systemEventBus !== undefined)
1880
+ closing.push(() => systemEventBus.close());
1881
+ else if (systemEventStore !== undefined)
1882
+ closing.push(() => systemEventStore.close());
1883
+ if (eventBus !== undefined)
1884
+ closing.push(() => eventBus.close());
1885
+ else if (eventStore !== undefined)
1886
+ closing.push(() => eventStore.close());
1887
+ for (const close of closing) {
1888
+ try {
1889
+ await close();
1890
+ }
1891
+ catch (error) {
1892
+ errors.push(error);
1893
+ }
1894
+ }
1417
1895
  },
1418
1896
  /**
1419
1897
  * Returns constituent failures from nested aggregate errors.
@@ -1463,15 +1941,12 @@ const ContextParts = Object.freeze({
1463
1941
  * @param buses Prepared domain and System buses.
1464
1942
  * @param running Prepared Stand and subscription runtime.
1465
1943
  * @param ai Effective AI registry when Agent repositories are present.
1944
+ * @param tenantIndex Effective live membership index.
1466
1945
  * @returns Constructed bounded context.
1467
1946
  */
1468
- createBoundedContext(specSnapshot, storageFactory, repositories, deliveryStrategy, buses, running, ai) {
1947
+ createBoundedContext(specSnapshot, storageFactory, repositories, deliveryStrategy, buses, running, ai, tenantIndex) {
1469
1948
  return constructBoundedContext({
1470
- snapshot: {
1471
- name: specSnapshot.name,
1472
- tenantMode: ContextParts.toTenantMode(specSnapshot.multitenant),
1473
- spec: specSnapshot,
1474
- },
1949
+ snapshot: ContextParts.snapshotFor(specSnapshot),
1475
1950
  commandBus: buses.commandBus,
1476
1951
  eventBus: buses.eventBus,
1477
1952
  systemEventBus: buses.systemEventBus,
@@ -1481,12 +1956,26 @@ const ContextParts = Object.freeze({
1481
1956
  subscriptionRuntime: running.runtime,
1482
1957
  systemSpec: buses.systemSpec,
1483
1958
  storageFactory,
1959
+ tenantIndex: tenantIndex ?? ServerEnvironment.instance().tenantIndex,
1484
1960
  repositories,
1485
1961
  deliveryStrategy,
1486
1962
  ...(ai === undefined ? {} : { ai }),
1487
1963
  token: frameworkConstructionToken,
1488
1964
  });
1489
1965
  },
1966
+ /**
1967
+ * Captures public context identity from the build specification.
1968
+ *
1969
+ * @param specSnapshot Prepared context specification.
1970
+ * @returns Immutable context metadata input.
1971
+ */
1972
+ snapshotFor(specSnapshot) {
1973
+ return {
1974
+ name: specSnapshot.name,
1975
+ tenantMode: ContextParts.toTenantMode(specSnapshot.multitenant),
1976
+ spec: specSnapshot,
1977
+ };
1978
+ },
1490
1979
  /**
1491
1980
  * Creates the storage mode represented by a context snapshot.
1492
1981
  *
@@ -1511,35 +2000,6 @@ const ContextParts = Object.freeze({
1511
2000
  multitenant: false,
1512
2001
  });
1513
2002
  },
1514
- /**
1515
- * Captures the shard count and validates later shard results.
1516
- *
1517
- * @param strategy Configured delivery strategy.
1518
- * @returns Immutable delivery strategy snapshot.
1519
- */
1520
- snapshotDeliveryStrategy(strategy) {
1521
- if (!Number.isSafeInteger(strategy.shardCount) || strategy.shardCount <= 0) {
1522
- throw new Error("Delivery strategy shard count must be a positive safe integer.");
1523
- }
1524
- const shardCount = strategy.shardCount;
1525
- return Object.freeze({
1526
- shardCount,
1527
- /**
1528
- * Returns a target shard after verifying the captured shard total.
1529
- *
1530
- * @param targetId Inbox target identifier.
1531
- * @param targetType Inbox target type.
1532
- * @returns Validated shard index.
1533
- */
1534
- shardFor(targetId, targetType) {
1535
- const shard = strategy.shardFor(InboxTargets.clone(targetId), targetType);
1536
- if (shard.ofTotal !== shardCount) {
1537
- throw new Error("Delivery strategy shard total must equal its resolved shard count.");
1538
- }
1539
- return new ShardIndex(shard.index, shard.ofTotal);
1540
- },
1541
- });
1542
- },
1543
2003
  /**
1544
2004
  * Creates the storage context for read-side catch-up.
1545
2005
  *
@@ -1718,8 +2178,7 @@ const ContextParts = Object.freeze({
1718
2178
  },
1719
2179
  });
1720
2180
  const ready = broker.open();
1721
- // Synchronous build returns before readiness; retain the failure for the next
1722
- // observable operation without letting Node report an unhandled rejection.
2181
+ // The builder awaits readiness; retain a rejection handler until it observes the result.
1723
2182
  void ready.catch(() => undefined);
1724
2183
  contextIntegrations.set(context, { broker, ready });
1725
2184
  },
@@ -1856,20 +2315,8 @@ const ContextParts = Object.freeze({
1856
2315
  */
1857
2316
  requireEntityClass(entityType, operation) {
1858
2317
  if (typeof entityType !== "function") {
1859
- throw new TypeError(`${operation} requires a Repository instance. Use an entity class only with buildAsync().`);
1860
- }
1861
- },
1862
- /**
1863
- * Rejects synchronous assembly when classes need generated metadata.
1864
- *
1865
- * @param entityTypes Entity classes to assemble.
1866
- */
1867
- rejectSyncEntityAssembly(entityTypes) {
1868
- if (entityTypes.size === 0) {
1869
- return;
2318
+ throw new TypeError(`${operation} requires a Repository instance. Use an entity class only with build().`);
1870
2319
  }
1871
- throw new Error("BoundedContextBuilder.build() cannot assemble entity classes from generated metadata. " +
1872
- "Use buildAsync().");
1873
2320
  },
1874
2321
  /**
1875
2322
  * Validates that a root exists when generated metadata must be loaded.
@@ -1881,7 +2328,7 @@ const ContextParts = Object.freeze({
1881
2328
  if (root !== undefined) {
1882
2329
  return root;
1883
2330
  }
1884
- throw new Error("BoundedContextBuilder.buildAsync() requires withGeneratedRegistryRoot(root) " +
2331
+ throw new Error("BoundedContextBuilder.build() requires withGeneratedRegistryRoot(root) " +
1885
2332
  "when assembling entity classes from generated metadata.");
1886
2333
  },
1887
2334
  /**
@@ -2273,16 +2720,6 @@ const ContextParts = Object.freeze({
2273
2720
  }
2274
2721
  return Object.freeze([...schemas.values()]);
2275
2722
  },
2276
- /**
2277
- * Clears metadata for a failed context build and closes its tenant index.
2278
- *
2279
- * @param context Context whose build failed.
2280
- * @param tenantIndex Tenant index to close.
2281
- */
2282
- cleanupFailedContext(context, tenantIndex) {
2283
- ContextParts.clearContextMetadata(context);
2284
- tenantIndex.close();
2285
- },
2286
2723
  /**
2287
2724
  * Removes runtime metadata associated with a context.
2288
2725
  *
@@ -2305,68 +2742,25 @@ const ContextParts = Object.freeze({
2305
2742
  contextStorageFactories.delete(context);
2306
2743
  contextDeliveryDescriptors.delete(context);
2307
2744
  contextSubscriptionRuntimes.delete(context);
2745
+ contextInputPreparations.delete(context);
2746
+ contextPreparations.delete(context);
2308
2747
  contextIntegrations.delete(context);
2309
2748
  eventSubscribers.delete(context);
2310
2749
  systemEventPosters.delete(context);
2311
2750
  },
2312
2751
  /**
2313
- * Creates delivery operations from the context inboxes and readiness state.
2752
+ * Creates delivery operations from the context inboxes.
2314
2753
  *
2315
- * @param context Built context snapshot.
2316
- * @param storageFactory Context storage provider.
2317
- * @param tenantIndex Tenant index for startup scopes.
2318
2754
  * @param entityInbox Registered Entity inbox.
2319
2755
  * @param projections Projection inbox.
2320
- * @param readiness Delivery readiness coordinator.
2321
2756
  * @returns Delivery descriptor.
2322
2757
  */
2323
- createDeliveryDescriptor(context, storageFactory, tenantIndex, entityInbox, projections, readiness) {
2758
+ createDeliveryDescriptor(entityInbox, projections) {
2324
2759
  return Object.freeze({
2325
- storageFactory,
2326
- startupScopes: () => ContextParts.deliveryStartupScopes(tenantIndex),
2327
- storageContext: (scope) => ContextParts.deliveryStorageContext(context, scope),
2328
2760
  endpoints: () => Object.freeze([...entityInbox.endpoints(), ...projections.endpoints()]),
2329
2761
  replay: (message, tenantId) => message.label === "UPDATE_SUBSCRIBER"
2330
2762
  ? projections.replay(message, tenantId)
2331
2763
  : entityInbox.replay(message, tenantId),
2332
- onReady: (onReady) => readiness.onReady(onReady),
2333
- transition: (scopes, onReady, options) => readiness.transition(scopes, onReady, options),
2334
- });
2335
- },
2336
- /**
2337
- * Lists delivery startup scopes, one per tenant in multitenant contexts.
2338
- *
2339
- * @param tenantIndex Tenant index supplying configured scopes.
2340
- * @returns Frozen startup scope list.
2341
- */
2342
- async deliveryStartupScopes(tenantIndex) {
2343
- if (tenantIndex.tenantMode === "single-tenant") {
2344
- return Object.freeze([Object.freeze({})]);
2345
- }
2346
- return Object.freeze((await tenantIndex.all()).map((tenantId) => Object.freeze({ tenantId })));
2347
- },
2348
- /**
2349
- * Creates tenant-validated storage context for a delivery scope.
2350
- *
2351
- * @param context Built context snapshot.
2352
- * @param scope Selected startup scope.
2353
- * @returns Storage context for the selected tenant.
2354
- */
2355
- deliveryStorageContext(context, scope) {
2356
- if (context.tenantMode === "single-tenant") {
2357
- if (scope.tenantId !== undefined) {
2358
- throw new Error(`Single-tenant context "${context.name.value}" does not accept tenantId.`);
2359
- }
2360
- return Object.freeze({ name: context.name.value, multitenant: false });
2361
- }
2362
- const tenantId = scope.tenantId;
2363
- if (tenantId === undefined) {
2364
- throw new Error(`Multitenant context "${context.name.value}" requires tenantId.`);
2365
- }
2366
- return Object.freeze({
2367
- name: context.name.value,
2368
- multitenant: true,
2369
- tenantId: TenantBoundary.from(tenantId).tenantId,
2370
2764
  });
2371
2765
  },
2372
2766
  /**
@@ -2466,7 +2860,7 @@ const ContextParts = Object.freeze({
2466
2860
  registeredRepositories.set(repository, { name: registration.name });
2467
2861
  },
2468
2862
  close: () => {
2469
- repositoryAccess.clearRuntime(repository);
2863
+ repositoryAccess.clearRuntimeIdle(repository);
2470
2864
  },
2471
2865
  };
2472
2866
  },
@@ -2480,6 +2874,7 @@ const ContextParts = Object.freeze({
2480
2874
  repositoryAccess.bindRuntime(repository, {
2481
2875
  context: registration.storageContext,
2482
2876
  storageFactory: registration.storageFactory,
2877
+ onAdmit: registration.onAdmit,
2483
2878
  ...(registration.ai === undefined ? {} : { ai: registration.ai }),
2484
2879
  stand: registration.stand,
2485
2880
  signalMetadata: new SignalMetadata(),
@@ -2488,13 +2883,12 @@ const ContextParts = Object.freeze({
2488
2883
  publisher: registration.publisher,
2489
2884
  registerEventSchema: registration.registerEventSchema,
2490
2885
  registerSystemEventSchema: registration.registerSystemEventSchema,
2491
- prepareSavedEvent: registration.prepareSavedEvent,
2492
- prepareSavedCommand: registration.prepareSavedCommand,
2493
- publishSavedEvent: registration.publishSavedEvent,
2494
- publishSavedCommand: registration.publishSavedCommand,
2886
+ publishAgentEvent: registration.publishAgentEvent,
2495
2887
  publishAgentSystemEvent: registration.publishAgentSystemEvent,
2496
- recordAcceptedSaved: registration.recordAcceptedSaved,
2497
- wakeAcceptedAgent: registration.wakeAcceptedAgent,
2888
+ agentReceipts: registration.agentReceipts,
2889
+ agentSignal: registration.agentSignal,
2890
+ reserveAgent: registration.reserveAgent,
2891
+ deferAgent: registration.deferAgent,
2498
2892
  });
2499
2893
  },
2500
2894
  /**
@@ -2616,7 +3010,7 @@ const ContextParts = Object.freeze({
2616
3010
  });
2617
3011
  }
2618
3012
  finally {
2619
- eventStore.close();
3013
+ await eventStore.close();
2620
3014
  }
2621
3015
  },
2622
3016
  /**