@zlink-systems/framework 0.29.1 → 0.30.1

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 (322) hide show
  1. package/LICENSE +150 -68
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/contracts/Actors/ZLinkActorClient.d.ts +2 -1
  4. package/dist/contracts/Channels/Calls.d.ts +2 -1
  5. package/dist/contracts/Common/ZLinkMessageMetadata.js +11 -5
  6. package/dist/contracts/Configuration/Builders.d.ts +1 -2
  7. package/dist/contracts/Configuration/Configs.d.ts +0 -5
  8. package/dist/contracts/Configuration/RegistrationBuilders.js +6 -4
  9. package/dist/contracts/Configuration/RegistrationTypes.d.ts +1 -6
  10. package/dist/contracts/Configuration/RegistrationValidators.js +4 -4
  11. package/dist/contracts/Configuration/index.d.ts +1 -1
  12. package/dist/contracts/Handlers/Attributes.d.ts +5 -13
  13. package/dist/contracts/Handlers/Attributes.js +7 -11
  14. package/dist/contracts/Handlers/JsonContract.d.ts +2 -46
  15. package/dist/contracts/Handlers/JsonContract.js +4 -153
  16. package/dist/contracts/Spots/Contracts.d.ts +2 -1
  17. package/dist/internal.d.ts +1 -0
  18. package/dist/internal.js +3 -1
  19. package/dist/nest-integration.d.ts +1 -1
  20. package/dist/nest-integration.js +2 -1
  21. package/dist/runtime/actors/actor-client.d.ts +1 -1
  22. package/dist/runtime/actors/actor-client.js +14 -12
  23. package/dist/runtime/actors/actor-handoff.d.ts +3 -2
  24. package/dist/runtime/actors/actor-handoff.js +15 -7
  25. package/dist/runtime/actors/actor-join-relocation.d.ts +1 -0
  26. package/dist/runtime/actors/actor-local-native-join.js +9 -12
  27. package/dist/runtime/actors/actor-remote-wire.js +15 -0
  28. package/dist/runtime/actors/actor-routed-join-transport.d.ts +6 -2
  29. package/dist/runtime/actors/actor-routed-json-request.d.ts +2 -0
  30. package/dist/runtime/actors/index.d.ts +2 -1
  31. package/dist/runtime/actors/index.js +18 -6
  32. package/dist/runtime/actors/spot-actor-dispatch.js +2 -2
  33. package/dist/runtime/admission.d.ts +1 -1
  34. package/dist/runtime/admission.js +15 -5
  35. package/dist/runtime/application-jobs/application-ingress-record-owner.d.ts +9 -9
  36. package/dist/runtime/application-jobs/application-ingress-record-owner.js +45 -23
  37. package/dist/runtime/application-jobs/application-job-queue-scope.d.ts +5 -2
  38. package/dist/runtime/application-jobs/application-job-queue-scope.js +41 -21
  39. package/dist/runtime/application-jobs/contracts.d.ts +15 -2
  40. package/dist/runtime/backend/contracts/index.d.ts +27 -27
  41. package/dist/runtime/backend/mesh-completion-table.d.ts +15 -5
  42. package/dist/runtime/backend/mesh-completion-table.js +160 -50
  43. package/dist/runtime/backend/mesh-dispatch-pump.d.ts +3 -0
  44. package/dist/runtime/backend/mesh-dispatch-pump.js +53 -36
  45. package/dist/runtime/backend/node/node-backend-adapter-factory.js +6 -1
  46. package/dist/runtime/backend/node/node-backend-adapter-support.d.ts +3 -3
  47. package/dist/runtime/backend/node/node-backend-adapter-support.js +33 -31
  48. package/dist/runtime/backend/node/node-dealer-channel-client-transport.d.ts +1 -1
  49. package/dist/runtime/backend/node/node-dealer-channel-client-transport.js +5 -2
  50. package/dist/runtime/backend/node/node-mesh-backend-adapter.d.ts +1 -9
  51. package/dist/runtime/backend/node/node-mesh-backend-adapter.js +1 -1
  52. package/dist/runtime/backend/node/node-raw-binding-port.js +50 -25
  53. package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +22 -16
  54. package/dist/runtime/backend/node/node-raw-mesh-backend.js +133 -149
  55. package/dist/runtime/backend/node/node-socket-backend-adapter.js +15 -10
  56. package/dist/runtime/backend/raw-binding-port.d.ts +10 -3
  57. package/dist/runtime/backend/runtime-message.d.ts +1 -0
  58. package/dist/runtime/backend/runtime-message.js +5 -0
  59. package/dist/runtime/backend/runtime-values.d.ts +1 -0
  60. package/dist/runtime/backend/runtime-values.js +2 -1
  61. package/dist/runtime/channels/channel-clients.d.ts +1 -0
  62. package/dist/runtime/channels/channel-clients.js +58 -21
  63. package/dist/runtime/channels/channel-dispatch-pipeline.d.ts +3 -2
  64. package/dist/runtime/channels/channel-dispatch-pipeline.js +20 -11
  65. package/dist/runtime/channels/channel-dispatch-services.d.ts +1 -0
  66. package/dist/runtime/channels/channel-dispatch-services.js +45 -0
  67. package/dist/runtime/channels/channel-dispatchers.d.ts +1 -1
  68. package/dist/runtime/channels/channel-dispatchers.js +27 -26
  69. package/dist/runtime/channels/channel-envelope-inspection.d.ts +1 -2
  70. package/dist/runtime/channels/channel-envelope-inspection.js +1 -16
  71. package/dist/runtime/channels/channel-envelope.d.ts +1 -0
  72. package/dist/runtime/channels/channel-envelope.js +83 -8
  73. package/dist/runtime/channels/channel-outbound-operations.d.ts +2 -2
  74. package/dist/runtime/channels/channel-outbound-operations.js +8 -8
  75. package/dist/runtime/channels/channel-receive-loops.js +3 -3
  76. package/dist/runtime/channels/channel-runtime-lifecycle.js +2 -1
  77. package/dist/runtime/channels/channel-runtime-manager.d.ts +6 -6
  78. package/dist/runtime/channels/channel-runtime-manager.js +12 -12
  79. package/dist/runtime/channels/channel-socket-registry.d.ts +10 -3
  80. package/dist/runtime/channels/channel-socket-registry.js +59 -82
  81. package/dist/runtime/channels/channel-transports.d.ts +18 -15
  82. package/dist/runtime/channels/channel-transports.js +48 -31
  83. package/dist/runtime/channels/local-spot-route-transport.d.ts +1 -1
  84. package/dist/runtime/channels/local-spot-route-transport.js +2 -1
  85. package/dist/runtime/channels/router-socket-spot-route-transport.d.ts +2 -2
  86. package/dist/runtime/channels/router-socket-spot-route-transport.js +4 -4
  87. package/dist/runtime/channels/source-spot-router.d.ts +2 -2
  88. package/dist/runtime/channels/source-spot-router.js +4 -4
  89. package/dist/runtime/channels/spot-node-route-transport.d.ts +2 -2
  90. package/dist/runtime/channels/spot-node-route-transport.js +4 -4
  91. package/dist/runtime/channels/spot-route-bridge-transport.d.ts +2 -2
  92. package/dist/runtime/channels/spot-route-bridge-transport.js +4 -4
  93. package/dist/runtime/channels/spot-route-dispatch-strategy.d.ts +5 -4
  94. package/dist/runtime/channels/spot-route-dispatch-strategy.js +18 -18
  95. package/dist/runtime/diagnostics/message-flow.d.ts +1 -0
  96. package/dist/runtime/diagnostics/message-flow.js +3 -3
  97. package/dist/runtime/execution/serial-execution-queue.d.ts +1 -0
  98. package/dist/runtime/execution/serial-execution-queue.js +1 -0
  99. package/dist/runtime/foundation/actor-join-recovery-codec.js +2 -2
  100. package/dist/runtime/foundation/durable-service-request.d.ts +14 -0
  101. package/dist/runtime/foundation/durable-service-request.js +98 -0
  102. package/dist/runtime/foundation/operation-identity.d.ts +1 -0
  103. package/dist/runtime/foundation/operation-identity.js +5 -1
  104. package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +37 -6
  105. package/dist/runtime/foundation/raw-service-mesh-runtime.js +473 -220
  106. package/dist/runtime/foundation/service-liveness-registry.d.ts +20 -8
  107. package/dist/runtime/foundation/service-liveness-registry.js +57 -44
  108. package/dist/runtime/foundation/service-mailbox.d.ts +3 -0
  109. package/dist/runtime/foundation/service-mailbox.js +2 -1
  110. package/dist/runtime/foundation/service-relocation-object-owner.d.ts +1 -0
  111. package/dist/runtime/foundation/service-relocation-object-owner.js +1 -0
  112. package/dist/runtime/foundation/service-relocation-runtime.d.ts +2 -0
  113. package/dist/runtime/foundation/service-relocation-runtime.js +13 -1
  114. package/dist/runtime/foundation/service-runtime-contracts.d.ts +2 -0
  115. package/dist/runtime/foundation/service-stateful-runtime.d.ts +10 -9
  116. package/dist/runtime/foundation/service-stateful-runtime.js +78 -126
  117. package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +5 -7
  118. package/dist/runtime/foundation/service-stateful-wire-codec.js +43 -61
  119. package/dist/runtime/foundation/service-topology-registry.d.ts +16 -4
  120. package/dist/runtime/foundation/service-topology-registry.js +69 -30
  121. package/dist/runtime/foundation/service-wire-m6a-codec.d.ts +3 -3
  122. package/dist/runtime/foundation/service-wire-m6a-codec.js +36 -38
  123. package/dist/runtime/handlers/handler-instance-scope.d.ts +8 -0
  124. package/dist/runtime/handlers/handler-instance-scope.js +54 -11
  125. package/dist/runtime/host/actor-packet-relay.js +7 -7
  126. package/dist/runtime/host/actor-runtime-options-factory.js +2 -2
  127. package/dist/runtime/host/application-job-queue.d.ts +28 -9
  128. package/dist/runtime/host/application-job-queue.js +214 -50
  129. package/dist/runtime/host/entry-actor-runtime.d.ts +1 -0
  130. package/dist/runtime/host/entry-actor-runtime.js +4 -1
  131. package/dist/runtime/host/index.d.ts +7 -1
  132. package/dist/runtime/host/index.js +154 -126
  133. package/dist/runtime/host/instance-activation-authority.d.ts +2 -1
  134. package/dist/runtime/host/instance-activation-authority.js +89 -25
  135. package/dist/runtime/host/remote-bound-session-relay.js +2 -18
  136. package/dist/runtime/host/route-mesh-runtime.js +1 -1
  137. package/dist/runtime/host/service-relocation-control.d.ts +1 -0
  138. package/dist/runtime/host/service-relocation-control.js +10 -4
  139. package/dist/runtime/host/service-relocation-host-runtime.d.ts +6 -8
  140. package/dist/runtime/host/service-relocation-host-runtime.js +215 -243
  141. package/dist/runtime/host/spot-address-transport.d.ts +1 -0
  142. package/dist/runtime/host/spot-address-transport.js +28 -14
  143. package/dist/runtime/host/spot-runtime-options-factory.js +3 -2
  144. package/dist/runtime/host/user-spot-creation-coordinator.d.ts +1 -0
  145. package/dist/runtime/host/user-spot-creation-coordinator.js +1 -0
  146. package/dist/runtime/locations/actor-location-claims.d.ts +2 -2
  147. package/dist/runtime/locations/actor-location-claims.js +34 -19
  148. package/dist/runtime/locations/domain-store-contract.d.ts +2 -2
  149. package/dist/runtime/locations/in-memory-authority-store.d.ts +4 -2
  150. package/dist/runtime/locations/in-memory-authority-store.js +80 -8
  151. package/dist/runtime/locations/in-memory-location-store.d.ts +2 -2
  152. package/dist/runtime/locations/in-memory-location-store.js +19 -3
  153. package/dist/runtime/locations/internal-location-contracts.d.ts +3 -0
  154. package/dist/runtime/locations/lifecycle.d.ts +1 -2
  155. package/dist/runtime/locations/lifecycle.js +2 -5
  156. package/dist/runtime/locations/location-store-repository.d.ts +3 -2
  157. package/dist/runtime/locations/location-store-repository.js +165 -22
  158. package/dist/runtime/locations/resolvers.d.ts +2 -1
  159. package/dist/runtime/locations/resolvers.js +10 -1
  160. package/dist/runtime/locations/runtime.d.ts +1 -1
  161. package/dist/runtime/locations/runtime.js +24 -23
  162. package/dist/runtime/messaging/framework-json-v1.d.ts +4 -6
  163. package/dist/runtime/messaging/framework-json-v1.js +38 -294
  164. package/dist/runtime/messaging/packet-name.d.ts +1 -1
  165. package/dist/runtime/messaging/packet-name.js +8 -24
  166. package/dist/runtime/messaging/request-result.d.ts +2 -0
  167. package/dist/runtime/messaging/request-result.js +54 -0
  168. package/dist/runtime/messaging/submission-result.d.ts +2 -1
  169. package/dist/runtime/messaging/submission-result.js +7 -4
  170. package/dist/runtime/protocol/service_wire_codec.generated.d.ts +15 -0
  171. package/dist/runtime/protocol/service_wire_codec.generated.js +144 -0
  172. package/dist/runtime/protocol/service_wire_pilot_codec.generated.d.ts +9 -0
  173. package/dist/runtime/protocol/service_wire_pilot_codec.generated.js +14 -1
  174. package/dist/runtime/spots/formal-remote-actor-admission-registry.d.ts +9 -2
  175. package/dist/runtime/spots/formal-remote-actor-admission-registry.js +33 -19
  176. package/dist/runtime/spots/index.d.ts +7 -3
  177. package/dist/runtime/spots/index.js +23 -16
  178. package/dist/runtime/spots/spot-activation.d.ts +3 -1
  179. package/dist/runtime/spots/spot-activation.js +21 -12
  180. package/dist/runtime/spots/spot-actor-admission-coordinator.d.ts +2 -1
  181. package/dist/runtime/spots/spot-actor-admission-coordinator.js +11 -10
  182. package/dist/runtime/spots/spot-actor-packet-dispatch.d.ts +4 -1
  183. package/dist/runtime/spots/spot-actor-packet-dispatch.js +7 -5
  184. package/dist/runtime/spots/spot-actor-packet-drain.js +2 -0
  185. package/dist/runtime/spots/spot-actor-packet-relay-dispatch.js +1 -0
  186. package/dist/runtime/spots/spot-entry-activation.js +9 -3
  187. package/dist/runtime/spots/spot-handler-registry.d.ts +3 -1
  188. package/dist/runtime/spots/spot-handler-registry.js +18 -8
  189. package/dist/runtime/spots/spot-node-autoconnect.js +4 -3
  190. package/dist/runtime/spots/spot-node-runtime-manager.d.ts +2 -1
  191. package/dist/runtime/spots/spot-node-runtime-manager.js +4 -11
  192. package/dist/runtime/spots/spot-outbound.d.ts +3 -0
  193. package/dist/runtime/spots/spot-outbound.js +24 -15
  194. package/dist/runtime/spots/spot-routed-spot-packet-dispatch.d.ts +1 -0
  195. package/dist/runtime/spots/spot-routed-spot-packet-dispatch.js +1 -1
  196. package/dist/runtime/spots/spot-routing-internal.d.ts +6 -0
  197. package/dist/runtime/spots/spot-runtime-ports.d.ts +3 -1
  198. package/dist/runtime/spots/spot-subscription-dispatch.js +0 -3
  199. package/dist/runtime/spots/spot-timer.js +1 -0
  200. package/dist/runtime/streams/stream-session-runtime.d.ts +1 -1
  201. package/dist/runtime/streams/stream-session-runtime.js +14 -28
  202. package/package.json +3 -3
  203. package/src/contracts/Actors/ZLinkActorClient.ts +2 -1
  204. package/src/contracts/Channels/Calls.ts +2 -1
  205. package/src/contracts/Common/ZLinkMessageMetadata.ts +13 -8
  206. package/src/contracts/Configuration/Builders.ts +1 -2
  207. package/src/contracts/Configuration/Configs.ts +0 -6
  208. package/src/contracts/Configuration/RegistrationBuilders.ts +8 -12
  209. package/src/contracts/Configuration/RegistrationTypes.ts +1 -6
  210. package/src/contracts/Configuration/RegistrationValidators.ts +9 -10
  211. package/src/contracts/Configuration/index.ts +1 -6
  212. package/src/contracts/Handlers/Attributes.ts +14 -21
  213. package/src/contracts/Handlers/JsonContract.ts +8 -216
  214. package/src/contracts/Spots/Contracts.ts +2 -1
  215. package/src/internal.ts +1 -0
  216. package/src/nest-integration.ts +1 -0
  217. package/src/runtime/actors/actor-client.ts +40 -16
  218. package/src/runtime/actors/actor-handoff.ts +22 -8
  219. package/src/runtime/actors/actor-join-relocation.ts +1 -0
  220. package/src/runtime/actors/actor-local-native-join.ts +17 -26
  221. package/src/runtime/actors/actor-remote-wire.ts +17 -0
  222. package/src/runtime/actors/actor-routed-join-transport.ts +14 -4
  223. package/src/runtime/actors/actor-routed-json-request.ts +10 -2
  224. package/src/runtime/actors/index.ts +19 -5
  225. package/src/runtime/actors/spot-actor-dispatch.ts +4 -2
  226. package/src/runtime/admission.ts +18 -5
  227. package/src/runtime/application-jobs/application-ingress-record-owner.ts +53 -27
  228. package/src/runtime/application-jobs/application-job-queue-scope.ts +56 -22
  229. package/src/runtime/application-jobs/contracts.ts +28 -2
  230. package/src/runtime/backend/contracts/index.ts +63 -32
  231. package/src/runtime/backend/mesh-completion-table.ts +175 -59
  232. package/src/runtime/backend/mesh-dispatch-pump.ts +59 -32
  233. package/src/runtime/backend/node/node-backend-adapter-factory.ts +12 -5
  234. package/src/runtime/backend/node/node-backend-adapter-support.ts +42 -31
  235. package/src/runtime/backend/node/node-dealer-channel-client-transport.ts +12 -2
  236. package/src/runtime/backend/node/node-mesh-backend-adapter.ts +3 -10
  237. package/src/runtime/backend/node/node-raw-binding-port.ts +73 -37
  238. package/src/runtime/backend/node/node-raw-mesh-backend.ts +209 -176
  239. package/src/runtime/backend/node/node-socket-backend-adapter.ts +32 -13
  240. package/src/runtime/backend/raw-binding-port.ts +18 -3
  241. package/src/runtime/backend/runtime-message.ts +6 -0
  242. package/src/runtime/backend/runtime-values.ts +1 -0
  243. package/src/runtime/channels/channel-clients.ts +90 -41
  244. package/src/runtime/channels/channel-dispatch-pipeline.ts +69 -34
  245. package/src/runtime/channels/channel-dispatch-services.ts +69 -1
  246. package/src/runtime/channels/channel-dispatchers.ts +29 -27
  247. package/src/runtime/channels/channel-envelope-inspection.ts +2 -16
  248. package/src/runtime/channels/channel-envelope.ts +133 -8
  249. package/src/runtime/channels/channel-outbound-operations.ts +22 -8
  250. package/src/runtime/channels/channel-receive-loops.ts +3 -3
  251. package/src/runtime/channels/channel-runtime-lifecycle.ts +7 -1
  252. package/src/runtime/channels/channel-runtime-manager.ts +29 -12
  253. package/src/runtime/channels/channel-socket-registry.ts +84 -130
  254. package/src/runtime/channels/channel-transports.ts +128 -60
  255. package/src/runtime/channels/local-spot-route-transport.ts +3 -1
  256. package/src/runtime/channels/router-socket-spot-route-transport.ts +13 -4
  257. package/src/runtime/channels/source-spot-router.ts +8 -4
  258. package/src/runtime/channels/spot-node-route-transport.ts +8 -4
  259. package/src/runtime/channels/spot-route-bridge-transport.ts +6 -4
  260. package/src/runtime/channels/spot-route-dispatch-strategy.ts +47 -18
  261. package/src/runtime/diagnostics/message-flow.ts +1 -1
  262. package/src/runtime/execution/serial-execution-queue.ts +2 -0
  263. package/src/runtime/foundation/actor-join-recovery-codec.ts +2 -2
  264. package/src/runtime/foundation/durable-service-request.ts +137 -0
  265. package/src/runtime/foundation/operation-identity.ts +5 -1
  266. package/src/runtime/foundation/raw-service-mesh-runtime.ts +642 -253
  267. package/src/runtime/foundation/service-liveness-registry.ts +68 -59
  268. package/src/runtime/foundation/service-mailbox.ts +7 -1
  269. package/src/runtime/foundation/service-relocation-object-owner.ts +2 -0
  270. package/src/runtime/foundation/service-relocation-runtime.ts +18 -1
  271. package/src/runtime/foundation/service-runtime-contracts.ts +7 -1
  272. package/src/runtime/foundation/service-stateful-runtime.ts +128 -160
  273. package/src/runtime/foundation/service-stateful-wire-codec.ts +55 -84
  274. package/src/runtime/foundation/service-topology-registry.ts +103 -42
  275. package/src/runtime/foundation/service-wire-m6a-codec.ts +57 -38
  276. package/src/runtime/handlers/handler-instance-scope.ts +67 -16
  277. package/src/runtime/host/actor-packet-relay.ts +7 -0
  278. package/src/runtime/host/actor-runtime-options-factory.ts +14 -2
  279. package/src/runtime/host/application-job-queue.ts +249 -48
  280. package/src/runtime/host/entry-actor-runtime.ts +5 -0
  281. package/src/runtime/host/index.ts +224 -160
  282. package/src/runtime/host/instance-activation-authority.ts +132 -27
  283. package/src/runtime/host/remote-bound-session-relay.ts +2 -23
  284. package/src/runtime/host/route-mesh-runtime.ts +1 -1
  285. package/src/runtime/host/service-relocation-control.ts +11 -5
  286. package/src/runtime/host/service-relocation-host-runtime.ts +317 -291
  287. package/src/runtime/host/spot-address-transport.ts +49 -24
  288. package/src/runtime/host/spot-runtime-options-factory.ts +4 -0
  289. package/src/runtime/host/user-spot-creation-coordinator.ts +8 -0
  290. package/src/runtime/locations/actor-location-claims.ts +52 -30
  291. package/src/runtime/locations/domain-store-contract.ts +6 -2
  292. package/src/runtime/locations/in-memory-authority-store.ts +113 -9
  293. package/src/runtime/locations/in-memory-location-store.ts +25 -3
  294. package/src/runtime/locations/internal-location-contracts.ts +4 -0
  295. package/src/runtime/locations/lifecycle.ts +8 -26
  296. package/src/runtime/locations/location-store-repository.ts +220 -15
  297. package/src/runtime/locations/resolvers.ts +25 -2
  298. package/src/runtime/locations/runtime.ts +28 -24
  299. package/src/runtime/messaging/framework-json-v1.ts +5 -325
  300. package/src/runtime/messaging/packet-name.ts +5 -25
  301. package/src/runtime/messaging/request-result.ts +58 -0
  302. package/src/runtime/messaging/submission-result.ts +7 -3
  303. package/src/runtime/protocol/service_wire_codec.generated.ts +131 -1
  304. package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +4 -4
  305. package/src/runtime/spots/formal-remote-actor-admission-registry.ts +45 -23
  306. package/src/runtime/spots/index.ts +30 -2
  307. package/src/runtime/spots/spot-activation.ts +33 -10
  308. package/src/runtime/spots/spot-actor-admission-coordinator.ts +13 -0
  309. package/src/runtime/spots/spot-actor-packet-dispatch.ts +10 -0
  310. package/src/runtime/spots/spot-actor-packet-drain.ts +2 -0
  311. package/src/runtime/spots/spot-actor-packet-relay-dispatch.ts +1 -0
  312. package/src/runtime/spots/spot-entry-activation.ts +12 -2
  313. package/src/runtime/spots/spot-handler-registry.ts +41 -8
  314. package/src/runtime/spots/spot-node-autoconnect.ts +6 -2
  315. package/src/runtime/spots/spot-node-runtime-manager.ts +7 -12
  316. package/src/runtime/spots/spot-outbound.ts +36 -16
  317. package/src/runtime/spots/spot-routed-spot-packet-dispatch.ts +2 -1
  318. package/src/runtime/spots/spot-routing-internal.ts +14 -0
  319. package/src/runtime/spots/spot-runtime-ports.ts +3 -0
  320. package/src/runtime/spots/spot-subscription-dispatch.ts +0 -3
  321. package/src/runtime/spots/spot-timer.ts +5 -1
  322. package/src/runtime/streams/stream-session-runtime.ts +13 -30
@@ -5,6 +5,7 @@ exports.decodeQueuedHandoffPacket = decodeQueuedHandoffPacket;
5
5
  exports.createServiceRelocationId = createServiceRelocationId;
6
6
  exports.relocationFailedFailureCode = relocationFailedFailureCode;
7
7
  exports.encodeHandoffQueuedMessages = encodeHandoffQueuedMessages;
8
+ const durable_service_request_1 = require("../foundation/durable-service-request");
8
9
  const stream_wire_1 = require("@zlink-systems/stream-wire");
9
10
  const node_crypto_1 = require("node:crypto");
10
11
  const contracts_1 = require("../../contracts");
@@ -42,7 +43,6 @@ const relocation_direct_transfer_1 = require("./relocation-direct-transfer");
42
43
  const relocation_integrity_fault_gate_1 = require("./relocation-integrity-fault-gate");
43
44
  const relocation_state_adapter_1 = require("./relocation-state-adapter");
44
45
  const service_relocation_control_1 = require("./service-relocation-control");
45
- const RELOCATION_ATTEMPT_TIMEOUT_MS = 250;
46
46
  const RELOCATION_AUTHORITY_RETRY_DELAY_MS = 25;
47
47
  const RELOCATION_MAX_SEND_ATTEMPTS = 120;
48
48
  const RELOCATION_AUTHORITY_POLL_INTERVAL_MS = 10;
@@ -60,6 +60,7 @@ const RELOCATION_PARTICIPANT_STATE_LIMIT_BYTES = 64 * 1024 * 1024;
60
60
  const RELOCATION_TARGET_TOMBSTONE_LIMIT = 1024;
61
61
  const RELOCATION_OPERATION_RETENTION_MS = 5 * 60_000;
62
62
  const SERVICE_CONTROL_TERMINAL_CAPACITY = 4096;
63
+ const INITIAL_MEMBERSHIP_EPOCH = 1n;
63
64
  /** Production host bridge from Retire inventory to remote RouteMesh owners. */
64
65
  class ZLinkHostServiceRelocationRuntime {
65
66
  options;
@@ -155,7 +156,7 @@ class ZLinkHostServiceRelocationRuntime {
155
156
  ? contracts_1.ZLinkSpotKind.Entry
156
157
  : contracts_1.ZLinkSpotKind.User,
157
158
  spotObjectGeneration: spotGeneration
158
- }, input.relocationId, true, input.advertisedReceiveChunkLimitBytes);
159
+ }, input.relocationId, true, input.advertisedReceiveChunkLimitBytes, input.deadlineAtMs);
159
160
  resolveReady();
160
161
  }
161
162
  catch (error) {
@@ -199,7 +200,10 @@ class ZLinkHostServiceRelocationRuntime {
199
200
  if (window.followTimer !== undefined)
200
201
  clearTimeout(window.followTimer);
201
202
  }
203
+ const hadSourceWindows = this.sourceCutoverWindows.size !== 0;
202
204
  this.sourceCutoverWindows.clear();
205
+ if (hadSourceWindows)
206
+ this.options.sourceQuiescenceChanged?.();
203
207
  const stopped = new Error('Relocation runtime stopped.');
204
208
  stopped.name = 'AbortError';
205
209
  this.targetPrepareOperations.clear();
@@ -402,18 +406,29 @@ class ZLinkHostServiceRelocationRuntime {
402
406
  }
403
407
  throw failure;
404
408
  }
405
- async tryHandleControl(meshName, record, signal) {
409
+ tryHandleControl(meshName, record, signal) {
406
410
  if (record.parts.length === 0)
407
411
  return false;
408
412
  const payload = record.parts[0].data();
409
- if (isServiceWireCommand(payload, service_stateful_wire_codec_1.M6bServiceWireCommand.replyRelay)) {
413
+ const command = (0, service_relocation_control_1.serviceRelocationControlCommand)(payload);
414
+ if (command === undefined) {
415
+ if (record.kind !== service_runtime_contracts_1.ReceiveKind.NodeSend)
416
+ return false;
417
+ const sourceLeave = (0, actor_remote_wire_1.decodeRemoteActorSourceLeaveTerminal)(payload);
418
+ if (sourceLeave === undefined)
419
+ return false;
420
+ if (record.parts.length !== 1)
421
+ return false;
422
+ return this.acceptActorJoinSourceLeave(sourceLeave);
423
+ }
424
+ return this.handleControl(meshName, record, payload, command, signal);
425
+ }
426
+ async handleControl(meshName, record, payload, command, signal) {
427
+ if (command === service_stateful_wire_codec_1.M6bServiceWireCommand.replyRelay) {
410
428
  await this.handleReplyRelay(meshName, (0, service_stateful_wire_codec_1.decodeMaintenanceReplyRelay)(record.parts.map((part) => part.data())), record.sourceNodeRid, signal);
411
429
  return true;
412
430
  }
413
- const sideband = record.parts.length === 1
414
- ? undefined
415
- : decodePrepareSideband(record.parts.slice(1).map((part) => part.data()));
416
- if (record.parts.length > 1 && sideband === undefined)
431
+ if (record.parts.length !== 1)
417
432
  return false;
418
433
  if (record.kind === service_runtime_contracts_1.ReceiveKind.NodeSend) {
419
434
  const sourceLeave = (0, actor_remote_wire_1.decodeRemoteActorSourceLeaveTerminal)(payload);
@@ -421,33 +436,28 @@ class ZLinkHostServiceRelocationRuntime {
421
436
  return this.acceptActorJoinSourceLeave(sourceLeave);
422
437
  }
423
438
  }
424
- if (isServiceWireCommand(payload, service_stateful_wire_codec_1.M6bServiceWireCommand.sessionRelocationSealed)) {
439
+ if (command === service_stateful_wire_codec_1.M6bServiceWireCommand.sessionRelocationSealed) {
425
440
  this.acceptSessionRelocationResponse((0, service_stateful_wire_codec_1.decodeSessionRelocationSealed)(payload), record.sourceNodeRid);
426
441
  return true;
427
442
  }
428
- if (isServiceWireCommand(payload, service_stateful_wire_codec_1.M6bServiceWireCommand.sessionRelocationSeal)) {
443
+ if (command === service_stateful_wire_codec_1.M6bServiceWireCommand.sessionRelocationSeal) {
429
444
  const request = (0, service_stateful_wire_codec_1.decodeSessionRelocationSeal)(payload);
430
445
  const response = await this.handleSessionRelocationSeal(meshName, request, record.sourceNodeRid, signal);
431
446
  await this.sendSessionRelocationResponse(meshName, record.sourceNodeRid, (0, service_stateful_wire_codec_1.encodeSessionRelocationSealed)(response));
432
447
  return true;
433
448
  }
434
- if (isServiceWireCommand(payload, service_stateful_wire_codec_1.M6bServiceWireCommand.sessionRelocationRoute)) {
449
+ if (command === service_stateful_wire_codec_1.M6bServiceWireCommand.sessionRelocationRoute) {
435
450
  const request = (0, service_stateful_wire_codec_1.decodeSessionRelocationRoute)(payload);
436
451
  await this.handleSessionRelocationRoute(meshName, request, record.sourceNodeRid, signal);
437
452
  return true;
438
453
  }
439
- if (isServiceWireCommand(payload, service_stateful_wire_codec_1.M6bServiceWireCommand.replyRelayAck)) {
454
+ if (command === service_stateful_wire_codec_1.M6bServiceWireCommand.replyRelayAck) {
440
455
  await this.acceptReplyRelayAck(meshName, (0, service_stateful_wire_codec_1.decodeMaintenanceReplyRelayAck)(payload), record.sourceNodeRid, signal);
441
456
  return true;
442
457
  }
443
458
  let request = (0, service_relocation_control_1.decodeServiceRelocationControlRequest)(payload);
444
459
  if (request === undefined)
445
460
  return false;
446
- if (sideband !== undefined) {
447
- if (request.kind !== 'prepare')
448
- return false;
449
- request = { ...request, nodeInternalBoundSessions: sideband };
450
- }
451
461
  // Ready(30) and Failed(53) are replies to Prepare(40), never independent
452
462
  // inbound controls. The source consumes them on Core's request reply leg.
453
463
  if (request.kind === 'ready' || request.kind === 'failed')
@@ -894,7 +904,7 @@ class ZLinkHostServiceRelocationRuntime {
894
904
  validateSessionOwnerFence(meshName, session) {
895
905
  const status = this.requireMeshNode(meshName).status();
896
906
  const owner = this.options.currentOwner();
897
- if (String(status.routingId) !== session.sessionOwnerNodeRid ||
907
+ if (!(0, routing_id_1.routingIdsEqual)(status.routingId, session.sessionOwnerNodeRid) ||
898
908
  status.lifecycleGeneration !== session.sessionOwnerNodeGeneration ||
899
909
  owner?.ownerId !== session.sessionOwnerId ||
900
910
  owner.leaseGeneration !== session.sessionOwnerLeaseGeneration) {
@@ -1121,7 +1131,7 @@ class ZLinkHostServiceRelocationRuntime {
1121
1131
  }
1122
1132
  async relocateStandaloneActor(meshName, state, target, targetApplicationVersion, signal, targetMembership, aggregateIdOverride, retainSourceForActorJoin = false,
1123
1133
  /** Target's advertised relocation state chunk cap (Actor Join only; spec 15 §4.2). */
1124
- advertisedReceiveChunkLimitBytes) {
1134
+ advertisedReceiveChunkLimitBytes, deadlineAtMs) {
1125
1135
  if ((0, diagnostics_1.isRelocationDebugEnabled)()) {
1126
1136
  (0, diagnostics_1.relocationDebug)('standalone_actor.begin', { actorId: state.actorId });
1127
1137
  }
@@ -1171,7 +1181,7 @@ class ZLinkHostServiceRelocationRuntime {
1171
1181
  if ((0, diagnostics_1.isRelocationDebugEnabled)()) {
1172
1182
  (0, diagnostics_1.relocationDebug)('standalone_actor.capture_complete', { actorId: state.actorId });
1173
1183
  }
1174
- await this.runCoordinator(meshName, target, authority, captured, new Map([[measuredUnit.authorityKey, authority]]), signal, sessions, advertisedReceiveChunkLimitBytes);
1184
+ await this.runCoordinator(meshName, target, authority, captured, new Map([[measuredUnit.authorityKey, authority]]), signal, sessions, advertisedReceiveChunkLimitBytes, deadlineAtMs);
1175
1185
  }
1176
1186
  catch (error) {
1177
1187
  outcome = 'failed';
@@ -1287,14 +1297,27 @@ class ZLinkHostServiceRelocationRuntime {
1287
1297
  }
1288
1298
  const prepared = standalone ? ownSession : sessions.find((value) => value.state === state);
1289
1299
  return {
1290
- boundSessionState: encodeActorSession(prepared?.prepared.target),
1300
+ boundSessionState: Buffer.alloc(0),
1301
+ ...(prepared?.prepared.target?.serviceWireRelocation === undefined
1302
+ ? {}
1303
+ : {
1304
+ sessionBinding: {
1305
+ participantId: 1n,
1306
+ sessionOwnerNodeRid: Buffer.from((0, routing_id_1.encodeRoutingIdStorageHex)(prepared.prepared.target.sessionNodeRid), 'hex'),
1307
+ sessionOwnerNodeGeneration: prepared.prepared.target.serviceWireRelocation.session
1308
+ .sessionOwnerNodeGeneration,
1309
+ sessionOwnerId: prepared.prepared.target.serviceWireRelocation.session.sessionOwnerId,
1310
+ sessionOwnerLeaseGeneration: prepared.prepared.target.serviceWireRelocation.session
1311
+ .sessionOwnerLeaseGeneration,
1312
+ sessionRid: Buffer.from((0, routing_id_1.encodeRoutingIdStorageHex)(prepared.prepared.target.sessionRid), 'hex'),
1313
+ bindingGeneration: prepared.prepared.target.serviceWireRelocation.session.bindingGeneration
1314
+ }
1315
+ }),
1291
1316
  queuedMessages: encodeHandoffQueuedMessages(prepared?.prepared.handoffBacklog ?? []),
1292
1317
  timers: []
1293
1318
  };
1294
1319
  },
1295
- // The canonical participant body (discriminator 1) is raw application
1296
- // state. The sealed bound-session target remains in sealed work and is
1297
- // transported only by Prepare's NODE-INTERNAL sideband frames.
1320
+ // The sealed Session identity is part of the canonical participant vector.
1298
1321
  captureApplicationState: (signal) => this.captureApplication(registration.relocation, state.actor, signal),
1299
1322
  commitSeal: async () => {
1300
1323
  if (!standalone ||
@@ -1367,7 +1390,7 @@ class ZLinkHostServiceRelocationRuntime {
1367
1390
  }
1368
1391
  async runCoordinator(meshName, target, primary, captured, _authorities, signal, sessions = [],
1369
1392
  /** Target's advertised relocation state chunk cap (Actor Join only; spec 15 §4.2). */
1370
- advertisedReceiveChunkLimitBytes) {
1393
+ advertisedReceiveChunkLimitBytes, controlDeadlineAtMs = performance.now() + RELOCATION_OPERATION_TIMEOUT_MS) {
1371
1394
  if ((0, diagnostics_1.isRelocationDebugEnabled)()) {
1372
1395
  (0, diagnostics_1.relocationDebug)('coordinator.begin', {
1373
1396
  aggregateId: captured.envelope.aggregateId,
@@ -1375,9 +1398,6 @@ class ZLinkHostServiceRelocationRuntime {
1375
1398
  });
1376
1399
  }
1377
1400
  const localStatus = this.requireMeshNode(meshName).status();
1378
- const controlDeadlineAtMs = signal === undefined
1379
- ? performance.now() + RELOCATION_OPERATION_TIMEOUT_MS
1380
- : Number.MAX_SAFE_INTEGER;
1381
1401
  const coordinator = {
1382
1402
  ownerId: primary.ownerId,
1383
1403
  leaseGeneration: primary.ownerLeaseGeneration,
@@ -1446,23 +1466,17 @@ class ZLinkHostServiceRelocationRuntime {
1446
1466
  // queue and the assembly on the target), then stream the payload chunks
1447
1467
  // on the same ordered connection. The Ready reply arrives only after
1448
1468
  // the target assembled, verified, and restored the payload.
1449
- const readyOperation = this.sendControl(meshName, target.rid, prepare, signal, controlDeadlineAtMs, encodePrepareSideband(captured.envelope));
1450
- try {
1451
- if ((0, diagnostics_1.isRelocationDebugEnabled)()) {
1469
+ const ready = await this.sendControl(meshName, target.rid, prepare, signal, controlDeadlineAtMs, async (attemptSignal) => {
1470
+ if ((0, diagnostics_1.isRelocationDebugEnabled)())
1452
1471
  (0, diagnostics_1.relocationDebug)('coordinator.state_transfer_begin', {
1453
1472
  aggregateId: captured.envelope.aggregateId
1454
1473
  });
1455
- }
1456
- await this.sendRelocationStateChunks(meshName, target, prepare, encoded, plan, signal);
1457
- }
1458
- catch (chunkError) {
1459
- readyOperation.catch(() => undefined);
1460
- throw chunkError;
1461
- }
1462
- if ((0, diagnostics_1.isRelocationDebugEnabled)()) {
1463
- (0, diagnostics_1.relocationDebug)('coordinator.await_ready', { aggregateId: captured.envelope.aggregateId });
1464
- }
1465
- const ready = await readyOperation;
1474
+ await this.sendRelocationStateChunks(meshName, target, prepare, encoded, plan, attemptSignal);
1475
+ if ((0, diagnostics_1.isRelocationDebugEnabled)())
1476
+ (0, diagnostics_1.relocationDebug)('coordinator.await_ready', {
1477
+ aggregateId: captured.envelope.aggregateId
1478
+ });
1479
+ });
1466
1480
  if ((0, diagnostics_1.isRelocationDebugEnabled)()) {
1467
1481
  (0, diagnostics_1.relocationDebug)('coordinator.ready_received', {
1468
1482
  aggregateId: captured.envelope.aggregateId
@@ -1511,7 +1525,7 @@ class ZLinkHostServiceRelocationRuntime {
1511
1525
  // The cutover submit result is not the authority result. The memory
1512
1526
  // copy of the boundary batch and cutover stays until the authority
1513
1527
  // settlement below (spec 28 §4.4).
1514
- let submitFailure;
1528
+ const submittedRouteGeneration = this.requireMeshNode(meshName).observePeerRoute?.(target.rid).generation;
1515
1529
  try {
1516
1530
  for (const record of boundaryBatch) {
1517
1531
  await this.submitControlFrame(meshName, target.rid, record.frame, 'relay');
@@ -1519,10 +1533,11 @@ class ZLinkHostServiceRelocationRuntime {
1519
1533
  await this.submitControlFrame(meshName, target.rid, cutoverFrame, 'cutover');
1520
1534
  }
1521
1535
  catch (error) {
1522
- submitFailure = error;
1536
+ if (!(0, durable_service_request_1.durableRequestCanReplay)(error))
1537
+ throw error;
1523
1538
  console.warn('[zlink.runtime.relocation.cutover_submit_failed]', relayAuthorityId, error);
1524
1539
  }
1525
- const window = this.beginSourceCutoverWindow(meshName, target.rid, relayAuthorityId, [...boundaryBatch.map((value) => value.frame), cutoverFrame], submitFailure !== undefined, limits);
1540
+ const window = this.beginSourceCutoverWindow(meshName, target.rid, relayAuthorityId, [...boundaryBatch.map((value) => value.frame), cutoverFrame], submittedRouteGeneration, limits);
1526
1541
  try {
1527
1542
  settlement = await this.settleSourceAuthority(captured.envelope, primary, targetFence, restoreDeadlineReached, window);
1528
1543
  }
@@ -1544,7 +1559,7 @@ class ZLinkHostServiceRelocationRuntime {
1544
1559
  if (settlement === 'lost') {
1545
1560
  // Expired owner: dispatch and Store changes stop for good and every
1546
1561
  // pending request without a terminal gets one Unavailable.
1547
- const unavailable = (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.RouteNotConnected, `Relocation '${relayAuthorityId}' source owner lease ended before its authority settled.`, true);
1562
+ const unavailable = (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.RouteNotConnected, `Relocation '${relayAuthorityId}' source authority ended (source owner lease expired, authority Missing, or owner changed).`, true);
1548
1563
  await captured.discardSource(unavailable);
1549
1564
  throw new service_relocation_coordinator_1.ServiceRelocationAuthorityError(unavailable.message, { cause: unavailable });
1550
1565
  }
@@ -1578,6 +1593,7 @@ class ZLinkHostServiceRelocationRuntime {
1578
1593
  const chunkData = (0, relocation_direct_transfer_1.relocationChunkAt)(encoded, plan, ordinal);
1579
1594
  const releases = await this.acquireRelocationBudget(String(target.rid), chunkData.byteLength, signal);
1580
1595
  try {
1596
+ signal?.throwIfAborted();
1581
1597
  await this.sendControlOneWay(meshName, target.rid, {
1582
1598
  kind: 'state',
1583
1599
  relocation: identity.relocation,
@@ -1638,18 +1654,21 @@ class ZLinkHostServiceRelocationRuntime {
1638
1654
  * window. S4 — the Message Follow route removal point — closes the unit for
1639
1655
  * SafeToShutdown.
1640
1656
  */
1641
- beginSourceCutoverWindow(meshName, targetNodeRid, relocationKey, frames, initialSubmitFailed, limits) {
1657
+ beginSourceCutoverWindow(meshName, targetNodeRid, relocationKey, frames, submittedRouteGeneration, limits) {
1642
1658
  const submittedAt = performance.now();
1643
1659
  const window = {
1644
1660
  meshName,
1645
1661
  targetNodeRid,
1646
1662
  frames,
1647
- resendPending: initialSubmitFailed,
1663
+ submittedRouteGeneration,
1648
1664
  cutoverSubmittedAtMs: submittedAt,
1649
1665
  windowClosed: false,
1650
1666
  followExpired: false
1651
1667
  };
1668
+ const wasQuiescent = this.isSafeToShutdown();
1652
1669
  this.sourceCutoverWindows.set(relocationKey, window);
1670
+ if (wasQuiescent)
1671
+ this.options.sourceQuiescenceChanged?.();
1653
1672
  window.followTimer = setTimeout(() => {
1654
1673
  window.followExpired = true;
1655
1674
  // S1→S4 route convergence: the span the source must keep its Message
@@ -1671,33 +1690,27 @@ class ZLinkHostServiceRelocationRuntime {
1671
1690
  window.followExpired &&
1672
1691
  this.sourceCutoverWindows.get(relocationKey) === window) {
1673
1692
  this.sourceCutoverWindows.delete(relocationKey);
1693
+ if (this.isSafeToShutdown())
1694
+ this.options.sourceQuiescenceChanged?.();
1674
1695
  }
1675
1696
  }
1676
- /**
1677
- * Sends the whole boundary batch and cutover again after a failed submit
1678
- * or an observed loss of the target connection (spec 28 §4.4). The target
1679
- * replaces its partial span with the whole batch.
1680
- */
1697
+ /** Relocation flow §4.4: replay the whole batch on a different ready route. */
1681
1698
  async resendSourceCutover(window) {
1682
1699
  const frames = window.frames;
1683
1700
  if (frames === undefined)
1684
1701
  return;
1685
- const peers = this.requireMeshNode(window.meshName).peers();
1686
- const peer = peers.find((value) => value.routingId !== null && String(value.routingId) === String(window.targetNodeRid));
1687
- if (peer !== undefined && peer.state !== service_runtime_contracts_1.MeshPeerRuntimeState.Serving) {
1688
- window.resendPending = true;
1689
- return;
1690
- }
1691
- if (!window.resendPending)
1702
+ const route = this.requireMeshNode(window.meshName).observePeerRoute?.(window.targetNodeRid);
1703
+ if (route?.ready !== true || route.generation === window.submittedRouteGeneration)
1692
1704
  return;
1705
+ window.submittedRouteGeneration = route.generation;
1693
1706
  try {
1694
1707
  for (const frame of frames) {
1695
1708
  await this.submitControlFrame(window.meshName, window.targetNodeRid, frame, 'cutover retransmission');
1696
1709
  }
1697
- window.resendPending = false;
1698
1710
  }
1699
- catch {
1700
- // The next settlement round retries the whole batch.
1711
+ catch (error) {
1712
+ if (!(0, durable_service_request_1.durableRequestCanReplay)(error))
1713
+ throw error;
1701
1714
  }
1702
1715
  }
1703
1716
  /**
@@ -1708,8 +1721,8 @@ class ZLinkHostServiceRelocationRuntime {
1708
1721
  * excludes a late target commit. `target`: the
1709
1722
  * target committed. `source`: Preserve fenced the target out while the
1710
1723
  * source owner lease was valid. `lost`: the source owner lease ended first
1711
- * or another authority owns the object. An uncertain Store or lease result
1712
- * keeps the work retained and repeats the same decision.
1724
+ * or authority is Missing or another authority owns the object. An uncertain
1725
+ * Store or lease result keeps the work retained and repeats the same decision.
1713
1726
  */
1714
1727
  async settleSourceAuthority(envelope, primary, target, restoreDeadlineReached, window) {
1715
1728
  const owner = { ownerId: primary.ownerId, leaseGeneration: primary.ownerLeaseGeneration };
@@ -1860,12 +1873,18 @@ class ZLinkHostServiceRelocationRuntime {
1860
1873
  throw new ServiceRelocationDataLostError(String(message));
1861
1874
  }
1862
1875
  const envelope = (0, service_relocation_runtime_1.decodeServiceRelocationEnvelope)(payload, request.targetAttemptGeneration);
1863
- const inventoryEnvelope = attachPrepareBoundSessions(await this.resolveTargetParticipantInventory(request, envelope, signal), request.nodeInternalBoundSessions);
1864
- validatePrepareEnvelope(request, inventoryEnvelope);
1865
- const releaseActivation = (await this.options.activationAdmission?.acquire(meshName, signal)) ?? (() => undefined);
1876
+ const recovery = canonicalActorJoinRecovery(envelope.participants);
1877
+ const releaseJoinAdmission = recovery === undefined
1878
+ ? () => undefined
1879
+ : this.options.spotManager().beginActorJoinRelocation(recovery.request.handoffId);
1866
1880
  let materialized;
1867
1881
  let reservation;
1882
+ let releaseActivation = () => undefined;
1868
1883
  try {
1884
+ const inventoryEnvelope = attachCanonicalBoundSessions(await this.resolveTargetParticipantInventory(meshName, request, envelope, signal), request, meshName);
1885
+ validatePrepareEnvelope(request, inventoryEnvelope);
1886
+ releaseActivation =
1887
+ (await this.options.activationAdmission?.acquire(meshName, signal)) ?? (() => undefined);
1869
1888
  // Deferred Join completion publishes into the source authority's
1870
1889
  // canonical relocation slot. Do that while the row is still CAS-able;
1871
1890
  // the aggregate marker installed by reserveTargetForPrepare deliberately
@@ -1887,11 +1906,13 @@ class ZLinkHostServiceRelocationRuntime {
1887
1906
  lane: Promise.resolve(),
1888
1907
  cutoverReceived: false,
1889
1908
  boundaryRelay: [],
1890
- releaseActivation
1909
+ releaseActivation,
1910
+ releaseJoinAdmission
1891
1911
  };
1892
1912
  this.targetStages.set(stagingId, stage);
1893
1913
  }
1894
1914
  catch (error) {
1915
+ releaseJoinAdmission();
1895
1916
  releaseActivation();
1896
1917
  if (reservation !== undefined) {
1897
1918
  await this.abortTargetReservation(reservation, signal).catch(() => undefined);
@@ -2082,6 +2103,9 @@ class ZLinkHostServiceRelocationRuntime {
2082
2103
  }
2083
2104
  throw error;
2084
2105
  }
2106
+ finally {
2107
+ stage.releaseJoinAdmission();
2108
+ }
2085
2109
  }
2086
2110
  validateRelocationData(stage, request) {
2087
2111
  const frozen = request.frozenRecord;
@@ -2096,7 +2120,7 @@ class ZLinkHostServiceRelocationRuntime {
2096
2120
  target.generation !== request.object.objectGeneration ||
2097
2121
  target.targetNodeRid !== preparedTarget.nodeRid ||
2098
2122
  target.targetNodeGeneration !== preparedTarget.nodeGeneration ||
2099
- target.authorityOwnerGeneration !== request.object.expectedAuthorityOwnerGeneration + 1n ||
2123
+ target.authorityOwnerGeneration !== request.object.expectedAuthorityOwnerGeneration ||
2100
2124
  target.ownerLeaseGeneration !== preparedTarget.ownerLeaseGeneration) {
2101
2125
  throw new Error('Relocation data does not target the exact temporary Actor queue.');
2102
2126
  }
@@ -2169,7 +2193,9 @@ class ZLinkHostServiceRelocationRuntime {
2169
2193
  async submitControlFrame(meshName, targetNodeRid, frame, kind) {
2170
2194
  const submitted = await this.sendInfrastructureControl(meshName, targetNodeRid, frame);
2171
2195
  if (submitted !== runtime_values_1.SubmitResult.Ok) {
2172
- throw new Error(`Relocation ${kind} was not accepted by RouteMesh.`);
2196
+ throw new runtime_values_1.ZLinkBackendResultError('submit', submitted, undefined, {
2197
+ cause: new Error(`Relocation ${kind} was not accepted by RouteMesh.`)
2198
+ });
2173
2199
  }
2174
2200
  }
2175
2201
  async clearTargetRelocationPublication(stage, primary, signal) {
@@ -2378,51 +2404,25 @@ class ZLinkHostServiceRelocationRuntime {
2378
2404
  await this.options.actorTransfer.publishRoutedActorOwnership(hidden.actor, carried === undefined ? undefined : decodeActorSession(carried.boundSessionState));
2379
2405
  }
2380
2406
  }
2381
- async sendControl(meshName, targetNodeRid, request, signal, deadlineAtMs = performance.now() + RELOCATION_OPERATION_TIMEOUT_MS, sideband = []) {
2407
+ async sendControl(meshName, targetNodeRid, request, signal, deadlineAtMs = performance.now() + RELOCATION_OPERATION_TIMEOUT_MS, onSubmitted) {
2382
2408
  const key = controlAckKey(request);
2383
- const frames = sideband.length === 0
2384
- ? [(0, service_relocation_control_1.encodeServiceRelocationControlRequest)(request)]
2385
- : [(0, service_relocation_control_1.encodeServiceRelocationControlRequest)(request), ...sideband];
2386
- let lastRequestError;
2387
- for (;;) {
2388
- signal?.throwIfAborted();
2389
- const remainingMs = deadlineAtMs - performance.now();
2390
- if (remainingMs <= 0) {
2391
- throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.DeadlineExceeded, `Relocation control ACK '${key}' timed out.`, true, lastRequestError);
2392
- }
2393
- const attemptTimeoutMs = Math.max(1, Math.min(RELOCATION_ATTEMPT_TIMEOUT_MS, Math.ceil(remainingMs)));
2394
- const startedAtMs = performance.now();
2395
- try {
2396
- const replyFrames = await this.requestInfrastructureControl(meshName, targetNodeRid, frames, attemptTimeoutMs);
2397
- if (replyFrames.length !== 1) {
2398
- throw new service_wire_m6a_codec_1.ServiceWireProtocolError(`Relocation control '${key}' reply must contain exactly one frame.`);
2399
- }
2400
- const response = (0, service_relocation_control_1.decodeServiceRelocationControlResponse)(Buffer.from(replyFrames[0]));
2401
- if (response.kind === 'failed') {
2402
- validateControlFailureResponse(request, response);
2403
- throw relocationFailureException(response);
2404
- }
2405
- validateControlResponse(request, response);
2406
- return response;
2407
- }
2408
- catch (error) {
2409
- if (error instanceof service_wire_m6a_codec_1.ServiceWireProtocolError || error instanceof contracts_1.ZLinkFrameworkException) {
2410
- throw error;
2411
- }
2412
- lastRequestError = error;
2413
- if ((0, diagnostics_1.isRelocationDebugEnabled)()) {
2414
- (0, diagnostics_1.relocationDebug)('control.request_retry', {
2415
- key,
2416
- kind: request.kind,
2417
- targetRid: String(targetNodeRid)
2418
- });
2419
- }
2420
- const retryDelayMs = Math.min(Math.max(0, attemptTimeoutMs - (performance.now() - startedAtMs)), Math.max(0, deadlineAtMs - performance.now()));
2421
- if (retryDelayMs > 0) {
2422
- await waitForRelocationRetry(retryDelayMs, signal);
2423
- }
2424
- }
2409
+ const frames = [(0, service_relocation_control_1.encodeServiceRelocationControlRequest)(request)];
2410
+ signal?.throwIfAborted();
2411
+ const remainingMs = Math.ceil(deadlineAtMs - performance.now());
2412
+ if (remainingMs <= 0) {
2413
+ throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.DeadlineExceeded, `Relocation control ACK '${key}' timed out.`, true);
2425
2414
  }
2415
+ const replyFrames = await this.requestInfrastructureControl(meshName, targetNodeRid, frames, remainingMs, signal, onSubmitted);
2416
+ if (replyFrames.length !== 1) {
2417
+ throw new service_wire_m6a_codec_1.ServiceWireProtocolError(`Relocation control '${key}' reply must contain exactly one frame.`);
2418
+ }
2419
+ const response = (0, service_relocation_control_1.decodeServiceRelocationControlResponse)(Buffer.from(replyFrames[0]));
2420
+ if (response.kind === 'failed') {
2421
+ validateControlFailureResponse(request, response);
2422
+ throw relocationFailureException(response);
2423
+ }
2424
+ validateControlResponse(request, response);
2425
+ return response;
2426
2426
  }
2427
2427
  async selectTarget(meshName, localRid, targetApplicationVersion, requirements = [], signal) {
2428
2428
  const descriptors = await this.options.liveDescriptors(meshName, signal);
@@ -2473,7 +2473,7 @@ class ZLinkHostServiceRelocationRuntime {
2473
2473
  const publication = relocationPublication(prepare, envelope);
2474
2474
  const participants = envelope.participants.map((participant) => {
2475
2475
  const expected = authorities.get(participant.key);
2476
- const membership = actorMembershipTarget(envelope, participant.key);
2476
+ const membership = actorMembershipTarget(envelope.memberships.find((value) => value.actorKey === participant.key), this.options.localDescriptor?.(meshName));
2477
2477
  const entrySpotId = expected.allocation.objectKind === 'actor' && membership === undefined
2478
2478
  ? this.options.spotManager()?.entrySpotIdForMesh(meshName)
2479
2479
  : undefined;
@@ -2497,18 +2497,14 @@ class ZLinkHostServiceRelocationRuntime {
2497
2497
  objectGeneration: expected.objectGeneration,
2498
2498
  targetAttemptGeneration: prepare.targetAttemptGeneration,
2499
2499
  coordinatorExpectedStoreVersion: expected.storeVersion.value,
2500
- ...(membership === undefined
2501
- ? expected.allocation.objectKind === 'actor'
2500
+ ...(membership ??
2501
+ (expected.allocation.objectKind === 'actor'
2502
2502
  ? {
2503
2503
  actorSpotId: entrySpotId,
2504
2504
  actorSpotGeneration: prepare.target.nodeGeneration,
2505
2505
  actorSpotKind: contracts_1.ZLinkSpotKind.Entry
2506
2506
  }
2507
- : {}
2508
- : {
2509
- ...membership,
2510
- actorSpotKind: contracts_1.ZLinkSpotKind.User
2511
- })
2507
+ : {}))
2512
2508
  }),
2513
2509
  membershipMutation: encodeMembershipMutation(envelope.memberships, participant.key)
2514
2510
  };
@@ -2599,6 +2595,7 @@ class ZLinkHostServiceRelocationRuntime {
2599
2595
  failures.push(error);
2600
2596
  }
2601
2597
  stage.phase = 'failed';
2598
+ stage.releaseJoinAdmission();
2602
2599
  if (failures.length === 1)
2603
2600
  throw failures[0];
2604
2601
  if (failures.length > 1) {
@@ -2729,7 +2726,7 @@ class ZLinkHostServiceRelocationRuntime {
2729
2726
  return { owner, staging, target };
2730
2727
  }
2731
2728
  /** Maps schema ordinals to the authoritative Location Store inventory. */
2732
- async resolveTargetParticipantInventory(request, envelope, signal) {
2729
+ async resolveTargetParticipantInventory(meshName, request, envelope, signal) {
2733
2730
  if (!envelope.participants.some((value) => value.rootSpotId !== undefined)) {
2734
2731
  return envelope;
2735
2732
  }
@@ -2752,7 +2749,8 @@ class ZLinkHostServiceRelocationRuntime {
2752
2749
  (0, authority_key_codec_1.decodeAuthorityKey)(candidate.key).kind !== 'actor')
2753
2750
  continue;
2754
2751
  const actor = (0, actor_authority_publication_1.decodeRelocatingActorAuthorityIdentity)(candidate.snapshot.payload, candidate.snapshot.objectGeneration);
2755
- if (actor?.spotId === request.object.spotId) {
2752
+ if (actor?.spotId === request.object.spotId &&
2753
+ actor.spotGeneration === request.object.objectGeneration) {
2756
2754
  entries.push(candidate);
2757
2755
  }
2758
2756
  }
@@ -2794,20 +2792,17 @@ class ZLinkHostServiceRelocationRuntime {
2794
2792
  authorityOwnerGeneration: snapshot.authorityOwnerGeneration
2795
2793
  };
2796
2794
  });
2797
- // Actor-root saved work is admitted against the destination membership.
2798
- // The canonical root intentionally omits a membership vector; meanwhile
2799
- // Location Store still names the source Spot until target cutover. Rebuild
2800
- // the Actor lane from the already accepted ActorJoin admission, preserving
2801
- // the target queue boundary for decoded saved-work.
2795
+ // Join recovery uses its accepted target membership. Maintenance Actor
2796
+ // roots restore into the target's startup Entry incarnation (§10.1).
2802
2797
  const memberships = request.object.kind === 'actor'
2803
- ? actorJoinTargetMembership(manager, envelope.aggregateId, participants)
2798
+ ? actorRootTargetMembership(manager, envelope.aggregateId, participants, this.options.localDescriptor?.(meshName))
2804
2799
  : entries
2805
2800
  .filter((entry) => entry.snapshot.allocation.objectKind === 'actor')
2806
2801
  .map((entry) => ({
2807
2802
  actorKey: entry.key.value,
2808
2803
  spotKey: primaryKey.value,
2809
2804
  spotObjectGeneration: primary.objectGeneration,
2810
- membershipEpoch: 1n
2805
+ membershipEpoch: INITIAL_MEMBERSHIP_EPOCH
2811
2806
  }));
2812
2807
  return {
2813
2808
  ...envelope,
@@ -3002,13 +2997,13 @@ class ZLinkHostServiceRelocationRuntime {
3002
2997
  }
3003
2998
  return await send.call(node, targetNodeRid, record);
3004
2999
  }
3005
- async requestInfrastructureControl(meshName, targetNodeRid, frames, timeoutMs) {
3000
+ async requestInfrastructureControl(meshName, targetNodeRid, frames, timeoutMs, signal, onSubmitted) {
3006
3001
  const node = this.requireMeshNode(meshName);
3007
3002
  const request = node.requestInfrastructureControlFrames;
3008
3003
  if (request === undefined) {
3009
3004
  throw new Error('RouteMesh backend cannot submit bare infrastructure requests.');
3010
3005
  }
3011
- return await request.call(node, targetNodeRid, frames, { timeoutMs });
3006
+ return await request.call(node, targetNodeRid, frames, { timeoutMs, signal, onSubmitted });
3012
3007
  }
3013
3008
  }
3014
3009
  exports.ZLinkHostServiceRelocationRuntime = ZLinkHostServiceRelocationRuntime;
@@ -3025,11 +3020,24 @@ function canonicalActorJoinRecovery(participants) {
3025
3020
  function actorJoinAdmissionIdentity(envelope) {
3026
3021
  return (canonicalActorJoinRecovery(envelope.participants)?.request.handoffId ?? envelope.aggregateId);
3027
3022
  }
3028
- function actorJoinTargetMembership(manager, relocationId, participants) {
3023
+ function actorRootTargetMembership(manager, relocationId, participants, localDescriptor) {
3029
3024
  const recovery = canonicalActorJoinRecovery(participants);
3030
- const admissionId = recovery?.request.handoffId ?? relocationId;
3031
- const admission = manager?.formalRemoteActorAdmissions?.get(admissionId);
3032
3025
  const actor = participants.find((value) => value.objectKind === 'actor');
3026
+ if (recovery === undefined) {
3027
+ if (actor === undefined || localDescriptor?.entrySpotId === undefined) {
3028
+ throw new Error(`Actor relocation '${relocationId}' has no target Entry membership.`);
3029
+ }
3030
+ return [
3031
+ {
3032
+ actorKey: actor.key,
3033
+ spotKey: (0, authority_key_codec_1.encodeAuthorityKey)('user_spot', localDescriptor.entrySpotId).value,
3034
+ spotObjectGeneration: localDescriptor.lifecycleGeneration,
3035
+ membershipEpoch: INITIAL_MEMBERSHIP_EPOCH
3036
+ }
3037
+ ];
3038
+ }
3039
+ const admissionId = recovery.request.handoffId;
3040
+ const admission = manager?.formalRemoteActorAdmissions?.get(admissionId);
3033
3041
  if (admission === undefined || actor === undefined) {
3034
3042
  throw new Error(`Actor relocation '${relocationId}' has no accepted target membership.`);
3035
3043
  }
@@ -3057,12 +3065,10 @@ class LocalTargetPort {
3057
3065
  const membership = this.envelope.memberships.find((value) => value.actorKey === participant.key);
3058
3066
  if (membership === undefined)
3059
3067
  throw new Error(`Actor '${identity}' relocation membership is missing.`);
3060
- const spotIdentity = (0, authority_key_codec_1.decodeAuthorityKey)({
3061
- value: membership.spotKey
3062
- }).globalId;
3063
- const localDescriptor = this.options.localDescriptor?.(this.meshName);
3064
- const nativeEntrySpot = localDescriptor?.entrySpotId === spotIdentity;
3065
- const actor = await this.requireActorManager().prepareRelocationActor(identity, participant.stableType, participant.objectGeneration, participant.authorityOwnerGeneration + 1n, nativeEntrySpot ? undefined : spotIdentity, membership.spotObjectGeneration, membership.membershipEpoch, signal);
3068
+ const targetMembership = actorMembershipTarget(membership, this.options.localDescriptor?.(this.meshName));
3069
+ const actor = await this.requireActorManager().prepareRelocationActor(identity, participant.stableType, participant.objectGeneration, participant.authorityOwnerGeneration, targetMembership.actorSpotKind === contracts_1.ZLinkSpotKind.Entry
3070
+ ? undefined
3071
+ : targetMembership.actorSpotId, targetMembership.actorSpotGeneration, membership.membershipEpoch, signal);
3066
3072
  return {
3067
3073
  authorityKey: participant.key,
3068
3074
  participant,
@@ -3074,7 +3080,7 @@ class LocalTargetPort {
3074
3080
  };
3075
3081
  }
3076
3082
  const registration = this.registration(participant.objectKind, participant.stableType);
3077
- const activation = await this.requireSpotManager().prepareRelocationSpot(this.meshName, participant.objectKind, participant.stableType, registration.implementation, identity, participant.objectGeneration, participant.authorityOwnerGeneration + 1n, signal);
3083
+ const activation = await this.requireSpotManager().prepareRelocationSpot(this.meshName, participant.objectKind, participant.stableType, registration.implementation, identity, participant.objectGeneration, participant.authorityOwnerGeneration, signal);
3078
3084
  return {
3079
3085
  authorityKey: participant.key,
3080
3086
  participant,
@@ -3102,17 +3108,14 @@ class LocalTargetPort {
3102
3108
  async restoreMemberships(hidden, memberships) {
3103
3109
  for (const membership of memberships) {
3104
3110
  const actor = hidden.get(membership.actorKey)?.actor;
3105
- const spotIdentity = (0, authority_key_codec_1.decodeAuthorityKey)({
3106
- value: membership.spotKey
3107
- }).globalId;
3111
+ const targetMembership = actorMembershipTarget(membership, this.options.localDescriptor?.(this.meshName));
3112
+ const spotIdentity = targetMembership.actorSpotId;
3108
3113
  const spot = hidden.get(membership.spotKey)?.activation ??
3109
3114
  this.requireSpotManager().resolveRelocationActivation(this.meshName, spotIdentity);
3110
3115
  if (actor === undefined)
3111
3116
  throw new Error('Relocation membership Actor staging is missing.');
3112
3117
  const state = this.requireActorManager().getState(actor.context.actorId);
3113
- const localDescriptor = this.options.localDescriptor?.(this.meshName);
3114
- const isEntryMembership = localDescriptor?.entrySpotId === spotIdentity;
3115
- if (isEntryMembership) {
3118
+ if (targetMembership.actorSpotKind === contracts_1.ZLinkSpotKind.Entry) {
3116
3119
  // Entry Spot identity is published as a Location membership key, but
3117
3120
  // it is not a User Spot activation in the Actor runtime. The native
3118
3121
  // restore already received the target MeshNode RID as its Entry
@@ -3121,7 +3124,7 @@ class LocalTargetPort {
3121
3124
  state.clearJoinedSpot();
3122
3125
  }
3123
3126
  else {
3124
- state.setJoinedSpot(spotIdentity, spot?.spot, membership.membershipEpoch);
3127
+ state.setJoinedSpot(spotIdentity, spot?.spot, membership.membershipEpoch, membership.spotObjectGeneration);
3125
3128
  }
3126
3129
  spot?.commitActorJoin(actor);
3127
3130
  }
@@ -3227,9 +3230,9 @@ class LocalTargetPort {
3227
3230
  if (runtime === undefined) {
3228
3231
  throw new Error('Relocated Entry Spot Actor dispatch is unavailable.');
3229
3232
  }
3230
- return runtime.dispatchEntryActorPacket(hidden.actor.context.actorId, parts, returnResponse, remoteBoundSessionTarget, fallbackActorRef);
3233
+ return runtime.dispatchEntryActorPacket('remote', hidden.actor.context.actorId, parts, returnResponse, remoteBoundSessionTarget, fallbackActorRef);
3231
3234
  }
3232
- return this.requireSpotManager().dispatchRoutedActorPacket(state.spotId, hidden.actor.context.actorId, parts, returnResponse, remoteBoundSessionTarget, fallbackActorRef);
3235
+ return this.requireSpotManager().dispatchRoutedActorPacket('remote', state.spotId, hidden.actor.context.actorId, parts, returnResponse, remoteBoundSessionTarget, fallbackActorRef);
3233
3236
  });
3234
3237
  hidden.replayResults.push(...results);
3235
3238
  }
@@ -3311,13 +3314,14 @@ function rewriteAuthorityApplicationRoute(payload, target) {
3311
3314
  }
3312
3315
  return ((0, service_authority_payload_codec_1.rewriteServiceAuthorityRoute)(applicationPayload, target.owner, target) ?? applicationPayload);
3313
3316
  }
3314
- function actorMembershipTarget(envelope, actorKey) {
3315
- const membership = envelope.memberships.find((value) => value.actorKey === actorKey);
3317
+ function actorMembershipTarget(membership, localDescriptor) {
3316
3318
  if (membership === undefined)
3317
3319
  return undefined;
3320
+ const spotId = (0, authority_key_codec_1.decodeAuthorityKey)({ value: membership.spotKey }).globalId;
3318
3321
  return {
3319
- actorSpotId: (0, authority_key_codec_1.decodeAuthorityKey)({ value: membership.spotKey }).globalId,
3320
- actorSpotGeneration: membership.spotObjectGeneration
3322
+ actorSpotId: spotId,
3323
+ actorSpotGeneration: membership.spotObjectGeneration,
3324
+ actorSpotKind: spotId === localDescriptor?.entrySpotId ? contracts_1.ZLinkSpotKind.Entry : contracts_1.ZLinkSpotKind.User
3321
3325
  };
3322
3326
  }
3323
3327
  function primaryKey(envelope) {
@@ -3884,7 +3888,7 @@ function canonicalQueuedFrozenRecord(participant, message, coordinator, target)
3884
3888
  objectGeneration: participant.objectGeneration,
3885
3889
  nodeRid: target.nodeRid,
3886
3890
  nodeGeneration: target.nodeGeneration,
3887
- authorityOwnerGeneration: participant.authorityOwnerGeneration + 1n,
3891
+ authorityOwnerGeneration: participant.authorityOwnerGeneration,
3888
3892
  ownerLeaseGeneration: target.ownerLeaseGeneration
3889
3893
  },
3890
3894
  operationId,
@@ -4023,13 +4027,6 @@ function replyRelayIdentityKey(value) {
4023
4027
  function replyRelayPendingKey(ackTargetNodeRid, value) {
4024
4028
  return JSON.stringify([ackTargetNodeRid, replyRelayIdentityKey(value)]);
4025
4029
  }
4026
- function isServiceWireCommand(payload, command) {
4027
- return (payload.byteLength >= 5 &&
4028
- payload[0] === 0x5a &&
4029
- payload[1] === 0x4d &&
4030
- payload[2] === 1 &&
4031
- payload[3] === command);
4032
- }
4033
4030
  function encodeHandoffQueuedMessages(backlog) {
4034
4031
  return backlog.map((packet) => ({
4035
4032
  sequence: BigInt(packet.index) + 1n,
@@ -4102,83 +4099,50 @@ function toServiceTimer(value) {
4102
4099
  pendingTicks: value.pendingTicks
4103
4100
  };
4104
4101
  }
4105
- const PREPARE_SIDEBAND_MAGIC = 'ZLNI';
4106
- const PREPARE_SIDEBAND_VERSION = 1;
4107
- const PREPARE_SIDEBAND_HEADER_BYTES = 11;
4108
- const PREPARE_SIDEBAND_VERSION_OFFSET = 4;
4109
- const PREPARE_SIDEBAND_KEY_LENGTH_OFFSET = 5;
4110
- const PREPARE_SIDEBAND_PAYLOAD_LENGTH_OFFSET = 7;
4111
4102
  const ACTOR_SESSION_JOURNAL_VERSION = 1;
4112
4103
  const SERVICE_RELOCATION_REPLY_PACKET_NAME = 'zlink.relocation.reply';
4113
- /**
4114
- * NODE-INTERNAL Prepare sideband. Frame zero remains the exact canonical
4115
- * command-40 schema record; each following ZLNI frame carries one sealed
4116
- * actor-session journal keyed by its canonical participant authority key.
4117
- * Sessionless relocation remains a single-frame, wire-identical Prepare.
4118
- */
4119
- function encodePrepareSideband(envelope) {
4120
- return envelope.participants
4121
- .filter((participant) => participant.boundSessionState.byteLength !== 0)
4122
- .map((participant) => {
4123
- const key = Buffer.from(participant.key, 'utf8');
4124
- const payload = Buffer.from(participant.boundSessionState);
4125
- if (key.byteLength === 0 || key.byteLength > 0xffff || payload.byteLength > 0xffff_ffff) {
4126
- throw new TypeError('Bound-session relocation sideband is out of bounds.');
4127
- }
4128
- const header = Buffer.allocUnsafe(PREPARE_SIDEBAND_HEADER_BYTES);
4129
- header.write(PREPARE_SIDEBAND_MAGIC, 0, 'ascii');
4130
- header[PREPARE_SIDEBAND_VERSION_OFFSET] = PREPARE_SIDEBAND_VERSION;
4131
- header.writeUInt16BE(key.byteLength, PREPARE_SIDEBAND_KEY_LENGTH_OFFSET);
4132
- header.writeUInt32BE(payload.byteLength, PREPARE_SIDEBAND_PAYLOAD_LENGTH_OFFSET);
4133
- return Buffer.concat([header, key, payload]);
4134
- });
4135
- }
4136
- function decodePrepareSideband(frames) {
4137
- const result = [];
4138
- const keys = new Set();
4139
- for (const frame of frames) {
4140
- const bytes = Buffer.from(frame);
4141
- if (bytes.byteLength < PREPARE_SIDEBAND_HEADER_BYTES ||
4142
- bytes.subarray(0, PREPARE_SIDEBAND_VERSION_OFFSET).toString('ascii') !==
4143
- PREPARE_SIDEBAND_MAGIC ||
4144
- bytes[PREPARE_SIDEBAND_VERSION_OFFSET] !== PREPARE_SIDEBAND_VERSION) {
4145
- return undefined;
4146
- }
4147
- const keyLength = bytes.readUInt16BE(PREPARE_SIDEBAND_KEY_LENGTH_OFFSET);
4148
- const payloadLength = bytes.readUInt32BE(PREPARE_SIDEBAND_PAYLOAD_LENGTH_OFFSET);
4149
- if (PREPARE_SIDEBAND_HEADER_BYTES + keyLength + payloadLength !== bytes.byteLength ||
4150
- keyLength === 0)
4151
- return undefined;
4152
- const participantKey = bytes
4153
- .subarray(PREPARE_SIDEBAND_HEADER_BYTES, PREPARE_SIDEBAND_HEADER_BYTES + keyLength)
4154
- .toString('utf8');
4155
- if (keys.has(participantKey))
4156
- return undefined;
4157
- keys.add(participantKey);
4158
- result.push({
4159
- participantKey,
4160
- payload: Buffer.from(bytes.subarray(PREPARE_SIDEBAND_HEADER_BYTES + keyLength))
4161
- });
4162
- }
4163
- return result;
4164
- }
4165
- function attachPrepareBoundSessions(envelope, sideband) {
4166
- if (sideband === undefined || sideband.length === 0)
4167
- return envelope;
4168
- const byKey = new Map(sideband.map((value) => [value.participantKey, Buffer.from(value.payload)]));
4169
- const participants = envelope.participants.map((participant) => {
4170
- const payload = byKey.get(participant.key);
4171
- if (payload === undefined)
4172
- return participant;
4173
- if (participant.objectKind !== 'actor') {
4174
- throw new TypeError('Bound-session relocation sideband names a non-Actor participant.');
4175
- }
4176
- byKey.delete(participant.key);
4177
- return { ...participant, boundSessionState: payload };
4178
- });
4179
- if (byKey.size !== 0)
4180
- throw new TypeError('Bound-session relocation sideband names an unknown participant.');
4181
- return { ...envelope, participants };
4104
+ function attachCanonicalBoundSessions(envelope, request, meshName) {
4105
+ return {
4106
+ ...envelope,
4107
+ participants: envelope.participants.map((participant) => {
4108
+ const binding = participant.sessionBinding;
4109
+ if (binding === undefined)
4110
+ return participant;
4111
+ if (participant.objectKind !== 'actor')
4112
+ throw new TypeError('Session binding names a non-Actor participant.');
4113
+ const sessionNodeRid = (0, routing_id_1.decodeRoutingId)('', Buffer.from(binding.sessionOwnerNodeRid).toString('hex'));
4114
+ const sessionRid = (0, routing_id_1.decodeRoutingId)('', Buffer.from(binding.sessionRid).toString('hex'));
4115
+ const session = {
4116
+ sessionOwnerNodeRid: sessionNodeRid,
4117
+ sessionOwnerNodeGeneration: binding.sessionOwnerNodeGeneration,
4118
+ sessionOwnerId: binding.sessionOwnerId,
4119
+ sessionOwnerLeaseGeneration: binding.sessionOwnerLeaseGeneration,
4120
+ sessionRid: sessionRid,
4121
+ bindingGeneration: binding.bindingGeneration
4122
+ };
4123
+ const target = {
4124
+ routerChannelId: meshName,
4125
+ targetNodeRid: sessionNodeRid,
4126
+ spotId: request.object.kind === 'actor'
4127
+ ? (participant.rootSpotId ?? '')
4128
+ : request.object.spotId,
4129
+ sessionNodeRid,
4130
+ sessionRid,
4131
+ sessionOwnerNodeGeneration: binding.sessionOwnerNodeGeneration,
4132
+ sessionOwnerId: binding.sessionOwnerId,
4133
+ sessionOwnerLeaseGeneration: binding.sessionOwnerLeaseGeneration,
4134
+ bindingGeneration: binding.bindingGeneration,
4135
+ previousAuthorityOwnerGeneration: participant.authorityOwnerGeneration,
4136
+ relocationSealId: envelope.aggregateId,
4137
+ serviceWireRelocation: {
4138
+ relocation: request.relocation,
4139
+ coordinator: request.coordinator,
4140
+ session
4141
+ }
4142
+ };
4143
+ return { ...participant, boundSessionState: encodeActorSession(target) };
4144
+ })
4145
+ };
4182
4146
  }
4183
4147
  function encodeActorSession(target) {
4184
4148
  if (target === undefined)
@@ -4189,7 +4153,11 @@ function encodeActorSession(target) {
4189
4153
  targetNodeRid: String(target.targetNodeRid),
4190
4154
  spotId: String(target.spotId),
4191
4155
  sessionNodeRid: target.sessionNodeRid === undefined ? undefined : String(target.sessionNodeRid),
4156
+ sessionNodeRidHex: target.sessionNodeRid === undefined
4157
+ ? undefined
4158
+ : (0, routing_id_1.encodeRoutingIdStorageHex)(target.sessionNodeRid),
4192
4159
  sessionRid: target.sessionRid === undefined ? undefined : String(target.sessionRid),
4160
+ sessionRidHex: target.sessionRid === undefined ? undefined : (0, routing_id_1.encodeRoutingIdStorageHex)(target.sessionRid),
4193
4161
  sessionOwnerNodeGeneration: target.sessionOwnerNodeGeneration?.toString(),
4194
4162
  sessionOwnerId: target.sessionOwnerId,
4195
4163
  sessionOwnerLeaseGeneration: target.sessionOwnerLeaseGeneration?.toString(),
@@ -4208,10 +4176,12 @@ function encodeActorSession(target) {
4208
4176
  coordinatorNodeGeneration: target.serviceWireRelocation.coordinator.nodeGeneration.toString(),
4209
4177
  expectedAuthorityStoreVersion: target.serviceWireRelocation.coordinator.expectedAuthorityStoreVersion,
4210
4178
  sessionOwnerNodeRid: target.serviceWireRelocation.session.sessionOwnerNodeRid,
4179
+ sessionOwnerNodeRidHex: (0, routing_id_1.encodeRoutingIdStorageHex)(target.serviceWireRelocation.session.sessionOwnerNodeRid),
4211
4180
  sessionOwnerNodeGeneration: target.serviceWireRelocation.session.sessionOwnerNodeGeneration.toString(),
4212
4181
  sessionOwnerId: target.serviceWireRelocation.session.sessionOwnerId,
4213
4182
  sessionOwnerLeaseGeneration: target.serviceWireRelocation.session.sessionOwnerLeaseGeneration.toString(),
4214
4183
  sessionRid: target.serviceWireRelocation.session.sessionRid,
4184
+ sessionRidHex: (0, routing_id_1.encodeRoutingIdStorageHex)(target.serviceWireRelocation.session.sessionRid),
4215
4185
  bindingGeneration: target.serviceWireRelocation.session.bindingGeneration.toString()
4216
4186
  }
4217
4187
  }), 'utf8');
@@ -4233,9 +4203,11 @@ function decodeActorSession(payload) {
4233
4203
  targetNodeRid: value.targetNodeRid,
4234
4204
  spotId: value.spotId,
4235
4205
  ...(typeof value.sessionNodeRid === 'string'
4236
- ? { sessionNodeRid: value.sessionNodeRid }
4206
+ ? { sessionNodeRid: (0, routing_id_1.decodeRoutingId)(value.sessionNodeRid, value.sessionNodeRidHex) }
4207
+ : {}),
4208
+ ...(typeof value.sessionRid === 'string'
4209
+ ? { sessionRid: (0, routing_id_1.decodeRoutingId)(value.sessionRid, value.sessionRidHex) }
4237
4210
  : {}),
4238
- ...(typeof value.sessionRid === 'string' ? { sessionRid: value.sessionRid } : {}),
4239
4211
  ...(optionalBigInt('sessionOwnerNodeGeneration') === undefined
4240
4212
  ? {}
4241
4213
  : { sessionOwnerNodeGeneration: optionalBigInt('sessionOwnerNodeGeneration') }),
@@ -4302,11 +4274,11 @@ function decodeActorSessionServiceWireFence(input) {
4302
4274
  expectedAuthorityStoreVersion: text('expectedAuthorityStoreVersion')
4303
4275
  },
4304
4276
  session: {
4305
- sessionOwnerNodeRid: text('sessionOwnerNodeRid'),
4277
+ sessionOwnerNodeRid: (0, routing_id_1.decodeRoutingId)(typeof value.sessionOwnerNodeRid === 'string' ? value.sessionOwnerNodeRid : '', value.sessionOwnerNodeRidHex),
4306
4278
  sessionOwnerNodeGeneration: positive('sessionOwnerNodeGeneration'),
4307
4279
  sessionOwnerId: text('sessionOwnerId'),
4308
4280
  sessionOwnerLeaseGeneration: positive('sessionOwnerLeaseGeneration'),
4309
- sessionRid: text('sessionRid'),
4281
+ sessionRid: (0, routing_id_1.decodeRoutingId)(typeof value.sessionRid === 'string' ? value.sessionRid : '', value.sessionRidHex),
4310
4282
  bindingGeneration: positive('bindingGeneration')
4311
4283
  }
4312
4284
  };