@zlink-systems/framework 0.30.3 → 0.32.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (398) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/contracts/Actors/ZLinkActor.d.ts +2 -0
  3. package/dist/contracts/Actors/ZLinkSessionBindingIdentity.d.ts +6 -0
  4. package/dist/contracts/Actors/ZLinkSessionBindingIdentity.js +2 -0
  5. package/dist/contracts/Actors/index.d.ts +1 -0
  6. package/dist/contracts/Actors/index.js +1 -0
  7. package/dist/contracts/Common/CoreTypes.d.ts +1 -0
  8. package/dist/contracts/Common/HandlerMessageType.d.ts +8 -0
  9. package/dist/contracts/Common/HandlerMessageType.js +41 -0
  10. package/dist/contracts/Common/ZLinkEncodedPayload.d.ts +1 -1
  11. package/dist/contracts/Common/ZLinkEncodedPayload.js +12 -20
  12. package/dist/contracts/Common/ZLinkMessage.js +11 -7
  13. package/dist/contracts/Common/encoded-payload-storage.d.ts +0 -2
  14. package/dist/contracts/Common/encoded-payload-storage.js +4 -16
  15. package/dist/contracts/Common/index.d.ts +1 -1
  16. package/dist/contracts/Common/payload-slab.d.ts +4 -0
  17. package/dist/contracts/Common/payload-slab.js +30 -0
  18. package/dist/contracts/Configuration/RegistrationBuilders.js +15 -9
  19. package/dist/contracts/Configuration/RegistrationTypes.d.ts +19 -0
  20. package/dist/contracts/Handlers/Contexts.d.ts +1 -0
  21. package/dist/contracts/Locations/Authority.d.ts +2 -0
  22. package/dist/internal.d.ts +9 -0
  23. package/dist/internal.js +23 -1
  24. package/dist/nest-integration.d.ts +1 -0
  25. package/dist/nest-integration.js +3 -1
  26. package/dist/runtime/actors/actor-client.d.ts +6 -2
  27. package/dist/runtime/actors/actor-client.js +120 -82
  28. package/dist/runtime/actors/actor-context.js +16 -5
  29. package/dist/runtime/actors/actor-execution-context.js +2 -2
  30. package/dist/runtime/actors/actor-handoff.d.ts +12 -1
  31. package/dist/runtime/actors/actor-handoff.js +79 -34
  32. package/dist/runtime/actors/actor-join-deferred-scope.js +6 -6
  33. package/dist/runtime/actors/actor-local-native-join.d.ts +2 -2
  34. package/dist/runtime/actors/actor-local-native-join.js +19 -17
  35. package/dist/runtime/actors/actor-mailbox.d.ts +1 -1
  36. package/dist/runtime/actors/actor-remote-joiner.d.ts +2 -2
  37. package/dist/runtime/actors/actor-remote-joiner.js +4 -4
  38. package/dist/runtime/actors/actor-routed-join-transport.d.ts +9 -3
  39. package/dist/runtime/actors/actor-routed-json-request.d.ts +3 -0
  40. package/dist/runtime/actors/actor-runtime-contracts.d.ts +2 -2
  41. package/dist/runtime/actors/actor-runtime-state.d.ts +1 -1
  42. package/dist/runtime/actors/spot-actor-dispatch.d.ts +9 -5
  43. package/dist/runtime/actors/spot-actor-dispatch.js +60 -38
  44. package/dist/runtime/admission.d.ts +6 -4
  45. package/dist/runtime/admission.js +21 -10
  46. package/dist/runtime/application-jobs/application-ingress-record-owner.d.ts +1 -0
  47. package/dist/runtime/application-jobs/application-ingress-record-owner.js +3 -0
  48. package/dist/runtime/backend/contracts/index.d.ts +26 -10
  49. package/dist/runtime/backend/mesh-completion-table.d.ts +7 -1
  50. package/dist/runtime/backend/mesh-completion-table.js +84 -20
  51. package/dist/runtime/backend/mesh-dispatch-pump.d.ts +19 -6
  52. package/dist/runtime/backend/mesh-dispatch-pump.js +246 -147
  53. package/dist/runtime/backend/node/node-backend-adapter-support.d.ts +3 -2
  54. package/dist/runtime/backend/node/node-backend-adapter-support.js +27 -19
  55. package/dist/runtime/backend/node/node-dealer-channel-client-transport.d.ts +5 -2
  56. package/dist/runtime/backend/node/node-dealer-channel-client-transport.js +70 -13
  57. package/dist/runtime/backend/node/node-event-loop-poller.d.ts +2 -2
  58. package/dist/runtime/backend/node/node-event-loop-poller.js +4 -3
  59. package/dist/runtime/backend/node/node-mesh-backend-adapter.js +5 -1
  60. package/dist/runtime/backend/node/node-raw-binding-port.d.ts +7 -2
  61. package/dist/runtime/backend/node/node-raw-binding-port.js +99 -63
  62. package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +34 -16
  63. package/dist/runtime/backend/node/node-raw-mesh-backend.js +210 -106
  64. package/dist/runtime/backend/node/node-socket-backend-adapter.js +20 -6
  65. package/dist/runtime/backend/raw-binding-port.d.ts +6 -3
  66. package/dist/runtime/channels/channel-clients.js +3 -3
  67. package/dist/runtime/channels/channel-dispatch-pipeline.d.ts +11 -7
  68. package/dist/runtime/channels/channel-dispatch-pipeline.js +40 -22
  69. package/dist/runtime/channels/channel-dispatch-services.d.ts +3 -1
  70. package/dist/runtime/channels/channel-dispatch-services.js +7 -6
  71. package/dist/runtime/channels/channel-dispatchers.d.ts +13 -6
  72. package/dist/runtime/channels/channel-dispatchers.js +57 -36
  73. package/dist/runtime/channels/channel-envelope.d.ts +2 -2
  74. package/dist/runtime/channels/channel-envelope.js +609 -83
  75. package/dist/runtime/channels/channel-multipart.d.ts +1 -0
  76. package/dist/runtime/channels/channel-multipart.js +10 -6
  77. package/dist/runtime/channels/channel-outbound-operations.d.ts +6 -9
  78. package/dist/runtime/channels/channel-outbound-operations.js +107 -105
  79. package/dist/runtime/channels/channel-receive-loops.d.ts +9 -7
  80. package/dist/runtime/channels/channel-receive-loops.js +126 -90
  81. package/dist/runtime/channels/channel-runtime-lifecycle.d.ts +23 -6
  82. package/dist/runtime/channels/channel-runtime-lifecycle.js +47 -38
  83. package/dist/runtime/channels/channel-runtime-manager.d.ts +13 -6
  84. package/dist/runtime/channels/channel-runtime-manager.js +32 -14
  85. package/dist/runtime/channels/channel-socket-registry.d.ts +28 -4
  86. package/dist/runtime/channels/channel-socket-registry.js +9 -1
  87. package/dist/runtime/channels/channel-transports.d.ts +23 -16
  88. package/dist/runtime/channels/channel-transports.js +139 -119
  89. package/dist/runtime/channels/dispatch-error-reporter.d.ts +4 -4
  90. package/dist/runtime/channels/dispatch-error-reporter.js +5 -5
  91. package/dist/runtime/channels/fanout-location-runtime.d.ts +1 -1
  92. package/dist/runtime/channels/local-spot-route-transport.d.ts +5 -2
  93. package/dist/runtime/channels/local-spot-route-transport.js +15 -18
  94. package/dist/runtime/channels/router-socket-spot-route-transport.d.ts +6 -3
  95. package/dist/runtime/channels/router-socket-spot-route-transport.js +33 -19
  96. package/dist/runtime/channels/source-spot-router.d.ts +6 -3
  97. package/dist/runtime/channels/source-spot-router.js +34 -23
  98. package/dist/runtime/channels/spot-node-route-transport.d.ts +6 -3
  99. package/dist/runtime/channels/spot-node-route-transport.js +23 -17
  100. package/dist/runtime/channels/spot-route-bridge-transport.d.ts +6 -3
  101. package/dist/runtime/channels/spot-route-bridge-transport.js +38 -24
  102. package/dist/runtime/channels/spot-route-dispatch-strategy.d.ts +8 -4
  103. package/dist/runtime/channels/spot-route-dispatch-strategy.js +36 -23
  104. package/dist/runtime/diagnostics/dispatch-error-details.js +9 -3
  105. package/dist/runtime/diagnostics/message-flow-bootstrap.d.ts +1 -0
  106. package/dist/runtime/diagnostics/message-flow-bootstrap.js +8 -0
  107. package/dist/runtime/diagnostics/message-flow-delivery.d.ts +47 -0
  108. package/dist/runtime/diagnostics/message-flow-delivery.js +149 -0
  109. package/dist/runtime/diagnostics/message-flow-record.d.ts +50 -0
  110. package/dist/runtime/diagnostics/message-flow-record.js +228 -0
  111. package/dist/runtime/diagnostics/message-flow-worker.d.ts +1 -0
  112. package/dist/runtime/diagnostics/message-flow-worker.js +118 -0
  113. package/dist/runtime/diagnostics/message-flow.d.ts +7 -19
  114. package/dist/runtime/diagnostics/message-flow.js +42 -290
  115. package/dist/runtime/diagnostics/runtime-metrics.d.ts +4 -3
  116. package/dist/runtime/diagnostics/runtime-metrics.js +8 -4
  117. package/dist/runtime/execution/index.d.ts +1 -0
  118. package/dist/runtime/execution/index.js +6 -3
  119. package/dist/runtime/execution/serial-execution-queue.d.ts +26 -13
  120. package/dist/runtime/execution/serial-execution-queue.js +75 -71
  121. package/dist/runtime/foundation/durable-service-request.d.ts +12 -3
  122. package/dist/runtime/foundation/durable-service-request.js +158 -73
  123. package/dist/runtime/foundation/operation-registry.d.ts +33 -3
  124. package/dist/runtime/foundation/operation-registry.js +272 -33
  125. package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +62 -23
  126. package/dist/runtime/foundation/raw-service-mesh-runtime.js +373 -194
  127. package/dist/runtime/foundation/request-runtime.d.ts +17 -0
  128. package/dist/runtime/foundation/request-runtime.js +163 -0
  129. package/dist/runtime/foundation/service-discovery-registry.d.ts +4 -0
  130. package/dist/runtime/foundation/service-discovery-registry.js +6 -0
  131. package/dist/runtime/foundation/service-liveness-registry.d.ts +1 -1
  132. package/dist/runtime/foundation/service-mailbox.d.ts +4 -2
  133. package/dist/runtime/foundation/service-mailbox.js +4 -1
  134. package/dist/runtime/foundation/service-relocation-object-owner.d.ts +2 -2
  135. package/dist/runtime/foundation/service-relocation-object-owner.js +12 -5
  136. package/dist/runtime/foundation/service-runtime-contracts.d.ts +7 -2
  137. package/dist/runtime/foundation/service-stateful-registry.d.ts +6 -2
  138. package/dist/runtime/foundation/service-stateful-registry.js +38 -17
  139. package/dist/runtime/foundation/service-stateful-runtime.d.ts +91 -26
  140. package/dist/runtime/foundation/service-stateful-runtime.js +245 -120
  141. package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +3 -0
  142. package/dist/runtime/foundation/service-stateful-wire-codec.js +15 -0
  143. package/dist/runtime/foundation/service-topology-registry.d.ts +2 -0
  144. package/dist/runtime/foundation/service-topology-registry.js +13 -3
  145. package/dist/runtime/foundation/service-wire-constants.generated.d.ts +1 -0
  146. package/dist/runtime/foundation/service-wire-constants.generated.js +12 -0
  147. package/dist/runtime/foundation/service-wire-m6a-codec.d.ts +5 -1
  148. package/dist/runtime/foundation/service-wire-m6a-codec.js +50 -15
  149. package/dist/runtime/host/actor-packet-relay.d.ts +5 -6
  150. package/dist/runtime/host/actor-packet-relay.js +58 -57
  151. package/dist/runtime/host/actor-placement-coordinator.d.ts +1 -1
  152. package/dist/runtime/host/actor-runtime-options-factory.d.ts +2 -0
  153. package/dist/runtime/host/actor-runtime-options-factory.js +3 -2
  154. package/dist/runtime/host/actor-transfer-runtime.d.ts +3 -3
  155. package/dist/runtime/host/application-job-queue.d.ts +7 -5
  156. package/dist/runtime/host/application-job-queue.js +33 -21
  157. package/dist/runtime/host/bound-session-relay.js +0 -1
  158. package/dist/runtime/host/channel-runtime-options-factory.d.ts +2 -0
  159. package/dist/runtime/host/channel-runtime-options-factory.js +1 -0
  160. package/dist/runtime/host/entry-actor-runtime.d.ts +5 -2
  161. package/dist/runtime/host/entry-actor-runtime.js +2 -2
  162. package/dist/runtime/host/index.d.ts +106 -37
  163. package/dist/runtime/host/index.js +303 -151
  164. package/dist/runtime/host/location-runtime-owner.d.ts +2 -2
  165. package/dist/runtime/host/location-runtime-owner.js +1 -1
  166. package/dist/runtime/host/service-relocation-host-runtime.d.ts +195 -45
  167. package/dist/runtime/host/service-relocation-host-runtime.js +257 -144
  168. package/dist/runtime/host/spot-address-transport.d.ts +3 -0
  169. package/dist/runtime/host/spot-address-transport.js +73 -76
  170. package/dist/runtime/host/spot-runtime-options-factory.js +2 -0
  171. package/dist/runtime/host/user-spot-creation-coordinator.d.ts +3 -1
  172. package/dist/runtime/host/user-spot-creation-coordinator.js +49 -21
  173. package/dist/runtime/internal-observation.d.ts +1 -0
  174. package/dist/runtime/internal-observation.js +5 -0
  175. package/dist/runtime/locations/actor-location-claims.d.ts +1 -1
  176. package/dist/runtime/locations/actor-location-claims.js +15 -6
  177. package/dist/runtime/locations/auto-connect-loop.d.ts +0 -1
  178. package/dist/runtime/locations/auto-connect-loop.js +25 -19
  179. package/dist/runtime/locations/auto-connect-planner.js +2 -5
  180. package/dist/runtime/locations/auto-connect-reconciler.d.ts +1 -0
  181. package/dist/runtime/locations/auto-connect-reconciler.js +35 -23
  182. package/dist/runtime/locations/in-memory-authority-store.d.ts +1 -0
  183. package/dist/runtime/locations/in-memory-authority-store.js +15 -5
  184. package/dist/runtime/locations/in-memory-location-store.d.ts +0 -2
  185. package/dist/runtime/locations/in-memory-location-store.js +1 -38
  186. package/dist/runtime/locations/lifecycle.d.ts +1 -1
  187. package/dist/runtime/locations/lifecycle.js +2 -2
  188. package/dist/runtime/locations/location-store-repository.d.ts +0 -1
  189. package/dist/runtime/locations/location-store-repository.js +163 -246
  190. package/dist/runtime/locations/resolvers.d.ts +8 -1
  191. package/dist/runtime/locations/resolvers.js +16 -2
  192. package/dist/runtime/locations/runtime.d.ts +3 -3
  193. package/dist/runtime/locations/runtime.js +12 -16
  194. package/dist/runtime/messaging/creation-payload-codec.js +8 -7
  195. package/dist/runtime/messaging/framework-json-v1.d.ts +1 -1
  196. package/dist/runtime/messaging/framework-json-v1.js +6 -2
  197. package/dist/runtime/messaging/payload-codec.js +21 -35
  198. package/dist/runtime/messaging/request-deadline.d.ts +4 -2
  199. package/dist/runtime/messaging/request-deadline.js +40 -25
  200. package/dist/runtime/messaging/request-result.d.ts +14 -1
  201. package/dist/runtime/messaging/request-result.js +74 -13
  202. package/dist/runtime/protocol/service_wire_codec.generated.d.ts +4 -0
  203. package/dist/runtime/protocol/service_wire_codec.generated.js +17 -7
  204. package/dist/runtime/spots/index.d.ts +28 -7
  205. package/dist/runtime/spots/index.js +31 -6
  206. package/dist/runtime/spots/spot-activation-registry.d.ts +3 -2
  207. package/dist/runtime/spots/spot-activation-registry.js +13 -8
  208. package/dist/runtime/spots/spot-activation-state.d.ts +2 -0
  209. package/dist/runtime/spots/spot-activation-state.js +1 -0
  210. package/dist/runtime/spots/spot-actor-admission-coordinator.d.ts +9 -4
  211. package/dist/runtime/spots/spot-actor-admission-coordinator.js +33 -12
  212. package/dist/runtime/spots/spot-actor-ingress-admission.d.ts +40 -0
  213. package/dist/runtime/spots/spot-actor-ingress-admission.js +78 -0
  214. package/dist/runtime/spots/spot-actor-membership.js +3 -3
  215. package/dist/runtime/spots/spot-actor-packet-dispatch.d.ts +16 -43
  216. package/dist/runtime/spots/spot-actor-packet-dispatch.js +56 -113
  217. package/dist/runtime/spots/spot-actor-packet-drain.d.ts +1 -0
  218. package/dist/runtime/spots/spot-actor-packet-drain.js +12 -5
  219. package/dist/runtime/spots/spot-entry-activation.d.ts +4 -3
  220. package/dist/runtime/spots/spot-entry-activation.js +7 -12
  221. package/dist/runtime/spots/spot-handler-registry.d.ts +5 -1
  222. package/dist/runtime/spots/spot-handler-registry.js +31 -15
  223. package/dist/runtime/spots/spot-manager-public.js +3 -2
  224. package/dist/runtime/spots/spot-node-runtime-manager.d.ts +11 -6
  225. package/dist/runtime/spots/spot-node-runtime-manager.js +6 -1
  226. package/dist/runtime/spots/spot-outbound.d.ts +8 -2
  227. package/dist/runtime/spots/spot-outbound.js +5 -5
  228. package/dist/runtime/spots/spot-route-packet-dispatch.js +13 -8
  229. package/dist/runtime/spots/spot-routed-spot-packet-dispatch.d.ts +3 -3
  230. package/dist/runtime/spots/spot-routed-spot-packet-dispatch.js +9 -5
  231. package/dist/runtime/spots/spot-runtime-ports.d.ts +2 -2
  232. package/dist/runtime/spots/spot-serial-executor.d.ts +2 -1
  233. package/dist/runtime/spots/spot-serial-turn-executor.js +20 -26
  234. package/dist/runtime/spots/spot-subscription-dispatch.js +5 -2
  235. package/dist/runtime/spots/spot-timer.d.ts +1 -1
  236. package/dist/runtime/streams/actor-session-binding-registry.d.ts +11 -3
  237. package/dist/runtime/streams/actor-session-binding-registry.js +28 -0
  238. package/dist/runtime/streams/bound-actor-relay-sender.d.ts +2 -2
  239. package/dist/runtime/streams/bound-actor-relay-sender.js +3 -4
  240. package/dist/runtime/streams/bound-session-service.js +6 -7
  241. package/dist/runtime/streams/index.d.ts +3 -3
  242. package/dist/runtime/streams/index.js +22 -2
  243. package/dist/runtime/streams/managed-stream.js +2 -1
  244. package/dist/runtime/streams/session-calls.d.ts +1 -1
  245. package/dist/runtime/streams/session-calls.js +3 -9
  246. package/dist/runtime/streams/session-context.d.ts +2 -2
  247. package/dist/runtime/streams/session-context.js +2 -2
  248. package/dist/runtime/streams/stream-session-runtime.d.ts +1 -0
  249. package/dist/runtime/streams/stream-session-runtime.js +64 -33
  250. package/package.json +3 -3
  251. package/src/contracts/Actors/ZLinkActor.ts +6 -0
  252. package/src/contracts/Actors/ZLinkSessionBindingIdentity.ts +7 -0
  253. package/src/contracts/Actors/index.ts +1 -0
  254. package/src/contracts/Common/CoreTypes.ts +1 -0
  255. package/src/contracts/Common/HandlerMessageType.ts +50 -0
  256. package/src/contracts/Common/ZLinkEncodedPayload.ts +13 -25
  257. package/src/contracts/Common/ZLinkMessage.ts +11 -7
  258. package/src/contracts/Common/encoded-payload-storage.ts +4 -16
  259. package/src/contracts/Common/index.ts +1 -1
  260. package/src/contracts/Common/payload-slab.ts +29 -0
  261. package/src/contracts/Configuration/RegistrationBuilders.ts +29 -15
  262. package/src/contracts/Configuration/RegistrationTypes.ts +19 -0
  263. package/src/contracts/Handlers/Contexts.ts +1 -0
  264. package/src/contracts/Locations/Authority.ts +7 -1
  265. package/src/internal.ts +17 -0
  266. package/src/nest-integration.ts +1 -0
  267. package/src/runtime/actors/actor-client.ts +257 -163
  268. package/src/runtime/actors/actor-context.ts +26 -14
  269. package/src/runtime/actors/actor-execution-context.ts +2 -2
  270. package/src/runtime/actors/actor-handoff.ts +86 -51
  271. package/src/runtime/actors/actor-join-deferred-scope.ts +6 -6
  272. package/src/runtime/actors/actor-local-native-join.ts +38 -17
  273. package/src/runtime/actors/actor-mailbox.ts +1 -1
  274. package/src/runtime/actors/actor-remote-joiner.ts +8 -4
  275. package/src/runtime/actors/actor-routed-join-transport.ts +13 -5
  276. package/src/runtime/actors/actor-routed-json-request.ts +3 -0
  277. package/src/runtime/actors/actor-runtime-contracts.ts +4 -2
  278. package/src/runtime/actors/actor-runtime-state.ts +1 -1
  279. package/src/runtime/actors/spot-actor-dispatch.ts +70 -68
  280. package/src/runtime/admission.ts +42 -15
  281. package/src/runtime/application-jobs/application-ingress-record-owner.ts +4 -0
  282. package/src/runtime/backend/contracts/index.ts +77 -10
  283. package/src/runtime/backend/mesh-completion-table.ts +106 -15
  284. package/src/runtime/backend/mesh-dispatch-pump.ts +294 -146
  285. package/src/runtime/backend/node/node-backend-adapter-support.ts +42 -32
  286. package/src/runtime/backend/node/node-dealer-channel-client-transport.ts +91 -34
  287. package/src/runtime/backend/node/node-event-loop-poller.ts +14 -5
  288. package/src/runtime/backend/node/node-mesh-backend-adapter.ts +5 -1
  289. package/src/runtime/backend/node/node-raw-binding-port.ts +180 -69
  290. package/src/runtime/backend/node/node-raw-mesh-backend.ts +386 -157
  291. package/src/runtime/backend/node/node-socket-backend-adapter.ts +56 -11
  292. package/src/runtime/backend/raw-binding-port.ts +13 -5
  293. package/src/runtime/channels/channel-clients.ts +26 -11
  294. package/src/runtime/channels/channel-dispatch-pipeline.ts +77 -65
  295. package/src/runtime/channels/channel-dispatch-services.ts +7 -12
  296. package/src/runtime/channels/channel-dispatchers.ts +93 -39
  297. package/src/runtime/channels/channel-envelope.ts +680 -144
  298. package/src/runtime/channels/channel-multipart.ts +17 -13
  299. package/src/runtime/channels/channel-outbound-operations.ts +204 -178
  300. package/src/runtime/channels/channel-receive-loops.ts +160 -107
  301. package/src/runtime/channels/channel-runtime-lifecycle.ts +64 -59
  302. package/src/runtime/channels/channel-runtime-manager.ts +74 -27
  303. package/src/runtime/channels/channel-socket-registry.ts +20 -5
  304. package/src/runtime/channels/channel-transports.ts +414 -287
  305. package/src/runtime/channels/dispatch-error-reporter.ts +4 -9
  306. package/src/runtime/channels/local-spot-route-transport.ts +27 -29
  307. package/src/runtime/channels/router-socket-spot-route-transport.ts +63 -32
  308. package/src/runtime/channels/source-spot-router.ts +75 -38
  309. package/src/runtime/channels/spot-node-route-transport.ts +67 -37
  310. package/src/runtime/channels/spot-route-bridge-transport.ts +62 -30
  311. package/src/runtime/channels/spot-route-dispatch-strategy.ts +105 -34
  312. package/src/runtime/diagnostics/dispatch-error-details.ts +10 -2
  313. package/src/runtime/diagnostics/message-flow-bootstrap.ts +6 -0
  314. package/src/runtime/diagnostics/message-flow-delivery.ts +171 -0
  315. package/src/runtime/diagnostics/message-flow-record.ts +295 -0
  316. package/src/runtime/diagnostics/message-flow-worker.ts +146 -0
  317. package/src/runtime/diagnostics/message-flow.ts +49 -362
  318. package/src/runtime/diagnostics/runtime-metrics.ts +10 -4
  319. package/src/runtime/execution/index.ts +6 -0
  320. package/src/runtime/execution/serial-execution-queue.ts +94 -96
  321. package/src/runtime/foundation/durable-service-request.ts +212 -89
  322. package/src/runtime/foundation/operation-registry.ts +287 -38
  323. package/src/runtime/foundation/raw-service-mesh-runtime.ts +617 -292
  324. package/src/runtime/foundation/request-runtime.ts +227 -0
  325. package/src/runtime/foundation/service-discovery-registry.ts +7 -0
  326. package/src/runtime/foundation/service-liveness-registry.ts +1 -1
  327. package/src/runtime/foundation/service-mailbox.ts +7 -2
  328. package/src/runtime/foundation/service-relocation-object-owner.ts +21 -6
  329. package/src/runtime/foundation/service-runtime-contracts.ts +12 -2
  330. package/src/runtime/foundation/service-stateful-registry.ts +52 -19
  331. package/src/runtime/foundation/service-stateful-runtime.ts +365 -198
  332. package/src/runtime/foundation/service-stateful-wire-codec.ts +18 -0
  333. package/src/runtime/foundation/service-topology-registry.ts +21 -3
  334. package/src/runtime/foundation/service-wire-constants.generated.ts +10 -0
  335. package/src/runtime/foundation/service-wire-m6a-codec.ts +69 -17
  336. package/src/runtime/host/actor-packet-relay.ts +160 -156
  337. package/src/runtime/host/actor-placement-coordinator.ts +1 -1
  338. package/src/runtime/host/actor-runtime-options-factory.ts +7 -2
  339. package/src/runtime/host/actor-transfer-runtime.ts +3 -3
  340. package/src/runtime/host/application-job-queue.ts +56 -27
  341. package/src/runtime/host/bound-session-relay.ts +0 -1
  342. package/src/runtime/host/channel-runtime-options-factory.ts +3 -0
  343. package/src/runtime/host/entry-actor-runtime.ts +14 -6
  344. package/src/runtime/host/index.ts +388 -113
  345. package/src/runtime/host/location-runtime-owner.ts +3 -3
  346. package/src/runtime/host/service-relocation-host-runtime.ts +380 -252
  347. package/src/runtime/host/spot-address-transport.ts +110 -95
  348. package/src/runtime/host/spot-runtime-options-factory.ts +3 -0
  349. package/src/runtime/host/user-spot-creation-coordinator.ts +69 -22
  350. package/src/runtime/internal-observation.ts +2 -0
  351. package/src/runtime/locations/actor-location-claims.ts +42 -16
  352. package/src/runtime/locations/auto-connect-loop.ts +24 -16
  353. package/src/runtime/locations/auto-connect-planner.ts +2 -5
  354. package/src/runtime/locations/auto-connect-reconciler.ts +37 -24
  355. package/src/runtime/locations/in-memory-authority-store.ts +27 -7
  356. package/src/runtime/locations/in-memory-location-store.ts +1 -74
  357. package/src/runtime/locations/lifecycle.ts +4 -2
  358. package/src/runtime/locations/location-store-repository.ts +228 -308
  359. package/src/runtime/locations/resolvers.ts +20 -8
  360. package/src/runtime/locations/runtime.ts +16 -28
  361. package/src/runtime/messaging/creation-payload-codec.ts +12 -10
  362. package/src/runtime/messaging/framework-json-v1.ts +10 -1
  363. package/src/runtime/messaging/payload-codec.ts +50 -75
  364. package/src/runtime/messaging/request-deadline.ts +47 -39
  365. package/src/runtime/messaging/request-result.ts +88 -17
  366. package/src/runtime/protocol/service_wire_codec.generated.ts +18 -8
  367. package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +1 -1
  368. package/src/runtime/spots/index.ts +57 -10
  369. package/src/runtime/spots/spot-activation-registry.ts +12 -8
  370. package/src/runtime/spots/spot-activation-state.ts +2 -0
  371. package/src/runtime/spots/spot-actor-admission-coordinator.ts +62 -37
  372. package/src/runtime/spots/spot-actor-ingress-admission.ts +157 -0
  373. package/src/runtime/spots/spot-actor-membership.ts +8 -5
  374. package/src/runtime/spots/spot-actor-packet-dispatch.ts +122 -206
  375. package/src/runtime/spots/spot-actor-packet-drain.ts +21 -6
  376. package/src/runtime/spots/spot-entry-activation.ts +25 -35
  377. package/src/runtime/spots/spot-handler-registry.ts +72 -15
  378. package/src/runtime/spots/spot-manager-public.ts +4 -2
  379. package/src/runtime/spots/spot-node-runtime-manager.ts +16 -7
  380. package/src/runtime/spots/spot-outbound.ts +26 -10
  381. package/src/runtime/spots/spot-route-packet-dispatch.ts +18 -8
  382. package/src/runtime/spots/spot-routed-spot-packet-dispatch.ts +14 -8
  383. package/src/runtime/spots/spot-runtime-ports.ts +5 -2
  384. package/src/runtime/spots/spot-serial-executor.ts +1 -1
  385. package/src/runtime/spots/spot-serial-turn-executor.ts +25 -40
  386. package/src/runtime/spots/spot-subscription-dispatch.ts +9 -2
  387. package/src/runtime/spots/spot-timer.ts +1 -1
  388. package/src/runtime/streams/actor-session-binding-registry.ts +46 -3
  389. package/src/runtime/streams/bound-actor-relay-sender.ts +16 -5
  390. package/src/runtime/streams/bound-session-service.ts +10 -7
  391. package/src/runtime/streams/index.ts +30 -4
  392. package/src/runtime/streams/managed-stream.ts +2 -1
  393. package/src/runtime/streams/session-calls.ts +9 -14
  394. package/src/runtime/streams/session-context.ts +6 -11
  395. package/src/runtime/streams/stream-session-runtime.ts +79 -40
  396. package/dist/runtime/spots/spot-lifecycle-metrics.d.ts +0 -8
  397. package/dist/runtime/spots/spot-lifecycle-metrics.js +0 -17
  398. package/src/runtime/spots/spot-lifecycle-metrics.ts +0 -16
@@ -1,16 +1,20 @@
1
1
  import type { Message } from '../../contracts/Common/Message';
2
- import { ZLinkBufferMessage } from '../backend/runtime-message';
3
2
  import type { ZLinkBackendMessageLike as MessageLike } from '../backend/runtime-values';
4
3
  import { randomBytes } from 'node:crypto';
5
4
  import { isUtf8 } from 'node:buffer';
6
5
  import {
6
+ type Type,
7
7
  ZLinkFrameworkErrorKind,
8
8
  ZLinkFrameworkException,
9
9
  type ZLinkMessageSerializer,
10
10
  type ZLinkFlowOrigin
11
11
  } from '../../contracts';
12
12
  import { borrowEncodedPayload } from '../../contracts/Common/encoded-payload-storage';
13
- import { isZLinkMessage, readZLinkMessageDeclaredType } from '../../contracts/Common/ZLinkMessage';
13
+ import {
14
+ isZLinkMessage,
15
+ materializeZLinkMessageValue,
16
+ readZLinkMessageDeclaredType
17
+ } from '../../contracts/Common/ZLinkMessage';
14
18
  import { ZLinkConfigurationException } from '../configuration';
15
19
  import {
16
20
  ZLinkFrameworkInternalErrorKind,
@@ -98,7 +102,7 @@ const CHANNEL_CORRELATION_TEXT = /^[0-9a-f]{32}$/;
98
102
  const CHANNEL_FLOW_FIELD = ',"flowId":';
99
103
  // A flow id is a lowercase UUIDv7 (spec 27 §3): fixed 36 JSON-safe ASCII bytes.
100
104
  const PREPARED_CHANNEL_FLOW = '00000000-0000-7000-8000-000000000000';
101
- const CHANNEL_FLOW_TEXT = /^[0-9a-f-]{36}$/;
105
+ const CHANNEL_FLOW_TEXT = /^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
102
106
 
103
107
  // A per-process random 64-bit prefix followed by a per-process counter, both
104
108
  // as lowercase hex: unique among the runtime's pending requests (spec 06-obs/04
@@ -109,9 +113,11 @@ let channelCorrelationCounter = 0;
109
113
 
110
114
  export function newChannelCorrelationId(): string {
111
115
  channelCorrelationCounter += 1;
116
+ const suffix = channelCorrelationCounter.toString(16);
112
117
  return (
113
118
  CHANNEL_CORRELATION_PREFIX +
114
- channelCorrelationCounter.toString(16).padStart(CHANNEL_CORRELATION_TEXT_LENGTH / 2, '0')
119
+ PREPARED_CHANNEL_CORRELATION.slice(suffix.length, CHANNEL_CORRELATION_TEXT_LENGTH / 2) +
120
+ suffix
115
121
  );
116
122
  }
117
123
 
@@ -166,33 +172,21 @@ export function encodeChannelEnvelopePartsAtDeadline(
166
172
  throw new RangeError('deadlineUnixMs must be a positive safe integer.');
167
173
  }
168
174
  const messageName = resolveFrameworkPacketName(payload, packetName, 'Channel');
169
- const encoded = encodePayload(
175
+ return encodePayload(
170
176
  payload,
171
177
  codecsForFrameworkPacket(messageName, codecs),
172
178
  messageName,
173
- 'payload'
179
+ 'payload',
180
+ kind,
181
+ channelName,
182
+ correlationId,
183
+ deadlineUnixMs,
184
+ topic,
185
+ createFlow,
186
+ metadata,
187
+ undefined,
188
+ codecs
174
189
  );
175
- const flow = createFlow ? currentOrCreateFlow('Application') : undefined;
176
- const envelopeCorrelationId = correlationIdForOutboundKind(kind, correlationId);
177
- return [
178
- encodeChannelHeader(
179
- kind,
180
- channelName,
181
- messageName,
182
- encoded.contentType,
183
- envelopeCorrelationId,
184
- deadlineUnixMs === undefined ? null : new Date(deadlineUnixMs).toISOString(),
185
- topic ?? null,
186
- null,
187
- null,
188
- undefined,
189
- applicationMetadataRecord(metadata),
190
- flow?.flowId,
191
- flow?.flowOrigin,
192
- codecs
193
- ),
194
- encoded.message
195
- ];
196
190
  }
197
191
 
198
192
  export function encodeChannelPublishEnvelopeParts(
@@ -205,31 +199,19 @@ export function encodeChannelPublishEnvelopeParts(
205
199
  metadata: ReadonlyMap<string, string> = EMPTY_OUTBOUND_METADATA
206
200
  ): readonly MessageLike[] {
207
201
  const messageName = resolveFrameworkPacketName(payload, packetName, 'Channel');
208
- const encoded = encodePayload(
202
+ return encodePayload(
209
203
  payload,
210
204
  codecsForFrameworkPacket(messageName, codecs),
211
205
  messageName,
212
- 'payload'
206
+ 'payload',
207
+ ZLinkChannelMessageKind.Publish,
208
+ channelName,
209
+ undefined,
210
+ undefined,
211
+ topic,
212
+ createFlow,
213
+ metadata
213
214
  );
214
- const flow = createFlow ? currentOrCreateFlow('Application') : undefined;
215
- return [
216
- encodeChannelHeader(
217
- ZLinkChannelMessageKind.Publish,
218
- channelName,
219
- messageName,
220
- encoded.contentType,
221
- null,
222
- null,
223
- topic,
224
- null,
225
- null,
226
- undefined,
227
- applicationMetadataRecord(metadata),
228
- flow?.flowId,
229
- flow?.flowOrigin
230
- ),
231
- encoded.message
232
- ];
233
215
  }
234
216
 
235
217
  export function encodeChannelReplyParts(
@@ -237,31 +219,21 @@ export function encodeChannelReplyParts(
237
219
  payload: unknown,
238
220
  codecs?: ZLinkChannelEnvelopeCodecRegistry
239
221
  ): readonly MessageLike[] {
240
- const encoded = encodePayload(
222
+ return encodePayload(
241
223
  payload ?? Buffer.alloc(0),
242
224
  codecsForFrameworkPacket(request.messageName, codecs),
243
225
  request.messageName,
244
- 'reply'
226
+ 'reply',
227
+ ZLinkChannelMessageKind.Response,
228
+ request.channelName,
229
+ request.correlationId ?? undefined,
230
+ undefined,
231
+ undefined,
232
+ false,
233
+ EMPTY_OUTBOUND_METADATA,
234
+ request,
235
+ codecs
245
236
  );
246
- return [
247
- encodeChannelHeader(
248
- ZLinkChannelMessageKind.Response,
249
- request.channelName,
250
- request.messageName,
251
- encoded.contentType,
252
- request.correlationId,
253
- null,
254
- null,
255
- undefined,
256
- undefined,
257
- undefined,
258
- EMPTY_APPLICATION_METADATA,
259
- request.flowId,
260
- request.flowOrigin,
261
- codecs
262
- ),
263
- encoded.message
264
- ];
265
237
  }
266
238
 
267
239
  /**
@@ -342,7 +314,7 @@ export function encodeChannelErrorReplyParts(
342
314
  request.flowId,
343
315
  request.flowOrigin
344
316
  ),
345
- encodeJsonBytes(null)
317
+ encodeJsonText(null)
346
318
  ];
347
319
  }
348
320
 
@@ -368,20 +340,18 @@ export function decodeChannelReply<TReply>(
368
340
  ) {
369
341
  throw unsupportedChannelContentType(header.contentType);
370
342
  }
371
- if (parts.length < 2 || parts[1].data().length === 0) {
343
+ const body = parts.length < 2 ? undefined : parts[1].data();
344
+ if (body === undefined || body.length === 0) {
372
345
  return undefined as TReply;
373
346
  }
374
347
  if (header.contentType === BINARY_CONTENT_TYPE) {
375
- return ZLinkBufferMessage.retainPayload(parts[1]) as TReply;
348
+ return body as TReply;
376
349
  }
377
350
  if (serializer !== undefined) {
378
- return serializer.deserialize<TReply>(
379
- encodedPayloadFromOwned(parts[1].data()),
380
- Object as never
381
- );
351
+ return serializer.deserialize<TReply>(encodedPayloadFromOwned(body), Object as never);
382
352
  }
383
353
  return parseWireJson(
384
- parts[1].data().toString(),
354
+ body.toString(),
385
355
  readZLinkPacketJsonContract(header.messageName)?.reply
386
356
  ) as TReply;
387
357
  }
@@ -442,7 +412,8 @@ export function decodeChannelEnvelope(
442
412
 
443
413
  export function decodeChannelPayload(
444
414
  envelope: ZLinkChannelEnvelope,
445
- codecs?: ZLinkChannelEnvelopeCodecRegistry
415
+ codecs?: ZLinkChannelEnvelopeCodecRegistry,
416
+ messageType?: Type
446
417
  ): unknown {
447
418
  try {
448
419
  if (!isCanonicalCodecContentType(envelope.header.contentType)) {
@@ -450,7 +421,10 @@ export function decodeChannelPayload(
450
421
  }
451
422
  const serializer = codecs?.serializers.get(envelope.header.contentType);
452
423
  if (serializer !== undefined) {
453
- return serializer.deserialize(encodedPayloadFromOwned(envelope.payload), Object as never);
424
+ return serializer.deserialize(
425
+ encodedPayloadFromOwned(envelope.payload),
426
+ (messageType ?? Object) as never
427
+ );
454
428
  }
455
429
  if (envelope.header.contentType === BINARY_CONTENT_TYPE) {
456
430
  // The receive loop owns the Message for the duration of dispatch, so
@@ -458,9 +432,12 @@ export function decodeChannelPayload(
458
432
  return envelope.payload;
459
433
  }
460
434
  if (envelope.header.contentType === JSON_CONTENT_TYPE) {
461
- return parseWireJson(
462
- envelope.payload.toString(),
463
- schemaForInboundChannelEnvelope(envelope.header)
435
+ return materializeZLinkMessageValue(
436
+ parseWireJson(
437
+ envelope.payload.toString(),
438
+ schemaForInboundChannelEnvelope(envelope.header)
439
+ ),
440
+ messageType
464
441
  );
465
442
  }
466
443
  throw unsupportedChannelContentType(envelope.header.contentType);
@@ -495,42 +472,71 @@ function encodePayload(
495
472
  value: unknown,
496
473
  codecs: ZLinkChannelEnvelopeCodecRegistry | undefined,
497
474
  packetName: string,
498
- contractPart: 'payload' | 'reply'
499
- ): {
500
- readonly contentType: string;
501
- readonly message: MessageLike;
502
- } {
475
+ contractPart: 'payload' | 'reply',
476
+ kind: ZLinkChannelMessageKind,
477
+ channelName: string,
478
+ correlationId: string | undefined,
479
+ deadlineUnixMs: number | undefined,
480
+ topic: string | undefined,
481
+ createFlow: boolean,
482
+ metadata: ReadonlyMap<string, string>,
483
+ request?: ZLinkChannelEnvelopeHeader,
484
+ headerCodecs?: ZLinkChannelEnvelopeCodecRegistry
485
+ ): readonly MessageLike[] {
486
+ let declaredType;
487
+ let contentType: string;
488
+ let message: MessageLike;
503
489
  if (isZLinkMessage(value) && value.isEncoded()) {
504
490
  const payload = value.toEncodedPayload();
505
- return {
506
- contentType: BINARY_CONTENT_TYPE,
507
- message: borrowEncodedPayload(payload) ?? payload.data()
508
- };
509
- }
510
- const declaredType = isZLinkMessage(value) ? readZLinkMessageDeclaredType(value) : undefined;
511
- if (isZLinkMessage(value)) value = value.decode();
512
- const selected = selectSerializerWithContentType(value, codecs, declaredType);
513
- if (
514
- selected !== undefined &&
515
- !(Buffer.isBuffer(value) || value instanceof Uint8Array || isMessage(value))
516
- ) {
517
- const payload = selected.serializer.serialize(value);
518
- return {
519
- contentType: selected.contentType,
520
- message: borrowEncodedPayload(payload) ?? payload.data()
521
- };
491
+ contentType = BINARY_CONTENT_TYPE;
492
+ message = borrowEncodedPayload(payload) ?? payload.data();
493
+ } else {
494
+ if (isZLinkMessage(value)) {
495
+ declaredType = readZLinkMessageDeclaredType(value);
496
+ value = value.decode();
497
+ }
498
+ const selected = selectSerializerWithContentType(value, codecs, declaredType);
499
+ if (
500
+ selected !== undefined &&
501
+ !(Buffer.isBuffer(value) || value instanceof Uint8Array || isMessage(value))
502
+ ) {
503
+ const payload = selected.serializer.serialize(value);
504
+ contentType = selected.contentType;
505
+ message = borrowEncodedPayload(payload) ?? payload.data();
506
+ } else {
507
+ contentType = contentTypeOf(value);
508
+ message = toMessageLike(value, readZLinkPacketJsonContract(packetName)?.[contractPart]);
509
+ }
522
510
  }
523
- return {
524
- contentType: contentTypeOf(value),
525
- message: toMessageLike(value, readZLinkPacketJsonContract(packetName)?.[contractPart])
526
- };
511
+ const flow = request ?? (createFlow ? currentOrCreateFlow('Application') : undefined);
512
+ return [
513
+ encodeChannelHeader(
514
+ kind,
515
+ channelName,
516
+ packetName,
517
+ contentType,
518
+ request === undefined
519
+ ? correlationIdForOutboundKind(kind, correlationId)
520
+ : request.correlationId,
521
+ deadlineUnixMs === undefined ? null : new Date(deadlineUnixMs).toISOString(),
522
+ topic ?? null,
523
+ contractPart === 'reply' ? undefined : null,
524
+ contractPart === 'reply' ? undefined : null,
525
+ undefined,
526
+ applicationMetadataRecord(metadata),
527
+ flow?.flowId,
528
+ flow?.flowOrigin,
529
+ headerCodecs
530
+ ),
531
+ message
532
+ ];
527
533
  }
528
534
 
529
535
  function toMessageLike(value: unknown, schema?: ZLinkJsonSchema): MessageLike {
530
536
  if (Buffer.isBuffer(value) || value instanceof Uint8Array || isMessage(value)) {
531
537
  return value;
532
538
  }
533
- return encodeJsonBytes(value, schema);
539
+ return encodeJsonText(value, schema);
534
540
  }
535
541
 
536
542
  function contentTypeOf(value: unknown): string {
@@ -547,8 +553,8 @@ function isMessage(value: unknown): value is Message {
547
553
  );
548
554
  }
549
555
 
550
- function encodeJsonBytes(value: unknown, schema?: ZLinkJsonSchema): Buffer {
551
- return Buffer.from(stringifyFrameworkJsonV1(value, schema));
556
+ function encodeJsonText(value: unknown, schema?: ZLinkJsonSchema): string {
557
+ return stringifyFrameworkJsonV1(value, schema);
552
558
  }
553
559
 
554
560
  function encodeChannelHeader(
@@ -887,44 +893,77 @@ export function decodeChannelHeader(
887
893
  if (parts.length === 0) {
888
894
  throw new ZLinkConfigurationException('Channel envelope header part is missing.');
889
895
  }
890
- return validateChannelHeader(parseChannelHeaderBytes(parts[0].data()), flowEnabled);
896
+ return validateChannelHeader(parseChannelHeaderBytes(parts[0].data(), flowEnabled), flowEnabled);
891
897
  }
892
898
 
899
+ const CHANNEL_JSON_PARSE_OPTIONS = Object.freeze({ rejectPropertyName: isPrototypeKey });
900
+
893
901
  function parseWireJson(payload: string, schema?: ZLinkJsonSchema): unknown {
894
- return parseFrameworkJsonV1(
895
- payload,
896
- {
897
- rejectPropertyName: isPrototypeKey
898
- },
899
- schema
900
- );
902
+ return parseFrameworkJsonV1(payload, CHANNEL_JSON_PARSE_OPTIONS, schema);
901
903
  }
902
904
 
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;
905
+ const CHANNEL_HEADER_FIELD_NAMES = [
906
+ '',
907
+ 'formatMarker',
908
+ 'kind',
909
+ 'channelName',
910
+ 'messageName',
911
+ 'contentType',
912
+ 'correlationId',
913
+ 'deadline',
914
+ 'topic',
915
+ 'errorCode',
916
+ 'errorMessage',
917
+ 'source',
918
+ 'flowId',
919
+ 'flowOrigin',
920
+ 'metadata'
921
+ ] as const;
922
+ const CHANNEL_HEADER_FIELD_COUNT = CHANNEL_HEADER_FIELD_NAMES.length - 1;
923
+ const CHANNEL_HEADER_INVALID_VALUE = Symbol('invalid channel header value');
924
+ const CANONICAL_CHANNEL_HEADER_PREFIX = '{"formatMarker":242,"kind":';
925
+
926
+ function parseChannelHeaderBytes(payload: Buffer, flowEnabled: boolean): unknown {
927
+ if (startsWithJson(payload, CANONICAL_CHANNEL_HEADER_PREFIX)) {
928
+ const reader = new CanonicalChannelHeaderReader(
929
+ payload,
930
+ CANONICAL_CHANNEL_HEADER_PREFIX.length
931
+ );
932
+ const canonical = tryParseCanonicalChannelHeader(reader, flowEnabled);
933
+ // Canonical ASCII headers need no UTF-8 pass; all other paths are checked
934
+ // before byte slices are decoded.
935
+ if (canonical !== undefined && !reader.sawNonAscii) return canonical;
936
+ if (canonical !== undefined) {
937
+ if (!isUtf8(payload)) {
938
+ throw new ZLinkFrameworkException(
939
+ ZLinkFrameworkErrorKind.ProtocolError,
940
+ 'Channel envelope header must contain valid UTF-8.'
941
+ );
942
+ }
943
+ return canonical;
944
+ }
945
+ }
909
946
  if (!isUtf8(payload)) {
910
947
  throw new ZLinkFrameworkException(
911
948
  ZLinkFrameworkErrorKind.ProtocolError,
912
949
  'Channel envelope header must contain valid UTF-8.'
913
950
  );
914
951
  }
915
- return canonical ?? parseFrameworkJsonV1(payload.toString());
952
+ return new ChannelHeaderJsonReader(payload, flowEnabled).parse();
953
+ }
954
+
955
+ function startsWithJson(bytes: Buffer, value: string): boolean {
956
+ if (bytes.length < value.length) return false;
957
+ for (let index = 0; index < value.length; index += 1) {
958
+ if (bytes[index] !== value.charCodeAt(index)) return false;
959
+ }
960
+ return true;
916
961
  }
917
962
 
918
- /**
919
- * Accept the byte layout emitted by writeChannelHeader without materializing
920
- * the enclosing JSON text. Any variation falls through to the established
921
- * framework-json-v1 parser, which remains the sole authority for JSON
922
- * failures and unknown properties. Header metadata accepts every valid string key.
923
- */
924
963
  function tryParseCanonicalChannelHeader(
925
- reader: CanonicalChannelHeaderReader
964
+ reader: CanonicalChannelHeaderReader,
965
+ flowEnabled: boolean
926
966
  ): Record<string, unknown> | undefined {
927
- if (!reader.consume('{"formatMarker":242,"kind":')) return undefined;
928
967
  const kind = reader.readSingleDigit();
929
968
  if (kind === undefined || !reader.consume(',"channelName":')) return undefined;
930
969
  const channelName = reader.readString();
@@ -948,16 +987,25 @@ function tryParseCanonicalChannelHeader(
948
987
  contentType,
949
988
  correlationId: correlationId === NULL_JSON_STRING ? null : correlationId,
950
989
  deadline: deadline === NULL_JSON_STRING ? null : deadline,
951
- topic: topic === NULL_JSON_STRING ? null : topic
990
+ topic: topic === NULL_JSON_STRING ? null : topic,
991
+ errorCode: null,
992
+ errorMessage: null,
993
+ source: undefined,
994
+ metadata: undefined,
995
+ flowId: undefined,
996
+ flowOrigin: undefined
952
997
  };
953
998
  if (!reader.readOptionalNullableString(CANONICAL_ERROR_CODE, 'errorCode', header))
954
999
  return undefined;
955
1000
  if (!reader.readOptionalNullableString(CANONICAL_ERROR_MESSAGE, 'errorMessage', header))
956
1001
  return undefined;
957
1002
  if (!reader.readOptionalNullableString(CANONICAL_SOURCE, 'source', header)) return undefined;
1003
+ const metadata = reader.readMetadata();
1004
+ if (metadata === undefined) return undefined;
958
1005
  // Empty metadata validates to the shared empty record.
959
- if (!reader.consume(',"metadata":{}')) return undefined;
960
- if (!reader.readOptionalString(CANONICAL_FLOW_ID, 'flowId', header)) return undefined;
1006
+ if (metadata !== NULL_JSON_STRING) header.metadata = metadata;
1007
+ if (!reader.readOptionalString(CANONICAL_FLOW_ID, 'flowId', header, flowEnabled))
1008
+ return undefined;
961
1009
  if (!reader.readOptionalSingleDigit(CANONICAL_FLOW_ORIGIN, 'flowOrigin', header))
962
1010
  return undefined;
963
1011
  return reader.consume('}') && reader.atEnd() ? header : undefined;
@@ -976,7 +1024,12 @@ class CanonicalChannelHeaderReader {
976
1024
  /** A string held a byte outside ASCII, so the caller must still check UTF-8. */
977
1025
  sawNonAscii = false;
978
1026
 
979
- constructor(private readonly bytes: Buffer) {}
1027
+ constructor(
1028
+ private readonly bytes: Buffer,
1029
+ initialIndex = 0
1030
+ ) {
1031
+ this.index = initialIndex;
1032
+ }
980
1033
 
981
1034
  atEnd(): boolean {
982
1035
  return this.index === this.bytes.length;
@@ -1045,6 +1098,37 @@ class CanonicalChannelHeaderReader {
1045
1098
  return this.readString();
1046
1099
  }
1047
1100
 
1101
+ readMetadata(): Record<string, unknown> | symbol | undefined {
1102
+ if (!this.consume(',"metadata":{')) return undefined;
1103
+ if (this.consume('}')) return NULL_JSON_STRING;
1104
+ const metadata: Record<string, unknown> = {};
1105
+ for (;;) {
1106
+ const key = this.readString();
1107
+ if (key === undefined) return undefined;
1108
+ if (Object.prototype.hasOwnProperty.call(metadata, key)) {
1109
+ throw new ZLinkFrameworkException(
1110
+ ZLinkFrameworkErrorKind.ProtocolError,
1111
+ 'duplicate envelope metadata key'
1112
+ );
1113
+ }
1114
+ if (!this.consume(':')) return undefined;
1115
+ const value = this.readString();
1116
+ if (value === undefined) return undefined;
1117
+ if (key === '__proto__') {
1118
+ Object.defineProperty(metadata, key, {
1119
+ configurable: true,
1120
+ enumerable: true,
1121
+ value,
1122
+ writable: true
1123
+ });
1124
+ } else {
1125
+ metadata[key] = value;
1126
+ }
1127
+ if (this.consume('}')) return metadata;
1128
+ if (!this.consume(',')) return undefined;
1129
+ }
1130
+ }
1131
+
1048
1132
  readOptionalNullableString(
1049
1133
  token: string,
1050
1134
  name: string,
@@ -1057,14 +1141,53 @@ class CanonicalChannelHeaderReader {
1057
1141
  return true;
1058
1142
  }
1059
1143
 
1060
- readOptionalString(token: string, name: string, target: Record<string, unknown>): boolean {
1144
+ readOptionalString(
1145
+ token: string,
1146
+ name: string,
1147
+ target: Record<string, unknown>,
1148
+ decode = true
1149
+ ): boolean {
1061
1150
  if (!this.consume(token)) return true;
1151
+ if (!decode) return this.skipString();
1062
1152
  const value = this.readString();
1063
1153
  if (value === undefined) return false;
1064
1154
  target[name] = value;
1065
1155
  return true;
1066
1156
  }
1067
1157
 
1158
+ private skipString(): boolean {
1159
+ if (this.bytes[this.index] !== 0x22) return false;
1160
+ this.index += 1;
1161
+ while (this.index < this.bytes.length) {
1162
+ const value = this.bytes[this.index++]!;
1163
+ if (value === 0x22) return true;
1164
+ if (value < 0x20) return false;
1165
+ if (value >= 0x80) this.sawNonAscii = true;
1166
+ if (value !== 0x5c) continue;
1167
+ if (this.index === this.bytes.length) return false;
1168
+ const escaped = this.bytes[this.index++]!;
1169
+ if (escaped === 0x75) {
1170
+ for (let count = 0; count < 4; count += 1) {
1171
+ if (this.index === this.bytes.length || !isHexDigit(this.bytes[this.index]!))
1172
+ return false;
1173
+ this.index += 1;
1174
+ }
1175
+ } else if (
1176
+ escaped !== 0x22 &&
1177
+ escaped !== 0x5c &&
1178
+ escaped !== 0x2f &&
1179
+ escaped !== 0x62 &&
1180
+ escaped !== 0x66 &&
1181
+ escaped !== 0x6e &&
1182
+ escaped !== 0x72 &&
1183
+ escaped !== 0x74
1184
+ ) {
1185
+ return false;
1186
+ }
1187
+ }
1188
+ return false;
1189
+ }
1190
+
1068
1191
  readOptionalSingleDigit(token: string, name: string, target: Record<string, unknown>): boolean {
1069
1192
  if (!this.consume(token)) return true;
1070
1193
  const value = this.readSingleDigit();
@@ -1082,6 +1205,418 @@ function isHexDigit(value: number): boolean {
1082
1205
  );
1083
1206
  }
1084
1207
 
1208
+ /** Reads a noncanonical channel header directly from its UTF-8 bytes. */
1209
+ class ChannelHeaderJsonReader {
1210
+ private index = 0;
1211
+ private propertyName = '';
1212
+ private stringStart = 0;
1213
+ private stringEnd = 0;
1214
+ private stringHasEscapes = false;
1215
+
1216
+ constructor(
1217
+ private readonly bytes: Buffer,
1218
+ private readonly flowEnabled: boolean
1219
+ ) {}
1220
+
1221
+ parse(): unknown {
1222
+ if (
1223
+ this.bytes.length >= 3 &&
1224
+ this.bytes[0] === 0xef &&
1225
+ this.bytes[1] === 0xbb &&
1226
+ this.bytes[2] === 0xbf
1227
+ ) {
1228
+ throw new SyntaxError('framework-json-v1 does not allow a UTF-8 BOM.');
1229
+ }
1230
+ this.skipWhitespace();
1231
+ if (this.bytes[this.index] !== 0x7b) {
1232
+ this.skipValue();
1233
+ this.skipWhitespace();
1234
+ if (this.index !== this.bytes.length) this.fail('trailing data');
1235
+ return CHANNEL_HEADER_INVALID_VALUE;
1236
+ }
1237
+
1238
+ const header: Record<string, unknown> = {};
1239
+ let seenFields = 0;
1240
+ this.index += 1;
1241
+ this.skipWhitespace();
1242
+ if (this.consumeByte(0x7d)) return this.finish(header);
1243
+
1244
+ for (;;) {
1245
+ const field = this.readPropertyName(true);
1246
+ const propertyName = this.propertyName;
1247
+ this.skipWhitespace();
1248
+ this.expectByte(0x3a, "':' after object property");
1249
+ this.skipWhitespace();
1250
+
1251
+ if (field !== 0) {
1252
+ const bit = 1 << field;
1253
+ if ((seenFields & bit) !== 0) {
1254
+ throw new ZLinkFrameworkException(
1255
+ ZLinkFrameworkErrorKind.ProtocolError,
1256
+ 'duplicate envelope header field'
1257
+ );
1258
+ }
1259
+ seenFields |= bit;
1260
+ const name = CHANNEL_HEADER_FIELD_NAMES[field]!;
1261
+ if (!this.flowEnabled && (field === 12 || field === 13)) {
1262
+ this.skipValue();
1263
+ header[name] = undefined;
1264
+ } else if (field === 14) {
1265
+ header[name] = this.readMetadata();
1266
+ } else {
1267
+ header[name] = this.readValue(field === 1 || field === 2 || field === 13);
1268
+ }
1269
+ } else {
1270
+ const value = this.readValue();
1271
+ if (propertyName === '__proto__') {
1272
+ Object.defineProperty(header, propertyName, {
1273
+ configurable: true,
1274
+ enumerable: true,
1275
+ value,
1276
+ writable: true
1277
+ });
1278
+ } else {
1279
+ header[propertyName] = value;
1280
+ }
1281
+ }
1282
+
1283
+ this.skipWhitespace();
1284
+ if (this.consumeByte(0x7d)) break;
1285
+ this.expectByte(0x2c, "',' or '}' after object property");
1286
+ this.skipWhitespace();
1287
+ }
1288
+ return this.finish(header);
1289
+ }
1290
+
1291
+ private finish(header: Record<string, unknown>): Record<string, unknown> {
1292
+ this.skipWhitespace();
1293
+ if (this.index !== this.bytes.length) this.fail('trailing data');
1294
+ return header;
1295
+ }
1296
+
1297
+ private readMetadata(): unknown {
1298
+ if (this.bytes[this.index] !== 0x7b) return this.readValue();
1299
+ this.index += 1;
1300
+ this.skipWhitespace();
1301
+ if (this.consumeByte(0x7d)) return undefined;
1302
+ const metadata: Record<string, unknown> = {};
1303
+
1304
+ for (;;) {
1305
+ const key = this.readString();
1306
+ if (Object.prototype.hasOwnProperty.call(metadata, key)) {
1307
+ throw new ZLinkFrameworkException(
1308
+ ZLinkFrameworkErrorKind.ProtocolError,
1309
+ 'duplicate envelope metadata key'
1310
+ );
1311
+ }
1312
+ this.skipWhitespace();
1313
+ this.expectByte(0x3a, "':' after object property");
1314
+ this.skipWhitespace();
1315
+ const value = this.readValue();
1316
+ if (key === '__proto__') {
1317
+ Object.defineProperty(metadata, key, {
1318
+ configurable: true,
1319
+ enumerable: true,
1320
+ value,
1321
+ writable: true
1322
+ });
1323
+ } else {
1324
+ metadata[key] = value;
1325
+ }
1326
+ this.skipWhitespace();
1327
+ if (this.consumeByte(0x7d)) return metadata;
1328
+ this.expectByte(0x2c, "',' or '}' after object property");
1329
+ this.skipWhitespace();
1330
+ }
1331
+ }
1332
+
1333
+ private readPropertyName(materializeUnknown = false): number {
1334
+ this.scanString();
1335
+ let field = 0;
1336
+ let decoded: string | undefined;
1337
+ if (this.stringHasEscapes) {
1338
+ decoded = this.decodeString();
1339
+ for (let candidate = 1; candidate <= CHANNEL_HEADER_FIELD_COUNT; candidate += 1) {
1340
+ if (CHANNEL_HEADER_FIELD_NAMES[candidate] === decoded) {
1341
+ field = candidate;
1342
+ break;
1343
+ }
1344
+ }
1345
+ } else {
1346
+ for (let candidate = 1; candidate <= CHANNEL_HEADER_FIELD_COUNT; candidate += 1) {
1347
+ if (
1348
+ this.matchesAscii(
1349
+ this.stringStart + 1,
1350
+ this.stringEnd - 1,
1351
+ CHANNEL_HEADER_FIELD_NAMES[candidate]!
1352
+ )
1353
+ ) {
1354
+ field = candidate;
1355
+ break;
1356
+ }
1357
+ }
1358
+ }
1359
+ this.propertyName =
1360
+ field !== 0
1361
+ ? CHANNEL_HEADER_FIELD_NAMES[field]!
1362
+ : (decoded ??
1363
+ (materializeUnknown
1364
+ ? this.bytes.toString('utf8', this.stringStart + 1, this.stringEnd - 1)
1365
+ : ''));
1366
+ return field;
1367
+ }
1368
+
1369
+ private readValue(integerOnly = false): unknown {
1370
+ const value = this.bytes[this.index];
1371
+ if (value === 0x22) return this.readString();
1372
+ if (value === 0x7b) return this.readObject();
1373
+ if (value === 0x5b) return this.readArray();
1374
+ if (value === 0x74) {
1375
+ this.readLiteral('true');
1376
+ return true;
1377
+ }
1378
+ if (value === 0x66) {
1379
+ this.readLiteral('false');
1380
+ return false;
1381
+ }
1382
+ if (value === 0x6e) {
1383
+ this.readLiteral('null');
1384
+ return null;
1385
+ }
1386
+ return this.readNumber(integerOnly);
1387
+ }
1388
+
1389
+ private readObject(): Record<string, unknown> {
1390
+ this.index += 1;
1391
+ this.skipWhitespace();
1392
+ const object: Record<string, unknown> = {};
1393
+ if (this.consumeByte(0x7d)) return object;
1394
+ for (;;) {
1395
+ const key = this.readString();
1396
+ this.skipWhitespace();
1397
+ this.expectByte(0x3a, "':' after object property");
1398
+ this.skipWhitespace();
1399
+ const value = this.readValue();
1400
+ if (key === '__proto__') {
1401
+ Object.defineProperty(object, key, {
1402
+ configurable: true,
1403
+ enumerable: true,
1404
+ value,
1405
+ writable: true
1406
+ });
1407
+ } else {
1408
+ object[key] = value;
1409
+ }
1410
+ this.skipWhitespace();
1411
+ if (this.consumeByte(0x7d)) return object;
1412
+ this.expectByte(0x2c, "',' or '}' after object property");
1413
+ this.skipWhitespace();
1414
+ }
1415
+ }
1416
+
1417
+ private readArray(): unknown[] {
1418
+ this.index += 1;
1419
+ this.skipWhitespace();
1420
+ const array: unknown[] = [];
1421
+ if (this.consumeByte(0x5d)) return array;
1422
+ for (;;) {
1423
+ array.push(this.readValue());
1424
+ this.skipWhitespace();
1425
+ if (this.consumeByte(0x5d)) return array;
1426
+ this.expectByte(0x2c, "',' or ']' after array item");
1427
+ this.skipWhitespace();
1428
+ }
1429
+ }
1430
+
1431
+ private skipValue(): void {
1432
+ const value = this.bytes[this.index];
1433
+ if (value === 0x22) {
1434
+ this.scanString();
1435
+ return;
1436
+ }
1437
+ if (value === 0x7b) return this.skipObject();
1438
+ if (value === 0x5b) return this.skipArray();
1439
+ if (value === 0x74) return this.readLiteral('true');
1440
+ if (value === 0x66) return this.readLiteral('false');
1441
+ if (value === 0x6e) return this.readLiteral('null');
1442
+ this.readNumber();
1443
+ }
1444
+
1445
+ private skipObject(): void {
1446
+ this.index += 1;
1447
+ this.skipWhitespace();
1448
+ if (this.consumeByte(0x7d)) return;
1449
+ for (;;) {
1450
+ this.readPropertyName();
1451
+ this.skipWhitespace();
1452
+ this.expectByte(0x3a, "':' after object property");
1453
+ this.skipWhitespace();
1454
+ this.skipValue();
1455
+ this.skipWhitespace();
1456
+ if (this.consumeByte(0x7d)) return;
1457
+ this.expectByte(0x2c, "',' or '}' after object property");
1458
+ this.skipWhitespace();
1459
+ }
1460
+ }
1461
+
1462
+ private skipArray(): void {
1463
+ this.index += 1;
1464
+ this.skipWhitespace();
1465
+ if (this.consumeByte(0x5d)) return;
1466
+ for (;;) {
1467
+ this.skipValue();
1468
+ this.skipWhitespace();
1469
+ if (this.consumeByte(0x5d)) return;
1470
+ this.expectByte(0x2c, "',' or ']' after array item");
1471
+ this.skipWhitespace();
1472
+ }
1473
+ }
1474
+
1475
+ private readString(): string {
1476
+ this.scanString();
1477
+ return this.decodeString();
1478
+ }
1479
+
1480
+ private scanString(): void {
1481
+ if (this.bytes[this.index] !== 0x22) this.fail('string');
1482
+ this.stringStart = this.index++;
1483
+ this.stringHasEscapes = false;
1484
+ while (this.index < this.bytes.length) {
1485
+ const value = this.bytes[this.index++]!;
1486
+ if (value === 0x22) {
1487
+ this.stringEnd = this.index;
1488
+ return;
1489
+ }
1490
+ if (value < 0x20) this.fail('valid string character');
1491
+ if (value !== 0x5c) continue;
1492
+ this.stringHasEscapes = true;
1493
+ if (this.index === this.bytes.length) this.fail('valid string escape');
1494
+ const escaped = this.bytes[this.index++]!;
1495
+ if (escaped === 0x75) {
1496
+ for (let count = 0; count < 4; count += 1) {
1497
+ if (this.index === this.bytes.length || !isHexDigit(this.bytes[this.index]!))
1498
+ this.fail('four hexadecimal digits after \\u');
1499
+ this.index += 1;
1500
+ }
1501
+ } else if (
1502
+ escaped !== 0x22 &&
1503
+ escaped !== 0x5c &&
1504
+ escaped !== 0x2f &&
1505
+ escaped !== 0x62 &&
1506
+ escaped !== 0x66 &&
1507
+ escaped !== 0x6e &&
1508
+ escaped !== 0x72 &&
1509
+ escaped !== 0x74
1510
+ ) {
1511
+ this.fail('valid string escape');
1512
+ }
1513
+ }
1514
+ this.fail('terminated string');
1515
+ }
1516
+
1517
+ private decodeString(): string {
1518
+ return this.stringHasEscapes
1519
+ ? (JSON.parse(this.bytes.toString('utf8', this.stringStart, this.stringEnd)) as string)
1520
+ : this.bytes.toString('utf8', this.stringStart + 1, this.stringEnd - 1);
1521
+ }
1522
+
1523
+ private readNumber(integerOnly = false): number {
1524
+ const start = this.index;
1525
+ let hasFractionOrExponent = false;
1526
+ if (this.bytes[this.index] === 0x2d) this.index += 1;
1527
+ if (this.bytes[this.index] === 0x30) {
1528
+ this.index += 1;
1529
+ } else if (this.isDigitOneToNine(this.bytes[this.index])) {
1530
+ while (this.isDigit(this.bytes[this.index])) this.index += 1;
1531
+ } else {
1532
+ this.fail('JSON value');
1533
+ }
1534
+ if (this.bytes[this.index] === 0x2e) {
1535
+ hasFractionOrExponent = true;
1536
+ this.index += 1;
1537
+ if (!this.isDigit(this.bytes[this.index])) this.fail('digit after decimal point');
1538
+ while (this.isDigit(this.bytes[this.index])) this.index += 1;
1539
+ }
1540
+ if (this.bytes[this.index] === 0x65 || this.bytes[this.index] === 0x45) {
1541
+ hasFractionOrExponent = true;
1542
+ this.index += 1;
1543
+ if (this.bytes[this.index] === 0x2b || this.bytes[this.index] === 0x2d) this.index += 1;
1544
+ if (!this.isDigit(this.bytes[this.index])) this.fail('digit in exponent');
1545
+ while (this.isDigit(this.bytes[this.index])) this.index += 1;
1546
+ }
1547
+ if (integerOnly && hasFractionOrExponent) {
1548
+ throw new ZLinkFrameworkException(
1549
+ ZLinkFrameworkErrorKind.ProtocolError,
1550
+ 'Channel envelope integer fields must use an integer literal.'
1551
+ );
1552
+ }
1553
+ if (integerOnly) {
1554
+ const negative = this.bytes[start] === 0x2d;
1555
+ const digitsStart = start + (negative ? 1 : 0);
1556
+ if (this.index - digitsStart <= 3) {
1557
+ let integer = 0;
1558
+ for (let offset = digitsStart; offset < this.index; offset += 1) {
1559
+ integer = integer * 10 + this.bytes[offset]! - 0x30;
1560
+ }
1561
+ return negative ? -integer : integer;
1562
+ }
1563
+ }
1564
+ const number = Number(this.bytes.toString('ascii', start, this.index));
1565
+ if (!Number.isFinite(number)) {
1566
+ throw new TypeError('framework-json-v1 only accepts finite JSON numbers.');
1567
+ }
1568
+ return number;
1569
+ }
1570
+
1571
+ private readLiteral(value: 'true' | 'false' | 'null'): void {
1572
+ for (let offset = 0; offset < value.length; offset += 1) {
1573
+ if (this.bytes[this.index + offset] !== value.charCodeAt(offset)) this.fail(value);
1574
+ }
1575
+ this.index += value.length;
1576
+ }
1577
+
1578
+ private matchesAscii(start: number, end: number, value: string): boolean {
1579
+ if (end - start !== value.length) return false;
1580
+ for (let offset = 0; offset < value.length; offset += 1) {
1581
+ if (this.bytes[start + offset] !== value.charCodeAt(offset)) return false;
1582
+ }
1583
+ return true;
1584
+ }
1585
+
1586
+ private isDigit(value: number | undefined): boolean {
1587
+ return value !== undefined && value >= 0x30 && value <= 0x39;
1588
+ }
1589
+
1590
+ private isDigitOneToNine(value: number | undefined): boolean {
1591
+ return value !== undefined && value >= 0x31 && value <= 0x39;
1592
+ }
1593
+
1594
+ private skipWhitespace(): void {
1595
+ while (
1596
+ this.bytes[this.index] === 0x20 ||
1597
+ this.bytes[this.index] === 0x09 ||
1598
+ this.bytes[this.index] === 0x0a ||
1599
+ this.bytes[this.index] === 0x0d
1600
+ ) {
1601
+ this.index += 1;
1602
+ }
1603
+ }
1604
+
1605
+ private consumeByte(value: number): boolean {
1606
+ if (this.bytes[this.index] !== value) return false;
1607
+ this.index += 1;
1608
+ return true;
1609
+ }
1610
+
1611
+ private expectByte(value: number, expected: string): void {
1612
+ if (!this.consumeByte(value)) this.fail(expected);
1613
+ }
1614
+
1615
+ private fail(expected: string): never {
1616
+ throw new SyntaxError(`framework-json-v1 expected ${expected} at offset ${this.index}.`);
1617
+ }
1618
+ }
1619
+
1085
1620
  function schemaForInboundChannelEnvelope(
1086
1621
  header: ZLinkChannelEnvelopeHeader
1087
1622
  ): ZLinkJsonSchema | undefined {
@@ -1183,10 +1718,11 @@ function validateCorrelationForKind(
1183
1718
  const MAXIMUM_CORRELATION_ID_BYTES = 64;
1184
1719
 
1185
1720
  export function isValidChannelCorrelationId(value: string): boolean {
1186
- const byteLength = Buffer.byteLength(value, 'utf8');
1187
- return (
1188
- byteLength >= 1 && byteLength <= MAXIMUM_CORRELATION_ID_BYTES && /^[\x00-\x7f]*$/.test(value)
1189
- );
1721
+ if (value.length < 1 || value.length > MAXIMUM_CORRELATION_ID_BYTES) return false;
1722
+ for (let index = 0; index < value.length; index++) {
1723
+ if (value.charCodeAt(index) > 0x7f) return false;
1724
+ }
1725
+ return true;
1190
1726
  }
1191
1727
 
1192
1728
  function validateCorrelationValue(correlationId: string): void {
@@ -1274,7 +1810,7 @@ function optionalFlowOrigin(value: unknown): ZLinkFlowOrigin | undefined {
1274
1810
 
1275
1811
  function requireFlowId(value: unknown): string {
1276
1812
  const flowId = requireString(value, 'flowId');
1277
- if (!/^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(flowId)) {
1813
+ if (!CHANNEL_FLOW_TEXT.test(flowId)) {
1278
1814
  throw new ZLinkConfigurationException('Channel envelope flowId must be a lowercase UUIDv7.');
1279
1815
  }
1280
1816
  return flowId;