@zlink-systems/framework 0.30.0 → 0.30.2

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 (456) 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/ZLinkEncodedPayload.d.ts +6 -0
  6. package/dist/contracts/Common/ZLinkEncodedPayload.js +18 -3
  7. package/dist/contracts/Common/ZLinkMessageMetadata.js +11 -5
  8. package/dist/contracts/Common/encoded-payload-storage.d.ts +1 -1
  9. package/dist/contracts/Common/encoded-payload-storage.js +5 -2
  10. package/dist/contracts/Configuration/Builders.d.ts +1 -1
  11. package/dist/contracts/Configuration/RegistrationBuilderPolicy.d.ts +2 -1
  12. package/dist/contracts/Configuration/RegistrationBuilderPolicy.js +5 -1
  13. package/dist/contracts/Configuration/RegistrationBuilders.js +2 -2
  14. package/dist/contracts/Configuration/RegistrationTypes.d.ts +1 -0
  15. package/dist/contracts/Dispatch/ZLinkDispatchOptions.d.ts +2 -2
  16. package/dist/contracts/Handlers/Attributes.d.ts +5 -13
  17. package/dist/contracts/Handlers/Attributes.js +7 -11
  18. package/dist/contracts/Handlers/JsonContract.d.ts +2 -46
  19. package/dist/contracts/Handlers/JsonContract.js +4 -153
  20. package/dist/contracts/Locations/Rows.d.ts +2 -0
  21. package/dist/contracts/Spots/Contracts.d.ts +6 -1
  22. package/dist/contracts/Spots/ZLinkSpot.d.ts +3 -3
  23. package/dist/nest-integration.d.ts +1 -1
  24. package/dist/nest-integration.js +2 -1
  25. package/dist/runtime/abort.d.ts +5 -0
  26. package/dist/runtime/abort.js +10 -0
  27. package/dist/runtime/actors/actor-authority-publication.js +3 -2
  28. package/dist/runtime/actors/actor-client.d.ts +1 -2
  29. package/dist/runtime/actors/actor-client.js +52 -57
  30. package/dist/runtime/actors/actor-context.d.ts +2 -0
  31. package/dist/runtime/actors/actor-context.js +46 -9
  32. package/dist/runtime/actors/actor-handoff.d.ts +8 -4
  33. package/dist/runtime/actors/actor-handoff.js +219 -92
  34. package/dist/runtime/actors/actor-join-relocation.d.ts +3 -0
  35. package/dist/runtime/actors/actor-local-native-join.js +13 -12
  36. package/dist/runtime/actors/actor-mailbox.js +27 -1
  37. package/dist/runtime/actors/actor-remote-joiner.js +3 -1
  38. package/dist/runtime/actors/actor-remote-wire.js +15 -0
  39. package/dist/runtime/actors/actor-reply.d.ts +4 -0
  40. package/dist/runtime/actors/actor-reply.js +29 -0
  41. package/dist/runtime/actors/actor-routed-join-transport.d.ts +6 -2
  42. package/dist/runtime/actors/actor-routed-json-request.d.ts +2 -0
  43. package/dist/runtime/actors/actor-runtime-contracts.d.ts +2 -0
  44. package/dist/runtime/actors/actor-runtime-state.js +2 -20
  45. package/dist/runtime/actors/actor-source-transfer.d.ts +1 -17
  46. package/dist/runtime/actors/index.d.ts +8 -3
  47. package/dist/runtime/actors/index.js +55 -27
  48. package/dist/runtime/actors/session-disconnected-wire.d.ts +8 -0
  49. package/dist/runtime/actors/session-disconnected-wire.js +48 -0
  50. package/dist/runtime/actors/spot-actor-dispatch.js +2 -2
  51. package/dist/runtime/admission.d.ts +9 -1
  52. package/dist/runtime/admission.js +56 -23
  53. package/dist/runtime/application-jobs/application-ingress-record-owner.d.ts +6 -8
  54. package/dist/runtime/application-jobs/application-ingress-record-owner.js +39 -22
  55. package/dist/runtime/application-jobs/application-job-queue-scope.d.ts +15 -1
  56. package/dist/runtime/application-jobs/application-job-queue-scope.js +61 -20
  57. package/dist/runtime/application-jobs/contracts.d.ts +12 -1
  58. package/dist/runtime/backend/contracts/index.d.ts +37 -12
  59. package/dist/runtime/backend/mesh-actor-session-node-adapter.js +2 -2
  60. package/dist/runtime/backend/mesh-completion-table.d.ts +9 -1
  61. package/dist/runtime/backend/mesh-completion-table.js +154 -49
  62. package/dist/runtime/backend/mesh-dispatch-pump.d.ts +28 -1
  63. package/dist/runtime/backend/mesh-dispatch-pump.js +208 -101
  64. package/dist/runtime/backend/node/node-backend-adapter-support.d.ts +2 -2
  65. package/dist/runtime/backend/node/node-backend-adapter-support.js +16 -9
  66. package/dist/runtime/backend/node/node-dealer-channel-client-transport.d.ts +1 -1
  67. package/dist/runtime/backend/node/node-dealer-channel-client-transport.js +5 -2
  68. package/dist/runtime/backend/node/node-raw-binding-port.js +124 -72
  69. package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +46 -13
  70. package/dist/runtime/backend/node/node-raw-mesh-backend.js +181 -164
  71. package/dist/runtime/backend/node/node-socket-backend-adapter.d.ts +1 -1
  72. package/dist/runtime/backend/node/node-socket-backend-adapter.js +11 -11
  73. package/dist/runtime/backend/raw-binding-port.d.ts +2 -2
  74. package/dist/runtime/backend/runtime-message.d.ts +1 -0
  75. package/dist/runtime/backend/runtime-message.js +5 -0
  76. package/dist/runtime/backend/runtime-values.d.ts +1 -0
  77. package/dist/runtime/backend/runtime-values.js +2 -1
  78. package/dist/runtime/channels/channel-clients.d.ts +2 -0
  79. package/dist/runtime/channels/channel-clients.js +75 -23
  80. package/dist/runtime/channels/channel-dispatch-pipeline.d.ts +25 -5
  81. package/dist/runtime/channels/channel-dispatch-pipeline.js +111 -56
  82. package/dist/runtime/channels/channel-dispatch-services.d.ts +1 -0
  83. package/dist/runtime/channels/channel-dispatch-services.js +45 -0
  84. package/dist/runtime/channels/channel-dispatchers.d.ts +4 -3
  85. package/dist/runtime/channels/channel-dispatchers.js +62 -54
  86. package/dist/runtime/channels/channel-envelope-inspection.d.ts +1 -2
  87. package/dist/runtime/channels/channel-envelope-inspection.js +1 -16
  88. package/dist/runtime/channels/channel-envelope.d.ts +2 -0
  89. package/dist/runtime/channels/channel-envelope.js +146 -28
  90. package/dist/runtime/channels/channel-outbound-operations.d.ts +2 -2
  91. package/dist/runtime/channels/channel-outbound-operations.js +8 -8
  92. package/dist/runtime/channels/channel-runtime-lifecycle.d.ts +4 -3
  93. package/dist/runtime/channels/channel-runtime-lifecycle.js +19 -24
  94. package/dist/runtime/channels/channel-runtime-manager.d.ts +9 -8
  95. package/dist/runtime/channels/channel-runtime-manager.js +16 -16
  96. package/dist/runtime/channels/channel-transports.d.ts +18 -16
  97. package/dist/runtime/channels/channel-transports.js +77 -58
  98. package/dist/runtime/channels/client-server-location-runtime.js +5 -4
  99. package/dist/runtime/channels/dispatch-error-reporter.d.ts +2 -1
  100. package/dist/runtime/channels/dispatch-error-reporter.js +2 -1
  101. package/dist/runtime/channels/fanout-location-runtime.d.ts +1 -1
  102. package/dist/runtime/channels/fanout-location-runtime.js +3 -3
  103. package/dist/runtime/channels/local-spot-route-transport.d.ts +1 -1
  104. package/dist/runtime/channels/local-spot-route-transport.js +2 -1
  105. package/dist/runtime/channels/router-socket-spot-route-transport.d.ts +2 -2
  106. package/dist/runtime/channels/router-socket-spot-route-transport.js +4 -4
  107. package/dist/runtime/channels/source-spot-router.d.ts +2 -2
  108. package/dist/runtime/channels/source-spot-router.js +4 -4
  109. package/dist/runtime/channels/spot-node-route-transport.d.ts +2 -2
  110. package/dist/runtime/channels/spot-node-route-transport.js +4 -4
  111. package/dist/runtime/channels/spot-route-bridge-transport.d.ts +2 -2
  112. package/dist/runtime/channels/spot-route-bridge-transport.js +4 -4
  113. package/dist/runtime/channels/spot-route-dispatch-strategy.d.ts +5 -4
  114. package/dist/runtime/channels/spot-route-dispatch-strategy.js +18 -18
  115. package/dist/runtime/diagnostics/flow-context.js +19 -7
  116. package/dist/runtime/diagnostics/index.js +4 -9
  117. package/dist/runtime/diagnostics/message-flow.d.ts +8 -0
  118. package/dist/runtime/diagnostics/message-flow.js +35 -5
  119. package/dist/runtime/diagnostics/runtime-metrics.d.ts +2 -2
  120. package/dist/runtime/diagnostics/runtime-metrics.js +10 -8
  121. package/dist/runtime/execution/index.d.ts +4 -2
  122. package/dist/runtime/execution/index.js +33 -10
  123. package/dist/runtime/execution/serial-execution-queue.d.ts +5 -0
  124. package/dist/runtime/execution/serial-execution-queue.js +22 -2
  125. package/dist/runtime/execution/state-lane.d.ts +2 -0
  126. package/dist/runtime/execution/state-lane.js +5 -0
  127. package/dist/runtime/foundation/actor-join-recovery-codec.js +2 -2
  128. package/dist/runtime/foundation/durable-service-request.d.ts +14 -0
  129. package/dist/runtime/foundation/durable-service-request.js +98 -0
  130. package/dist/runtime/foundation/operation-identity.d.ts +1 -0
  131. package/dist/runtime/foundation/operation-identity.js +5 -1
  132. package/dist/runtime/foundation/operation-registry.d.ts +25 -1
  133. package/dist/runtime/foundation/operation-registry.js +86 -18
  134. package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +61 -8
  135. package/dist/runtime/foundation/raw-service-mesh-runtime.js +486 -266
  136. package/dist/runtime/foundation/service-liveness-registry.d.ts +12 -1
  137. package/dist/runtime/foundation/service-liveness-registry.js +38 -0
  138. package/dist/runtime/foundation/service-mailbox.d.ts +7 -0
  139. package/dist/runtime/foundation/service-maintenance-runtime.js +1 -6
  140. package/dist/runtime/foundation/service-relocation-object-owner.d.ts +3 -3
  141. package/dist/runtime/foundation/service-relocation-object-owner.js +48 -34
  142. package/dist/runtime/foundation/service-relocation-runtime.d.ts +2 -0
  143. package/dist/runtime/foundation/service-relocation-runtime.js +20 -4
  144. package/dist/runtime/foundation/service-runtime-contracts.d.ts +10 -1
  145. package/dist/runtime/foundation/service-session-binding-ingress-port.d.ts +2 -1
  146. package/dist/runtime/foundation/service-stateful-registry.d.ts +5 -4
  147. package/dist/runtime/foundation/service-stateful-registry.js +24 -26
  148. package/dist/runtime/foundation/service-stateful-runtime.d.ts +75 -9
  149. package/dist/runtime/foundation/service-stateful-runtime.js +486 -218
  150. package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +14 -6
  151. package/dist/runtime/foundation/service-stateful-wire-codec.js +48 -27
  152. package/dist/runtime/foundation/service-topology-registry.d.ts +12 -2
  153. package/dist/runtime/foundation/service-topology-registry.js +61 -27
  154. package/dist/runtime/foundation/service-wire-binary-primitives.d.ts +6 -1
  155. package/dist/runtime/foundation/service-wire-binary-primitives.js +27 -11
  156. package/dist/runtime/foundation/service-wire-constants.generated.d.ts +1 -0
  157. package/dist/runtime/foundation/service-wire-constants.generated.js +1 -0
  158. package/dist/runtime/foundation/service-wire-m6a-codec.d.ts +13 -3
  159. package/dist/runtime/foundation/service-wire-m6a-codec.js +189 -78
  160. package/dist/runtime/handlers/handler-instance-scope.d.ts +8 -0
  161. package/dist/runtime/handlers/handler-instance-scope.js +54 -11
  162. package/dist/runtime/host/actor-packet-relay.d.ts +6 -4
  163. package/dist/runtime/host/actor-packet-relay.js +59 -72
  164. package/dist/runtime/host/actor-placement-coordinator.js +25 -8
  165. package/dist/runtime/host/actor-runtime-options-factory.js +2 -2
  166. package/dist/runtime/host/actor-transfer-runtime.d.ts +7 -31
  167. package/dist/runtime/host/actor-transfer-runtime.js +85 -331
  168. package/dist/runtime/host/application-job-queue.d.ts +40 -7
  169. package/dist/runtime/host/application-job-queue.js +137 -42
  170. package/dist/runtime/host/entry-actor-runtime.d.ts +1 -0
  171. package/dist/runtime/host/entry-actor-runtime.js +3 -0
  172. package/dist/runtime/host/index.d.ts +12 -2
  173. package/dist/runtime/host/index.js +300 -202
  174. package/dist/runtime/host/location-runtime-owner.js +2 -6
  175. package/dist/runtime/host/mesh-router-resolver.d.ts +4 -0
  176. package/dist/runtime/host/mesh-router-resolver.js +14 -6
  177. package/dist/runtime/host/remote-bound-session-relay.d.ts +2 -4
  178. package/dist/runtime/host/remote-bound-session-relay.js +73 -208
  179. package/dist/runtime/host/route-mesh-runtime.d.ts +2 -2
  180. package/dist/runtime/host/route-mesh-runtime.js +6 -4
  181. package/dist/runtime/host/runtime-shutdown.d.ts +1 -0
  182. package/dist/runtime/host/runtime-shutdown.js +3 -2
  183. package/dist/runtime/host/service-relocation-control.d.ts +1 -0
  184. package/dist/runtime/host/service-relocation-control.js +10 -4
  185. package/dist/runtime/host/service-relocation-host-runtime.d.ts +22 -14
  186. package/dist/runtime/host/service-relocation-host-runtime.js +754 -599
  187. package/dist/runtime/host/spot-address-transport.js +3 -2
  188. package/dist/runtime/host/spot-runtime-options-factory.js +16 -7
  189. package/dist/runtime/host/user-spot-creation-coordinator.js +33 -84
  190. package/dist/runtime/locations/actor-location-claims.d.ts +2 -2
  191. package/dist/runtime/locations/actor-location-claims.js +34 -19
  192. package/dist/runtime/locations/auto-connect-loop.d.ts +2 -0
  193. package/dist/runtime/locations/auto-connect-loop.js +22 -14
  194. package/dist/runtime/locations/auto-connect-reconciler.js +0 -6
  195. package/dist/runtime/locations/auto-connect-types.d.ts +0 -1
  196. package/dist/runtime/locations/descriptor-publication.d.ts +4 -0
  197. package/dist/runtime/locations/descriptor-publication.js +11 -0
  198. package/dist/runtime/locations/domain-store-contract.d.ts +1 -0
  199. package/dist/runtime/locations/in-memory-authority-store.d.ts +7 -1
  200. package/dist/runtime/locations/in-memory-authority-store.js +56 -19
  201. package/dist/runtime/locations/in-memory-location-store.js +1 -10
  202. package/dist/runtime/locations/index.d.ts +1 -0
  203. package/dist/runtime/locations/index.js +1 -0
  204. package/dist/runtime/locations/lease-tracker.js +1 -6
  205. package/dist/runtime/locations/lifecycle.d.ts +1 -2
  206. package/dist/runtime/locations/lifecycle.js +2 -5
  207. package/dist/runtime/locations/location-store-repository.d.ts +51 -1
  208. package/dist/runtime/locations/location-store-repository.js +363 -139
  209. package/dist/runtime/locations/relocation-blob.d.ts +18 -1
  210. package/dist/runtime/locations/relocation-blob.js +52 -1
  211. package/dist/runtime/locations/request-source-resolver.d.ts +37 -0
  212. package/dist/runtime/locations/request-source-resolver.js +80 -0
  213. package/dist/runtime/locations/resolvers.js +1 -1
  214. package/dist/runtime/locations/runtime.d.ts +7 -3
  215. package/dist/runtime/locations/runtime.js +61 -53
  216. package/dist/runtime/messaging/framework-json-v1.d.ts +4 -6
  217. package/dist/runtime/messaging/framework-json-v1.js +38 -294
  218. package/dist/runtime/messaging/packet-name.d.ts +1 -1
  219. package/dist/runtime/messaging/packet-name.js +8 -24
  220. package/dist/runtime/messaging/payload-codec.d.ts +7 -1
  221. package/dist/runtime/messaging/payload-codec.js +7 -6
  222. package/dist/runtime/messaging/request-result.d.ts +2 -0
  223. package/dist/runtime/messaging/request-result.js +57 -0
  224. package/dist/runtime/messaging/submission-result.d.ts +1 -0
  225. package/dist/runtime/messaging/submission-result.js +5 -2
  226. package/dist/runtime/protocol/service_wire_codec.generated.d.ts +34 -1
  227. package/dist/runtime/protocol/service_wire_codec.generated.js +229 -0
  228. package/dist/runtime/protocol/service_wire_pilot_codec.generated.d.ts +16 -1
  229. package/dist/runtime/protocol/service_wire_pilot_codec.generated.js +37 -8
  230. package/dist/runtime/spots/formal-remote-actor-admission-registry.d.ts +7 -2
  231. package/dist/runtime/spots/formal-remote-actor-admission-registry.js +36 -21
  232. package/dist/runtime/spots/index.d.ts +21 -11
  233. package/dist/runtime/spots/index.js +243 -178
  234. package/dist/runtime/spots/spot-activation-registry.d.ts +4 -2
  235. package/dist/runtime/spots/spot-activation-registry.js +21 -11
  236. package/dist/runtime/spots/spot-activation-state.d.ts +1 -1
  237. package/dist/runtime/spots/spot-activation-state.js +7 -7
  238. package/dist/runtime/spots/spot-activation.d.ts +7 -3
  239. package/dist/runtime/spots/spot-activation.js +140 -52
  240. package/dist/runtime/spots/spot-actor-admission-coordinator.d.ts +1 -0
  241. package/dist/runtime/spots/spot-actor-admission-coordinator.js +13 -22
  242. package/dist/runtime/spots/spot-actor-membership.d.ts +0 -1
  243. package/dist/runtime/spots/spot-actor-membership.js +0 -8
  244. package/dist/runtime/spots/spot-actor-packet-dispatch.js +33 -8
  245. package/dist/runtime/spots/spot-actor-packet-drain.js +5 -33
  246. package/dist/runtime/spots/spot-entry-activation.d.ts +2 -0
  247. package/dist/runtime/spots/spot-entry-activation.js +20 -11
  248. package/dist/runtime/spots/spot-handler-registry.d.ts +7 -4
  249. package/dist/runtime/spots/spot-handler-registry.js +24 -10
  250. package/dist/runtime/spots/spot-manager-internal-contracts.d.ts +2 -2
  251. package/dist/runtime/spots/spot-manager-public.js +2 -2
  252. package/dist/runtime/spots/spot-node-autoconnect.d.ts +2 -1
  253. package/dist/runtime/spots/spot-node-autoconnect.js +22 -42
  254. package/dist/runtime/spots/spot-node-runtime-manager.d.ts +19 -2
  255. package/dist/runtime/spots/spot-node-runtime-manager.js +115 -50
  256. package/dist/runtime/spots/spot-outbound.d.ts +3 -0
  257. package/dist/runtime/spots/spot-outbound.js +27 -18
  258. package/dist/runtime/spots/spot-remote-codec.js +5 -1
  259. package/dist/runtime/spots/spot-routed-spot-packet-dispatch.d.ts +1 -0
  260. package/dist/runtime/spots/spot-routed-spot-packet-dispatch.js +1 -1
  261. package/dist/runtime/spots/spot-runtime-ports.d.ts +1 -1
  262. package/dist/runtime/spots/spot-serial-executor.d.ts +10 -0
  263. package/dist/runtime/spots/spot-serial-executor.js +61 -8
  264. package/dist/runtime/spots/spot-serial-turn-executor.js +19 -2
  265. package/dist/runtime/spots/spot-subscription-dispatch.js +1 -4
  266. package/dist/runtime/spots/spot-timer.d.ts +57 -5
  267. package/dist/runtime/spots/spot-timer.js +288 -103
  268. package/dist/runtime/streams/actor-session-binding-registry.d.ts +42 -11
  269. package/dist/runtime/streams/actor-session-binding-registry.js +165 -48
  270. package/dist/runtime/streams/actor-session-binding-runtime-owner.d.ts +8 -4
  271. package/dist/runtime/streams/bound-actor-relay-sender.d.ts +2 -1
  272. package/dist/runtime/streams/bound-actor-relay-sender.js +15 -8
  273. package/dist/runtime/streams/bound-session-service.d.ts +1 -1
  274. package/dist/runtime/streams/bound-session-service.js +6 -11
  275. package/dist/runtime/streams/index.d.ts +3 -2
  276. package/dist/runtime/streams/index.js +6 -4
  277. package/dist/runtime/streams/managed-stream.js +3 -2
  278. package/dist/runtime/streams/native-fallback-bound-session.js +8 -73
  279. package/dist/runtime/streams/session-actor-coordinator.d.ts +2 -8
  280. package/dist/runtime/streams/session-actor-coordinator.js +15 -32
  281. package/dist/runtime/streams/stream-binding-runtime-ports.d.ts +3 -10
  282. package/dist/runtime/streams/stream-session-runtime.d.ts +1 -1
  283. package/dist/runtime/streams/stream-session-runtime.js +14 -31
  284. package/dist/runtime/workers/index.js +1 -1
  285. package/package.json +3 -3
  286. package/src/contracts/Actors/ZLinkActorClient.ts +2 -1
  287. package/src/contracts/Channels/Calls.ts +2 -1
  288. package/src/contracts/Common/ZLinkEncodedPayload.ts +24 -4
  289. package/src/contracts/Common/ZLinkMessageMetadata.ts +13 -8
  290. package/src/contracts/Common/encoded-payload-storage.ts +6 -3
  291. package/src/contracts/Configuration/Builders.ts +4 -1
  292. package/src/contracts/Configuration/RegistrationBuilderPolicy.ts +7 -2
  293. package/src/contracts/Configuration/RegistrationBuilders.ts +6 -2
  294. package/src/contracts/Configuration/RegistrationTypes.ts +1 -0
  295. package/src/contracts/Dispatch/ZLinkDispatchOptions.ts +2 -1
  296. package/src/contracts/Handlers/Attributes.ts +14 -21
  297. package/src/contracts/Handlers/JsonContract.ts +8 -216
  298. package/src/contracts/Locations/Rows.ts +2 -0
  299. package/src/contracts/Spots/Contracts.ts +10 -1
  300. package/src/contracts/Spots/ZLinkSpot.ts +3 -3
  301. package/src/nest-integration.ts +1 -0
  302. package/src/runtime/abort.ts +12 -0
  303. package/src/runtime/actors/actor-authority-publication.ts +3 -2
  304. package/src/runtime/actors/actor-client.ts +100 -85
  305. package/src/runtime/actors/actor-context.ts +49 -9
  306. package/src/runtime/actors/actor-handoff.ts +291 -110
  307. package/src/runtime/actors/actor-join-relocation.ts +3 -0
  308. package/src/runtime/actors/actor-local-native-join.ts +21 -26
  309. package/src/runtime/actors/actor-mailbox.ts +40 -2
  310. package/src/runtime/actors/actor-remote-joiner.ts +6 -1
  311. package/src/runtime/actors/actor-remote-wire.ts +17 -0
  312. package/src/runtime/actors/actor-reply.ts +42 -0
  313. package/src/runtime/actors/actor-routed-join-transport.ts +14 -4
  314. package/src/runtime/actors/actor-routed-json-request.ts +10 -2
  315. package/src/runtime/actors/actor-runtime-contracts.ts +2 -0
  316. package/src/runtime/actors/actor-runtime-state.ts +2 -20
  317. package/src/runtime/actors/actor-source-transfer.ts +1 -34
  318. package/src/runtime/actors/index.ts +60 -32
  319. package/src/runtime/actors/session-disconnected-wire.ts +66 -0
  320. package/src/runtime/actors/spot-actor-dispatch.ts +4 -2
  321. package/src/runtime/admission.ts +69 -21
  322. package/src/runtime/application-jobs/application-ingress-record-owner.ts +41 -25
  323. package/src/runtime/application-jobs/application-job-queue-scope.ts +83 -22
  324. package/src/runtime/application-jobs/contracts.ts +16 -1
  325. package/src/runtime/backend/contracts/index.ts +92 -18
  326. package/src/runtime/backend/mesh-actor-session-node-adapter.ts +5 -3
  327. package/src/runtime/backend/mesh-completion-table.ts +160 -57
  328. package/src/runtime/backend/mesh-dispatch-pump.ts +237 -108
  329. package/src/runtime/backend/node/node-backend-adapter-support.ts +17 -8
  330. package/src/runtime/backend/node/node-dealer-channel-client-transport.ts +12 -2
  331. package/src/runtime/backend/node/node-raw-binding-port.ts +148 -85
  332. package/src/runtime/backend/node/node-raw-mesh-backend.ts +315 -201
  333. package/src/runtime/backend/node/node-socket-backend-adapter.ts +26 -11
  334. package/src/runtime/backend/raw-binding-port.ts +7 -2
  335. package/src/runtime/backend/runtime-message.ts +6 -0
  336. package/src/runtime/backend/runtime-values.ts +1 -0
  337. package/src/runtime/channels/channel-clients.ts +132 -58
  338. package/src/runtime/channels/channel-dispatch-pipeline.ts +198 -114
  339. package/src/runtime/channels/channel-dispatch-services.ts +69 -1
  340. package/src/runtime/channels/channel-dispatchers.ts +136 -90
  341. package/src/runtime/channels/channel-envelope-inspection.ts +2 -16
  342. package/src/runtime/channels/channel-envelope.ts +225 -31
  343. package/src/runtime/channels/channel-outbound-operations.ts +22 -8
  344. package/src/runtime/channels/channel-runtime-lifecycle.ts +13 -13
  345. package/src/runtime/channels/channel-runtime-manager.ts +41 -17
  346. package/src/runtime/channels/channel-transports.ts +171 -112
  347. package/src/runtime/channels/client-server-location-runtime.ts +11 -10
  348. package/src/runtime/channels/dispatch-error-reporter.ts +4 -2
  349. package/src/runtime/channels/fanout-location-runtime.ts +17 -9
  350. package/src/runtime/channels/local-spot-route-transport.ts +3 -1
  351. package/src/runtime/channels/router-socket-spot-route-transport.ts +13 -4
  352. package/src/runtime/channels/source-spot-router.ts +8 -4
  353. package/src/runtime/channels/spot-node-route-transport.ts +8 -4
  354. package/src/runtime/channels/spot-route-bridge-transport.ts +6 -4
  355. package/src/runtime/channels/spot-route-dispatch-strategy.ts +47 -18
  356. package/src/runtime/diagnostics/flow-context.ts +20 -7
  357. package/src/runtime/diagnostics/index.ts +1 -7
  358. package/src/runtime/diagnostics/message-flow.ts +47 -9
  359. package/src/runtime/diagnostics/runtime-metrics.ts +12 -10
  360. package/src/runtime/execution/index.ts +40 -14
  361. package/src/runtime/execution/serial-execution-queue.ts +33 -4
  362. package/src/runtime/execution/state-lane.ts +7 -0
  363. package/src/runtime/foundation/actor-join-recovery-codec.ts +2 -2
  364. package/src/runtime/foundation/durable-service-request.ts +137 -0
  365. package/src/runtime/foundation/operation-identity.ts +5 -1
  366. package/src/runtime/foundation/operation-registry.ts +98 -20
  367. package/src/runtime/foundation/raw-service-mesh-runtime.ts +704 -336
  368. package/src/runtime/foundation/service-liveness-registry.ts +39 -0
  369. package/src/runtime/foundation/service-mailbox.ts +8 -0
  370. package/src/runtime/foundation/service-maintenance-runtime.ts +1 -8
  371. package/src/runtime/foundation/service-relocation-object-owner.ts +55 -36
  372. package/src/runtime/foundation/service-relocation-runtime.ts +25 -4
  373. package/src/runtime/foundation/service-runtime-contracts.ts +19 -2
  374. package/src/runtime/foundation/service-session-binding-ingress-port.ts +2 -1
  375. package/src/runtime/foundation/service-stateful-registry.ts +38 -35
  376. package/src/runtime/foundation/service-stateful-runtime.ts +732 -275
  377. package/src/runtime/foundation/service-stateful-wire-codec.ts +49 -16
  378. package/src/runtime/foundation/service-topology-registry.ts +91 -36
  379. package/src/runtime/foundation/service-wire-binary-primitives.ts +35 -12
  380. package/src/runtime/foundation/service-wire-constants.generated.ts +1 -0
  381. package/src/runtime/foundation/service-wire-m6a-codec.ts +231 -76
  382. package/src/runtime/handlers/handler-instance-scope.ts +67 -16
  383. package/src/runtime/host/actor-packet-relay.ts +113 -94
  384. package/src/runtime/host/actor-placement-coordinator.ts +31 -8
  385. package/src/runtime/host/actor-runtime-options-factory.ts +13 -2
  386. package/src/runtime/host/actor-transfer-runtime.ts +104 -430
  387. package/src/runtime/host/application-job-queue.ts +160 -41
  388. package/src/runtime/host/entry-actor-runtime.ts +4 -0
  389. package/src/runtime/host/index.ts +473 -271
  390. package/src/runtime/host/location-runtime-owner.ts +2 -6
  391. package/src/runtime/host/mesh-router-resolver.ts +13 -5
  392. package/src/runtime/host/remote-bound-session-relay.ts +88 -271
  393. package/src/runtime/host/route-mesh-runtime.ts +12 -6
  394. package/src/runtime/host/runtime-shutdown.ts +15 -4
  395. package/src/runtime/host/service-relocation-control.ts +11 -5
  396. package/src/runtime/host/service-relocation-host-runtime.ts +1092 -759
  397. package/src/runtime/host/spot-address-transport.ts +4 -2
  398. package/src/runtime/host/spot-runtime-options-factory.ts +20 -7
  399. package/src/runtime/host/user-spot-creation-coordinator.ts +41 -100
  400. package/src/runtime/locations/actor-location-claims.ts +52 -30
  401. package/src/runtime/locations/auto-connect-loop.ts +22 -14
  402. package/src/runtime/locations/auto-connect-reconciler.ts +0 -6
  403. package/src/runtime/locations/auto-connect-types.ts +0 -1
  404. package/src/runtime/locations/descriptor-publication.ts +7 -0
  405. package/src/runtime/locations/domain-store-contract.ts +5 -0
  406. package/src/runtime/locations/in-memory-authority-store.ts +85 -23
  407. package/src/runtime/locations/in-memory-location-store.ts +1 -12
  408. package/src/runtime/locations/index.ts +1 -0
  409. package/src/runtime/locations/lease-tracker.ts +2 -9
  410. package/src/runtime/locations/lifecycle.ts +8 -26
  411. package/src/runtime/locations/location-store-repository.ts +628 -152
  412. package/src/runtime/locations/relocation-blob.ts +75 -1
  413. package/src/runtime/locations/request-source-resolver.ts +138 -0
  414. package/src/runtime/locations/resolvers.ts +2 -2
  415. package/src/runtime/locations/runtime.ts +98 -64
  416. package/src/runtime/messaging/framework-json-v1.ts +5 -325
  417. package/src/runtime/messaging/packet-name.ts +5 -25
  418. package/src/runtime/messaging/payload-codec.ts +8 -11
  419. package/src/runtime/messaging/request-result.ts +62 -0
  420. package/src/runtime/messaging/submission-result.ts +5 -1
  421. package/src/runtime/protocol/service_wire_codec.generated.ts +218 -5
  422. package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +16 -13
  423. package/src/runtime/spots/formal-remote-actor-admission-registry.ts +46 -25
  424. package/src/runtime/spots/index.ts +389 -283
  425. package/src/runtime/spots/spot-activation-registry.ts +25 -13
  426. package/src/runtime/spots/spot-activation-state.ts +12 -19
  427. package/src/runtime/spots/spot-activation.ts +198 -96
  428. package/src/runtime/spots/spot-actor-admission-coordinator.ts +25 -55
  429. package/src/runtime/spots/spot-actor-membership.ts +0 -15
  430. package/src/runtime/spots/spot-actor-packet-dispatch.ts +56 -11
  431. package/src/runtime/spots/spot-actor-packet-drain.ts +9 -52
  432. package/src/runtime/spots/spot-entry-activation.ts +33 -21
  433. package/src/runtime/spots/spot-handler-registry.ts +56 -12
  434. package/src/runtime/spots/spot-manager-internal-contracts.ts +2 -2
  435. package/src/runtime/spots/spot-manager-public.ts +2 -2
  436. package/src/runtime/spots/spot-node-autoconnect.ts +28 -47
  437. package/src/runtime/spots/spot-node-runtime-manager.ts +197 -67
  438. package/src/runtime/spots/spot-outbound.ts +39 -19
  439. package/src/runtime/spots/spot-remote-codec.ts +9 -2
  440. package/src/runtime/spots/spot-routed-spot-packet-dispatch.ts +2 -1
  441. package/src/runtime/spots/spot-runtime-ports.ts +1 -1
  442. package/src/runtime/spots/spot-serial-executor.ts +97 -25
  443. package/src/runtime/spots/spot-serial-turn-executor.ts +22 -3
  444. package/src/runtime/spots/spot-subscription-dispatch.ts +1 -4
  445. package/src/runtime/spots/spot-timer.ts +418 -158
  446. package/src/runtime/streams/actor-session-binding-registry.ts +236 -64
  447. package/src/runtime/streams/actor-session-binding-runtime-owner.ts +16 -8
  448. package/src/runtime/streams/bound-actor-relay-sender.ts +23 -9
  449. package/src/runtime/streams/bound-session-service.ts +7 -10
  450. package/src/runtime/streams/index.ts +12 -6
  451. package/src/runtime/streams/managed-stream.ts +4 -2
  452. package/src/runtime/streams/native-fallback-bound-session.ts +14 -103
  453. package/src/runtime/streams/session-actor-coordinator.ts +39 -88
  454. package/src/runtime/streams/stream-binding-runtime-ports.ts +3 -9
  455. package/src/runtime/streams/stream-session-runtime.ts +13 -34
  456. package/src/runtime/workers/index.ts +1 -1
@@ -1,3 +1,6 @@
1
+ import { routingIdsEqual } from '../../routing-id';
2
+ import { requestDurableService } from '../../foundation/durable-service-request';
3
+ import { encodeRoutingIdStorageHex, toBackendRoutingId } from '../../routing-id';
1
4
  import {
2
5
  decodeStreamWireFrame,
3
6
  decodeStreamWireHeader,
@@ -19,7 +22,11 @@ import {
19
22
  import { randomBytes } from 'node:crypto';
20
23
  import type { ZLinkMeshCompletionHandler } from '../mesh-completion-table';
21
24
  import { setImmediate as yieldToIO } from 'node:timers/promises';
22
- import { type RoutingId, ZLinkFrameworkException } from '../../../contracts';
25
+ import {
26
+ type RoutingId,
27
+ ZLinkFrameworkException,
28
+ ZLinkFrameworkErrorKind
29
+ } from '../../../contracts';
23
30
 
24
31
  import type { Message as FrameworkMessage } from '../../../contracts/Common/Message';
25
32
  import { ZLinkConfigurationException } from '../../../contracts/Configuration/ConfigurationException';
@@ -43,6 +50,8 @@ import {
43
50
  import {
44
51
  RawServiceMeshRuntime,
45
52
  RAW_MESH_RECEIVE_TIME_BUDGET_MS,
53
+ type RawServiceObservedRequest,
54
+ type RawServiceRequestObserver,
46
55
  type RawServiceRequestResult
47
56
  } from '../../foundation/raw-service-mesh-runtime';
48
57
  import type { ServiceInstanceActivationRecoveryEnvelope } from '../../foundation/service-instance-activation-recovery-codec';
@@ -80,6 +89,7 @@ import {
80
89
  type ServiceAsyncInstanceActivationAuthority,
81
90
  type ServiceInstanceApplicationLifecycle,
82
91
  type ServicePendingInstanceActivation,
92
+ type ServiceSessionOwnerDescriptors,
83
93
  type ServiceSpotMessageFollowSeal,
84
94
  type ServiceStatefulMailboxData,
85
95
  type ServiceStatefulPendingOperation,
@@ -111,9 +121,10 @@ import {
111
121
  ServiceWireFrameworkErrorCode
112
122
  } from '../../foundation/service-wire-constants.generated';
113
123
  import {
114
- APPLICATION_PAYLOAD_MINIMUM_FIELD_BYTES,
115
- APPLICATION_PAYLOAD_VERSION,
116
124
  decodeApplicationPayloadView,
125
+ decodeMultipartApplicationPayloadView,
126
+ decodeMultipartApplicationParts,
127
+ decodeMultipartParts,
117
128
  encodeMultipartApplicationPayload,
118
129
  ServiceWireProtocolError,
119
130
  type ServiceApplicationPayload
@@ -132,18 +143,20 @@ import {
132
143
  ZLinkBackendResultError,
133
144
  type ZLinkBackendMessageLike as MessageLike
134
145
  } from '../runtime-values';
135
- import { translateBindingResultError } from './node-backend-adapter-support';
136
- import { disconnectStreamPeer } from './node-socket-backend-adapter';
146
+ import { translateBindingResultError, toNativeRoutingId } from './node-backend-adapter-support';
147
+ import { disconnectSocketPeer } from './node-socket-backend-adapter';
137
148
  const DEFAULT_NATIVE_ACTIVE_CAPACITY = 10_000;
138
149
  const UNSTARTED_DIAGNOSTIC_ENDPOINT = 'inproc://not-started';
139
150
 
140
151
  const MULTIPART_PACKET_NAME = SERVICE_FRAMEWORK_MULTIPART_PACKET_NAME;
141
152
  const MULTIPART_CONTENT_TYPE = SERVICE_FRAMEWORK_MULTIPART_CONTENT_TYPE;
142
- const FATAL_UTF8 = new TextDecoder('utf-8', { fatal: true });
143
153
  const MAX_DRAIN_RECORDS = 64;
144
- // Preserve the existing route observation/admission/liveness cadence. Only the binding
145
- // readable handler admits receive work; this timer never probes the socket.
154
+ // The maintenance timer runs at the nearest management deadline and never
155
+ // sooner than this. Only the binding readable handler admits receive work;
156
+ // this timer never probes the socket.
146
157
  const MESH_BACKEND_MAINTENANCE_INTERVAL_MS = 1;
158
+ /** The longest single timer delay Node accepts. */
159
+ const MESH_BACKEND_MAINTENANCE_MAX_DELAY_MS = 2 ** 31 - 1;
147
160
  // Spec 08 §4.2 bounds the combined turn. Raw gets one equal share; stateful
148
161
  // can use the remaining turn, including time the raw registry did not consume.
149
162
  const MESH_BACKEND_RAW_MAINTENANCE_SHARE = 1 / 2;
@@ -172,7 +185,7 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
172
185
  }
173
186
  >();
174
187
  private completionHandler?: ZLinkMeshCompletionHandler;
175
- private readonly routingId: string;
188
+ readonly routingId: string;
176
189
  private readonly lifecycleGeneration: bigint;
177
190
  private bindEndpoint?: string;
178
191
  private advertiseHost?: string;
@@ -180,15 +193,17 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
180
193
  private stateful?: ServiceStatefulRuntime;
181
194
  private readyHandler?: (domains: number) => number;
182
195
  private maintenanceTimer?: NodeJS.Timeout;
183
- private pumping = false;
196
+ private maintenanceDueMs = Number.POSITIVE_INFINITY;
197
+ private pumpTask?: Promise<void>;
184
198
  private readable = 0;
185
199
  private readonly onReadable = (receiveReady: boolean, routeReady: boolean): void => {
186
200
  if (receiveReady) this.readable |= 1;
187
201
  if (routeReady) this.readable |= 2;
188
- if (!this.closed && !this.pumping) void this.pump();
202
+ this.pump();
189
203
  };
190
204
  private readonly onMaintenance = (): void => {
191
205
  this.maintenanceTimer = undefined;
206
+ this.maintenanceDueMs = Number.POSITIVE_INFINITY;
192
207
  if (this.closed) return;
193
208
  const nowMs = performance.now();
194
209
  const turnDeadlineMs = nowMs + RAW_MESH_RECEIVE_TIME_BUDGET_MS;
@@ -198,7 +213,7 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
198
213
  );
199
214
  this.stateful?.expireOperations(nowMs, turnDeadlineMs);
200
215
  this.scheduleMaintenance();
201
- void this.pump();
216
+ this.pump();
202
217
  };
203
218
  private readonly onPendingOperationsChanged = (): void => this.scheduleMaintenance();
204
219
  private nextPeerIntent = 1n;
@@ -223,6 +238,8 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
223
238
  record: import('../../foundation/service-stateful-wire-codec').ServiceMessageFollowRecord
224
239
  ) => void;
225
240
  private dispatchErrors?: ZLinkDispatchErrorReporter;
241
+ private sessionOwnerDescriptors?: ServiceSessionOwnerDescriptors;
242
+ private requestSourceAcceptance?: import('../contracts').ZLinkBackendRequestSourceAcceptance;
226
243
  private readonly peerDisconnectedHandlers = new Set<(endpoint: string) => void>();
227
244
  constructor(
228
245
  private readonly meshName: string,
@@ -279,6 +296,11 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
279
296
  this.stateful?.setDispatchErrorReporter(reporter, this.meshName);
280
297
  }
281
298
 
299
+ setSessionOwnerDescriptors(source: ServiceSessionOwnerDescriptors): void {
300
+ this.sessionOwnerDescriptors = source;
301
+ this.stateful?.setSessionOwnerDescriptors(source);
302
+ }
303
+
282
304
  setProtocolErrorHandler(
283
305
  handler: (record: {
284
306
  readonly sourceNodeRid: string;
@@ -342,7 +364,8 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
342
364
  parts: MessageLike | readonly MessageLike[],
343
365
  deadlineUnixMs: bigint,
344
366
  sourceSpotId?: string,
345
- metadata?: ReadonlyMap<string, string>
367
+ metadata?: ReadonlyMap<string, string>,
368
+ onAdmitted?: () => void
346
369
  ): MeshOperationId {
347
370
  return this.observeStateful(
348
371
  OperationKind.InstanceSpotRequest,
@@ -351,13 +374,14 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
351
374
  encodeMultipartApplicationFrame(parts),
352
375
  deadlineUnixMs,
353
376
  sourceSpotId,
354
- metadata === undefined ? undefined : encodeServiceMetadataFrame(metadata)
377
+ metadata === undefined ? undefined : encodeServiceMetadataFrame(metadata),
378
+ onAdmitted
355
379
  )
356
380
  );
357
381
  }
358
382
 
359
383
  setRoutingId(routingId: unknown): void {
360
- if (String(routingId) !== this.routingId) {
384
+ if (!routingIdsEqual(toBackendRoutingId(routingId), this.routingId)) {
361
385
  throw new Error('MeshNode routing id is immutable after construction.');
362
386
  }
363
387
  }
@@ -411,15 +435,7 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
411
435
  }
412
436
  }
413
437
  },
414
- onPeerDisconnected: (nodeRoutingId, endpoint) => {
415
- for (const [intentId, peer] of this.peerIntents) {
416
- if (
417
- peer.endpoint === endpoint &&
418
- (peer.nodeRoutingId === undefined || peer.nodeRoutingId === nodeRoutingId)
419
- ) {
420
- this.peerIntents.delete(intentId);
421
- }
422
- }
438
+ onPeerDisconnected: (_nodeRoutingId, endpoint) => {
423
439
  for (const handler of this.peerDisconnectedHandlers) handler(endpoint);
424
440
  }
425
441
  });
@@ -433,15 +449,21 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
433
449
  if (this.dispatchErrors !== undefined) {
434
450
  this.stateful.setDispatchErrorReporter(this.dispatchErrors, this.meshName);
435
451
  }
452
+ if (this.sessionOwnerDescriptors !== undefined) {
453
+ this.stateful.setSessionOwnerDescriptors(this.sessionOwnerDescriptors);
454
+ }
436
455
  if (this.mailboxRecordDropped !== undefined) {
437
456
  this.stateful.setMailboxDropHandler(this.mailboxRecordDropped);
438
457
  }
439
458
  this.stateful.setMessageFollowHandler((record) => this.messageFollowHandler?.(record));
459
+ if (this.requestSourceAcceptance !== undefined) {
460
+ this.stateful.setRequestSourceAcceptance(this.requestSourceAcceptance);
461
+ }
440
462
  this.runtime = runtime;
441
463
  try {
442
464
  runtime.setReadableHandler(this.onReadable);
443
465
  } catch (error) {
444
- this.close();
466
+ void this.close().catch((failure) => runtime.reportInfrastructureFailure(failure));
445
467
  throw error;
446
468
  }
447
469
  this.scheduleMaintenance();
@@ -465,25 +487,30 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
465
487
  return await this.requireStateful().sendMessageFollowNotification(targetNodeRid, record);
466
488
  }
467
489
 
468
- shutdown(_timeoutMs: number): RequestResultValue {
469
- this.close();
490
+ async shutdown(_timeoutMs: number): Promise<RequestResultValue> {
491
+ await this.close();
470
492
  return RequestResult.Ok;
471
493
  }
472
494
 
495
+ cancelPendingOperations(reason: unknown): void {
496
+ this.stateful?.cancelPendingOperations(reason);
497
+ this.runtime?.cancelPendingOperations(reason);
498
+ }
499
+
473
500
  async publishDraining(): Promise<void> {
474
501
  for (const name of this.channels.keys()) this.channels.set(name, 0);
475
502
  await this.requireRuntime().updateLocalDescriptor({ state: 'draining' });
476
503
  }
477
504
 
478
- close(): void {
479
- if (this.closed) return;
505
+ async close(): Promise<void> {
506
+ this.closed = true;
480
507
  if (this.maintenanceTimer !== undefined) clearTimeout(this.maintenanceTimer);
481
508
  this.maintenanceTimer = undefined;
509
+ if (this.pumpTask !== undefined) await this.pumpTask;
482
510
  this.stateful?.close();
483
511
  this.stateful = undefined;
484
512
  this.runtime?.close();
485
513
  this.runtime = undefined;
486
- this.closed = true;
487
514
  }
488
515
 
489
516
  addChannelName(name: string): void {
@@ -546,6 +573,13 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
546
573
  return intent;
547
574
  }
548
575
 
576
+ setRequestSourceAcceptance(
577
+ acceptance: import('../contracts').ZLinkBackendRequestSourceAcceptance
578
+ ): void {
579
+ this.requestSourceAcceptance = acceptance;
580
+ this.stateful?.setRequestSourceAcceptance(acceptance);
581
+ }
582
+
549
583
  expectPeer(peer: {
550
584
  readonly nodeRoutingId: string;
551
585
  readonly endpoint: string;
@@ -630,20 +664,52 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
630
664
  return this.requireRuntime().isObjectClientNodeDirectTarget(String(targetRid));
631
665
  }
632
666
 
667
+ waitForPeerRoute(
668
+ targetRid: unknown,
669
+ lifecycleGeneration: bigint,
670
+ deadlineUnixMs: bigint,
671
+ signal?: AbortSignal
672
+ ): Promise<void> {
673
+ return this.requireRuntime().waitForPeerRoute(
674
+ String(targetRid),
675
+ lifecycleGeneration,
676
+ deadlineUnixMs,
677
+ signal
678
+ );
679
+ }
680
+
681
+ observePeerRoute(targetRid: unknown) {
682
+ return this.requireRuntime().observePeerRoute(String(targetRid));
683
+ }
684
+
685
+ hasPeerRouteOrConnectionIntent(targetRid: unknown, endpoint: string): boolean {
686
+ const rid = String(targetRid);
687
+ if (this.requireRuntime().hasSelectedPeerRoute(rid)) return true;
688
+ for (const intent of this.peerIntents.values()) {
689
+ if (
690
+ intent.nodeRoutingId === rid ||
691
+ (intent.nodeRoutingId === undefined && intent.endpoint === endpoint)
692
+ )
693
+ return true;
694
+ }
695
+ return false;
696
+ }
697
+
633
698
  isPeerRouteReady(targetRid: unknown, lifecycleGeneration?: bigint): boolean {
634
699
  return this.requireRuntime().isPeerRouteReady(String(targetRid), lifecycleGeneration);
635
700
  }
636
701
 
637
- async sendToNode(
702
+ sendToNode(
638
703
  targetRid: unknown,
639
704
  parts: MessageLike | readonly MessageLike[]
640
- ): Promise<SubmitResultValue> {
641
- return (await this.requireRuntime().sendToNode(
705
+ ): SubmitResultValue | Promise<SubmitResultValue> {
706
+ const submitted = this.requireRuntime().sendToNode(
642
707
  String(targetRid),
643
708
  encodeMultipartApplicationFrame(parts)
644
- ))
645
- ? SubmitResult.Ok
646
- : SubmitResult.NotConnected;
709
+ );
710
+ return submitted instanceof Promise
711
+ ? submitted.then(nodeSendResult)
712
+ : nodeSendResult(submitted);
647
713
  }
648
714
 
649
715
  async sendInfrastructureControl(
@@ -673,26 +739,37 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
673
739
  async requestInfrastructureControlFrames(
674
740
  targetRid: unknown,
675
741
  frames: readonly Uint8Array[],
676
- options?: { readonly timeoutMs?: number }
742
+ options?: {
743
+ readonly timeoutMs?: number;
744
+ readonly signal?: AbortSignal;
745
+ readonly onSubmitted?: (signal: AbortSignal) => Promise<void>;
746
+ }
677
747
  ): Promise<readonly Uint8Array[]> {
678
- return await this.requireRuntime().requestService(
748
+ return requestDurableService(
749
+ this.requireRuntime(),
679
750
  String(targetRid),
680
- frames.map((frame) => Buffer.from(frame)),
681
- options?.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS
751
+ frames,
752
+ performance.now() + (options?.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS),
753
+ 'relocation control',
754
+ options?.signal,
755
+ options?.onSubmitted
682
756
  );
683
757
  }
684
758
 
685
759
  requestToNode(
686
760
  targetRid: unknown,
687
761
  parts: MessageLike | readonly MessageLike[],
688
- options?: { readonly timeoutMs?: number }
762
+ options?: { readonly timeoutMs?: number; readonly onAdmitted?: () => void }
689
763
  ): MeshOperationId {
690
764
  const pending = this.requireRuntime().requestToNode(
691
765
  String(targetRid),
692
766
  encodeMultipartApplicationFrame(parts),
693
- options?.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS
767
+ options?.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS,
768
+ options?.onAdmitted,
769
+ this.requestObserver,
770
+ OperationKind.NodeRequest
694
771
  );
695
- return this.observeCompletion(pending.id, OperationKind.NodeRequest, pending.promise);
772
+ return this.observedOperation(pending, OperationKind.NodeRequest);
696
773
  }
697
774
 
698
775
  async sendToChannel(
@@ -705,14 +782,17 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
705
782
  requestToChannel(
706
783
  channelName: string,
707
784
  parts: MessageLike | readonly MessageLike[],
708
- options?: { readonly timeoutMs?: number }
785
+ options?: { readonly timeoutMs?: number; readonly onAdmitted?: () => void }
709
786
  ): MeshOperationId {
710
787
  const pending = this.requireRuntime().requestToChannel(
711
788
  channelName,
712
789
  encodeMultipartApplicationFrame(parts),
713
- options?.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS
790
+ options?.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS,
791
+ options?.onAdmitted,
792
+ this.requestObserver,
793
+ OperationKind.ChannelRequest
714
794
  );
715
- return this.observeCompletion(pending.id, OperationKind.ChannelRequest, pending.promise);
795
+ return this.observedOperation(pending, OperationKind.ChannelRequest);
716
796
  }
717
797
 
718
798
  status() {
@@ -918,7 +998,8 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
918
998
  }
919
999
 
920
1000
  waitForInstanceApplicationQuiescence(spotId: string, signal?: AbortSignal): Promise<void> {
921
- return this.requireStateful().waitForInstanceApplicationQuiescence(spotId, signal);
1001
+ // Closing the stateful owner terminalizes its operations and clears these waiters.
1002
+ return this.stateful?.waitForInstanceApplicationQuiescence(spotId, signal) ?? Promise.resolve();
922
1003
  }
923
1004
 
924
1005
  restoreUserSpotAuthority(
@@ -1004,7 +1085,7 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
1004
1085
  generation: actor.generation
1005
1086
  },
1006
1087
  String(sessionNodeRid),
1007
- String(sessionRid),
1088
+ toBackendRoutingId(sessionRid),
1008
1089
  bindingGeneration
1009
1090
  );
1010
1091
  }
@@ -1136,7 +1217,7 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
1136
1217
 
1137
1218
  commitSpotMessageFollowIngress(
1138
1219
  seal: ServiceSpotMessageFollowSeal,
1139
- target: ServiceDirectSpotRouteFence,
1220
+ target: ServiceDirectSpotRouteFence | null,
1140
1221
  durationMs: number
1141
1222
  ): Promise<boolean> {
1142
1223
  return this.requireStateful().commitSpotMessageFollowIngress(seal, target, durationMs);
@@ -1173,7 +1254,8 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
1173
1254
  timeoutMs: number = DEFAULT_REQUEST_TIMEOUT_MS,
1174
1255
  sourceSpotId?: string,
1175
1256
  metadata?: ReadonlyMap<string, string>,
1176
- instanceIntent = false
1257
+ instanceIntent = false,
1258
+ onAdmitted?: () => void
1177
1259
  ): MeshOperationId {
1178
1260
  return this.observeStateful(
1179
1261
  OperationKind.InstanceSpotRequest,
@@ -1183,7 +1265,8 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
1183
1265
  timeoutMs,
1184
1266
  sourceSpotId,
1185
1267
  metadata === undefined ? undefined : encodeServiceMetadataFrame(metadata),
1186
- instanceIntent
1268
+ instanceIntent,
1269
+ onAdmitted
1187
1270
  )
1188
1271
  );
1189
1272
  }
@@ -1315,33 +1398,52 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
1315
1398
 
1316
1399
  async sendToActor(
1317
1400
  actor: ZLinkBackendActorRef,
1318
- parts: MessageLike | readonly MessageLike[]
1401
+ parts: MessageLike | readonly MessageLike[],
1402
+ options?: {
1403
+ readonly flags?: number;
1404
+ readonly routeFence?: import('../../foundation/service-stateful-wire-codec').ServiceActorRouteFence;
1405
+ }
1319
1406
  ): Promise<SubmitResultValue> {
1320
1407
  return this.requireStateful().sendToActor(
1321
1408
  actor,
1322
- this.peerGeneration(String(actor.nodeRid)),
1323
- actor.generation,
1324
- encodeMultipart(parts)
1409
+ encodeMultipart(parts),
1410
+ undefined,
1411
+ undefined,
1412
+ options?.routeFence
1325
1413
  ) as Promise<SubmitResultValue>;
1326
1414
  }
1327
1415
 
1328
1416
  requestToActor(
1329
1417
  actor: ZLinkBackendActorRef,
1330
1418
  parts: MessageLike | readonly MessageLike[],
1331
- options?: { readonly timeoutMs?: number }
1419
+ options?: {
1420
+ readonly timeoutMs?: number;
1421
+ readonly onAdmitted?: () => void;
1422
+ readonly routeFence?: import('../../foundation/service-stateful-wire-codec').ServiceActorRouteFence;
1423
+ }
1332
1424
  ): MeshOperationId {
1333
1425
  return this.observeStateful(
1334
1426
  OperationKind.ActorRequest,
1335
1427
  this.requireStateful().requestToActor(
1336
1428
  actor,
1337
- this.peerGeneration(String(actor.nodeRid)),
1338
- actor.generation,
1339
1429
  encodeMultipart(parts),
1340
- options?.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS
1430
+ options?.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS,
1431
+ undefined,
1432
+ undefined,
1433
+ options?.onAdmitted,
1434
+ options?.routeFence
1341
1435
  )
1342
1436
  );
1343
1437
  }
1344
1438
 
1439
+ acceptRelocatedActorTerminal(
1440
+ operation: { readonly high: bigint; readonly low: bigint },
1441
+ replyRouteId: bigint,
1442
+ result: import('../../foundation/service-stateful-runtime').ServiceStatefulResult
1443
+ ): 'terminalReceived' | 'alreadyTerminal' | undefined {
1444
+ return this.requireStateful().acceptRelocatedActorTerminal(operation, replyRouteId, result);
1445
+ }
1446
+
1345
1447
  async actorSendToActor(
1346
1448
  source: ZLinkBackendActorRef,
1347
1449
  target: ZLinkBackendActorRef,
@@ -1349,8 +1451,6 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
1349
1451
  ): Promise<SubmitResultValue> {
1350
1452
  return (await this.requireStateful().sendToActor(
1351
1453
  target,
1352
- this.peerGeneration(String(target.nodeRid)),
1353
- target.generation,
1354
1454
  encodeMultipart(parts),
1355
1455
  source
1356
1456
  )) as SubmitResultValue;
@@ -1360,17 +1460,17 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
1360
1460
  source: ZLinkBackendActorRef,
1361
1461
  target: ZLinkBackendActorRef,
1362
1462
  parts: MessageLike | readonly MessageLike[],
1363
- options?: { readonly timeoutMs?: number }
1463
+ options?: { readonly timeoutMs?: number; readonly onAdmitted?: () => void }
1364
1464
  ): MeshOperationId {
1365
1465
  return this.observeStateful(
1366
1466
  OperationKind.ActorRequest,
1367
1467
  this.requireStateful().requestToActor(
1368
1468
  target,
1369
- this.peerGeneration(String(target.nodeRid)),
1370
- target.generation,
1371
1469
  encodeMultipart(parts),
1372
1470
  options?.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS,
1373
- source
1471
+ source,
1472
+ undefined,
1473
+ options?.onAdmitted
1374
1474
  )
1375
1475
  );
1376
1476
  }
@@ -1393,18 +1493,9 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
1393
1493
  expectedBindingGeneration: bigint,
1394
1494
  timeoutMs: number = DEFAULT_REQUEST_TIMEOUT_MS
1395
1495
  ): MeshOperationId {
1396
- const binding = this.requireStateful().registry.binding(actor);
1397
- if (binding === undefined) {
1398
- return this.observeImmediateFailure(OperationKind.StreamUnbind, RequestResult.NotFound);
1399
- }
1400
1496
  return this.observeStateful(
1401
1497
  OperationKind.StreamUnbind,
1402
- this.requireStateful().unbindSession(
1403
- binding.sessionRid,
1404
- actor,
1405
- expectedBindingGeneration,
1406
- timeoutMs
1407
- )
1498
+ this.requireStateful().closeBoundSession(actor, expectedBindingGeneration, timeoutMs)
1408
1499
  );
1409
1500
  }
1410
1501
 
@@ -1443,7 +1534,8 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
1443
1534
  source: ServiceSpotState,
1444
1535
  target: ServiceDirectSpotRouteFence,
1445
1536
  parts: MessageLike | readonly MessageLike[],
1446
- timeoutMs: number
1537
+ timeoutMs: number,
1538
+ onAdmitted?: () => void
1447
1539
  ): MeshOperationId {
1448
1540
  return this.observeStateful(
1449
1541
  OperationKind.SpotRequest,
@@ -1451,7 +1543,8 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
1451
1543
  source.ref.spotId,
1452
1544
  target,
1453
1545
  encodeMultipart(parts),
1454
- timeoutMs
1546
+ timeoutMs,
1547
+ onAdmitted
1455
1548
  )
1456
1549
  );
1457
1550
  }
@@ -1475,6 +1568,11 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
1475
1568
  }
1476
1569
 
1477
1570
  setSpotSubscription(state: ServiceSpotState, channelName: string, topicFilter: string): void {
1571
+ if (!this.channels.has(channelName))
1572
+ throw new ZLinkFrameworkException(
1573
+ ZLinkFrameworkErrorKind.InvalidOperation,
1574
+ `Spot does not participate in subscription channel '${channelName}'.`
1575
+ );
1478
1576
  this.requireStateful().setSubscription(state, channelName, topicFilter);
1479
1577
  }
1480
1578
 
@@ -1522,9 +1620,35 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
1522
1620
  return result;
1523
1621
  }
1524
1622
 
1623
+ /**
1624
+ * Arms the one maintenance timer for the nearest management deadline
1625
+ * (spec 08 §4.2): request expiry, liveness, or a pending peer handshake.
1626
+ * An earlier deadline re-arms it; a later one keeps the armed time.
1627
+ */
1525
1628
  private scheduleMaintenance(): void {
1526
1629
  if (this.closed) return;
1527
- this.maintenanceTimer ??= setTimeout(this.onMaintenance, MESH_BACKEND_MAINTENANCE_INTERVAL_MS);
1630
+ const nowMs = performance.now();
1631
+ const dueMs = Math.max(
1632
+ nowMs + MESH_BACKEND_MAINTENANCE_INTERVAL_MS,
1633
+ Math.min(
1634
+ this.runtime?.nextMaintenanceDeadlineMs(nowMs) ?? Number.POSITIVE_INFINITY,
1635
+ this.stateful?.nextMaintenanceDeadlineMs() ?? Number.POSITIVE_INFINITY
1636
+ )
1637
+ );
1638
+ if (dueMs === Number.POSITIVE_INFINITY) {
1639
+ if (this.maintenanceTimer !== undefined) clearTimeout(this.maintenanceTimer);
1640
+ this.maintenanceTimer = undefined;
1641
+ this.maintenanceDueMs = dueMs;
1642
+ return;
1643
+ }
1644
+ if (this.maintenanceTimer === undefined || dueMs < this.maintenanceDueMs) {
1645
+ if (this.maintenanceTimer !== undefined) clearTimeout(this.maintenanceTimer);
1646
+ this.maintenanceTimer = setTimeout(
1647
+ this.onMaintenance,
1648
+ Math.min(MESH_BACKEND_MAINTENANCE_MAX_DELAY_MS, Math.ceil(dueMs - nowMs))
1649
+ );
1650
+ this.maintenanceDueMs = dueMs;
1651
+ }
1528
1652
  const pending =
1529
1653
  (this.runtime?.pendingOperationCount ?? 0) + (this.stateful?.pendingOperationCount ?? 0) > 0;
1530
1654
  if (pending === this.maintenanceTimer.hasRef()) return;
@@ -1535,14 +1659,19 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
1535
1659
  }
1536
1660
  }
1537
1661
 
1538
- private async pump(): Promise<void> {
1539
- if (this.isClosed() || this.pumping) return;
1540
- this.pumping = true;
1662
+ private pump(): void {
1663
+ if (this.closed || this.pumpTask !== undefined) return;
1664
+ this.pumpTask = this.runPump(this.requireRuntime());
1665
+ }
1666
+
1667
+ private async runPump(runtime: RawServiceMeshRuntime): Promise<void> {
1668
+ // Publish pumpTask before any callback can signal readiness or begin close.
1669
+ await Promise.resolve();
1541
1670
  try {
1542
1671
  do {
1543
1672
  const ready = this.readable;
1544
1673
  this.readable = 0;
1545
- const more = await this.requireRuntime().pumpBatch((ready & 1) !== 0, (ready & 2) !== 0);
1674
+ const more = await runtime.pumpBatch((ready & 1) !== 0, (ready & 2) !== 0);
1546
1675
  if (more) {
1547
1676
  // Yield only after actual progress, retaining readiness across the
1548
1677
  // existing batch limits until receive reports no data.
@@ -1550,16 +1679,14 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
1550
1679
  await yieldToIO();
1551
1680
  }
1552
1681
  } while (!this.closed && this.readable !== 0);
1682
+ } catch (error) {
1683
+ runtime.reportInfrastructureFailure(error);
1553
1684
  } finally {
1554
- this.pumping = false;
1685
+ this.pumpTask = undefined;
1555
1686
  this.scheduleMaintenance();
1556
1687
  }
1557
1688
  }
1558
1689
 
1559
- private isClosed(): boolean {
1560
- return this.closed;
1561
- }
1562
-
1563
1690
  private notifyReady(): void {
1564
1691
  const runtime = this.runtime;
1565
1692
  let domains = ReadyDomain.None;
@@ -1572,6 +1699,26 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
1572
1699
  if (domains !== ReadyDomain.None) this.readyHandler?.(domains);
1573
1700
  }
1574
1701
 
1702
+ /**
1703
+ * The raw registry takes a remote request's terminal and hands it here,
1704
+ * where the Framework completion owner receives it in the same turn.
1705
+ */
1706
+ private readonly requestObserver: RawServiceRequestObserver = {
1707
+ operationCompleted: (id, result, operationKind) =>
1708
+ this.deliverCompletion({ high: 1n, low: id }, operationKind ?? 0, result),
1709
+ operationFailed: (id, error, operationKind) =>
1710
+ this.deliverCompletion({ high: 1n, low: id }, operationKind ?? 0, requestFailureResult(error))
1711
+ };
1712
+
1713
+ private observedOperation(
1714
+ pending: RawServiceObservedRequest,
1715
+ operationKind: number
1716
+ ): MeshOperationId {
1717
+ return pending.promise === undefined
1718
+ ? { high: 1n, low: pending.id }
1719
+ : this.observeCompletion(pending.id, operationKind, pending.promise);
1720
+ }
1721
+
1575
1722
  private observeCompletion(
1576
1723
  low: bigint,
1577
1724
  operationKind: number,
@@ -1597,15 +1744,6 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
1597
1744
  return id;
1598
1745
  }
1599
1746
 
1600
- private observeImmediateFailure(operationKind: number, terminalResult: number): MeshOperationId {
1601
- const low = this.nextPeerIntent++;
1602
- return this.observeCompletion(
1603
- low,
1604
- operationKind,
1605
- Promise.resolve({ terminalResult, failureCode: 0 })
1606
- );
1607
- }
1608
-
1609
1747
  private deliverCompletion(
1610
1748
  operationId: MeshOperationId,
1611
1749
  operationKind: number,
@@ -1719,7 +1857,11 @@ class RawServiceSpot implements ServiceSpot {
1719
1857
  requestToChannel(
1720
1858
  channelName: string,
1721
1859
  parts: MessageLike | readonly MessageLike[],
1722
- options?: { readonly flags?: number; readonly timeoutMs?: number }
1860
+ options?: {
1861
+ readonly flags?: number;
1862
+ readonly timeoutMs?: number;
1863
+ readonly onAdmitted?: () => void;
1864
+ }
1723
1865
  ): MeshOperationId {
1724
1866
  this.requireOpen();
1725
1867
  return this.backend.requestToChannel(channelName, parts, options);
@@ -1755,6 +1897,7 @@ class RawServiceSpot implements ServiceSpot {
1755
1897
  parts: MessageLike | readonly MessageLike[],
1756
1898
  options?: {
1757
1899
  readonly timeoutMs?: number;
1900
+ readonly onAdmitted?: () => void;
1758
1901
  readonly routeFence?: ServiceDirectSpotRouteFence;
1759
1902
  readonly entrySpot?: boolean;
1760
1903
  }
@@ -1773,7 +1916,8 @@ class RawServiceSpot implements ServiceSpot {
1773
1916
  this.state,
1774
1917
  routeFence,
1775
1918
  parts,
1776
- options?.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS
1919
+ options?.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS,
1920
+ options?.onAdmitted
1777
1921
  );
1778
1922
  }
1779
1923
 
@@ -1823,6 +1967,10 @@ class RawServiceSpot implements ServiceSpot {
1823
1967
  }
1824
1968
  }
1825
1969
 
1970
+ function nodeSendResult(submitted: boolean): SubmitResultValue {
1971
+ return submitted ? SubmitResult.Ok : SubmitResult.NotConnected;
1972
+ }
1973
+
1826
1974
  function requireDirectSpotRouteFence(
1827
1975
  route: ServiceDirectSpotRouteFence | undefined,
1828
1976
  targetNodeRid: string,
@@ -1884,7 +2032,9 @@ class RawStreamSessionService implements StreamSessionService {
1884
2032
  return {
1885
2033
  state: this.state,
1886
2034
  lifecycleGeneration: 1n,
1887
- sessionCount: BigInt(new Set(bindings.map((value) => value.sessionRid)).size),
2035
+ sessionCount: BigInt(
2036
+ new Set(bindings.map((value) => encodeRoutingIdStorageHex(value.sessionRid))).size
2037
+ ),
1888
2038
  bindingCount: BigInt(bindings.length),
1889
2039
  pendingMessageCount: 0n,
1890
2040
  pendingByteCount: 0n,
@@ -1913,7 +2063,8 @@ class RawStreamSessionService implements StreamSessionService {
1913
2063
  retiredSession: ServiceRetiredBoundSessionRouteFence,
1914
2064
  actor: ServiceActorRef
1915
2065
  ) => void,
1916
- actorAuthority?: StreamSessionActorAuthorityFence
2066
+ actorAuthority?: StreamSessionActorAuthorityFence,
2067
+ close?: () => Promise<void>
1917
2068
  ): MeshOperationId {
1918
2069
  this.requireStarted();
1919
2070
  const sessionKey = String(sessionRid);
@@ -1921,13 +2072,13 @@ class RawStreamSessionService implements StreamSessionService {
1921
2072
  return this.observe(
1922
2073
  OperationKind.StreamBind,
1923
2074
  this.stateful.bindSession(
1924
- sessionKey,
2075
+ sessionRid,
1925
2076
  actor,
1926
2077
  timeoutMs,
1927
- (targetSessionRid, payloadFrame) =>
1928
- this.deliver(targetSessionRid, actor.actorId, payloadFrame),
2078
+ (_targetSessionRid, payloadFrame) => this.deliver(sessionKey, actor.actorId, payloadFrame),
1929
2079
  onBindingReplaced,
1930
- actorAuthority
2080
+ actorAuthority,
2081
+ close
1931
2082
  )
1932
2083
  );
1933
2084
  }
@@ -1941,12 +2092,12 @@ class RawStreamSessionService implements StreamSessionService {
1941
2092
  this.requireStarted();
1942
2093
  return this.observe(
1943
2094
  OperationKind.StreamUnbind,
1944
- this.stateful.unbindSession(String(sessionRid), actor, expectedBindingGeneration, timeoutMs)
2095
+ this.stateful.unbindSession(sessionRid, actor, expectedBindingGeneration, timeoutMs)
1945
2096
  );
1946
2097
  }
1947
2098
 
1948
2099
  bindings(sessionRid: RoutingId) {
1949
- return this.stateful.sessionBindings(String(sessionRid));
2100
+ return this.stateful.sessionBindings(sessionRid);
1950
2101
  }
1951
2102
 
1952
2103
  async sendToActor(
@@ -1956,7 +2107,7 @@ class RawStreamSessionService implements StreamSessionService {
1956
2107
  ): Promise<SubmitResultValue> {
1957
2108
  this.requireStarted();
1958
2109
  return (await this.stateful.sendSessionToActor(
1959
- String(sessionRid),
2110
+ sessionRid,
1960
2111
  actor,
1961
2112
  encodeMultipart(parts)
1962
2113
  )) as SubmitResultValue;
@@ -1970,11 +2121,14 @@ class RawStreamSessionService implements StreamSessionService {
1970
2121
  const target = this.sessionTargets.get(sessionRid);
1971
2122
  if (target === undefined) return false;
1972
2123
  const operation = this.stream.send(target as unknown as BindingRoutingId);
1973
- const parts = decodeMultipartBuffers(decodeApplicationPayloadView(payload).payload);
2124
+ const parts = decodeMultipartParts(
2125
+ decodeApplicationPayloadView(payload).payload,
2126
+ borrowMultipartPart
2127
+ );
1974
2128
  if (parts.length === 0) return false;
1975
2129
  const actorSlot = await serviceSessionBindingIngressPortIfRegistered(this)?.actorSlot(
1976
2130
  actorId,
1977
- sessionRid
2131
+ target
1978
2132
  );
1979
2133
  if (actorSlot === undefined) return false;
1980
2134
  parts[0] = Buffer.from(streamFrameWithActorSlot(parts[0]!, actorSlot));
@@ -1993,7 +2147,7 @@ class RawStreamSessionService implements StreamSessionService {
1993
2147
  case SubmitResult.Terminated:
1994
2148
  // Let the socket monitor drive the existing STREAM close/unbind
1995
2149
  // lifecycle instead of maintaining a second session-close state.
1996
- disconnectStreamPeer(this.stream, target);
2150
+ disconnectSocketPeer(this.stream, toNativeRoutingId(target));
1997
2151
  throw new ZLinkBackendResultError('submit', error.result, error.nativeErrno, {
1998
2152
  cause: error
1999
2153
  });
@@ -2242,7 +2396,11 @@ function decodeMultipartRecord(
2242
2396
  const header = record.parts[0]!;
2243
2397
  const command = header[SERVICE_WIRE_COMMAND_OFFSET]!;
2244
2398
  const payloadFrame = record.parts[1]!;
2245
- const application = decodeApplicationEnvelope(payloadFrame);
2399
+ const parts = decodeMultipartApplicationParts(
2400
+ payloadFrame,
2401
+ ZLinkBufferMessage.fromOwned,
2402
+ closeMultipartMessage
2403
+ );
2246
2404
  const channelName = record.owner.startsWith('channel:')
2247
2405
  ? record.owner.slice('channel:'.length)
2248
2406
  : null;
@@ -2264,7 +2422,7 @@ function decodeMultipartRecord(
2264
2422
  : kind === ReceiveKind.ChannelRequest
2265
2423
  ? OperationKind.ChannelRequest
2266
2424
  : 0;
2267
- const ingressLifecycle = receiveIngressLifecycle(record);
2425
+ const applicationJob = record.applicationJob;
2268
2426
  return {
2269
2427
  kind,
2270
2428
  domain: readyDomain(record.domain),
@@ -2277,22 +2435,38 @@ function decodeMultipartRecord(
2277
2435
  channelName,
2278
2436
  topic: null,
2279
2437
  applicationMetadata: null,
2280
- packetName: application.packetName,
2281
- contentType: application.contentType,
2438
+ packetName: SERVICE_FRAMEWORK_MULTIPART_PACKET_NAME,
2439
+ contentType: SERVICE_FRAMEWORK_MULTIPART_CONTENT_TYPE,
2282
2440
  kindData: null,
2283
2441
  terminalResult: 0,
2284
2442
  failureErrno: 0,
2285
- ...ingressLifecycle,
2286
- parts: decodeMultipart(application.payload),
2443
+ applicationJobPermit: applicationJob,
2444
+ releaseRetainedIngress: applicationJob === undefined ? undefined : releaseRecordApplicationJob,
2445
+ parts,
2287
2446
  reply(parts) {
2288
2447
  if (record.correlation === undefined) return SubmitResult.InvalidState;
2289
2448
  runtime.reply(record, encodeMultipartApplicationFrame(parts));
2290
2449
  return SubmitResult.Ok;
2291
2450
  },
2292
- replyActorJoin: () => SubmitResult.NotSupported
2451
+ replyActorJoin: replyActorJoinNotSupported
2293
2452
  };
2294
2453
  }
2295
2454
 
2455
+ /** Shared by every ordinary record: the record's own permit lease is its retained ingress. */
2456
+ function releaseRecordApplicationJob(this: {
2457
+ readonly applicationJobPermit?: import('../../application-jobs/contracts').ApplicationJobPermitPort;
2458
+ }): void {
2459
+ (
2460
+ this.applicationJobPermit as
2461
+ | import('../../application-jobs/application-ingress-record-owner').ApplicationJobRecordLease
2462
+ | undefined
2463
+ )?.close();
2464
+ }
2465
+
2466
+ function replyActorJoinNotSupported(): SubmitResultValue {
2467
+ return SubmitResult.NotSupported;
2468
+ }
2469
+
2296
2470
  function decodeStatefulRecord(
2297
2471
  record: ServiceMailboxRecord,
2298
2472
  stateful: ServiceStatefulMailboxData
@@ -2308,7 +2482,7 @@ function decodeStatefulRecord(
2308
2482
  ? stateful.canonicalApplicationPayload
2309
2483
  : payloadFrame === undefined
2310
2484
  ? undefined
2311
- : decodeApplicationEnvelope(payloadFrame);
2485
+ : decodeMultipartApplicationPayloadView(payloadFrame);
2312
2486
  const operationId =
2313
2487
  record.correlation === undefined
2314
2488
  ? { high: 0n, low: 0n }
@@ -2316,6 +2490,12 @@ function decodeStatefulRecord(
2316
2490
  const ingressLifecycle = receiveIngressLifecycle(record);
2317
2491
  return {
2318
2492
  kind: stateful.receiveKind,
2493
+ get requestSource() {
2494
+ return record.requestSource;
2495
+ },
2496
+ prepareDispatch:
2497
+ record.sourcePreparationOwner === undefined ? undefined : prepareStatefulMailboxDispatch,
2498
+ statefulMailboxRecord: record,
2319
2499
  domain: readyDomain(record.domain),
2320
2500
  sourceNodeRid: (record.sourceRoutingId as RoutingId | undefined) ?? null,
2321
2501
  sourceSpotId: (stateful.sourceSpotId as RoutingId | undefined) ?? null,
@@ -2414,6 +2594,17 @@ function receiveIngressLifecycle(record: ServiceMailboxRecord): {
2414
2594
  };
2415
2595
  }
2416
2596
 
2597
+ function prepareStatefulMailboxDispatch(
2598
+ this: import('../../foundation/service-runtime-contracts').ReceiveRecord,
2599
+ signal: AbortSignal
2600
+ ): boolean | Promise<boolean> {
2601
+ const mailboxRecord = this.statefulMailboxRecord;
2602
+ const owner = mailboxRecord?.sourcePreparationOwner;
2603
+ return mailboxRecord === undefined || owner === undefined
2604
+ ? true
2605
+ : owner.prepareDispatch(mailboxRecord, signal);
2606
+ }
2607
+
2417
2608
  function readyOwner(
2418
2609
  owner: string,
2419
2610
  nodeRid: string,
@@ -2536,93 +2727,16 @@ function encodeMultipartApplicationFrame(parts: MessageLike | readonly MessageLi
2536
2727
  );
2537
2728
  }
2538
2729
 
2539
- function decodeApplicationEnvelope(frame: Uint8Array) {
2540
- const bytes = Buffer.from(frame.buffer, frame.byteOffset, frame.byteLength);
2541
- if (
2542
- bytes.length < APPLICATION_PAYLOAD_MINIMUM_FIELD_BYTES ||
2543
- bytes[0] !== APPLICATION_PAYLOAD_VERSION
2544
- ) {
2545
- throw new ServiceWireProtocolError('Invalid application envelope.');
2546
- }
2547
- const bodyLength = bytes.readUInt32BE(1);
2548
- if (bodyLength !== bytes.length - 5) {
2549
- throw new ServiceWireProtocolError('Invalid application envelope length.');
2550
- }
2551
- let offset = 5;
2552
- const packetLength = bytes[offset++]!;
2553
- if (packetLength === 0 || bytes.length - offset < packetLength + 1) {
2554
- throw new ServiceWireProtocolError('Invalid application envelope packet name.');
2555
- }
2556
- let packetName: string;
2557
- try {
2558
- packetName = FATAL_UTF8.decode(bytes.subarray(offset, offset + packetLength));
2559
- } catch {
2560
- throw new ServiceWireProtocolError('Invalid application envelope packet name.');
2561
- }
2562
- offset += packetLength;
2563
- const contentLength = bytes[offset++]!;
2564
- if (contentLength === 0 || bytes.length - offset < contentLength + 4) {
2565
- throw new ServiceWireProtocolError('Invalid application envelope content type.');
2566
- }
2567
- let contentType: string;
2568
- try {
2569
- contentType = FATAL_UTF8.decode(bytes.subarray(offset, offset + contentLength));
2570
- } catch {
2571
- throw new ServiceWireProtocolError('Invalid application envelope content type.');
2572
- }
2573
- offset += contentLength;
2574
- const payloadLength = bytes.readUInt32BE(offset);
2575
- offset += 4;
2576
- if (
2577
- packetName !== MULTIPART_PACKET_NAME ||
2578
- contentType !== MULTIPART_CONTENT_TYPE ||
2579
- payloadLength !== bytes.length - offset
2580
- ) {
2581
- throw new ServiceWireProtocolError('Unexpected M6A application payload.');
2582
- }
2583
- return { packetName, contentType, payload: bytes.subarray(offset) };
2730
+ function decodeMultipart(payload: Uint8Array): FrameworkMessage[] {
2731
+ return decodeMultipartParts(payload, ZLinkBufferMessage.fromOwned, closeMultipartMessage);
2584
2732
  }
2585
2733
 
2586
- function decodeMultipart(payload: Uint8Array): FrameworkMessage[] {
2587
- const buffers = decodeMultipartBuffers(payload);
2588
- const parts = new Array<FrameworkMessage>(buffers.length);
2589
- let materialized = 0;
2590
- try {
2591
- for (; materialized < buffers.length; materialized += 1) {
2592
- parts[materialized] = ZLinkBufferMessage.fromOwned(buffers[materialized]!);
2593
- }
2594
- return parts;
2595
- } catch (error) {
2596
- for (let index = 0; index < materialized; index += 1) parts[index]!.close();
2597
- throw error;
2598
- }
2734
+ function closeMultipartMessage(part: FrameworkMessage): void {
2735
+ part.close();
2599
2736
  }
2600
2737
 
2601
- function decodeMultipartBuffers(payload: Uint8Array): Buffer[] {
2602
- const bytes = Buffer.from(payload.buffer, payload.byteOffset, payload.byteLength);
2603
- if (bytes.length < 4) throw new ServiceWireProtocolError('Truncated multipart payload.');
2604
- const count = bytes.readUInt32BE(0);
2605
- if (count === 0 || count > Math.floor((bytes.length - 4) / 4)) {
2606
- throw new ServiceWireProtocolError('Invalid multipart part count.');
2607
- }
2608
- const result = new Array<Buffer>(count);
2609
- let offset = 4;
2610
- for (let index = 0; index < count; index++) {
2611
- if (bytes.length - offset < 4) {
2612
- throw new ServiceWireProtocolError('Truncated multipart part length.');
2613
- }
2614
- const length = bytes.readUInt32BE(offset);
2615
- offset += 4;
2616
- if (bytes.length - offset < length) {
2617
- throw new ServiceWireProtocolError('Truncated multipart part.');
2618
- }
2619
- result[index] = bytes.subarray(offset, offset + length);
2620
- offset += length;
2621
- }
2622
- if (offset !== bytes.length) {
2623
- throw new ServiceWireProtocolError('Multipart payload has trailing bytes.');
2624
- }
2625
- return result;
2738
+ function borrowMultipartPart(part: Buffer): Buffer {
2739
+ return part;
2626
2740
  }
2627
2741
 
2628
2742
  function messageBytesView(value: MessageLike): Uint8Array {