@zlink-systems/framework 0.30.1 → 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 (340) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/contracts/Common/ZLinkEncodedPayload.d.ts +6 -0
  3. package/dist/contracts/Common/ZLinkEncodedPayload.js +18 -3
  4. package/dist/contracts/Common/encoded-payload-storage.d.ts +1 -1
  5. package/dist/contracts/Common/encoded-payload-storage.js +5 -2
  6. package/dist/contracts/Configuration/Builders.d.ts +1 -1
  7. package/dist/contracts/Configuration/RegistrationBuilderPolicy.d.ts +2 -1
  8. package/dist/contracts/Configuration/RegistrationBuilderPolicy.js +5 -1
  9. package/dist/contracts/Configuration/RegistrationBuilders.js +2 -2
  10. package/dist/contracts/Configuration/RegistrationTypes.d.ts +1 -0
  11. package/dist/contracts/Dispatch/ZLinkDispatchOptions.d.ts +2 -2
  12. package/dist/contracts/Locations/Rows.d.ts +2 -0
  13. package/dist/contracts/Spots/Contracts.d.ts +4 -0
  14. package/dist/contracts/Spots/ZLinkSpot.d.ts +3 -3
  15. package/dist/runtime/abort.d.ts +5 -0
  16. package/dist/runtime/abort.js +10 -0
  17. package/dist/runtime/actors/actor-authority-publication.js +3 -2
  18. package/dist/runtime/actors/actor-client.d.ts +0 -1
  19. package/dist/runtime/actors/actor-client.js +38 -45
  20. package/dist/runtime/actors/actor-context.d.ts +2 -0
  21. package/dist/runtime/actors/actor-context.js +46 -9
  22. package/dist/runtime/actors/actor-handoff.d.ts +7 -3
  23. package/dist/runtime/actors/actor-handoff.js +212 -88
  24. package/dist/runtime/actors/actor-join-relocation.d.ts +2 -0
  25. package/dist/runtime/actors/actor-local-native-join.js +4 -0
  26. package/dist/runtime/actors/actor-mailbox.js +27 -1
  27. package/dist/runtime/actors/actor-remote-joiner.js +3 -1
  28. package/dist/runtime/actors/actor-reply.d.ts +4 -0
  29. package/dist/runtime/actors/actor-reply.js +29 -0
  30. package/dist/runtime/actors/actor-runtime-contracts.d.ts +2 -0
  31. package/dist/runtime/actors/actor-runtime-state.js +2 -20
  32. package/dist/runtime/actors/actor-source-transfer.d.ts +1 -17
  33. package/dist/runtime/actors/index.d.ts +6 -2
  34. package/dist/runtime/actors/index.js +37 -21
  35. package/dist/runtime/actors/session-disconnected-wire.d.ts +8 -0
  36. package/dist/runtime/actors/session-disconnected-wire.js +48 -0
  37. package/dist/runtime/admission.d.ts +9 -1
  38. package/dist/runtime/admission.js +55 -32
  39. package/dist/runtime/application-jobs/application-job-queue-scope.d.ts +13 -0
  40. package/dist/runtime/application-jobs/application-job-queue-scope.js +27 -1
  41. package/dist/runtime/application-jobs/contracts.d.ts +2 -0
  42. package/dist/runtime/backend/contracts/index.d.ts +19 -3
  43. package/dist/runtime/backend/mesh-actor-session-node-adapter.js +2 -2
  44. package/dist/runtime/backend/mesh-completion-table.js +5 -0
  45. package/dist/runtime/backend/mesh-dispatch-pump.d.ts +26 -2
  46. package/dist/runtime/backend/mesh-dispatch-pump.js +193 -107
  47. package/dist/runtime/backend/node/node-raw-binding-port.js +90 -58
  48. package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +33 -8
  49. package/dist/runtime/backend/node/node-raw-mesh-backend.js +142 -143
  50. package/dist/runtime/backend/node/node-socket-backend-adapter.d.ts +1 -1
  51. package/dist/runtime/backend/node/node-socket-backend-adapter.js +5 -5
  52. package/dist/runtime/channels/channel-clients.d.ts +1 -0
  53. package/dist/runtime/channels/channel-clients.js +20 -5
  54. package/dist/runtime/channels/channel-dispatch-pipeline.d.ts +22 -3
  55. package/dist/runtime/channels/channel-dispatch-pipeline.js +103 -57
  56. package/dist/runtime/channels/channel-dispatchers.d.ts +3 -2
  57. package/dist/runtime/channels/channel-dispatchers.js +44 -37
  58. package/dist/runtime/channels/channel-envelope.d.ts +1 -0
  59. package/dist/runtime/channels/channel-envelope.js +74 -31
  60. package/dist/runtime/channels/channel-runtime-lifecycle.d.ts +4 -3
  61. package/dist/runtime/channels/channel-runtime-lifecycle.js +19 -24
  62. package/dist/runtime/channels/channel-runtime-manager.d.ts +3 -2
  63. package/dist/runtime/channels/channel-runtime-manager.js +4 -4
  64. package/dist/runtime/channels/channel-transports.d.ts +0 -1
  65. package/dist/runtime/channels/channel-transports.js +35 -33
  66. package/dist/runtime/channels/client-server-location-runtime.js +5 -4
  67. package/dist/runtime/channels/dispatch-error-reporter.d.ts +2 -1
  68. package/dist/runtime/channels/dispatch-error-reporter.js +2 -1
  69. package/dist/runtime/channels/fanout-location-runtime.d.ts +1 -1
  70. package/dist/runtime/channels/fanout-location-runtime.js +3 -3
  71. package/dist/runtime/diagnostics/flow-context.js +19 -7
  72. package/dist/runtime/diagnostics/index.js +4 -9
  73. package/dist/runtime/diagnostics/message-flow.d.ts +8 -0
  74. package/dist/runtime/diagnostics/message-flow.js +35 -5
  75. package/dist/runtime/diagnostics/runtime-metrics.d.ts +2 -2
  76. package/dist/runtime/diagnostics/runtime-metrics.js +10 -8
  77. package/dist/runtime/execution/index.d.ts +4 -2
  78. package/dist/runtime/execution/index.js +33 -10
  79. package/dist/runtime/execution/serial-execution-queue.d.ts +4 -0
  80. package/dist/runtime/execution/serial-execution-queue.js +21 -2
  81. package/dist/runtime/execution/state-lane.d.ts +2 -0
  82. package/dist/runtime/execution/state-lane.js +5 -0
  83. package/dist/runtime/foundation/operation-registry.d.ts +25 -1
  84. package/dist/runtime/foundation/operation-registry.js +86 -18
  85. package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +39 -3
  86. package/dist/runtime/foundation/raw-service-mesh-runtime.js +151 -55
  87. package/dist/runtime/foundation/service-liveness-registry.d.ts +12 -1
  88. package/dist/runtime/foundation/service-liveness-registry.js +38 -0
  89. package/dist/runtime/foundation/service-mailbox.d.ts +7 -0
  90. package/dist/runtime/foundation/service-maintenance-runtime.js +1 -6
  91. package/dist/runtime/foundation/service-relocation-object-owner.d.ts +2 -3
  92. package/dist/runtime/foundation/service-relocation-object-owner.js +48 -35
  93. package/dist/runtime/foundation/service-relocation-runtime.js +7 -3
  94. package/dist/runtime/foundation/service-runtime-contracts.d.ts +8 -1
  95. package/dist/runtime/foundation/service-session-binding-ingress-port.d.ts +2 -1
  96. package/dist/runtime/foundation/service-stateful-registry.d.ts +5 -4
  97. package/dist/runtime/foundation/service-stateful-registry.js +24 -26
  98. package/dist/runtime/foundation/service-stateful-runtime.d.ts +72 -6
  99. package/dist/runtime/foundation/service-stateful-runtime.js +444 -117
  100. package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +14 -1
  101. package/dist/runtime/foundation/service-stateful-wire-codec.js +48 -27
  102. package/dist/runtime/foundation/service-wire-binary-primitives.d.ts +6 -1
  103. package/dist/runtime/foundation/service-wire-binary-primitives.js +27 -11
  104. package/dist/runtime/foundation/service-wire-constants.generated.d.ts +1 -0
  105. package/dist/runtime/foundation/service-wire-constants.generated.js +1 -0
  106. package/dist/runtime/foundation/service-wire-m6a-codec.d.ts +10 -0
  107. package/dist/runtime/foundation/service-wire-m6a-codec.js +166 -53
  108. package/dist/runtime/host/actor-packet-relay.d.ts +6 -4
  109. package/dist/runtime/host/actor-packet-relay.js +59 -72
  110. package/dist/runtime/host/actor-placement-coordinator.js +25 -8
  111. package/dist/runtime/host/actor-transfer-runtime.d.ts +7 -31
  112. package/dist/runtime/host/actor-transfer-runtime.js +85 -331
  113. package/dist/runtime/host/application-job-queue.d.ts +24 -3
  114. package/dist/runtime/host/application-job-queue.js +28 -41
  115. package/dist/runtime/host/index.d.ts +5 -1
  116. package/dist/runtime/host/index.js +171 -97
  117. package/dist/runtime/host/location-runtime-owner.js +2 -6
  118. package/dist/runtime/host/mesh-router-resolver.d.ts +4 -0
  119. package/dist/runtime/host/mesh-router-resolver.js +14 -6
  120. package/dist/runtime/host/remote-bound-session-relay.d.ts +2 -4
  121. package/dist/runtime/host/remote-bound-session-relay.js +71 -190
  122. package/dist/runtime/host/route-mesh-runtime.d.ts +2 -2
  123. package/dist/runtime/host/route-mesh-runtime.js +5 -3
  124. package/dist/runtime/host/runtime-shutdown.d.ts +1 -0
  125. package/dist/runtime/host/runtime-shutdown.js +3 -2
  126. package/dist/runtime/host/service-relocation-host-runtime.d.ts +17 -7
  127. package/dist/runtime/host/service-relocation-host-runtime.js +550 -367
  128. package/dist/runtime/host/spot-runtime-options-factory.js +15 -7
  129. package/dist/runtime/host/user-spot-creation-coordinator.js +33 -84
  130. package/dist/runtime/locations/auto-connect-loop.d.ts +2 -0
  131. package/dist/runtime/locations/auto-connect-loop.js +22 -14
  132. package/dist/runtime/locations/auto-connect-reconciler.js +0 -6
  133. package/dist/runtime/locations/auto-connect-types.d.ts +0 -1
  134. package/dist/runtime/locations/descriptor-publication.d.ts +4 -0
  135. package/dist/runtime/locations/descriptor-publication.js +11 -0
  136. package/dist/runtime/locations/domain-store-contract.d.ts +1 -0
  137. package/dist/runtime/locations/in-memory-authority-store.d.ts +7 -1
  138. package/dist/runtime/locations/in-memory-authority-store.js +56 -19
  139. package/dist/runtime/locations/in-memory-location-store.js +1 -10
  140. package/dist/runtime/locations/index.d.ts +1 -0
  141. package/dist/runtime/locations/index.js +1 -0
  142. package/dist/runtime/locations/lease-tracker.js +1 -6
  143. package/dist/runtime/locations/location-store-repository.d.ts +51 -1
  144. package/dist/runtime/locations/location-store-repository.js +363 -139
  145. package/dist/runtime/locations/relocation-blob.d.ts +18 -1
  146. package/dist/runtime/locations/relocation-blob.js +52 -1
  147. package/dist/runtime/locations/request-source-resolver.d.ts +37 -0
  148. package/dist/runtime/locations/request-source-resolver.js +80 -0
  149. package/dist/runtime/locations/resolvers.js +1 -1
  150. package/dist/runtime/locations/runtime.d.ts +6 -2
  151. package/dist/runtime/locations/runtime.js +37 -30
  152. package/dist/runtime/messaging/payload-codec.d.ts +7 -1
  153. package/dist/runtime/messaging/payload-codec.js +7 -6
  154. package/dist/runtime/messaging/request-result.js +29 -26
  155. package/dist/runtime/protocol/service_wire_codec.generated.d.ts +19 -1
  156. package/dist/runtime/protocol/service_wire_codec.generated.js +85 -0
  157. package/dist/runtime/protocol/service_wire_pilot_codec.generated.d.ts +7 -1
  158. package/dist/runtime/protocol/service_wire_pilot_codec.generated.js +23 -7
  159. package/dist/runtime/spots/formal-remote-actor-admission-registry.js +3 -2
  160. package/dist/runtime/spots/index.d.ts +18 -11
  161. package/dist/runtime/spots/index.js +234 -176
  162. package/dist/runtime/spots/spot-activation-registry.d.ts +4 -2
  163. package/dist/runtime/spots/spot-activation-registry.js +21 -11
  164. package/dist/runtime/spots/spot-activation-state.d.ts +1 -1
  165. package/dist/runtime/spots/spot-activation-state.js +7 -7
  166. package/dist/runtime/spots/spot-activation.d.ts +6 -3
  167. package/dist/runtime/spots/spot-activation.js +123 -44
  168. package/dist/runtime/spots/spot-actor-admission-coordinator.d.ts +1 -0
  169. package/dist/runtime/spots/spot-actor-admission-coordinator.js +13 -22
  170. package/dist/runtime/spots/spot-actor-membership.d.ts +0 -1
  171. package/dist/runtime/spots/spot-actor-membership.js +0 -8
  172. package/dist/runtime/spots/spot-actor-packet-dispatch.js +33 -8
  173. package/dist/runtime/spots/spot-actor-packet-drain.js +5 -33
  174. package/dist/runtime/spots/spot-entry-activation.d.ts +2 -0
  175. package/dist/runtime/spots/spot-entry-activation.js +14 -9
  176. package/dist/runtime/spots/spot-handler-registry.d.ts +4 -3
  177. package/dist/runtime/spots/spot-handler-registry.js +6 -2
  178. package/dist/runtime/spots/spot-manager-internal-contracts.d.ts +2 -2
  179. package/dist/runtime/spots/spot-manager-public.js +2 -2
  180. package/dist/runtime/spots/spot-node-autoconnect.d.ts +2 -1
  181. package/dist/runtime/spots/spot-node-autoconnect.js +18 -39
  182. package/dist/runtime/spots/spot-node-runtime-manager.d.ts +19 -2
  183. package/dist/runtime/spots/spot-node-runtime-manager.js +115 -50
  184. package/dist/runtime/spots/spot-outbound.js +3 -3
  185. package/dist/runtime/spots/spot-remote-codec.js +5 -1
  186. package/dist/runtime/spots/spot-runtime-ports.d.ts +0 -1
  187. package/dist/runtime/spots/spot-serial-executor.d.ts +10 -0
  188. package/dist/runtime/spots/spot-serial-executor.js +61 -8
  189. package/dist/runtime/spots/spot-serial-turn-executor.js +19 -2
  190. package/dist/runtime/spots/spot-subscription-dispatch.js +1 -1
  191. package/dist/runtime/spots/spot-timer.d.ts +57 -5
  192. package/dist/runtime/spots/spot-timer.js +287 -103
  193. package/dist/runtime/streams/actor-session-binding-registry.d.ts +42 -11
  194. package/dist/runtime/streams/actor-session-binding-registry.js +165 -48
  195. package/dist/runtime/streams/actor-session-binding-runtime-owner.d.ts +8 -4
  196. package/dist/runtime/streams/bound-actor-relay-sender.d.ts +2 -1
  197. package/dist/runtime/streams/bound-actor-relay-sender.js +15 -8
  198. package/dist/runtime/streams/bound-session-service.d.ts +1 -1
  199. package/dist/runtime/streams/bound-session-service.js +6 -11
  200. package/dist/runtime/streams/index.d.ts +3 -2
  201. package/dist/runtime/streams/index.js +6 -4
  202. package/dist/runtime/streams/managed-stream.js +3 -2
  203. package/dist/runtime/streams/native-fallback-bound-session.js +8 -73
  204. package/dist/runtime/streams/session-actor-coordinator.d.ts +2 -8
  205. package/dist/runtime/streams/session-actor-coordinator.js +15 -32
  206. package/dist/runtime/streams/stream-binding-runtime-ports.d.ts +3 -10
  207. package/dist/runtime/streams/stream-session-runtime.js +1 -4
  208. package/dist/runtime/workers/index.js +1 -1
  209. package/package.json +3 -3
  210. package/src/contracts/Common/ZLinkEncodedPayload.ts +24 -4
  211. package/src/contracts/Common/encoded-payload-storage.ts +6 -3
  212. package/src/contracts/Configuration/Builders.ts +4 -1
  213. package/src/contracts/Configuration/RegistrationBuilderPolicy.ts +7 -2
  214. package/src/contracts/Configuration/RegistrationBuilders.ts +6 -2
  215. package/src/contracts/Configuration/RegistrationTypes.ts +1 -0
  216. package/src/contracts/Dispatch/ZLinkDispatchOptions.ts +2 -1
  217. package/src/contracts/Locations/Rows.ts +2 -0
  218. package/src/contracts/Spots/Contracts.ts +8 -0
  219. package/src/contracts/Spots/ZLinkSpot.ts +3 -3
  220. package/src/runtime/abort.ts +12 -0
  221. package/src/runtime/actors/actor-authority-publication.ts +3 -2
  222. package/src/runtime/actors/actor-client.ts +61 -70
  223. package/src/runtime/actors/actor-context.ts +49 -9
  224. package/src/runtime/actors/actor-handoff.ts +282 -106
  225. package/src/runtime/actors/actor-join-relocation.ts +2 -0
  226. package/src/runtime/actors/actor-local-native-join.ts +4 -0
  227. package/src/runtime/actors/actor-mailbox.ts +40 -2
  228. package/src/runtime/actors/actor-remote-joiner.ts +6 -1
  229. package/src/runtime/actors/actor-reply.ts +42 -0
  230. package/src/runtime/actors/actor-runtime-contracts.ts +2 -0
  231. package/src/runtime/actors/actor-runtime-state.ts +2 -20
  232. package/src/runtime/actors/actor-source-transfer.ts +1 -34
  233. package/src/runtime/actors/index.ts +41 -27
  234. package/src/runtime/actors/session-disconnected-wire.ts +66 -0
  235. package/src/runtime/admission.ts +69 -34
  236. package/src/runtime/application-jobs/application-job-queue-scope.ts +33 -1
  237. package/src/runtime/application-jobs/contracts.ts +2 -0
  238. package/src/runtime/backend/contracts/index.ts +39 -4
  239. package/src/runtime/backend/mesh-actor-session-node-adapter.ts +5 -3
  240. package/src/runtime/backend/mesh-completion-table.ts +4 -0
  241. package/src/runtime/backend/mesh-dispatch-pump.ts +223 -124
  242. package/src/runtime/backend/node/node-raw-binding-port.ts +106 -70
  243. package/src/runtime/backend/node/node-raw-mesh-backend.ts +221 -170
  244. package/src/runtime/backend/node/node-socket-backend-adapter.ts +5 -5
  245. package/src/runtime/channels/channel-clients.ts +49 -24
  246. package/src/runtime/channels/channel-dispatch-pipeline.ts +173 -124
  247. package/src/runtime/channels/channel-dispatchers.ts +116 -72
  248. package/src/runtime/channels/channel-envelope.ts +105 -36
  249. package/src/runtime/channels/channel-runtime-lifecycle.ts +13 -13
  250. package/src/runtime/channels/channel-runtime-manager.ts +12 -5
  251. package/src/runtime/channels/channel-transports.ts +49 -58
  252. package/src/runtime/channels/client-server-location-runtime.ts +11 -10
  253. package/src/runtime/channels/dispatch-error-reporter.ts +4 -2
  254. package/src/runtime/channels/fanout-location-runtime.ts +17 -9
  255. package/src/runtime/diagnostics/flow-context.ts +20 -7
  256. package/src/runtime/diagnostics/index.ts +1 -7
  257. package/src/runtime/diagnostics/message-flow.ts +47 -9
  258. package/src/runtime/diagnostics/runtime-metrics.ts +12 -10
  259. package/src/runtime/execution/index.ts +40 -14
  260. package/src/runtime/execution/serial-execution-queue.ts +31 -4
  261. package/src/runtime/execution/state-lane.ts +7 -0
  262. package/src/runtime/foundation/operation-registry.ts +98 -20
  263. package/src/runtime/foundation/raw-service-mesh-runtime.ts +244 -67
  264. package/src/runtime/foundation/service-liveness-registry.ts +39 -0
  265. package/src/runtime/foundation/service-mailbox.ts +8 -0
  266. package/src/runtime/foundation/service-maintenance-runtime.ts +1 -8
  267. package/src/runtime/foundation/service-relocation-object-owner.ts +54 -37
  268. package/src/runtime/foundation/service-relocation-runtime.ts +7 -3
  269. package/src/runtime/foundation/service-runtime-contracts.ts +12 -1
  270. package/src/runtime/foundation/service-session-binding-ingress-port.ts +2 -1
  271. package/src/runtime/foundation/service-stateful-registry.ts +38 -35
  272. package/src/runtime/foundation/service-stateful-runtime.ts +667 -152
  273. package/src/runtime/foundation/service-stateful-wire-codec.ts +49 -11
  274. package/src/runtime/foundation/service-wire-binary-primitives.ts +35 -12
  275. package/src/runtime/foundation/service-wire-constants.generated.ts +1 -0
  276. package/src/runtime/foundation/service-wire-m6a-codec.ts +187 -51
  277. package/src/runtime/host/actor-packet-relay.ts +113 -94
  278. package/src/runtime/host/actor-placement-coordinator.ts +31 -8
  279. package/src/runtime/host/actor-transfer-runtime.ts +104 -430
  280. package/src/runtime/host/application-job-queue.ts +29 -44
  281. package/src/runtime/host/index.ts +286 -129
  282. package/src/runtime/host/location-runtime-owner.ts +2 -6
  283. package/src/runtime/host/mesh-router-resolver.ts +13 -5
  284. package/src/runtime/host/remote-bound-session-relay.ts +86 -248
  285. package/src/runtime/host/route-mesh-runtime.ts +11 -5
  286. package/src/runtime/host/runtime-shutdown.ts +15 -4
  287. package/src/runtime/host/service-relocation-host-runtime.ts +784 -475
  288. package/src/runtime/host/spot-runtime-options-factory.ts +18 -7
  289. package/src/runtime/host/user-spot-creation-coordinator.ts +41 -100
  290. package/src/runtime/locations/auto-connect-loop.ts +22 -14
  291. package/src/runtime/locations/auto-connect-reconciler.ts +0 -6
  292. package/src/runtime/locations/auto-connect-types.ts +0 -1
  293. package/src/runtime/locations/descriptor-publication.ts +7 -0
  294. package/src/runtime/locations/domain-store-contract.ts +5 -0
  295. package/src/runtime/locations/in-memory-authority-store.ts +85 -23
  296. package/src/runtime/locations/in-memory-location-store.ts +1 -12
  297. package/src/runtime/locations/index.ts +1 -0
  298. package/src/runtime/locations/lease-tracker.ts +2 -9
  299. package/src/runtime/locations/location-store-repository.ts +628 -152
  300. package/src/runtime/locations/relocation-blob.ts +75 -1
  301. package/src/runtime/locations/request-source-resolver.ts +138 -0
  302. package/src/runtime/locations/resolvers.ts +2 -2
  303. package/src/runtime/locations/runtime.ts +70 -40
  304. package/src/runtime/messaging/payload-codec.ts +8 -11
  305. package/src/runtime/messaging/request-result.ts +33 -29
  306. package/src/runtime/protocol/service_wire_codec.generated.ts +87 -4
  307. package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +13 -10
  308. package/src/runtime/spots/formal-remote-actor-admission-registry.ts +3 -2
  309. package/src/runtime/spots/index.ts +375 -281
  310. package/src/runtime/spots/spot-activation-registry.ts +25 -13
  311. package/src/runtime/spots/spot-activation-state.ts +12 -19
  312. package/src/runtime/spots/spot-activation.ts +170 -86
  313. package/src/runtime/spots/spot-actor-admission-coordinator.ts +25 -55
  314. package/src/runtime/spots/spot-actor-membership.ts +0 -15
  315. package/src/runtime/spots/spot-actor-packet-dispatch.ts +56 -11
  316. package/src/runtime/spots/spot-actor-packet-drain.ts +9 -52
  317. package/src/runtime/spots/spot-entry-activation.ts +24 -19
  318. package/src/runtime/spots/spot-handler-registry.ts +15 -4
  319. package/src/runtime/spots/spot-manager-internal-contracts.ts +2 -2
  320. package/src/runtime/spots/spot-manager-public.ts +2 -2
  321. package/src/runtime/spots/spot-node-autoconnect.ts +22 -45
  322. package/src/runtime/spots/spot-node-runtime-manager.ts +197 -67
  323. package/src/runtime/spots/spot-outbound.ts +3 -3
  324. package/src/runtime/spots/spot-remote-codec.ts +9 -2
  325. package/src/runtime/spots/spot-runtime-ports.ts +0 -1
  326. package/src/runtime/spots/spot-serial-executor.ts +97 -25
  327. package/src/runtime/spots/spot-serial-turn-executor.ts +22 -3
  328. package/src/runtime/spots/spot-subscription-dispatch.ts +1 -1
  329. package/src/runtime/spots/spot-timer.ts +413 -157
  330. package/src/runtime/streams/actor-session-binding-registry.ts +236 -64
  331. package/src/runtime/streams/actor-session-binding-runtime-owner.ts +16 -8
  332. package/src/runtime/streams/bound-actor-relay-sender.ts +23 -9
  333. package/src/runtime/streams/bound-session-service.ts +7 -10
  334. package/src/runtime/streams/index.ts +12 -6
  335. package/src/runtime/streams/managed-stream.ts +4 -2
  336. package/src/runtime/streams/native-fallback-bound-session.ts +14 -103
  337. package/src/runtime/streams/session-actor-coordinator.ts +39 -88
  338. package/src/runtime/streams/stream-binding-runtime-ports.ts +3 -9
  339. package/src/runtime/streams/stream-session-runtime.ts +1 -5
  340. package/src/runtime/workers/index.ts +1 -1
@@ -1,3 +1,4 @@
1
+ import type { ZLinkMeshDispatchAdmission } from '../admission';
1
2
  import type {
2
3
  RoutingId,
3
4
  ZLinkMessageContext,
@@ -40,7 +41,8 @@ import {
40
41
  import { codecsForFrameworkPacket } from './channel-framework-packets';
41
42
  import {
42
43
  ZLinkChannelDispatchPipeline,
43
- type ZLinkChannelDispatchFields
44
+ type ZLinkChannelDispatchFields,
45
+ type ZLinkRequestDispatch
44
46
  } from './channel-dispatch-pipeline';
45
47
 
46
48
  export interface ZLinkChannelRequestDispatcherOptions {
@@ -238,7 +240,11 @@ export class ZLinkChannelRequestDispatcher {
238
240
  });
239
241
  }
240
242
 
241
- dispatchMesh(record: ReceiveRecord, signal?: AbortSignal): Promise<void> {
243
+ dispatchMesh(
244
+ record: ReceiveRecord,
245
+ signal?: AbortSignal,
246
+ admit?: ZLinkMeshDispatchAdmission
247
+ ): void | Promise<void> {
242
248
  if (record.parts.length === 0 || record.parts[0].data().length === 0) {
243
249
  return completedChannelReply;
244
250
  }
@@ -270,20 +276,23 @@ export class ZLinkChannelRequestDispatcher {
270
276
  }
271
277
  const correlationId = envelope.header.correlationId ?? undefined;
272
278
  if (envelope.header.kind === ZLinkChannelMessageKind.Command) {
273
- return this.pipeline.dispatchOneWay({
274
- fields: {
275
- messageKind: ZLinkDispatchMessageKind.Send,
276
- packetName,
277
- correlationId,
278
- flowId: envelope.header.flowId,
279
- flowOrigin: envelope.header.flowOrigin
279
+ return this.pipeline.dispatchOneWay(
280
+ {
281
+ fields: {
282
+ messageKind: ZLinkDispatchMessageKind.Send,
283
+ packetName,
284
+ correlationId,
285
+ flowId: envelope.header.flowId,
286
+ flowOrigin: envelope.header.flowOrigin
287
+ },
288
+ envelope,
289
+ codecs: this.options.codecs,
290
+ handler: this.options.sendHandlers?.get(packetName),
291
+ context: this.createMeshContext(envelope, record.sourceNodeRid),
292
+ signal
280
293
  },
281
- envelope,
282
- codecs: this.options.codecs,
283
- handler: this.options.sendHandlers?.get(packetName),
284
- context: this.createMeshContext(envelope, record.sourceNodeRid),
285
- signal
286
- });
294
+ admit
295
+ );
287
296
  }
288
297
  if (envelope.header.kind !== ZLinkChannelMessageKind.Request) {
289
298
  return completedChannelReply;
@@ -295,25 +304,20 @@ export class ZLinkChannelRequestDispatcher {
295
304
  flowId: envelope.header.flowId,
296
305
  flowOrigin: envelope.header.flowOrigin
297
306
  };
298
- return this.pipeline.dispatchRequest({
299
- fields,
300
- envelope,
301
- codecs: this.options.codecs,
302
- handler: this.options.handlers.get(packetName),
303
- context: this.createMeshContext(envelope, record.sourceNodeRid),
304
- signal,
305
- missingHandlerMessage: `No channel request handler is registered for '${this.options.channelName}:${packetName}'.`,
306
- writeReply: (reply) => {
307
- requireMeshReplyAccepted(
308
- record.reply(encodeChannelReplyParts(envelope.header, reply, this.options.codecs))
309
- );
310
- },
311
- writeError: (error) => {
312
- requireMeshReplyAccepted(
313
- record.reply(encodeChannelErrorReplyParts(envelope.header, error))
314
- );
315
- }
316
- });
307
+ return this.pipeline.dispatchRequest(
308
+ new ZLinkMeshRequestDispatch(
309
+ fields,
310
+ envelope,
311
+ this.options.codecs,
312
+ this.options.handlers.get(packetName),
313
+ this.createMeshContext(envelope, record.sourceNodeRid),
314
+ signal,
315
+ record,
316
+ 'channel',
317
+ this.options.channelName
318
+ ),
319
+ admit
320
+ );
317
321
  }
318
322
 
319
323
  private submitReply(
@@ -350,6 +354,43 @@ export class ZLinkChannelRequestDispatcher {
350
354
  }
351
355
  }
352
356
 
357
+ /**
358
+ * One mesh request handed to the dispatch pipeline. The reply writers are
359
+ * methods over the received record instead of per-message closures, and the
360
+ * missing-handler text is built only when no handler exists.
361
+ */
362
+ class ZLinkMeshRequestDispatch<
363
+ TContext extends ZLinkMessageContext
364
+ > implements ZLinkRequestDispatch<TContext> {
365
+ constructor(
366
+ readonly fields: ZLinkChannelDispatchFields,
367
+ readonly envelope: ReturnType<typeof decodeChannelEnvelope>,
368
+ readonly codecs: ZLinkChannelEnvelopeCodecRegistry | undefined,
369
+ readonly handler: ZLinkRequestDispatch<TContext>['handler'],
370
+ readonly context: TContext,
371
+ readonly signal: AbortSignal | undefined,
372
+ private readonly record: ReceiveRecord,
373
+ private readonly handlerSurface: 'channel' | 'routed',
374
+ private readonly channelName: string
375
+ ) {}
376
+
377
+ get missingHandlerMessage(): string {
378
+ return `No ${this.handlerSurface} request handler is registered for '${this.channelName}:${this.fields.packetName}'.`;
379
+ }
380
+
381
+ writeReply(reply: unknown): void {
382
+ requireMeshReplyAccepted(
383
+ this.record.reply(encodeChannelReplyParts(this.envelope.header, reply, this.codecs))
384
+ );
385
+ }
386
+
387
+ writeError(error: unknown): void {
388
+ requireMeshReplyAccepted(
389
+ this.record.reply(encodeChannelErrorReplyParts(this.envelope.header, error))
390
+ );
391
+ }
392
+ }
393
+
353
394
  function requireMeshReplyAccepted(result: number): void {
354
395
  if (result !== SubmitResult.Ok) {
355
396
  throw new ZLinkConfigurationException(
@@ -685,7 +726,11 @@ export class ZLinkRoutePacketDispatcher {
685
726
  });
686
727
  }
687
728
 
688
- dispatchMesh(record: ReceiveRecord, signal?: AbortSignal): Promise<void> {
729
+ dispatchMesh(
730
+ record: ReceiveRecord,
731
+ signal?: AbortSignal,
732
+ admit?: ZLinkMeshDispatchAdmission
733
+ ): void | Promise<void> {
689
734
  if (record.parts.length === 0 || record.parts[0].data().length === 0) {
690
735
  return completedChannelReply;
691
736
  }
@@ -723,7 +768,8 @@ export class ZLinkRoutePacketDispatcher {
723
768
  packetName,
724
769
  sourceNodeRid,
725
770
  record.sourceNodeRid,
726
- signal
771
+ signal,
772
+ admit
727
773
  );
728
774
  }
729
775
  if (envelope.header.kind !== ZLinkChannelMessageKind.Request) {
@@ -737,26 +783,20 @@ export class ZLinkRoutePacketDispatcher {
737
783
  flowId: envelope.header.flowId,
738
784
  flowOrigin: envelope.header.flowOrigin
739
785
  };
740
- const codecs = codecsForFrameworkPacket(packetName, this.codecs);
741
- return this.pipeline.dispatchRequest({
742
- fields,
743
- envelope,
744
- codecs,
745
- handler: this.requestHandlers.get(packetName),
746
- context: this.createRouteContext(envelope, record.sourceNodeRid),
747
- signal,
748
- missingHandlerMessage: `No routed request handler is registered for '${this.routerChannelId}:${packetName}'.`,
749
- writeReply: (reply) => {
750
- requireMeshReplyAccepted(
751
- record.reply(encodeChannelReplyParts(envelope.header, reply, codecs))
752
- );
753
- },
754
- writeError: (error) => {
755
- requireMeshReplyAccepted(
756
- record.reply(encodeChannelErrorReplyParts(envelope.header, error))
757
- );
758
- }
759
- });
786
+ return this.pipeline.dispatchRequest(
787
+ new ZLinkMeshRequestDispatch(
788
+ fields,
789
+ envelope,
790
+ codecsForFrameworkPacket(packetName, this.codecs),
791
+ this.requestHandlers.get(packetName),
792
+ this.createRouteContext(envelope, record.sourceNodeRid),
793
+ signal,
794
+ record,
795
+ 'routed',
796
+ this.routerChannelId
797
+ ),
798
+ admit
799
+ );
760
800
  }
761
801
 
762
802
  async dispatchLocalCommand(
@@ -801,23 +841,27 @@ export class ZLinkRoutePacketDispatcher {
801
841
  packetName: string,
802
842
  sourceRid: string,
803
843
  sourceNodeRid: unknown,
804
- signal?: AbortSignal
805
- ): Promise<void> {
806
- return this.pipeline.dispatchOneWay({
807
- fields: {
808
- messageKind: ZLinkDispatchMessageKind.Send,
809
- packetName,
810
- sourceRid,
811
- correlationId: envelope.header.correlationId ?? undefined,
812
- flowId: envelope.header.flowId,
813
- flowOrigin: envelope.header.flowOrigin
844
+ signal?: AbortSignal,
845
+ admit?: ZLinkMeshDispatchAdmission
846
+ ): void | Promise<void> {
847
+ return this.pipeline.dispatchOneWay(
848
+ {
849
+ fields: {
850
+ messageKind: ZLinkDispatchMessageKind.Send,
851
+ packetName,
852
+ sourceRid,
853
+ correlationId: envelope.header.correlationId ?? undefined,
854
+ flowId: envelope.header.flowId,
855
+ flowOrigin: envelope.header.flowOrigin
856
+ },
857
+ envelope,
858
+ codecs: codecsForFrameworkPacket(packetName, this.codecs),
859
+ handler: this.sendHandlers.get(packetName),
860
+ context: this.createRouteContext(envelope, sourceNodeRid),
861
+ signal
814
862
  },
815
- envelope,
816
- codecs: codecsForFrameworkPacket(packetName, this.codecs),
817
- handler: this.sendHandlers.get(packetName),
818
- context: this.createRouteContext(envelope, sourceNodeRid),
819
- signal
820
- });
863
+ admit
864
+ );
821
865
  }
822
866
 
823
867
  private submitReply(operation: ZLinkMultipartReplyOperation): Promise<void> {
@@ -1,12 +1,11 @@
1
1
  import type { Message } from '../../contracts/Common/Message';
2
2
  import { ZLinkBufferMessage } from '../backend/runtime-message';
3
3
  import type { ZLinkBackendMessageLike as MessageLike } from '../backend/runtime-values';
4
- import { randomUUID } from 'node:crypto';
4
+ import { randomBytes } from 'node:crypto';
5
5
  import { isUtf8 } from 'node:buffer';
6
6
  import {
7
7
  ZLinkFrameworkErrorKind,
8
8
  ZLinkFrameworkException,
9
- ZLinkEncodedPayload,
10
9
  type ZLinkMessageSerializer,
11
10
  type ZLinkFlowOrigin
12
11
  } from '../../contracts';
@@ -18,7 +17,10 @@ import {
18
17
  createInternalFrameworkException
19
18
  } from '../framework-errors-internal';
20
19
  import { resolveFrameworkPacketName } from '../messaging/packet-name';
21
- import { selectSerializerWithContentType } from '../messaging/payload-codec';
20
+ import {
21
+ encodedPayloadFromOwned,
22
+ selectSerializerWithContentType
23
+ } from '../messaging/payload-codec';
22
24
  import { isCanonicalCodecContentType } from '../../contracts/Configuration/CodecContentType';
23
25
  import { parseFrameworkJsonV1, stringifyFrameworkJsonV1 } from '../messaging/framework-json-v1';
24
26
  import { currentOrCreateFlow } from '../diagnostics/flow-context';
@@ -75,9 +77,14 @@ interface PreparedChannelHeader {
75
77
  readonly bytes: Buffer;
76
78
  readonly correlationOffset: number;
77
79
  readonly deadlineOffset: number;
80
+ readonly flowOffset: number;
78
81
  }
79
82
 
80
- type PreparedHeaderVariants = Map<ZLinkChannelMessageKind, Map<boolean, PreparedChannelHeader>>;
83
+ /** Per kind, deadline presence and flow origin (`undefined` when the header carries no flow). */
84
+ type PreparedHeaderVariants = Map<
85
+ ZLinkChannelMessageKind,
86
+ Map<boolean, Map<ZLinkFlowOrigin | undefined, PreparedChannelHeader>>
87
+ >;
81
88
  const preparedChannelHeaders = new WeakMap<
82
89
  ReadonlyMap<string, ZLinkMessageSerializer>,
83
90
  Map<string, Map<string, Map<string, PreparedHeaderVariants>>>
@@ -88,9 +95,24 @@ const CHANNEL_CORRELATION_TEXT_LENGTH = 32;
88
95
  const PREPARED_CHANNEL_CORRELATION = '0'.repeat(CHANNEL_CORRELATION_TEXT_LENGTH);
89
96
  const PREPARED_CHANNEL_DEADLINE = '2000-01-01T00:00:00.000Z';
90
97
  const CHANNEL_CORRELATION_TEXT = /^[0-9a-f]{32}$/;
98
+ const CHANNEL_FLOW_FIELD = ',"flowId":';
99
+ // A flow id is a lowercase UUIDv7 (spec 27 §3): fixed 36 JSON-safe ASCII bytes.
100
+ const PREPARED_CHANNEL_FLOW = '00000000-0000-7000-8000-000000000000';
101
+ const CHANNEL_FLOW_TEXT = /^[0-9a-f-]{36}$/;
102
+
103
+ // A per-process random 64-bit prefix followed by a per-process counter, both
104
+ // as lowercase hex: unique among the runtime's pending requests (spec 06-obs/04
105
+ // §3) without drawing random bytes for every request — the shape Java
106
+ // ZLinkServiceOperationIds uses.
107
+ const CHANNEL_CORRELATION_PREFIX = randomBytes(CHANNEL_CORRELATION_TEXT_LENGTH / 4).toString('hex');
108
+ let channelCorrelationCounter = 0;
91
109
 
92
110
  export function newChannelCorrelationId(): string {
93
- return randomUUID().replaceAll('-', '');
111
+ channelCorrelationCounter += 1;
112
+ return (
113
+ CHANNEL_CORRELATION_PREFIX +
114
+ channelCorrelationCounter.toString(16).padStart(CHANNEL_CORRELATION_TEXT_LENGTH / 2, '0')
115
+ );
94
116
  }
95
117
 
96
118
  export function encodeChannelEnvelopeParts(
@@ -276,6 +298,10 @@ const ERROR_KIND_BY_WIRE_NAME: ReadonlyMap<string, ZLinkFrameworkErrorKind> = ne
276
298
  ERROR_KIND_WIRE_NAMES.map((name, kind) => [name, kind as ZLinkFrameworkErrorKind])
277
299
  );
278
300
 
301
+ export function channelErrorKindFromCode(code: string): ZLinkFrameworkErrorKind | undefined {
302
+ return ERROR_KIND_BY_WIRE_NAME.get(code);
303
+ }
304
+
279
305
  export function channelErrorCodeName(kind: ZLinkFrameworkErrorKind): string {
280
306
  return ERROR_KIND_WIRE_NAMES[kind] ?? 'internal_failure';
281
307
  }
@@ -350,7 +376,7 @@ export function decodeChannelReply<TReply>(
350
376
  }
351
377
  if (serializer !== undefined) {
352
378
  return serializer.deserialize<TReply>(
353
- ZLinkEncodedPayload.from(parts[1].data()),
379
+ encodedPayloadFromOwned(parts[1].data()),
354
380
  Object as never
355
381
  );
356
382
  }
@@ -373,7 +399,7 @@ function decodeChannelError(header: ZLinkChannelEnvelopeHeader): ZLinkChannelDec
373
399
  // Cross-language contract: errorCode carries the snake_case wire name.
374
400
  // An unknown name degrades to InternalFailure, matching the C++
375
401
  // request_failure_mapper fallback for unrecognized codes.
376
- const publicKind = ERROR_KIND_BY_WIRE_NAME.get(code) ?? ZLinkFrameworkErrorKind.InternalFailure;
402
+ const publicKind = channelErrorKindFromCode(code) ?? ZLinkFrameworkErrorKind.InternalFailure;
377
403
  failure = new ZLinkFrameworkException(publicKind, message);
378
404
  }
379
405
  // Cross-language contract (.NET ZLinkErrorOriginWire.RemoteReplyOrigin /
@@ -424,7 +450,7 @@ export function decodeChannelPayload(
424
450
  }
425
451
  const serializer = codecs?.serializers.get(envelope.header.contentType);
426
452
  if (serializer !== undefined) {
427
- return serializer.deserialize(ZLinkEncodedPayload.from(envelope.payload), Object as never);
453
+ return serializer.deserialize(encodedPayloadFromOwned(envelope.payload), Object as never);
428
454
  }
429
455
  if (envelope.header.contentType === BINARY_CONTENT_TYPE) {
430
456
  // The receive loop owns the Message for the duration of dispatch, so
@@ -544,8 +570,9 @@ function encodeChannelHeader(
544
570
  if (
545
571
  codecs !== undefined &&
546
572
  metadata === EMPTY_APPLICATION_METADATA &&
547
- flowId === undefined &&
548
- flowOrigin === undefined &&
573
+ (flowId === undefined
574
+ ? flowOrigin === undefined
575
+ : flowOrigin !== undefined && CHANNEL_FLOW_TEXT.test(flowId)) &&
549
576
  topic === null &&
550
577
  source === undefined &&
551
578
  ((kind === ZLinkChannelMessageKind.Command &&
@@ -576,7 +603,9 @@ function encodeChannelHeader(
576
603
  correlationId,
577
604
  deadline,
578
605
  errorCode,
579
- errorMessage
606
+ errorMessage,
607
+ flowId,
608
+ flowOrigin
580
609
  );
581
610
  }
582
611
  // The wire has a fixed field order. Measure escaped UTF-8 first, then write
@@ -629,7 +658,9 @@ function preparedChannelHeader(
629
658
  correlationId: string | null,
630
659
  deadline: string | null,
631
660
  errorCode: string | null | undefined,
632
- errorMessage: string | null | undefined
661
+ errorMessage: string | null | undefined,
662
+ flowId: string | undefined,
663
+ flowOrigin: ZLinkFlowOrigin | undefined
633
664
  ): Buffer {
634
665
  let channels = preparedChannelHeaders.get(codecs.serializers);
635
666
  if (channels === undefined)
@@ -643,7 +674,9 @@ function preparedChannelHeader(
643
674
  let deadlines = kinds.get(kind);
644
675
  if (deadlines === undefined) kinds.set(kind, (deadlines = new Map()));
645
676
  const hasDeadline = deadline !== null;
646
- let prepared = deadlines.get(hasDeadline);
677
+ let flows = deadlines.get(hasDeadline);
678
+ if (flows === undefined) deadlines.set(hasDeadline, (flows = new Map()));
679
+ let prepared = flows.get(flowOrigin);
647
680
  if (prepared === undefined) {
648
681
  const bytes = encodeChannelHeader(
649
682
  kind,
@@ -657,23 +690,32 @@ function preparedChannelHeader(
657
690
  errorMessage,
658
691
  undefined,
659
692
  EMPTY_APPLICATION_METADATA,
660
- undefined,
661
- undefined
693
+ flowOrigin === undefined ? undefined : PREPARED_CHANNEL_FLOW,
694
+ flowOrigin
662
695
  );
663
696
  prepared = {
664
697
  bytes,
665
698
  correlationOffset:
666
699
  bytes.indexOf(CHANNEL_CORRELATION_FIELD) + CHANNEL_CORRELATION_FIELD.length + 1,
667
- deadlineOffset: bytes.indexOf(CHANNEL_DEADLINE_FIELD) + CHANNEL_DEADLINE_FIELD.length + 1
700
+ deadlineOffset: bytes.indexOf(CHANNEL_DEADLINE_FIELD) + CHANNEL_DEADLINE_FIELD.length + 1,
701
+ flowOffset: bytes.indexOf(CHANNEL_FLOW_FIELD) + CHANNEL_FLOW_FIELD.length + 1
668
702
  };
669
- deadlines.set(hasDeadline, prepared);
703
+ flows.set(flowOrigin, prepared);
670
704
  }
671
- if (correlationId === null) return prepared.bytes;
672
- const bytes = Buffer.alloc(prepared.bytes.byteLength);
705
+ if (correlationId === null && flowId === undefined) return prepared.bytes;
706
+ const bytes = Buffer.allocUnsafe(prepared.bytes.byteLength);
673
707
  prepared.bytes.copy(bytes);
674
- bytes.write(correlationId, prepared.correlationOffset, CHANNEL_CORRELATION_TEXT_LENGTH, 'ascii');
708
+ if (correlationId !== null)
709
+ bytes.write(
710
+ correlationId,
711
+ prepared.correlationOffset,
712
+ CHANNEL_CORRELATION_TEXT_LENGTH,
713
+ 'ascii'
714
+ );
675
715
  if (deadline !== null)
676
716
  bytes.write(deadline, prepared.deadlineOffset, PREPARED_CHANNEL_DEADLINE.length, 'ascii');
717
+ if (flowId !== undefined)
718
+ bytes.write(flowId, prepared.flowOffset, PREPARED_CHANNEL_FLOW.length, 'ascii');
677
719
  return bytes;
678
720
  }
679
721
 
@@ -859,13 +901,18 @@ function parseWireJson(payload: string, schema?: ZLinkJsonSchema): unknown {
859
901
  }
860
902
 
861
903
  function parseChannelHeaderBytes(payload: Buffer): unknown {
904
+ const reader = new CanonicalChannelHeaderReader(payload);
905
+ const canonical = tryParseCanonicalChannelHeader(reader);
906
+ // An all-ASCII canonical header is valid UTF-8 by construction; any other
907
+ // header is checked before it is decoded.
908
+ if (canonical !== undefined && !reader.sawNonAscii) return canonical;
862
909
  if (!isUtf8(payload)) {
863
910
  throw new ZLinkFrameworkException(
864
911
  ZLinkFrameworkErrorKind.ProtocolError,
865
912
  'Channel envelope header must contain valid UTF-8.'
866
913
  );
867
914
  }
868
- return tryParseCanonicalChannelHeader(payload) ?? parseFrameworkJsonV1(payload.toString());
915
+ return canonical ?? parseFrameworkJsonV1(payload.toString());
869
916
  }
870
917
 
871
918
  /**
@@ -874,8 +921,9 @@ function parseChannelHeaderBytes(payload: Buffer): unknown {
874
921
  * framework-json-v1 parser, which remains the sole authority for JSON
875
922
  * failures and unknown properties. Header metadata accepts every valid string key.
876
923
  */
877
- function tryParseCanonicalChannelHeader(payload: Buffer): Record<string, unknown> | undefined {
878
- const reader = new CanonicalChannelHeaderReader(payload);
924
+ function tryParseCanonicalChannelHeader(
925
+ reader: CanonicalChannelHeaderReader
926
+ ): Record<string, unknown> | undefined {
879
927
  if (!reader.consume('{"formatMarker":242,"kind":')) return undefined;
880
928
  const kind = reader.readSingleDigit();
881
929
  if (kind === undefined || !reader.consume(',"channelName":')) return undefined;
@@ -902,20 +950,31 @@ function tryParseCanonicalChannelHeader(payload: Buffer): Record<string, unknown
902
950
  deadline: deadline === NULL_JSON_STRING ? null : deadline,
903
951
  topic: topic === NULL_JSON_STRING ? null : topic
904
952
  };
905
- if (!reader.readOptionalNullableString('errorCode', header)) return undefined;
906
- if (!reader.readOptionalNullableString('errorMessage', header)) return undefined;
907
- if (!reader.readOptionalNullableString('source', header)) return undefined;
953
+ if (!reader.readOptionalNullableString(CANONICAL_ERROR_CODE, 'errorCode', header))
954
+ return undefined;
955
+ if (!reader.readOptionalNullableString(CANONICAL_ERROR_MESSAGE, 'errorMessage', header))
956
+ return undefined;
957
+ if (!reader.readOptionalNullableString(CANONICAL_SOURCE, 'source', header)) return undefined;
958
+ // Empty metadata validates to the shared empty record.
908
959
  if (!reader.consume(',"metadata":{}')) return undefined;
909
- header.metadata = {};
910
- if (!reader.readOptionalString('flowId', header)) return undefined;
911
- if (!reader.readOptionalSingleDigit('flowOrigin', header)) return undefined;
960
+ if (!reader.readOptionalString(CANONICAL_FLOW_ID, 'flowId', header)) return undefined;
961
+ if (!reader.readOptionalSingleDigit(CANONICAL_FLOW_ORIGIN, 'flowOrigin', header))
962
+ return undefined;
912
963
  return reader.consume('}') && reader.atEnd() ? header : undefined;
913
964
  }
914
965
 
966
+ const CANONICAL_ERROR_CODE = ',"errorCode":';
967
+ const CANONICAL_ERROR_MESSAGE = ',"errorMessage":';
968
+ const CANONICAL_SOURCE = ',"source":';
969
+ const CANONICAL_FLOW_ID = ',"flowId":';
970
+ const CANONICAL_FLOW_ORIGIN = ',"flowOrigin":';
971
+
915
972
  const NULL_JSON_STRING = Symbol('null JSON string');
916
973
 
917
974
  class CanonicalChannelHeaderReader {
918
975
  private index = 0;
976
+ /** A string held a byte outside ASCII, so the caller must still check UTF-8. */
977
+ sawNonAscii = false;
919
978
 
920
979
  constructor(private readonly bytes: Buffer) {}
921
980
 
@@ -944,13 +1003,19 @@ class CanonicalChannelHeaderReader {
944
1003
  if (this.bytes[this.index] !== 0x22) return undefined;
945
1004
  const start = this.index;
946
1005
  this.index += 1;
1006
+ let hasEscape = false;
947
1007
  while (this.index < this.bytes.length) {
948
1008
  const value = this.bytes[this.index++]!;
949
1009
  if (value === 0x22) {
950
- return JSON.parse(this.bytes.toString('utf8', start, this.index)) as string;
1010
+ // Without escapes the JSON string is its own bytes; decode them once.
1011
+ return hasEscape
1012
+ ? (JSON.parse(this.bytes.toString('utf8', start, this.index)) as string)
1013
+ : this.bytes.toString(this.sawNonAscii ? 'utf8' : 'latin1', start + 1, this.index - 1);
951
1014
  }
952
1015
  if (value < 0x20) return undefined;
1016
+ if (value >= 0x80) this.sawNonAscii = true;
953
1017
  if (value !== 0x5c) continue;
1018
+ hasEscape = true;
954
1019
  if (this.index === this.bytes.length) return undefined;
955
1020
  const escaped = this.bytes[this.index++]!;
956
1021
  if (escaped === 0x75) {
@@ -980,24 +1045,28 @@ class CanonicalChannelHeaderReader {
980
1045
  return this.readString();
981
1046
  }
982
1047
 
983
- readOptionalNullableString(name: string, target: Record<string, unknown>): boolean {
984
- if (!this.consume(`,\"${name}\":`)) return true;
1048
+ readOptionalNullableString(
1049
+ token: string,
1050
+ name: string,
1051
+ target: Record<string, unknown>
1052
+ ): boolean {
1053
+ if (!this.consume(token)) return true;
985
1054
  const value = this.readNullableString();
986
1055
  if (value === undefined) return false;
987
1056
  target[name] = value === NULL_JSON_STRING ? null : value;
988
1057
  return true;
989
1058
  }
990
1059
 
991
- readOptionalString(name: string, target: Record<string, unknown>): boolean {
992
- if (!this.consume(`,\"${name}\":`)) return true;
1060
+ readOptionalString(token: string, name: string, target: Record<string, unknown>): boolean {
1061
+ if (!this.consume(token)) return true;
993
1062
  const value = this.readString();
994
1063
  if (value === undefined) return false;
995
1064
  target[name] = value;
996
1065
  return true;
997
1066
  }
998
1067
 
999
- readOptionalSingleDigit(name: string, target: Record<string, unknown>): boolean {
1000
- if (!this.consume(`,\"${name}\":`)) return true;
1068
+ readOptionalSingleDigit(token: string, name: string, target: Record<string, unknown>): boolean {
1069
+ if (!this.consume(token)) return true;
1001
1070
  const value = this.readSingleDigit();
1002
1071
  if (value === undefined) return false;
1003
1072
  target[name] = value;
@@ -1,3 +1,4 @@
1
+ import type { ZLinkMeshDispatchAdmission } from '../admission';
1
2
  import { RuntimeDisposal } from '../disposal';
2
3
  import type { ZLinkLocationOptionOverrides } from '../../contracts/Locations/Options';
3
4
  import type { ZLinkRequestHandler, ZLinkSendHandler } from '../../contracts/Handlers';
@@ -50,12 +51,9 @@ import {
50
51
  endpointConnections
51
52
  } from '../../contracts/Configuration/RuntimeEndpointConnections';
52
53
  import type { ApplicationJobQueue } from '../host/application-job-queue';
53
- import { AsyncResource } from 'node:async_hooks';
54
- import { ZLinkStateLane } from '../execution/state-lane';
54
+ import { startOutsideStateLane, ZLinkStateLane } from '../execution/state-lane';
55
55
  import { ZLinkSerialExecutionQueue } from '../execution/serial-execution-queue';
56
56
 
57
- const detachedStateLaneResource = new AsyncResource('zlink:channel-runtime-lifecycle');
58
-
59
57
  interface ManualFanoutSubscriberState {
60
58
  readonly channelName: string;
61
59
  readonly endpoint: string;
@@ -349,8 +347,9 @@ export class ZLinkChannelRuntimeLifecycle {
349
347
  dispatchMeshChannel(
350
348
  meshName: string,
351
349
  record: ReceiveRecord,
352
- signal?: AbortSignal
353
- ): Promise<void> {
350
+ signal?: AbortSignal,
351
+ admit?: ZLinkMeshDispatchAdmission
352
+ ): void | Promise<void> {
354
353
  const channelName = record.channelName;
355
354
  if (channelName === null) {
356
355
  throw new ZLinkConfigurationException('MeshNode channel record is missing channelName.');
@@ -361,17 +360,22 @@ export class ZLinkChannelRuntimeLifecycle {
361
360
  `RouteMesh '${meshName}' channel '${channelName}' has no registered handlers.`
362
361
  );
363
362
  }
364
- return dispatcher.dispatchMesh(record, signal);
363
+ return dispatcher.dispatchMesh(record, signal, admit);
365
364
  }
366
365
 
367
- dispatchMeshRoute(meshName: string, record: ReceiveRecord, signal?: AbortSignal): Promise<void> {
366
+ dispatchMeshRoute(
367
+ meshName: string,
368
+ record: ReceiveRecord,
369
+ signal?: AbortSignal,
370
+ admit?: ZLinkMeshDispatchAdmission
371
+ ): void | Promise<void> {
368
372
  const dispatcher = this.meshRouteDispatchers.get(meshName);
369
373
  if (dispatcher === undefined) {
370
374
  throw new ZLinkConfigurationException(
371
375
  `RouteMesh '${meshName}' has no registered node-direct handlers.`
372
376
  );
373
377
  }
374
- return dispatcher.dispatchMesh(record, signal);
378
+ return dispatcher.dispatchMesh(record, signal, admit);
375
379
  }
376
380
 
377
381
  dispatchLocalMeshRoute(
@@ -1060,7 +1064,3 @@ function hasFanoutLocationTopology(registration: ZLinkFrameworkRegistration): bo
1060
1064
  }
1061
1065
  return false;
1062
1066
  }
1063
-
1064
- function startOutsideStateLane<T>(work: () => T): T {
1065
- return detachedStateLaneResource.runInAsyncScope(work);
1066
- }
@@ -1,3 +1,4 @@
1
+ import type { ZLinkMeshDispatchAdmission } from '../admission';
1
2
  import type { ZLinkListenerRecords } from '../foundation/listener-records';
2
3
  import type { ZLinkLocationOptionOverrides } from '../../contracts/Locations/Options';
3
4
  import type { RoutingId } from '../../contracts';
@@ -207,13 +208,19 @@ export class ZLinkChannelRuntimeManager {
207
208
  dispatchMeshChannel(
208
209
  meshName: string,
209
210
  record: ReceiveRecord,
210
- signal?: AbortSignal
211
- ): Promise<void> {
212
- return this.lifecycle.dispatchMeshChannel(meshName, record, signal);
211
+ signal?: AbortSignal,
212
+ admit?: ZLinkMeshDispatchAdmission
213
+ ): void | Promise<void> {
214
+ return this.lifecycle.dispatchMeshChannel(meshName, record, signal, admit);
213
215
  }
214
216
 
215
- dispatchMeshRoute(meshName: string, record: ReceiveRecord, signal?: AbortSignal): Promise<void> {
216
- return this.lifecycle.dispatchMeshRoute(meshName, record, signal);
217
+ dispatchMeshRoute(
218
+ meshName: string,
219
+ record: ReceiveRecord,
220
+ signal?: AbortSignal,
221
+ admit?: ZLinkMeshDispatchAdmission
222
+ ): void | Promise<void> {
223
+ return this.lifecycle.dispatchMeshRoute(meshName, record, signal, admit);
217
224
  }
218
225
 
219
226
  dispatchLocalMeshRoute(