@zlink-systems/framework 0.30.3 → 0.32.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 (398) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/contracts/Actors/ZLinkActor.d.ts +2 -0
  3. package/dist/contracts/Actors/ZLinkSessionBindingIdentity.d.ts +6 -0
  4. package/dist/contracts/Actors/ZLinkSessionBindingIdentity.js +2 -0
  5. package/dist/contracts/Actors/index.d.ts +1 -0
  6. package/dist/contracts/Actors/index.js +1 -0
  7. package/dist/contracts/Common/CoreTypes.d.ts +1 -0
  8. package/dist/contracts/Common/HandlerMessageType.d.ts +8 -0
  9. package/dist/contracts/Common/HandlerMessageType.js +41 -0
  10. package/dist/contracts/Common/ZLinkEncodedPayload.d.ts +1 -1
  11. package/dist/contracts/Common/ZLinkEncodedPayload.js +12 -20
  12. package/dist/contracts/Common/ZLinkMessage.js +11 -7
  13. package/dist/contracts/Common/encoded-payload-storage.d.ts +0 -2
  14. package/dist/contracts/Common/encoded-payload-storage.js +4 -16
  15. package/dist/contracts/Common/index.d.ts +1 -1
  16. package/dist/contracts/Common/payload-slab.d.ts +4 -0
  17. package/dist/contracts/Common/payload-slab.js +30 -0
  18. package/dist/contracts/Configuration/RegistrationBuilders.js +15 -9
  19. package/dist/contracts/Configuration/RegistrationTypes.d.ts +19 -0
  20. package/dist/contracts/Handlers/Contexts.d.ts +1 -0
  21. package/dist/contracts/Locations/Authority.d.ts +2 -0
  22. package/dist/internal.d.ts +9 -0
  23. package/dist/internal.js +23 -1
  24. package/dist/nest-integration.d.ts +1 -0
  25. package/dist/nest-integration.js +3 -1
  26. package/dist/runtime/actors/actor-client.d.ts +6 -2
  27. package/dist/runtime/actors/actor-client.js +120 -82
  28. package/dist/runtime/actors/actor-context.js +16 -5
  29. package/dist/runtime/actors/actor-execution-context.js +2 -2
  30. package/dist/runtime/actors/actor-handoff.d.ts +12 -1
  31. package/dist/runtime/actors/actor-handoff.js +79 -34
  32. package/dist/runtime/actors/actor-join-deferred-scope.js +6 -6
  33. package/dist/runtime/actors/actor-local-native-join.d.ts +2 -2
  34. package/dist/runtime/actors/actor-local-native-join.js +19 -17
  35. package/dist/runtime/actors/actor-mailbox.d.ts +1 -1
  36. package/dist/runtime/actors/actor-remote-joiner.d.ts +2 -2
  37. package/dist/runtime/actors/actor-remote-joiner.js +4 -4
  38. package/dist/runtime/actors/actor-routed-join-transport.d.ts +9 -3
  39. package/dist/runtime/actors/actor-routed-json-request.d.ts +3 -0
  40. package/dist/runtime/actors/actor-runtime-contracts.d.ts +2 -2
  41. package/dist/runtime/actors/actor-runtime-state.d.ts +1 -1
  42. package/dist/runtime/actors/spot-actor-dispatch.d.ts +9 -5
  43. package/dist/runtime/actors/spot-actor-dispatch.js +60 -38
  44. package/dist/runtime/admission.d.ts +6 -4
  45. package/dist/runtime/admission.js +21 -10
  46. package/dist/runtime/application-jobs/application-ingress-record-owner.d.ts +1 -0
  47. package/dist/runtime/application-jobs/application-ingress-record-owner.js +3 -0
  48. package/dist/runtime/backend/contracts/index.d.ts +26 -10
  49. package/dist/runtime/backend/mesh-completion-table.d.ts +7 -1
  50. package/dist/runtime/backend/mesh-completion-table.js +84 -20
  51. package/dist/runtime/backend/mesh-dispatch-pump.d.ts +19 -6
  52. package/dist/runtime/backend/mesh-dispatch-pump.js +246 -147
  53. package/dist/runtime/backend/node/node-backend-adapter-support.d.ts +3 -2
  54. package/dist/runtime/backend/node/node-backend-adapter-support.js +27 -19
  55. package/dist/runtime/backend/node/node-dealer-channel-client-transport.d.ts +5 -2
  56. package/dist/runtime/backend/node/node-dealer-channel-client-transport.js +70 -13
  57. package/dist/runtime/backend/node/node-event-loop-poller.d.ts +2 -2
  58. package/dist/runtime/backend/node/node-event-loop-poller.js +4 -3
  59. package/dist/runtime/backend/node/node-mesh-backend-adapter.js +5 -1
  60. package/dist/runtime/backend/node/node-raw-binding-port.d.ts +7 -2
  61. package/dist/runtime/backend/node/node-raw-binding-port.js +99 -63
  62. package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +34 -16
  63. package/dist/runtime/backend/node/node-raw-mesh-backend.js +210 -106
  64. package/dist/runtime/backend/node/node-socket-backend-adapter.js +20 -6
  65. package/dist/runtime/backend/raw-binding-port.d.ts +6 -3
  66. package/dist/runtime/channels/channel-clients.js +3 -3
  67. package/dist/runtime/channels/channel-dispatch-pipeline.d.ts +11 -7
  68. package/dist/runtime/channels/channel-dispatch-pipeline.js +40 -22
  69. package/dist/runtime/channels/channel-dispatch-services.d.ts +3 -1
  70. package/dist/runtime/channels/channel-dispatch-services.js +7 -6
  71. package/dist/runtime/channels/channel-dispatchers.d.ts +13 -6
  72. package/dist/runtime/channels/channel-dispatchers.js +57 -36
  73. package/dist/runtime/channels/channel-envelope.d.ts +2 -2
  74. package/dist/runtime/channels/channel-envelope.js +609 -83
  75. package/dist/runtime/channels/channel-multipart.d.ts +1 -0
  76. package/dist/runtime/channels/channel-multipart.js +10 -6
  77. package/dist/runtime/channels/channel-outbound-operations.d.ts +6 -9
  78. package/dist/runtime/channels/channel-outbound-operations.js +107 -105
  79. package/dist/runtime/channels/channel-receive-loops.d.ts +9 -7
  80. package/dist/runtime/channels/channel-receive-loops.js +126 -90
  81. package/dist/runtime/channels/channel-runtime-lifecycle.d.ts +23 -6
  82. package/dist/runtime/channels/channel-runtime-lifecycle.js +47 -38
  83. package/dist/runtime/channels/channel-runtime-manager.d.ts +13 -6
  84. package/dist/runtime/channels/channel-runtime-manager.js +32 -14
  85. package/dist/runtime/channels/channel-socket-registry.d.ts +28 -4
  86. package/dist/runtime/channels/channel-socket-registry.js +9 -1
  87. package/dist/runtime/channels/channel-transports.d.ts +23 -16
  88. package/dist/runtime/channels/channel-transports.js +139 -119
  89. package/dist/runtime/channels/dispatch-error-reporter.d.ts +4 -4
  90. package/dist/runtime/channels/dispatch-error-reporter.js +5 -5
  91. package/dist/runtime/channels/fanout-location-runtime.d.ts +1 -1
  92. package/dist/runtime/channels/local-spot-route-transport.d.ts +5 -2
  93. package/dist/runtime/channels/local-spot-route-transport.js +15 -18
  94. package/dist/runtime/channels/router-socket-spot-route-transport.d.ts +6 -3
  95. package/dist/runtime/channels/router-socket-spot-route-transport.js +33 -19
  96. package/dist/runtime/channels/source-spot-router.d.ts +6 -3
  97. package/dist/runtime/channels/source-spot-router.js +34 -23
  98. package/dist/runtime/channels/spot-node-route-transport.d.ts +6 -3
  99. package/dist/runtime/channels/spot-node-route-transport.js +23 -17
  100. package/dist/runtime/channels/spot-route-bridge-transport.d.ts +6 -3
  101. package/dist/runtime/channels/spot-route-bridge-transport.js +38 -24
  102. package/dist/runtime/channels/spot-route-dispatch-strategy.d.ts +8 -4
  103. package/dist/runtime/channels/spot-route-dispatch-strategy.js +36 -23
  104. package/dist/runtime/diagnostics/dispatch-error-details.js +9 -3
  105. package/dist/runtime/diagnostics/message-flow-bootstrap.d.ts +1 -0
  106. package/dist/runtime/diagnostics/message-flow-bootstrap.js +8 -0
  107. package/dist/runtime/diagnostics/message-flow-delivery.d.ts +47 -0
  108. package/dist/runtime/diagnostics/message-flow-delivery.js +149 -0
  109. package/dist/runtime/diagnostics/message-flow-record.d.ts +50 -0
  110. package/dist/runtime/diagnostics/message-flow-record.js +228 -0
  111. package/dist/runtime/diagnostics/message-flow-worker.d.ts +1 -0
  112. package/dist/runtime/diagnostics/message-flow-worker.js +118 -0
  113. package/dist/runtime/diagnostics/message-flow.d.ts +7 -19
  114. package/dist/runtime/diagnostics/message-flow.js +42 -290
  115. package/dist/runtime/diagnostics/runtime-metrics.d.ts +4 -3
  116. package/dist/runtime/diagnostics/runtime-metrics.js +8 -4
  117. package/dist/runtime/execution/index.d.ts +1 -0
  118. package/dist/runtime/execution/index.js +6 -3
  119. package/dist/runtime/execution/serial-execution-queue.d.ts +26 -13
  120. package/dist/runtime/execution/serial-execution-queue.js +75 -71
  121. package/dist/runtime/foundation/durable-service-request.d.ts +12 -3
  122. package/dist/runtime/foundation/durable-service-request.js +158 -73
  123. package/dist/runtime/foundation/operation-registry.d.ts +33 -3
  124. package/dist/runtime/foundation/operation-registry.js +272 -33
  125. package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +62 -23
  126. package/dist/runtime/foundation/raw-service-mesh-runtime.js +373 -194
  127. package/dist/runtime/foundation/request-runtime.d.ts +17 -0
  128. package/dist/runtime/foundation/request-runtime.js +163 -0
  129. package/dist/runtime/foundation/service-discovery-registry.d.ts +4 -0
  130. package/dist/runtime/foundation/service-discovery-registry.js +6 -0
  131. package/dist/runtime/foundation/service-liveness-registry.d.ts +1 -1
  132. package/dist/runtime/foundation/service-mailbox.d.ts +4 -2
  133. package/dist/runtime/foundation/service-mailbox.js +4 -1
  134. package/dist/runtime/foundation/service-relocation-object-owner.d.ts +2 -2
  135. package/dist/runtime/foundation/service-relocation-object-owner.js +12 -5
  136. package/dist/runtime/foundation/service-runtime-contracts.d.ts +7 -2
  137. package/dist/runtime/foundation/service-stateful-registry.d.ts +6 -2
  138. package/dist/runtime/foundation/service-stateful-registry.js +38 -17
  139. package/dist/runtime/foundation/service-stateful-runtime.d.ts +91 -26
  140. package/dist/runtime/foundation/service-stateful-runtime.js +245 -120
  141. package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +3 -0
  142. package/dist/runtime/foundation/service-stateful-wire-codec.js +15 -0
  143. package/dist/runtime/foundation/service-topology-registry.d.ts +2 -0
  144. package/dist/runtime/foundation/service-topology-registry.js +13 -3
  145. package/dist/runtime/foundation/service-wire-constants.generated.d.ts +1 -0
  146. package/dist/runtime/foundation/service-wire-constants.generated.js +12 -0
  147. package/dist/runtime/foundation/service-wire-m6a-codec.d.ts +5 -1
  148. package/dist/runtime/foundation/service-wire-m6a-codec.js +50 -15
  149. package/dist/runtime/host/actor-packet-relay.d.ts +5 -6
  150. package/dist/runtime/host/actor-packet-relay.js +58 -57
  151. package/dist/runtime/host/actor-placement-coordinator.d.ts +1 -1
  152. package/dist/runtime/host/actor-runtime-options-factory.d.ts +2 -0
  153. package/dist/runtime/host/actor-runtime-options-factory.js +3 -2
  154. package/dist/runtime/host/actor-transfer-runtime.d.ts +3 -3
  155. package/dist/runtime/host/application-job-queue.d.ts +7 -5
  156. package/dist/runtime/host/application-job-queue.js +33 -21
  157. package/dist/runtime/host/bound-session-relay.js +0 -1
  158. package/dist/runtime/host/channel-runtime-options-factory.d.ts +2 -0
  159. package/dist/runtime/host/channel-runtime-options-factory.js +1 -0
  160. package/dist/runtime/host/entry-actor-runtime.d.ts +5 -2
  161. package/dist/runtime/host/entry-actor-runtime.js +2 -2
  162. package/dist/runtime/host/index.d.ts +106 -37
  163. package/dist/runtime/host/index.js +303 -151
  164. package/dist/runtime/host/location-runtime-owner.d.ts +2 -2
  165. package/dist/runtime/host/location-runtime-owner.js +1 -1
  166. package/dist/runtime/host/service-relocation-host-runtime.d.ts +195 -45
  167. package/dist/runtime/host/service-relocation-host-runtime.js +257 -144
  168. package/dist/runtime/host/spot-address-transport.d.ts +3 -0
  169. package/dist/runtime/host/spot-address-transport.js +73 -76
  170. package/dist/runtime/host/spot-runtime-options-factory.js +2 -0
  171. package/dist/runtime/host/user-spot-creation-coordinator.d.ts +3 -1
  172. package/dist/runtime/host/user-spot-creation-coordinator.js +49 -21
  173. package/dist/runtime/internal-observation.d.ts +1 -0
  174. package/dist/runtime/internal-observation.js +5 -0
  175. package/dist/runtime/locations/actor-location-claims.d.ts +1 -1
  176. package/dist/runtime/locations/actor-location-claims.js +15 -6
  177. package/dist/runtime/locations/auto-connect-loop.d.ts +0 -1
  178. package/dist/runtime/locations/auto-connect-loop.js +25 -19
  179. package/dist/runtime/locations/auto-connect-planner.js +2 -5
  180. package/dist/runtime/locations/auto-connect-reconciler.d.ts +1 -0
  181. package/dist/runtime/locations/auto-connect-reconciler.js +35 -23
  182. package/dist/runtime/locations/in-memory-authority-store.d.ts +1 -0
  183. package/dist/runtime/locations/in-memory-authority-store.js +15 -5
  184. package/dist/runtime/locations/in-memory-location-store.d.ts +0 -2
  185. package/dist/runtime/locations/in-memory-location-store.js +1 -38
  186. package/dist/runtime/locations/lifecycle.d.ts +1 -1
  187. package/dist/runtime/locations/lifecycle.js +2 -2
  188. package/dist/runtime/locations/location-store-repository.d.ts +0 -1
  189. package/dist/runtime/locations/location-store-repository.js +163 -246
  190. package/dist/runtime/locations/resolvers.d.ts +8 -1
  191. package/dist/runtime/locations/resolvers.js +16 -2
  192. package/dist/runtime/locations/runtime.d.ts +3 -3
  193. package/dist/runtime/locations/runtime.js +12 -16
  194. package/dist/runtime/messaging/creation-payload-codec.js +8 -7
  195. package/dist/runtime/messaging/framework-json-v1.d.ts +1 -1
  196. package/dist/runtime/messaging/framework-json-v1.js +6 -2
  197. package/dist/runtime/messaging/payload-codec.js +21 -35
  198. package/dist/runtime/messaging/request-deadline.d.ts +4 -2
  199. package/dist/runtime/messaging/request-deadline.js +40 -25
  200. package/dist/runtime/messaging/request-result.d.ts +14 -1
  201. package/dist/runtime/messaging/request-result.js +74 -13
  202. package/dist/runtime/protocol/service_wire_codec.generated.d.ts +4 -0
  203. package/dist/runtime/protocol/service_wire_codec.generated.js +17 -7
  204. package/dist/runtime/spots/index.d.ts +28 -7
  205. package/dist/runtime/spots/index.js +31 -6
  206. package/dist/runtime/spots/spot-activation-registry.d.ts +3 -2
  207. package/dist/runtime/spots/spot-activation-registry.js +13 -8
  208. package/dist/runtime/spots/spot-activation-state.d.ts +2 -0
  209. package/dist/runtime/spots/spot-activation-state.js +1 -0
  210. package/dist/runtime/spots/spot-actor-admission-coordinator.d.ts +9 -4
  211. package/dist/runtime/spots/spot-actor-admission-coordinator.js +33 -12
  212. package/dist/runtime/spots/spot-actor-ingress-admission.d.ts +40 -0
  213. package/dist/runtime/spots/spot-actor-ingress-admission.js +78 -0
  214. package/dist/runtime/spots/spot-actor-membership.js +3 -3
  215. package/dist/runtime/spots/spot-actor-packet-dispatch.d.ts +16 -43
  216. package/dist/runtime/spots/spot-actor-packet-dispatch.js +56 -113
  217. package/dist/runtime/spots/spot-actor-packet-drain.d.ts +1 -0
  218. package/dist/runtime/spots/spot-actor-packet-drain.js +12 -5
  219. package/dist/runtime/spots/spot-entry-activation.d.ts +4 -3
  220. package/dist/runtime/spots/spot-entry-activation.js +7 -12
  221. package/dist/runtime/spots/spot-handler-registry.d.ts +5 -1
  222. package/dist/runtime/spots/spot-handler-registry.js +31 -15
  223. package/dist/runtime/spots/spot-manager-public.js +3 -2
  224. package/dist/runtime/spots/spot-node-runtime-manager.d.ts +11 -6
  225. package/dist/runtime/spots/spot-node-runtime-manager.js +6 -1
  226. package/dist/runtime/spots/spot-outbound.d.ts +8 -2
  227. package/dist/runtime/spots/spot-outbound.js +5 -5
  228. package/dist/runtime/spots/spot-route-packet-dispatch.js +13 -8
  229. package/dist/runtime/spots/spot-routed-spot-packet-dispatch.d.ts +3 -3
  230. package/dist/runtime/spots/spot-routed-spot-packet-dispatch.js +9 -5
  231. package/dist/runtime/spots/spot-runtime-ports.d.ts +2 -2
  232. package/dist/runtime/spots/spot-serial-executor.d.ts +2 -1
  233. package/dist/runtime/spots/spot-serial-turn-executor.js +20 -26
  234. package/dist/runtime/spots/spot-subscription-dispatch.js +5 -2
  235. package/dist/runtime/spots/spot-timer.d.ts +1 -1
  236. package/dist/runtime/streams/actor-session-binding-registry.d.ts +11 -3
  237. package/dist/runtime/streams/actor-session-binding-registry.js +28 -0
  238. package/dist/runtime/streams/bound-actor-relay-sender.d.ts +2 -2
  239. package/dist/runtime/streams/bound-actor-relay-sender.js +3 -4
  240. package/dist/runtime/streams/bound-session-service.js +6 -7
  241. package/dist/runtime/streams/index.d.ts +3 -3
  242. package/dist/runtime/streams/index.js +22 -2
  243. package/dist/runtime/streams/managed-stream.js +2 -1
  244. package/dist/runtime/streams/session-calls.d.ts +1 -1
  245. package/dist/runtime/streams/session-calls.js +3 -9
  246. package/dist/runtime/streams/session-context.d.ts +2 -2
  247. package/dist/runtime/streams/session-context.js +2 -2
  248. package/dist/runtime/streams/stream-session-runtime.d.ts +1 -0
  249. package/dist/runtime/streams/stream-session-runtime.js +64 -33
  250. package/package.json +3 -3
  251. package/src/contracts/Actors/ZLinkActor.ts +6 -0
  252. package/src/contracts/Actors/ZLinkSessionBindingIdentity.ts +7 -0
  253. package/src/contracts/Actors/index.ts +1 -0
  254. package/src/contracts/Common/CoreTypes.ts +1 -0
  255. package/src/contracts/Common/HandlerMessageType.ts +50 -0
  256. package/src/contracts/Common/ZLinkEncodedPayload.ts +13 -25
  257. package/src/contracts/Common/ZLinkMessage.ts +11 -7
  258. package/src/contracts/Common/encoded-payload-storage.ts +4 -16
  259. package/src/contracts/Common/index.ts +1 -1
  260. package/src/contracts/Common/payload-slab.ts +29 -0
  261. package/src/contracts/Configuration/RegistrationBuilders.ts +29 -15
  262. package/src/contracts/Configuration/RegistrationTypes.ts +19 -0
  263. package/src/contracts/Handlers/Contexts.ts +1 -0
  264. package/src/contracts/Locations/Authority.ts +7 -1
  265. package/src/internal.ts +17 -0
  266. package/src/nest-integration.ts +1 -0
  267. package/src/runtime/actors/actor-client.ts +257 -163
  268. package/src/runtime/actors/actor-context.ts +26 -14
  269. package/src/runtime/actors/actor-execution-context.ts +2 -2
  270. package/src/runtime/actors/actor-handoff.ts +86 -51
  271. package/src/runtime/actors/actor-join-deferred-scope.ts +6 -6
  272. package/src/runtime/actors/actor-local-native-join.ts +38 -17
  273. package/src/runtime/actors/actor-mailbox.ts +1 -1
  274. package/src/runtime/actors/actor-remote-joiner.ts +8 -4
  275. package/src/runtime/actors/actor-routed-join-transport.ts +13 -5
  276. package/src/runtime/actors/actor-routed-json-request.ts +3 -0
  277. package/src/runtime/actors/actor-runtime-contracts.ts +4 -2
  278. package/src/runtime/actors/actor-runtime-state.ts +1 -1
  279. package/src/runtime/actors/spot-actor-dispatch.ts +70 -68
  280. package/src/runtime/admission.ts +42 -15
  281. package/src/runtime/application-jobs/application-ingress-record-owner.ts +4 -0
  282. package/src/runtime/backend/contracts/index.ts +77 -10
  283. package/src/runtime/backend/mesh-completion-table.ts +106 -15
  284. package/src/runtime/backend/mesh-dispatch-pump.ts +294 -146
  285. package/src/runtime/backend/node/node-backend-adapter-support.ts +42 -32
  286. package/src/runtime/backend/node/node-dealer-channel-client-transport.ts +91 -34
  287. package/src/runtime/backend/node/node-event-loop-poller.ts +14 -5
  288. package/src/runtime/backend/node/node-mesh-backend-adapter.ts +5 -1
  289. package/src/runtime/backend/node/node-raw-binding-port.ts +180 -69
  290. package/src/runtime/backend/node/node-raw-mesh-backend.ts +386 -157
  291. package/src/runtime/backend/node/node-socket-backend-adapter.ts +56 -11
  292. package/src/runtime/backend/raw-binding-port.ts +13 -5
  293. package/src/runtime/channels/channel-clients.ts +26 -11
  294. package/src/runtime/channels/channel-dispatch-pipeline.ts +77 -65
  295. package/src/runtime/channels/channel-dispatch-services.ts +7 -12
  296. package/src/runtime/channels/channel-dispatchers.ts +93 -39
  297. package/src/runtime/channels/channel-envelope.ts +680 -144
  298. package/src/runtime/channels/channel-multipart.ts +17 -13
  299. package/src/runtime/channels/channel-outbound-operations.ts +204 -178
  300. package/src/runtime/channels/channel-receive-loops.ts +160 -107
  301. package/src/runtime/channels/channel-runtime-lifecycle.ts +64 -59
  302. package/src/runtime/channels/channel-runtime-manager.ts +74 -27
  303. package/src/runtime/channels/channel-socket-registry.ts +20 -5
  304. package/src/runtime/channels/channel-transports.ts +414 -287
  305. package/src/runtime/channels/dispatch-error-reporter.ts +4 -9
  306. package/src/runtime/channels/local-spot-route-transport.ts +27 -29
  307. package/src/runtime/channels/router-socket-spot-route-transport.ts +63 -32
  308. package/src/runtime/channels/source-spot-router.ts +75 -38
  309. package/src/runtime/channels/spot-node-route-transport.ts +67 -37
  310. package/src/runtime/channels/spot-route-bridge-transport.ts +62 -30
  311. package/src/runtime/channels/spot-route-dispatch-strategy.ts +105 -34
  312. package/src/runtime/diagnostics/dispatch-error-details.ts +10 -2
  313. package/src/runtime/diagnostics/message-flow-bootstrap.ts +6 -0
  314. package/src/runtime/diagnostics/message-flow-delivery.ts +171 -0
  315. package/src/runtime/diagnostics/message-flow-record.ts +295 -0
  316. package/src/runtime/diagnostics/message-flow-worker.ts +146 -0
  317. package/src/runtime/diagnostics/message-flow.ts +49 -362
  318. package/src/runtime/diagnostics/runtime-metrics.ts +10 -4
  319. package/src/runtime/execution/index.ts +6 -0
  320. package/src/runtime/execution/serial-execution-queue.ts +94 -96
  321. package/src/runtime/foundation/durable-service-request.ts +212 -89
  322. package/src/runtime/foundation/operation-registry.ts +287 -38
  323. package/src/runtime/foundation/raw-service-mesh-runtime.ts +617 -292
  324. package/src/runtime/foundation/request-runtime.ts +227 -0
  325. package/src/runtime/foundation/service-discovery-registry.ts +7 -0
  326. package/src/runtime/foundation/service-liveness-registry.ts +1 -1
  327. package/src/runtime/foundation/service-mailbox.ts +7 -2
  328. package/src/runtime/foundation/service-relocation-object-owner.ts +21 -6
  329. package/src/runtime/foundation/service-runtime-contracts.ts +12 -2
  330. package/src/runtime/foundation/service-stateful-registry.ts +52 -19
  331. package/src/runtime/foundation/service-stateful-runtime.ts +365 -198
  332. package/src/runtime/foundation/service-stateful-wire-codec.ts +18 -0
  333. package/src/runtime/foundation/service-topology-registry.ts +21 -3
  334. package/src/runtime/foundation/service-wire-constants.generated.ts +10 -0
  335. package/src/runtime/foundation/service-wire-m6a-codec.ts +69 -17
  336. package/src/runtime/host/actor-packet-relay.ts +160 -156
  337. package/src/runtime/host/actor-placement-coordinator.ts +1 -1
  338. package/src/runtime/host/actor-runtime-options-factory.ts +7 -2
  339. package/src/runtime/host/actor-transfer-runtime.ts +3 -3
  340. package/src/runtime/host/application-job-queue.ts +56 -27
  341. package/src/runtime/host/bound-session-relay.ts +0 -1
  342. package/src/runtime/host/channel-runtime-options-factory.ts +3 -0
  343. package/src/runtime/host/entry-actor-runtime.ts +14 -6
  344. package/src/runtime/host/index.ts +388 -113
  345. package/src/runtime/host/location-runtime-owner.ts +3 -3
  346. package/src/runtime/host/service-relocation-host-runtime.ts +380 -252
  347. package/src/runtime/host/spot-address-transport.ts +110 -95
  348. package/src/runtime/host/spot-runtime-options-factory.ts +3 -0
  349. package/src/runtime/host/user-spot-creation-coordinator.ts +69 -22
  350. package/src/runtime/internal-observation.ts +2 -0
  351. package/src/runtime/locations/actor-location-claims.ts +42 -16
  352. package/src/runtime/locations/auto-connect-loop.ts +24 -16
  353. package/src/runtime/locations/auto-connect-planner.ts +2 -5
  354. package/src/runtime/locations/auto-connect-reconciler.ts +37 -24
  355. package/src/runtime/locations/in-memory-authority-store.ts +27 -7
  356. package/src/runtime/locations/in-memory-location-store.ts +1 -74
  357. package/src/runtime/locations/lifecycle.ts +4 -2
  358. package/src/runtime/locations/location-store-repository.ts +228 -308
  359. package/src/runtime/locations/resolvers.ts +20 -8
  360. package/src/runtime/locations/runtime.ts +16 -28
  361. package/src/runtime/messaging/creation-payload-codec.ts +12 -10
  362. package/src/runtime/messaging/framework-json-v1.ts +10 -1
  363. package/src/runtime/messaging/payload-codec.ts +50 -75
  364. package/src/runtime/messaging/request-deadline.ts +47 -39
  365. package/src/runtime/messaging/request-result.ts +88 -17
  366. package/src/runtime/protocol/service_wire_codec.generated.ts +18 -8
  367. package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +1 -1
  368. package/src/runtime/spots/index.ts +57 -10
  369. package/src/runtime/spots/spot-activation-registry.ts +12 -8
  370. package/src/runtime/spots/spot-activation-state.ts +2 -0
  371. package/src/runtime/spots/spot-actor-admission-coordinator.ts +62 -37
  372. package/src/runtime/spots/spot-actor-ingress-admission.ts +157 -0
  373. package/src/runtime/spots/spot-actor-membership.ts +8 -5
  374. package/src/runtime/spots/spot-actor-packet-dispatch.ts +122 -206
  375. package/src/runtime/spots/spot-actor-packet-drain.ts +21 -6
  376. package/src/runtime/spots/spot-entry-activation.ts +25 -35
  377. package/src/runtime/spots/spot-handler-registry.ts +72 -15
  378. package/src/runtime/spots/spot-manager-public.ts +4 -2
  379. package/src/runtime/spots/spot-node-runtime-manager.ts +16 -7
  380. package/src/runtime/spots/spot-outbound.ts +26 -10
  381. package/src/runtime/spots/spot-route-packet-dispatch.ts +18 -8
  382. package/src/runtime/spots/spot-routed-spot-packet-dispatch.ts +14 -8
  383. package/src/runtime/spots/spot-runtime-ports.ts +5 -2
  384. package/src/runtime/spots/spot-serial-executor.ts +1 -1
  385. package/src/runtime/spots/spot-serial-turn-executor.ts +25 -40
  386. package/src/runtime/spots/spot-subscription-dispatch.ts +9 -2
  387. package/src/runtime/spots/spot-timer.ts +1 -1
  388. package/src/runtime/streams/actor-session-binding-registry.ts +46 -3
  389. package/src/runtime/streams/bound-actor-relay-sender.ts +16 -5
  390. package/src/runtime/streams/bound-session-service.ts +10 -7
  391. package/src/runtime/streams/index.ts +30 -4
  392. package/src/runtime/streams/managed-stream.ts +2 -1
  393. package/src/runtime/streams/session-calls.ts +9 -14
  394. package/src/runtime/streams/session-context.ts +6 -11
  395. package/src/runtime/streams/stream-session-runtime.ts +79 -40
  396. package/dist/runtime/spots/spot-lifecycle-metrics.d.ts +0 -8
  397. package/dist/runtime/spots/spot-lifecycle-metrics.js +0 -17
  398. package/src/runtime/spots/spot-lifecycle-metrics.ts +0 -16
@@ -1,7 +1,10 @@
1
+ import type { RequestRuntime } from '../foundation/request-runtime';
2
+ import type { PendingOperation } from '../foundation/operation-registry';
3
+ import { inspectRuntime } from '../internal-observation';
1
4
  import { encodeActorReply } from '../actors/actor-reply';
2
5
  import { ZLinkStreamMessageKind } from '../streams/protocol';
3
6
  import {
4
- decodeApplicationPayloadView,
7
+ decodeApplicationPayload,
5
8
  encodeMultipartApplicationPayload
6
9
  } from '../foundation/service-wire-m6a-codec';
7
10
  import {
@@ -77,6 +80,7 @@ import {
77
80
  flowIfEnabled,
78
81
  type ZLinkMessageFlowTracer
79
82
  } from '../diagnostics/message-flow';
83
+ import { currentFlowContext } from '../diagnostics/flow-context';
80
84
  import { dispatchErrorDetails } from '../diagnostics/dispatch-error-details';
81
85
  import { isStructuralGuardEnabled, trackDiagnosticCompletion } from '../execution/state-lane';
82
86
  import {
@@ -243,6 +247,7 @@ const SERVICE_CONTROL_TERMINAL_CAPACITY = 4096;
243
247
  const INITIAL_MEMBERSHIP_EPOCH = 1n;
244
248
 
245
249
  interface ZLinkHostRelocationOptions {
250
+ readonly requests: RequestRuntime;
246
251
  readonly flowCreationEnabled?: () => boolean;
247
252
  readonly messageFlow?: () => ZLinkMessageFlowTracer | undefined;
248
253
  readonly registration: ZLinkFrameworkRegistration;
@@ -272,7 +277,7 @@ interface ZLinkHostRelocationOptions {
272
277
  clear?(): void | Promise<void>;
273
278
  };
274
279
  readonly trackInstanceSpot?: (input: ZLinkTrackedInstanceAuthority) => void;
275
- readonly invalidateActorRoute?: (actorId: string) => void;
280
+ readonly observeActorAuthorityVersion?: (actorId: string, storeVersion: string) => void;
276
281
  readonly reconcileStatefulAuthorityRoutes?: (signal?: AbortSignal) => Promise<void>;
277
282
  readonly runtimeEventPublisher?: ZLinkRuntimeEventPublisher;
278
283
  readonly metrics?: ZLinkRuntimeMetrics;
@@ -414,13 +419,32 @@ interface TerminalSessionRelocationControl {
414
419
 
415
420
  /** Production host bridge from Retire inventory to remote RouteMesh owners. */
416
421
  export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocation {
417
- private readonly targetStages = new Map<string, LocalStage>();
422
+ [inspectRuntime]() {
423
+ const sourceWindow = this.sourceCutoverWindows.values().next().value;
424
+ return Object.freeze({
425
+ targetStages: this.targetStages.size,
426
+ targetAssemblies: this.targetAssemblies.size,
427
+ pendingReplyRelays: this.pendingReplyRelays.size,
428
+ sourceActorJoinProfiles: this.sourceActorJoinProfiles.size,
429
+ sourceCutoverWindow:
430
+ sourceWindow === undefined
431
+ ? undefined
432
+ : Object.freeze({
433
+ get frameCount() {
434
+ return sourceWindow.frames?.length;
435
+ }
436
+ }),
437
+ terminalTargets: [...this.terminalTargets].length
438
+ });
439
+ }
440
+
441
+ readonly targetStages = new Map<string, LocalStage>();
418
442
  private readonly terminalTargets = new BoundedReplayMap<string, string>(
419
443
  RELOCATION_TARGET_TOMBSTONE_LIMIT
420
444
  );
421
- private readonly targetPrepareOperations = new Map<string, TargetPrepareOperation>();
445
+ readonly targetPrepareOperations = new Map<string, TargetPrepareOperation>();
422
446
  private readonly pendingReplyRelays = new Map<string, PendingRelocationReplyRelay>();
423
- private readonly pendingSessionRelocations = new Map<string, PendingSessionRelocation>();
447
+ readonly pendingSessionRelocations = new Map<string, PendingSessionRelocation>();
424
448
  private readonly terminalSessionRelocations = new BoundedReplayMap<
425
449
  string,
426
450
  TerminalSessionRelocationControl
@@ -434,7 +458,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
434
458
  SERVICE_CONTROL_TERMINAL_CAPACITY
435
459
  );
436
460
  private readonly sourceRelocationIds = new Set<string>();
437
- private readonly targetAssemblies = new Map<string, TargetPayloadAssembly>();
461
+ readonly targetAssemblies = new Map<string, TargetPayloadAssembly>();
438
462
  /**
439
463
  * Terminal restore failures (assembly/checksum/factory/restore error): the
440
464
  * target already sent relocationFailed (command 53) once. An exact-identity
@@ -461,7 +485,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
461
485
  private readonly terminalActorJoinSourceLeaves = new BoundedReplayMap<string, string>(
462
486
  SERVICE_CONTROL_TERMINAL_CAPACITY
463
487
  );
464
- private readonly codec = new ServiceRelocationAuthorityPayloadCodec();
488
+ readonly codec = new ServiceRelocationAuthorityPayloadCodec();
465
489
  /**
466
490
  * Set once dispose() starts tearing assemblies down. A payload() rejection
467
491
  * observed after this point is the shutdown itself, not a chunk-assembly or
@@ -470,7 +494,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
470
494
  private disposed = false;
471
495
  private readonly targetPreparationStop = new AbortController();
472
496
 
473
- constructor(private readonly options: ZLinkHostRelocationOptions) {}
497
+ constructor(readonly options: ZLinkHostRelocationOptions) {}
474
498
 
475
499
  async relocateActorJoin(
476
500
  input: Parameters<ZLinkActorJoinRelocation['relocateActorJoin']>[0]
@@ -1106,7 +1130,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
1106
1130
  }
1107
1131
 
1108
1132
  /** Sends the Ready reply once the async restore finished; failures replay on resend. */
1109
- private async deliverTargetReady(
1133
+ async deliverTargetReady(
1110
1134
  meshName: string,
1111
1135
  operationKey: string,
1112
1136
  request: ServiceMaintenanceRelocationPrepare,
@@ -1658,7 +1682,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
1658
1682
  }
1659
1683
  }
1660
1684
 
1661
- private async relocateSpotAggregate(
1685
+ async relocateSpotAggregate(
1662
1686
  meshName: string,
1663
1687
  activation: ZLinkSpotActivation,
1664
1688
  kind: 'user_spot' | 'instance_spot',
@@ -1861,8 +1885,9 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
1861
1885
  ? failures[0]
1862
1886
  : new AggregateError(failures, 'Spot source retirement failed.');
1863
1887
  },
1864
- abortSeal: async () => {
1888
+ abortSeal: async (onCleanupError) => {
1865
1889
  const failures: unknown[] = [];
1890
+ const cleanupFailures: unknown[] = [];
1866
1891
  if (spotCapture !== undefined) {
1867
1892
  // Spot model §5.1: Continued completes while the source seal still holds jobs.
1868
1893
  if (readinessBoundaryConsumed) {
@@ -1871,11 +1896,13 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
1871
1896
  ZLinkSpotRelocationReadyOutcome.Continued
1872
1897
  );
1873
1898
  } catch (error) {
1874
- failures.push(error);
1899
+ cleanupFailures.push(error);
1875
1900
  }
1876
1901
  }
1877
1902
  try {
1878
- activation.abortRelocation(spotCapture);
1903
+ if (!activation.abortRelocation(spotCapture)) {
1904
+ throw new Error(`Spot '${String(activation.spotId)}' relocation seal became stale.`);
1905
+ }
1879
1906
  } catch (error) {
1880
1907
  failures.push(error);
1881
1908
  }
@@ -1888,7 +1915,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
1888
1915
  throw new Error('Spot Message Follow abort fence became stale.');
1889
1916
  }
1890
1917
  } catch (error) {
1891
- failures.push(error);
1918
+ cleanupFailures.push(error);
1892
1919
  }
1893
1920
  }
1894
1921
  for (const session of [...sessions].reverse()) {
@@ -1899,7 +1926,18 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
1899
1926
  }
1900
1927
  }
1901
1928
  if (failures.length !== 0) {
1902
- throw new AggregateError(failures, 'Spot relocation source rollback was incomplete.');
1929
+ throw new AggregateError(
1930
+ [...failures, ...cleanupFailures],
1931
+ 'Spot relocation source rollback was incomplete.'
1932
+ );
1933
+ }
1934
+ if (cleanupFailures.length !== 0) {
1935
+ const cleanup = new AggregateError(
1936
+ cleanupFailures,
1937
+ 'Spot relocation source rollback was incomplete.'
1938
+ );
1939
+ if (onCleanupError === undefined) throw cleanup;
1940
+ onCleanupError(cleanup);
1903
1941
  }
1904
1942
  }
1905
1943
  };
@@ -1925,7 +1963,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
1925
1963
  const relocationMetric =
1926
1964
  spotRegistration.relocation.kind === 'disabled'
1927
1965
  ? undefined
1928
- : this.options.metrics?.startRelocation(meshName, kind, spotRegistration.relocation.kind);
1966
+ : this.startSourceRelocationMetric(meshName, kind, spotRegistration.relocation.kind);
1929
1967
  try {
1930
1968
  const waitForRelocationBoundary = (
1931
1969
  activation as unknown as {
@@ -2004,7 +2042,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
2004
2042
  }
2005
2043
  }
2006
2044
 
2007
- private async relocateStandaloneActor(
2045
+ async relocateStandaloneActor(
2008
2046
  meshName: string,
2009
2047
  state: ZLinkActorRuntimeState,
2010
2048
  target: ZLinkMeshNodeDescriptor | undefined,
@@ -2078,7 +2116,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
2078
2116
  const relocationMetric =
2079
2117
  actorPolicy === 'disabled'
2080
2118
  ? undefined
2081
- : this.options.metrics?.startRelocation(meshName, 'actor', actorPolicy);
2119
+ : this.startSourceRelocationMetric(meshName, 'actor', actorPolicy, state.actorId);
2082
2120
  try {
2083
2121
  if (isRelocationDebugEnabled()) {
2084
2122
  relocationDebug('standalone_actor.wait_budget', {
@@ -2121,7 +2159,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
2121
2159
  }
2122
2160
  }
2123
2161
 
2124
- private async relocatePerActorSpotShell(
2162
+ async relocatePerActorSpotShell(
2125
2163
  meshName: string,
2126
2164
  activation: ZLinkSpotActivation,
2127
2165
  target: ZLinkMeshNodeDescriptor | undefined,
@@ -2216,13 +2254,22 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
2216
2254
  }
2217
2255
  await this.requireSpotManager().completeRelocationSource(activation);
2218
2256
  },
2219
- abortSeal: async () => {
2220
- if (spotCapture !== undefined) activation.abortRelocation(spotCapture);
2257
+ abortSeal: async (onCleanupError) => {
2258
+ if (spotCapture !== undefined && !activation.abortRelocation(spotCapture)) {
2259
+ throw new Error(
2260
+ `PerActor Spot '${String(activation.spotId)}' relocation seal became stale.`
2261
+ );
2262
+ }
2221
2263
  if (spotMessageFollowSeal !== undefined) {
2222
- const node = this.requireMeshNode(meshName);
2223
- const abort = node.abortSpotMessageFollowIngress;
2224
- if (abort === undefined || !abort.call(node, spotMessageFollowSeal)) {
2225
- throw new Error('Spot Message Follow abort fence became stale.');
2264
+ try {
2265
+ const node = this.requireMeshNode(meshName);
2266
+ const abort = node.abortSpotMessageFollowIngress;
2267
+ if (abort === undefined || !abort.call(node, spotMessageFollowSeal)) {
2268
+ throw new Error('Spot Message Follow abort fence became stale.');
2269
+ }
2270
+ } catch (error) {
2271
+ if (onCleanupError === undefined) throw error;
2272
+ onCleanupError(error);
2226
2273
  }
2227
2274
  }
2228
2275
  }
@@ -2231,11 +2278,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
2231
2278
  const relocationMetric =
2232
2279
  spotRegistration.relocation.kind === 'disabled'
2233
2280
  ? undefined
2234
- : this.options.metrics?.startRelocation(
2235
- meshName,
2236
- 'user_spot',
2237
- spotRegistration.relocation.kind
2238
- );
2281
+ : this.startSourceRelocationMetric(meshName, 'user_spot', spotRegistration.relocation.kind);
2239
2282
  try {
2240
2283
  await this.waitForRelocationBudgetHeadroom(String(target.rid), signal);
2241
2284
  const captured = await new ServiceRelocationObjectCaptureOwner().captureUserSpotAggregate(
@@ -2427,7 +2470,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
2427
2470
  this.sourceRelocationIds.add(id);
2428
2471
  }
2429
2472
 
2430
- private async runCoordinator(
2473
+ async runCoordinator(
2431
2474
  meshName: string,
2432
2475
  target: ZLinkMeshNodeDescriptor,
2433
2476
  primary: ZLinkAuthoritySnapshot,
@@ -2497,159 +2540,192 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
2497
2540
  advertisedReceiveChunkLimitBytes
2498
2541
  );
2499
2542
  const plan = planRelocationChunks(encoded, chunkLimitBytes);
2500
- // The Restore absolute deadline is this unit's relocation deadline: the
2501
- // caller's signal, or the control deadline without one. From it the
2502
- // source settles the authority with its Preserve fence (Location runtime
2503
- // §10). The target keeps no deadline of its own.
2504
- const restoreDeadlineReached = () =>
2505
- signal?.aborted === true || performance.now() >= controlDeadlineAtMs;
2506
- let readyReceived = false;
2543
+ // The unit's original Restore absolute deadline authorizes the source
2544
+ // Preserve fence (Location runtime §10). Caller cancellation cannot
2545
+ // advance that deadline. The target keeps no deadline of its own.
2546
+ const restoreDeadlineReached = () => performance.now() >= controlDeadlineAtMs;
2507
2547
  let settlement:
2508
- Awaited<ReturnType<ZLinkHostServiceRelocationRuntime['settleSourceAuthority']>> | undefined;
2548
+ Awaited<ReturnType<ZLinkHostServiceRelocationRuntime['settleSourceAuthority']>> | undefined =
2549
+ 'source' as
2550
+ Awaited<ReturnType<ZLinkHostServiceRelocationRuntime['settleSourceAuthority']>> | undefined;
2551
+ let failure: { readonly error: unknown } | undefined;
2552
+ let window: SourceCutoverWindow | undefined;
2509
2553
  try {
2510
- const prepare = {
2511
- kind: 'prepare',
2512
- relocation,
2513
- targetAttemptGeneration,
2514
- coordinator,
2515
- target: targetFence,
2516
- initiatorRole: 'source',
2517
- object,
2518
- sourceNodeRid: coordinator.nodeRid,
2519
- sourceNodeGeneration: coordinator.nodeGeneration,
2520
- payloadTotalLength: BigInt(plan.totalLength),
2521
- payloadChunkCount: plan.chunkCount,
2522
- payloadChecksumCrc32c: plan.checksumCrc32c,
2523
- applicationVersion: target.applicationVersion,
2524
- deadlineUnixMs: BigInt(
2525
- Date.now() + Math.max(0, Math.ceil(controlDeadlineAtMs - performance.now()))
2526
- )
2527
- } satisfies ServiceMaintenanceRelocationPrepare;
2528
- // Start the Restore request first (it also registers the temporary
2529
- // queue and the assembly on the target), then stream the payload chunks
2530
- // on the same ordered connection. The Ready reply arrives only after
2531
- // the target assembled, verified, and restored the payload.
2532
- const ready = await this.sendControl(
2533
- meshName,
2534
- target.rid,
2535
- prepare,
2536
- signal,
2537
- controlDeadlineAtMs,
2538
- async (attemptSignal) => {
2539
- if (isRelocationDebugEnabled())
2540
- relocationDebug('coordinator.state_transfer_begin', {
2541
- aggregateId: captured.envelope.aggregateId
2542
- });
2543
- await this.sendRelocationStateChunks(
2544
- meshName,
2545
- target,
2546
- prepare,
2547
- encoded,
2548
- plan,
2549
- attemptSignal
2554
+ try {
2555
+ const prepare = {
2556
+ kind: 'prepare',
2557
+ relocation,
2558
+ targetAttemptGeneration,
2559
+ coordinator,
2560
+ target: targetFence,
2561
+ initiatorRole: 'source',
2562
+ object,
2563
+ sourceNodeRid: coordinator.nodeRid,
2564
+ sourceNodeGeneration: coordinator.nodeGeneration,
2565
+ payloadTotalLength: BigInt(plan.totalLength),
2566
+ payloadChunkCount: plan.chunkCount,
2567
+ payloadChecksumCrc32c: plan.checksumCrc32c,
2568
+ applicationVersion: target.applicationVersion,
2569
+ deadlineUnixMs: BigInt(
2570
+ Date.now() + Math.max(0, Math.ceil(controlDeadlineAtMs - performance.now()))
2571
+ )
2572
+ } satisfies ServiceMaintenanceRelocationPrepare;
2573
+ // Start the Restore request first (it also registers the temporary
2574
+ // queue and the assembly on the target), then stream the payload chunks
2575
+ // on the same ordered connection. The Ready reply arrives only after
2576
+ // the target assembled, verified, and restored the payload.
2577
+ const ready = await this.sendControl(
2578
+ meshName,
2579
+ target.rid,
2580
+ prepare,
2581
+ signal,
2582
+ controlDeadlineAtMs,
2583
+ async (attemptSignal) => {
2584
+ settlement = undefined;
2585
+ if (isRelocationDebugEnabled())
2586
+ relocationDebug('coordinator.state_transfer_begin', {
2587
+ aggregateId: captured.envelope.aggregateId
2588
+ });
2589
+ await this.sendRelocationStateChunks(
2590
+ meshName,
2591
+ target,
2592
+ prepare,
2593
+ encoded,
2594
+ plan,
2595
+ attemptSignal
2596
+ );
2597
+ if (isRelocationDebugEnabled())
2598
+ relocationDebug('coordinator.await_ready', {
2599
+ aggregateId: captured.envelope.aggregateId
2600
+ });
2601
+ }
2602
+ );
2603
+ if (ready.kind === 'failed') {
2604
+ settlement = 'source';
2605
+ throw relocationFailureException(ready);
2606
+ }
2607
+ validateControlResponse(prepare, ready);
2608
+ if (isRelocationDebugEnabled()) {
2609
+ relocationDebug('coordinator.ready_received', {
2610
+ aggregateId: captured.envelope.aggregateId
2611
+ });
2612
+ }
2613
+ actorJoinProfile?.relayReady();
2614
+
2615
+ const boundaryBatch: Array<{
2616
+ readonly frame: Buffer;
2617
+ readonly canonicalBytes: Buffer;
2618
+ }> = [];
2619
+ for (const session of sessions) {
2620
+ const participant = captured.envelope.participants.find(
2621
+ (value) =>
2622
+ value.objectKind === 'actor' &&
2623
+ decodeAuthorityKey({ value: value.key } as ZLinkAuthorityKey).globalId ===
2624
+ session.state.actorId
2550
2625
  );
2551
- if (isRelocationDebugEnabled())
2552
- relocationDebug('coordinator.await_ready', {
2553
- aggregateId: captured.envelope.aggregateId
2626
+ if (participant === undefined) {
2627
+ throw new Error(
2628
+ `Relocation Actor '${session.state.actorId}' is missing from its envelope.`
2629
+ );
2630
+ }
2631
+ for (const packet of session.prepared.takeRelocationRelay()) {
2632
+ const frozenRecord = canonicalRelayFrozenRecord(
2633
+ participant,
2634
+ packet,
2635
+ coordinator,
2636
+ targetFence
2637
+ );
2638
+ const data = {
2639
+ kind: 'data',
2640
+ relocation,
2641
+ targetAttemptGeneration,
2642
+ coordinator,
2643
+ senderRole: 'source',
2644
+ object: relocationObjectForParticipant(participant),
2645
+ frozenRecord
2646
+ } satisfies Extract<ServiceMaintenanceRelocationControl, { kind: 'data' }>;
2647
+ boundaryBatch.push({
2648
+ frame: encodeServiceRelocationControlRequest(data),
2649
+ canonicalBytes: frozenRecord.canonicalBytes
2554
2650
  });
2651
+ }
2555
2652
  }
2556
- );
2557
- if (isRelocationDebugEnabled()) {
2558
- relocationDebug('coordinator.ready_received', {
2559
- aggregateId: captured.envelope.aggregateId
2653
+ const cutoverFrame = encodeServiceRelocationControlRequest({
2654
+ kind: 'cutover',
2655
+ relocation,
2656
+ targetAttemptGeneration,
2657
+ coordinator,
2658
+ senderRole: 'source',
2659
+ object,
2660
+ boundaryRecordCount: BigInt(boundaryBatch.length),
2661
+ boundaryChecksumCrc32c: crc32c(
2662
+ Buffer.concat(boundaryBatch.map((value) => value.canonicalBytes))
2663
+ )
2560
2664
  });
2561
- }
2562
- validateControlResponse(prepare, ready);
2563
- // Ready arms the target's cutover-wait fallback. From this point
2564
- // forward the source can no longer reopen dispatch without risking two
2565
- // owners.
2566
- readyReceived = true;
2567
- actorJoinProfile?.relayReady();
2568
-
2569
- const boundaryBatch: Array<{
2570
- readonly frame: Buffer;
2571
- readonly canonicalBytes: Buffer;
2572
- }> = [];
2573
- for (const session of sessions) {
2574
- const participant = captured.envelope.participants.find(
2575
- (value) =>
2576
- value.objectKind === 'actor' &&
2577
- decodeAuthorityKey({ value: value.key } as ZLinkAuthorityKey).globalId ===
2578
- session.state.actorId
2579
- );
2580
- if (participant === undefined) {
2581
- throw new Error(
2582
- `Relocation Actor '${session.state.actorId}' is missing from its envelope.`
2583
- );
2584
- }
2585
- for (const packet of session.prepared.takeRelocationRelay()) {
2586
- const frozenRecord = canonicalRelayFrozenRecord(
2587
- participant,
2588
- packet,
2589
- coordinator,
2590
- targetFence
2591
- );
2592
- const data = {
2593
- kind: 'data',
2594
- relocation,
2595
- targetAttemptGeneration,
2596
- coordinator,
2597
- senderRole: 'source',
2598
- object: relocationObjectForParticipant(participant),
2599
- frozenRecord
2600
- } satisfies Extract<ServiceMaintenanceRelocationControl, { kind: 'data' }>;
2601
- boundaryBatch.push({
2602
- frame: encodeServiceRelocationControlRequest(data),
2603
- canonicalBytes: frozenRecord.canonicalBytes
2604
- });
2665
+ // The cutover submit result is not the authority result. The memory
2666
+ // copy of the boundary batch and cutover stays until the authority
2667
+ // settlement below (spec 28 §4.4).
2668
+ const submittedRouteGeneration = this.requireMeshNode(meshName).observePeerRoute?.(
2669
+ target.rid
2670
+ ).generation;
2671
+ try {
2672
+ for (const record of boundaryBatch) {
2673
+ await this.submitControlFrame(meshName, target.rid, record.frame, 'relay');
2674
+ }
2675
+ await this.submitControlFrame(meshName, target.rid, cutoverFrame, 'cutover');
2676
+ } catch (error) {
2677
+ if (!durableRequestCanReplay(error)) throw error;
2678
+ console.warn('[zlink.runtime.relocation.cutover_submit_failed]', relayAuthorityId, error);
2605
2679
  }
2680
+ window = this.beginSourceCutoverWindow(
2681
+ meshName,
2682
+ target.rid,
2683
+ relayAuthorityId,
2684
+ [...boundaryBatch.map((value) => value.frame), cutoverFrame],
2685
+ submittedRouteGeneration,
2686
+ limits
2687
+ );
2688
+ } catch (error) {
2689
+ failure = { error };
2606
2690
  }
2607
- const cutoverFrame = encodeServiceRelocationControlRequest({
2608
- kind: 'cutover',
2609
- relocation,
2610
- targetAttemptGeneration,
2611
- coordinator,
2612
- senderRole: 'source',
2613
- object,
2614
- boundaryRecordCount: BigInt(boundaryBatch.length),
2615
- boundaryChecksumCrc32c: crc32c(
2616
- Buffer.concat(boundaryBatch.map((value) => value.canonicalBytes))
2617
- )
2618
- });
2619
- // The cutover submit result is not the authority result. The memory
2620
- // copy of the boundary batch and cutover stays until the authority
2621
- // settlement below (spec 28 §4.4).
2622
- const submittedRouteGeneration = this.requireMeshNode(meshName).observePeerRoute?.(
2623
- target.rid
2624
- ).generation;
2625
2691
  try {
2626
- for (const record of boundaryBatch) {
2627
- await this.submitControlFrame(meshName, target.rid, record.frame, 'relay');
2692
+ try {
2693
+ if (settlement === undefined) {
2694
+ settlement = await this.settleSourceAuthority(
2695
+ captured.envelope,
2696
+ primary,
2697
+ targetFence,
2698
+ restoreDeadlineReached,
2699
+ window,
2700
+ relocationMetric
2701
+ );
2702
+ } else if (failure !== undefined) {
2703
+ // Restoration without authority settlement did not confirm Preserve.
2704
+ throw failure.error;
2705
+ }
2706
+ } finally {
2707
+ if (settlement === 'source') {
2708
+ // Source restoration is authorized: captured queue, timers and held records
2709
+ // return in their accepted order, and source dispatch reopens.
2710
+ try {
2711
+ await captured.abortSource((error) => {
2712
+ failure ??= { error };
2713
+ });
2714
+ } catch (error) {
2715
+ throw failure === undefined ? error : failure.error;
2716
+ }
2717
+ }
2628
2718
  }
2629
- await this.submitControlFrame(meshName, target.rid, cutoverFrame, 'cutover');
2719
+ this.completeSourceRelocationMetric(relocationMetric, settlement);
2630
2720
  } catch (error) {
2631
- if (!durableRequestCanReplay(error)) throw error;
2632
- console.warn('[zlink.runtime.relocation.cutover_submit_failed]', relayAuthorityId, error);
2633
- }
2634
- const window = this.beginSourceCutoverWindow(
2635
- meshName,
2636
- target.rid,
2637
- relayAuthorityId,
2638
- [...boundaryBatch.map((value) => value.frame), cutoverFrame],
2639
- submittedRouteGeneration,
2640
- limits
2641
- );
2642
- try {
2643
- settlement = await this.settleSourceAuthority(
2644
- captured.envelope,
2645
- primary,
2646
- targetFence,
2647
- restoreDeadlineReached,
2648
- window,
2649
- relocationMetric
2650
- );
2721
+ failure = { error };
2722
+ throw error;
2651
2723
  } finally {
2652
- this.closeSourceCutoverWindow(relayAuthorityId, window);
2724
+ try {
2725
+ if (window !== undefined) this.closeSourceCutoverWindow(relayAuthorityId, window);
2726
+ } catch (error) {
2727
+ throw failure === undefined ? error : failure.error;
2728
+ }
2653
2729
  }
2654
2730
  if (isRelocationDebugEnabled()) {
2655
2731
  relocationDebug('coordinator.authority_settled', {
@@ -2658,16 +2734,12 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
2658
2734
  });
2659
2735
  }
2660
2736
  if (settlement === 'source') {
2661
- // Preserve won: the captured queue, timers and held records return to
2662
- // the source queue in their accepted order, and dispatch reopens.
2663
- await captured.abortSource();
2664
- this.completeSourceRelocationMetric(relocationMetric, settlement);
2737
+ if (failure !== undefined) throw failure.error;
2665
2738
  throw new Error(
2666
2739
  `Relocation '${relayAuthorityId}' ended by the source Preserve fence; the source kept the authority.`
2667
2740
  );
2668
2741
  }
2669
2742
  if (settlement === 'lost') {
2670
- this.completeSourceRelocationMetric(relocationMetric, settlement);
2671
2743
  // Expired owner: dispatch and Store changes stop for good and every
2672
2744
  // pending request without a terminal gets one Unavailable.
2673
2745
  const unavailable = createInternalFrameworkException(
@@ -2678,10 +2750,10 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
2678
2750
  await captured.discardSource(unavailable);
2679
2751
  throw new ServiceRelocationAuthorityError(unavailable.message, { cause: unavailable });
2680
2752
  }
2681
- this.completeSourceRelocationMetric(relocationMetric, settlement);
2682
2753
  for (const session of sessions) session.prepared.setReplayResults([]);
2683
2754
  await captured.commitSource(settlement.followAuthorities);
2684
2755
  await this.options.reconcileStatefulAuthorityRoutes?.(signal);
2756
+ if (failure !== undefined) throw failure.error;
2685
2757
  } catch (error) {
2686
2758
  if (
2687
2759
  this.disposed &&
@@ -2706,11 +2778,6 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
2706
2778
  );
2707
2779
  } finally {
2708
2780
  this.completeSourceRelocationMetric(relocationMetric);
2709
- if (!readyReceived) {
2710
- // Only an explicit failure before the Ready reply becomes accepted
2711
- // restores the source from the memory payload (spec 28 §9).
2712
- await captured.abortSource().catch(() => undefined);
2713
- }
2714
2781
  }
2715
2782
  }
2716
2783
 
@@ -2732,6 +2799,50 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
2732
2799
  );
2733
2800
  }
2734
2801
 
2802
+ startSourceRelocationMetric(
2803
+ meshName: string,
2804
+ objectKind: 'actor' | 'user_spot' | 'instance_spot',
2805
+ policy: 'recreate' | 'snapshot',
2806
+ actorId?: string
2807
+ ): ZLinkRelocationMetricOperation | undefined {
2808
+ const flow = objectKind === 'actor' ? this.options.messageFlow?.() : undefined;
2809
+ const flowContext = flow?.flowCreationEnabled() === true ? currentFlowContext() : undefined;
2810
+ const traceTerminal = (outcome: string): void => {
2811
+ if (flow === undefined || flowContext === undefined) return;
2812
+ const result =
2813
+ outcome === 'completed' ? 'succeeded' : outcome === 'shutdown' ? 'shutdown' : 'failed';
2814
+ flowIfEnabled(flow, ZLinkMessageFlowOutcome.Completed, result, flowContext.flowId)?.trace({
2815
+ outcome: ZLinkMessageFlowOutcome.Completed,
2816
+ result,
2817
+ surface: ZLinkDispatchErrorSurface.ActorRelocation,
2818
+ messageKind: ZLinkDispatchMessageKind.Control,
2819
+ meshName,
2820
+ actorId,
2821
+ flowId: flowContext.flowId,
2822
+ flowOrigin: flowContext.flowOrigin,
2823
+ errorMessage: result === 'failed' ? `source_relocation_${outcome}` : undefined
2824
+ });
2825
+ };
2826
+ const metric = this.options.metrics?.startRelocation(
2827
+ meshName,
2828
+ objectKind,
2829
+ policy,
2830
+ traceTerminal
2831
+ );
2832
+ if (metric !== undefined) return metric;
2833
+ if (flow === undefined || flowContext === undefined) return undefined;
2834
+
2835
+ let completed = false;
2836
+ return {
2837
+ recordBytes: (): void => {},
2838
+ complete: (outcome: string): void => {
2839
+ if (completed) return;
2840
+ completed = true;
2841
+ traceTerminal(outcome);
2842
+ }
2843
+ };
2844
+ }
2845
+
2735
2846
  /** Streams the payload chunks of one stage under the effective in-flight budgets. */
2736
2847
  private async sendRelocationStateChunks(
2737
2848
  meshName: string,
@@ -2794,10 +2905,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
2794
2905
  }
2795
2906
 
2796
2907
  /** Pre-seal admission wait — a full budget delays the next unit before seal. */
2797
- private async waitForRelocationBudgetHeadroom(
2798
- targetRid: string,
2799
- signal?: AbortSignal
2800
- ): Promise<void> {
2908
+ async waitForRelocationBudgetHeadroom(targetRid: string, signal?: AbortSignal): Promise<void> {
2801
2909
  await this.requireNodePayloadBudget().waitForHeadroom(signal);
2802
2910
  await this.requirePeerPayloadBudget(targetRid).waitForHeadroom(signal);
2803
2911
  }
@@ -2884,7 +2992,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
2884
2992
  }
2885
2993
 
2886
2994
  /** Relocation flow §4.4: replay the whole batch on a different ready route. */
2887
- private async resendSourceCutover(window: SourceCutoverWindow): Promise<void> {
2995
+ async resendSourceCutover(window: SourceCutoverWindow): Promise<void> {
2888
2996
  const frames = window.frames;
2889
2997
  if (frames === undefined) return;
2890
2998
  const route = this.requireMeshNode(window.meshName).observePeerRoute?.(window.targetNodeRid);
@@ -2905,7 +3013,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
2905
3013
  }
2906
3014
 
2907
3015
  /**
2908
- * The one source authority settlement after Ready (Location runtime
3016
+ * The one source authority settlement after request creation (Location runtime
2909
3017
  * §6.1·§10, spec 28 §4.4). It reads the Store until the target commit or
2910
3018
  * the Restore deadline. From the Restore deadline it runs the source
2911
3019
  * Preserve fence: a CAS on the StoreVersion expected by target NewOwner
@@ -2916,12 +3024,12 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
2916
3024
  * A committed later owner has no Follow snapshot (Location runtime §10). An uncertain
2917
3025
  * Store or lease result keeps the work retained and repeats the same decision.
2918
3026
  */
2919
- private async settleSourceAuthority(
3027
+ async settleSourceAuthority(
2920
3028
  envelope: ServiceRelocationEnvelope,
2921
3029
  primary: ZLinkAuthoritySnapshot,
2922
3030
  target: ServiceWireRelocationTarget,
2923
3031
  restoreDeadlineReached: () => boolean,
2924
- window: SourceCutoverWindow,
3032
+ window: SourceCutoverWindow | undefined,
2925
3033
  relocationMetric?: ZLinkRelocationMetricOperation
2926
3034
  ): Promise<SourceAuthorityCommit | 'source' | 'lost'> {
2927
3035
  const owner = { ownerId: primary.ownerId, leaseGeneration: primary.ownerLeaseGeneration };
@@ -2931,7 +3039,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
2931
3039
  this.completeSourceRelocationMetric(relocationMetric, undefined, true);
2932
3040
  throw new ServiceRelocationRuntimeStoppedError();
2933
3041
  }
2934
- await this.resendSourceCutover(window);
3042
+ if (window !== undefined) await this.resendSourceCutover(window);
2935
3043
  const observed = await this.readSourceSettlement(envelope, primary, target).catch(
2936
3044
  (error: unknown) => {
2937
3045
  if (!isIndeterminateLocationStoreFailure(error)) throw error;
@@ -3028,7 +3136,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
3028
3136
  return this.sourceCutoverWindows.size === 0;
3029
3137
  }
3030
3138
 
3031
- private async releaseParticipantAuthorities(
3139
+ async releaseParticipantAuthorities(
3032
3140
  envelope: ServiceRelocationEnvelope,
3033
3141
  primaryKey: string,
3034
3142
  signal?: AbortSignal
@@ -3052,11 +3160,17 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
3052
3160
  if (result.kind !== 'stored') {
3053
3161
  throw new Error(`Participant '${participant.key}' recovery pointer release failed.`);
3054
3162
  }
3163
+ if (participant.objectKind === 'actor') {
3164
+ this.options.observeActorAuthorityVersion?.(
3165
+ decodeAuthorityKey(key).globalId,
3166
+ result.storeVersion.value
3167
+ );
3168
+ }
3055
3169
  }
3056
3170
  }
3057
3171
 
3058
3172
  /** Restores the hidden object and its saved-work prefix before Ready. */
3059
- private async handlePrepareControl(
3173
+ async handlePrepareControl(
3060
3174
  meshName: string,
3061
3175
  stagingId: string,
3062
3176
  request: ServiceMaintenanceRelocationPrepare,
@@ -3314,7 +3428,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
3314
3428
  * whole (the retransmission always resends the entire batch, so the exact
3315
3429
  * span is the staged suffix of `boundaryRecordCount` records).
3316
3430
  */
3317
- private reconcileBoundaryRelay(
3431
+ reconcileBoundaryRelay(
3318
3432
  stage: LocalStage,
3319
3433
  request: ServiceMaintenanceRelocationCutover,
3320
3434
  stagingId: string
@@ -3345,7 +3459,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
3345
3459
  );
3346
3460
  }
3347
3461
 
3348
- private beginTargetFinalize(
3462
+ beginTargetFinalize(
3349
3463
  meshName: string,
3350
3464
  stagingId: string,
3351
3465
  stage: LocalStage,
@@ -3362,7 +3476,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
3362
3476
  return finalize;
3363
3477
  }
3364
3478
 
3365
- private async finalizeTargetStage(
3479
+ async finalizeTargetStage(
3366
3480
  meshName: string,
3367
3481
  stagingId: string,
3368
3482
  stage: LocalStage,
@@ -3414,15 +3528,6 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
3414
3528
  );
3415
3529
  }
3416
3530
  await stage.owner.normalize(stage.staging, authority, signal);
3417
- // The target may have visited this Actor before and still retain that
3418
- // tenure in its private Actor-client resolver. The target-only CAS is
3419
- // now authoritative, so expire the old projection before OnJoinedActor
3420
- // can issue an Actor request and deadlock behind source leave.
3421
- for (const hidden of stage.staging.hidden.values()) {
3422
- if (hidden.actor !== undefined) {
3423
- this.options.invalidateActorRoute?.(hidden.actor.context.actorId);
3424
- }
3425
- }
3426
3531
  await this.finalizeActorJoinProfiles(meshName, stage, signal);
3427
3532
  await this.publishSessionRoutes(stage.staging);
3428
3533
  stage.phase = 'open';
@@ -3502,7 +3607,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
3502
3607
  );
3503
3608
  }
3504
3609
 
3505
- private async finalizeActorJoinProfiles(
3610
+ async finalizeActorJoinProfiles(
3506
3611
  meshName: string,
3507
3612
  stage: LocalStage,
3508
3613
  signal?: AbortSignal
@@ -3535,7 +3640,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
3535
3640
  }
3536
3641
  }
3537
3642
 
3538
- private async submitActorJoinSourceLeave(
3643
+ async submitActorJoinSourceLeave(
3539
3644
  meshName: string,
3540
3645
  sourceNodeRid: RoutingId,
3541
3646
  relocationId: string,
@@ -3561,7 +3666,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
3561
3666
  }
3562
3667
  }
3563
3668
 
3564
- private acceptActorJoinSourceLeave(input: {
3669
+ acceptActorJoinSourceLeave(input: {
3565
3670
  readonly transferId: string;
3566
3671
  readonly actorId: string;
3567
3672
  readonly succeeded: boolean;
@@ -3601,7 +3706,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
3601
3706
  );
3602
3707
  }
3603
3708
 
3604
- private async submitControlFrame(
3709
+ async submitControlFrame(
3605
3710
  meshName: string,
3606
3711
  targetNodeRid: RoutingId,
3607
3712
  frame: Buffer,
@@ -3615,7 +3720,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
3615
3720
  }
3616
3721
  }
3617
3722
 
3618
- private async clearTargetRelocationPublication(
3723
+ async clearTargetRelocationPublication(
3619
3724
  stage: LocalStage,
3620
3725
  primary: ZLinkAuthoritySnapshot,
3621
3726
  signal?: AbortSignal
@@ -3644,6 +3749,12 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
3644
3749
  if (result.kind !== 'stored') {
3645
3750
  throw new Error('Relocation target authority normalization CAS failed.');
3646
3751
  }
3752
+ if (primary.allocation.objectKind === 'actor') {
3753
+ this.options.observeActorAuthorityVersion?.(
3754
+ decodeAuthorityKey(stage.staging.primaryAuthorityKey).globalId,
3755
+ result.storeVersion.value
3756
+ );
3757
+ }
3647
3758
  return { ...result, kind: 'snapshot' };
3648
3759
  }
3649
3760
 
@@ -3723,7 +3834,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
3723
3834
  }
3724
3835
  }
3725
3836
 
3726
- private async sendReplyRelay(
3837
+ async sendReplyRelay(
3727
3838
  meshName: string,
3728
3839
  ackTargetNodeRid: RoutingId,
3729
3840
  request: ServiceMaintenanceReplyRelay,
@@ -3841,7 +3952,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
3841
3952
  }
3842
3953
  }
3843
3954
 
3844
- private targetReplyRelayCoordinator(
3955
+ targetReplyRelayCoordinator(
3845
3956
  meshName: string,
3846
3957
  stage: LocalStage,
3847
3958
  authority: ZLinkAuthoritySnapshot
@@ -3867,7 +3978,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
3867
3978
  };
3868
3979
  }
3869
3980
 
3870
- private async relayTerminalReply(
3981
+ async relayTerminalReply(
3871
3982
  meshName: string,
3872
3983
  stage: LocalStage,
3873
3984
  coordinator: ServiceWireRelocationCoordinatorFence,
@@ -3917,9 +4028,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
3917
4028
  );
3918
4029
  }
3919
4030
 
3920
- private async publishSessionRoutes(
3921
- staging: ServiceObjectRelocationStaging<LocalHidden>
3922
- ): Promise<void> {
4031
+ async publishSessionRoutes(staging: ServiceObjectRelocationStaging<LocalHidden>): Promise<void> {
3923
4032
  for (const [key, hidden] of staging.hidden) {
3924
4033
  if (hidden.actor === undefined) continue;
3925
4034
  // The Session seal travels with the relocation envelope, not the Actor.
@@ -3931,7 +4040,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
3931
4040
  }
3932
4041
  }
3933
4042
 
3934
- private async sendControl(
4043
+ async sendControl(
3935
4044
  meshName: string,
3936
4045
  targetNodeRid: RoutingId,
3937
4046
  request: ZLinkServiceRelocationControlRequest,
@@ -3950,26 +4059,42 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
3950
4059
  true
3951
4060
  );
3952
4061
  }
3953
- const replyFrames = await this.requestInfrastructureControl(
3954
- meshName,
3955
- targetNodeRid,
3956
- frames,
3957
- remainingMs,
3958
- signal,
3959
- onSubmitted
4062
+ const pending = this.options.requests.begin<
4063
+ ReturnType<typeof decodeServiceRelocationControlResponse>
4064
+ >(remainingMs, signal, undefined, deadlineAtMs);
4065
+ return this.options.requests.run(
4066
+ pending,
4067
+ (receiver) => {
4068
+ void this.requestInfrastructureControl(
4069
+ meshName,
4070
+ targetNodeRid,
4071
+ frames,
4072
+ remainingMs,
4073
+ signal,
4074
+ onSubmitted,
4075
+ pending
4076
+ ).then(
4077
+ (reply) => receiver.operationCompleted(pending.id, reply, undefined),
4078
+ (error) => receiver.operationFailed(pending.id, error, undefined)
4079
+ );
4080
+ },
4081
+ (raw) => {
4082
+ const replyFrames = raw as readonly Uint8Array[];
4083
+ if (replyFrames.length !== 1) {
4084
+ throw new ServiceWireProtocolError(
4085
+ `Relocation control '${key}' reply must contain exactly one frame.`
4086
+ );
4087
+ }
4088
+ const response = decodeServiceRelocationControlResponse(Buffer.from(replyFrames[0]!));
4089
+ if (response.kind === 'failed') {
4090
+ validateControlFailureResponse(request, response);
4091
+ } else {
4092
+ validateControlResponse(request, response);
4093
+ }
4094
+ return response;
4095
+ },
4096
+ (error) => error
3960
4097
  );
3961
- if (replyFrames.length !== 1) {
3962
- throw new ServiceWireProtocolError(
3963
- `Relocation control '${key}' reply must contain exactly one frame.`
3964
- );
3965
- }
3966
- const response = decodeServiceRelocationControlResponse(Buffer.from(replyFrames[0]!));
3967
- if (response.kind === 'failed') {
3968
- validateControlFailureResponse(request, response);
3969
- throw relocationFailureException(response);
3970
- }
3971
- validateControlResponse(request, response);
3972
- return response;
3973
4098
  }
3974
4099
 
3975
4100
  private async selectTarget(
@@ -4046,7 +4171,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
4046
4171
  return authorities;
4047
4172
  }
4048
4173
 
4049
- private async reserveTargetForPrepare(
4174
+ async reserveTargetForPrepare(
4050
4175
  meshName: string,
4051
4176
  prepare: ServiceMaintenanceRelocationPrepare,
4052
4177
  envelope: ServiceRelocationEnvelope,
@@ -4120,7 +4245,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
4120
4245
  };
4121
4246
  }
4122
4247
 
4123
- private authorityPayloadForPublication(
4248
+ authorityPayloadForPublication(
4124
4249
  payload: Uint8Array,
4125
4250
  publication: ServiceRelocationPublication,
4126
4251
  target?: {
@@ -4251,7 +4376,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
4251
4376
  }
4252
4377
  }
4253
4378
 
4254
- private async commitTargetReservation(
4379
+ async commitTargetReservation(
4255
4380
  stage: LocalStage,
4256
4381
  reservation: TargetRelocationReservation,
4257
4382
  signal?: AbortSignal
@@ -4326,7 +4451,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
4326
4451
  }
4327
4452
  }
4328
4453
 
4329
- private async readAggregateForCommitRetry(
4454
+ async readAggregateForCommitRetry(
4330
4455
  prepared: ServicePreparedRelocationAggregate,
4331
4456
  signal?: AbortSignal
4332
4457
  ): Promise<
@@ -4374,7 +4499,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
4374
4499
  return source === prepared.plan.participants.length ? { kind: 'source' } : { kind: 'stale' };
4375
4500
  }
4376
4501
 
4377
- private async materializeTargetEnvelope(
4502
+ async materializeTargetEnvelope(
4378
4503
  meshName: string,
4379
4504
  envelope: ServiceRelocationEnvelope,
4380
4505
  signal?: AbortSignal
@@ -4392,7 +4517,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
4392
4517
  }
4393
4518
 
4394
4519
  /** Maps schema ordinals to the authoritative Location Store inventory. */
4395
- private async resolveTargetParticipantInventory(
4520
+ async resolveTargetParticipantInventory(
4396
4521
  meshName: string,
4397
4522
  request: ServiceMaintenanceRelocationPrepare,
4398
4523
  envelope: ServiceRelocationEnvelope,
@@ -4549,7 +4674,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
4549
4674
  return value;
4550
4675
  }
4551
4676
 
4552
- private async captureApplication<T>(
4677
+ async captureApplication<T>(
4553
4678
  policy: { readonly kind: 'disabled' | 'recreate' | 'snapshot'; readonly adapterType?: Type },
4554
4679
  value: T,
4555
4680
  signal?: AbortSignal
@@ -4690,11 +4815,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
4690
4815
  return value;
4691
4816
  }
4692
4817
 
4693
- private afterSpotCloseDecision<T>(
4694
- meshName: string,
4695
- spotId: RoutingId,
4696
- seal: () => T
4697
- ): T | Promise<T> {
4818
+ afterSpotCloseDecision<T>(meshName: string, spotId: RoutingId, seal: () => T): T | Promise<T> {
4698
4819
  const manager = this.requireSpotManager();
4699
4820
  const sealAfterDecision = (): T => {
4700
4821
  if (manager.isSpotClosing(meshName, spotId)) {
@@ -4778,14 +4899,20 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
4778
4899
  frames: readonly Uint8Array[],
4779
4900
  timeoutMs: number,
4780
4901
  signal?: AbortSignal,
4781
- onSubmitted?: (signal: AbortSignal) => Promise<void>
4902
+ onSubmitted?: (signal: AbortSignal) => Promise<void>,
4903
+ requestOperation?: PendingOperation<unknown>
4782
4904
  ): Promise<readonly Uint8Array[]> {
4783
4905
  const node = this.requireMeshNode(meshName);
4784
4906
  const request = node.requestInfrastructureControlFrames;
4785
4907
  if (request === undefined) {
4786
4908
  throw new Error('RouteMesh backend cannot submit bare infrastructure requests.');
4787
4909
  }
4788
- return await request.call(node, targetNodeRid, frames, { timeoutMs, signal, onSubmitted });
4910
+ return await request.call(node, targetNodeRid, frames, {
4911
+ timeoutMs,
4912
+ signal,
4913
+ onSubmitted,
4914
+ requestOperation
4915
+ });
4789
4916
  }
4790
4917
  }
4791
4918
 
@@ -5037,6 +5164,7 @@ class LocalTargetPort implements ServiceRelocationTargetObjectPort<LocalHidden>
5037
5164
  value: hidden.authorityKey
5038
5165
  } as ZLinkAuthorityKey);
5039
5166
  const actorId = hidden.actor.context.actorId;
5167
+ this.options.observeActorAuthorityVersion?.(actorId, current.storeVersion.value);
5040
5168
  const node = this.options.meshNode(this.meshName);
5041
5169
  const restore = node?.restoreActorAuthority;
5042
5170
  if (node === undefined || restore === undefined) {
@@ -5744,7 +5872,7 @@ function maintenanceReplyRelay(
5744
5872
  const direct = packet.messageFollowOrigin?.requestSource !== undefined;
5745
5873
  const application =
5746
5874
  direct && completion.result.ok
5747
- ? decodeApplicationPayloadView(
5875
+ ? decodeApplicationPayload(
5748
5876
  encodeMultipartApplicationPayload(
5749
5877
  encodeActorReply(
5750
5878
  Buffer.from(packet.header, 'base64'),