@zlink-systems/framework 0.10.0

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 (1121) hide show
  1. package/LICENSE +105 -0
  2. package/dist/.tsbuildinfo +1 -0
  3. package/dist/contracts/Actors/ZLinkActor.d.ts +7 -0
  4. package/dist/contracts/Actors/ZLinkActor.js +2 -0
  5. package/dist/contracts/Actors/ZLinkActorClient.d.ts +15 -0
  6. package/dist/contracts/Actors/ZLinkActorClient.js +2 -0
  7. package/dist/contracts/Actors/ZLinkActorContext.d.ts +14 -0
  8. package/dist/contracts/Actors/ZLinkActorContext.js +2 -0
  9. package/dist/contracts/Actors/ZLinkActorFactory.d.ts +34 -0
  10. package/dist/contracts/Actors/ZLinkActorFactory.js +2 -0
  11. package/dist/contracts/Actors/ZLinkActorManager.d.ts +34 -0
  12. package/dist/contracts/Actors/ZLinkActorManager.js +2 -0
  13. package/dist/contracts/Actors/index.d.ts +5 -0
  14. package/dist/contracts/Actors/index.js +21 -0
  15. package/dist/contracts/Channels/Calls.d.ts +28 -0
  16. package/dist/contracts/Channels/Calls.js +2 -0
  17. package/dist/contracts/Channels/IZLinkChannelClient.d.ts +5 -0
  18. package/dist/contracts/Channels/IZLinkChannelClient.js +2 -0
  19. package/dist/contracts/Channels/IZLinkFanoutClient.d.ts +11 -0
  20. package/dist/contracts/Channels/IZLinkFanoutClient.js +2 -0
  21. package/dist/contracts/Channels/RouteCalls.d.ts +11 -0
  22. package/dist/contracts/Channels/RouteCalls.js +2 -0
  23. package/dist/contracts/Channels/index.d.ts +4 -0
  24. package/dist/contracts/Channels/index.js +20 -0
  25. package/dist/contracts/Codecs/IZLinkCodecRegistryBuilder.d.ts +14 -0
  26. package/dist/contracts/Codecs/IZLinkCodecRegistryBuilder.js +2 -0
  27. package/dist/contracts/Codecs/ZLinkMessageSerializer.d.ts +5 -0
  28. package/dist/contracts/Codecs/ZLinkMessageSerializer.js +2 -0
  29. package/dist/contracts/Codecs/index.d.ts +2 -0
  30. package/dist/contracts/Codecs/index.js +18 -0
  31. package/dist/contracts/Common/ActorRef.d.ts +7 -0
  32. package/dist/contracts/Common/ActorRef.js +2 -0
  33. package/dist/contracts/Common/CoreTypes.d.ts +6 -0
  34. package/dist/contracts/Common/CoreTypes.js +2 -0
  35. package/dist/contracts/Common/Message.d.ts +9 -0
  36. package/dist/contracts/Common/Message.js +2 -0
  37. package/dist/contracts/Common/ZLinkEncodedPayload.d.ts +12 -0
  38. package/dist/contracts/Common/ZLinkEncodedPayload.js +41 -0
  39. package/dist/contracts/Common/ZLinkMessage.d.ts +25 -0
  40. package/dist/contracts/Common/ZLinkMessage.js +127 -0
  41. package/dist/contracts/Common/ZLinkMessageMetadata.d.ts +10 -0
  42. package/dist/contracts/Common/ZLinkMessageMetadata.js +49 -0
  43. package/dist/contracts/Common/ZLinkProviderResolver.d.ts +5 -0
  44. package/dist/contracts/Common/ZLinkProviderResolver.js +2 -0
  45. package/dist/contracts/Common/encoded-payload-storage.d.ts +3 -0
  46. package/dist/contracts/Common/encoded-payload-storage.js +18 -0
  47. package/dist/contracts/Common/index.d.ts +5 -0
  48. package/dist/contracts/Common/index.js +24 -0
  49. package/dist/contracts/Configuration/Builders.d.ts +153 -0
  50. package/dist/contracts/Configuration/Builders.js +2 -0
  51. package/dist/contracts/Configuration/CodecContentType.d.ts +2 -0
  52. package/dist/contracts/Configuration/CodecContentType.js +68 -0
  53. package/dist/contracts/Configuration/CodecSerializerSelection.d.ts +9 -0
  54. package/dist/contracts/Configuration/CodecSerializerSelection.js +15 -0
  55. package/dist/contracts/Configuration/Configs.d.ts +23 -0
  56. package/dist/contracts/Configuration/Configs.js +2 -0
  57. package/dist/contracts/Configuration/ConfigurationException.d.ts +3 -0
  58. package/dist/contracts/Configuration/ConfigurationException.js +10 -0
  59. package/dist/contracts/Configuration/Connections.d.ts +5 -0
  60. package/dist/contracts/Configuration/Connections.js +2 -0
  61. package/dist/contracts/Configuration/DiagnosticsValidation.d.ts +3 -0
  62. package/dist/contracts/Configuration/DiagnosticsValidation.js +23 -0
  63. package/dist/contracts/Configuration/EndpointNotation.d.ts +77 -0
  64. package/dist/contracts/Configuration/EndpointNotation.js +218 -0
  65. package/dist/contracts/Configuration/InternalDefaults.d.ts +7 -0
  66. package/dist/contracts/Configuration/InternalDefaults.js +47 -0
  67. package/dist/contracts/Configuration/ObjectRoles.d.ts +38 -0
  68. package/dist/contracts/Configuration/ObjectRoles.js +13 -0
  69. package/dist/contracts/Configuration/Registration.d.ts +11 -0
  70. package/dist/contracts/Configuration/Registration.js +162 -0
  71. package/dist/contracts/Configuration/RegistrationBuilderPolicy.d.ts +14 -0
  72. package/dist/contracts/Configuration/RegistrationBuilderPolicy.js +61 -0
  73. package/dist/contracts/Configuration/RegistrationBuilders.d.ts +61 -0
  74. package/dist/contracts/Configuration/RegistrationBuilders.js +1181 -0
  75. package/dist/contracts/Configuration/RegistrationCodecRegistry.d.ts +19 -0
  76. package/dist/contracts/Configuration/RegistrationCodecRegistry.js +79 -0
  77. package/dist/contracts/Configuration/RegistrationNormalizers.d.ts +23 -0
  78. package/dist/contracts/Configuration/RegistrationNormalizers.js +319 -0
  79. package/dist/contracts/Configuration/RegistrationTypes.d.ts +414 -0
  80. package/dist/contracts/Configuration/RegistrationTypes.js +2 -0
  81. package/dist/contracts/Configuration/RegistrationValidators.d.ts +2 -0
  82. package/dist/contracts/Configuration/RegistrationValidators.js +461 -0
  83. package/dist/contracts/Configuration/RouteChannelInternalState.d.ts +10 -0
  84. package/dist/contracts/Configuration/RouteChannelInternalState.js +39 -0
  85. package/dist/contracts/Configuration/RuntimeEndpointConnections.d.ts +9 -0
  86. package/dist/contracts/Configuration/RuntimeEndpointConnections.js +80 -0
  87. package/dist/contracts/Configuration/SendTimeoutValidation.d.ts +2 -0
  88. package/dist/contracts/Configuration/SendTimeoutValidation.js +16 -0
  89. package/dist/contracts/Configuration/TimerRegistrationValidator.d.ts +2 -0
  90. package/dist/contracts/Configuration/TimerRegistrationValidator.js +24 -0
  91. package/dist/contracts/Configuration/index.d.ts +5 -0
  92. package/dist/contracts/Configuration/index.js +18 -0
  93. package/dist/contracts/Dispatch/ZLinkDispatchOptions.d.ts +181 -0
  94. package/dist/contracts/Dispatch/ZLinkDispatchOptions.js +89 -0
  95. package/dist/contracts/Dispatch/ZLinkFlowOrigin.d.ts +1 -0
  96. package/dist/contracts/Dispatch/ZLinkFlowOrigin.js +2 -0
  97. package/dist/contracts/Dispatch/index.d.ts +2 -0
  98. package/dist/contracts/Dispatch/index.js +18 -0
  99. package/dist/contracts/Errors/ZLinkFrameworkException.d.ts +20 -0
  100. package/dist/contracts/Errors/ZLinkFrameworkException.js +29 -0
  101. package/dist/contracts/Errors/index.d.ts +1 -0
  102. package/dist/contracts/Errors/index.js +6 -0
  103. package/dist/contracts/Eventing/Metrics.d.ts +29 -0
  104. package/dist/contracts/Eventing/Metrics.js +4 -0
  105. package/dist/contracts/Eventing/index.d.ts +1 -0
  106. package/dist/contracts/Eventing/index.js +17 -0
  107. package/dist/contracts/Handlers/Attributes.d.ts +24 -0
  108. package/dist/contracts/Handlers/Attributes.js +84 -0
  109. package/dist/contracts/Handlers/Contexts.d.ts +18 -0
  110. package/dist/contracts/Handlers/Contexts.js +2 -0
  111. package/dist/contracts/Handlers/IZLinkChannelHandlers.d.ts +43 -0
  112. package/dist/contracts/Handlers/IZLinkChannelHandlers.js +2 -0
  113. package/dist/contracts/Handlers/IZLinkHandlerFilter.d.ts +15 -0
  114. package/dist/contracts/Handlers/IZLinkHandlerFilter.js +11 -0
  115. package/dist/contracts/Handlers/JsonContract.d.ts +46 -0
  116. package/dist/contracts/Handlers/JsonContract.js +137 -0
  117. package/dist/contracts/Handlers/ZLinkHandlerFilterNext.d.ts +1 -0
  118. package/dist/contracts/Handlers/ZLinkHandlerFilterNext.js +2 -0
  119. package/dist/contracts/Handlers/index.d.ts +5 -0
  120. package/dist/contracts/Handlers/index.js +33 -0
  121. package/dist/contracts/Locations/ActorTransfer.d.ts +41 -0
  122. package/dist/contracts/Locations/ActorTransfer.js +2 -0
  123. package/dist/contracts/Locations/Authority.d.ts +296 -0
  124. package/dist/contracts/Locations/Authority.js +17 -0
  125. package/dist/contracts/Locations/Diagnostics.d.ts +42 -0
  126. package/dist/contracts/Locations/Diagnostics.js +12 -0
  127. package/dist/contracts/Locations/Keys.d.ts +86 -0
  128. package/dist/contracts/Locations/Keys.js +2 -0
  129. package/dist/contracts/Locations/Models.d.ts +7 -0
  130. package/dist/contracts/Locations/Models.js +23 -0
  131. package/dist/contracts/Locations/Options.d.ts +23 -0
  132. package/dist/contracts/Locations/Options.js +20 -0
  133. package/dist/contracts/Locations/Readiness.d.ts +5 -0
  134. package/dist/contracts/Locations/Readiness.js +2 -0
  135. package/dist/contracts/Locations/RelocationStore.d.ts +38 -0
  136. package/dist/contracts/Locations/RelocationStore.js +2 -0
  137. package/dist/contracts/Locations/Resolvers.d.ts +4 -0
  138. package/dist/contracts/Locations/Resolvers.js +2 -0
  139. package/dist/contracts/Locations/Rows.d.ts +152 -0
  140. package/dist/contracts/Locations/Rows.js +19 -0
  141. package/dist/contracts/Locations/RuntimeQuery.d.ts +25 -0
  142. package/dist/contracts/Locations/RuntimeQuery.js +2 -0
  143. package/dist/contracts/Locations/Stores.d.ts +88 -0
  144. package/dist/contracts/Locations/Stores.js +2 -0
  145. package/dist/contracts/Locations/Values.d.ts +27 -0
  146. package/dist/contracts/Locations/Values.js +36 -0
  147. package/dist/contracts/Locations/Watch.d.ts +14 -0
  148. package/dist/contracts/Locations/Watch.js +12 -0
  149. package/dist/contracts/Locations/Writes.d.ts +48 -0
  150. package/dist/contracts/Locations/Writes.js +15 -0
  151. package/dist/contracts/Locations/index.d.ts +12 -0
  152. package/dist/contracts/Locations/index.js +30 -0
  153. package/dist/contracts/RouteMesh/Contracts.d.ts +102 -0
  154. package/dist/contracts/RouteMesh/Contracts.js +39 -0
  155. package/dist/contracts/RouteMesh/RuntimeTopology.d.ts +165 -0
  156. package/dist/contracts/RouteMesh/RuntimeTopology.js +38 -0
  157. package/dist/contracts/RouteMesh/index.d.ts +2 -0
  158. package/dist/contracts/RouteMesh/index.js +18 -0
  159. package/dist/contracts/Spots/Builders.d.ts +10 -0
  160. package/dist/contracts/Spots/Builders.js +2 -0
  161. package/dist/contracts/Spots/Contracts.d.ts +110 -0
  162. package/dist/contracts/Spots/Contracts.js +9 -0
  163. package/dist/contracts/Spots/SpotKind.d.ts +8 -0
  164. package/dist/contracts/Spots/SpotKind.js +28 -0
  165. package/dist/contracts/Spots/ZLinkSpot.d.ts +62 -0
  166. package/dist/contracts/Spots/ZLinkSpot.js +15 -0
  167. package/dist/contracts/Spots/index.d.ts +3 -0
  168. package/dist/contracts/Spots/index.js +19 -0
  169. package/dist/contracts/Streams/BoundSessionContracts.d.ts +8 -0
  170. package/dist/contracts/Streams/BoundSessionContracts.js +2 -0
  171. package/dist/contracts/Streams/IZLinkSession.d.ts +44 -0
  172. package/dist/contracts/Streams/IZLinkSession.js +2 -0
  173. package/dist/contracts/Streams/IZLinkSessionActor.d.ts +15 -0
  174. package/dist/contracts/Streams/IZLinkSessionActor.js +2 -0
  175. package/dist/contracts/Streams/IZLinkSessionPacketHandler.d.ts +9 -0
  176. package/dist/contracts/Streams/IZLinkSessionPacketHandler.js +2 -0
  177. package/dist/contracts/Streams/IZLinkStream.d.ts +9 -0
  178. package/dist/contracts/Streams/IZLinkStream.js +2 -0
  179. package/dist/contracts/Streams/ZLinkMessageMetadata.d.ts +1 -0
  180. package/dist/contracts/Streams/ZLinkMessageMetadata.js +2 -0
  181. package/dist/contracts/Streams/ZLinkStreamCompression.d.ts +8 -0
  182. package/dist/contracts/Streams/ZLinkStreamCompression.js +2 -0
  183. package/dist/contracts/Streams/ZLinkStreamError.d.ts +8 -0
  184. package/dist/contracts/Streams/ZLinkStreamError.js +8 -0
  185. package/dist/contracts/Streams/index.d.ts +8 -0
  186. package/dist/contracts/Streams/index.js +24 -0
  187. package/dist/contracts/Timers/IZLinkTimer.d.ts +5 -0
  188. package/dist/contracts/Timers/IZLinkTimer.js +2 -0
  189. package/dist/contracts/Timers/ZLinkTimerOptions.d.ts +10 -0
  190. package/dist/contracts/Timers/ZLinkTimerOptions.js +9 -0
  191. package/dist/contracts/Timers/ZLinkTimerTick.d.ts +12 -0
  192. package/dist/contracts/Timers/ZLinkTimerTick.js +2 -0
  193. package/dist/contracts/Timers/index.d.ts +3 -0
  194. package/dist/contracts/Timers/index.js +19 -0
  195. package/dist/contracts/index.d.ts +25 -0
  196. package/dist/contracts/index.js +45 -0
  197. package/dist/index.d.ts +1 -0
  198. package/dist/index.js +17 -0
  199. package/dist/internal.d.ts +26 -0
  200. package/dist/internal.js +48 -0
  201. package/dist/location-store-integration.d.ts +5 -0
  202. package/dist/location-store-integration.js +31 -0
  203. package/dist/nest-integration.d.ts +49 -0
  204. package/dist/nest-integration.js +143 -0
  205. package/dist/runtime/abort.d.ts +13 -0
  206. package/dist/runtime/abort.js +71 -0
  207. package/dist/runtime/actors/actor-authority-payload-codec.d.ts +33 -0
  208. package/dist/runtime/actors/actor-authority-payload-codec.js +366 -0
  209. package/dist/runtime/actors/actor-authority-publication.d.ts +28 -0
  210. package/dist/runtime/actors/actor-authority-publication.js +207 -0
  211. package/dist/runtime/actors/actor-client.d.ts +36 -0
  212. package/dist/runtime/actors/actor-client.js +612 -0
  213. package/dist/runtime/actors/actor-context.d.ts +26 -0
  214. package/dist/runtime/actors/actor-context.js +433 -0
  215. package/dist/runtime/actors/actor-creation.d.ts +19 -0
  216. package/dist/runtime/actors/actor-creation.js +158 -0
  217. package/dist/runtime/actors/actor-execution-context.d.ts +6 -0
  218. package/dist/runtime/actors/actor-execution-context.js +27 -0
  219. package/dist/runtime/actors/actor-handoff.d.ts +191 -0
  220. package/dist/runtime/actors/actor-handoff.js +1252 -0
  221. package/dist/runtime/actors/actor-join-deferred-scope.d.ts +11 -0
  222. package/dist/runtime/actors/actor-join-deferred-scope.js +144 -0
  223. package/dist/runtime/actors/actor-join-relocation.d.ts +38 -0
  224. package/dist/runtime/actors/actor-join-relocation.js +2 -0
  225. package/dist/runtime/actors/actor-lifecycle-snapshot.d.ts +21 -0
  226. package/dist/runtime/actors/actor-lifecycle-snapshot.js +58 -0
  227. package/dist/runtime/actors/actor-local-native-join.d.ts +27 -0
  228. package/dist/runtime/actors/actor-local-native-join.js +409 -0
  229. package/dist/runtime/actors/actor-mailbox.d.ts +10 -0
  230. package/dist/runtime/actors/actor-mailbox.js +53 -0
  231. package/dist/runtime/actors/actor-message-follow-context.d.ts +46 -0
  232. package/dist/runtime/actors/actor-message-follow-context.js +257 -0
  233. package/dist/runtime/actors/actor-native-lookup.d.ts +4 -0
  234. package/dist/runtime/actors/actor-native-lookup.js +30 -0
  235. package/dist/runtime/actors/actor-packet-relay-wire.d.ts +73 -0
  236. package/dist/runtime/actors/actor-packet-relay-wire.js +144 -0
  237. package/dist/runtime/actors/actor-remote-joiner.d.ts +37 -0
  238. package/dist/runtime/actors/actor-remote-joiner.js +122 -0
  239. package/dist/runtime/actors/actor-remote-wire.d.ts +73 -0
  240. package/dist/runtime/actors/actor-remote-wire.js +84 -0
  241. package/dist/runtime/actors/actor-retry-delay.d.ts +5 -0
  242. package/dist/runtime/actors/actor-retry-delay.js +40 -0
  243. package/dist/runtime/actors/actor-routed-join-transport.d.ts +33 -0
  244. package/dist/runtime/actors/actor-routed-join-transport.js +2 -0
  245. package/dist/runtime/actors/actor-routed-json-request.d.ts +11 -0
  246. package/dist/runtime/actors/actor-routed-json-request.js +39 -0
  247. package/dist/runtime/actors/actor-runtime-contracts.d.ts +63 -0
  248. package/dist/runtime/actors/actor-runtime-contracts.js +2 -0
  249. package/dist/runtime/actors/actor-runtime-state.d.ts +152 -0
  250. package/dist/runtime/actors/actor-runtime-state.js +545 -0
  251. package/dist/runtime/actors/actor-source-transfer.d.ts +27 -0
  252. package/dist/runtime/actors/actor-source-transfer.js +2 -0
  253. package/dist/runtime/actors/actor-transfer-registry.d.ts +18 -0
  254. package/dist/runtime/actors/actor-transfer-registry.js +71 -0
  255. package/dist/runtime/actors/actor-transport-delivery-gate.d.ts +6 -0
  256. package/dist/runtime/actors/actor-transport-delivery-gate.js +4 -0
  257. package/dist/runtime/actors/bound-session-wire.d.ts +81 -0
  258. package/dist/runtime/actors/bound-session-wire.js +184 -0
  259. package/dist/runtime/actors/deferred-join-accepted-journal.d.ts +47 -0
  260. package/dist/runtime/actors/deferred-join-accepted-journal.js +962 -0
  261. package/dist/runtime/actors/index.d.ts +79 -0
  262. package/dist/runtime/actors/index.js +639 -0
  263. package/dist/runtime/actors/post-commit-actor-binder.d.ts +18 -0
  264. package/dist/runtime/actors/post-commit-actor-binder.js +68 -0
  265. package/dist/runtime/actors/post-commit-actor-location.d.ts +19 -0
  266. package/dist/runtime/actors/post-commit-actor-location.js +72 -0
  267. package/dist/runtime/actors/spot-actor-dispatch.d.ts +59 -0
  268. package/dist/runtime/actors/spot-actor-dispatch.js +179 -0
  269. package/dist/runtime/actors/transferred-actor-rollback.d.ts +16 -0
  270. package/dist/runtime/actors/transferred-actor-rollback.js +91 -0
  271. package/dist/runtime/admission.d.ts +20 -0
  272. package/dist/runtime/admission.js +166 -0
  273. package/dist/runtime/application-jobs/application-ingress-record-owner.d.ts +57 -0
  274. package/dist/runtime/application-jobs/application-ingress-record-owner.js +185 -0
  275. package/dist/runtime/application-jobs/application-job-queue-handler-start-gate.d.ts +8 -0
  276. package/dist/runtime/application-jobs/application-job-queue-handler-start-gate.js +8 -0
  277. package/dist/runtime/application-jobs/application-job-queue-scope.d.ts +17 -0
  278. package/dist/runtime/application-jobs/application-job-queue-scope.js +57 -0
  279. package/dist/runtime/application-jobs/contracts.d.ts +19 -0
  280. package/dist/runtime/application-jobs/contracts.js +2 -0
  281. package/dist/runtime/application-jobs/receive-flow-controller.d.ts +32 -0
  282. package/dist/runtime/application-jobs/receive-flow-controller.js +165 -0
  283. package/dist/runtime/backend/contracts/index.d.ts +487 -0
  284. package/dist/runtime/backend/contracts/index.js +29 -0
  285. package/dist/runtime/backend/index.d.ts +9 -0
  286. package/dist/runtime/backend/index.js +25 -0
  287. package/dist/runtime/backend/mesh-actor-session-node-adapter.d.ts +3 -0
  288. package/dist/runtime/backend/mesh-actor-session-node-adapter.js +51 -0
  289. package/dist/runtime/backend/mesh-completion-table.d.ts +34 -0
  290. package/dist/runtime/backend/mesh-completion-table.js +124 -0
  291. package/dist/runtime/backend/mesh-dispatch-pump.d.ts +48 -0
  292. package/dist/runtime/backend/mesh-dispatch-pump.js +322 -0
  293. package/dist/runtime/backend/mesh-record-dispatcher.d.ts +19 -0
  294. package/dist/runtime/backend/mesh-record-dispatcher.js +53 -0
  295. package/dist/runtime/backend/node/index.d.ts +4 -0
  296. package/dist/runtime/backend/node/index.js +22 -0
  297. package/dist/runtime/backend/node/node-backend-adapter-factory.d.ts +12 -0
  298. package/dist/runtime/backend/node/node-backend-adapter-factory.js +161 -0
  299. package/dist/runtime/backend/node/node-backend-adapter-support.d.ts +52 -0
  300. package/dist/runtime/backend/node/node-backend-adapter-support.js +203 -0
  301. package/dist/runtime/backend/node/node-dealer-channel-client-transport.d.ts +13 -0
  302. package/dist/runtime/backend/node/node-dealer-channel-client-transport.js +52 -0
  303. package/dist/runtime/backend/node/node-mesh-backend-adapter.d.ts +11 -0
  304. package/dist/runtime/backend/node/node-mesh-backend-adapter.js +23 -0
  305. package/dist/runtime/backend/node/node-monitor-backend-adapter.d.ts +6 -0
  306. package/dist/runtime/backend/node/node-monitor-backend-adapter.js +38 -0
  307. package/dist/runtime/backend/node/node-raw-binding-port.d.ts +8 -0
  308. package/dist/runtime/backend/node/node-raw-binding-port.js +411 -0
  309. package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +266 -0
  310. package/dist/runtime/backend/node/node-raw-mesh-backend.js +1707 -0
  311. package/dist/runtime/backend/node/node-socket-backend-adapter.d.ts +9 -0
  312. package/dist/runtime/backend/node/node-socket-backend-adapter.js +286 -0
  313. package/dist/runtime/backend/node-backend-adapter.d.ts +9 -0
  314. package/dist/runtime/backend/node-backend-adapter.js +12 -0
  315. package/dist/runtime/backend/raw-binding-port.d.ts +58 -0
  316. package/dist/runtime/backend/raw-binding-port.js +2 -0
  317. package/dist/runtime/backend/runtime-message.d.ts +14 -0
  318. package/dist/runtime/backend/runtime-message.js +44 -0
  319. package/dist/runtime/backend/runtime-values.d.ts +78 -0
  320. package/dist/runtime/backend/runtime-values.js +66 -0
  321. package/dist/runtime/channels/channel-autoconnect.d.ts +14 -0
  322. package/dist/runtime/channels/channel-autoconnect.js +23 -0
  323. package/dist/runtime/channels/channel-clients.d.ts +50 -0
  324. package/dist/runtime/channels/channel-clients.js +329 -0
  325. package/dist/runtime/channels/channel-dispatch-pipeline.d.ts +76 -0
  326. package/dist/runtime/channels/channel-dispatch-pipeline.js +237 -0
  327. package/dist/runtime/channels/channel-dispatch-services.d.ts +52 -0
  328. package/dist/runtime/channels/channel-dispatch-services.js +132 -0
  329. package/dist/runtime/channels/channel-dispatchers.d.ts +125 -0
  330. package/dist/runtime/channels/channel-dispatchers.js +575 -0
  331. package/dist/runtime/channels/channel-envelope-inspection.d.ts +25 -0
  332. package/dist/runtime/channels/channel-envelope-inspection.js +96 -0
  333. package/dist/runtime/channels/channel-envelope.d.ts +73 -0
  334. package/dist/runtime/channels/channel-envelope.js +546 -0
  335. package/dist/runtime/channels/channel-framework-packets.d.ts +2 -0
  336. package/dist/runtime/channels/channel-framework-packets.js +6 -0
  337. package/dist/runtime/channels/channel-multipart.d.ts +16 -0
  338. package/dist/runtime/channels/channel-multipart.js +31 -0
  339. package/dist/runtime/channels/channel-outbound-operations.d.ts +33 -0
  340. package/dist/runtime/channels/channel-outbound-operations.js +343 -0
  341. package/dist/runtime/channels/channel-receive-loops.d.ts +151 -0
  342. package/dist/runtime/channels/channel-receive-loops.js +728 -0
  343. package/dist/runtime/channels/channel-receive-task-tracker.d.ts +14 -0
  344. package/dist/runtime/channels/channel-receive-task-tracker.js +37 -0
  345. package/dist/runtime/channels/channel-runtime-lifecycle.d.ts +77 -0
  346. package/dist/runtime/channels/channel-runtime-lifecycle.js +630 -0
  347. package/dist/runtime/channels/channel-runtime-manager.d.ts +84 -0
  348. package/dist/runtime/channels/channel-runtime-manager.js +193 -0
  349. package/dist/runtime/channels/channel-socket-options.d.ts +18 -0
  350. package/dist/runtime/channels/channel-socket-options.js +119 -0
  351. package/dist/runtime/channels/channel-socket-registry.d.ts +157 -0
  352. package/dist/runtime/channels/channel-socket-registry.js +1428 -0
  353. package/dist/runtime/channels/channel-transports.d.ts +126 -0
  354. package/dist/runtime/channels/channel-transports.js +448 -0
  355. package/dist/runtime/channels/client-server-location-runtime.d.ts +41 -0
  356. package/dist/runtime/channels/client-server-location-runtime.js +465 -0
  357. package/dist/runtime/channels/client-server-service-wire.d.ts +48 -0
  358. package/dist/runtime/channels/client-server-service-wire.js +306 -0
  359. package/dist/runtime/channels/dispatch-error-reporter.d.ts +22 -0
  360. package/dist/runtime/channels/dispatch-error-reporter.js +133 -0
  361. package/dist/runtime/channels/fanout-location-runtime.d.ts +38 -0
  362. package/dist/runtime/channels/fanout-location-runtime.js +356 -0
  363. package/dist/runtime/channels/fanout-service-wire.d.ts +12 -0
  364. package/dist/runtime/channels/fanout-service-wire.js +29 -0
  365. package/dist/runtime/channels/handler-filter-scope.d.ts +8 -0
  366. package/dist/runtime/channels/handler-filter-scope.js +11 -0
  367. package/dist/runtime/channels/index.d.ts +9 -0
  368. package/dist/runtime/channels/index.js +30 -0
  369. package/dist/runtime/channels/local-spot-route-transport.d.ts +9 -0
  370. package/dist/runtime/channels/local-spot-route-transport.js +40 -0
  371. package/dist/runtime/channels/route-disconnected-error.d.ts +3 -0
  372. package/dist/runtime/channels/route-disconnected-error.js +10 -0
  373. package/dist/runtime/channels/route-member-snapshot.d.ts +10 -0
  374. package/dist/runtime/channels/route-member-snapshot.js +55 -0
  375. package/dist/runtime/channels/router-socket-spot-route-transport.d.ts +12 -0
  376. package/dist/runtime/channels/router-socket-spot-route-transport.js +43 -0
  377. package/dist/runtime/channels/source-spot-router.d.ts +10 -0
  378. package/dist/runtime/channels/source-spot-router.js +46 -0
  379. package/dist/runtime/channels/spot-direct-envelope.d.ts +5 -0
  380. package/dist/runtime/channels/spot-direct-envelope.js +29 -0
  381. package/dist/runtime/channels/spot-node-route-transport.d.ts +13 -0
  382. package/dist/runtime/channels/spot-node-route-transport.js +60 -0
  383. package/dist/runtime/channels/spot-route-bridge-transport.d.ts +14 -0
  384. package/dist/runtime/channels/spot-route-bridge-transport.js +58 -0
  385. package/dist/runtime/channels/spot-route-dispatch-strategy.d.ts +50 -0
  386. package/dist/runtime/channels/spot-route-dispatch-strategy.js +128 -0
  387. package/dist/runtime/channels/spot-route-target-resolver.d.ts +16 -0
  388. package/dist/runtime/channels/spot-route-target-resolver.js +92 -0
  389. package/dist/runtime/codecs/index.d.ts +14 -0
  390. package/dist/runtime/codecs/index.js +44 -0
  391. package/dist/runtime/configuration/index.d.ts +1 -0
  392. package/dist/runtime/configuration/index.js +17 -0
  393. package/dist/runtime/diagnostics/dispatch-error-port.d.ts +8 -0
  394. package/dist/runtime/diagnostics/dispatch-error-port.js +2 -0
  395. package/dist/runtime/diagnostics/flow-context.d.ts +21 -0
  396. package/dist/runtime/diagnostics/flow-context.js +68 -0
  397. package/dist/runtime/diagnostics/index.d.ts +82 -0
  398. package/dist/runtime/diagnostics/index.js +335 -0
  399. package/dist/runtime/diagnostics/internal-event-contracts.d.ts +139 -0
  400. package/dist/runtime/diagnostics/internal-event-contracts.js +68 -0
  401. package/dist/runtime/diagnostics/message-flow.d.ts +55 -0
  402. package/dist/runtime/diagnostics/message-flow.js +420 -0
  403. package/dist/runtime/diagnostics/runtime-metrics.d.ts +123 -0
  404. package/dist/runtime/diagnostics/runtime-metrics.js +454 -0
  405. package/dist/runtime/diagnostics/runtime-observation-queue.d.ts +58 -0
  406. package/dist/runtime/diagnostics/runtime-observation-queue.js +324 -0
  407. package/dist/runtime/diagnostics/topology-runtime-projections.d.ts +33 -0
  408. package/dist/runtime/diagnostics/topology-runtime-projections.js +255 -0
  409. package/dist/runtime/execution/index.d.ts +114 -0
  410. package/dist/runtime/execution/index.js +363 -0
  411. package/dist/runtime/execution/serial-execution-queue.d.ts +94 -0
  412. package/dist/runtime/execution/serial-execution-queue.js +411 -0
  413. package/dist/runtime/execution/serial-work-size.d.ts +4 -0
  414. package/dist/runtime/execution/serial-work-size.js +28 -0
  415. package/dist/runtime/execution/state-lane.d.ts +28 -0
  416. package/dist/runtime/execution/state-lane.js +105 -0
  417. package/dist/runtime/foundation/actor-join-recovery-codec.d.ts +72 -0
  418. package/dist/runtime/foundation/actor-join-recovery-codec.js +333 -0
  419. package/dist/runtime/foundation/event-loop-resources.d.ts +37 -0
  420. package/dist/runtime/foundation/event-loop-resources.js +163 -0
  421. package/dist/runtime/foundation/index.d.ts +18 -0
  422. package/dist/runtime/foundation/index.js +34 -0
  423. package/dist/runtime/foundation/message-follow-suppression-registry.d.ts +38 -0
  424. package/dist/runtime/foundation/message-follow-suppression-registry.js +89 -0
  425. package/dist/runtime/foundation/operation-identity.d.ts +12 -0
  426. package/dist/runtime/foundation/operation-identity.js +33 -0
  427. package/dist/runtime/foundation/operation-registry.d.ts +42 -0
  428. package/dist/runtime/foundation/operation-registry.js +146 -0
  429. package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +143 -0
  430. package/dist/runtime/foundation/raw-service-mesh-runtime.js +1349 -0
  431. package/dist/runtime/foundation/route-mesh-connection-policy.d.ts +3 -0
  432. package/dist/runtime/foundation/route-mesh-connection-policy.js +13 -0
  433. package/dist/runtime/foundation/runtime-state-projections.d.ts +13 -0
  434. package/dist/runtime/foundation/runtime-state-projections.js +44 -0
  435. package/dist/runtime/foundation/service-authority-payload-codec.d.ts +56 -0
  436. package/dist/runtime/foundation/service-authority-payload-codec.js +411 -0
  437. package/dist/runtime/foundation/service-discovery-registry.d.ts +42 -0
  438. package/dist/runtime/foundation/service-discovery-registry.js +175 -0
  439. package/dist/runtime/foundation/service-instance-activation-recovery-codec.d.ts +19 -0
  440. package/dist/runtime/foundation/service-instance-activation-recovery-codec.js +287 -0
  441. package/dist/runtime/foundation/service-liveness-registry.d.ts +28 -0
  442. package/dist/runtime/foundation/service-liveness-registry.js +109 -0
  443. package/dist/runtime/foundation/service-mailbox.d.ts +60 -0
  444. package/dist/runtime/foundation/service-mailbox.js +283 -0
  445. package/dist/runtime/foundation/service-maintenance-runtime.d.ts +45 -0
  446. package/dist/runtime/foundation/service-maintenance-runtime.js +198 -0
  447. package/dist/runtime/foundation/service-metadata-codec.d.ts +2 -0
  448. package/dist/runtime/foundation/service-metadata-codec.js +69 -0
  449. package/dist/runtime/foundation/service-relocation-aggregate-committer.d.ts +35 -0
  450. package/dist/runtime/foundation/service-relocation-aggregate-committer.js +139 -0
  451. package/dist/runtime/foundation/service-relocation-coordinator.d.ts +19 -0
  452. package/dist/runtime/foundation/service-relocation-coordinator.js +16 -0
  453. package/dist/runtime/foundation/service-relocation-object-owner.d.ts +71 -0
  454. package/dist/runtime/foundation/service-relocation-object-owner.js +242 -0
  455. package/dist/runtime/foundation/service-relocation-runtime.d.ts +143 -0
  456. package/dist/runtime/foundation/service-relocation-runtime.js +1080 -0
  457. package/dist/runtime/foundation/service-runtime-contracts.d.ts +332 -0
  458. package/dist/runtime/foundation/service-runtime-contracts.js +66 -0
  459. package/dist/runtime/foundation/service-session-binding-ingress-port.d.ts +23 -0
  460. package/dist/runtime/foundation/service-session-binding-ingress-port.js +11 -0
  461. package/dist/runtime/foundation/service-stateful-registry.d.ts +142 -0
  462. package/dist/runtime/foundation/service-stateful-registry.js +465 -0
  463. package/dist/runtime/foundation/service-stateful-runtime.d.ts +393 -0
  464. package/dist/runtime/foundation/service-stateful-runtime.js +3898 -0
  465. package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +597 -0
  466. package/dist/runtime/foundation/service-stateful-wire-codec.js +2006 -0
  467. package/dist/runtime/foundation/service-topology-registry.d.ts +68 -0
  468. package/dist/runtime/foundation/service-topology-registry.js +393 -0
  469. package/dist/runtime/foundation/service-weighted-selection.d.ts +14 -0
  470. package/dist/runtime/foundation/service-weighted-selection.js +128 -0
  471. package/dist/runtime/foundation/service-wire-binary-primitives.d.ts +10 -0
  472. package/dist/runtime/foundation/service-wire-binary-primitives.js +53 -0
  473. package/dist/runtime/foundation/service-wire-codec.d.ts +22 -0
  474. package/dist/runtime/foundation/service-wire-codec.js +67 -0
  475. package/dist/runtime/foundation/service-wire-constants.generated.d.ts +110 -0
  476. package/dist/runtime/foundation/service-wire-constants.generated.js +132 -0
  477. package/dist/runtime/foundation/service-wire-m6a-codec.d.ts +102 -0
  478. package/dist/runtime/foundation/service-wire-m6a-codec.js +568 -0
  479. package/dist/runtime/framework-errors-internal.d.ts +95 -0
  480. package/dist/runtime/framework-errors-internal.js +301 -0
  481. package/dist/runtime/handlers/handler-instance-scope.d.ts +11 -0
  482. package/dist/runtime/handlers/handler-instance-scope.js +284 -0
  483. package/dist/runtime/handlers/index.d.ts +13 -0
  484. package/dist/runtime/handlers/index.js +57 -0
  485. package/dist/runtime/host/actor-packet-relay.d.ts +60 -0
  486. package/dist/runtime/host/actor-packet-relay.js +664 -0
  487. package/dist/runtime/host/actor-placement-coordinator.d.ts +32 -0
  488. package/dist/runtime/host/actor-placement-coordinator.js +386 -0
  489. package/dist/runtime/host/actor-runtime-options-factory.d.ts +65 -0
  490. package/dist/runtime/host/actor-runtime-options-factory.js +160 -0
  491. package/dist/runtime/host/actor-transfer-authority-runtime.d.ts +26 -0
  492. package/dist/runtime/host/actor-transfer-authority-runtime.js +138 -0
  493. package/dist/runtime/host/actor-transfer-runtime.d.ts +149 -0
  494. package/dist/runtime/host/actor-transfer-runtime.js +1245 -0
  495. package/dist/runtime/host/application-job-queue.d.ts +99 -0
  496. package/dist/runtime/host/application-job-queue.js +409 -0
  497. package/dist/runtime/host/bound-session-relay.d.ts +41 -0
  498. package/dist/runtime/host/bound-session-relay.js +52 -0
  499. package/dist/runtime/host/bounded-replay-map.d.ts +12 -0
  500. package/dist/runtime/host/bounded-replay-map.js +42 -0
  501. package/dist/runtime/host/channel-runtime-options-factory.d.ts +22 -0
  502. package/dist/runtime/host/channel-runtime-options-factory.js +76 -0
  503. package/dist/runtime/host/entry-actor-runtime.d.ts +30 -0
  504. package/dist/runtime/host/entry-actor-runtime.js +80 -0
  505. package/dist/runtime/host/host-capacity-status.d.ts +11 -0
  506. package/dist/runtime/host/host-capacity-status.js +85 -0
  507. package/dist/runtime/host/index.d.ts +188 -0
  508. package/dist/runtime/host/index.js +2552 -0
  509. package/dist/runtime/host/instance-activation-authority.d.ts +33 -0
  510. package/dist/runtime/host/instance-activation-authority.js +496 -0
  511. package/dist/runtime/host/location-runtime-owner.d.ts +48 -0
  512. package/dist/runtime/host/location-runtime-owner.js +227 -0
  513. package/dist/runtime/host/mesh-router-resolver.d.ts +16 -0
  514. package/dist/runtime/host/mesh-router-resolver.js +108 -0
  515. package/dist/runtime/host/relocation-direct-transfer.d.ts +81 -0
  516. package/dist/runtime/host/relocation-direct-transfer.js +240 -0
  517. package/dist/runtime/host/relocation-integrity-fault-gate.d.ts +6 -0
  518. package/dist/runtime/host/relocation-integrity-fault-gate.js +5 -0
  519. package/dist/runtime/host/relocation-state-adapter.d.ts +8 -0
  520. package/dist/runtime/host/relocation-state-adapter.js +13 -0
  521. package/dist/runtime/host/remote-actor-join-receiver.d.ts +47 -0
  522. package/dist/runtime/host/remote-actor-join-receiver.js +161 -0
  523. package/dist/runtime/host/remote-actor-packet-target-store.d.ts +29 -0
  524. package/dist/runtime/host/remote-actor-packet-target-store.js +185 -0
  525. package/dist/runtime/host/remote-bound-session-relay.d.ts +58 -0
  526. package/dist/runtime/host/remote-bound-session-relay.js +540 -0
  527. package/dist/runtime/host/route-mesh-runtime-options.d.ts +9 -0
  528. package/dist/runtime/host/route-mesh-runtime-options.js +41 -0
  529. package/dist/runtime/host/route-mesh-runtime.d.ts +76 -0
  530. package/dist/runtime/host/route-mesh-runtime.js +746 -0
  531. package/dist/runtime/host/runtime-shutdown.d.ts +33 -0
  532. package/dist/runtime/host/runtime-shutdown.js +68 -0
  533. package/dist/runtime/host/service-relocation-control.d.ts +7 -0
  534. package/dist/runtime/host/service-relocation-control.js +24 -0
  535. package/dist/runtime/host/service-relocation-host-runtime.d.ts +241 -0
  536. package/dist/runtime/host/service-relocation-host-runtime.js +4113 -0
  537. package/dist/runtime/host/spot-address-transport.d.ts +47 -0
  538. package/dist/runtime/host/spot-address-transport.js +601 -0
  539. package/dist/runtime/host/spot-node-runtime-options-factory.d.ts +38 -0
  540. package/dist/runtime/host/spot-node-runtime-options-factory.js +36 -0
  541. package/dist/runtime/host/spot-runtime-options-factory.d.ts +48 -0
  542. package/dist/runtime/host/spot-runtime-options-factory.js +169 -0
  543. package/dist/runtime/host/stateful-authority-route-runtime.d.ts +34 -0
  544. package/dist/runtime/host/stateful-authority-route-runtime.js +440 -0
  545. package/dist/runtime/host/user-spot-creation-coordinator.d.ts +69 -0
  546. package/dist/runtime/host/user-spot-creation-coordinator.js +759 -0
  547. package/dist/runtime/locations/actor-location-claims.d.ts +43 -0
  548. package/dist/runtime/locations/actor-location-claims.js +319 -0
  549. package/dist/runtime/locations/actor-session-route-claims.d.ts +10 -0
  550. package/dist/runtime/locations/actor-session-route-claims.js +51 -0
  551. package/dist/runtime/locations/aggregate-inventory-store.d.ts +18 -0
  552. package/dist/runtime/locations/aggregate-inventory-store.js +399 -0
  553. package/dist/runtime/locations/authority-key-codec.d.ts +6 -0
  554. package/dist/runtime/locations/authority-key-codec.js +78 -0
  555. package/dist/runtime/locations/auto-connect-loop.d.ts +37 -0
  556. package/dist/runtime/locations/auto-connect-loop.js +112 -0
  557. package/dist/runtime/locations/auto-connect-planner.d.ts +9 -0
  558. package/dist/runtime/locations/auto-connect-planner.js +137 -0
  559. package/dist/runtime/locations/auto-connect-reconciler.d.ts +57 -0
  560. package/dist/runtime/locations/auto-connect-reconciler.js +358 -0
  561. package/dist/runtime/locations/auto-connect-types.d.ts +42 -0
  562. package/dist/runtime/locations/auto-connect-types.js +2 -0
  563. package/dist/runtime/locations/auto-connect.d.ts +4 -0
  564. package/dist/runtime/locations/auto-connect.js +20 -0
  565. package/dist/runtime/locations/canonical-codec.d.ts +7 -0
  566. package/dist/runtime/locations/canonical-codec.js +48 -0
  567. package/dist/runtime/locations/domain-store-contract.d.ts +34 -0
  568. package/dist/runtime/locations/domain-store-contract.js +2 -0
  569. package/dist/runtime/locations/in-memory-authority-store.d.ts +51 -0
  570. package/dist/runtime/locations/in-memory-authority-store.js +895 -0
  571. package/dist/runtime/locations/in-memory-location-store.d.ts +78 -0
  572. package/dist/runtime/locations/in-memory-location-store.js +1008 -0
  573. package/dist/runtime/locations/in-memory-provider-location-store.d.ts +19 -0
  574. package/dist/runtime/locations/in-memory-provider-location-store.js +183 -0
  575. package/dist/runtime/locations/index.d.ts +11 -0
  576. package/dist/runtime/locations/index.js +27 -0
  577. package/dist/runtime/locations/internal-location-contracts.d.ts +7 -0
  578. package/dist/runtime/locations/internal-location-contracts.js +21 -0
  579. package/dist/runtime/locations/internal-store-contracts.d.ts +35 -0
  580. package/dist/runtime/locations/internal-store-contracts.js +2 -0
  581. package/dist/runtime/locations/key-codec.d.ts +13 -0
  582. package/dist/runtime/locations/key-codec.js +41 -0
  583. package/dist/runtime/locations/lease-tracker.d.ts +36 -0
  584. package/dist/runtime/locations/lease-tracker.js +155 -0
  585. package/dist/runtime/locations/lifecycle-runtime.d.ts +19 -0
  586. package/dist/runtime/locations/lifecycle-runtime.js +2 -0
  587. package/dist/runtime/locations/lifecycle.d.ts +40 -0
  588. package/dist/runtime/locations/lifecycle.js +120 -0
  589. package/dist/runtime/locations/location-store-repository.d.ts +72 -0
  590. package/dist/runtime/locations/location-store-repository.js +3198 -0
  591. package/dist/runtime/locations/relocation-blob.d.ts +7 -0
  592. package/dist/runtime/locations/relocation-blob.js +24 -0
  593. package/dist/runtime/locations/resolvers.d.ts +145 -0
  594. package/dist/runtime/locations/resolvers.js +693 -0
  595. package/dist/runtime/locations/runtime.d.ts +144 -0
  596. package/dist/runtime/locations/runtime.js +792 -0
  597. package/dist/runtime/locations/spot-location-claims.d.ts +36 -0
  598. package/dist/runtime/locations/spot-location-claims.js +305 -0
  599. package/dist/runtime/messaging/creation-payload-codec.d.ts +4 -0
  600. package/dist/runtime/messaging/creation-payload-codec.js +40 -0
  601. package/dist/runtime/messaging/framework-json-v1.d.ts +7 -0
  602. package/dist/runtime/messaging/framework-json-v1.js +296 -0
  603. package/dist/runtime/messaging/index.d.ts +1 -0
  604. package/dist/runtime/messaging/index.js +2 -0
  605. package/dist/runtime/messaging/packet-name.d.ts +4 -0
  606. package/dist/runtime/messaging/packet-name.js +79 -0
  607. package/dist/runtime/messaging/payload-codec.d.ts +25 -0
  608. package/dist/runtime/messaging/payload-codec.js +255 -0
  609. package/dist/runtime/messaging/submission-result.d.ts +15 -0
  610. package/dist/runtime/messaging/submission-result.js +37 -0
  611. package/dist/runtime/protocol/service_wire_pilot_codec.generated.d.ts +395 -0
  612. package/dist/runtime/protocol/service_wire_pilot_codec.generated.js +645 -0
  613. package/dist/runtime/routing-id.d.ts +8 -0
  614. package/dist/runtime/routing-id.js +112 -0
  615. package/dist/runtime/spots/formal-remote-actor-admission-registry.d.ts +124 -0
  616. package/dist/runtime/spots/formal-remote-actor-admission-registry.js +269 -0
  617. package/dist/runtime/spots/formal-remote-actor-transfer-registry.d.ts +33 -0
  618. package/dist/runtime/spots/formal-remote-actor-transfer-registry.js +94 -0
  619. package/dist/runtime/spots/index.d.ts +247 -0
  620. package/dist/runtime/spots/index.js +2090 -0
  621. package/dist/runtime/spots/spot-activation-registry.d.ts +47 -0
  622. package/dist/runtime/spots/spot-activation-registry.js +272 -0
  623. package/dist/runtime/spots/spot-activation-state.d.ts +104 -0
  624. package/dist/runtime/spots/spot-activation-state.js +288 -0
  625. package/dist/runtime/spots/spot-activation.d.ts +89 -0
  626. package/dist/runtime/spots/spot-activation.js +601 -0
  627. package/dist/runtime/spots/spot-actor-admission-coordinator.d.ts +20 -0
  628. package/dist/runtime/spots/spot-actor-admission-coordinator.js +194 -0
  629. package/dist/runtime/spots/spot-actor-join-dispatch.d.ts +83 -0
  630. package/dist/runtime/spots/spot-actor-join-dispatch.js +185 -0
  631. package/dist/runtime/spots/spot-actor-lifecycle-drain.d.ts +22 -0
  632. package/dist/runtime/spots/spot-actor-lifecycle-drain.js +51 -0
  633. package/dist/runtime/spots/spot-actor-membership.d.ts +39 -0
  634. package/dist/runtime/spots/spot-actor-membership.js +179 -0
  635. package/dist/runtime/spots/spot-actor-packet-dispatch.d.ts +91 -0
  636. package/dist/runtime/spots/spot-actor-packet-dispatch.js +315 -0
  637. package/dist/runtime/spots/spot-actor-packet-drain.d.ts +40 -0
  638. package/dist/runtime/spots/spot-actor-packet-drain.js +235 -0
  639. package/dist/runtime/spots/spot-actor-packet-relay-dispatch.d.ts +18 -0
  640. package/dist/runtime/spots/spot-actor-packet-relay-dispatch.js +110 -0
  641. package/dist/runtime/spots/spot-closing.d.ts +2 -0
  642. package/dist/runtime/spots/spot-closing.js +30 -0
  643. package/dist/runtime/spots/spot-context.d.ts +46 -0
  644. package/dist/runtime/spots/spot-context.js +113 -0
  645. package/dist/runtime/spots/spot-entry-activation.d.ts +107 -0
  646. package/dist/runtime/spots/spot-entry-activation.js +342 -0
  647. package/dist/runtime/spots/spot-handle.d.ts +28 -0
  648. package/dist/runtime/spots/spot-handle.js +38 -0
  649. package/dist/runtime/spots/spot-handler-registry.d.ts +52 -0
  650. package/dist/runtime/spots/spot-handler-registry.js +155 -0
  651. package/dist/runtime/spots/spot-lifecycle-metrics.d.ts +8 -0
  652. package/dist/runtime/spots/spot-lifecycle-metrics.js +16 -0
  653. package/dist/runtime/spots/spot-location-claim.d.ts +25 -0
  654. package/dist/runtime/spots/spot-location-claim.js +55 -0
  655. package/dist/runtime/spots/spot-manager-internal-contracts.d.ts +10 -0
  656. package/dist/runtime/spots/spot-manager-internal-contracts.js +2 -0
  657. package/dist/runtime/spots/spot-manager-public.d.ts +32 -0
  658. package/dist/runtime/spots/spot-manager-public.js +219 -0
  659. package/dist/runtime/spots/spot-native-actor-join-admission.d.ts +26 -0
  660. package/dist/runtime/spots/spot-native-actor-join-admission.js +105 -0
  661. package/dist/runtime/spots/spot-native-flags.d.ts +2 -0
  662. package/dist/runtime/spots/spot-native-flags.js +5 -0
  663. package/dist/runtime/spots/spot-node-autoconnect.d.ts +23 -0
  664. package/dist/runtime/spots/spot-node-autoconnect.js +246 -0
  665. package/dist/runtime/spots/spot-node-runtime-manager.d.ts +137 -0
  666. package/dist/runtime/spots/spot-node-runtime-manager.js +1111 -0
  667. package/dist/runtime/spots/spot-outbound.d.ts +78 -0
  668. package/dist/runtime/spots/spot-outbound.js +460 -0
  669. package/dist/runtime/spots/spot-provider.d.ts +4 -0
  670. package/dist/runtime/spots/spot-provider.js +28 -0
  671. package/dist/runtime/spots/spot-publisher-transport.d.ts +14 -0
  672. package/dist/runtime/spots/spot-publisher-transport.js +28 -0
  673. package/dist/runtime/spots/spot-remote-codec.d.ts +50 -0
  674. package/dist/runtime/spots/spot-remote-codec.js +190 -0
  675. package/dist/runtime/spots/spot-remote-route-codec.d.ts +47 -0
  676. package/dist/runtime/spots/spot-remote-route-codec.js +168 -0
  677. package/dist/runtime/spots/spot-route-packet-dispatch.d.ts +25 -0
  678. package/dist/runtime/spots/spot-route-packet-dispatch.js +238 -0
  679. package/dist/runtime/spots/spot-route-replies.d.ts +17 -0
  680. package/dist/runtime/spots/spot-route-replies.js +76 -0
  681. package/dist/runtime/spots/spot-route-reply-wire.d.ts +10 -0
  682. package/dist/runtime/spots/spot-route-reply-wire.js +6 -0
  683. package/dist/runtime/spots/spot-routed-actor-admission.d.ts +36 -0
  684. package/dist/runtime/spots/spot-routed-actor-admission.js +240 -0
  685. package/dist/runtime/spots/spot-routed-bound-session-dispatch.d.ts +19 -0
  686. package/dist/runtime/spots/spot-routed-bound-session-dispatch.js +46 -0
  687. package/dist/runtime/spots/spot-routed-frame-dispatch.d.ts +54 -0
  688. package/dist/runtime/spots/spot-routed-frame-dispatch.js +162 -0
  689. package/dist/runtime/spots/spot-routed-spot-packet-dispatch.d.ts +43 -0
  690. package/dist/runtime/spots/spot-routed-spot-packet-dispatch.js +152 -0
  691. package/dist/runtime/spots/spot-routing-internal.d.ts +28 -0
  692. package/dist/runtime/spots/spot-routing-internal.js +2 -0
  693. package/dist/runtime/spots/spot-runtime-ports.d.ts +64 -0
  694. package/dist/runtime/spots/spot-runtime-ports.js +2 -0
  695. package/dist/runtime/spots/spot-serial-executor.d.ts +38 -0
  696. package/dist/runtime/spots/spot-serial-executor.js +133 -0
  697. package/dist/runtime/spots/spot-serial-turn-executor.d.ts +54 -0
  698. package/dist/runtime/spots/spot-serial-turn-executor.js +219 -0
  699. package/dist/runtime/spots/spot-subscription-dispatch.d.ts +32 -0
  700. package/dist/runtime/spots/spot-subscription-dispatch.js +194 -0
  701. package/dist/runtime/spots/spot-timer.d.ts +110 -0
  702. package/dist/runtime/spots/spot-timer.js +419 -0
  703. package/dist/runtime/streams/actor-session-binding-registry.d.ts +193 -0
  704. package/dist/runtime/streams/actor-session-binding-registry.js +1127 -0
  705. package/dist/runtime/streams/actor-session-binding-runtime-owner.d.ts +20 -0
  706. package/dist/runtime/streams/actor-session-binding-runtime-owner.js +19 -0
  707. package/dist/runtime/streams/actor-session-lifecycle-coordinator.d.ts +4 -0
  708. package/dist/runtime/streams/actor-session-lifecycle-coordinator.js +24 -0
  709. package/dist/runtime/streams/bound-actor-relay-sender.d.ts +29 -0
  710. package/dist/runtime/streams/bound-actor-relay-sender.js +181 -0
  711. package/dist/runtime/streams/bound-session-response-target.d.ts +25 -0
  712. package/dist/runtime/streams/bound-session-response-target.js +54 -0
  713. package/dist/runtime/streams/bound-session-service.d.ts +48 -0
  714. package/dist/runtime/streams/bound-session-service.js +201 -0
  715. package/dist/runtime/streams/index.d.ts +152 -0
  716. package/dist/runtime/streams/index.js +338 -0
  717. package/dist/runtime/streams/managed-stream.d.ts +53 -0
  718. package/dist/runtime/streams/managed-stream.js +329 -0
  719. package/dist/runtime/streams/native-fallback-bound-session.d.ts +24 -0
  720. package/dist/runtime/streams/native-fallback-bound-session.js +201 -0
  721. package/dist/runtime/streams/protocol.d.ts +67 -0
  722. package/dist/runtime/streams/protocol.js +244 -0
  723. package/dist/runtime/streams/session-actor-coordinator.d.ts +56 -0
  724. package/dist/runtime/streams/session-actor-coordinator.js +371 -0
  725. package/dist/runtime/streams/session-calls.d.ts +59 -0
  726. package/dist/runtime/streams/session-calls.js +123 -0
  727. package/dist/runtime/streams/session-context.d.ts +108 -0
  728. package/dist/runtime/streams/session-context.js +377 -0
  729. package/dist/runtime/streams/session-local-actors.d.ts +10 -0
  730. package/dist/runtime/streams/session-local-actors.js +26 -0
  731. package/dist/runtime/streams/session-provider.d.ts +4 -0
  732. package/dist/runtime/streams/session-provider.js +30 -0
  733. package/dist/runtime/streams/session-requests.d.ts +25 -0
  734. package/dist/runtime/streams/session-requests.js +100 -0
  735. package/dist/runtime/streams/session-serial-executor.d.ts +12 -0
  736. package/dist/runtime/streams/session-serial-executor.js +58 -0
  737. package/dist/runtime/streams/stream-binding-runtime-ports.d.ts +62 -0
  738. package/dist/runtime/streams/stream-binding-runtime-ports.js +2 -0
  739. package/dist/runtime/streams/stream-frame-factory.d.ts +44 -0
  740. package/dist/runtime/streams/stream-frame-factory.js +149 -0
  741. package/dist/runtime/streams/stream-message-utils.d.ts +5 -0
  742. package/dist/runtime/streams/stream-message-utils.js +74 -0
  743. package/dist/runtime/streams/stream-session-runtime.d.ts +166 -0
  744. package/dist/runtime/streams/stream-session-runtime.js +1144 -0
  745. package/dist/runtime/workers/index.d.ts +38 -0
  746. package/dist/runtime/workers/index.js +474 -0
  747. package/package.json +19 -0
  748. package/src/contracts/Actors/ZLinkActor.ts +8 -0
  749. package/src/contracts/Actors/ZLinkActorClient.ts +18 -0
  750. package/src/contracts/Actors/ZLinkActorContext.ts +15 -0
  751. package/src/contracts/Actors/ZLinkActorFactory.ts +41 -0
  752. package/src/contracts/Actors/ZLinkActorManager.ts +31 -0
  753. package/src/contracts/Actors/index.ts +5 -0
  754. package/src/contracts/Channels/Calls.ts +33 -0
  755. package/src/contracts/Channels/IZLinkChannelClient.ts +6 -0
  756. package/src/contracts/Channels/IZLinkFanoutClient.ts +13 -0
  757. package/src/contracts/Channels/RouteCalls.ts +13 -0
  758. package/src/contracts/Channels/index.ts +4 -0
  759. package/src/contracts/Codecs/IZLinkCodecRegistryBuilder.ts +22 -0
  760. package/src/contracts/Codecs/ZLinkMessageSerializer.ts +6 -0
  761. package/src/contracts/Codecs/index.ts +2 -0
  762. package/src/contracts/Common/ActorRef.ts +8 -0
  763. package/src/contracts/Common/CoreTypes.ts +6 -0
  764. package/src/contracts/Common/Message.ts +9 -0
  765. package/src/contracts/Common/ZLinkEncodedPayload.ts +47 -0
  766. package/src/contracts/Common/ZLinkMessage.ts +135 -0
  767. package/src/contracts/Common/ZLinkMessageMetadata.ts +77 -0
  768. package/src/contracts/Common/ZLinkProviderResolver.ts +6 -0
  769. package/src/contracts/Common/encoded-payload-storage.ts +16 -0
  770. package/src/contracts/Common/index.ts +5 -0
  771. package/src/contracts/Configuration/Builders.ts +200 -0
  772. package/src/contracts/Configuration/CodecContentType.ts +68 -0
  773. package/src/contracts/Configuration/CodecSerializerSelection.ts +28 -0
  774. package/src/contracts/Configuration/Configs.ts +27 -0
  775. package/src/contracts/Configuration/ConfigurationException.ts +6 -0
  776. package/src/contracts/Configuration/Connections.ts +5 -0
  777. package/src/contracts/Configuration/DiagnosticsValidation.ts +25 -0
  778. package/src/contracts/Configuration/EndpointNotation.ts +232 -0
  779. package/src/contracts/Configuration/InternalDefaults.ts +13 -0
  780. package/src/contracts/Configuration/ObjectRoles.ts +47 -0
  781. package/src/contracts/Configuration/Registration.ts +191 -0
  782. package/src/contracts/Configuration/RegistrationBuilderPolicy.ts +76 -0
  783. package/src/contracts/Configuration/RegistrationBuilders.ts +1705 -0
  784. package/src/contracts/Configuration/RegistrationCodecRegistry.ts +118 -0
  785. package/src/contracts/Configuration/RegistrationNormalizers.ts +404 -0
  786. package/src/contracts/Configuration/RegistrationTypes.ts +499 -0
  787. package/src/contracts/Configuration/RegistrationValidators.ts +698 -0
  788. package/src/contracts/Configuration/RouteChannelInternalState.ts +50 -0
  789. package/src/contracts/Configuration/RuntimeEndpointConnections.ts +91 -0
  790. package/src/contracts/Configuration/SendTimeoutValidation.ts +15 -0
  791. package/src/contracts/Configuration/TimerRegistrationValidator.ts +37 -0
  792. package/src/contracts/Configuration/index.ts +35 -0
  793. package/src/contracts/Dispatch/ZLinkDispatchOptions.ts +222 -0
  794. package/src/contracts/Dispatch/ZLinkFlowOrigin.ts +1 -0
  795. package/src/contracts/Dispatch/index.ts +2 -0
  796. package/src/contracts/Errors/ZLinkFrameworkException.ts +27 -0
  797. package/src/contracts/Errors/index.ts +4 -0
  798. package/src/contracts/Eventing/Metrics.ts +27 -0
  799. package/src/contracts/Eventing/index.ts +1 -0
  800. package/src/contracts/Handlers/Attributes.ts +111 -0
  801. package/src/contracts/Handlers/Contexts.ts +21 -0
  802. package/src/contracts/Handlers/IZLinkChannelHandlers.ts +69 -0
  803. package/src/contracts/Handlers/IZLinkHandlerFilter.ts +22 -0
  804. package/src/contracts/Handlers/JsonContract.ts +172 -0
  805. package/src/contracts/Handlers/ZLinkHandlerFilterNext.ts +1 -0
  806. package/src/contracts/Handlers/index.ts +17 -0
  807. package/src/contracts/Locations/ActorTransfer.ts +84 -0
  808. package/src/contracts/Locations/Authority.ts +308 -0
  809. package/src/contracts/Locations/Diagnostics.ts +48 -0
  810. package/src/contracts/Locations/Keys.ts +93 -0
  811. package/src/contracts/Locations/Models.ts +7 -0
  812. package/src/contracts/Locations/Options.ts +42 -0
  813. package/src/contracts/Locations/Readiness.ts +11 -0
  814. package/src/contracts/Locations/RelocationStore.ts +51 -0
  815. package/src/contracts/Locations/Resolvers.ts +8 -0
  816. package/src/contracts/Locations/Rows.ts +164 -0
  817. package/src/contracts/Locations/RuntimeQuery.ts +56 -0
  818. package/src/contracts/Locations/Stores.ts +92 -0
  819. package/src/contracts/Locations/Values.ts +32 -0
  820. package/src/contracts/Locations/Watch.ts +16 -0
  821. package/src/contracts/Locations/Writes.ts +56 -0
  822. package/src/contracts/Locations/index.ts +48 -0
  823. package/src/contracts/RouteMesh/Contracts.ts +145 -0
  824. package/src/contracts/RouteMesh/RuntimeTopology.ts +201 -0
  825. package/src/contracts/RouteMesh/index.ts +2 -0
  826. package/src/contracts/Spots/Builders.ts +11 -0
  827. package/src/contracts/Spots/Contracts.ts +150 -0
  828. package/src/contracts/Spots/SpotKind.ts +24 -0
  829. package/src/contracts/Spots/ZLinkSpot.ts +88 -0
  830. package/src/contracts/Spots/index.ts +3 -0
  831. package/src/contracts/Streams/BoundSessionContracts.ts +9 -0
  832. package/src/contracts/Streams/IZLinkSession.ts +52 -0
  833. package/src/contracts/Streams/IZLinkSessionActor.ts +17 -0
  834. package/src/contracts/Streams/IZLinkSessionPacketHandler.ts +11 -0
  835. package/src/contracts/Streams/IZLinkStream.ts +10 -0
  836. package/src/contracts/Streams/ZLinkMessageMetadata.ts +1 -0
  837. package/src/contracts/Streams/ZLinkStreamCompression.ts +9 -0
  838. package/src/contracts/Streams/ZLinkStreamError.ts +9 -0
  839. package/src/contracts/Streams/index.ts +8 -0
  840. package/src/contracts/Timers/IZLinkTimer.ts +5 -0
  841. package/src/contracts/Timers/ZLinkTimerOptions.ts +11 -0
  842. package/src/contracts/Timers/ZLinkTimerTick.ts +12 -0
  843. package/src/contracts/Timers/index.ts +3 -0
  844. package/src/contracts/index.ts +71 -0
  845. package/src/index.ts +1 -0
  846. package/src/internal.ts +29 -0
  847. package/src/location-store-integration.ts +51 -0
  848. package/src/nest-integration.ts +251 -0
  849. package/src/runtime/abort.ts +70 -0
  850. package/src/runtime/actors/actor-authority-payload-codec.ts +454 -0
  851. package/src/runtime/actors/actor-authority-publication.ts +277 -0
  852. package/src/runtime/actors/actor-client.ts +1018 -0
  853. package/src/runtime/actors/actor-context.ts +583 -0
  854. package/src/runtime/actors/actor-creation.ts +254 -0
  855. package/src/runtime/actors/actor-execution-context.ts +38 -0
  856. package/src/runtime/actors/actor-handoff.ts +1911 -0
  857. package/src/runtime/actors/actor-join-deferred-scope.ts +183 -0
  858. package/src/runtime/actors/actor-join-relocation.ts +39 -0
  859. package/src/runtime/actors/actor-lifecycle-snapshot.ts +90 -0
  860. package/src/runtime/actors/actor-local-native-join.ts +725 -0
  861. package/src/runtime/actors/actor-mailbox.ts +92 -0
  862. package/src/runtime/actors/actor-message-follow-context.ts +347 -0
  863. package/src/runtime/actors/actor-native-lookup.ts +38 -0
  864. package/src/runtime/actors/actor-packet-relay-wire.ts +223 -0
  865. package/src/runtime/actors/actor-remote-joiner.ts +238 -0
  866. package/src/runtime/actors/actor-remote-wire.ts +169 -0
  867. package/src/runtime/actors/actor-retry-delay.ts +37 -0
  868. package/src/runtime/actors/actor-routed-join-transport.ts +58 -0
  869. package/src/runtime/actors/actor-routed-json-request.ts +44 -0
  870. package/src/runtime/actors/actor-runtime-contracts.ts +126 -0
  871. package/src/runtime/actors/actor-runtime-state.ts +805 -0
  872. package/src/runtime/actors/actor-source-transfer.ts +62 -0
  873. package/src/runtime/actors/actor-transfer-registry.ts +112 -0
  874. package/src/runtime/actors/actor-transport-delivery-gate.ts +17 -0
  875. package/src/runtime/actors/bound-session-wire.ts +257 -0
  876. package/src/runtime/actors/deferred-join-accepted-journal.ts +1319 -0
  877. package/src/runtime/actors/index.ts +972 -0
  878. package/src/runtime/actors/post-commit-actor-binder.ts +70 -0
  879. package/src/runtime/actors/post-commit-actor-location.ts +114 -0
  880. package/src/runtime/actors/spot-actor-dispatch.ts +362 -0
  881. package/src/runtime/actors/transferred-actor-rollback.ts +123 -0
  882. package/src/runtime/admission.ts +192 -0
  883. package/src/runtime/application-jobs/application-ingress-record-owner.ts +216 -0
  884. package/src/runtime/application-jobs/application-job-queue-handler-start-gate.ts +10 -0
  885. package/src/runtime/application-jobs/application-job-queue-scope.ts +64 -0
  886. package/src/runtime/application-jobs/contracts.ts +26 -0
  887. package/src/runtime/application-jobs/receive-flow-controller.ts +188 -0
  888. package/src/runtime/backend/contracts/index.ts +765 -0
  889. package/src/runtime/backend/index.ts +9 -0
  890. package/src/runtime/backend/mesh-actor-session-node-adapter.ts +73 -0
  891. package/src/runtime/backend/mesh-completion-table.ts +165 -0
  892. package/src/runtime/backend/mesh-dispatch-pump.ts +363 -0
  893. package/src/runtime/backend/mesh-record-dispatcher.ts +65 -0
  894. package/src/runtime/backend/node/index.ts +4 -0
  895. package/src/runtime/backend/node/node-backend-adapter-factory.ts +204 -0
  896. package/src/runtime/backend/node/node-backend-adapter-support.ts +257 -0
  897. package/src/runtime/backend/node/node-dealer-channel-client-transport.ts +133 -0
  898. package/src/runtime/backend/node/node-mesh-backend-adapter.ts +44 -0
  899. package/src/runtime/backend/node/node-monitor-backend-adapter.ts +39 -0
  900. package/src/runtime/backend/node/node-raw-binding-port.contract.ts +21 -0
  901. package/src/runtime/backend/node/node-raw-binding-port.ts +518 -0
  902. package/src/runtime/backend/node/node-raw-mesh-backend.ts +2669 -0
  903. package/src/runtime/backend/node/node-socket-backend-adapter.ts +372 -0
  904. package/src/runtime/backend/node-backend-adapter.ts +19 -0
  905. package/src/runtime/backend/raw-binding-port.ts +69 -0
  906. package/src/runtime/backend/runtime-message.ts +51 -0
  907. package/src/runtime/backend/runtime-values.ts +107 -0
  908. package/src/runtime/channels/channel-autoconnect.ts +46 -0
  909. package/src/runtime/channels/channel-clients.ts +527 -0
  910. package/src/runtime/channels/channel-dispatch-pipeline.ts +408 -0
  911. package/src/runtime/channels/channel-dispatch-services.ts +234 -0
  912. package/src/runtime/channels/channel-dispatchers.ts +790 -0
  913. package/src/runtime/channels/channel-envelope-inspection.ts +125 -0
  914. package/src/runtime/channels/channel-envelope.ts +743 -0
  915. package/src/runtime/channels/channel-framework-packets.ts +8 -0
  916. package/src/runtime/channels/channel-multipart.ts +61 -0
  917. package/src/runtime/channels/channel-outbound-operations.ts +584 -0
  918. package/src/runtime/channels/channel-receive-loops.ts +901 -0
  919. package/src/runtime/channels/channel-receive-task-tracker.ts +39 -0
  920. package/src/runtime/channels/channel-runtime-lifecycle.ts +969 -0
  921. package/src/runtime/channels/channel-runtime-manager.ts +444 -0
  922. package/src/runtime/channels/channel-socket-options.ts +153 -0
  923. package/src/runtime/channels/channel-socket-registry.ts +1837 -0
  924. package/src/runtime/channels/channel-transports.ts +1154 -0
  925. package/src/runtime/channels/client-server-location-runtime.ts +576 -0
  926. package/src/runtime/channels/client-server-service-wire.ts +390 -0
  927. package/src/runtime/channels/dispatch-error-reporter.ts +165 -0
  928. package/src/runtime/channels/fanout-location-runtime.ts +459 -0
  929. package/src/runtime/channels/fanout-service-wire.ts +43 -0
  930. package/src/runtime/channels/handler-filter-scope.ts +29 -0
  931. package/src/runtime/channels/index.ts +45 -0
  932. package/src/runtime/channels/local-spot-route-transport.ts +59 -0
  933. package/src/runtime/channels/route-disconnected-error.ts +6 -0
  934. package/src/runtime/channels/route-member-snapshot.ts +55 -0
  935. package/src/runtime/channels/router-socket-spot-route-transport.ts +77 -0
  936. package/src/runtime/channels/source-spot-router.ts +89 -0
  937. package/src/runtime/channels/spot-direct-envelope.ts +44 -0
  938. package/src/runtime/channels/spot-node-route-transport.ts +92 -0
  939. package/src/runtime/channels/spot-route-bridge-transport.ts +75 -0
  940. package/src/runtime/channels/spot-route-dispatch-strategy.ts +329 -0
  941. package/src/runtime/channels/spot-route-target-resolver.ts +101 -0
  942. package/src/runtime/codecs/index.ts +69 -0
  943. package/src/runtime/configuration/index.ts +1 -0
  944. package/src/runtime/diagnostics/dispatch-error-port.ts +8 -0
  945. package/src/runtime/diagnostics/flow-context.ts +84 -0
  946. package/src/runtime/diagnostics/index.ts +441 -0
  947. package/src/runtime/diagnostics/internal-event-contracts.ts +135 -0
  948. package/src/runtime/diagnostics/message-flow.ts +560 -0
  949. package/src/runtime/diagnostics/runtime-metrics.ts +601 -0
  950. package/src/runtime/diagnostics/runtime-observation-queue.ts +362 -0
  951. package/src/runtime/diagnostics/topology-runtime-projections.ts +298 -0
  952. package/src/runtime/execution/index.ts +466 -0
  953. package/src/runtime/execution/serial-execution-queue.ts +534 -0
  954. package/src/runtime/execution/serial-work-size.ts +31 -0
  955. package/src/runtime/execution/state-lane.ts +116 -0
  956. package/src/runtime/foundation/actor-join-recovery-codec.ts +465 -0
  957. package/src/runtime/foundation/event-loop-resources.ts +162 -0
  958. package/src/runtime/foundation/index.ts +18 -0
  959. package/src/runtime/foundation/message-follow-suppression-registry.ts +130 -0
  960. package/src/runtime/foundation/operation-identity.ts +49 -0
  961. package/src/runtime/foundation/operation-registry.ts +162 -0
  962. package/src/runtime/foundation/raw-service-mesh-runtime.ts +1771 -0
  963. package/src/runtime/foundation/route-mesh-connection-policy.ts +28 -0
  964. package/src/runtime/foundation/runtime-state-projections.ts +68 -0
  965. package/src/runtime/foundation/service-authority-payload-codec.ts +566 -0
  966. package/src/runtime/foundation/service-discovery-registry.ts +263 -0
  967. package/src/runtime/foundation/service-instance-activation-recovery-codec.ts +329 -0
  968. package/src/runtime/foundation/service-liveness-registry.ts +144 -0
  969. package/src/runtime/foundation/service-mailbox.ts +369 -0
  970. package/src/runtime/foundation/service-maintenance-runtime.ts +242 -0
  971. package/src/runtime/foundation/service-metadata-codec.ts +75 -0
  972. package/src/runtime/foundation/service-relocation-aggregate-committer.ts +218 -0
  973. package/src/runtime/foundation/service-relocation-coordinator.ts +37 -0
  974. package/src/runtime/foundation/service-relocation-object-owner.ts +428 -0
  975. package/src/runtime/foundation/service-relocation-runtime.ts +1407 -0
  976. package/src/runtime/foundation/service-runtime-contracts.ts +423 -0
  977. package/src/runtime/foundation/service-session-binding-ingress-port.ts +45 -0
  978. package/src/runtime/foundation/service-stateful-registry.ts +664 -0
  979. package/src/runtime/foundation/service-stateful-runtime.ts +5753 -0
  980. package/src/runtime/foundation/service-stateful-wire-codec.ts +3008 -0
  981. package/src/runtime/foundation/service-topology-registry.ts +599 -0
  982. package/src/runtime/foundation/service-weighted-selection.ts +166 -0
  983. package/src/runtime/foundation/service-wire-binary-primitives.ts +80 -0
  984. package/src/runtime/foundation/service-wire-codec.ts +91 -0
  985. package/src/runtime/foundation/service-wire-constants.generated.ts +131 -0
  986. package/src/runtime/foundation/service-wire-m6a-codec.ts +647 -0
  987. package/src/runtime/framework-errors-internal.ts +338 -0
  988. package/src/runtime/handlers/handler-instance-scope.ts +372 -0
  989. package/src/runtime/handlers/index.ts +93 -0
  990. package/src/runtime/host/actor-packet-relay.ts +1070 -0
  991. package/src/runtime/host/actor-placement-coordinator.ts +573 -0
  992. package/src/runtime/host/actor-runtime-options-factory.ts +282 -0
  993. package/src/runtime/host/actor-transfer-authority-runtime.ts +225 -0
  994. package/src/runtime/host/actor-transfer-runtime.ts +1958 -0
  995. package/src/runtime/host/application-job-queue.ts +518 -0
  996. package/src/runtime/host/bound-session-relay.ts +94 -0
  997. package/src/runtime/host/bounded-replay-map.ts +42 -0
  998. package/src/runtime/host/channel-runtime-options-factory.ts +104 -0
  999. package/src/runtime/host/entry-actor-runtime.ts +115 -0
  1000. package/src/runtime/host/host-capacity-status.ts +103 -0
  1001. package/src/runtime/host/index.ts +3492 -0
  1002. package/src/runtime/host/instance-activation-authority.ts +658 -0
  1003. package/src/runtime/host/location-runtime-owner.ts +313 -0
  1004. package/src/runtime/host/mesh-router-resolver.ts +114 -0
  1005. package/src/runtime/host/relocation-direct-transfer.ts +273 -0
  1006. package/src/runtime/host/relocation-integrity-fault-gate.ts +8 -0
  1007. package/src/runtime/host/relocation-state-adapter.ts +24 -0
  1008. package/src/runtime/host/remote-actor-join-receiver.ts +264 -0
  1009. package/src/runtime/host/remote-actor-packet-target-store.ts +244 -0
  1010. package/src/runtime/host/remote-bound-session-relay.ts +900 -0
  1011. package/src/runtime/host/route-mesh-runtime-options.ts +46 -0
  1012. package/src/runtime/host/route-mesh-runtime.ts +891 -0
  1013. package/src/runtime/host/runtime-shutdown.ts +101 -0
  1014. package/src/runtime/host/service-relocation-control.ts +28 -0
  1015. package/src/runtime/host/service-relocation-host-runtime.ts +5817 -0
  1016. package/src/runtime/host/spot-address-transport.ts +997 -0
  1017. package/src/runtime/host/spot-node-runtime-options-factory.ts +82 -0
  1018. package/src/runtime/host/spot-runtime-options-factory.ts +286 -0
  1019. package/src/runtime/host/stateful-authority-route-runtime.ts +662 -0
  1020. package/src/runtime/host/user-spot-creation-coordinator.ts +1176 -0
  1021. package/src/runtime/locations/actor-location-claims.ts +426 -0
  1022. package/src/runtime/locations/actor-session-route-claims.ts +64 -0
  1023. package/src/runtime/locations/aggregate-inventory-store.ts +581 -0
  1024. package/src/runtime/locations/authority-key-codec.ts +80 -0
  1025. package/src/runtime/locations/auto-connect-loop.ts +131 -0
  1026. package/src/runtime/locations/auto-connect-planner.ts +178 -0
  1027. package/src/runtime/locations/auto-connect-reconciler.ts +425 -0
  1028. package/src/runtime/locations/auto-connect-types.ts +62 -0
  1029. package/src/runtime/locations/auto-connect.ts +4 -0
  1030. package/src/runtime/locations/canonical-codec.ts +54 -0
  1031. package/src/runtime/locations/domain-store-contract.ts +149 -0
  1032. package/src/runtime/locations/in-memory-authority-store.ts +1172 -0
  1033. package/src/runtime/locations/in-memory-location-store.ts +1467 -0
  1034. package/src/runtime/locations/in-memory-provider-location-store.ts +213 -0
  1035. package/src/runtime/locations/index.ts +11 -0
  1036. package/src/runtime/locations/internal-location-contracts.ts +22 -0
  1037. package/src/runtime/locations/internal-store-contracts.ts +90 -0
  1038. package/src/runtime/locations/key-codec.ts +61 -0
  1039. package/src/runtime/locations/lease-tracker.ts +221 -0
  1040. package/src/runtime/locations/lifecycle-runtime.ts +44 -0
  1041. package/src/runtime/locations/lifecycle.ts +272 -0
  1042. package/src/runtime/locations/location-store-repository.ts +4211 -0
  1043. package/src/runtime/locations/relocation-blob.ts +36 -0
  1044. package/src/runtime/locations/resolvers.ts +1054 -0
  1045. package/src/runtime/locations/runtime.ts +1126 -0
  1046. package/src/runtime/locations/spot-location-claims.ts +435 -0
  1047. package/src/runtime/messaging/creation-payload-codec.ts +59 -0
  1048. package/src/runtime/messaging/framework-json-v1.ts +307 -0
  1049. package/src/runtime/messaging/index.ts +1 -0
  1050. package/src/runtime/messaging/packet-name.ts +94 -0
  1051. package/src/runtime/messaging/payload-codec.ts +418 -0
  1052. package/src/runtime/messaging/submission-result.ts +61 -0
  1053. package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +189 -0
  1054. package/src/runtime/routing-id.ts +125 -0
  1055. package/src/runtime/spots/formal-remote-actor-admission-registry.ts +418 -0
  1056. package/src/runtime/spots/formal-remote-actor-transfer-registry.ts +147 -0
  1057. package/src/runtime/spots/index.ts +3303 -0
  1058. package/src/runtime/spots/spot-activation-registry.ts +335 -0
  1059. package/src/runtime/spots/spot-activation-state.ts +414 -0
  1060. package/src/runtime/spots/spot-activation.ts +1027 -0
  1061. package/src/runtime/spots/spot-actor-admission-coordinator.ts +354 -0
  1062. package/src/runtime/spots/spot-actor-join-dispatch.ts +303 -0
  1063. package/src/runtime/spots/spot-actor-lifecycle-drain.ts +79 -0
  1064. package/src/runtime/spots/spot-actor-membership.ts +266 -0
  1065. package/src/runtime/spots/spot-actor-packet-dispatch.ts +593 -0
  1066. package/src/runtime/spots/spot-actor-packet-drain.ts +328 -0
  1067. package/src/runtime/spots/spot-actor-packet-relay-dispatch.ts +162 -0
  1068. package/src/runtime/spots/spot-closing.ts +34 -0
  1069. package/src/runtime/spots/spot-context.ts +259 -0
  1070. package/src/runtime/spots/spot-entry-activation.ts +551 -0
  1071. package/src/runtime/spots/spot-handle.ts +101 -0
  1072. package/src/runtime/spots/spot-handler-registry.ts +273 -0
  1073. package/src/runtime/spots/spot-lifecycle-metrics.ts +15 -0
  1074. package/src/runtime/spots/spot-location-claim.ts +86 -0
  1075. package/src/runtime/spots/spot-manager-internal-contracts.ts +11 -0
  1076. package/src/runtime/spots/spot-manager-public.ts +361 -0
  1077. package/src/runtime/spots/spot-native-actor-join-admission.ts +151 -0
  1078. package/src/runtime/spots/spot-native-flags.ts +4 -0
  1079. package/src/runtime/spots/spot-node-autoconnect.ts +325 -0
  1080. package/src/runtime/spots/spot-node-runtime-manager.ts +1573 -0
  1081. package/src/runtime/spots/spot-outbound.ts +761 -0
  1082. package/src/runtime/spots/spot-provider.ts +36 -0
  1083. package/src/runtime/spots/spot-publisher-transport.ts +69 -0
  1084. package/src/runtime/spots/spot-remote-codec.ts +308 -0
  1085. package/src/runtime/spots/spot-remote-route-codec.ts +284 -0
  1086. package/src/runtime/spots/spot-route-packet-dispatch.ts +359 -0
  1087. package/src/runtime/spots/spot-route-replies.ts +126 -0
  1088. package/src/runtime/spots/spot-route-reply-wire.ts +15 -0
  1089. package/src/runtime/spots/spot-routed-actor-admission.ts +351 -0
  1090. package/src/runtime/spots/spot-routed-bound-session-dispatch.ts +132 -0
  1091. package/src/runtime/spots/spot-routed-frame-dispatch.ts +250 -0
  1092. package/src/runtime/spots/spot-routed-spot-packet-dispatch.ts +254 -0
  1093. package/src/runtime/spots/spot-routing-internal.ts +33 -0
  1094. package/src/runtime/spots/spot-runtime-ports.ts +196 -0
  1095. package/src/runtime/spots/spot-serial-executor.ts +170 -0
  1096. package/src/runtime/spots/spot-serial-turn-executor.ts +319 -0
  1097. package/src/runtime/spots/spot-subscription-dispatch.ts +252 -0
  1098. package/src/runtime/spots/spot-timer.ts +609 -0
  1099. package/src/runtime/streams/actor-session-binding-registry.ts +1691 -0
  1100. package/src/runtime/streams/actor-session-binding-runtime-owner.ts +78 -0
  1101. package/src/runtime/streams/actor-session-lifecycle-coordinator.ts +20 -0
  1102. package/src/runtime/streams/bound-actor-relay-sender.ts +275 -0
  1103. package/src/runtime/streams/bound-session-response-target.ts +91 -0
  1104. package/src/runtime/streams/bound-session-service.ts +500 -0
  1105. package/src/runtime/streams/index.ts +706 -0
  1106. package/src/runtime/streams/managed-stream.ts +509 -0
  1107. package/src/runtime/streams/native-fallback-bound-session.ts +321 -0
  1108. package/src/runtime/streams/protocol.ts +291 -0
  1109. package/src/runtime/streams/session-actor-coordinator.ts +605 -0
  1110. package/src/runtime/streams/session-calls.ts +221 -0
  1111. package/src/runtime/streams/session-context.ts +609 -0
  1112. package/src/runtime/streams/session-local-actors.ts +30 -0
  1113. package/src/runtime/streams/session-provider.ts +50 -0
  1114. package/src/runtime/streams/session-requests.ts +109 -0
  1115. package/src/runtime/streams/session-serial-executor.ts +97 -0
  1116. package/src/runtime/streams/stream-binding-runtime-ports.ts +106 -0
  1117. package/src/runtime/streams/stream-frame-factory.ts +255 -0
  1118. package/src/runtime/streams/stream-message-utils.ts +89 -0
  1119. package/src/runtime/streams/stream-session-runtime.ts +1420 -0
  1120. package/src/runtime/workers/index.ts +580 -0
  1121. package/tsconfig.json +17 -0
@@ -0,0 +1,4113 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ServiceRelocationDataLostError = exports.ZLinkHostServiceRelocationRuntime = exports.ZLinkRelocationStateIncompatibleError = void 0;
4
+ exports.decodeQueuedHandoffPacket = decodeQueuedHandoffPacket;
5
+ exports.createServiceRelocationId = createServiceRelocationId;
6
+ exports.relocationFailedFailureCode = relocationFailedFailureCode;
7
+ exports.encodeHandoffQueuedMessages = encodeHandoffQueuedMessages;
8
+ const node_crypto_1 = require("node:crypto");
9
+ const runtime_values_1 = require("../backend/runtime-values");
10
+ const contracts_1 = require("../../contracts");
11
+ const Options_1 = require("../../contracts/Locations/Options");
12
+ const framework_errors_internal_1 = require("../framework-errors-internal");
13
+ const service_runtime_contracts_1 = require("../foundation/service-runtime-contracts");
14
+ const routing_id_1 = require("../routing-id");
15
+ const service_wire_m6a_codec_1 = require("../foundation/service-wire-m6a-codec");
16
+ const service_relocation_runtime_1 = require("../foundation/service-relocation-runtime");
17
+ const relocation_direct_transfer_1 = require("./relocation-direct-transfer");
18
+ const relocation_state_adapter_1 = require("./relocation-state-adapter");
19
+ const service_relocation_coordinator_1 = require("../foundation/service-relocation-coordinator");
20
+ const service_maintenance_runtime_1 = require("../foundation/service-maintenance-runtime");
21
+ const service_relocation_object_owner_1 = require("../foundation/service-relocation-object-owner");
22
+ const service_relocation_aggregate_committer_1 = require("../foundation/service-relocation-aggregate-committer");
23
+ const spot_provider_1 = require("../spots/spot-provider");
24
+ const actor_runtime_state_1 = require("../actors/actor-runtime-state");
25
+ const actor_handoff_1 = require("../actors/actor-handoff");
26
+ const spot_remote_codec_1 = require("../spots/spot-remote-codec");
27
+ const actor_authority_publication_1 = require("../actors/actor-authority-publication");
28
+ const service_authority_payload_codec_1 = require("../foundation/service-authority-payload-codec");
29
+ const actor_transfer_runtime_1 = require("./actor-transfer-runtime");
30
+ const authority_key_codec_1 = require("../locations/authority-key-codec");
31
+ const service_relocation_control_1 = require("./service-relocation-control");
32
+ const service_stateful_wire_codec_1 = require("../foundation/service-stateful-wire-codec");
33
+ const service_wire_constants_generated_1 = require("../foundation/service-wire-constants.generated");
34
+ const bounded_replay_map_1 = require("./bounded-replay-map");
35
+ const relocation_integrity_fault_gate_1 = require("./relocation-integrity-fault-gate");
36
+ const actor_remote_wire_1 = require("../actors/actor-remote-wire");
37
+ const actor_join_recovery_codec_1 = require("../foundation/actor-join-recovery-codec");
38
+ class ZLinkRelocationStateIncompatibleError extends Error {
39
+ constructor(message) {
40
+ super(message);
41
+ this.name = 'ZLinkRelocationStateIncompatibleError';
42
+ }
43
+ }
44
+ exports.ZLinkRelocationStateIncompatibleError = ZLinkRelocationStateIncompatibleError;
45
+ const RELOCATION_PARTICIPANT_STATE_LIMIT_BYTES = 64 * 1024 * 1024;
46
+ const RELOCATION_TARGET_TOMBSTONE_LIMIT = 1024;
47
+ const RELOCATION_OPERATION_RETENTION_MS = 5 * 60_000;
48
+ const SERVICE_CONTROL_TERMINAL_CAPACITY = 4096;
49
+ /** Production host bridge from Retire inventory to remote RouteMesh owners. */
50
+ class ZLinkHostServiceRelocationRuntime {
51
+ options;
52
+ targetStages = new Map();
53
+ terminalTargets = new bounded_replay_map_1.BoundedReplayMap(RELOCATION_TARGET_TOMBSTONE_LIMIT);
54
+ relocationAuthorityKeys = new Map();
55
+ targetPrepareOperations = new Map();
56
+ pendingReplyRelays = new Map();
57
+ pendingSessionRelocations = new Map();
58
+ terminalSessionRelocations = new bounded_replay_map_1.BoundedReplayMap(SERVICE_CONTROL_TERMINAL_CAPACITY);
59
+ /**
60
+ * A command 44 submit has no response path. Keep a bounded record of a
61
+ * rejected one-way attempt without turning the committed relocation into a
62
+ * retry loop.
63
+ */
64
+ failedSessionRouteSubmits = new bounded_replay_map_1.BoundedReplayMap(SERVICE_CONTROL_TERMINAL_CAPACITY);
65
+ sourceRelocationIds = new Set();
66
+ targetAssemblies = new Map();
67
+ /**
68
+ * Terminal restore failures (assembly/checksum/factory/restore error): the
69
+ * target already sent relocationFailed (command 53) once. An exact-identity
70
+ * Prepare resend replays the stored response rather than retrying the
71
+ * restore; a different exact identity reusing the same RelocationId+attempt
72
+ * key supersedes the stale entry (spec 28 §3, §9).
73
+ */
74
+ targetReadyFailures = new Map();
75
+ /**
76
+ * Successful restores retained across a Ready delivery retry: an
77
+ * exact-identity Prepare resend re-submits Ready against this retained
78
+ * staging instead of redoing the restore (spec 28).
79
+ */
80
+ targetReadyResponses = new Map();
81
+ sourceCutoverWindows = new Map();
82
+ peerPayloadBudgets = new Map();
83
+ nodePayloadBudget;
84
+ sourceActorJoinProfiles = new Map();
85
+ terminalActorJoinSourceLeaves = new bounded_replay_map_1.BoundedReplayMap(SERVICE_CONTROL_TERMINAL_CAPACITY);
86
+ codec = new service_relocation_runtime_1.ServiceRelocationAuthorityPayloadCodec();
87
+ /**
88
+ * Set once dispose() starts tearing assemblies down. A payload() rejection
89
+ * observed after this point is the shutdown itself, not a chunk-assembly or
90
+ * checksum integrity failure — it must not be reported as DataLost(35).
91
+ */
92
+ disposed = false;
93
+ constructor(options) {
94
+ this.options = options;
95
+ }
96
+ async relocateActorJoin(input) {
97
+ const sourceRef = input.state.nativeActorRef;
98
+ if (sourceRef === undefined) {
99
+ throw new Error(`Actor '${input.state.actorId}' has no source authority identity.`);
100
+ }
101
+ const descriptors = await this.options.liveDescriptors(input.meshName, input.signal);
102
+ const target = descriptors.find(value => (0, routing_id_1.routingIdsEqual)(value.rid, input.target.targetNodeRid));
103
+ if (target === undefined) {
104
+ throw new Error(`Actor '${input.state.actorId}' Join target '${String(input.target.targetNodeRid)}' is not live.`);
105
+ }
106
+ if (input.target.targetNodeGeneration !== undefined
107
+ && target.lifecycleGeneration !== input.target.targetNodeGeneration) {
108
+ throw new Error(`Actor '${input.state.actorId}' Join target generation changed after admission.`);
109
+ }
110
+ this.reserveExactRelocationId(input.relocationId);
111
+ let resolveReady;
112
+ const ready = new Promise((resolve) => {
113
+ resolveReady = resolve;
114
+ });
115
+ this.sourceActorJoinProfiles.set(input.relocationId, {
116
+ actor: input.actor,
117
+ state: input.state,
118
+ sourceActorRef: sourceRef,
119
+ sourceSpotId: input.state.spotId,
120
+ targetSpotId: input.target.spotId,
121
+ targetNodeRid: input.target.targetNodeRid,
122
+ relocationContentType: this.actorRegistration(input.state.meshName ?? input.meshName, input.state.actorType ?? '').relocation.kind === 'snapshot'
123
+ ? 'application/vnd.zlink.actor-relocation.snapshot'
124
+ : 'application/vnd.zlink.actor-relocation.recreate',
125
+ completionOperationId: input.completionOperationId,
126
+ canonicalRecovery: input.canonicalRecovery,
127
+ ready,
128
+ resolveReady
129
+ });
130
+ const membershipEpoch = input.state.spotMembershipEpoch > 0n
131
+ ? input.state.spotMembershipEpoch
132
+ : 1n;
133
+ const spotGeneration = input.target.targetSpotGeneration ?? target.lifecycleGeneration;
134
+ try {
135
+ await this.relocateStandaloneActor(input.meshName, input.state, target, target.applicationVersion, input.signal, {
136
+ spotId: input.target.spotId,
137
+ spotKind: input.target.spotKind === contracts_1.ZLinkSpotKind.Entry
138
+ ? contracts_1.ZLinkSpotKind.Entry
139
+ : contracts_1.ZLinkSpotKind.User,
140
+ spotObjectGeneration: spotGeneration
141
+ }, input.relocationId, true, input.advertisedReceiveChunkLimitBytes);
142
+ resolveReady();
143
+ }
144
+ catch (error) {
145
+ this.sourceActorJoinProfiles.delete(input.relocationId);
146
+ throw error;
147
+ }
148
+ return {
149
+ actorRef: {
150
+ actorId: sourceRef.actorId,
151
+ generation: sourceRef.generation,
152
+ nodeRid: target.rid
153
+ },
154
+ membershipEpoch,
155
+ spotGeneration
156
+ };
157
+ }
158
+ async dispose() {
159
+ this.disposed = true;
160
+ const errors = [];
161
+ for (const stage of this.targetStages.values()) {
162
+ if (stage.fallback !== undefined)
163
+ clearTimeout(stage.fallback);
164
+ try {
165
+ if (stage.finalize !== undefined) {
166
+ await stage.finalize;
167
+ }
168
+ else if (stage.phase === 'ready') {
169
+ await this.abortTargetStage(stage);
170
+ }
171
+ }
172
+ catch (error) {
173
+ errors.push(error);
174
+ }
175
+ }
176
+ this.targetStages.clear();
177
+ this.terminalTargets.clear();
178
+ for (const pending of this.targetAssemblies.values()) {
179
+ pending.assembly.fail('Relocation runtime stopped.');
180
+ }
181
+ this.targetAssemblies.clear();
182
+ this.targetReadyFailures.clear();
183
+ this.targetReadyResponses.clear();
184
+ for (const window of this.sourceCutoverWindows.values()) {
185
+ if (window.windowTimer !== undefined)
186
+ clearTimeout(window.windowTimer);
187
+ if (window.retryTimer !== undefined)
188
+ clearTimeout(window.retryTimer);
189
+ if (window.followTimer !== undefined)
190
+ clearTimeout(window.followTimer);
191
+ }
192
+ this.sourceCutoverWindows.clear();
193
+ const stopped = new Error('Relocation runtime stopped.');
194
+ stopped.name = 'AbortError';
195
+ this.targetPrepareOperations.clear();
196
+ for (const pending of this.pendingReplyRelays.values()) {
197
+ if (pending.timer !== undefined)
198
+ clearTimeout(pending.timer);
199
+ pending.reject(stopped);
200
+ }
201
+ this.pendingReplyRelays.clear();
202
+ for (const pending of this.pendingSessionRelocations.values()) {
203
+ if (pending.retryTimer !== undefined)
204
+ clearTimeout(pending.retryTimer);
205
+ if (pending.deadlineTimer !== undefined)
206
+ clearTimeout(pending.deadlineTimer);
207
+ pending.reject(stopped);
208
+ }
209
+ this.pendingSessionRelocations.clear();
210
+ this.terminalSessionRelocations.clear();
211
+ this.failedSessionRouteSubmits.clear();
212
+ this.sourceActorJoinProfiles.clear();
213
+ this.terminalActorJoinSourceLeaves.clear();
214
+ this.options.boundSessionRelocation?.clear?.();
215
+ this.relocationAuthorityKeys.clear();
216
+ if (errors.length === 1)
217
+ throw errors[0];
218
+ if (errors.length > 1)
219
+ throw new AggregateError(errors, 'Relocation runtime stop failed.');
220
+ }
221
+ completeActorJoinSourceCleanup(actorId) {
222
+ for (const [relocationId, profile] of this.sourceActorJoinProfiles) {
223
+ if (profile.state.actorId !== actorId)
224
+ continue;
225
+ this.sourceActorJoinProfiles.delete(relocationId);
226
+ this.terminalActorJoinSourceLeaves.remember(relocationId, actorId);
227
+ void profile.ready.then(async () => {
228
+ await this.options.actorTransfer.completeRelocationSourceLeave(profile.actor, profile.sourceSpotId);
229
+ await this.options.actorManager()?.completeRelocationSource(actorId, profile.sourceActorRef);
230
+ }).catch(error => {
231
+ console.error('[zlink.runtime.relocation.source_cleanup_failed]', error);
232
+ });
233
+ }
234
+ }
235
+ async relocateMesh(meshName, targetApplicationVersion, signal, stopStartingSignal) {
236
+ const spotManager = this.options.spotManager();
237
+ const actorManager = this.options.actorManager();
238
+ // A stateless host has no relocation work. The corresponding managers are
239
+ // not created for that registration, and the no-op path must still allow
240
+ // the host relocation lifecycle to complete.
241
+ if (spotManager === undefined || actorManager === undefined)
242
+ return;
243
+ const groupedActorIds = new Set();
244
+ const work = [];
245
+ for (const activation of spotManager.relocationActivations(meshName)) {
246
+ const kind = this.spotKind(meshName, activation);
247
+ if (kind === undefined)
248
+ continue;
249
+ const states = actorManager.snapshotStates().filter(state => state.actor !== undefined && String(state.spotId) === String(activation.spotId));
250
+ for (const state of states)
251
+ groupedActorIds.add(state.actorId);
252
+ if (kind === 'user_spot'
253
+ && activation.executionMode === contracts_1.ZLinkUserSpotExecutionMode.PerActor) {
254
+ let shellRelocation;
255
+ const relocateShell = (relocationSignal) => {
256
+ shellRelocation ??= this.relocatePerActorSpotShell(meshName, activation, undefined, targetApplicationVersion, relocationSignal);
257
+ return shellRelocation;
258
+ };
259
+ work.push({
260
+ id: `spot:${String(activation.spotId)}`,
261
+ relocate: relocateShell
262
+ });
263
+ for (const state of states) {
264
+ work.push({
265
+ id: `actor:${state.actorId}`,
266
+ relocate: async (relocationSignal) => {
267
+ await relocateShell(relocationSignal);
268
+ await this.relocateStandaloneActor(meshName, state, undefined, targetApplicationVersion, relocationSignal, {
269
+ spotId: activation.spotId,
270
+ spotKind: contracts_1.ZLinkSpotKind.User,
271
+ spotObjectGeneration: (await requireAuthority(this.requireLocationStore(), (0, authority_key_codec_1.encodeAuthorityKey)('user_spot', String(activation.spotId)), relocationSignal)).objectGeneration
272
+ });
273
+ }
274
+ });
275
+ }
276
+ continue;
277
+ }
278
+ work.push({
279
+ id: `spot:${String(activation.spotId)}`,
280
+ relocate: relocationSignal => this.relocateSpotAggregate(meshName, activation, kind, states, undefined, targetApplicationVersion, relocationSignal)
281
+ });
282
+ }
283
+ for (const state of actorManager.snapshotStates()) {
284
+ if (state.actor === undefined || groupedActorIds.has(state.actorId))
285
+ continue;
286
+ if ((state.meshName ?? meshName) !== meshName)
287
+ continue;
288
+ work.push({
289
+ id: `actor:${state.actorId}`,
290
+ relocate: relocationSignal => this.relocateStandaloneActor(meshName, state, undefined, targetApplicationVersion, relocationSignal)
291
+ });
292
+ }
293
+ if (work.length === 0)
294
+ return;
295
+ const maintenance = new service_maintenance_runtime_1.ServiceMaintenanceRuntime({
296
+ preflight: async () => true,
297
+ publishState: () => undefined,
298
+ forceStop: () => undefined
299
+ });
300
+ for (const unit of work) {
301
+ maintenance.enqueue({
302
+ id: unit.id,
303
+ ready: () => true,
304
+ relocate: unit.relocate
305
+ });
306
+ }
307
+ const operationSignal = signal ?? new AbortController().signal;
308
+ const deadlineMs = signal === undefined ? 30_000 : 24 * 60 * 60 * 1000;
309
+ const result = await raceAbort(maintenance.start('retire', deadlineMs, stopStartingSignal, operationSignal), operationSignal);
310
+ if (result.state !== 'completed') {
311
+ throw result.terminalError ?? new Error(`Host relocation ended in '${result.state}'.`);
312
+ }
313
+ }
314
+ async tryHandleControl(meshName, record, signal) {
315
+ if (record.parts.length === 0)
316
+ return false;
317
+ const payload = record.parts[0].data();
318
+ if (isServiceWireCommand(payload, service_stateful_wire_codec_1.M6bServiceWireCommand.replyRelay)) {
319
+ await this.handleReplyRelay(meshName, (0, service_stateful_wire_codec_1.decodeMaintenanceReplyRelay)(record.parts.map(part => part.data())), record.sourceNodeRid, signal);
320
+ return true;
321
+ }
322
+ const sideband = record.parts.length === 1
323
+ ? undefined
324
+ : decodePrepareSideband(record.parts.slice(1).map(part => part.data()));
325
+ if (record.parts.length > 1 && sideband === undefined)
326
+ return false;
327
+ if (record.kind === service_runtime_contracts_1.ReceiveKind.NodeSend) {
328
+ const sourceLeave = (0, actor_remote_wire_1.decodeRemoteActorSourceLeaveTerminal)(payload);
329
+ if (sourceLeave !== undefined) {
330
+ return this.acceptActorJoinSourceLeave(sourceLeave);
331
+ }
332
+ }
333
+ if (isServiceWireCommand(payload, service_stateful_wire_codec_1.M6bServiceWireCommand.sessionRelocationSealed)) {
334
+ this.acceptSessionRelocationResponse((0, service_stateful_wire_codec_1.decodeSessionRelocationSealed)(payload), record.sourceNodeRid);
335
+ return true;
336
+ }
337
+ if (isServiceWireCommand(payload, service_stateful_wire_codec_1.M6bServiceWireCommand.sessionRelocationSeal)) {
338
+ const request = (0, service_stateful_wire_codec_1.decodeSessionRelocationSeal)(payload);
339
+ const response = await this.handleSessionRelocationSeal(meshName, request, record.sourceNodeRid, signal);
340
+ await this.sendSessionRelocationResponse(meshName, record.sourceNodeRid, (0, service_stateful_wire_codec_1.encodeSessionRelocationSealed)(response));
341
+ return true;
342
+ }
343
+ if (isServiceWireCommand(payload, service_stateful_wire_codec_1.M6bServiceWireCommand.sessionRelocationRoute)) {
344
+ const request = (0, service_stateful_wire_codec_1.decodeSessionRelocationRoute)(payload);
345
+ await this.handleSessionRelocationRoute(meshName, request, record.sourceNodeRid, signal);
346
+ return true;
347
+ }
348
+ if (isServiceWireCommand(payload, service_stateful_wire_codec_1.M6bServiceWireCommand.replyRelayAck)) {
349
+ await this.acceptReplyRelayAck(meshName, (0, service_stateful_wire_codec_1.decodeMaintenanceReplyRelayAck)(payload), record.sourceNodeRid, signal);
350
+ return true;
351
+ }
352
+ let request = (0, service_relocation_control_1.decodeServiceRelocationControlRequest)(payload);
353
+ if (request === undefined)
354
+ return false;
355
+ if (sideband !== undefined) {
356
+ if (request.kind !== 'prepare')
357
+ return false;
358
+ request = { ...request, nodeInternalBoundSessions: sideband };
359
+ }
360
+ // Ready(30) and Failed(53) are replies to Prepare(40), never independent
361
+ // inbound controls. The source consumes them on Core's request reply leg.
362
+ if (request.kind === 'ready' || request.kind === 'failed')
363
+ return false;
364
+ if (request.kind === 'state') {
365
+ this.acceptRelocationStateChunk(request, record.sourceNodeRid);
366
+ return true;
367
+ }
368
+ if (request.kind === 'prepare') {
369
+ if (record.sourceNodeRid === null) {
370
+ throw new Error('Relocation prepare has no authenticated source node.');
371
+ }
372
+ if (record.kind !== service_runtime_contracts_1.ReceiveKind.NodeRequest) {
373
+ throw new service_wire_m6a_codec_1.ServiceWireProtocolError('Relocation prepare requires a Core request leg.');
374
+ }
375
+ const operationKey = relocationStagingId(request);
376
+ const fingerprint = stringifyWire(request);
377
+ // A restore that failed outright is terminal: the source observes the
378
+ // same explicit relocationFailed on every identical Prepare resend
379
+ // rather than a silent stall. A different exact identity reusing the
380
+ // same RelocationId+attempt key supersedes the stale failure — the
381
+ // newer attempt wins (spec 28 §3).
382
+ const readyFailure = this.targetReadyFailures.get(operationKey);
383
+ if (readyFailure !== undefined) {
384
+ if (readyFailure.fingerprint === fingerprint) {
385
+ this.replyPrepare(record, readyFailure.response);
386
+ return true;
387
+ }
388
+ this.targetReadyFailures.delete(operationKey);
389
+ }
390
+ // Spec 28: an exact-identity Restore resend against staging that
391
+ // already restored successfully reuses that staging — it re-submits
392
+ // READY rather than restarting the restore.
393
+ const readyPending = this.targetReadyResponses.get(operationKey);
394
+ if (readyPending !== undefined) {
395
+ if (readyPending.fingerprint !== fingerprint) {
396
+ throw new Error(`Relocation '${operationKey}' repeated Prepare with different bytes.`);
397
+ }
398
+ this.submitTargetReady(meshName, operationKey, record, readyPending.response);
399
+ return true;
400
+ }
401
+ let operation = this.targetPrepareOperations.get(operationKey);
402
+ if (operation !== undefined && operation.fingerprint !== fingerprint) {
403
+ throw new Error(`Relocation '${operationKey}' repeated Prepare with different bytes.`);
404
+ }
405
+ if (operation === undefined) {
406
+ // The prepare turn must not block the ordered dispatch lane: the
407
+ // payload chunks that complete this operation arrive as later records
408
+ // on the same connection. Register the assembly synchronously, then
409
+ // finish the restore and the Ready reply asynchronously.
410
+ this.registerTargetAssembly(operationKey, request, String(record.sourceNodeRid));
411
+ const promise = this.handlePrepareControl(meshName, operationKey, request, record.sourceNodeRid, signal);
412
+ operation = { fingerprint, promise };
413
+ this.targetPrepareOperations.set(operationKey, operation);
414
+ void promise.finally(() => {
415
+ if (this.targetPrepareOperations.get(operationKey) === operation) {
416
+ this.targetPrepareOperations.delete(operationKey);
417
+ }
418
+ }).catch(() => undefined);
419
+ }
420
+ void this.deliverTargetReady(meshName, operationKey, request, record, operation.promise);
421
+ return true;
422
+ }
423
+ await this.handleOneWayControl(meshName, request, record.sourceNodeRid, signal);
424
+ return true;
425
+ }
426
+ /** Sends the Ready reply once the async restore finished; failures replay on resend. */
427
+ async deliverTargetReady(meshName, operationKey, request, ingress, operation) {
428
+ let response;
429
+ try {
430
+ response = await operation;
431
+ }
432
+ catch (error) {
433
+ // The restore itself failed (chunk assembly/checksum, factory,
434
+ // restore or staging): this is terminal. Send relocationFailed
435
+ // (command 53) once and remember it so an identical Prepare resend
436
+ // replays the same response instead of retrying the restore.
437
+ const failed = relocationFailed(request, relocationFailedFailureCode(error, request.object.kind));
438
+ this.targetReadyFailures.set(operationKey, {
439
+ fingerprint: stringifyWire(request),
440
+ response: failed
441
+ });
442
+ // The stored failure replay is bounded by the same Restore validity
443
+ // window as everything else in this attempt — it is not kept forever
444
+ // (spec 28 §9).
445
+ const failureExpiry = setTimeout(() => {
446
+ this.targetReadyFailures.delete(operationKey);
447
+ }, RELOCATION_OPERATION_RETENTION_MS);
448
+ failureExpiry.unref();
449
+ console.error('[zlink.runtime.relocation.restore_failed]', operationKey, error);
450
+ const submitted = this.replyPrepare(ingress, failed);
451
+ if (submitted !== runtime_values_1.SubmitResult.Ok) {
452
+ console.error('[zlink.runtime.relocation.failure_reply_failed]', operationKey, error);
453
+ }
454
+ return;
455
+ }
456
+ // Spec 28: staging that finished restoring successfully is retained
457
+ // across a Ready delivery retry — an identical Prepare resend re-submits
458
+ // Ready against this staging instead of the restore being redone or the
459
+ // attempt being failed outright.
460
+ this.targetReadyResponses.set(operationKey, {
461
+ fingerprint: stringifyWire(request),
462
+ response
463
+ });
464
+ // A Ready that never delivers within the Restore validity window is
465
+ // bounded, too: the retained staging, its reservation and hidden objects
466
+ // are cleaned up exactly once instead of being held indefinitely (spec
467
+ // 28 §9, finding F3). A successful submit removes the map entry first,
468
+ // so this fire is then a harmless no-op.
469
+ const readyExpiry = setTimeout(() => {
470
+ this.expireTargetReadyResponse(operationKey);
471
+ }, RELOCATION_OPERATION_RETENTION_MS);
472
+ readyExpiry.unref();
473
+ this.submitTargetReady(meshName, operationKey, ingress, response);
474
+ }
475
+ /** Cleans up a Ready reply that never delivered within the Restore validity window. */
476
+ expireTargetReadyResponse(operationKey) {
477
+ if (!this.targetReadyResponses.delete(operationKey))
478
+ return;
479
+ const stage = this.targetStages.get(operationKey);
480
+ if (stage === undefined)
481
+ return;
482
+ this.targetStages.delete(operationKey);
483
+ void this.abortTargetStage(stage).catch(error => {
484
+ console.error('[zlink.runtime.relocation.ready_expired_abort_failed]', operationKey, error);
485
+ });
486
+ }
487
+ /**
488
+ * Submits one Ready reply. A failed submit is left for the next identical
489
+ * Prepare resend to retry against the retained staging (spec 28) — it is
490
+ * not rolled back here and does not arm the cutover fallback.
491
+ */
492
+ submitTargetReady(meshName, operationKey, ingress, response) {
493
+ const submitted = this.replyPrepare(ingress, response);
494
+ if (submitted !== runtime_values_1.SubmitResult.Ok) {
495
+ console.warn('[zlink.runtime.relocation.ready_submit_pending_resend]', operationKey);
496
+ return;
497
+ }
498
+ this.targetReadyResponses.delete(operationKey);
499
+ this.armTargetCutoverFallback(meshName, operationKey);
500
+ }
501
+ replyPrepare(ingress, response) {
502
+ try {
503
+ return ingress.reply((0, service_relocation_control_1.encodeServiceRelocationControlResponse)(response));
504
+ }
505
+ catch {
506
+ return runtime_values_1.SubmitResult.NotConnected;
507
+ }
508
+ }
509
+ /** Copies one exact-identity payload chunk into its registered assembly. */
510
+ acceptRelocationStateChunk(request, sourceNodeRid) {
511
+ const operationKey = relocationStagingId(request);
512
+ const pending = this.targetAssemblies.get(operationKey);
513
+ if (pending === undefined
514
+ || sourceNodeRid === null
515
+ || String(sourceNodeRid) !== pending.authenticatedSourceNodeRid
516
+ || request.senderRole !== 'source'
517
+ || !sameCoordinator(request.coordinator, pending.prepare.coordinator)
518
+ || stringifyWire(request.object) !== stringifyWire(pending.prepare.object)) {
519
+ // Spec 28 §4.3 — a chunk with a different exact identity is never
520
+ // attached to an in-progress assembly; it is discarded.
521
+ console.warn('[zlink.runtime.relocation.stale_state_chunk]', operationKey);
522
+ return;
523
+ }
524
+ let chunkData = request.chunkData;
525
+ if (this.relocationIntegrityFaultGate()?.consumeChecksumMismatch() === true) {
526
+ // Preserve the exact command identity and manifest while changing only
527
+ // one delivered payload byte.
528
+ chunkData = Buffer.from(chunkData);
529
+ if (chunkData.byteLength > 0)
530
+ chunkData[0] ^= 0x01;
531
+ }
532
+ pending.assembly.accept(request.chunkOrdinal, chunkData);
533
+ }
534
+ registerTargetAssembly(operationKey, request, authenticatedSourceNodeRid) {
535
+ const existing = this.targetAssemblies.get(operationKey);
536
+ if (existing !== undefined) {
537
+ if (existing.fingerprint !== stringifyWire(request)) {
538
+ // Same exact identity with a different declared length or checksum is
539
+ // an explicit conflict failure; the existing assembly is neither
540
+ // reused nor overwritten (spec 28 §4.3).
541
+ throw existing.assembly.fail(`Relocation '${operationKey}' repeated Prepare with a conflicting manifest.`);
542
+ }
543
+ return existing;
544
+ }
545
+ const pending = {
546
+ prepare: request,
547
+ fingerprint: stringifyWire(request),
548
+ authenticatedSourceNodeRid,
549
+ assembly: new relocation_direct_transfer_1.ZLinkRelocationPayloadAssembly(Number(request.payloadTotalLength), request.payloadChunkCount, request.payloadChecksumCrc32c)
550
+ };
551
+ this.targetAssemblies.set(operationKey, pending);
552
+ if (this.relocationIntegrityFaultGate()?.consumeIdentityConflict() === true) {
553
+ // Route a same-identity, different-manifest delivery through the normal
554
+ // conflict branch so existing staging is neither reused nor overwritten.
555
+ return this.registerTargetAssembly(operationKey, {
556
+ ...request,
557
+ payloadChecksumCrc32c: request.payloadChecksumCrc32c ^ 1
558
+ }, authenticatedSourceNodeRid);
559
+ }
560
+ return pending;
561
+ }
562
+ relocationIntegrityFaultGate() {
563
+ try {
564
+ return this.options.providerResolver?.get?.(relocation_integrity_fault_gate_1.ZLINK_INTERNAL_RELOCATION_INTEGRITY_FAULT_GATE);
565
+ }
566
+ catch {
567
+ return undefined;
568
+ }
569
+ }
570
+ requestSessionRelocationSeal(meshName, targetNodeRid, request, signal) {
571
+ return this.requestSessionRelocationSealControl(meshName, targetNodeRid, request, signal);
572
+ }
573
+ async sendSessionRelocationRoute(meshName, targetNodeRid, request, signal) {
574
+ // A relocation whose session owner IS this node publishes the route
575
+ // to itself; RouteMesh has no self connection (NotConnected), so the
576
+ // control dispatches through the same inbound handler locally.
577
+ const localRid = this.requireMeshNode(meshName).status().routingId;
578
+ if (String(localRid) === String(targetNodeRid)) {
579
+ await this.handleSessionRelocationRoute(meshName, request, localRid, signal);
580
+ return;
581
+ }
582
+ // Spec 20 §5.1 / config-10 ST-E1C: command 44 is a one-way control with
583
+ // no response or application ACK. Submit exactly once; a rejected
584
+ // submit is retained only as bounded per-attempt state. The receiving
585
+ // Session owns seal-timeout cleanup, after which reconnect plus explicit
586
+ // bind is the only recovery path -- never a second command 44 send.
587
+ const bytes = (0, service_stateful_wire_codec_1.encodeSessionRelocationRoute)(request);
588
+ signal?.throwIfAborted();
589
+ const submitted = await this.sendInfrastructureControl(meshName, targetNodeRid, bytes);
590
+ if (submitted !== runtime_values_1.SubmitResult.Ok) {
591
+ this.failedSessionRouteSubmits.remember(sessionRelocationRouteSubmitKey(request, targetNodeRid), submitted);
592
+ }
593
+ }
594
+ requestSessionRelocationSealControl(meshName, targetNodeRid, request, signal) {
595
+ const key = sessionRelocationPendingKey(request);
596
+ const bytes = (0, service_stateful_wire_codec_1.encodeSessionRelocationSeal)(request);
597
+ const requestFingerprint = bytes.toString('base64');
598
+ const expectedTarget = String(targetNodeRid);
599
+ const terminal = this.terminalSessionRelocations.get(key);
600
+ if (terminal !== undefined) {
601
+ if (terminal.targetNodeRid !== expectedTarget
602
+ || terminal.requestFingerprint !== requestFingerprint) {
603
+ return Promise.reject(new service_wire_m6a_codec_1.ServiceWireProtocolError(`Session relocation control '${key}' repeated with different bytes or target.`));
604
+ }
605
+ this.terminalSessionRelocations.touch(key);
606
+ }
607
+ const existing = this.pendingSessionRelocations.get(key);
608
+ if (existing !== undefined) {
609
+ if (existing.targetNodeRid !== expectedTarget
610
+ || existing.requestFingerprint !== requestFingerprint) {
611
+ return Promise.reject(new service_wire_m6a_codec_1.ServiceWireProtocolError(`Session relocation control '${key}' repeated with different bytes or target.`));
612
+ }
613
+ return existing.promise;
614
+ }
615
+ let resolvePromise;
616
+ let rejectPromise;
617
+ const promise = new Promise((resolve, reject) => {
618
+ resolvePromise = resolve;
619
+ rejectPromise = reject;
620
+ });
621
+ let abortListener;
622
+ let settled = false;
623
+ const finish = (action) => {
624
+ if (settled)
625
+ return;
626
+ settled = true;
627
+ const current = this.pendingSessionRelocations.get(key);
628
+ if (current === pending) {
629
+ if (current.retryTimer !== undefined)
630
+ clearTimeout(current.retryTimer);
631
+ if (current.deadlineTimer !== undefined)
632
+ clearTimeout(current.deadlineTimer);
633
+ this.pendingSessionRelocations.delete(key);
634
+ }
635
+ if (abortListener !== undefined) {
636
+ signal?.removeEventListener('abort', abortListener);
637
+ }
638
+ action();
639
+ };
640
+ let pending;
641
+ // Spec 48:205/20:408 — the seal control keeps the operation's deadline
642
+ // and cancellation contract; an unbounded identical-bytes resend loop
643
+ // turned a lost ACK into a permanent relocation stall (observed ~30s
644
+ // admission interruption until teardown). Resends stay within the
645
+ // relocation seal window, then the join terminates DeadlineExceeded
646
+ // (spec 32:88).
647
+ // Spec 06 — the configured SessionRelocationSealTimeout is an additional
648
+ // finite upper bound; the caller's earlier absolute deadline still wins.
649
+ const registration = Object.hasOwn(this.options, 'registration')
650
+ ? this.options.registration
651
+ : undefined;
652
+ const sealTimeoutMs = registration?.locations.options
653
+ .sessionRelocationSealTimeoutMs
654
+ ?? Options_1.zlinkRuntimeDefaultLocationOptions.sessionRelocationSealTimeoutMs;
655
+ const resendDeadline = performance.now() + sealTimeoutMs;
656
+ const send = async () => {
657
+ if (signal?.aborted === true) {
658
+ finish(() => rejectPromise(signal.reason));
659
+ return;
660
+ }
661
+ // A seal whose session owner IS this node has no RouteMesh self
662
+ // connection (NotConnected); dispatch through the inbound handler
663
+ // locally instead of the wire.
664
+ const localRid = this.requireMeshNode(meshName).status().routingId;
665
+ if (String(localRid) === expectedTarget) {
666
+ try {
667
+ const response = await this.handleSessionRelocationSeal(meshName, request, localRid, signal);
668
+ pending.resolve(response);
669
+ }
670
+ catch (error) {
671
+ pending.reject(error);
672
+ }
673
+ return;
674
+ }
675
+ if (performance.now() >= resendDeadline) {
676
+ pending.reject((0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.DeadlineExceeded, `Session relocation seal '${key}' was not acknowledged within the relocation seal timeout.`, true));
677
+ return;
678
+ }
679
+ try {
680
+ const submitted = await this.sendInfrastructureControl(meshName, targetNodeRid, bytes);
681
+ if (submitted !== runtime_values_1.SubmitResult.Ok) {
682
+ pending.reject((0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.RelocationTargetUnavailable, `Session relocation seal '${key}' was not accepted by RouteMesh.`, true));
683
+ return;
684
+ }
685
+ if (this.pendingSessionRelocations.get(key) === pending) {
686
+ pending.retryTimer = setTimeout(() => void send(), 250);
687
+ }
688
+ }
689
+ catch (error) {
690
+ pending.reject((0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.RelocationTargetUnavailable, `Session relocation seal '${key}' could not reach its RouteMesh owner.`, true, error));
691
+ }
692
+ };
693
+ pending = {
694
+ targetNodeRid: expectedTarget,
695
+ request,
696
+ requestFingerprint,
697
+ promise,
698
+ resolve: response => finish(() => {
699
+ this.terminalSessionRelocations.remember(key, {
700
+ targetNodeRid: expectedTarget,
701
+ request,
702
+ requestFingerprint,
703
+ responseFingerprint: sessionRelocationResponseFingerprint(response)
704
+ });
705
+ resolvePromise(response);
706
+ }),
707
+ reject: error => finish(() => rejectPromise(error))
708
+ };
709
+ this.pendingSessionRelocations.set(key, pending);
710
+ pending.deadlineTimer = setTimeout(() => pending.reject((0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.DeadlineExceeded, `Session relocation seal '${key}' was not acknowledged within the relocation seal timeout.`, true)), Math.max(0, resendDeadline - performance.now()));
711
+ pending.deadlineTimer.unref();
712
+ abortListener = () => pending.reject(signal?.reason ?? (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.DeadlineExceeded, `Session relocation seal '${key}' was cancelled.`, true));
713
+ if (signal?.aborted === true) {
714
+ abortListener();
715
+ return promise;
716
+ }
717
+ signal?.addEventListener('abort', abortListener, { once: true });
718
+ void send();
719
+ return promise;
720
+ }
721
+ acceptSessionRelocationResponse(response, sourceNodeRid) {
722
+ const key = sessionRelocationResponseKey(response);
723
+ const pending = this.pendingSessionRelocations.get(key);
724
+ if (pending === undefined) {
725
+ const terminal = this.terminalSessionRelocations.get(key);
726
+ if (terminal === undefined)
727
+ return;
728
+ if (sourceNodeRid === null || String(sourceNodeRid) !== terminal.targetNodeRid) {
729
+ throw new service_wire_m6a_codec_1.ServiceWireProtocolError(`Session relocation ACK '${key}' source node changed.`);
730
+ }
731
+ validateSessionRelocationResponse(terminal.request, response);
732
+ if (sessionRelocationResponseFingerprint(response) !== terminal.responseFingerprint) {
733
+ throw new service_wire_m6a_codec_1.ServiceWireProtocolError(`Session relocation ACK '${key}' repeated with different bytes.`);
734
+ }
735
+ this.terminalSessionRelocations.touch(key);
736
+ return;
737
+ }
738
+ if (sourceNodeRid === null || String(sourceNodeRid) !== pending.targetNodeRid) {
739
+ pending.reject(new service_wire_m6a_codec_1.ServiceWireProtocolError(`Session relocation ACK '${key}' source node changed.`));
740
+ return;
741
+ }
742
+ try {
743
+ validateSessionRelocationResponse(pending.request, response);
744
+ pending.resolve(response);
745
+ }
746
+ catch (error) {
747
+ pending.reject(error);
748
+ }
749
+ }
750
+ // A relocation control dispatched locally names THIS node as its
751
+ // source; the peers() view never contains the local node, so its
752
+ // lifecycle generation comes from the node status instead.
753
+ sourceLifecycleGeneration(meshName, sourceNodeRid) {
754
+ if (sourceNodeRid === null)
755
+ return undefined;
756
+ const node = this.requireMeshNode(meshName);
757
+ const status = node.status();
758
+ if (String(status.routingId) === String(sourceNodeRid)) {
759
+ return status.lifecycleGeneration;
760
+ }
761
+ return node.peers().find(peer => peer.routingId !== null
762
+ && String(peer.routingId) === String(sourceNodeRid))?.lifecycleGeneration;
763
+ }
764
+ async handleSessionRelocationSeal(meshName, request, sourceNodeRid, signal) {
765
+ if (sourceNodeRid === null
766
+ || String(sourceNodeRid) !== request.coordinator.nodeRid
767
+ || String(sourceNodeRid) !== request.actor.actor.nodeRid) {
768
+ throw new service_wire_m6a_codec_1.ServiceWireProtocolError('Session relocation seal source does not match its coordinator and Actor fence.');
769
+ }
770
+ this.validateSessionOwnerFence(meshName, request.session);
771
+ const sealSourceGeneration = this.sourceLifecycleGeneration(meshName, sourceNodeRid);
772
+ if (sealSourceGeneration !== request.actor.targetNodeGeneration
773
+ || sealSourceGeneration !== request.coordinator.nodeGeneration) {
774
+ throw new service_wire_m6a_codec_1.ServiceWireProtocolError('Session relocation seal source lifecycle generation is stale.');
775
+ }
776
+ const handler = this.options.boundSessionRelocation?.receiveSeal;
777
+ if (handler === undefined) {
778
+ throw new Error('Session relocation seal ingress is not configured.');
779
+ }
780
+ return await handler(request, signal);
781
+ }
782
+ async handleSessionRelocationRoute(meshName, request, sourceNodeRid, _signal) {
783
+ this.validateSessionOwnerFence(meshName, request.session);
784
+ const expectedSource = request.route.action === 'commit'
785
+ ? request.route.targetNodeRid
786
+ : request.coordinator.nodeRid;
787
+ if (sourceNodeRid === null || String(sourceNodeRid) !== expectedSource) {
788
+ throw new service_wire_m6a_codec_1.ServiceWireProtocolError('Session relocation route source does not match its action fence.');
789
+ }
790
+ const routeSourceGeneration = this.sourceLifecycleGeneration(meshName, sourceNodeRid);
791
+ const expectedSourceGeneration = request.route.action === 'commit'
792
+ ? request.route.targetNodeGeneration
793
+ : request.coordinator.nodeGeneration;
794
+ if (routeSourceGeneration !== expectedSourceGeneration) {
795
+ throw new service_wire_m6a_codec_1.ServiceWireProtocolError('Session relocation route source lifecycle generation is stale.');
796
+ }
797
+ const handler = this.options.boundSessionRelocation?.receiveRoute;
798
+ if (handler === undefined) {
799
+ throw new Error('Session relocation route ingress is not configured.');
800
+ }
801
+ await handler(request);
802
+ }
803
+ validateSessionOwnerFence(meshName, session) {
804
+ const status = this.requireMeshNode(meshName).status();
805
+ const owner = this.options.currentOwner();
806
+ if (String(status.routingId) !== session.sessionOwnerNodeRid
807
+ || status.lifecycleGeneration !== session.sessionOwnerNodeGeneration
808
+ || owner?.ownerId !== session.sessionOwnerId
809
+ || owner.leaseGeneration !== session.sessionOwnerLeaseGeneration) {
810
+ throw new service_wire_m6a_codec_1.ServiceWireProtocolError('Session relocation command does not match the local Session owner fence.');
811
+ }
812
+ }
813
+ async sendSessionRelocationResponse(meshName, targetNodeRid, bytes) {
814
+ if (targetNodeRid === null) {
815
+ throw new service_wire_m6a_codec_1.ServiceWireProtocolError('Session relocation command has no authenticated source.');
816
+ }
817
+ const submitted = await this.sendInfrastructureControl(meshName, targetNodeRid, bytes);
818
+ if (submitted !== runtime_values_1.SubmitResult.Ok) {
819
+ throw new Error('Session relocation ACK was not accepted by RouteMesh.');
820
+ }
821
+ }
822
+ async relocateSpotAggregate(meshName, activation, kind, actorStates, target, targetApplicationVersion, signal) {
823
+ const store = this.requireLocationStore();
824
+ const spotKey = (0, authority_key_codec_1.encodeAuthorityKey)(kind, String(activation.spotId));
825
+ const spotAuthority = await requireAuthority(store, spotKey, signal);
826
+ const actorAuthorities = new Map();
827
+ for (const state of actorStates) {
828
+ actorAuthorities.set(state.actorId, await requireAuthority(store, (0, authority_key_codec_1.encodeAuthorityKey)('actor', state.actorId), signal));
829
+ }
830
+ const sessions = [];
831
+ let spotCapture;
832
+ let spotMessageFollowSeal;
833
+ let spotSealCommitted = false;
834
+ let readinessBoundaryConsumed = false;
835
+ let interruptionStartedAt;
836
+ const spotRegistration = this.spotRegistration(meshName, kind, spotAuthority.allocation.stableType);
837
+ target ??= await this.selectTarget(meshName, String(this.requireMeshNode(meshName).status().routingId), targetApplicationVersion, relocationTargetRequirements([
838
+ {
839
+ objectKind: kind,
840
+ stableType: spotAuthority.allocation.stableType,
841
+ policy: spotRegistration.relocation.kind,
842
+ count: 1
843
+ },
844
+ ...actorStates.map(state => {
845
+ const actorAuthority = actorAuthorities.get(state.actorId);
846
+ return {
847
+ objectKind: 'actor',
848
+ stableType: actorAuthority.allocation.stableType,
849
+ policy: this.actorRegistration(state.meshName ?? meshName, actorAuthority.allocation.stableType).relocation.kind,
850
+ count: 1
851
+ };
852
+ })
853
+ ]), signal);
854
+ const aggregateId = this.reserveRelocationId();
855
+ const spotUnit = {
856
+ authorityKey: spotKey.value,
857
+ objectKind: kind,
858
+ stableType: spotAuthority.allocation.stableType,
859
+ objectGeneration: spotAuthority.objectGeneration,
860
+ authorityOwnerGeneration: spotAuthority.authorityOwnerGeneration,
861
+ seal: async (captureSignal) => {
862
+ interruptionStartedAt = performance.now();
863
+ spotMessageFollowSeal = this.sealSpotMessageFollow(meshName, spotAuthority, activation);
864
+ // captureRelocation seals synchronously before its first await. Invoke
865
+ // it in the same event-loop turn as the wire ingress seal so no
866
+ // accepted direct message can enter between the two boundaries.
867
+ const spotCaptureOperation = activation.captureRelocation(captureSignal);
868
+ const preparedSessions = Promise.all(actorStates.map(async (state) => ({
869
+ state,
870
+ actor: state.actor,
871
+ prepared: await this.options.actorTransfer.prepareMaintenanceSession(state.actor, state, captureSignal, false, relocationWireId(aggregateId))
872
+ })));
873
+ const preparedSessionsOutcome = preparedSessions.then(value => ({ value }), error => ({ error }));
874
+ spotCapture = await spotCaptureOperation;
875
+ const preparation = await preparedSessionsOutcome;
876
+ if ('error' in preparation)
877
+ throw preparation.error;
878
+ sessions.push(...preparation.value);
879
+ return {
880
+ boundSessionState: Buffer.alloc(0),
881
+ queuedMessages: [],
882
+ timers: spotCapture.timers.map(toServiceTimer)
883
+ };
884
+ },
885
+ captureApplicationState: captureSignal => this.captureApplication(spotRegistration.relocation, activation.spot, captureSignal),
886
+ commitSeal: async () => {
887
+ if (!spotSealCommitted) {
888
+ if (spotCapture === undefined || !await activation.commitRelocation(spotCapture)) {
889
+ throw new Error(`Spot '${String(activation.spotId)}' relocation seal became stale.`);
890
+ }
891
+ spotSealCommitted = true;
892
+ }
893
+ if (spotMessageFollowSeal !== undefined) {
894
+ await this.commitSpotMessageFollow(meshName, spotMessageFollowSeal, spotKey, activation, target);
895
+ }
896
+ for (const session of sessions) {
897
+ const committedAuthority = await requireAuthority(this.requireLocationStore(), (0, authority_key_codec_1.encodeAuthorityKey)('actor', session.state.actorId));
898
+ const targetActorRef = {
899
+ actorId: session.state.actorId,
900
+ objectGeneration: actorAuthorities.get(session.state.actorId).objectGeneration,
901
+ meshName,
902
+ nodeRid: target.rid
903
+ };
904
+ await session.prepared.commit({
905
+ routerChannelId: meshName,
906
+ targetNodeRid: target.rid,
907
+ spotId: activation.spotId,
908
+ spotKind: kind === 'user_spot'
909
+ ? contracts_1.ZLinkSpotKind.User
910
+ : contracts_1.ZLinkSpotKind.Instance,
911
+ authorityOwnerGeneration: committedAuthority.authorityOwnerGeneration
912
+ }, targetActorRef, (0, actor_transfer_runtime_1.committedActorOwnerFence)(session.state.actorId, targetActorRef, committedAuthority));
913
+ activation.commitActorDeparture(session.state.actorId);
914
+ await this.requireActorManager().completeRelocationSource(session.state.actorId);
915
+ }
916
+ await this.requireSpotManager().completeRelocationSource(activation);
917
+ },
918
+ abortSeal: async () => {
919
+ const failures = [];
920
+ if (spotCapture !== undefined) {
921
+ try {
922
+ activation.abortRelocation(spotCapture);
923
+ }
924
+ catch (error) {
925
+ failures.push(error);
926
+ }
927
+ }
928
+ if (spotMessageFollowSeal !== undefined) {
929
+ try {
930
+ const node = this.requireMeshNode(meshName);
931
+ const abort = node.abortSpotMessageFollowIngress;
932
+ if (abort === undefined || !abort.call(node, spotMessageFollowSeal)) {
933
+ throw new Error('Spot Message Follow abort fence became stale.');
934
+ }
935
+ }
936
+ catch (error) {
937
+ failures.push(error);
938
+ }
939
+ }
940
+ for (const session of [...sessions].reverse()) {
941
+ try {
942
+ await session.prepared.rollback();
943
+ }
944
+ catch (error) {
945
+ failures.push(error);
946
+ }
947
+ }
948
+ if (failures.length !== 0) {
949
+ throw new AggregateError(failures, 'Spot relocation source rollback was incomplete.');
950
+ }
951
+ }
952
+ };
953
+ const actorUnits = actorStates.map(state => this.actorCaptureUnit(state, actorAuthorities.get(state.actorId), sessions, false, undefined, undefined, undefined, undefined, false));
954
+ const memberships = actorStates.map(state => ({
955
+ actorKey: (0, authority_key_codec_1.encodeAuthorityKey)('actor', state.actorId).value,
956
+ spotKey: spotKey.value,
957
+ spotObjectGeneration: spotAuthority.objectGeneration,
958
+ membershipEpoch: state.spotMembershipEpoch > 0n ? state.spotMembershipEpoch : 1n
959
+ }));
960
+ let outcome = 'completed';
961
+ try {
962
+ const waitForRelocationBoundary = activation.waitForRelocationBoundary;
963
+ readinessBoundaryConsumed = waitForRelocationBoundary === undefined
964
+ ? false
965
+ : await waitForRelocationBoundary.call(activation, signal);
966
+ // A full in-flight payload budget delays this unit before its seal, so
967
+ // the Spot and its Actors keep processing messages while waiting.
968
+ await this.waitForRelocationBudgetHeadroom(String(target.rid), signal);
969
+ const captureOwner = new service_relocation_object_owner_1.ServiceRelocationObjectCaptureOwner();
970
+ const captured = kind === 'user_spot'
971
+ ? await captureOwner.captureUserSpotAggregate(aggregateId, 1n, spotUnit, actorUnits, memberships, signal)
972
+ : await captureOwner.captureInstanceSpotAggregate(aggregateId, 1n, spotUnit, actorUnits, memberships, signal);
973
+ await this.runCoordinator(meshName, target, spotAuthority, captured, new Map([[spotKey.value, spotAuthority], ...actorStates.map(state => [
974
+ (0, authority_key_codec_1.encodeAuthorityKey)('actor', state.actorId).value,
975
+ actorAuthorities.get(state.actorId)
976
+ ])]), signal, sessions);
977
+ }
978
+ catch (error) {
979
+ outcome = 'failed';
980
+ if (readinessBoundaryConsumed
981
+ && !(error instanceof service_relocation_coordinator_1.ServiceRelocationPostCommitError)) {
982
+ await activation.completeConsumedRelocationBoundary(contracts_1.ZLinkSpotRelocationReadyOutcome.Continued).catch(() => undefined);
983
+ }
984
+ throw error;
985
+ }
986
+ finally {
987
+ this.sourceRelocationIds.delete(aggregateId);
988
+ if (interruptionStartedAt !== undefined) {
989
+ this.recordRelocationInterruption(meshName, kind, kind === 'user_spot' ? 'spot_wide' : undefined, interruptionStartedAt, outcome);
990
+ }
991
+ }
992
+ }
993
+ async relocateStandaloneActor(meshName, state, target, targetApplicationVersion, signal, targetMembership, aggregateIdOverride, retainSourceForActorJoin = false,
994
+ /** Target's advertised relocation state chunk cap (Actor Join only; spec 15 §4.2). */
995
+ advertisedReceiveChunkLimitBytes) {
996
+ relocationDebug('standalone_actor.begin', { actorId: state.actorId });
997
+ const authority = await requireAuthority(this.requireLocationStore(), (0, authority_key_codec_1.encodeAuthorityKey)('actor', state.actorId), signal);
998
+ target ??= await this.selectTarget(meshName, String(this.requireMeshNode(meshName).status().routingId), targetApplicationVersion, [{
999
+ objectKind: 'actor',
1000
+ stableType: authority.allocation.stableType,
1001
+ policy: this.actorRegistration(state.meshName ?? meshName, authority.allocation.stableType).relocation.kind,
1002
+ count: 1
1003
+ }], signal);
1004
+ const sessions = [];
1005
+ const membershipSpotId = targetMembership?.spotId
1006
+ ?? (target.entrySpotId ?? String(target.rid));
1007
+ const aggregateId = aggregateIdOverride ?? this.reserveRelocationId();
1008
+ const unit = this.actorCaptureUnit(state, authority, sessions, true, target, meshName, {
1009
+ spotId: membershipSpotId,
1010
+ spotKind: targetMembership?.spotKind ?? contracts_1.ZLinkSpotKind.Entry
1011
+ }, relocationWireId(aggregateId), retainSourceForActorJoin);
1012
+ const membership = {
1013
+ actorKey: (0, authority_key_codec_1.encodeAuthorityKey)('actor', state.actorId).value,
1014
+ spotKey: (0, authority_key_codec_1.encodeAuthorityKey)('user_spot', String(membershipSpotId)).value,
1015
+ spotObjectGeneration: targetMembership?.spotObjectGeneration ?? target.lifecycleGeneration,
1016
+ membershipEpoch: state.spotMembershipEpoch > 0n ? state.spotMembershipEpoch : 1n
1017
+ };
1018
+ let interruptionStartedAt;
1019
+ const measuredUnit = {
1020
+ ...unit,
1021
+ seal: async (captureSignal) => {
1022
+ interruptionStartedAt = performance.now();
1023
+ return unit.seal(captureSignal);
1024
+ }
1025
+ };
1026
+ let outcome = 'completed';
1027
+ try {
1028
+ relocationDebug('standalone_actor.wait_budget', { actorId: state.actorId, targetRid: String(target.rid) });
1029
+ await this.waitForRelocationBudgetHeadroom(String(target.rid), signal);
1030
+ relocationDebug('standalone_actor.capture_begin', { actorId: state.actorId });
1031
+ const captured = await new service_relocation_object_owner_1.ServiceRelocationObjectCaptureOwner().captureStandaloneActor(aggregateId, 1n, measuredUnit, membership, signal);
1032
+ relocationDebug('standalone_actor.capture_complete', { actorId: state.actorId });
1033
+ await this.runCoordinator(meshName, target, authority, captured, new Map([[measuredUnit.authorityKey, authority]]), signal, sessions, advertisedReceiveChunkLimitBytes);
1034
+ }
1035
+ catch (error) {
1036
+ outcome = 'failed';
1037
+ throw error;
1038
+ }
1039
+ finally {
1040
+ this.sourceRelocationIds.delete(aggregateId);
1041
+ if (interruptionStartedAt !== undefined) {
1042
+ this.recordRelocationInterruption(meshName, 'actor', undefined, interruptionStartedAt, outcome);
1043
+ }
1044
+ }
1045
+ }
1046
+ async relocatePerActorSpotShell(meshName, activation, target, targetApplicationVersion, signal) {
1047
+ const spotKey = (0, authority_key_codec_1.encodeAuthorityKey)('user_spot', String(activation.spotId));
1048
+ const spotAuthority = await requireAuthority(this.requireLocationStore(), spotKey, signal);
1049
+ const spotRegistration = this.spotRegistration(meshName, 'user_spot', spotAuthority.allocation.stableType);
1050
+ target ??= await this.selectTarget(meshName, String(this.requireMeshNode(meshName).status().routingId), targetApplicationVersion, [{
1051
+ objectKind: 'user_spot',
1052
+ stableType: spotAuthority.allocation.stableType,
1053
+ policy: spotRegistration.relocation.kind,
1054
+ count: 1
1055
+ }], signal);
1056
+ let spotCapture;
1057
+ let spotMessageFollowSeal;
1058
+ let sealCommitted = false;
1059
+ let interruptionStartedAt;
1060
+ const spotUnit = {
1061
+ authorityKey: spotKey.value,
1062
+ objectKind: 'user_spot',
1063
+ stableType: spotAuthority.allocation.stableType,
1064
+ objectGeneration: spotAuthority.objectGeneration,
1065
+ authorityOwnerGeneration: spotAuthority.authorityOwnerGeneration,
1066
+ seal: async (captureSignal) => {
1067
+ interruptionStartedAt = performance.now();
1068
+ spotMessageFollowSeal = this.sealSpotMessageFollow(meshName, spotAuthority, activation);
1069
+ spotCapture = await activation.captureRelocation(captureSignal);
1070
+ return {
1071
+ boundSessionState: Buffer.alloc(0),
1072
+ queuedMessages: [],
1073
+ timers: spotCapture.timers.map(toServiceTimer)
1074
+ };
1075
+ },
1076
+ // PerActor User Spots are stateless shells. Application state and the
1077
+ // Spot relocation adapter are intentionally not part of this unit.
1078
+ captureApplicationState: async () => Buffer.alloc(0),
1079
+ commitSeal: async () => {
1080
+ if (!sealCommitted) {
1081
+ if (spotCapture === undefined || !await activation.commitRelocation(spotCapture)) {
1082
+ throw new Error(`PerActor Spot '${String(activation.spotId)}' relocation seal became stale.`);
1083
+ }
1084
+ sealCommitted = true;
1085
+ }
1086
+ if (spotMessageFollowSeal !== undefined) {
1087
+ await this.commitSpotMessageFollow(meshName, spotMessageFollowSeal, spotKey, activation, target);
1088
+ }
1089
+ await this.requireSpotManager().completeRelocationSource(activation);
1090
+ },
1091
+ abortSeal: async () => {
1092
+ if (spotCapture !== undefined)
1093
+ activation.abortRelocation(spotCapture);
1094
+ if (spotMessageFollowSeal !== undefined) {
1095
+ const node = this.requireMeshNode(meshName);
1096
+ const abort = node.abortSpotMessageFollowIngress;
1097
+ if (abort === undefined || !abort.call(node, spotMessageFollowSeal)) {
1098
+ throw new Error('Spot Message Follow abort fence became stale.');
1099
+ }
1100
+ }
1101
+ }
1102
+ };
1103
+ const aggregateId = this.reserveRelocationId();
1104
+ let outcome = 'completed';
1105
+ try {
1106
+ await this.waitForRelocationBudgetHeadroom(String(target.rid), signal);
1107
+ const captured = await new service_relocation_object_owner_1.ServiceRelocationObjectCaptureOwner().captureUserSpotAggregate(aggregateId, 1n, spotUnit, [], [], signal);
1108
+ await this.runCoordinator(meshName, target, spotAuthority, captured, new Map([[spotKey.value, spotAuthority]]), signal, []);
1109
+ }
1110
+ catch (error) {
1111
+ outcome = 'failed';
1112
+ throw error;
1113
+ }
1114
+ finally {
1115
+ this.sourceRelocationIds.delete(aggregateId);
1116
+ if (interruptionStartedAt !== undefined) {
1117
+ this.recordRelocationInterruption(meshName, 'user_spot', 'per_actor', interruptionStartedAt, outcome);
1118
+ }
1119
+ }
1120
+ }
1121
+ actorCaptureUnit(state, authority, sessions, standalone = false, target, meshName, targetMembership, sessionRelocation, retainSourceForActorJoin = false) {
1122
+ const registration = this.actorRegistration(state.meshName ?? meshName ?? '', state.actorType ?? authority.allocation.stableType);
1123
+ let ownSession;
1124
+ return {
1125
+ authorityKey: (0, authority_key_codec_1.encodeAuthorityKey)('actor', state.actorId).value,
1126
+ objectKind: 'actor',
1127
+ stableType: authority.allocation.stableType,
1128
+ objectGeneration: authority.objectGeneration,
1129
+ authorityOwnerGeneration: authority.authorityOwnerGeneration,
1130
+ seal: async (signal) => {
1131
+ if (standalone) {
1132
+ ownSession = {
1133
+ state,
1134
+ actor: state.actor,
1135
+ prepared: await this.options.actorTransfer.prepareMaintenanceSession(state.actor, state, signal, true, sessionRelocation)
1136
+ };
1137
+ sessions.push(ownSession);
1138
+ }
1139
+ const prepared = standalone ? ownSession : sessions.find(value => value.state === state);
1140
+ return {
1141
+ boundSessionState: encodeActorSession(prepared?.prepared.target),
1142
+ queuedMessages: encodeHandoffQueuedMessages(prepared?.prepared.handoffBacklog ?? []),
1143
+ timers: []
1144
+ };
1145
+ },
1146
+ // The canonical participant body (discriminator 1) is raw application
1147
+ // state. The sealed bound-session target remains in sealed work and is
1148
+ // transported only by Prepare's NODE-INTERNAL sideband frames.
1149
+ captureApplicationState: signal => this.captureApplication(registration.relocation, state.actor, signal),
1150
+ commitSeal: async () => {
1151
+ if (!standalone || ownSession === undefined || target === undefined || meshName === undefined)
1152
+ return;
1153
+ const membershipSpotId = targetMembership?.spotId
1154
+ ?? (target.entrySpotId ?? String(target.rid));
1155
+ const committedAuthority = await requireAuthority(this.requireLocationStore(), (0, authority_key_codec_1.encodeAuthorityKey)('actor', state.actorId));
1156
+ const targetActorRef = {
1157
+ actorId: state.actorId,
1158
+ objectGeneration: authority.objectGeneration,
1159
+ meshName,
1160
+ nodeRid: target.rid
1161
+ };
1162
+ await ownSession.prepared.commit({
1163
+ routerChannelId: meshName,
1164
+ targetNodeRid: target.rid,
1165
+ spotId: membershipSpotId,
1166
+ spotKind: targetMembership?.spotKind ?? contracts_1.ZLinkSpotKind.Entry,
1167
+ authorityOwnerGeneration: committedAuthority.authorityOwnerGeneration
1168
+ }, targetActorRef, (0, actor_transfer_runtime_1.committedActorOwnerFence)(state.actorId, targetActorRef, committedAuthority));
1169
+ if (!retainSourceForActorJoin) {
1170
+ await this.requireActorManager().completeRelocationSource(state.actorId);
1171
+ }
1172
+ },
1173
+ abortSeal: async () => {
1174
+ if (standalone && ownSession !== undefined)
1175
+ await ownSession.prepared.rollback();
1176
+ }
1177
+ };
1178
+ }
1179
+ reserveRelocationId() {
1180
+ const id = createServiceRelocationId(candidate => {
1181
+ if (this.sourceRelocationIds.has(candidate))
1182
+ return true;
1183
+ const wire = relocationWireId(candidate);
1184
+ const prefix = `${wire.high}:${wire.low}:`;
1185
+ return [...this.targetStages.keys()].some(key => key.startsWith(prefix));
1186
+ });
1187
+ this.sourceRelocationIds.add(id);
1188
+ return id;
1189
+ }
1190
+ reserveExactRelocationId(id) {
1191
+ const wire = relocationWireId(id);
1192
+ const prefix = `${wire.high}:${wire.low}:`;
1193
+ if (this.sourceRelocationIds.has(id)
1194
+ || [...this.targetStages.keys()].some(key => key.startsWith(prefix))) {
1195
+ throw new Error(`Actor Join relocation '${id}' is already active.`);
1196
+ }
1197
+ this.sourceRelocationIds.add(id);
1198
+ }
1199
+ async runCoordinator(meshName, target, primary, captured, _authorities, signal, sessions = [],
1200
+ /** Target's advertised relocation state chunk cap (Actor Join only; spec 15 §4.2). */
1201
+ advertisedReceiveChunkLimitBytes) {
1202
+ relocationDebug('coordinator.begin', { aggregateId: captured.envelope.aggregateId, targetRid: String(target.rid) });
1203
+ const localStatus = this.requireMeshNode(meshName).status();
1204
+ const controlDeadlineAtMs = signal === undefined
1205
+ ? performance.now() + 30_000
1206
+ : Number.MAX_SAFE_INTEGER;
1207
+ const coordinator = {
1208
+ ownerId: primary.ownerId,
1209
+ leaseGeneration: primary.ownerLeaseGeneration,
1210
+ nodeRid: String(localStatus.routingId),
1211
+ nodeGeneration: localStatus.lifecycleGeneration,
1212
+ expectedAuthorityStoreVersion: primary.storeVersion.value
1213
+ };
1214
+ const targetFence = {
1215
+ nodeRid: String(target.rid),
1216
+ nodeGeneration: target.lifecycleGeneration,
1217
+ ownerId: target.ownerId,
1218
+ ownerLeaseGeneration: target.leaseGeneration
1219
+ };
1220
+ const relocation = relocationWireId(captured.envelope.aggregateId);
1221
+ const object = relocationObject(captured.envelope);
1222
+ // The selected target lifecycle is the attempt fence used by the
1223
+ // reference C++ relocation path. Keep the envelope and every control leg
1224
+ // on that one exact identity; a process replacement is a different
1225
+ // attempt even when it reuses the same routing id.
1226
+ const targetAttemptGeneration = target.lifecycleGeneration;
1227
+ const relayAuthorityId = wireIdText(relocationWireId(captured.envelope.aggregateId));
1228
+ const relayAuthorityKey = primaryKey(captured.envelope);
1229
+ if (this.relocationAuthorityKeys.has(relayAuthorityId)) {
1230
+ throw new Error(`Relocation reply relay authority '${relayAuthorityId}' is already registered.`);
1231
+ }
1232
+ this.relocationAuthorityKeys.set(relayAuthorityId, relayAuthorityKey);
1233
+ // The captured payload stays in source memory: this copy is the only
1234
+ // handoff original until the cutover submit terminal and the
1235
+ // retransmission window end (spec 28 §4.2).
1236
+ const canonicalEnvelope = canonicalizeCapturedHandoffBacklog(captured.envelope, coordinator, targetFence);
1237
+ const actorJoinProfile = this.sourceActorJoinProfiles.get(captured.envelope.aggregateId);
1238
+ const transportEnvelope = actorJoinProfile?.canonicalRecovery === undefined
1239
+ ? canonicalEnvelope
1240
+ : appendCanonicalActorJoinRecovery(canonicalEnvelope, actorJoinProfile, coordinator, primary);
1241
+ const encoded = (0, service_relocation_runtime_1.encodeServiceRelocationEnvelope)(transportEnvelope, target.applicationVersion);
1242
+ const limits = this.relocationLimits();
1243
+ // Actor Join threads the target's admission-time advertised cap in;
1244
+ // other relocation paths have no such negotiation and fall back to the
1245
+ // configured limit unchanged (spec 15 §4.2).
1246
+ const chunkLimitBytes = (0, relocation_direct_transfer_1.effectiveActorJoinChunkLimitBytes)(limits.relocationPayloadChunkLimitBytes, advertisedReceiveChunkLimitBytes);
1247
+ const plan = (0, relocation_direct_transfer_1.planRelocationChunks)(encoded, chunkLimitBytes);
1248
+ const convergenceDeadlineAtMs = signal === undefined
1249
+ ? performance.now() + RELOCATION_OPERATION_RETENTION_MS
1250
+ : controlDeadlineAtMs;
1251
+ let readyReceived = false;
1252
+ let sourceCommitted = false;
1253
+ try {
1254
+ const prepare = {
1255
+ kind: 'prepare',
1256
+ relocation,
1257
+ targetAttemptGeneration,
1258
+ coordinator,
1259
+ target: targetFence,
1260
+ initiatorRole: 'source',
1261
+ object,
1262
+ sourceNodeRid: coordinator.nodeRid,
1263
+ sourceNodeGeneration: coordinator.nodeGeneration,
1264
+ payloadTotalLength: BigInt(plan.totalLength),
1265
+ payloadChunkCount: plan.chunkCount,
1266
+ payloadChecksumCrc32c: plan.checksumCrc32c,
1267
+ applicationVersion: target.applicationVersion
1268
+ };
1269
+ // Start the Restore request first (it also registers the temporary
1270
+ // queue and the assembly on the target), then stream the payload chunks
1271
+ // on the same ordered connection. The Ready reply arrives only after
1272
+ // the target assembled, verified, and restored the payload.
1273
+ const readyOperation = this.sendControl(meshName, target.rid, prepare, signal, controlDeadlineAtMs, encodePrepareSideband(captured.envelope));
1274
+ try {
1275
+ relocationDebug('coordinator.state_transfer_begin', { aggregateId: captured.envelope.aggregateId });
1276
+ await this.sendRelocationStateChunks(meshName, target, prepare, encoded, plan, signal);
1277
+ }
1278
+ catch (chunkError) {
1279
+ readyOperation.catch(() => undefined);
1280
+ throw chunkError;
1281
+ }
1282
+ relocationDebug('coordinator.await_ready', { aggregateId: captured.envelope.aggregateId });
1283
+ const ready = await readyOperation;
1284
+ relocationDebug('coordinator.ready_received', { aggregateId: captured.envelope.aggregateId });
1285
+ validateControlResponse(prepare, ready);
1286
+ // Ready arms the target's cutover-wait fallback. From this point
1287
+ // forward the source can no longer reopen dispatch without risking two
1288
+ // owners.
1289
+ readyReceived = true;
1290
+ const boundaryBatch = [];
1291
+ for (const session of sessions) {
1292
+ const participant = captured.envelope.participants.find(value => value.objectKind === 'actor'
1293
+ && (0, authority_key_codec_1.decodeAuthorityKey)({ value: value.key }).globalId
1294
+ === session.state.actorId);
1295
+ if (participant === undefined) {
1296
+ throw new Error(`Relocation Actor '${session.state.actorId}' is missing from its envelope.`);
1297
+ }
1298
+ for (const packet of session.prepared.takeRelocationRelay()) {
1299
+ const frozenRecord = canonicalRelayFrozenRecord(participant, packet, coordinator, targetFence);
1300
+ const data = {
1301
+ kind: 'data',
1302
+ relocation,
1303
+ targetAttemptGeneration,
1304
+ coordinator,
1305
+ senderRole: 'source',
1306
+ object: relocationObjectForParticipant(participant),
1307
+ frozenRecord
1308
+ };
1309
+ boundaryBatch.push({
1310
+ frame: (0, service_relocation_control_1.encodeServiceRelocationControlRequest)(data),
1311
+ canonicalBytes: frozenRecord.canonicalBytes
1312
+ });
1313
+ }
1314
+ }
1315
+ const cutoverFrame = (0, service_relocation_control_1.encodeServiceRelocationControlRequest)({
1316
+ kind: 'cutover',
1317
+ relocation,
1318
+ targetAttemptGeneration,
1319
+ coordinator,
1320
+ senderRole: 'source',
1321
+ object,
1322
+ boundaryRecordCount: BigInt(boundaryBatch.length),
1323
+ boundaryChecksumCrc32c: (0, service_relocation_runtime_1.crc32c)(Buffer.concat(boundaryBatch.map(value => value.canonicalBytes)))
1324
+ });
1325
+ // The one-way cutover submit reaches a terminal result exactly once;
1326
+ // success and failure both end source dispatch permanently. The batch
1327
+ // copy stays for the retransmission window (spec 28 §4.4).
1328
+ let submitFailure;
1329
+ try {
1330
+ for (const record of boundaryBatch) {
1331
+ await this.submitControlFrame(meshName, target.rid, record.frame, 'relay');
1332
+ }
1333
+ await this.submitControlFrame(meshName, target.rid, cutoverFrame, 'cutover');
1334
+ }
1335
+ catch (error) {
1336
+ submitFailure = error;
1337
+ console.warn('[zlink.runtime.relocation.cutover_submit_failed]', relayAuthorityId, error);
1338
+ }
1339
+ this.beginSourceCutoverWindow(meshName, target.rid, relayAuthorityId, [...boundaryBatch.map(value => value.frame), cutoverFrame], submitFailure !== undefined, limits);
1340
+ await this.waitForTargetAuthorities(captured.envelope, targetFence, convergenceDeadlineAtMs, signal);
1341
+ relocationDebug('coordinator.target_authorities_observed', { aggregateId: captured.envelope.aggregateId });
1342
+ for (const session of sessions)
1343
+ session.prepared.setReplayResults([]);
1344
+ await captured.commitSource();
1345
+ sourceCommitted = true;
1346
+ await this.options.reconcileStatefulAuthorityRoutes?.(signal);
1347
+ }
1348
+ catch (error) {
1349
+ if (!readyReceived)
1350
+ throw error;
1351
+ try {
1352
+ await this.waitForTargetAuthorities(captured.envelope, targetFence, convergenceDeadlineAtMs);
1353
+ if (!sourceCommitted) {
1354
+ for (const session of sessions)
1355
+ session.prepared.setReplayResults([]);
1356
+ await captured.commitSource();
1357
+ sourceCommitted = true;
1358
+ }
1359
+ await this.options.reconcileStatefulAuthorityRoutes?.();
1360
+ const authority = await requireAuthority(this.requireLocationStore(), { value: primaryKey(captured.envelope) }, undefined);
1361
+ throw new service_relocation_coordinator_1.ServiceRelocationPostCommitError(authority, { id: `${captured.envelope.aggregateId}:${captured.envelope.aggregateGeneration}` }, error);
1362
+ }
1363
+ catch (convergenceError) {
1364
+ if (convergenceError instanceof service_relocation_coordinator_1.ServiceRelocationPostCommitError) {
1365
+ throw convergenceError;
1366
+ }
1367
+ throw new AggregateError([error, convergenceError], 'Relocation became irreversible after Ready and target convergence failed.');
1368
+ }
1369
+ }
1370
+ finally {
1371
+ if (!readyReceived) {
1372
+ // Only an explicit failure before the Ready reply becomes accepted
1373
+ // restores the source from the memory payload (spec 28 §9).
1374
+ await captured.abortSource().catch(() => undefined);
1375
+ }
1376
+ if (this.relocationAuthorityKeys.get(relayAuthorityId) === relayAuthorityKey) {
1377
+ this.relocationAuthorityKeys.delete(relayAuthorityId);
1378
+ }
1379
+ }
1380
+ }
1381
+ /** Streams the payload chunks of one stage under the effective in-flight budgets. */
1382
+ async sendRelocationStateChunks(meshName, target, identity, encoded, plan, signal) {
1383
+ for (let ordinal = 0; ordinal < plan.chunkCount; ordinal += 1) {
1384
+ const chunkData = (0, relocation_direct_transfer_1.relocationChunkAt)(encoded, plan, ordinal);
1385
+ const releases = await this.acquireRelocationBudget(String(target.rid), chunkData.byteLength, signal);
1386
+ try {
1387
+ await this.sendControlOneWay(meshName, target.rid, {
1388
+ kind: 'state',
1389
+ relocation: identity.relocation,
1390
+ targetAttemptGeneration: identity.targetAttemptGeneration,
1391
+ coordinator: identity.coordinator,
1392
+ senderRole: 'source',
1393
+ object: identity.object,
1394
+ chunkOrdinal: ordinal,
1395
+ chunkData
1396
+ });
1397
+ }
1398
+ finally {
1399
+ for (const release of releases)
1400
+ release();
1401
+ }
1402
+ }
1403
+ }
1404
+ /**
1405
+ * Phase 1 in-flight accounting: the charge covers the submit window of one
1406
+ * chunk under min(configured, conservative) budgets per peer and per node.
1407
+ */
1408
+ async acquireRelocationBudget(targetRid, bytes, signal) {
1409
+ const releases = [];
1410
+ const nodeBudget = this.requireNodePayloadBudget();
1411
+ const peerBudget = this.requirePeerPayloadBudget(targetRid);
1412
+ releases.push(await nodeBudget.acquire(bytes, signal));
1413
+ try {
1414
+ releases.push(await peerBudget.acquire(bytes, signal));
1415
+ }
1416
+ catch (error) {
1417
+ for (const release of releases)
1418
+ release();
1419
+ throw error;
1420
+ }
1421
+ return releases;
1422
+ }
1423
+ /** Pre-seal admission wait — a full budget delays the next unit before seal. */
1424
+ async waitForRelocationBudgetHeadroom(targetRid, signal) {
1425
+ await this.requireNodePayloadBudget().waitForHeadroom(signal);
1426
+ await this.requirePeerPayloadBudget(targetRid).waitForHeadroom(signal);
1427
+ }
1428
+ requireNodePayloadBudget() {
1429
+ this.nodePayloadBudget ??= new relocation_direct_transfer_1.ZLinkRelocationInFlightBudget((0, relocation_direct_transfer_1.effectiveRelocationBudgetBytes)(this.relocationLimits().relocationNodeInFlightPayloadBudgetBytes));
1430
+ return this.nodePayloadBudget;
1431
+ }
1432
+ requirePeerPayloadBudget(targetRid) {
1433
+ let budget = this.peerPayloadBudgets.get(targetRid);
1434
+ if (budget === undefined) {
1435
+ budget = new relocation_direct_transfer_1.ZLinkRelocationInFlightBudget((0, relocation_direct_transfer_1.effectiveRelocationBudgetBytes)(this.relocationLimits().relocationInFlightPayloadBudgetBytes));
1436
+ this.peerPayloadBudgets.set(targetRid, budget);
1437
+ }
1438
+ return budget;
1439
+ }
1440
+ /**
1441
+ * Starts the source retransmission window after the cutover submit
1442
+ * terminal. The boundary batch and cutover copies live in framework memory
1443
+ * (not charged to the in-flight budget) and are cleaned exactly once when
1444
+ * the window ends. While the window is open a failed submit retries the
1445
+ * whole batch on the (re-established) connection. S4 — the Message Follow
1446
+ * route removal point — closes the unit for SafeToShutdown.
1447
+ */
1448
+ beginSourceCutoverWindow(meshName, targetNodeRid, relocationKey, frames, initialSubmitFailed, limits) {
1449
+ const submittedAt = performance.now();
1450
+ const window = {
1451
+ meshName,
1452
+ targetNodeRid,
1453
+ frames,
1454
+ cutoverSubmittedAtMs: submittedAt,
1455
+ windowClosed: false,
1456
+ followExpired: false
1457
+ };
1458
+ this.sourceCutoverWindows.set(relocationKey, window);
1459
+ const settle = () => {
1460
+ if (window.windowClosed && window.followExpired) {
1461
+ this.sourceCutoverWindows.delete(relocationKey);
1462
+ }
1463
+ };
1464
+ window.windowTimer = setTimeout(() => {
1465
+ window.windowClosed = true;
1466
+ window.frames = undefined;
1467
+ if (window.retryTimer !== undefined)
1468
+ clearTimeout(window.retryTimer);
1469
+ settle();
1470
+ }, limits.relocationCutoverWaitTimeoutMs);
1471
+ window.windowTimer.unref();
1472
+ window.followTimer = setTimeout(() => {
1473
+ window.followExpired = true;
1474
+ // S1→S4 route convergence: the span the source must keep its Message
1475
+ // Follow route (spec 30 §7.1).
1476
+ this.options.metrics?.duration('zlink.relocation.route_convergence', Math.max(0, performance.now() - submittedAt) / 1000, { mesh_name: meshName });
1477
+ settle();
1478
+ }, limits.messageFollowDurationMs);
1479
+ window.followTimer.unref();
1480
+ if (initialSubmitFailed)
1481
+ this.scheduleCutoverRetransmit(window);
1482
+ }
1483
+ scheduleCutoverRetransmit(window) {
1484
+ if (window.windowClosed || window.frames === undefined)
1485
+ return;
1486
+ window.retryTimer = setTimeout(() => {
1487
+ void (async () => {
1488
+ const frames = window.frames;
1489
+ if (window.windowClosed || frames === undefined)
1490
+ return;
1491
+ try {
1492
+ for (const frame of frames) {
1493
+ await this.submitControlFrame(window.meshName, window.targetNodeRid, frame, 'cutover retransmission');
1494
+ }
1495
+ }
1496
+ catch {
1497
+ this.scheduleCutoverRetransmit(window);
1498
+ }
1499
+ })();
1500
+ }, 250);
1501
+ window.retryTimer.unref();
1502
+ }
1503
+ /**
1504
+ * True when every relocation this source started reached its Message
1505
+ * Follow route removal point (S4) and its cutover retransmission window
1506
+ * ended — both source-local events (spec 30 §11).
1507
+ */
1508
+ isSafeToShutdown() {
1509
+ return this.sourceCutoverWindows.size === 0;
1510
+ }
1511
+ async releaseParticipantAuthorities(envelope, primaryKey, signal) {
1512
+ for (const participant of envelope.participants) {
1513
+ if (participant.key === primaryKey)
1514
+ continue;
1515
+ const key = { value: participant.key };
1516
+ const current = await requireAuthority(this.requireLocationStore(), key, signal);
1517
+ const publication = this.codec.read(current.payload);
1518
+ if (publication === undefined)
1519
+ continue;
1520
+ const result = await this.requireLocationStore().compareExchangeAuthority(key, current.storeVersion, {
1521
+ kind: 'put',
1522
+ generationTransition: 'preserve',
1523
+ payload: this.codec.clear(current.payload, publication.reference)
1524
+ }, signal);
1525
+ if (result.kind !== 'stored') {
1526
+ throw new Error(`Participant '${participant.key}' recovery pointer release failed.`);
1527
+ }
1528
+ }
1529
+ }
1530
+ /** Restores the hidden object and its saved-work prefix before Ready. */
1531
+ async handlePrepareControl(meshName, stagingId, request, sourceNodeRid, signal) {
1532
+ if (sourceNodeRid === null || String(sourceNodeRid) !== request.sourceNodeRid) {
1533
+ throw new Error('Relocation prepare source node fence does not match the authenticated peer.');
1534
+ }
1535
+ const targetStatus = this.requireMeshNode(meshName).status();
1536
+ const targetOwner = this.options.currentOwner();
1537
+ const targetDescriptor = this.options.localDescriptor?.(meshName);
1538
+ if (targetOwner === undefined
1539
+ || String(targetStatus.routingId) !== request.target.nodeRid
1540
+ || targetStatus.lifecycleGeneration !== request.target.nodeGeneration
1541
+ || targetOwner.ownerId !== request.target.ownerId
1542
+ || targetOwner.leaseGeneration !== request.target.ownerLeaseGeneration
1543
+ || targetDescriptor !== undefined
1544
+ && targetDescriptor.applicationVersion !== request.applicationVersion) {
1545
+ throw new Error('Relocation prepare target fence does not match the target owner.');
1546
+ }
1547
+ const fingerprint = stringifyWire(request);
1548
+ const existing = this.targetStages.get(stagingId);
1549
+ if (existing !== undefined) {
1550
+ if (existing.offer.authenticatedSourceNodeRid !== String(sourceNodeRid)
1551
+ || existing.offer.prepareFingerprint !== fingerprint) {
1552
+ throw new Error('Relocation prepare retry source node changed.');
1553
+ }
1554
+ return relocationReady(request);
1555
+ }
1556
+ const terminal = this.terminalTargets.get(stagingId);
1557
+ if (terminal !== undefined) {
1558
+ if (terminal !== fingerprint) {
1559
+ throw new Error(`Relocation '${stagingId}' repeated Prepare with different bytes.`);
1560
+ }
1561
+ this.terminalTargets.touch(stagingId);
1562
+ return relocationReady(request);
1563
+ }
1564
+ const pendingAssembly = this.targetAssemblies.get(stagingId);
1565
+ if (pendingAssembly === undefined || pendingAssembly.fingerprint !== fingerprint) {
1566
+ throw new Error(`Relocation '${stagingId}' has no matching payload assembly.`);
1567
+ }
1568
+ // The directly transferred payload replaces the shared durable root: the
1569
+ // Restore starts only after every chunk arrived and the assembled bytes
1570
+ // matched the manifest checksum exactly once.
1571
+ let payload;
1572
+ try {
1573
+ payload = await pendingAssembly.assembly.payload();
1574
+ }
1575
+ catch (error) {
1576
+ // A rejection observed after dispose() started is the runtime shutting
1577
+ // down, not a chunk-assembly or checksum integrity failure — it must
1578
+ // not be reported as DataLost(35). There is no dedicated ShuttingDown
1579
+ // wire code in the vocabulary yet, so it falls through unwrapped to
1580
+ // the generic InternalFailure code (spec 15 §4).
1581
+ if (this.disposed)
1582
+ throw error;
1583
+ const message = error !== null && typeof error === 'object' && 'message' in error
1584
+ ? error.message ?? error
1585
+ : error;
1586
+ throw new ServiceRelocationDataLostError(String(message));
1587
+ }
1588
+ const envelope = (0, service_relocation_runtime_1.decodeServiceRelocationEnvelope)(payload, request.targetAttemptGeneration);
1589
+ const inventoryEnvelope = attachPrepareBoundSessions(await this.resolveTargetParticipantInventory(request, envelope, signal), request.nodeInternalBoundSessions);
1590
+ validatePrepareEnvelope(request, inventoryEnvelope);
1591
+ let materialized;
1592
+ let reservation;
1593
+ try {
1594
+ // Deferred Join completion publishes into the source authority's
1595
+ // canonical relocation slot. Do that while the row is still CAS-able;
1596
+ // the aggregate marker installed by reserveTargetForPrepare deliberately
1597
+ // rejects unrelated authority CAS until commit/abort.
1598
+ materialized = await this.materializeTargetEnvelope(meshName, inventoryEnvelope, signal);
1599
+ await materialized.owner.restoreSavedWork(materialized.staging, signal);
1600
+ reservation = await this.reserveTargetForPrepare(meshName, request, inventoryEnvelope, materialized.target, signal);
1601
+ const offer = {
1602
+ prepare: request,
1603
+ prepareFingerprint: fingerprint,
1604
+ authenticatedSourceNodeRid: String(sourceNodeRid),
1605
+ envelope: inventoryEnvelope,
1606
+ restoreDeadlineAtMs: performance.now() + RELOCATION_OPERATION_RETENTION_MS,
1607
+ reservation
1608
+ };
1609
+ const stage = {
1610
+ offer,
1611
+ ...materialized,
1612
+ phase: 'ready',
1613
+ lane: Promise.resolve(),
1614
+ cutoverReceived: false,
1615
+ boundaryRelay: []
1616
+ };
1617
+ this.targetStages.set(stagingId, stage);
1618
+ }
1619
+ catch (error) {
1620
+ if (reservation !== undefined) {
1621
+ await this.abortTargetReservation(reservation, signal).catch(() => undefined);
1622
+ }
1623
+ if (materialized !== undefined) {
1624
+ await materialized.owner.abort(materialized.staging).catch(() => undefined);
1625
+ }
1626
+ throw error;
1627
+ }
1628
+ return relocationReady(request);
1629
+ }
1630
+ armTargetCutoverFallback(meshName, stagingId) {
1631
+ const stage = this.targetStages.get(stagingId);
1632
+ if (stage === undefined || stage.fallback !== undefined || stage.finalize !== undefined)
1633
+ return;
1634
+ stage.fallback = setTimeout(() => {
1635
+ void this.beginTargetFinalize(meshName, stagingId, stage, true)
1636
+ .catch(error => console.error('[zlink.runtime.relocation.location_update_failed]', error));
1637
+ }, this.relocationLimits().relocationCutoverWaitTimeoutMs);
1638
+ stage.fallback.unref();
1639
+ }
1640
+ async handleOneWayControl(meshName, request, sourceNodeRid, signal) {
1641
+ if (request.senderRole !== 'source' || sourceNodeRid === null) {
1642
+ throw new Error('Relocation one-way control has no exact source peer.');
1643
+ }
1644
+ const stagingId = relocationStagingId(request);
1645
+ const stage = this.targetStages.get(stagingId);
1646
+ if (stage === undefined) {
1647
+ if (this.terminalTargets.get(stagingId) !== undefined) {
1648
+ if (request.kind === 'cutover') {
1649
+ console.warn('[zlink.runtime.relocation.late_cutover]', stagingId);
1650
+ }
1651
+ return;
1652
+ }
1653
+ throw new Error(`Relocation staging '${stagingId}' is missing.`);
1654
+ }
1655
+ validateTargetOneWayControl(stage, request, sourceNodeRid);
1656
+ if (request.kind === 'data') {
1657
+ stage.lane = stage.lane.then(() => this.stageBoundaryRelay(stage, request));
1658
+ await stage.lane;
1659
+ return;
1660
+ }
1661
+ if (stage.cutoverReceived || stage.phase !== 'ready') {
1662
+ console.warn('[zlink.runtime.relocation.late_cutover]', stagingId);
1663
+ return;
1664
+ }
1665
+ this.reconcileBoundaryRelay(stage, request, stagingId);
1666
+ stage.cutoverReceived = true;
1667
+ if (stage.fallback !== undefined)
1668
+ clearTimeout(stage.fallback);
1669
+ await this.beginTargetFinalize(meshName, stagingId, stage, false, signal);
1670
+ }
1671
+ /** Validates one boundary relay record and buffers it until cutover applies it. */
1672
+ async stageBoundaryRelay(stage, request) {
1673
+ this.validateRelocationData(stage, request);
1674
+ stage.boundaryRelay.push(request);
1675
+ }
1676
+ /**
1677
+ * Compares the cutover confirmation values against the staged boundary
1678
+ * relay. A retransmitted batch replaces a partially received span as a
1679
+ * whole (the retransmission always resends the entire batch, so the exact
1680
+ * span is the staged suffix of `boundaryRecordCount` records).
1681
+ */
1682
+ reconcileBoundaryRelay(stage, request, stagingId) {
1683
+ if (request.boundaryRecordCount > BigInt(Number.MAX_SAFE_INTEGER)) {
1684
+ throw new Error('Relocation cutover boundary record count is out of range.');
1685
+ }
1686
+ const expectedCount = Number(request.boundaryRecordCount);
1687
+ const staged = stage.boundaryRelay;
1688
+ const checksumOf = (records) => (0, service_relocation_runtime_1.crc32c)(Buffer.concat(records.map(value => value.frozenRecord.canonicalBytes)));
1689
+ if (staged.length === expectedCount
1690
+ && checksumOf(staged) === request.boundaryChecksumCrc32c) {
1691
+ return;
1692
+ }
1693
+ if (staged.length > expectedCount) {
1694
+ const suffix = staged.slice(staged.length - expectedCount);
1695
+ if (checksumOf(suffix) === request.boundaryChecksumCrc32c) {
1696
+ console.warn('[zlink.runtime.relocation.boundary_batch_replaced]', stagingId);
1697
+ staged.splice(0, staged.length - expectedCount);
1698
+ return;
1699
+ }
1700
+ }
1701
+ // Spec 28 §4.4 — on an ordered connection this comparison always holds on
1702
+ // the normal path; a mismatch signals an implementation defect.
1703
+ throw new Error(`Relocation cutover boundary confirmation mismatch for '${stagingId}' `
1704
+ + `(staged=${staged.length} declared=${expectedCount}).`);
1705
+ }
1706
+ beginTargetFinalize(meshName, stagingId, stage, fallback, signal) {
1707
+ if (stage.finalize !== undefined)
1708
+ return stage.finalize;
1709
+ if (fallback) {
1710
+ console.warn('[zlink.runtime.relocation.cutover_timeout]', stagingId);
1711
+ this.options.metrics?.count('zlink.relocation.cutover_timeout', 1, {
1712
+ mesh_name: meshName
1713
+ });
1714
+ }
1715
+ const finalize = stage.lane.then(() => this.finalizeTargetStage(meshName, stagingId, stage, signal));
1716
+ stage.finalize = finalize;
1717
+ stage.lane = finalize;
1718
+ return finalize;
1719
+ }
1720
+ async finalizeTargetStage(meshName, stagingId, stage, signal) {
1721
+ if (stage.phase !== 'ready')
1722
+ return;
1723
+ stage.phase = 'finalizing';
1724
+ let authorityCommitted = false;
1725
+ let authority;
1726
+ let resumeStartedAt;
1727
+ try {
1728
+ // The boundary relay span is applied to the temporary queue before the
1729
+ // owner CAS so the merged order is saved work, pre-boundary relay, then
1730
+ // post-boundary temporary records (spec 28 §4.6).
1731
+ for (const relay of stage.boundaryRelay.splice(0)) {
1732
+ await this.applyRelocationData(stage, relay, signal);
1733
+ }
1734
+ authority = await this.commitTargetReservation(stage, stage.offer.reservation, signal);
1735
+ authorityCommitted = true;
1736
+ resumeStartedAt = performance.now();
1737
+ stage.phase = 'committed';
1738
+ await stage.owner.normalize(stage.staging, authority, signal);
1739
+ await stage.owner.publish(stage.staging, authority, signal);
1740
+ // The target may have visited this Actor before and still retain that
1741
+ // tenure in its private Actor-client resolver. The target-only CAS is
1742
+ // now authoritative, so expire the old projection before OnJoinedActor
1743
+ // can issue an Actor request and deadlock behind source leave.
1744
+ for (const hidden of stage.staging.hidden.values()) {
1745
+ if (hidden.actor !== undefined) {
1746
+ this.options.invalidateActorRoute?.(hidden.actor.context.actorId);
1747
+ }
1748
+ }
1749
+ await this.finalizeActorJoinProfiles(meshName, stage, signal);
1750
+ // Actor Join completion may advance its accepted-completion journal in
1751
+ // the canonical authority slot. Try to clear that final publication
1752
+ // before admission becomes externally visible so a later Join cannot
1753
+ // reserve against the previous root. A bounded CAS conflict must not
1754
+ // roll back already committed target ownership or strand its staged
1755
+ // object: the next reservation recognizes the retained journal root and
1756
+ // continues its existing cleanup/retry path.
1757
+ try {
1758
+ await this.clearTargetRelocationPublication(stage, authority, signal);
1759
+ }
1760
+ catch (error) {
1761
+ console.warn('[zlink.runtime.relocation.publication_clear_failed]', stagingId, error);
1762
+ this.options.metrics?.count('zlink.relocation.publication_clear_failed', 1, {
1763
+ mesh_name: meshName
1764
+ });
1765
+ }
1766
+ await stage.owner.openAdmission(stage.staging, signal);
1767
+ // S2→S3: owner confirmation to application dispatch opening.
1768
+ this.options.metrics?.duration('zlink.relocation.target_resume', Math.max(0, performance.now() - resumeStartedAt) / 1000, { mesh_name: meshName });
1769
+ await this.publishSessionRoutes(stage.staging);
1770
+ await this.relayTerminalReplies(meshName, stage, this.targetReplyRelayCoordinator(meshName, stage, authority), signal);
1771
+ stage.phase = 'open';
1772
+ this.terminalTargets.remember(stagingId, stage.offer.prepareFingerprint);
1773
+ this.targetStages.delete(stagingId);
1774
+ this.targetAssemblies.delete(stagingId);
1775
+ }
1776
+ catch (error) {
1777
+ stage.phase = 'failed';
1778
+ this.terminalTargets.remember(stagingId, stage.offer.prepareFingerprint);
1779
+ this.targetStages.delete(stagingId);
1780
+ this.targetAssemblies.delete(stagingId);
1781
+ if (!authorityCommitted) {
1782
+ await this.abortTargetStage(stage).catch(() => undefined);
1783
+ throw error;
1784
+ }
1785
+ if (authority !== undefined) {
1786
+ throw new service_relocation_coordinator_1.ServiceRelocationPostCommitError(authority, stage.staging, error);
1787
+ }
1788
+ throw error;
1789
+ }
1790
+ }
1791
+ validateRelocationData(stage, request) {
1792
+ const frozen = request.frozenRecord;
1793
+ const target = frozen.target;
1794
+ const payload = frozen.applicationPayload;
1795
+ const preparedTarget = stage.offer.prepare.target;
1796
+ if (request.object.kind !== 'actor'
1797
+ || target?.kind !== 'actor'
1798
+ || payload === undefined
1799
+ || payload.packetName !== '__zlink.actor.handoff.accepted'
1800
+ || target.actorId !== request.object.actorId
1801
+ || target.generation !== request.object.objectGeneration
1802
+ || target.targetNodeRid !== preparedTarget.nodeRid
1803
+ || target.targetNodeGeneration !== preparedTarget.nodeGeneration
1804
+ || target.authorityOwnerGeneration
1805
+ !== request.object.expectedAuthorityOwnerGeneration + 1n
1806
+ || target.ownerLeaseGeneration !== preparedTarget.ownerLeaseGeneration) {
1807
+ throw new Error('Relocation data does not target the exact temporary Actor queue.');
1808
+ }
1809
+ const key = (0, authority_key_codec_1.encodeAuthorityKey)('actor', request.object.actorId).value;
1810
+ const participant = stage.staging.envelope.participants.find(value => value.key === key);
1811
+ if (participant === undefined
1812
+ || participant.objectGeneration !== request.object.objectGeneration
1813
+ || participant.authorityOwnerGeneration
1814
+ !== request.object.expectedAuthorityOwnerGeneration) {
1815
+ throw new Error('Relocation data Actor is not part of the prepared unit.');
1816
+ }
1817
+ }
1818
+ async applyRelocationData(stage, request, signal) {
1819
+ const payload = request.frozenRecord.applicationPayload;
1820
+ await stage.owner.replayRelayedMessage(stage.staging, (0, authority_key_codec_1.encodeAuthorityKey)('actor', request.object.actorId).value, { sequence: 0n, payload: Buffer.from(payload.bytes) }, signal);
1821
+ }
1822
+ async finalizeActorJoinProfiles(meshName, stage, signal) {
1823
+ const manager = this.options.spotManager();
1824
+ if (manager === undefined)
1825
+ return;
1826
+ for (const hidden of stage.staging.hidden.values()) {
1827
+ if (hidden.actor === undefined)
1828
+ continue;
1829
+ const state = this.options.actorManager()?.getState(hidden.actor.context.actorId);
1830
+ const nativeRef = state?.nativeActorRef;
1831
+ if (nativeRef === undefined) {
1832
+ throw new Error(`Actor '${hidden.actor.context.actorId}' relocation target has no native identity.`);
1833
+ }
1834
+ await manager.finalizeActorJoinRelocation(meshName, actorJoinAdmissionIdentity(stage.staging.envelope), hidden.actor, (0, actor_runtime_state_1.toFrameworkActorRef)(nativeRef, meshName), sourceNodeRid => this.submitActorJoinSourceLeave(meshName, sourceNodeRid, stage.staging.envelope.aggregateId, hidden.actor.context.actorId), signal);
1835
+ }
1836
+ }
1837
+ async submitActorJoinSourceLeave(meshName, sourceNodeRid, relocationId, actorId) {
1838
+ try {
1839
+ const submitted = await this.requireMeshNode(meshName).sendToNode(sourceNodeRid, Buffer.from(JSON.stringify({
1840
+ packetName: actor_remote_wire_1.ZLINK_REMOTE_ACTOR_SOURCE_LEAVE_TERMINAL,
1841
+ transferId: relocationId,
1842
+ actorId,
1843
+ succeeded: true
1844
+ })));
1845
+ if (submitted !== runtime_values_1.SubmitResult.Ok) {
1846
+ console.warn('[zlink.runtime.relocation.source_leave_submit_failed]', actorId, submitted);
1847
+ }
1848
+ }
1849
+ catch (error) {
1850
+ console.warn('[zlink.runtime.relocation.source_leave_submit_failed]', actorId, error);
1851
+ }
1852
+ }
1853
+ acceptActorJoinSourceLeave(input) {
1854
+ const profile = this.sourceActorJoinProfiles.get(input.transferId);
1855
+ if (profile === undefined) {
1856
+ const terminalActorId = this.terminalActorJoinSourceLeaves.get(input.transferId);
1857
+ if (terminalActorId === undefined)
1858
+ return false;
1859
+ if (terminalActorId !== input.actorId || !input.succeeded) {
1860
+ throw new Error(`Actor Join relocation '${input.transferId}' source leave identity changed.`);
1861
+ }
1862
+ this.terminalActorJoinSourceLeaves.touch(input.transferId);
1863
+ return true;
1864
+ }
1865
+ if (profile.state.actorId !== input.actorId || !input.succeeded) {
1866
+ throw new Error(`Actor Join relocation '${input.transferId}' source leave identity changed.`);
1867
+ }
1868
+ this.sourceActorJoinProfiles.delete(input.transferId);
1869
+ this.terminalActorJoinSourceLeaves.remember(input.transferId, input.actorId);
1870
+ void profile.ready.then(async () => {
1871
+ await this.options.actorTransfer.completeRelocationSourceLeave(profile.actor, profile.sourceSpotId);
1872
+ await this.options.actorManager()?.completeRelocationSource(input.actorId, profile.sourceActorRef);
1873
+ }).catch(error => {
1874
+ console.error('[zlink.runtime.relocation.source_leave_failed]', error);
1875
+ });
1876
+ return true;
1877
+ }
1878
+ async sendControlOneWay(meshName, targetNodeRid, request) {
1879
+ await this.submitControlFrame(meshName, targetNodeRid, (0, service_relocation_control_1.encodeServiceRelocationControlRequest)(request), request.kind);
1880
+ }
1881
+ async submitControlFrame(meshName, targetNodeRid, frame, kind) {
1882
+ const submitted = await this.sendInfrastructureControl(meshName, targetNodeRid, frame);
1883
+ if (submitted !== runtime_values_1.SubmitResult.Ok) {
1884
+ throw new Error(`Relocation ${kind} was not accepted by RouteMesh.`);
1885
+ }
1886
+ }
1887
+ async waitForTargetAuthorities(envelope, target, deadlineAtMs, signal) {
1888
+ for (;;) {
1889
+ signal?.throwIfAborted();
1890
+ let exact = true;
1891
+ for (const participant of envelope.participants) {
1892
+ const current = await this.requireLocationStore().readAuthority({ value: participant.key }, signal);
1893
+ if (current.kind !== 'snapshot'
1894
+ || current.objectGeneration !== participant.objectGeneration
1895
+ || current.ownerId !== target.ownerId
1896
+ || current.ownerLeaseGeneration !== target.ownerLeaseGeneration
1897
+ || current.authorityOwnerGeneration <= participant.authorityOwnerGeneration
1898
+ || String(current.allocation.descriptor.rid) !== target.nodeRid
1899
+ || current.allocation.descriptorLifecycleGeneration !== target.nodeGeneration) {
1900
+ exact = false;
1901
+ break;
1902
+ }
1903
+ }
1904
+ if (exact)
1905
+ return;
1906
+ if (performance.now() >= deadlineAtMs) {
1907
+ throw new Error('Relocation target owner was not confirmed before its original deadline.');
1908
+ }
1909
+ await new Promise(resolve => setTimeout(resolve, 10));
1910
+ }
1911
+ }
1912
+ async clearTargetRelocationPublication(stage, primary, signal) {
1913
+ await this.releaseParticipantAuthorities(stage.staging.envelope, stage.staging.primaryAuthorityKey.value, signal);
1914
+ // The deferred-Join journal advances its completion cursor with its
1915
+ // own authority CAS while the target finalizes, so the initially
1916
+ // captured storeVersion can be stale by the time the relocation
1917
+ // wrapper is cleared. Re-read and retry on conflict instead of turning
1918
+ // a completed relocation into a post-commit failure (spec 28 —
1919
+ // retryable store conflicts converge on the same CAS and the same
1920
+ // relocation identity until the outcome is determined).
1921
+ let current = primary;
1922
+ for (let attempt = 0; attempt < 16; attempt += 1) {
1923
+ const publication = this.codec.read(current.payload);
1924
+ if (publication === undefined)
1925
+ return;
1926
+ const result = await this.requireLocationStore().compareExchangeAuthority(stage.staging.primaryAuthorityKey, current.storeVersion, {
1927
+ kind: 'put',
1928
+ generationTransition: 'preserve',
1929
+ payload: this.codec.clear(current.payload, publication.reference)
1930
+ }, signal);
1931
+ if (result.kind === 'stored')
1932
+ return;
1933
+ const read = await this.requireLocationStore().readAuthority(stage.staging.primaryAuthorityKey, signal);
1934
+ if (read.kind !== 'snapshot')
1935
+ break;
1936
+ current = read;
1937
+ }
1938
+ throw new Error('Relocation target authority normalization CAS failed.');
1939
+ }
1940
+ async handleReplyRelay(meshName, relay, sourceNodeRid, signal) {
1941
+ if (sourceNodeRid === null) {
1942
+ throw new Error('Relocation reply relay has no authenticated target node.');
1943
+ }
1944
+ await this.requireAdmittedPeer(meshName, String(sourceNodeRid), relay.coordinator, signal);
1945
+ const relocationId = wireIdText(relay.relocation);
1946
+ const authorityKey = this.relocationAuthorityKeys.get(relocationId);
1947
+ if (authorityKey === undefined) {
1948
+ throw new Error('Relocation reply relay has no registered durable authority.');
1949
+ }
1950
+ const authority = await requireAuthority(this.requireLocationStore(), { value: authorityKey }, signal);
1951
+ if (authority.storeVersion.value !== relay.coordinator.expectedAuthorityStoreVersion
1952
+ || authority.ownerId !== relay.coordinator.ownerId
1953
+ || authority.ownerLeaseGeneration !== relay.coordinator.leaseGeneration
1954
+ || String(authority.allocation.descriptor.rid) !== relay.coordinator.nodeRid
1955
+ || authority.allocation.descriptorLifecycleGeneration
1956
+ !== relay.coordinator.nodeGeneration) {
1957
+ throw new Error('Relocation reply relay coordinator authority fence is stale.');
1958
+ }
1959
+ const accepted = this.options.actorTransfer.relayCanonicalMaintenanceTerminal(wireIdText(relay.operation), relay.replyRouteId.toString(), handoffResultFromRelay(relay), sourceNodeRid);
1960
+ if (accepted.status !== 'terminalReceived' && accepted.status !== 'alreadyTerminal'
1961
+ || accepted.source === undefined) {
1962
+ throw new Error('Canonical relocation reply relay collided with another source route.');
1963
+ }
1964
+ const requestSource = handoffSourceFence(accepted.source);
1965
+ const localStatus = this.requireMeshNode(meshName).status();
1966
+ const localOwner = this.options.currentOwner();
1967
+ if (localOwner === undefined
1968
+ || requestSource.ownerId !== localOwner.ownerId
1969
+ || requestSource.leaseGeneration !== localOwner.leaseGeneration
1970
+ || !(0, routing_id_1.routingIdsEqual)(requestSource.nodeRid, localStatus.routingId)
1971
+ || requestSource.nodeGeneration !== localStatus.lifecycleGeneration) {
1972
+ throw new Error('Relocation reply relay request-source fence changed after capture.');
1973
+ }
1974
+ const ack = {
1975
+ relocation: relay.relocation,
1976
+ coordinator: relay.coordinator,
1977
+ operation: relay.operation,
1978
+ replyRouteId: relay.replyRouteId,
1979
+ requestSource,
1980
+ status: accepted.status
1981
+ };
1982
+ if (await this.sendInfrastructureControl(meshName, sourceNodeRid, (0, service_stateful_wire_codec_1.encodeMaintenanceReplyRelayAck)(ack)) !== runtime_values_1.SubmitResult.Ok) {
1983
+ throw new Error('Relocation reply relay ACK send was rejected.');
1984
+ }
1985
+ }
1986
+ async sendReplyRelay(meshName, ackTargetNodeRid, request, expectedRequestSource, signal) {
1987
+ const targetRid = String(ackTargetNodeRid);
1988
+ const identityKey = replyRelayIdentityKey(request);
1989
+ const key = replyRelayPendingKey(targetRid, request);
1990
+ if (this.pendingReplyRelays.has(key)) {
1991
+ throw new Error(`Relocation reply relay ACK '${key}' is already pending.`);
1992
+ }
1993
+ return await new Promise((resolve, reject) => {
1994
+ let attempts = 0;
1995
+ const finish = (action) => {
1996
+ const pending = this.pendingReplyRelays.get(key);
1997
+ if (pending?.timer !== undefined)
1998
+ clearTimeout(pending.timer);
1999
+ this.pendingReplyRelays.delete(key);
2000
+ action();
2001
+ };
2002
+ const pending = {
2003
+ ackTargetNodeRid: targetRid,
2004
+ identityKey,
2005
+ request,
2006
+ expectedRequestSource,
2007
+ resolve: delivery => finish(() => resolve(delivery)),
2008
+ reject: error => finish(() => reject(error))
2009
+ };
2010
+ const send = async () => {
2011
+ try {
2012
+ if (signal?.aborted === true) {
2013
+ pending.reject(signal.reason);
2014
+ return;
2015
+ }
2016
+ if (await this.exactSourceLeaseExpired(expectedRequestSource, signal)) {
2017
+ pending.resolve('sourceLeaseExpired');
2018
+ return;
2019
+ }
2020
+ if (++attempts > 120) {
2021
+ pending.reject(new Error(`Relocation reply relay ACK '${key}' timed out.`));
2022
+ return;
2023
+ }
2024
+ await this.sendInfrastructureControl(meshName, ackTargetNodeRid, (0, service_stateful_wire_codec_1.encodeMaintenanceReplyRelay)(request));
2025
+ if (this.pendingReplyRelays.get(key) === pending) {
2026
+ pending.timer = setTimeout(() => void send(), 250);
2027
+ }
2028
+ }
2029
+ catch (error) {
2030
+ pending.reject(error);
2031
+ }
2032
+ };
2033
+ this.pendingReplyRelays.set(key, pending);
2034
+ void send();
2035
+ });
2036
+ }
2037
+ async acceptReplyRelayAck(meshName, ack, sourceNodeRid, signal) {
2038
+ const identityKey = replyRelayIdentityKey(ack);
2039
+ const exactKey = sourceNodeRid === null
2040
+ ? undefined
2041
+ : replyRelayPendingKey(String(sourceNodeRid), ack);
2042
+ const pending = exactKey === undefined ? undefined : this.pendingReplyRelays.get(exactKey);
2043
+ if (pending === undefined) {
2044
+ const collision = [...this.pendingReplyRelays.values()].find(value => value.identityKey === identityKey);
2045
+ collision?.reject(new Error('Relocation reply relay ACK target source collided.'));
2046
+ return;
2047
+ }
2048
+ try {
2049
+ await this.requireAdmittedPeer(meshName, pending.ackTargetNodeRid, pending.expectedRequestSource, signal);
2050
+ if (!sameWireId(ack.relocation, pending.request.relocation)
2051
+ || !sameWireId(ack.operation, pending.request.operation)
2052
+ || ack.replyRouteId !== pending.request.replyRouteId
2053
+ || !sameCoordinator(ack.coordinator, pending.request.coordinator)
2054
+ || !sameRequestSource(ack.requestSource, pending.expectedRequestSource)) {
2055
+ throw new Error('Relocation reply relay ACK does not match its durable source fence.');
2056
+ }
2057
+ pending.resolve(ack.status);
2058
+ }
2059
+ catch (error) {
2060
+ pending.reject(error);
2061
+ }
2062
+ }
2063
+ async requireAdmittedPeer(meshName, authenticatedRid, expected, signal) {
2064
+ const descriptor = (await this.options.liveDescriptors(meshName, signal)).find(value => String(value.rid) === authenticatedRid && value.state === 1);
2065
+ if (descriptor === undefined
2066
+ || expected !== undefined && (descriptor.ownerId !== expected.ownerId
2067
+ || descriptor.leaseGeneration !== expected.leaseGeneration
2068
+ || String(descriptor.rid) !== expected.nodeRid
2069
+ || descriptor.lifecycleGeneration !== expected.nodeGeneration)) {
2070
+ throw new Error('Relocation reply relay peer is not the exact admitted source fence.');
2071
+ }
2072
+ }
2073
+ targetReplyRelayCoordinator(meshName, stage, authority) {
2074
+ const status = this.requireMeshNode(meshName).status();
2075
+ const owner = this.options.currentOwner();
2076
+ const target = stage.offer.prepare.target;
2077
+ if (owner === undefined
2078
+ || owner.ownerId !== target.ownerId
2079
+ || owner.leaseGeneration !== target.ownerLeaseGeneration
2080
+ || String(status.routingId) !== target.nodeRid
2081
+ || status.lifecycleGeneration !== target.nodeGeneration) {
2082
+ throw new Error('Relocation reply relay target coordinator fence is stale.');
2083
+ }
2084
+ return {
2085
+ ownerId: owner.ownerId,
2086
+ leaseGeneration: owner.leaseGeneration,
2087
+ nodeRid: String(status.routingId),
2088
+ nodeGeneration: status.lifecycleGeneration,
2089
+ expectedAuthorityStoreVersion: authority.storeVersion.value
2090
+ };
2091
+ }
2092
+ async relayTerminalReplies(meshName, stage, coordinator, signal) {
2093
+ for (const [participantIndex, participant] of stage.staging.envelope.participants.entries()) {
2094
+ const hidden = stage.staging.hidden.get(participant.key);
2095
+ if (hidden?.actor === undefined)
2096
+ continue;
2097
+ for (const [resultIndex, packet] of hidden.replayPackets.entries()) {
2098
+ if (!packet.returnResponse || packet.source === undefined)
2099
+ continue;
2100
+ const result = hidden.replayResults.at(resultIndex);
2101
+ if (result === undefined || result.index !== packet.index) {
2102
+ throw new Error('Relocation request result changed after target dispatch.');
2103
+ }
2104
+ const completion = {
2105
+ index: packet.index,
2106
+ operationId: packet.messageFollowContext.operationId,
2107
+ source: packet.source,
2108
+ result
2109
+ };
2110
+ await this.sendReplyRelay(meshName, packet.source.nodeRid, maintenanceReplyRelay(stage, coordinator, BigInt(participantIndex + 1), completion), handoffSourceFence(packet.source), signal);
2111
+ }
2112
+ }
2113
+ }
2114
+ async exactSourceLeaseExpired(source, signal) {
2115
+ const lease = await this.requireLocationStore().readOwnerLease(source.ownerId, signal);
2116
+ return lease.kind === 'missing'
2117
+ || lease.token.ownerId !== source.ownerId
2118
+ || lease.token.leaseGeneration !== source.leaseGeneration
2119
+ || lease.leaseExpiresAt.getTime() <= lease.storeNow.getTime();
2120
+ }
2121
+ async publishSessionRoutes(staging) {
2122
+ for (const hidden of staging.hidden.values()) {
2123
+ if (hidden.actor !== undefined) {
2124
+ await this.options.actorTransfer.publishRoutedActorOwnership(hidden.actor);
2125
+ }
2126
+ }
2127
+ }
2128
+ async sendControl(meshName, targetNodeRid, request, signal, deadlineAtMs = performance.now() + 30_000, sideband = []) {
2129
+ const key = controlAckKey(request);
2130
+ const frames = sideband.length === 0
2131
+ ? [(0, service_relocation_control_1.encodeServiceRelocationControlRequest)(request)]
2132
+ : [(0, service_relocation_control_1.encodeServiceRelocationControlRequest)(request), ...sideband];
2133
+ let lastRequestError;
2134
+ for (;;) {
2135
+ signal?.throwIfAborted();
2136
+ const remainingMs = deadlineAtMs - performance.now();
2137
+ if (remainingMs <= 0) {
2138
+ throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.DeadlineExceeded, `Relocation control ACK '${key}' timed out.`, true, lastRequestError);
2139
+ }
2140
+ const attemptTimeoutMs = Math.max(1, Math.min(250, Math.ceil(remainingMs)));
2141
+ const startedAtMs = performance.now();
2142
+ try {
2143
+ const replyFrames = await this.requestInfrastructureControl(meshName, targetNodeRid, frames, attemptTimeoutMs);
2144
+ if (replyFrames.length !== 1) {
2145
+ throw new service_wire_m6a_codec_1.ServiceWireProtocolError(`Relocation control '${key}' reply must contain exactly one frame.`);
2146
+ }
2147
+ const response = (0, service_relocation_control_1.decodeServiceRelocationControlResponse)(Buffer.from(replyFrames[0]));
2148
+ if (response.kind === 'failed') {
2149
+ validateControlFailureResponse(request, response);
2150
+ throw relocationFailureException(response);
2151
+ }
2152
+ validateControlResponse(request, response);
2153
+ return response;
2154
+ }
2155
+ catch (error) {
2156
+ if (error instanceof service_wire_m6a_codec_1.ServiceWireProtocolError
2157
+ || error instanceof contracts_1.ZLinkFrameworkException) {
2158
+ throw error;
2159
+ }
2160
+ lastRequestError = error;
2161
+ relocationDebug('control.request_retry', {
2162
+ key,
2163
+ kind: request.kind,
2164
+ targetRid: String(targetNodeRid)
2165
+ });
2166
+ const retryDelayMs = Math.min(Math.max(0, attemptTimeoutMs - (performance.now() - startedAtMs)), Math.max(0, deadlineAtMs - performance.now()));
2167
+ if (retryDelayMs > 0) {
2168
+ await waitForRelocationRetry(retryDelayMs, signal);
2169
+ }
2170
+ }
2171
+ }
2172
+ }
2173
+ async selectTarget(meshName, localRid, targetApplicationVersion, requirements = [], signal) {
2174
+ const descriptors = await this.options.liveDescriptors(meshName, signal);
2175
+ const local = this.options.localDescriptor?.(meshName)
2176
+ ?? descriptors.find(descriptor => String(descriptor.rid) === localRid);
2177
+ const requiredVersion = targetApplicationVersion ?? local?.applicationVersion;
2178
+ const peers = this.requireMeshNode(meshName).peers();
2179
+ const candidates = descriptors
2180
+ .filter(descriptor => String(descriptor.rid) !== localRid
2181
+ && descriptor.state === contracts_1.ZLinkFrameworkRuntimeState.Serving
2182
+ && descriptor.objectRole === contracts_1.ZLinkObjectRole.Server
2183
+ && descriptor.placementWeight > 0
2184
+ && (requiredVersion === undefined
2185
+ || descriptor.applicationVersion === requiredVersion)
2186
+ && (local?.maintenanceWave === undefined
2187
+ || descriptor.maintenanceWave !== local.maintenanceWave)
2188
+ && peers.some(peer => peer.routingId !== null
2189
+ && String(peer.routingId) === String(descriptor.rid)
2190
+ && peer.lifecycleGeneration === descriptor.lifecycleGeneration
2191
+ && peer.state === 3)
2192
+ && relocationTargetSupports(descriptor, requirements))
2193
+ .sort((left, right) => String(left.rid).localeCompare(String(right.rid)));
2194
+ const target = selectWeightedRelocationTarget(candidates);
2195
+ if (target === undefined) {
2196
+ // Spec 15 §"Failed.Kind": no compatible target node is Unavailable, the
2197
+ // same classification the session-seal control path uses for a target
2198
+ // it cannot reach.
2199
+ throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.RelocationTargetUnavailable, `RouteMesh '${meshName}' has no relocation target.`, true);
2200
+ }
2201
+ return target;
2202
+ }
2203
+ async readTargetParticipantAuthorities(envelope, signal) {
2204
+ const authorities = new Map();
2205
+ for (const participant of envelope.participants) {
2206
+ const current = await requireAuthority(this.requireLocationStore(), { value: participant.key }, signal);
2207
+ if (current.objectGeneration !== participant.objectGeneration
2208
+ || current.authorityOwnerGeneration !== participant.authorityOwnerGeneration
2209
+ || current.allocation.objectKind !== participant.objectKind
2210
+ || current.allocation.stableType !== participant.stableType
2211
+ || current.allocation.state !== 'active') {
2212
+ throw new Error(`Relocation participant '${participant.key}' authority changed before reservation.`);
2213
+ }
2214
+ authorities.set(participant.key, current);
2215
+ }
2216
+ return authorities;
2217
+ }
2218
+ async reserveTargetForPrepare(meshName, prepare, envelope, targetPort, signal) {
2219
+ const authorities = await this.readTargetParticipantAuthorities(envelope, signal);
2220
+ const publication = relocationPublication(prepare, envelope);
2221
+ // Carries the exact reference + CRC of a deferred-Join publication the
2222
+ // target reservation must keep connected through the CAS (spec 28 —
2223
+ // clearing/replacing it here would strand the journal's own
2224
+ // prepared->committed transition with nothing left for it to find).
2225
+ const retainedDeferredJoinRoots = new Map();
2226
+ for (const participant of envelope.participants) {
2227
+ const staged = targetPort.deferredJoinRoot(participant.key);
2228
+ if (staged !== undefined) {
2229
+ retainedDeferredJoinRoots.set(participant.key, {
2230
+ reference: staged.reference.value,
2231
+ checksumCrc32c: staged.checksumCrc32c
2232
+ });
2233
+ continue;
2234
+ }
2235
+ const current = this.codec.read(authorities.get(participant.key).payload);
2236
+ if (participant.objectKind === 'actor'
2237
+ && current?.canonical === true
2238
+ && await this.options.actorTransfer.isDeferredJoinAcceptedRootPublication(current.reference, current.checksumCrc32c, {
2239
+ authorityKey: participant.key,
2240
+ objectKind: 'actor',
2241
+ objectGeneration: participant.objectGeneration,
2242
+ aggregateId: current.aggregateId,
2243
+ aggregateGeneration: current.aggregateGeneration
2244
+ }, signal)) {
2245
+ retainedDeferredJoinRoots.set(participant.key, {
2246
+ reference: current.reference,
2247
+ checksumCrc32c: current.checksumCrc32c
2248
+ });
2249
+ }
2250
+ }
2251
+ const participants = envelope.participants.map(participant => {
2252
+ const expected = authorities.get(participant.key);
2253
+ const membership = actorMembershipTarget(envelope, participant.key);
2254
+ const entrySpotId = expected.allocation.objectKind === 'actor'
2255
+ && membership === undefined
2256
+ ? this.options.spotManager()?.entrySpotIdForMesh(meshName)
2257
+ : undefined;
2258
+ if (expected.allocation.objectKind === 'actor'
2259
+ && membership === undefined
2260
+ && entrySpotId === undefined) {
2261
+ throw new Error(`Relocation target RouteMesh '${meshName}' has no Entry Spot.`);
2262
+ }
2263
+ const retainedDeferredJoinRoot = retainedDeferredJoinRoots.get(participant.key);
2264
+ const participantPublication = retainedDeferredJoinRoot === undefined
2265
+ ? publication
2266
+ : {
2267
+ ...publication,
2268
+ reference: retainedDeferredJoinRoot.reference,
2269
+ checksumCrc32c: retainedDeferredJoinRoot.checksumCrc32c
2270
+ };
2271
+ return {
2272
+ key: { value: participant.key },
2273
+ expected,
2274
+ ownerTransition: 'newOwner',
2275
+ authorityPayload: this.authorityPayloadForPublication(expected.payload, participantPublication, {
2276
+ owner: {
2277
+ ownerId: prepare.target.ownerId,
2278
+ leaseGeneration: prepare.target.ownerLeaseGeneration
2279
+ },
2280
+ meshName,
2281
+ nodeRid: prepare.target.nodeRid,
2282
+ nodeGeneration: prepare.target.nodeGeneration,
2283
+ objectGeneration: expected.objectGeneration,
2284
+ targetAttemptGeneration: prepare.targetAttemptGeneration,
2285
+ coordinatorExpectedStoreVersion: expected.storeVersion.value,
2286
+ ...(membership === undefined
2287
+ ? expected.allocation.objectKind === 'actor'
2288
+ ? {
2289
+ actorSpotId: entrySpotId,
2290
+ actorSpotGeneration: prepare.target.nodeGeneration,
2291
+ actorSpotKind: contracts_1.ZLinkSpotKind.Entry
2292
+ }
2293
+ : {}
2294
+ : {
2295
+ ...membership,
2296
+ actorSpotKind: contracts_1.ZLinkSpotKind.User
2297
+ })
2298
+ }, retainedDeferredJoinRoot !== undefined),
2299
+ membershipMutation: encodeMembershipMutation(envelope.memberships, participant.key)
2300
+ };
2301
+ });
2302
+ const plan = {
2303
+ envelope,
2304
+ participants,
2305
+ targetDescriptor: { meshName, rid: prepare.target.nodeRid },
2306
+ targetDescriptorLifecycleGeneration: prepare.target.nodeGeneration,
2307
+ capacity: participants.reduce((sum, participant) => addCapacity(sum, participant.expected.allocation.capacity), { actors: 0, spots: 0 }),
2308
+ targetOwner: {
2309
+ ownerId: prepare.target.ownerId,
2310
+ leaseGeneration: prepare.target.ownerLeaseGeneration
2311
+ }
2312
+ };
2313
+ return {
2314
+ prepared: await new service_relocation_aggregate_committer_1.ServiceRelocationAggregateCommitter(this.requireLocationStore())
2315
+ .prepare(plan, signal)
2316
+ };
2317
+ }
2318
+ authorityPayloadForPublication(payload, publication, target, replacesDeferredJoinRoot = false) {
2319
+ const existing = this.codec.read(payload);
2320
+ const canonicalIdentity = (0, service_relocation_runtime_1.serviceRelocationAuthoritySlotIdentity)(payload);
2321
+ const replacesCanonicalJournal = replacesDeferredJoinRoot
2322
+ && existing?.canonical === true;
2323
+ if (canonicalIdentity !== undefined
2324
+ && (existing === undefined
2325
+ || existing.canonical === true
2326
+ && (existing.aggregateId === publication.aggregateId
2327
+ || replacesCanonicalJournal))) {
2328
+ const published = existing === undefined
2329
+ ? this.codec.publish(payload, publication)
2330
+ : replacesCanonicalJournal
2331
+ && existing.aggregateId !== publication.aggregateId
2332
+ ? this.codec.publish(this.codec.clear(payload, existing.reference), publication)
2333
+ : payload;
2334
+ if (target === undefined)
2335
+ return published;
2336
+ return (0, service_relocation_runtime_1.projectServiceRelocationAuthorityTargetReady)((0, service_relocation_runtime_1.replaceServiceRelocationAuthorityApplicationPayload)(published, rewriteAuthorityApplicationRoute(published, target)), {
2337
+ targetAttemptGeneration: target.targetAttemptGeneration,
2338
+ nodeRid: target.nodeRid,
2339
+ nodeGeneration: target.nodeGeneration,
2340
+ ownerId: target.owner.ownerId,
2341
+ ownerLeaseGeneration: target.owner.leaseGeneration,
2342
+ coordinatorExpectedStoreVersion: target.coordinatorExpectedStoreVersion
2343
+ });
2344
+ }
2345
+ if (existing === undefined) {
2346
+ const published = this.codec.publish(payload, publication);
2347
+ if (target === undefined) {
2348
+ return published;
2349
+ }
2350
+ if ((0, service_relocation_runtime_1.serviceRelocationAuthoritySlotIdentity)(published) !== undefined) {
2351
+ return (0, service_relocation_runtime_1.projectServiceRelocationAuthorityTargetReady)((0, service_relocation_runtime_1.replaceServiceRelocationAuthorityApplicationPayload)(published, rewriteAuthorityApplicationRoute(published, target)), {
2352
+ targetAttemptGeneration: target.targetAttemptGeneration,
2353
+ nodeRid: target.nodeRid,
2354
+ nodeGeneration: target.nodeGeneration,
2355
+ ownerId: target.owner.ownerId,
2356
+ ownerLeaseGeneration: target.owner.leaseGeneration,
2357
+ coordinatorExpectedStoreVersion: target.coordinatorExpectedStoreVersion
2358
+ });
2359
+ }
2360
+ return this.codec.publish(rewriteAuthorityApplicationRoute(payload, target), publication);
2361
+ }
2362
+ if (existing.reference !== publication.reference
2363
+ || existing.checksumCrc32c !== publication.checksumCrc32c
2364
+ || existing.aggregateId !== publication.aggregateId
2365
+ || existing.aggregateGeneration !== publication.aggregateGeneration
2366
+ || existing.inventoryDigest !== publication.inventoryDigest
2367
+ || existing.targetOwnerId !== publication.targetOwnerId
2368
+ || existing.targetOwnerLeaseGeneration
2369
+ !== publication.targetOwnerLeaseGeneration) {
2370
+ throw new Error('Relocation authority contains another published root '
2371
+ + `(current=${existing.aggregateId}/${existing.aggregateGeneration}`
2372
+ + `/${existing.reference}/canonical=${existing.canonical === true}, `
2373
+ + `requested=${publication.aggregateId}/${publication.aggregateGeneration}`
2374
+ + `/${publication.reference}).`);
2375
+ }
2376
+ return payload;
2377
+ }
2378
+ async abortTargetReservation(reservation, signal) {
2379
+ await new service_relocation_aggregate_committer_1.ServiceRelocationAggregateCommitter(this.requireLocationStore())
2380
+ .abort(reservation.prepared, signal);
2381
+ }
2382
+ async abortTargetStage(stage, signal) {
2383
+ if (stage.fallback !== undefined)
2384
+ clearTimeout(stage.fallback);
2385
+ const failures = [];
2386
+ try {
2387
+ await this.abortTargetReservation(stage.offer.reservation, signal);
2388
+ }
2389
+ catch (error) {
2390
+ failures.push(error);
2391
+ }
2392
+ try {
2393
+ await stage.owner.abort(stage.staging);
2394
+ }
2395
+ catch (error) {
2396
+ failures.push(error);
2397
+ }
2398
+ stage.phase = 'failed';
2399
+ if (failures.length === 1)
2400
+ throw failures[0];
2401
+ if (failures.length > 1) {
2402
+ throw new AggregateError(failures, 'Relocation target rollback was incomplete.');
2403
+ }
2404
+ }
2405
+ async commitTargetReservation(stage, reservation, signal) {
2406
+ return await this.commitTargetAggregate(stage, reservation.prepared, signal);
2407
+ }
2408
+ async commitTargetAggregate(stage, prepared, signal) {
2409
+ let firstError;
2410
+ for (;;) {
2411
+ signal?.throwIfAborted();
2412
+ let result;
2413
+ try {
2414
+ result = await this.requireLocationStore().commitAggregate(prepared.fence, signal);
2415
+ }
2416
+ catch (error) {
2417
+ firstError ??= error;
2418
+ }
2419
+ if (result?.kind === 'stale' || result?.kind === 'generationExhausted') {
2420
+ throw new Error(`location_update_failed: relocation aggregate commit returned ${result.kind}.`, { cause: firstError });
2421
+ }
2422
+ const observed = await this.readAggregateForCommitRetry(prepared, signal);
2423
+ if (observed.kind === 'committed') {
2424
+ const primary = observed.authorities.get(stage.staging.primaryAuthorityKey.value);
2425
+ if (primary === undefined) {
2426
+ throw new Error('Committed relocation aggregate omitted its primary authority.');
2427
+ }
2428
+ return primary;
2429
+ }
2430
+ if (observed.kind === 'stale') {
2431
+ throw new Error('location_update_failed: relocation aggregate source authority became stale.', {
2432
+ cause: firstError
2433
+ });
2434
+ }
2435
+ await waitForLocationRetry(stage.offer.restoreDeadlineAtMs, signal, firstError);
2436
+ }
2437
+ }
2438
+ async readAggregateForCommitRetry(prepared, signal) {
2439
+ const authorities = new Map();
2440
+ let source = 0;
2441
+ let committed = 0;
2442
+ try {
2443
+ for (const participant of prepared.plan.participants) {
2444
+ const current = await this.requireLocationStore().readAuthority(participant.key, signal);
2445
+ if (current.kind !== 'snapshot')
2446
+ return { kind: 'stale' };
2447
+ if (isExactCommittedTarget(current, participant.expected, {
2448
+ nodeRid: String(prepared.plan.targetDescriptor.rid),
2449
+ nodeGeneration: prepared.plan.targetDescriptorLifecycleGeneration,
2450
+ ownerId: prepared.plan.targetOwner.ownerId,
2451
+ ownerLeaseGeneration: prepared.plan.targetOwner.leaseGeneration
2452
+ }, participant.authorityPayload)) {
2453
+ committed += 1;
2454
+ authorities.set(participant.key.value, current);
2455
+ }
2456
+ else if (isExactSourceAuthority(current, participant.expected)) {
2457
+ source += 1;
2458
+ }
2459
+ else {
2460
+ return { kind: 'stale' };
2461
+ }
2462
+ }
2463
+ }
2464
+ catch {
2465
+ return { kind: 'unknown' };
2466
+ }
2467
+ if (committed === prepared.plan.participants.length) {
2468
+ return { kind: 'committed', authorities };
2469
+ }
2470
+ return source === prepared.plan.participants.length
2471
+ ? { kind: 'source' }
2472
+ : { kind: 'stale' };
2473
+ }
2474
+ async materializeTargetEnvelope(meshName, envelope, signal) {
2475
+ const target = new LocalTargetPort(this.options, meshName, envelope);
2476
+ const owner = new service_relocation_object_owner_1.ServiceRelocationObjectRestoreOwner(target, value => ({ value }));
2477
+ const staging = await owner.prepare(envelope, signal);
2478
+ if (staging.id !== `${envelope.aggregateId}:${envelope.aggregateGeneration}`) {
2479
+ throw new Error('Relocation materialization returned a different staging identity.');
2480
+ }
2481
+ return { owner, staging, target };
2482
+ }
2483
+ /** Maps schema ordinals to the authoritative Location Store inventory. */
2484
+ async resolveTargetParticipantInventory(request, envelope, signal) {
2485
+ if (!envelope.participants.some(value => value.rootSpotId !== undefined)) {
2486
+ return envelope;
2487
+ }
2488
+ const store = this.requireLocationStore();
2489
+ const manager = this.options.spotManager();
2490
+ const primaryKey = request.object.kind === 'actor'
2491
+ ? (0, authority_key_codec_1.encodeAuthorityKey)('actor', request.object.actorId)
2492
+ : (0, authority_key_codec_1.encodeAuthorityKey)(request.object.kind === 'userSpot' ? 'user_spot' : 'instance_spot', request.object.spotId);
2493
+ const primary = await requireAuthority(store, primaryKey, signal);
2494
+ const entries = [
2495
+ { key: primaryKey, snapshot: primary }
2496
+ ];
2497
+ if (request.object.kind === 'userSpot' || request.object.kind === 'instanceSpot') {
2498
+ let cursor;
2499
+ for (;;) {
2500
+ const page = await store.listAuthorities('', cursor, 1000, signal);
2501
+ if (page.kind === 'scanExpired') {
2502
+ throw new Error('Location Store authority scan expired during relocation.');
2503
+ }
2504
+ for (const candidate of page.items) {
2505
+ if (candidate.key.value === primaryKey.value
2506
+ || (0, authority_key_codec_1.decodeAuthorityKey)(candidate.key).kind !== 'actor')
2507
+ continue;
2508
+ const actor = (0, actor_authority_publication_1.decodeRelocatingActorAuthorityIdentity)(candidate.snapshot.payload, candidate.snapshot.objectGeneration);
2509
+ if (actor?.spotId === request.object.spotId) {
2510
+ entries.push(candidate);
2511
+ }
2512
+ }
2513
+ if (page.nextCursor === undefined)
2514
+ break;
2515
+ cursor = page.nextCursor;
2516
+ }
2517
+ }
2518
+ entries.sort((left, right) => Buffer.compare(Buffer.from(left.key.value, 'utf8'), Buffer.from(right.key.value, 'utf8')));
2519
+ if (new Set(entries.map(entry => entry.key.value)).size !== entries.length) {
2520
+ throw new Error('Location Store relocation inventory has duplicate authority keys.');
2521
+ }
2522
+ const root = envelope.participants.find(value => value.rootSpotId !== undefined);
2523
+ const expectedRootId = request.object.kind === 'actor'
2524
+ ? request.object.actorId
2525
+ : request.object.spotId;
2526
+ if (root === undefined
2527
+ || root.rootSpotId !== expectedRootId
2528
+ || root.rootObjectKind !== primary.allocation.objectKind
2529
+ || root.rootSpotGeneration !== primary.objectGeneration
2530
+ || root.rootObjectKind !== 'instance_spot'
2531
+ && root.rootOwnerGeneration !== primary.authorityOwnerGeneration) {
2532
+ throw new Error('Relocation root object projection does not match Location Store.');
2533
+ }
2534
+ const transferred = new Map(envelope.participants.map(participant => [participant.participantId, participant]));
2535
+ if (transferred.size !== envelope.participants.length || transferred.size !== entries.length) {
2536
+ throw new Error('Relocation payload participant inventory does not match Location Store.');
2537
+ }
2538
+ const participants = entries.map(({ key, snapshot }, index) => {
2539
+ const participantId = BigInt(index + 1);
2540
+ const transferredParticipant = transferred.get(participantId);
2541
+ if (transferredParticipant === undefined) {
2542
+ throw new Error('Relocation payload participant identity does not match Location Store.');
2543
+ }
2544
+ return {
2545
+ ...transferredParticipant,
2546
+ key: key.value,
2547
+ objectKind: snapshot.allocation.objectKind,
2548
+ stableType: snapshot.allocation.stableType,
2549
+ objectGeneration: snapshot.objectGeneration,
2550
+ authorityOwnerGeneration: snapshot.authorityOwnerGeneration
2551
+ };
2552
+ });
2553
+ // Actor-root saved work is admitted against the destination membership.
2554
+ // The canonical root intentionally omits a membership vector; meanwhile
2555
+ // Location Store still names the source Spot until target cutover. Rebuild
2556
+ // the Actor lane from the already accepted ActorJoin admission, preserving
2557
+ // the target queue boundary for decoded saved-work.
2558
+ const memberships = request.object.kind === 'actor'
2559
+ ? actorJoinTargetMembership(manager, envelope.aggregateId, participants)
2560
+ : entries
2561
+ .filter(entry => entry.snapshot.allocation.objectKind === 'actor')
2562
+ .map(entry => ({
2563
+ actorKey: entry.key.value,
2564
+ spotKey: primaryKey.value,
2565
+ spotObjectGeneration: primary.objectGeneration,
2566
+ membershipEpoch: 1n
2567
+ }));
2568
+ return {
2569
+ ...envelope,
2570
+ participants,
2571
+ memberships
2572
+ };
2573
+ }
2574
+ spotKind(meshName, activation) {
2575
+ const node = this.options.registration.spotNodes.get(meshName);
2576
+ const registrations = activation.domain.kind === 'user'
2577
+ ? node?.spotFactoryRegistrations
2578
+ : node?.instanceSpotFactoryRegistrations;
2579
+ return Object.values(registrations ?? {})
2580
+ .some(value => value.implementation === activation.spotType)
2581
+ ? activation.domain.kind === 'user' ? 'user_spot' : 'instance_spot'
2582
+ : undefined;
2583
+ }
2584
+ spotRegistration(meshName, kind, stableType) {
2585
+ const node = this.options.registration.spotNodes.get(meshName);
2586
+ const value = kind === 'user_spot'
2587
+ ? node?.spotFactoryRegistrations?.[stableType]
2588
+ : node?.instanceSpotFactoryRegistrations?.[stableType];
2589
+ if (value === undefined)
2590
+ throw new Error(`Relocation Spot type '${stableType}' is not registered.`);
2591
+ return value;
2592
+ }
2593
+ actorRegistration(meshName, stableType) {
2594
+ const value = this.options.registration.spotNodes.get(meshName)
2595
+ ?.actorFactoryRegistrations?.[stableType];
2596
+ if (value === undefined)
2597
+ throw new Error(`Relocation Actor type '${stableType}' is not registered.`);
2598
+ return value;
2599
+ }
2600
+ async captureApplication(policy, value, signal) {
2601
+ if (policy.kind === 'disabled') {
2602
+ throw new Error(`Relocation is disabled for '${value.constructor?.name ?? 'object'}'.`);
2603
+ }
2604
+ if (policy.kind === 'recreate')
2605
+ return Buffer.alloc(0);
2606
+ const adapter = await this.createRelocationAdapter(policy.adapterType);
2607
+ const captured = await (0, relocation_state_adapter_1.captureRelocationAdapterState)(adapter, value, signal ?? new AbortController().signal);
2608
+ if (captured.byteLength > RELOCATION_PARTICIPANT_STATE_LIMIT_BYTES) {
2609
+ throw new ZLinkRelocationStateIncompatibleError('Relocation application state exceeds the 64 MiB participant limit.');
2610
+ }
2611
+ return captured;
2612
+ }
2613
+ async createRelocationAdapter(adapterType) {
2614
+ return await (0, spot_provider_1.createProviderInstance)(adapterType, this.options.providerResolver);
2615
+ }
2616
+ recordRelocationInterruption(meshName, unitKind, executionMode, startedAt, outcome) {
2617
+ const seconds = Math.max(0, performance.now() - startedAt) / 1000;
2618
+ const attributes = {
2619
+ unit_kind: unitKind,
2620
+ ...(executionMode === undefined ? {} : { execution_mode: executionMode })
2621
+ };
2622
+ this.options.metrics?.duration('zlink.relocation.interruption', seconds, attributes);
2623
+ this.options.metrics?.count('zlink.relocation.completed', 1, {
2624
+ mesh_name: meshName,
2625
+ object_kind: unitKind,
2626
+ policy: unitKind === 'user_spot' && executionMode === 'per_actor'
2627
+ ? 'recreate'
2628
+ : 'configured',
2629
+ outcome
2630
+ });
2631
+ if (seconds <= 1)
2632
+ return;
2633
+ console.warn(`[zlink.runtime.relocation.changed] ${unitKind} admission interruption ` +
2634
+ `exceeded 1 second (${seconds.toFixed(3)}s).`);
2635
+ void this.options.runtimeEventPublisher?.publish({
2636
+ sourceName: 'zlink.runtime.relocation',
2637
+ timestamp: new Date(),
2638
+ identifier: 'zlink.runtime.relocation.changed',
2639
+ meshName,
2640
+ unitKind,
2641
+ executionMode,
2642
+ interruptionTargetExceeded: true,
2643
+ durationSeconds: seconds
2644
+ });
2645
+ }
2646
+ sealSpotMessageFollow(meshName, authority, activation) {
2647
+ const node = this.requireMeshNode(meshName);
2648
+ const seal = node.sealSpotMessageFollowIngress;
2649
+ const abort = node.abortSpotMessageFollowIngress;
2650
+ const commit = node.commitSpotMessageFollowIngress;
2651
+ if (seal === undefined && abort === undefined && commit === undefined)
2652
+ return undefined;
2653
+ if (seal === undefined || abort === undefined || commit === undefined) {
2654
+ throw new Error('Spot Message Follow backend support is incomplete.');
2655
+ }
2656
+ const status = node.status();
2657
+ const result = seal.call(node, {
2658
+ spot: {
2659
+ spotId: String(activation.spotId),
2660
+ generation: authority.objectGeneration
2661
+ },
2662
+ targetNodeRid: String(status.routingId),
2663
+ targetNodeGeneration: status.lifecycleGeneration,
2664
+ authorityOwnerGeneration: authority.authorityOwnerGeneration,
2665
+ ownerLeaseGeneration: authority.ownerLeaseGeneration,
2666
+ storeVersion: authority.storeVersion.value
2667
+ });
2668
+ if (result === undefined) {
2669
+ throw new Error(`Spot '${String(activation.spotId)}' ingress could not be sealed for relocation.`);
2670
+ }
2671
+ return result;
2672
+ }
2673
+ async commitSpotMessageFollow(meshName, seal, authorityKey, activation, target) {
2674
+ const node = this.requireMeshNode(meshName);
2675
+ const commit = node.commitSpotMessageFollowIngress;
2676
+ if (commit === undefined) {
2677
+ throw new Error('Spot Message Follow backend support is incomplete.');
2678
+ }
2679
+ const committed = await requireAuthority(this.requireLocationStore(), authorityKey);
2680
+ const accepted = await commit.call(node, seal, {
2681
+ spot: {
2682
+ spotId: String(activation.spotId),
2683
+ generation: committed.objectGeneration
2684
+ },
2685
+ targetNodeRid: String(target.rid),
2686
+ targetNodeGeneration: target.lifecycleGeneration,
2687
+ authorityOwnerGeneration: committed.authorityOwnerGeneration,
2688
+ ownerLeaseGeneration: committed.ownerLeaseGeneration,
2689
+ storeVersion: committed.storeVersion.value
2690
+ }, this.relocationLimits().messageFollowDurationMs);
2691
+ if (!accepted) {
2692
+ throw new Error(`Spot '${String(activation.spotId)}' Message Follow route became stale.`);
2693
+ }
2694
+ }
2695
+ requireLocationStore() {
2696
+ const value = this.options.locationStore();
2697
+ if (value === undefined)
2698
+ throw new Error('Host relocation requires a Location Store.');
2699
+ return value;
2700
+ }
2701
+ requireSpotManager() {
2702
+ const value = this.options.spotManager();
2703
+ if (value === undefined)
2704
+ throw new Error('Host relocation requires the Spot manager.');
2705
+ return value;
2706
+ }
2707
+ requireActorManager() {
2708
+ const value = this.options.actorManager();
2709
+ if (value === undefined)
2710
+ throw new Error('Host relocation requires the Actor manager.');
2711
+ return value;
2712
+ }
2713
+ relocationLimits() {
2714
+ const configured = this.options.registration?.locations?.options;
2715
+ return {
2716
+ ...Options_1.zlinkRuntimeDefaultLocationOptions,
2717
+ ...(configured ?? {})
2718
+ };
2719
+ }
2720
+ requireMeshNode(meshName) {
2721
+ const value = this.options.meshNode(meshName);
2722
+ if (value === undefined)
2723
+ throw new Error(`RouteMesh '${meshName}' is not started.`);
2724
+ return value;
2725
+ }
2726
+ async sendInfrastructureControl(meshName, targetNodeRid, record) {
2727
+ const node = this.requireMeshNode(meshName);
2728
+ const send = node.sendInfrastructureControl;
2729
+ if (send === undefined) {
2730
+ // Compatibility backends may expose raw RouteMesh delivery through the
2731
+ // ordinary node-send port. Production Node backends provide the
2732
+ // dedicated service-control API above, so this branch neither changes
2733
+ // their framing nor turns a missing send into an immediate terminal:
2734
+ // command 42 still owns its configured deadline while admission waits.
2735
+ if (Array.isArray(record)) {
2736
+ return await node.sendToNode(targetNodeRid, record.map(frame => Buffer.from(frame)));
2737
+ }
2738
+ return await node.sendToNode(targetNodeRid, Buffer.from(record));
2739
+ }
2740
+ if (Array.isArray(record)) {
2741
+ const sendFrames = node.sendInfrastructureControlFrames;
2742
+ if (sendFrames !== undefined) {
2743
+ return await sendFrames.call(node, targetNodeRid, record);
2744
+ }
2745
+ // Legacy in-memory backends have no multipart ingress. They exercise
2746
+ // the canonical frame only; production Node backends implement the
2747
+ // explicit multipart capability above.
2748
+ return await send.call(node, targetNodeRid, record[0]);
2749
+ }
2750
+ return await send.call(node, targetNodeRid, record);
2751
+ }
2752
+ async requestInfrastructureControl(meshName, targetNodeRid, frames, timeoutMs) {
2753
+ const node = this.requireMeshNode(meshName);
2754
+ const request = node.requestInfrastructureControlFrames;
2755
+ if (request === undefined) {
2756
+ throw new Error('RouteMesh backend cannot submit bare infrastructure requests.');
2757
+ }
2758
+ return await request.call(node, targetNodeRid, frames, { timeoutMs });
2759
+ }
2760
+ }
2761
+ exports.ZLinkHostServiceRelocationRuntime = ZLinkHostServiceRelocationRuntime;
2762
+ function canonicalActorJoinRecovery(participants) {
2763
+ const matches = participants.flatMap(participant => participant.queuedMessages.flatMap(message => {
2764
+ const recovery = (0, actor_join_recovery_codec_1.decodeCanonicalActorJoinRecoverySavedWork)(message.payload);
2765
+ return recovery === undefined ? [] : [recovery];
2766
+ }));
2767
+ if (matches.length > 1) {
2768
+ throw new Error('Actor relocation contains duplicate canonical Join recovery records.');
2769
+ }
2770
+ return matches[0];
2771
+ }
2772
+ function actorJoinAdmissionIdentity(envelope) {
2773
+ return canonicalActorJoinRecovery(envelope.participants)?.request.handoffId
2774
+ ?? envelope.aggregateId;
2775
+ }
2776
+ function actorJoinTargetMembership(manager, relocationId, participants) {
2777
+ const recovery = canonicalActorJoinRecovery(participants);
2778
+ const admissionId = recovery?.request.handoffId ?? relocationId;
2779
+ const admission = manager?.formalRemoteActorAdmissions?.get(admissionId);
2780
+ const actor = participants.find(value => value.objectKind === 'actor');
2781
+ if (admission === undefined || actor === undefined) {
2782
+ throw new Error(`Actor relocation '${relocationId}' has no accepted target membership.`);
2783
+ }
2784
+ return [{
2785
+ actorKey: actor.key,
2786
+ spotKey: (0, authority_key_codec_1.encodeAuthorityKey)('user_spot', String(admission.admission.spotId)).value,
2787
+ spotObjectGeneration: admission.admission.targetSpotGeneration,
2788
+ membershipEpoch: admission.admission.expectedMembershipEpoch
2789
+ }];
2790
+ }
2791
+ function relocationDebug(marker, detail) {
2792
+ if (process.env.ZLINK_DEBUG_FRAMEWORK_RELOCATION !== '1')
2793
+ return;
2794
+ console.error('[zlink.runtime.relocation]', marker, detail);
2795
+ }
2796
+ class LocalTargetPort {
2797
+ options;
2798
+ meshName;
2799
+ envelope;
2800
+ deferredJoinRoots = new Map();
2801
+ constructor(options, meshName, envelope) {
2802
+ this.options = options;
2803
+ this.meshName = meshName;
2804
+ this.envelope = envelope;
2805
+ }
2806
+ async createHidden(participant, signal) {
2807
+ const identity = (0, authority_key_codec_1.decodeAuthorityKey)({ value: participant.key }).globalId;
2808
+ if (participant.objectKind === 'actor') {
2809
+ const membership = this.envelope.memberships.find(value => value.actorKey === participant.key);
2810
+ if (membership === undefined)
2811
+ throw new Error(`Actor '${identity}' relocation membership is missing.`);
2812
+ const spotIdentity = (0, authority_key_codec_1.decodeAuthorityKey)({ value: membership.spotKey }).globalId;
2813
+ const localDescriptor = this.options.localDescriptor?.(this.meshName);
2814
+ const nativeEntrySpot = localDescriptor?.entrySpotId === spotIdentity;
2815
+ const actor = await this.requireActorManager().prepareRelocationActor(identity, participant.stableType, participant.objectGeneration, participant.authorityOwnerGeneration + 1n, (nativeEntrySpot ? localDescriptor.rid : spotIdentity), nativeEntrySpot ? localDescriptor.lifecycleGeneration : membership.spotObjectGeneration, membership.membershipEpoch, signal);
2816
+ return {
2817
+ authorityKey: participant.key,
2818
+ participant,
2819
+ actor,
2820
+ initialized: false,
2821
+ restoredTimers: [],
2822
+ replayResults: [],
2823
+ replayPackets: []
2824
+ };
2825
+ }
2826
+ const registration = this.registration(participant.objectKind, participant.stableType);
2827
+ const activation = await this.requireSpotManager().prepareRelocationSpot(this.meshName, participant.objectKind, participant.stableType, registration.implementation, identity, participant.objectGeneration, participant.authorityOwnerGeneration + 1n, signal);
2828
+ return {
2829
+ authorityKey: participant.key,
2830
+ participant,
2831
+ activation,
2832
+ initialized: false,
2833
+ restoredTimers: [],
2834
+ replayResults: [],
2835
+ replayPackets: []
2836
+ };
2837
+ }
2838
+ async restoreApplicationState(hidden, payload, signal) {
2839
+ const registration = this.registration(hidden.participant.objectKind, hidden.participant.stableType);
2840
+ if (registration.relocation.kind === 'recreate') {
2841
+ if (payload.byteLength !== 0)
2842
+ throw new Error('Recreate relocation contains snapshot state.');
2843
+ return;
2844
+ }
2845
+ if (registration.relocation.kind !== 'snapshot') {
2846
+ throw new Error(`Relocation is disabled for '${hidden.participant.stableType}'.`);
2847
+ }
2848
+ const adapter = await (0, spot_provider_1.createProviderInstance)(registration.relocation.adapterType, this.options.providerResolver);
2849
+ const instance = (hidden.actor ?? hidden.activation?.spot);
2850
+ await (0, relocation_state_adapter_1.restoreRelocationAdapterState)(adapter, instance, payload, signal ?? new AbortController().signal);
2851
+ }
2852
+ async restoreMemberships(hidden, memberships) {
2853
+ for (const membership of memberships) {
2854
+ const actor = hidden.get(membership.actorKey)?.actor;
2855
+ const spotIdentity = (0, authority_key_codec_1.decodeAuthorityKey)({ value: membership.spotKey }).globalId;
2856
+ const spot = hidden.get(membership.spotKey)?.activation
2857
+ ?? this.requireSpotManager().resolveRelocationActivation(this.meshName, spotIdentity);
2858
+ if (actor === undefined)
2859
+ throw new Error('Relocation membership Actor staging is missing.');
2860
+ const state = this.requireActorManager().getState(actor.context.actorId);
2861
+ const localDescriptor = this.options.localDescriptor?.(this.meshName);
2862
+ const isEntryMembership = localDescriptor?.entrySpotId === spotIdentity;
2863
+ if (isEntryMembership) {
2864
+ // Entry Spot identity is published as a Location membership key, but
2865
+ // it is not a User Spot activation in the Actor runtime. The native
2866
+ // restore already received the target MeshNode RID as its Entry
2867
+ // membership; clearing the framework Spot state keeps dispatch on the
2868
+ // local Entry Spot path after the target commit.
2869
+ state.clearJoinedSpot();
2870
+ }
2871
+ else {
2872
+ state.setJoinedSpot(spotIdentity, spot?.spot, membership.membershipEpoch);
2873
+ }
2874
+ spot?.commitActorJoin(actor);
2875
+ }
2876
+ }
2877
+ async publish(hidden, authority) {
2878
+ if (hidden.actor !== undefined) {
2879
+ const store = this.requireLocationStore();
2880
+ const current = await requireAuthority(store, { value: hidden.authorityKey });
2881
+ const actorId = hidden.actor.context.actorId;
2882
+ const node = this.options.meshNode(this.meshName);
2883
+ const restore = node?.restoreActorAuthority;
2884
+ if (node === undefined || restore === undefined) {
2885
+ throw new Error(`Relocation Actor '${actorId}' native authority publication is unavailable.`);
2886
+ }
2887
+ const native = node.actorLookup(actorId);
2888
+ restore.call(node, actorId, hidden.participant.stableType, current.objectGeneration, current.authorityOwnerGeneration, String(native.spotId), native.spotGeneration, native.membershipEpoch);
2889
+ this.requireActorManager().adoptCreatedAuthority(actorId, current.authorityOwnerGeneration, current.ownerLeaseGeneration);
2890
+ hidden.targetAuthorityOwnerGeneration = current.authorityOwnerGeneration;
2891
+ }
2892
+ else if (hidden.activation !== undefined) {
2893
+ const registration = this.registration(hidden.participant.objectKind, hidden.participant.stableType);
2894
+ const applicationSignaled = hidden.participant.objectKind === 'user_spot'
2895
+ && registration.options?.relocationCoordinationMode
2896
+ === contracts_1.ZLinkSpotRelocationCoordinationMode.ApplicationSignaled;
2897
+ await this.requireSpotManager().publishRelocationSpot(hidden.activation, applicationSignaled
2898
+ ? () => hidden.activation.notifyRelocatedBoundary()
2899
+ : undefined);
2900
+ this.options.meshNode(this.meshName)?.rememberSpotRoute?.({
2901
+ spot: {
2902
+ spotId: String(hidden.activation.spotId),
2903
+ generation: authority.objectGeneration
2904
+ },
2905
+ targetNodeRid: String(authority.allocation.descriptor.rid),
2906
+ targetNodeGeneration: authority.allocation.descriptorLifecycleGeneration,
2907
+ authorityOwnerGeneration: authority.authorityOwnerGeneration,
2908
+ ownerLeaseGeneration: authority.ownerLeaseGeneration,
2909
+ storeVersion: authority.storeVersion.value
2910
+ });
2911
+ if (hidden.participant.objectKind === 'instance_spot') {
2912
+ this.options.trackInstanceSpot?.({
2913
+ meshName: this.meshName,
2914
+ spotId: hidden.activation.spotId,
2915
+ stableType: hidden.participant.stableType,
2916
+ nodeRid: authority.allocation.descriptor.rid,
2917
+ nodeGeneration: authority.allocation.descriptorLifecycleGeneration,
2918
+ objectGeneration: authority.objectGeneration,
2919
+ authorityOwnerGeneration: authority.authorityOwnerGeneration,
2920
+ ownerId: authority.ownerId,
2921
+ ownerLeaseGeneration: authority.ownerLeaseGeneration,
2922
+ storeVersion: authority.storeVersion.value,
2923
+ deactivate: () => this.requireSpotManager().abortRelocationSpot(hidden.activation)
2924
+ });
2925
+ }
2926
+ }
2927
+ hidden.initialized = true;
2928
+ }
2929
+ async restoreBoundSession(hidden, payload) {
2930
+ if (hidden.actor === undefined || payload.byteLength === 0)
2931
+ return;
2932
+ const target = decodeActorSession(payload);
2933
+ const state = this.requireActorManager().getState(hidden.actor.context.actorId);
2934
+ state.setRemoteBoundSessionTarget(target);
2935
+ state.setBoundSessionTransferTarget(target);
2936
+ if (target.bindingGeneration !== undefined) {
2937
+ state.setBoundSessionBindingGeneration(target.bindingGeneration);
2938
+ }
2939
+ }
2940
+ async replayQueuedMessage(hidden, message) {
2941
+ if (hidden.actor === undefined) {
2942
+ throw new Error('Only Actor relocation participants can contain packet backlog.');
2943
+ }
2944
+ const recovery = (0, actor_join_recovery_codec_1.decodeCanonicalActorJoinRecoverySavedWork)(message.payload);
2945
+ if (recovery !== undefined) {
2946
+ if (recovery.request.actorId !== hidden.actor.context.actorId) {
2947
+ throw new Error('Canonical Actor Join recovery names a different staged Actor.');
2948
+ }
2949
+ const deferred = await this.requireSpotManager().restoreCanonicalActorJoinRecovery(recovery, undefined, (0, service_relocation_runtime_1.inventoryDigest)(this.envelope.participants, this.envelope.memberships));
2950
+ if (deferred !== undefined) {
2951
+ this.deferredJoinRoots.set(hidden.authorityKey, deferred);
2952
+ }
2953
+ return;
2954
+ }
2955
+ const packet = decodeQueuedHandoffPacket(message);
2956
+ const state = this.requireActorManager().getState(hidden.actor.context.actorId);
2957
+ if (state === undefined)
2958
+ throw new Error('Relocated Actor state is not staged.');
2959
+ hidden.replayPackets.push(packet);
2960
+ }
2961
+ deferredJoinRoot(authorityKey) {
2962
+ return this.deferredJoinRoots.get(authorityKey);
2963
+ }
2964
+ async openAdmission(hidden) {
2965
+ if (hidden.actor === undefined)
2966
+ return;
2967
+ this.requireActorManager().publishRelocationActor(hidden.actor.context.actorId);
2968
+ if (hidden.replayPackets.length === 0)
2969
+ return;
2970
+ const state = this.requireActorManager().getState(hidden.actor.context.actorId);
2971
+ if (state === undefined)
2972
+ throw new Error('Relocated Actor state is not staged.');
2973
+ const results = await (0, actor_handoff_1.replayActorHandoffBacklog)(hidden.replayPackets, (parts, returnResponse, remoteBoundSessionTarget, fallbackActorRef) => {
2974
+ if (state.spotId === undefined) {
2975
+ const runtime = this.options.spotNodeRuntime();
2976
+ if (runtime === undefined) {
2977
+ throw new Error('Relocated Entry Spot Actor dispatch is unavailable.');
2978
+ }
2979
+ return runtime.dispatchEntryActorPacket(hidden.actor.context.actorId, parts, returnResponse, remoteBoundSessionTarget, fallbackActorRef);
2980
+ }
2981
+ return this.requireSpotManager().dispatchRoutedActorPacket(state.spotId, hidden.actor.context.actorId, parts, returnResponse, remoteBoundSessionTarget, fallbackActorRef);
2982
+ });
2983
+ hidden.replayResults.push(...results);
2984
+ }
2985
+ async restoreTimer(hidden, timer) {
2986
+ if (hidden.activation === undefined)
2987
+ throw new Error('Actor relocation cannot restore a Spot timer.');
2988
+ hidden.restoredTimers.push(timer);
2989
+ if (hidden.restoredTimers.length !== hidden.participant.timers.length)
2990
+ return;
2991
+ hidden.activation.timers.restoreRelocation(hidden.restoredTimers.map(value => ({
2992
+ name: value.timerId,
2993
+ handlerType: value.handlerType,
2994
+ periodMs: value.intervalMs,
2995
+ overrunPolicy: value.overrunPolicy,
2996
+ maxCatchUpTicks: value.maxCatchUpTicks,
2997
+ stopOnUnhandledException: value.stopOnUnhandledException,
2998
+ startedAtUnixMs: value.startedAtUnixMs,
2999
+ deliveryIndex: value.deliveryIndex,
3000
+ lastScheduledIndex: value.lastScheduledIndex,
3001
+ nextDueAtUnixMs: value.dueAtUnixMs,
3002
+ pendingTicks: value.pendingTicks
3003
+ })));
3004
+ }
3005
+ async normalize(_hidden) { }
3006
+ async abort(hidden) {
3007
+ if (hidden.actor !== undefined) {
3008
+ await this.requireActorManager().abortRelocationActor(hidden.actor.context.actorId);
3009
+ }
3010
+ else if (hidden.activation !== undefined) {
3011
+ await this.requireSpotManager().abortRelocationSpot(hidden.activation);
3012
+ }
3013
+ }
3014
+ registration(kind, stableType) {
3015
+ const node = this.options.registration.spotNodes.get(this.meshName);
3016
+ const value = kind === 'actor'
3017
+ ? node?.actorFactoryRegistrations?.[stableType]
3018
+ : kind === 'user_spot'
3019
+ ? node?.spotFactoryRegistrations?.[stableType]
3020
+ : node?.instanceSpotFactoryRegistrations?.[stableType];
3021
+ if (value === undefined)
3022
+ throw new Error(`Relocation type '${stableType}' is not registered.`);
3023
+ return value;
3024
+ }
3025
+ requireLocationStore() {
3026
+ const store = this.options.locationStore();
3027
+ if (store === undefined)
3028
+ throw new Error('Relocation target Location Store is unavailable.');
3029
+ return store;
3030
+ }
3031
+ requireSpotManager() {
3032
+ const manager = this.options.spotManager();
3033
+ if (manager === undefined)
3034
+ throw new Error('Relocation target Spot manager is unavailable.');
3035
+ return manager;
3036
+ }
3037
+ requireActorManager() {
3038
+ const manager = this.options.actorManager();
3039
+ if (manager === undefined)
3040
+ throw new Error('Relocation target Actor manager is unavailable.');
3041
+ return manager;
3042
+ }
3043
+ }
3044
+ async function requireAuthority(store, key, signal) {
3045
+ const current = await store.readAuthority(key, signal);
3046
+ if (current.kind !== 'snapshot')
3047
+ throw new Error(`Authority '${key.value}' is missing.`);
3048
+ return current;
3049
+ }
3050
+ function rewriteAuthorityApplicationRoute(payload, target) {
3051
+ const applicationPayload = (0, service_relocation_runtime_1.serviceRelocationAuthorityApplicationPayload)(payload);
3052
+ const actor = (0, actor_authority_publication_1.decodeRelocatingActorAuthorityIdentity)(applicationPayload, target.objectGeneration);
3053
+ if (actor !== undefined) {
3054
+ return (0, actor_authority_publication_1.rewriteActorAuthorityRoute)(applicationPayload, {
3055
+ actorId: actor.actor.actorId,
3056
+ objectGeneration: actor.actor.objectGeneration,
3057
+ meshName: target.meshName,
3058
+ nodeRid: target.nodeRid
3059
+ }, target.actorSpotId ?? actor.spotId, target.actorSpotGeneration ?? actor.spotGeneration, target.actorSpotKind ?? actor.spotKind, target.nodeGeneration, target.owner);
3060
+ }
3061
+ return (0, service_authority_payload_codec_1.rewriteServiceAuthorityRoute)(applicationPayload, target.owner, target)
3062
+ ?? applicationPayload;
3063
+ }
3064
+ function actorMembershipTarget(envelope, actorKey) {
3065
+ const membership = envelope.memberships.find(value => value.actorKey === actorKey);
3066
+ if (membership === undefined)
3067
+ return undefined;
3068
+ return {
3069
+ actorSpotId: (0, authority_key_codec_1.decodeAuthorityKey)({ value: membership.spotKey }).globalId,
3070
+ actorSpotGeneration: membership.spotObjectGeneration
3071
+ };
3072
+ }
3073
+ function primaryKey(envelope) {
3074
+ return envelope.participants.find(value => value.objectKind !== 'actor')?.key
3075
+ ?? envelope.participants[0].key;
3076
+ }
3077
+ function relocationTargetRequirements(values) {
3078
+ const grouped = new Map();
3079
+ for (const value of values) {
3080
+ const key = `${value.objectKind}\0${value.stableType}\0${value.policy}`;
3081
+ const existing = grouped.get(key);
3082
+ grouped.set(key, existing === undefined
3083
+ ? value
3084
+ : { ...existing, count: existing.count + value.count });
3085
+ }
3086
+ return [...grouped.values()];
3087
+ }
3088
+ function relocationTargetSupports(descriptor, requirements) {
3089
+ if (descriptor.activationConcurrency.limit !== 0
3090
+ && descriptor.activationConcurrency.active >= descriptor.activationConcurrency.limit) {
3091
+ return false;
3092
+ }
3093
+ const actorCount = requirements
3094
+ .filter(value => value.objectKind === 'actor')
3095
+ .reduce((sum, value) => sum + value.count, 0);
3096
+ const spotCount = requirements
3097
+ .filter(value => value.objectKind !== 'actor')
3098
+ .reduce((sum, value) => sum + value.count, 0);
3099
+ if ((descriptor.populationCapacity.actors.limit !== 0
3100
+ && descriptor.populationCapacity.actors.active
3101
+ + descriptor.populationCapacity.actors.reserved
3102
+ + actorCount > descriptor.populationCapacity.actors.limit) || (descriptor.populationCapacity.spots.limit !== 0
3103
+ && descriptor.populationCapacity.spots.active
3104
+ + descriptor.populationCapacity.spots.reserved
3105
+ + spotCount > descriptor.populationCapacity.spots.limit)) {
3106
+ return false;
3107
+ }
3108
+ for (const requirement of requirements) {
3109
+ if (!descriptor.objectCapabilities.some(capability => capability.objectKind === requirement.objectKind
3110
+ && capability.stableType === requirement.stableType
3111
+ && capability.policy === requirement.policy)) {
3112
+ return false;
3113
+ }
3114
+ if (requirement.objectKind !== 'actor') {
3115
+ const capacity = descriptor.populationCapacity.spotTypes.find(value => value.objectKind === requirement.objectKind
3116
+ && value.stableType === requirement.stableType);
3117
+ if (capacity === undefined
3118
+ || (capacity.limit !== 0
3119
+ && capacity.active + capacity.reserved + requirement.count > capacity.limit)) {
3120
+ return false;
3121
+ }
3122
+ }
3123
+ }
3124
+ return true;
3125
+ }
3126
+ function selectWeightedRelocationTarget(candidates) {
3127
+ const total = candidates.reduce((sum, value) => sum + value.placementWeight, 0);
3128
+ if (total <= 0)
3129
+ return undefined;
3130
+ let selected = Math.random() * total;
3131
+ for (const candidate of candidates) {
3132
+ selected -= candidate.placementWeight;
3133
+ if (selected < 0)
3134
+ return candidate;
3135
+ }
3136
+ return candidates.at(-1);
3137
+ }
3138
+ function decodeQueuedHandoffPacket(message) {
3139
+ const payload = Buffer.from(message.payload);
3140
+ const frozen = isCanonicalFrozenRecord(payload)
3141
+ ? (0, service_stateful_wire_codec_1.decodeServiceWireFrozenRecord)(payload)
3142
+ : undefined;
3143
+ const value = JSON.parse(Buffer.from(frozen?.applicationPayload?.bytes ?? payload).toString('utf8'));
3144
+ const index = value.index;
3145
+ if (!Number.isSafeInteger(index) || index < 0) {
3146
+ throw new TypeError('Relocation Actor packet index is invalid.');
3147
+ }
3148
+ const messageFollowOrigin = decodeQueuedMessageFollowOrigin(value.messageFollowOrigin);
3149
+ const decoded = (0, spot_remote_codec_1.decodeHandoffBacklog)([{
3150
+ ...value,
3151
+ index: 0,
3152
+ ...(messageFollowOrigin === undefined ? {} : { messageFollowOrigin })
3153
+ }])[0];
3154
+ return { ...decoded, index: index };
3155
+ }
3156
+ /**
3157
+ * The JSON relocation envelope remains the Stage 1 container, but Actor
3158
+ * backlog entries are frozen service-wire records before it leaves source
3159
+ * ownership. This makes correlation, reply route and canonical payload
3160
+ * validation part of the captured record rather than an ad-hoc JSON packet.
3161
+ */
3162
+ function canonicalizeCapturedHandoffBacklog(envelope, coordinator, target) {
3163
+ return {
3164
+ ...envelope,
3165
+ participants: envelope.participants.map(participant => participant.objectKind !== 'actor'
3166
+ ? participant
3167
+ : {
3168
+ ...participant,
3169
+ queuedMessages: participant.queuedMessages.map(message => ({
3170
+ ...message,
3171
+ payload: canonicalQueuedFrozenRecord(participant, message, coordinator, target).canonicalBytes
3172
+ }))
3173
+ })
3174
+ };
3175
+ }
3176
+ function appendCanonicalActorJoinRecovery(envelope, profile, coordinator, sourceAuthoritySnapshot) {
3177
+ const recovery = profile.canonicalRecovery;
3178
+ const actorType = profile.state.actorType;
3179
+ const sourceAuthority = (0, actor_authority_publication_1.decodeRelocatingActorAuthorityIdentity)(sourceAuthoritySnapshot.payload, sourceAuthoritySnapshot.objectGeneration);
3180
+ if (actorType === undefined
3181
+ || sourceAuthority === undefined
3182
+ || sourceAuthority.actor.actorId !== profile.state.actorId
3183
+ || sourceAuthority.actor.objectGeneration !== profile.sourceActorRef.generation
3184
+ || !(0, routing_id_1.routingIdsEqual)(sourceAuthority.actor.nodeRid, profile.sourceActorRef.nodeRid)
3185
+ || sourceAuthority.ownerNodeGeneration !== recovery.actorNodeGeneration
3186
+ || sourceAuthoritySnapshot.authorityOwnerGeneration !== profile.state.locationGeneration) {
3187
+ throw new Error(`Actor '${profile.state.actorId}' canonical Join recovery identity is incomplete.`);
3188
+ }
3189
+ const attachment = { attached: false };
3190
+ const participants = envelope.participants.map(participant => {
3191
+ if (participant.objectKind !== 'actor'
3192
+ || (0, authority_key_codec_1.decodeAuthorityKey)({ value: participant.key }).globalId
3193
+ !== profile.state.actorId) {
3194
+ return participant;
3195
+ }
3196
+ if (attachment.attached)
3197
+ throw new Error('Canonical Actor Join recovery has duplicate Actor participants.');
3198
+ attachment.attached = true;
3199
+ const encoded = (0, actor_join_recovery_codec_1.encodeCanonicalActorJoinRecoverySavedWork)({
3200
+ actorId: profile.state.actorId,
3201
+ actorType,
3202
+ handoffId: recovery.handoffId,
3203
+ // The command-28 target admitted this same fenced Store authority. Keep
3204
+ // its CurrentSpotId as the recovery identity instead of projecting the
3205
+ // application Actor state (which may already name an Entry fallback).
3206
+ sourceSpotId: sourceAuthority.spotId,
3207
+ sourceNodeRid: profile.sourceActorRef.nodeRid,
3208
+ actorGeneration: profile.sourceActorRef.generation,
3209
+ actorAuthorityOwnerGeneration: sourceAuthoritySnapshot.authorityOwnerGeneration,
3210
+ actorNodeGeneration: recovery.actorNodeGeneration,
3211
+ expectedOwnerLeaseGeneration: recovery.expectedOwnerLeaseGeneration,
3212
+ relocationId: envelope.aggregateId,
3213
+ relocationContentType: profile.relocationContentType,
3214
+ requestContentType: recovery.requestContentType,
3215
+ request: recovery.request,
3216
+ targetSpotId: String(profile.targetSpotId),
3217
+ targetNodeRid: profile.targetNodeRid,
3218
+ targetNodeGeneration: recovery.targetNodeGeneration,
3219
+ targetSpotGeneration: recovery.targetSpotGeneration,
3220
+ targetAuthorityOwnerGeneration: recovery.targetAuthorityOwnerGeneration,
3221
+ targetSpotAuthorityOwnerGeneration: recovery.targetSpotAuthorityOwnerGeneration,
3222
+ coordinator: {
3223
+ ownerId: coordinator.ownerId,
3224
+ leaseGeneration: coordinator.leaseGeneration,
3225
+ nodeRid: coordinator.nodeRid,
3226
+ nodeGeneration: coordinator.nodeGeneration,
3227
+ expectedAuthorityStoreVersion: coordinator.expectedAuthorityStoreVersion
3228
+ },
3229
+ operationId: recovery.admissionOperationId,
3230
+ ...(recovery.replyContentType === undefined
3231
+ ? {}
3232
+ : { replyContentType: recovery.replyContentType }),
3233
+ reply: recovery.reply
3234
+ });
3235
+ return {
3236
+ ...participant,
3237
+ queuedMessages: [
3238
+ { sequence: 1n, payload: encoded },
3239
+ ...participant.queuedMessages.map(message => ({
3240
+ ...message,
3241
+ sequence: message.sequence + 1n
3242
+ }))
3243
+ ]
3244
+ };
3245
+ });
3246
+ if (!attachment.attached)
3247
+ throw new Error('Canonical Actor Join recovery Actor participant is missing.');
3248
+ return { ...envelope, participants };
3249
+ }
3250
+ function isCanonicalFrozenRecord(payload) {
3251
+ try {
3252
+ (0, service_stateful_wire_codec_1.decodeServiceWireFrozenRecord)(payload);
3253
+ return true;
3254
+ }
3255
+ catch {
3256
+ return false;
3257
+ }
3258
+ }
3259
+ function relocationWireId(value) {
3260
+ const hex = value.replaceAll('-', '');
3261
+ if (!/^[0-9a-fA-F]{32}$/.test(hex)) {
3262
+ throw new Error(`Relocation aggregate '${value}' is not a canonical 128-bit identity.`);
3263
+ }
3264
+ const result = {
3265
+ high: BigInt(`0x${hex.slice(0, 16)}`),
3266
+ low: BigInt(`0x${hex.slice(16)}`)
3267
+ };
3268
+ if (result.high === 0n && result.low === 0n) {
3269
+ throw new Error('Relocation identity must not be zero.');
3270
+ }
3271
+ return result;
3272
+ }
3273
+ function createServiceRelocationId(isInUse, entropy = node_crypto_1.randomBytes) {
3274
+ for (;;) {
3275
+ const bytes = entropy(16);
3276
+ if (bytes.byteLength !== 16) {
3277
+ throw new Error('Relocation identity entropy must return exactly 16 bytes.');
3278
+ }
3279
+ let nonZero = false;
3280
+ for (const byte of bytes) {
3281
+ if (byte !== 0) {
3282
+ nonZero = true;
3283
+ break;
3284
+ }
3285
+ }
3286
+ if (!nonZero)
3287
+ continue;
3288
+ const hex = Buffer.from(bytes).toString('hex');
3289
+ const candidate = `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-`
3290
+ + `${hex.slice(16, 20)}-${hex.slice(20)}`;
3291
+ if (!isInUse(candidate))
3292
+ return candidate;
3293
+ }
3294
+ }
3295
+ function operationWireId(value) {
3296
+ const match = /^(\d+):(\d+)$/.exec(value);
3297
+ if (match === null)
3298
+ throw new Error(`Actor handoff operation '${value}' is not canonical.`);
3299
+ const result = { high: BigInt(match[1]), low: BigInt(match[2]) };
3300
+ if (result.high === 0n && result.low === 0n) {
3301
+ throw new Error('Actor handoff operation identity must not be zero.');
3302
+ }
3303
+ return result;
3304
+ }
3305
+ function sameWireId(left, right) {
3306
+ return left.high === right.high && left.low === right.low;
3307
+ }
3308
+ function sameCoordinator(left, right) {
3309
+ return left.ownerId === right.ownerId
3310
+ && left.leaseGeneration === right.leaseGeneration
3311
+ && left.nodeRid === right.nodeRid
3312
+ && left.nodeGeneration === right.nodeGeneration
3313
+ && left.expectedAuthorityStoreVersion === right.expectedAuthorityStoreVersion;
3314
+ }
3315
+ function isExactSourceAuthority(current, expected) {
3316
+ return current.storeVersion.value === expected.storeVersion.value
3317
+ && current.objectGeneration === expected.objectGeneration
3318
+ && current.authorityOwnerGeneration === expected.authorityOwnerGeneration
3319
+ && current.ownerId === expected.ownerId
3320
+ && current.ownerLeaseGeneration === expected.ownerLeaseGeneration
3321
+ && current.allocation.state === expected.allocation.state
3322
+ && current.allocation.objectKind === expected.allocation.objectKind
3323
+ && current.allocation.stableType === expected.allocation.stableType
3324
+ && String(current.allocation.descriptor.rid)
3325
+ === String(expected.allocation.descriptor.rid)
3326
+ && current.allocation.descriptorLifecycleGeneration
3327
+ === expected.allocation.descriptorLifecycleGeneration;
3328
+ }
3329
+ function isExactCommittedTarget(current, expected, target, payload) {
3330
+ return current.objectGeneration === expected.objectGeneration
3331
+ && current.authorityOwnerGeneration > expected.authorityOwnerGeneration
3332
+ && current.ownerId === target.ownerId
3333
+ && current.ownerLeaseGeneration === target.ownerLeaseGeneration
3334
+ && String(current.allocation.descriptor.rid) === target.nodeRid
3335
+ && current.allocation.descriptorLifecycleGeneration === target.nodeGeneration
3336
+ && Buffer.from(current.payload).equals(Buffer.from(payload));
3337
+ }
3338
+ async function waitForLocationRetry(deadlineAtMs, signal, cause) {
3339
+ signal?.throwIfAborted();
3340
+ if (performance.now() >= deadlineAtMs) {
3341
+ throw new Error('location_update_failed: relocation Restore validity expired before exact target owner confirmation.', { cause });
3342
+ }
3343
+ await new Promise((resolve, reject) => {
3344
+ let timer;
3345
+ const aborted = () => {
3346
+ if (timer !== undefined)
3347
+ clearTimeout(timer);
3348
+ reject(signal?.reason);
3349
+ };
3350
+ signal?.addEventListener('abort', aborted, { once: true });
3351
+ timer = setTimeout(() => {
3352
+ signal?.removeEventListener('abort', aborted);
3353
+ resolve();
3354
+ }, Math.min(25, Math.max(1, deadlineAtMs - performance.now())));
3355
+ timer.unref();
3356
+ });
3357
+ }
3358
+ async function waitForRelocationRetry(delayMs, signal) {
3359
+ signal?.throwIfAborted();
3360
+ await new Promise((resolve, reject) => {
3361
+ let timer;
3362
+ const aborted = () => {
3363
+ if (timer !== undefined)
3364
+ clearTimeout(timer);
3365
+ reject(signal?.reason);
3366
+ };
3367
+ signal?.addEventListener('abort', aborted, { once: true });
3368
+ timer = setTimeout(() => {
3369
+ signal?.removeEventListener('abort', aborted);
3370
+ resolve();
3371
+ }, delayMs);
3372
+ timer.unref();
3373
+ });
3374
+ }
3375
+ function sameRequestSource(left, right) {
3376
+ return left.ownerId === right.ownerId
3377
+ && left.leaseGeneration === right.leaseGeneration
3378
+ && left.nodeRid === right.nodeRid
3379
+ && left.nodeGeneration === right.nodeGeneration;
3380
+ }
3381
+ function handoffSourceFence(value) {
3382
+ return {
3383
+ ownerId: value.ownerId,
3384
+ leaseGeneration: BigInt(value.ownerLeaseGeneration),
3385
+ nodeRid: value.nodeRid,
3386
+ nodeGeneration: BigInt(value.nodeGeneration)
3387
+ };
3388
+ }
3389
+ function maintenanceReplyRelay(stage, coordinator, participantId, completion) {
3390
+ const value = completion.result.ok ? completion.result.response : undefined;
3391
+ return {
3392
+ relocation: relocationWireId(stage.staging.envelope.aggregateId),
3393
+ targetAttemptGeneration: stage.offer.prepare.targetAttemptGeneration,
3394
+ coordinator,
3395
+ operation: operationWireId(completion.operationId),
3396
+ replyRouteId: BigInt(completion.source.replyRouteId),
3397
+ participantId,
3398
+ sequence: BigInt(completion.index + 1),
3399
+ terminalResult: completion.result.ok ? 0 : 105,
3400
+ failureCode: completion.result.ok ? 0 : 17,
3401
+ ...(value === undefined ? {} : { payload: {
3402
+ packetName: 'zlink.relocation.reply',
3403
+ contentType: 'application/json',
3404
+ bytes: Buffer.from(JSON.stringify(value), 'utf8')
3405
+ } })
3406
+ };
3407
+ }
3408
+ function handoffResultFromRelay(relay) {
3409
+ if (relay.sequence > BigInt(Number.MAX_SAFE_INTEGER)) {
3410
+ throw new TypeError('Relocation terminal sequence exceeds the Node index range.');
3411
+ }
3412
+ let value;
3413
+ if (relay.payload !== undefined) {
3414
+ if (relay.terminalResult !== 0
3415
+ || relay.payload.packetName !== 'zlink.relocation.reply'
3416
+ || relay.payload.contentType !== 'application/json') {
3417
+ throw new TypeError('Relocation terminal payload boundary is invalid.');
3418
+ }
3419
+ value = JSON.parse(Buffer.from(relay.payload.bytes).toString('utf8'));
3420
+ }
3421
+ const index = Number(relay.sequence - 1n);
3422
+ return relay.terminalResult === 0
3423
+ ? { index, ok: true, ...(value === undefined ? {} : { response: value }) }
3424
+ : { index, ok: false, error: `Actor handoff failed with framework code ${relay.failureCode}.` };
3425
+ }
3426
+ function wireIdText(value) {
3427
+ return `${value.high}:${value.low}`;
3428
+ }
3429
+ /**
3430
+ * Tags a target-side restore failure as data loss (chunk assembly or
3431
+ * checksum verification) so relocationFailed reports failureCode 35 rather
3432
+ * than the generic internal-failure code (spec 15 §4).
3433
+ */
3434
+ class ServiceRelocationDataLostError extends Error {
3435
+ }
3436
+ exports.ServiceRelocationDataLostError = ServiceRelocationDataLostError;
3437
+ /**
3438
+ * Maps a target-side relocation Prepare failure to the closest wire
3439
+ * framework-error code the generated schema
3440
+ * ({@link ServiceWireFrameworkErrorCode}) defines — mirrors the java
3441
+ * reference mapping (commit 97fc074058) and the dotnet/cpp ports. The wire
3442
+ * vocabulary predates the framework's typed error kinds and has no
3443
+ * one-to-one code for every kind, so several kinds share the nearest fit
3444
+ * (documented per case below); unresolvable vocabulary gaps belong at the
3445
+ * schema level, not invented here. {@link ServiceRelocationDataLostError}
3446
+ * is this runtime's dedicated tag for a verified checksum/assembly/digest
3447
+ * integrity failure — the case that keeps relocationDataLost(35). An
3448
+ * unclassified error carries no evidence of integrity loss and takes the
3449
+ * generic opaque requestFailed(17). `objectKind` (the Prepare's
3450
+ * ObjectFence.kind, spec 28 §4.2) picks between an Actor- and
3451
+ * Spot-specific code where the schema splits by object kind.
3452
+ */
3453
+ function relocationFailedFailureCode(error, objectKind) {
3454
+ if (error instanceof ServiceRelocationDataLostError) {
3455
+ return service_wire_constants_generated_1.ServiceWireFrameworkErrorCode.relocationDataLost;
3456
+ }
3457
+ if (!(error instanceof contracts_1.ZLinkFrameworkException)) {
3458
+ return service_wire_constants_generated_1.ServiceWireFrameworkErrorCode.requestFailed;
3459
+ }
3460
+ switch (error.kind) {
3461
+ case contracts_1.ZLinkFrameworkErrorKind.DataLost:
3462
+ return service_wire_constants_generated_1.ServiceWireFrameworkErrorCode.relocationDataLost;
3463
+ case contracts_1.ZLinkFrameworkErrorKind.Rejected:
3464
+ return service_wire_constants_generated_1.ServiceWireFrameworkErrorCode.requestRejected;
3465
+ case contracts_1.ZLinkFrameworkErrorKind.ProtocolError:
3466
+ return service_wire_constants_generated_1.ServiceWireFrameworkErrorCode.requestProtocolError;
3467
+ // No dedicated "capacity exceeded" wire code exists; a full queue is
3468
+ // the closest capacity-shaped signal.
3469
+ case contracts_1.ZLinkFrameworkErrorKind.CapacityExceeded:
3470
+ return service_wire_constants_generated_1.ServiceWireFrameworkErrorCode.workerQueueFull;
3471
+ // No dedicated "deadline exceeded" wire code exists; a worker timeout
3472
+ // is the closest timeout-shaped signal.
3473
+ case contracts_1.ZLinkFrameworkErrorKind.DeadlineExceeded:
3474
+ return service_wire_constants_generated_1.ServiceWireFrameworkErrorCode.workerTimedOut;
3475
+ // A stale generation/fence is the concrete cause of InvalidOperation
3476
+ // along this path (spec 15 failure table); pick the
3477
+ // object-kind-specific stale code.
3478
+ case contracts_1.ZLinkFrameworkErrorKind.InvalidOperation:
3479
+ return objectKind === 'actor'
3480
+ ? service_wire_constants_generated_1.ServiceWireFrameworkErrorCode.actorLocationStale
3481
+ : service_wire_constants_generated_1.ServiceWireFrameworkErrorCode.spotGenerationStale;
3482
+ // No dedicated generic "unavailable" wire code exists; a disconnected
3483
+ // route is the closest "cannot reach/use the target" signal.
3484
+ case contracts_1.ZLinkFrameworkErrorKind.Unavailable:
3485
+ return service_wire_constants_generated_1.ServiceWireFrameworkErrorCode.routeNotConnected;
3486
+ case contracts_1.ZLinkFrameworkErrorKind.NotFound:
3487
+ return service_wire_constants_generated_1.ServiceWireFrameworkErrorCode.requestTargetNotFound;
3488
+ // The only "already exists" wire code is Actor-specific; not expected
3489
+ // along this target-failure path, mapped for completeness.
3490
+ case contracts_1.ZLinkFrameworkErrorKind.AlreadyExists:
3491
+ return service_wire_constants_generated_1.ServiceWireFrameworkErrorCode.actorAlreadyExists;
3492
+ case contracts_1.ZLinkFrameworkErrorKind.TypeMismatch:
3493
+ return objectKind === 'actor'
3494
+ ? service_wire_constants_generated_1.ServiceWireFrameworkErrorCode.actorTypeMismatch
3495
+ : service_wire_constants_generated_1.ServiceWireFrameworkErrorCode.spotTypeMismatch;
3496
+ // No dedicated "not configured" wire code exists; a missing configured
3497
+ // handler is the closest analog.
3498
+ case contracts_1.ZLinkFrameworkErrorKind.NotConfigured:
3499
+ return service_wire_constants_generated_1.ServiceWireFrameworkErrorCode.handlerNotFound;
3500
+ // No dedicated generic "internal failure" or "shutting down" wire code
3501
+ // exists; the generic opaque request-failure code is the closest fit
3502
+ // for both (ShuttingDown included — re-judged 2026-08-19, C-10).
3503
+ case contracts_1.ZLinkFrameworkErrorKind.ShuttingDown:
3504
+ case contracts_1.ZLinkFrameworkErrorKind.InternalFailure:
3505
+ default:
3506
+ return service_wire_constants_generated_1.ServiceWireFrameworkErrorCode.requestFailed;
3507
+ }
3508
+ }
3509
+ function relocationStagingId(value) {
3510
+ return `${value.relocation.high}:${value.relocation.low}:${value.targetAttemptGeneration}`;
3511
+ }
3512
+ function coordinatorSource(value) {
3513
+ return { ownerId: value.ownerId, leaseGeneration: value.leaseGeneration,
3514
+ nodeRid: value.nodeRid, nodeGeneration: value.nodeGeneration };
3515
+ }
3516
+ function relocationObject(envelope) {
3517
+ const participant = envelope.participants.find(value => value.objectKind !== 'actor')
3518
+ ?? envelope.participants[0];
3519
+ const identity = (0, authority_key_codec_1.decodeAuthorityKey)({ value: participant.key }).globalId;
3520
+ if (participant.objectKind === 'actor') {
3521
+ return { kind: 'actor', actorId: identity, objectGeneration: participant.objectGeneration,
3522
+ expectedAuthorityOwnerGeneration: participant.authorityOwnerGeneration };
3523
+ }
3524
+ if (participant.objectKind === 'user_spot') {
3525
+ return { kind: 'userSpot', spotId: identity, objectGeneration: participant.objectGeneration,
3526
+ expectedAuthorityOwnerGeneration: participant.authorityOwnerGeneration };
3527
+ }
3528
+ return { kind: 'instanceSpot', stableType: participant.stableType,
3529
+ spotId: identity, objectGeneration: participant.objectGeneration };
3530
+ }
3531
+ function relocationObjectForParticipant(participant) {
3532
+ const identity = (0, authority_key_codec_1.decodeAuthorityKey)({ value: participant.key }).globalId;
3533
+ if (participant.objectKind === 'actor') {
3534
+ return {
3535
+ kind: 'actor',
3536
+ actorId: identity,
3537
+ objectGeneration: participant.objectGeneration,
3538
+ expectedAuthorityOwnerGeneration: participant.authorityOwnerGeneration
3539
+ };
3540
+ }
3541
+ if (participant.objectKind === 'user_spot') {
3542
+ return {
3543
+ kind: 'userSpot',
3544
+ spotId: identity,
3545
+ objectGeneration: participant.objectGeneration,
3546
+ expectedAuthorityOwnerGeneration: participant.authorityOwnerGeneration
3547
+ };
3548
+ }
3549
+ return {
3550
+ kind: 'instanceSpot',
3551
+ stableType: participant.stableType,
3552
+ spotId: identity,
3553
+ objectGeneration: participant.objectGeneration
3554
+ };
3555
+ }
3556
+ function relocationReady(request) {
3557
+ return {
3558
+ kind: 'ready',
3559
+ relocation: request.relocation,
3560
+ targetAttemptGeneration: request.targetAttemptGeneration,
3561
+ coordinator: request.coordinator,
3562
+ target: request.target,
3563
+ object: request.object,
3564
+ senderRole: 'target'
3565
+ };
3566
+ }
3567
+ function relocationFailed(request, failureCode) {
3568
+ return {
3569
+ kind: 'failed',
3570
+ relocation: request.relocation,
3571
+ targetAttemptGeneration: request.targetAttemptGeneration,
3572
+ coordinator: request.coordinator,
3573
+ target: request.target,
3574
+ object: request.object,
3575
+ senderRole: 'target',
3576
+ failureCode
3577
+ };
3578
+ }
3579
+ function validatePrepareEnvelope(request, envelope) {
3580
+ if (!sameWireId(request.relocation, relocationWireId(envelope.aggregateId))
3581
+ || request.applicationVersion !== envelope.applicationVersion
3582
+ || stringifyWire(request.object) !== stringifyWire(relocationObject(envelope))) {
3583
+ throw new Error('Relocation Prepare does not match its immutable root identity.');
3584
+ }
3585
+ }
3586
+ function validateTargetOneWayControl(stage, request, sourceNodeRid) {
3587
+ const prepare = stage.offer.prepare;
3588
+ if (String(sourceNodeRid) !== stage.offer.authenticatedSourceNodeRid
3589
+ || !sameWireId(request.relocation, prepare.relocation)
3590
+ || request.targetAttemptGeneration !== prepare.targetAttemptGeneration
3591
+ || !sameCoordinator(request.coordinator, prepare.coordinator)
3592
+ || stringifyWire(request.object) !== stringifyWire(request.kind === 'data' ? request.object : prepare.object)) {
3593
+ throw new Error('Relocation one-way control changed its exact Prepare fence.');
3594
+ }
3595
+ if (request.kind === 'cutover'
3596
+ && stringifyWire(request.object) !== stringifyWire(prepare.object)) {
3597
+ throw new Error('Relocation Cutover changed its prepared object.');
3598
+ }
3599
+ }
3600
+ function relocationPublication(prepare, envelope) {
3601
+ // The direct transfer has no durable store root; the authority wrapper
3602
+ // keeps a synthetic in-progress marker derived from the exact relocation
3603
+ // identity and the payload manifest checksum.
3604
+ return {
3605
+ reference: `zlink-direct:${envelope.aggregateId}:${prepare.targetAttemptGeneration}`,
3606
+ checksumCrc32c: prepare.payloadChecksumCrc32c,
3607
+ aggregateId: envelope.aggregateId,
3608
+ aggregateGeneration: envelope.aggregateGeneration,
3609
+ targetAttemptGeneration: prepare.targetAttemptGeneration,
3610
+ targetNodeRid: prepare.target.nodeRid,
3611
+ targetNodeGeneration: prepare.target.nodeGeneration,
3612
+ coordinatorOwnerId: prepare.coordinator.ownerId,
3613
+ coordinatorLeaseGeneration: prepare.coordinator.leaseGeneration,
3614
+ coordinatorNodeRid: prepare.coordinator.nodeRid,
3615
+ coordinatorNodeGeneration: prepare.coordinator.nodeGeneration,
3616
+ coordinatorExpectedStoreVersion: prepare.coordinator.expectedAuthorityStoreVersion,
3617
+ inventoryDigest: (0, service_relocation_runtime_1.inventoryDigest)(envelope.participants, envelope.memberships),
3618
+ targetOwnerId: prepare.target.ownerId,
3619
+ targetOwnerLeaseGeneration: prepare.target.ownerLeaseGeneration
3620
+ };
3621
+ }
3622
+ function canonicalRelayFrozenRecord(participant, packet, coordinator, target) {
3623
+ const message = encodeHandoffQueuedMessages([packet])[0];
3624
+ return canonicalQueuedFrozenRecord(participant, message, coordinator, target);
3625
+ }
3626
+ function raceAbort(operation, signal) {
3627
+ if (signal.aborted)
3628
+ return Promise.reject(signal.reason);
3629
+ return new Promise((resolve, reject) => {
3630
+ const aborted = () => reject(signal.reason);
3631
+ signal.addEventListener('abort', aborted, { once: true });
3632
+ operation.then(value => {
3633
+ signal.removeEventListener('abort', aborted);
3634
+ resolve(value);
3635
+ }, error => {
3636
+ signal.removeEventListener('abort', aborted);
3637
+ reject(error);
3638
+ });
3639
+ });
3640
+ }
3641
+ function canonicalQueuedFrozenRecord(participant, message, coordinator, target) {
3642
+ if (participant.objectKind !== 'actor') {
3643
+ throw new Error('Only Actor object-mailbox participants can contain accepted packets.');
3644
+ }
3645
+ const packet = decodeQueuedHandoffPacket(message);
3646
+ const identity = (0, authority_key_codec_1.decodeAuthorityKey)({ value: participant.key }).globalId;
3647
+ const source = packet.source === undefined
3648
+ ? coordinatorSource(coordinator)
3649
+ : {
3650
+ ownerId: packet.source.ownerId,
3651
+ leaseGeneration: BigInt(packet.source.ownerLeaseGeneration),
3652
+ nodeRid: packet.source.nodeRid,
3653
+ nodeGeneration: BigInt(packet.source.nodeGeneration)
3654
+ };
3655
+ const operationId = parseHandoffOperationId(packet.messageFollowContext.operationId);
3656
+ if (packet.returnResponse && packet.source === undefined) {
3657
+ throw new Error('Captured Actor request has no exact request-source fence.');
3658
+ }
3659
+ if (!packet.returnResponse && packet.source === undefined
3660
+ && packet.remoteBoundSessionTarget !== undefined) {
3661
+ // A durable frozen record is permitted only for a lease-backed source.
3662
+ // Work tied to a Session connection's lifetime drains before Captured,
3663
+ // so freezing it under the coordinator's fence is a protocol error.
3664
+ throw new Error('Captured connection-bound Actor send cannot enter a relocation envelope.');
3665
+ }
3666
+ return (0, service_stateful_wire_codec_1.encodeServiceWireFrozenActorApplicationRecord)({
3667
+ source,
3668
+ target: {
3669
+ actorId: identity,
3670
+ objectGeneration: participant.objectGeneration,
3671
+ nodeRid: target.nodeRid,
3672
+ nodeGeneration: target.nodeGeneration,
3673
+ authorityOwnerGeneration: participant.authorityOwnerGeneration + 1n,
3674
+ ownerLeaseGeneration: target.ownerLeaseGeneration
3675
+ },
3676
+ operationId,
3677
+ ...(packet.returnResponse ? { replyRouteId: BigInt(packet.source.replyRouteId) } : {}),
3678
+ payload: {
3679
+ packetName: '__zlink.actor.handoff.accepted',
3680
+ contentType: 'application/json',
3681
+ bytes: message.payload
3682
+ }
3683
+ });
3684
+ }
3685
+ function parseHandoffOperationId(value) {
3686
+ if (!/^[0-9a-f]{32}$/.test(value)) {
3687
+ throw new Error('Captured Actor operation ID is invalid.');
3688
+ }
3689
+ const operation = {
3690
+ high: BigInt(`0x${value.slice(0, 16)}`),
3691
+ low: BigInt(`0x${value.slice(16)}`)
3692
+ };
3693
+ if (operation.high === 0n && operation.low === 0n) {
3694
+ throw new Error('Captured Actor operation ID must not be zero.');
3695
+ }
3696
+ return operation;
3697
+ }
3698
+ function stringifyWire(value) {
3699
+ return JSON.stringify(value, (_key, item) => typeof item === 'bigint' ? item.toString() : item);
3700
+ }
3701
+ function validateControlResponse(request, response) {
3702
+ if (request.kind !== 'prepare'
3703
+ || response.kind !== 'ready'
3704
+ || !sameWireId(response.relocation, request.relocation)
3705
+ || response.targetAttemptGeneration !== request.targetAttemptGeneration
3706
+ || !sameCoordinator(response.coordinator, request.coordinator)
3707
+ || stringifyWire(response.target) !== stringifyWire(request.target)
3708
+ || stringifyWire(response.object) !== stringifyWire(request.object)
3709
+ || response.senderRole !== 'target') {
3710
+ throw new Error('Relocation control response does not match the request fence.');
3711
+ }
3712
+ }
3713
+ /**
3714
+ * Same exact-identity fence as {@link validateControlResponse}, for an
3715
+ * explicit Failed(53) reply. A Failed for a different relocation identity
3716
+ * (exact ordinal/coordinator/target/object) must never resolve a different
3717
+ * pending Prepare's ACK.
3718
+ */
3719
+ function validateControlFailureResponse(request, response) {
3720
+ if (request.kind !== 'prepare'
3721
+ || response.kind !== 'failed'
3722
+ || !sameWireId(response.relocation, request.relocation)
3723
+ || response.targetAttemptGeneration !== request.targetAttemptGeneration
3724
+ || !sameCoordinator(response.coordinator, request.coordinator)
3725
+ || stringifyWire(response.target) !== stringifyWire(request.target)
3726
+ || stringifyWire(response.object) !== stringifyWire(request.object)
3727
+ || response.senderRole !== 'target') {
3728
+ throw new Error('Relocation control response does not match the request fence.');
3729
+ }
3730
+ }
3731
+ /**
3732
+ * Maps a relocationFailed(53) wire failureCode (the generated
3733
+ * ServiceWireFrameworkErrorCode vocabulary) to its internal error kind, so a
3734
+ * source-side reject carries the same classification the target chose
3735
+ * instead of a generic Error. Direct 1:1 correspondence with the generated
3736
+ * names; an unrecognised or absent code falls back to RequestFailed
3737
+ * (InternalFailure) — the closest existing kind (spec 15 §"Failed.Kind").
3738
+ */
3739
+ function relocationFailureCodeKind(failureCode) {
3740
+ switch (failureCode) {
3741
+ case 1: return framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.ActorRouteNotFound;
3742
+ case 2: return framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.ActorCreateFailed;
3743
+ case 3: return framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.ActorAlreadyExists;
3744
+ case 4: return framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.ActorTypeMismatch;
3745
+ case 5: return framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotCreateFailed;
3746
+ case 6: return framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotRouteNotFound;
3747
+ case 7: return framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotTypeMismatch;
3748
+ case 8: return framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.ActorSessionNotBound;
3749
+ case 9: return framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.HandlerNotFound;
3750
+ case 10: return framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.RouteHandlerNotFound;
3751
+ case 11: return framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.ActorDispatchHandlerNotFound;
3752
+ case 12: return framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.PayloadDecodeFailed;
3753
+ case 13: return framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.RouteNotConnected;
3754
+ case 14: return framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.RequestTargetNotFound;
3755
+ case 15: return framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.RequestRejected;
3756
+ case 16: return framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.RequestProtocolError;
3757
+ case 18: return framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.WorkerQueueFull;
3758
+ case 19: return framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.WorkerTimedOut;
3759
+ case 20: return framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.WorkerFailed;
3760
+ case 21: return framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.ActorLocationStale;
3761
+ case 22: return framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.ActorCreateRejected;
3762
+ case 33: return framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotGenerationStale;
3763
+ case 34: return framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotMoving;
3764
+ case 35: return framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.RelocationDataLost;
3765
+ case 17:
3766
+ default:
3767
+ return framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.RequestFailed;
3768
+ }
3769
+ }
3770
+ /** Builds the typed exception a Prepare waiter rejects with on an explicit Failed(53). */
3771
+ function relocationFailureException(response) {
3772
+ return (0, framework_errors_internal_1.createInternalFrameworkException)(relocationFailureCodeKind(response.failureCode), `Relocation '${response.relocation.high}:${response.relocation.low}:`
3773
+ + `${response.targetAttemptGeneration}' failed with wire failureCode ${response.failureCode}.`, true);
3774
+ }
3775
+ function controlAckKey(request) {
3776
+ if (request.kind !== 'prepare') {
3777
+ throw new Error(`Relocation ${request.kind} is one-way and has no response key.`);
3778
+ }
3779
+ return `relocation:${request.relocation.high}:${request.relocation.low}:`
3780
+ + `${request.targetAttemptGeneration}:ready`;
3781
+ }
3782
+ function sessionRelocationPendingKey(request) {
3783
+ return sessionRelocationIdentityKey(request);
3784
+ }
3785
+ function sessionRelocationRouteSubmitKey(request, targetNodeRid) {
3786
+ return `${sessionRelocationIdentityKey(request)}:${String(targetNodeRid)}`;
3787
+ }
3788
+ function sessionRelocationResponseKey(response) {
3789
+ return sessionRelocationIdentityKey(response);
3790
+ }
3791
+ function sessionRelocationResponseFingerprint(response) {
3792
+ return (0, service_stateful_wire_codec_1.encodeSessionRelocationSealed)(response).toString('base64');
3793
+ }
3794
+ function sessionRelocationIdentityKey(value) {
3795
+ return `session-relocation:${(0, service_stateful_wire_codec_1.serviceSessionRelocationIdentityKey)(value)}:sealed`;
3796
+ }
3797
+ function validateSessionRelocationResponse(request, response) {
3798
+ const sameCoordinator = request.coordinator.ownerId === response.coordinator.ownerId
3799
+ && request.coordinator.leaseGeneration === response.coordinator.leaseGeneration
3800
+ && request.coordinator.nodeRid === response.coordinator.nodeRid
3801
+ && request.coordinator.nodeGeneration === response.coordinator.nodeGeneration
3802
+ && request.coordinator.expectedAuthorityStoreVersion
3803
+ === response.coordinator.expectedAuthorityStoreVersion;
3804
+ const sameSession = request.session.sessionOwnerNodeRid === response.session.sessionOwnerNodeRid
3805
+ && request.session.sessionOwnerNodeGeneration
3806
+ === response.session.sessionOwnerNodeGeneration
3807
+ && request.session.sessionOwnerId === response.session.sessionOwnerId
3808
+ && request.session.sessionOwnerLeaseGeneration
3809
+ === response.session.sessionOwnerLeaseGeneration
3810
+ && request.session.sessionRid === response.session.sessionRid
3811
+ && request.session.bindingGeneration === response.session.bindingGeneration;
3812
+ if (request.relocation.high !== response.relocation.high
3813
+ || request.relocation.low !== response.relocation.low
3814
+ || !sameCoordinator
3815
+ || !sameSession) {
3816
+ throw new service_wire_m6a_codec_1.ServiceWireProtocolError('Session relocation ACK changed its exact fence.');
3817
+ }
3818
+ if (request.actor.actor.actorId !== response.actor.actor.actorId
3819
+ || request.actor.actor.generation !== response.actor.actor.generation
3820
+ || request.actor.actor.nodeRid !== response.actor.actor.nodeRid
3821
+ || request.actor.targetNodeGeneration !== response.actor.targetNodeGeneration
3822
+ || request.actor.authorityOwnerGeneration !== response.actor.authorityOwnerGeneration
3823
+ || request.actor.ownerLeaseGeneration !== response.actor.ownerLeaseGeneration) {
3824
+ throw new service_wire_m6a_codec_1.ServiceWireProtocolError('Command 43 ACK does not echo command 42.');
3825
+ }
3826
+ }
3827
+ function replyRelayIdentityKey(value) {
3828
+ return JSON.stringify([
3829
+ value.operation.high.toString(),
3830
+ value.operation.low.toString(),
3831
+ value.replyRouteId.toString(),
3832
+ value.relocation.high.toString(),
3833
+ value.relocation.low.toString(),
3834
+ value.coordinator.ownerId,
3835
+ value.coordinator.leaseGeneration.toString(),
3836
+ value.coordinator.nodeRid,
3837
+ value.coordinator.nodeGeneration.toString(),
3838
+ value.coordinator.expectedAuthorityStoreVersion
3839
+ ]);
3840
+ }
3841
+ function replyRelayPendingKey(ackTargetNodeRid, value) {
3842
+ return JSON.stringify([ackTargetNodeRid, replyRelayIdentityKey(value)]);
3843
+ }
3844
+ function isServiceWireCommand(payload, command) {
3845
+ return payload.byteLength >= 5
3846
+ && payload[0] === 0x5a && payload[1] === 0x4d && payload[2] === 1
3847
+ && payload[3] === command;
3848
+ }
3849
+ function encodeHandoffQueuedMessages(backlog) {
3850
+ return backlog.map(packet => ({
3851
+ sequence: BigInt(packet.index) + 1n,
3852
+ payload: Buffer.from(JSON.stringify({
3853
+ ...packet,
3854
+ ...(packet.messageFollowOrigin === undefined ? {} : {
3855
+ messageFollowOrigin: {
3856
+ sourceNodeRid: String(packet.messageFollowOrigin.sourceNodeRid),
3857
+ sourceNodeRidHex: (0, routing_id_1.encodeRoutingIdStorageHex)(packet.messageFollowOrigin.sourceNodeRid),
3858
+ originalOperation: {
3859
+ high: packet.messageFollowOrigin.originalOperation.high.toString(),
3860
+ low: packet.messageFollowOrigin.originalOperation.low.toString()
3861
+ },
3862
+ originalReplyRouteId: packet.messageFollowOrigin.originalReplyRouteId.toString()
3863
+ }
3864
+ })
3865
+ }), 'utf8')
3866
+ }));
3867
+ }
3868
+ function decodeQueuedMessageFollowOrigin(value) {
3869
+ if (value === undefined)
3870
+ return undefined;
3871
+ if (typeof value !== 'object' || value === null) {
3872
+ throw new TypeError('Relocation Actor Message Follow origin is invalid.');
3873
+ }
3874
+ const origin = value;
3875
+ const operation = origin.originalOperation;
3876
+ if (typeof origin.sourceNodeRid !== 'string'
3877
+ || origin.sourceNodeRid.length === 0
3878
+ || typeof operation !== 'object'
3879
+ || operation === null) {
3880
+ throw new TypeError('Relocation Actor Message Follow origin is invalid.');
3881
+ }
3882
+ const operationRecord = operation;
3883
+ const high = queuedMessageU64(operationRecord.high, 'originalOperation.high');
3884
+ const low = queuedMessageU64(operationRecord.low, 'originalOperation.low');
3885
+ if (high === 0n && low === 0n) {
3886
+ throw new TypeError('Relocation Actor Message Follow operation must not be zero.');
3887
+ }
3888
+ return {
3889
+ sourceNodeRid: (0, routing_id_1.decodeRoutingId)(origin.sourceNodeRid, origin.sourceNodeRidHex),
3890
+ originalOperation: { high, low },
3891
+ originalReplyRouteId: queuedMessageU64(origin.originalReplyRouteId, 'originalReplyRouteId')
3892
+ };
3893
+ }
3894
+ function queuedMessageU64(value, field) {
3895
+ if (typeof value !== 'string' || !/^(?:0|[1-9][0-9]*)$/.test(value)) {
3896
+ throw new TypeError(`Relocation Actor Message Follow ${field} is invalid.`);
3897
+ }
3898
+ const result = BigInt(value);
3899
+ if (result > 0xffffffffffffffffn) {
3900
+ throw new TypeError(`Relocation Actor Message Follow ${field} is outside u64.`);
3901
+ }
3902
+ return result;
3903
+ }
3904
+ function toServiceTimer(value) {
3905
+ return {
3906
+ timerId: value.name,
3907
+ handlerType: value.handlerType,
3908
+ startedAtUnixMs: value.startedAtUnixMs,
3909
+ dueAtUnixMs: value.nextDueAtUnixMs,
3910
+ intervalMs: value.periodMs,
3911
+ deliveryIndex: value.deliveryIndex,
3912
+ lastScheduledIndex: value.lastScheduledIndex,
3913
+ overrunPolicy: value.overrunPolicy,
3914
+ maxCatchUpTicks: value.maxCatchUpTicks,
3915
+ stopOnUnhandledException: value.stopOnUnhandledException,
3916
+ pendingTicks: value.pendingTicks
3917
+ };
3918
+ }
3919
+ /**
3920
+ * NODE-INTERNAL Prepare sideband. Frame zero remains the exact canonical
3921
+ * command-40 schema record; each following ZLNI frame carries one sealed
3922
+ * actor-session journal keyed by its canonical participant authority key.
3923
+ * Sessionless relocation remains a single-frame, wire-identical Prepare.
3924
+ */
3925
+ function encodePrepareSideband(envelope) {
3926
+ return envelope.participants
3927
+ .filter(participant => participant.boundSessionState.byteLength !== 0)
3928
+ .map(participant => {
3929
+ const key = Buffer.from(participant.key, 'utf8');
3930
+ const payload = Buffer.from(participant.boundSessionState);
3931
+ if (key.byteLength === 0 || key.byteLength > 0xffff || payload.byteLength > 0xffff_ffff) {
3932
+ throw new TypeError('Bound-session relocation sideband is out of bounds.');
3933
+ }
3934
+ const header = Buffer.allocUnsafe(11);
3935
+ header.write('ZLNI', 0, 'ascii');
3936
+ header[4] = 1;
3937
+ header.writeUInt16BE(key.byteLength, 5);
3938
+ header.writeUInt32BE(payload.byteLength, 7);
3939
+ return Buffer.concat([header, key, payload]);
3940
+ });
3941
+ }
3942
+ function decodePrepareSideband(frames) {
3943
+ const result = [];
3944
+ const keys = new Set();
3945
+ for (const frame of frames) {
3946
+ const bytes = Buffer.from(frame);
3947
+ if (bytes.byteLength < 11 || bytes.subarray(0, 4).toString('ascii') !== 'ZLNI' || bytes[4] !== 1) {
3948
+ return undefined;
3949
+ }
3950
+ const keyLength = bytes.readUInt16BE(5);
3951
+ const payloadLength = bytes.readUInt32BE(7);
3952
+ if (11 + keyLength + payloadLength !== bytes.byteLength || keyLength === 0)
3953
+ return undefined;
3954
+ const participantKey = bytes.subarray(11, 11 + keyLength).toString('utf8');
3955
+ if (keys.has(participantKey))
3956
+ return undefined;
3957
+ keys.add(participantKey);
3958
+ result.push({ participantKey, payload: Buffer.from(bytes.subarray(11 + keyLength)) });
3959
+ }
3960
+ return result;
3961
+ }
3962
+ function attachPrepareBoundSessions(envelope, sideband) {
3963
+ if (sideband === undefined || sideband.length === 0)
3964
+ return envelope;
3965
+ const byKey = new Map(sideband.map(value => [value.participantKey, Buffer.from(value.payload)]));
3966
+ const participants = envelope.participants.map(participant => {
3967
+ const payload = byKey.get(participant.key);
3968
+ if (payload === undefined)
3969
+ return participant;
3970
+ if (participant.objectKind !== 'actor') {
3971
+ throw new TypeError('Bound-session relocation sideband names a non-Actor participant.');
3972
+ }
3973
+ byKey.delete(participant.key);
3974
+ return { ...participant, boundSessionState: payload };
3975
+ });
3976
+ if (byKey.size !== 0)
3977
+ throw new TypeError('Bound-session relocation sideband names an unknown participant.');
3978
+ return { ...envelope, participants };
3979
+ }
3980
+ function encodeActorSession(target) {
3981
+ if (target === undefined)
3982
+ return Buffer.alloc(0);
3983
+ return Buffer.from(JSON.stringify({
3984
+ version: 1,
3985
+ routerChannelId: target.routerChannelId,
3986
+ targetNodeRid: String(target.targetNodeRid),
3987
+ spotId: String(target.spotId),
3988
+ sessionNodeRid: target.sessionNodeRid === undefined ? undefined : String(target.sessionNodeRid),
3989
+ sessionRid: target.sessionRid === undefined ? undefined : String(target.sessionRid),
3990
+ bindingGeneration: target.bindingGeneration?.toString(),
3991
+ previousAuthorityOwnerGeneration: target.previousAuthorityOwnerGeneration?.toString(),
3992
+ previousOwnerLeaseGeneration: target.previousOwnerLeaseGeneration?.toString(),
3993
+ relocationSealId: target.relocationSealId,
3994
+ serviceWireRelocation: target.serviceWireRelocation === undefined
3995
+ ? undefined
3996
+ : {
3997
+ relocationHigh: target.serviceWireRelocation.relocation.high.toString(),
3998
+ relocationLow: target.serviceWireRelocation.relocation.low.toString(),
3999
+ coordinatorOwnerId: target.serviceWireRelocation.coordinator.ownerId,
4000
+ coordinatorLeaseGeneration: target.serviceWireRelocation.coordinator.leaseGeneration.toString(),
4001
+ coordinatorNodeRid: target.serviceWireRelocation.coordinator.nodeRid,
4002
+ coordinatorNodeGeneration: target.serviceWireRelocation.coordinator.nodeGeneration.toString(),
4003
+ expectedAuthorityStoreVersion: target.serviceWireRelocation.coordinator.expectedAuthorityStoreVersion,
4004
+ sessionOwnerNodeRid: target.serviceWireRelocation.session.sessionOwnerNodeRid,
4005
+ sessionOwnerNodeGeneration: target.serviceWireRelocation.session.sessionOwnerNodeGeneration.toString(),
4006
+ sessionOwnerId: target.serviceWireRelocation.session.sessionOwnerId,
4007
+ sessionOwnerLeaseGeneration: target.serviceWireRelocation.session.sessionOwnerLeaseGeneration.toString(),
4008
+ sessionRid: target.serviceWireRelocation.session.sessionRid,
4009
+ bindingGeneration: target.serviceWireRelocation.session.bindingGeneration.toString()
4010
+ }
4011
+ }), 'utf8');
4012
+ }
4013
+ function decodeActorSession(payload) {
4014
+ const value = JSON.parse(Buffer.from(payload).toString('utf8'));
4015
+ const optionalBigInt = (field) => typeof value[field] === 'string'
4016
+ ? BigInt(value[field])
4017
+ : undefined;
4018
+ if (value.version !== 1 || typeof value.routerChannelId !== 'string'
4019
+ || typeof value.targetNodeRid !== 'string' || typeof value.spotId !== 'string') {
4020
+ throw new TypeError('Actor relocation Session journal is invalid.');
4021
+ }
4022
+ const serviceWire = decodeActorSessionServiceWireFence(value.serviceWireRelocation);
4023
+ return {
4024
+ routerChannelId: value.routerChannelId,
4025
+ targetNodeRid: value.targetNodeRid,
4026
+ spotId: value.spotId,
4027
+ ...(typeof value.sessionNodeRid === 'string' ? { sessionNodeRid: value.sessionNodeRid } : {}),
4028
+ ...(typeof value.sessionRid === 'string' ? { sessionRid: value.sessionRid } : {}),
4029
+ ...(optionalBigInt('bindingGeneration') === undefined ? {} : { bindingGeneration: optionalBigInt('bindingGeneration') }),
4030
+ ...(optionalBigInt('previousAuthorityOwnerGeneration') === undefined ? {} : { previousAuthorityOwnerGeneration: optionalBigInt('previousAuthorityOwnerGeneration') }),
4031
+ ...(optionalBigInt('previousOwnerLeaseGeneration') === undefined ? {} : { previousOwnerLeaseGeneration: optionalBigInt('previousOwnerLeaseGeneration') }),
4032
+ ...(typeof value.relocationSealId === 'string' ? { relocationSealId: value.relocationSealId } : {}),
4033
+ ...(serviceWire === undefined ? {} : { serviceWireRelocation: serviceWire })
4034
+ };
4035
+ }
4036
+ function decodeActorSessionServiceWireFence(input) {
4037
+ if (input === undefined)
4038
+ return undefined;
4039
+ if (typeof input !== 'object' || input === null) {
4040
+ throw new TypeError('Actor relocation Session service-wire fence is invalid.');
4041
+ }
4042
+ const value = input;
4043
+ const text = (field) => {
4044
+ if (typeof value[field] !== 'string' || value[field].length === 0) {
4045
+ throw new TypeError(`Actor relocation Session service-wire '${field}' is invalid.`);
4046
+ }
4047
+ return value[field];
4048
+ };
4049
+ const positive = (field) => {
4050
+ const parsed = BigInt(text(field));
4051
+ if (parsed <= 0n) {
4052
+ throw new TypeError(`Actor relocation Session service-wire '${field}' is invalid.`);
4053
+ }
4054
+ return parsed;
4055
+ };
4056
+ const ordinal = (field) => {
4057
+ const parsed = BigInt(text(field));
4058
+ if (parsed < 0n) {
4059
+ throw new TypeError(`Actor relocation Session service-wire '${field}' is invalid.`);
4060
+ }
4061
+ return parsed;
4062
+ };
4063
+ const relocation = {
4064
+ high: ordinal('relocationHigh'),
4065
+ low: ordinal('relocationLow')
4066
+ };
4067
+ if (relocation.high === 0n && relocation.low === 0n) {
4068
+ throw new TypeError('Actor relocation Session service-wire identity is zero.');
4069
+ }
4070
+ return {
4071
+ relocation,
4072
+ coordinator: {
4073
+ ownerId: text('coordinatorOwnerId'),
4074
+ leaseGeneration: positive('coordinatorLeaseGeneration'),
4075
+ nodeRid: text('coordinatorNodeRid'),
4076
+ nodeGeneration: positive('coordinatorNodeGeneration'),
4077
+ expectedAuthorityStoreVersion: text('expectedAuthorityStoreVersion')
4078
+ },
4079
+ session: {
4080
+ sessionOwnerNodeRid: text('sessionOwnerNodeRid'),
4081
+ sessionOwnerNodeGeneration: positive('sessionOwnerNodeGeneration'),
4082
+ sessionOwnerId: text('sessionOwnerId'),
4083
+ sessionOwnerLeaseGeneration: positive('sessionOwnerLeaseGeneration'),
4084
+ sessionRid: text('sessionRid'),
4085
+ bindingGeneration: positive('bindingGeneration')
4086
+ }
4087
+ };
4088
+ }
4089
+ function encodeMembershipMutation(memberships, participantKey) {
4090
+ return Buffer.from(JSON.stringify(memberships.filter(value => value.actorKey === participantKey || value.spotKey === participantKey).map(value => ({
4091
+ ...value,
4092
+ spotObjectGeneration: value.spotObjectGeneration.toString(),
4093
+ membershipEpoch: value.membershipEpoch.toString()
4094
+ }))), 'utf8');
4095
+ }
4096
+ function addCapacity(left, right) {
4097
+ const spotType = left.spotType ?? right.spotType;
4098
+ if (left.spotType !== undefined && right.spotType !== undefined
4099
+ && (left.spotType.objectKind !== right.spotType.objectKind
4100
+ || left.spotType.stableType !== right.spotType.stableType)) {
4101
+ throw new Error('Relocation aggregate contains more than one Spot stable type.');
4102
+ }
4103
+ return {
4104
+ actors: left.actors + right.actors,
4105
+ spots: left.spots + right.spots,
4106
+ ...(spotType === undefined ? {} : {
4107
+ spotType: {
4108
+ ...spotType,
4109
+ count: (left.spotType?.count ?? 0) + (right.spotType?.count ?? 0)
4110
+ }
4111
+ })
4112
+ };
4113
+ }