@zlink-systems/framework 0.29.1 → 0.30.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (322) hide show
  1. package/LICENSE +150 -68
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/contracts/Actors/ZLinkActorClient.d.ts +2 -1
  4. package/dist/contracts/Channels/Calls.d.ts +2 -1
  5. package/dist/contracts/Common/ZLinkMessageMetadata.js +11 -5
  6. package/dist/contracts/Configuration/Builders.d.ts +1 -2
  7. package/dist/contracts/Configuration/Configs.d.ts +0 -5
  8. package/dist/contracts/Configuration/RegistrationBuilders.js +6 -4
  9. package/dist/contracts/Configuration/RegistrationTypes.d.ts +1 -6
  10. package/dist/contracts/Configuration/RegistrationValidators.js +4 -4
  11. package/dist/contracts/Configuration/index.d.ts +1 -1
  12. package/dist/contracts/Handlers/Attributes.d.ts +5 -13
  13. package/dist/contracts/Handlers/Attributes.js +7 -11
  14. package/dist/contracts/Handlers/JsonContract.d.ts +2 -46
  15. package/dist/contracts/Handlers/JsonContract.js +4 -153
  16. package/dist/contracts/Spots/Contracts.d.ts +2 -1
  17. package/dist/internal.d.ts +1 -0
  18. package/dist/internal.js +3 -1
  19. package/dist/nest-integration.d.ts +1 -1
  20. package/dist/nest-integration.js +2 -1
  21. package/dist/runtime/actors/actor-client.d.ts +1 -1
  22. package/dist/runtime/actors/actor-client.js +14 -12
  23. package/dist/runtime/actors/actor-handoff.d.ts +3 -2
  24. package/dist/runtime/actors/actor-handoff.js +15 -7
  25. package/dist/runtime/actors/actor-join-relocation.d.ts +1 -0
  26. package/dist/runtime/actors/actor-local-native-join.js +9 -12
  27. package/dist/runtime/actors/actor-remote-wire.js +15 -0
  28. package/dist/runtime/actors/actor-routed-join-transport.d.ts +6 -2
  29. package/dist/runtime/actors/actor-routed-json-request.d.ts +2 -0
  30. package/dist/runtime/actors/index.d.ts +2 -1
  31. package/dist/runtime/actors/index.js +18 -6
  32. package/dist/runtime/actors/spot-actor-dispatch.js +2 -2
  33. package/dist/runtime/admission.d.ts +1 -1
  34. package/dist/runtime/admission.js +15 -5
  35. package/dist/runtime/application-jobs/application-ingress-record-owner.d.ts +9 -9
  36. package/dist/runtime/application-jobs/application-ingress-record-owner.js +45 -23
  37. package/dist/runtime/application-jobs/application-job-queue-scope.d.ts +5 -2
  38. package/dist/runtime/application-jobs/application-job-queue-scope.js +41 -21
  39. package/dist/runtime/application-jobs/contracts.d.ts +15 -2
  40. package/dist/runtime/backend/contracts/index.d.ts +27 -27
  41. package/dist/runtime/backend/mesh-completion-table.d.ts +15 -5
  42. package/dist/runtime/backend/mesh-completion-table.js +160 -50
  43. package/dist/runtime/backend/mesh-dispatch-pump.d.ts +3 -0
  44. package/dist/runtime/backend/mesh-dispatch-pump.js +53 -36
  45. package/dist/runtime/backend/node/node-backend-adapter-factory.js +6 -1
  46. package/dist/runtime/backend/node/node-backend-adapter-support.d.ts +3 -3
  47. package/dist/runtime/backend/node/node-backend-adapter-support.js +33 -31
  48. package/dist/runtime/backend/node/node-dealer-channel-client-transport.d.ts +1 -1
  49. package/dist/runtime/backend/node/node-dealer-channel-client-transport.js +5 -2
  50. package/dist/runtime/backend/node/node-mesh-backend-adapter.d.ts +1 -9
  51. package/dist/runtime/backend/node/node-mesh-backend-adapter.js +1 -1
  52. package/dist/runtime/backend/node/node-raw-binding-port.js +50 -25
  53. package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +22 -16
  54. package/dist/runtime/backend/node/node-raw-mesh-backend.js +133 -149
  55. package/dist/runtime/backend/node/node-socket-backend-adapter.js +15 -10
  56. package/dist/runtime/backend/raw-binding-port.d.ts +10 -3
  57. package/dist/runtime/backend/runtime-message.d.ts +1 -0
  58. package/dist/runtime/backend/runtime-message.js +5 -0
  59. package/dist/runtime/backend/runtime-values.d.ts +1 -0
  60. package/dist/runtime/backend/runtime-values.js +2 -1
  61. package/dist/runtime/channels/channel-clients.d.ts +1 -0
  62. package/dist/runtime/channels/channel-clients.js +58 -21
  63. package/dist/runtime/channels/channel-dispatch-pipeline.d.ts +3 -2
  64. package/dist/runtime/channels/channel-dispatch-pipeline.js +20 -11
  65. package/dist/runtime/channels/channel-dispatch-services.d.ts +1 -0
  66. package/dist/runtime/channels/channel-dispatch-services.js +45 -0
  67. package/dist/runtime/channels/channel-dispatchers.d.ts +1 -1
  68. package/dist/runtime/channels/channel-dispatchers.js +27 -26
  69. package/dist/runtime/channels/channel-envelope-inspection.d.ts +1 -2
  70. package/dist/runtime/channels/channel-envelope-inspection.js +1 -16
  71. package/dist/runtime/channels/channel-envelope.d.ts +1 -0
  72. package/dist/runtime/channels/channel-envelope.js +83 -8
  73. package/dist/runtime/channels/channel-outbound-operations.d.ts +2 -2
  74. package/dist/runtime/channels/channel-outbound-operations.js +8 -8
  75. package/dist/runtime/channels/channel-receive-loops.js +3 -3
  76. package/dist/runtime/channels/channel-runtime-lifecycle.js +2 -1
  77. package/dist/runtime/channels/channel-runtime-manager.d.ts +6 -6
  78. package/dist/runtime/channels/channel-runtime-manager.js +12 -12
  79. package/dist/runtime/channels/channel-socket-registry.d.ts +10 -3
  80. package/dist/runtime/channels/channel-socket-registry.js +59 -82
  81. package/dist/runtime/channels/channel-transports.d.ts +18 -15
  82. package/dist/runtime/channels/channel-transports.js +48 -31
  83. package/dist/runtime/channels/local-spot-route-transport.d.ts +1 -1
  84. package/dist/runtime/channels/local-spot-route-transport.js +2 -1
  85. package/dist/runtime/channels/router-socket-spot-route-transport.d.ts +2 -2
  86. package/dist/runtime/channels/router-socket-spot-route-transport.js +4 -4
  87. package/dist/runtime/channels/source-spot-router.d.ts +2 -2
  88. package/dist/runtime/channels/source-spot-router.js +4 -4
  89. package/dist/runtime/channels/spot-node-route-transport.d.ts +2 -2
  90. package/dist/runtime/channels/spot-node-route-transport.js +4 -4
  91. package/dist/runtime/channels/spot-route-bridge-transport.d.ts +2 -2
  92. package/dist/runtime/channels/spot-route-bridge-transport.js +4 -4
  93. package/dist/runtime/channels/spot-route-dispatch-strategy.d.ts +5 -4
  94. package/dist/runtime/channels/spot-route-dispatch-strategy.js +18 -18
  95. package/dist/runtime/diagnostics/message-flow.d.ts +1 -0
  96. package/dist/runtime/diagnostics/message-flow.js +3 -3
  97. package/dist/runtime/execution/serial-execution-queue.d.ts +1 -0
  98. package/dist/runtime/execution/serial-execution-queue.js +1 -0
  99. package/dist/runtime/foundation/actor-join-recovery-codec.js +2 -2
  100. package/dist/runtime/foundation/durable-service-request.d.ts +14 -0
  101. package/dist/runtime/foundation/durable-service-request.js +98 -0
  102. package/dist/runtime/foundation/operation-identity.d.ts +1 -0
  103. package/dist/runtime/foundation/operation-identity.js +5 -1
  104. package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +37 -6
  105. package/dist/runtime/foundation/raw-service-mesh-runtime.js +473 -220
  106. package/dist/runtime/foundation/service-liveness-registry.d.ts +20 -8
  107. package/dist/runtime/foundation/service-liveness-registry.js +57 -44
  108. package/dist/runtime/foundation/service-mailbox.d.ts +3 -0
  109. package/dist/runtime/foundation/service-mailbox.js +2 -1
  110. package/dist/runtime/foundation/service-relocation-object-owner.d.ts +1 -0
  111. package/dist/runtime/foundation/service-relocation-object-owner.js +1 -0
  112. package/dist/runtime/foundation/service-relocation-runtime.d.ts +2 -0
  113. package/dist/runtime/foundation/service-relocation-runtime.js +13 -1
  114. package/dist/runtime/foundation/service-runtime-contracts.d.ts +2 -0
  115. package/dist/runtime/foundation/service-stateful-runtime.d.ts +10 -9
  116. package/dist/runtime/foundation/service-stateful-runtime.js +78 -126
  117. package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +5 -7
  118. package/dist/runtime/foundation/service-stateful-wire-codec.js +43 -61
  119. package/dist/runtime/foundation/service-topology-registry.d.ts +16 -4
  120. package/dist/runtime/foundation/service-topology-registry.js +69 -30
  121. package/dist/runtime/foundation/service-wire-m6a-codec.d.ts +3 -3
  122. package/dist/runtime/foundation/service-wire-m6a-codec.js +36 -38
  123. package/dist/runtime/handlers/handler-instance-scope.d.ts +8 -0
  124. package/dist/runtime/handlers/handler-instance-scope.js +54 -11
  125. package/dist/runtime/host/actor-packet-relay.js +7 -7
  126. package/dist/runtime/host/actor-runtime-options-factory.js +2 -2
  127. package/dist/runtime/host/application-job-queue.d.ts +28 -9
  128. package/dist/runtime/host/application-job-queue.js +214 -50
  129. package/dist/runtime/host/entry-actor-runtime.d.ts +1 -0
  130. package/dist/runtime/host/entry-actor-runtime.js +4 -1
  131. package/dist/runtime/host/index.d.ts +7 -1
  132. package/dist/runtime/host/index.js +154 -126
  133. package/dist/runtime/host/instance-activation-authority.d.ts +2 -1
  134. package/dist/runtime/host/instance-activation-authority.js +89 -25
  135. package/dist/runtime/host/remote-bound-session-relay.js +2 -18
  136. package/dist/runtime/host/route-mesh-runtime.js +1 -1
  137. package/dist/runtime/host/service-relocation-control.d.ts +1 -0
  138. package/dist/runtime/host/service-relocation-control.js +10 -4
  139. package/dist/runtime/host/service-relocation-host-runtime.d.ts +6 -8
  140. package/dist/runtime/host/service-relocation-host-runtime.js +215 -243
  141. package/dist/runtime/host/spot-address-transport.d.ts +1 -0
  142. package/dist/runtime/host/spot-address-transport.js +28 -14
  143. package/dist/runtime/host/spot-runtime-options-factory.js +3 -2
  144. package/dist/runtime/host/user-spot-creation-coordinator.d.ts +1 -0
  145. package/dist/runtime/host/user-spot-creation-coordinator.js +1 -0
  146. package/dist/runtime/locations/actor-location-claims.d.ts +2 -2
  147. package/dist/runtime/locations/actor-location-claims.js +34 -19
  148. package/dist/runtime/locations/domain-store-contract.d.ts +2 -2
  149. package/dist/runtime/locations/in-memory-authority-store.d.ts +4 -2
  150. package/dist/runtime/locations/in-memory-authority-store.js +80 -8
  151. package/dist/runtime/locations/in-memory-location-store.d.ts +2 -2
  152. package/dist/runtime/locations/in-memory-location-store.js +19 -3
  153. package/dist/runtime/locations/internal-location-contracts.d.ts +3 -0
  154. package/dist/runtime/locations/lifecycle.d.ts +1 -2
  155. package/dist/runtime/locations/lifecycle.js +2 -5
  156. package/dist/runtime/locations/location-store-repository.d.ts +3 -2
  157. package/dist/runtime/locations/location-store-repository.js +165 -22
  158. package/dist/runtime/locations/resolvers.d.ts +2 -1
  159. package/dist/runtime/locations/resolvers.js +10 -1
  160. package/dist/runtime/locations/runtime.d.ts +1 -1
  161. package/dist/runtime/locations/runtime.js +24 -23
  162. package/dist/runtime/messaging/framework-json-v1.d.ts +4 -6
  163. package/dist/runtime/messaging/framework-json-v1.js +38 -294
  164. package/dist/runtime/messaging/packet-name.d.ts +1 -1
  165. package/dist/runtime/messaging/packet-name.js +8 -24
  166. package/dist/runtime/messaging/request-result.d.ts +2 -0
  167. package/dist/runtime/messaging/request-result.js +54 -0
  168. package/dist/runtime/messaging/submission-result.d.ts +2 -1
  169. package/dist/runtime/messaging/submission-result.js +7 -4
  170. package/dist/runtime/protocol/service_wire_codec.generated.d.ts +15 -0
  171. package/dist/runtime/protocol/service_wire_codec.generated.js +144 -0
  172. package/dist/runtime/protocol/service_wire_pilot_codec.generated.d.ts +9 -0
  173. package/dist/runtime/protocol/service_wire_pilot_codec.generated.js +14 -1
  174. package/dist/runtime/spots/formal-remote-actor-admission-registry.d.ts +9 -2
  175. package/dist/runtime/spots/formal-remote-actor-admission-registry.js +33 -19
  176. package/dist/runtime/spots/index.d.ts +7 -3
  177. package/dist/runtime/spots/index.js +23 -16
  178. package/dist/runtime/spots/spot-activation.d.ts +3 -1
  179. package/dist/runtime/spots/spot-activation.js +21 -12
  180. package/dist/runtime/spots/spot-actor-admission-coordinator.d.ts +2 -1
  181. package/dist/runtime/spots/spot-actor-admission-coordinator.js +11 -10
  182. package/dist/runtime/spots/spot-actor-packet-dispatch.d.ts +4 -1
  183. package/dist/runtime/spots/spot-actor-packet-dispatch.js +7 -5
  184. package/dist/runtime/spots/spot-actor-packet-drain.js +2 -0
  185. package/dist/runtime/spots/spot-actor-packet-relay-dispatch.js +1 -0
  186. package/dist/runtime/spots/spot-entry-activation.js +9 -3
  187. package/dist/runtime/spots/spot-handler-registry.d.ts +3 -1
  188. package/dist/runtime/spots/spot-handler-registry.js +18 -8
  189. package/dist/runtime/spots/spot-node-autoconnect.js +4 -3
  190. package/dist/runtime/spots/spot-node-runtime-manager.d.ts +2 -1
  191. package/dist/runtime/spots/spot-node-runtime-manager.js +4 -11
  192. package/dist/runtime/spots/spot-outbound.d.ts +3 -0
  193. package/dist/runtime/spots/spot-outbound.js +24 -15
  194. package/dist/runtime/spots/spot-routed-spot-packet-dispatch.d.ts +1 -0
  195. package/dist/runtime/spots/spot-routed-spot-packet-dispatch.js +1 -1
  196. package/dist/runtime/spots/spot-routing-internal.d.ts +6 -0
  197. package/dist/runtime/spots/spot-runtime-ports.d.ts +3 -1
  198. package/dist/runtime/spots/spot-subscription-dispatch.js +0 -3
  199. package/dist/runtime/spots/spot-timer.js +1 -0
  200. package/dist/runtime/streams/stream-session-runtime.d.ts +1 -1
  201. package/dist/runtime/streams/stream-session-runtime.js +14 -28
  202. package/package.json +3 -3
  203. package/src/contracts/Actors/ZLinkActorClient.ts +2 -1
  204. package/src/contracts/Channels/Calls.ts +2 -1
  205. package/src/contracts/Common/ZLinkMessageMetadata.ts +13 -8
  206. package/src/contracts/Configuration/Builders.ts +1 -2
  207. package/src/contracts/Configuration/Configs.ts +0 -6
  208. package/src/contracts/Configuration/RegistrationBuilders.ts +8 -12
  209. package/src/contracts/Configuration/RegistrationTypes.ts +1 -6
  210. package/src/contracts/Configuration/RegistrationValidators.ts +9 -10
  211. package/src/contracts/Configuration/index.ts +1 -6
  212. package/src/contracts/Handlers/Attributes.ts +14 -21
  213. package/src/contracts/Handlers/JsonContract.ts +8 -216
  214. package/src/contracts/Spots/Contracts.ts +2 -1
  215. package/src/internal.ts +1 -0
  216. package/src/nest-integration.ts +1 -0
  217. package/src/runtime/actors/actor-client.ts +40 -16
  218. package/src/runtime/actors/actor-handoff.ts +22 -8
  219. package/src/runtime/actors/actor-join-relocation.ts +1 -0
  220. package/src/runtime/actors/actor-local-native-join.ts +17 -26
  221. package/src/runtime/actors/actor-remote-wire.ts +17 -0
  222. package/src/runtime/actors/actor-routed-join-transport.ts +14 -4
  223. package/src/runtime/actors/actor-routed-json-request.ts +10 -2
  224. package/src/runtime/actors/index.ts +19 -5
  225. package/src/runtime/actors/spot-actor-dispatch.ts +4 -2
  226. package/src/runtime/admission.ts +18 -5
  227. package/src/runtime/application-jobs/application-ingress-record-owner.ts +53 -27
  228. package/src/runtime/application-jobs/application-job-queue-scope.ts +56 -22
  229. package/src/runtime/application-jobs/contracts.ts +28 -2
  230. package/src/runtime/backend/contracts/index.ts +63 -32
  231. package/src/runtime/backend/mesh-completion-table.ts +175 -59
  232. package/src/runtime/backend/mesh-dispatch-pump.ts +59 -32
  233. package/src/runtime/backend/node/node-backend-adapter-factory.ts +12 -5
  234. package/src/runtime/backend/node/node-backend-adapter-support.ts +42 -31
  235. package/src/runtime/backend/node/node-dealer-channel-client-transport.ts +12 -2
  236. package/src/runtime/backend/node/node-mesh-backend-adapter.ts +3 -10
  237. package/src/runtime/backend/node/node-raw-binding-port.ts +73 -37
  238. package/src/runtime/backend/node/node-raw-mesh-backend.ts +209 -176
  239. package/src/runtime/backend/node/node-socket-backend-adapter.ts +32 -13
  240. package/src/runtime/backend/raw-binding-port.ts +18 -3
  241. package/src/runtime/backend/runtime-message.ts +6 -0
  242. package/src/runtime/backend/runtime-values.ts +1 -0
  243. package/src/runtime/channels/channel-clients.ts +90 -41
  244. package/src/runtime/channels/channel-dispatch-pipeline.ts +69 -34
  245. package/src/runtime/channels/channel-dispatch-services.ts +69 -1
  246. package/src/runtime/channels/channel-dispatchers.ts +29 -27
  247. package/src/runtime/channels/channel-envelope-inspection.ts +2 -16
  248. package/src/runtime/channels/channel-envelope.ts +133 -8
  249. package/src/runtime/channels/channel-outbound-operations.ts +22 -8
  250. package/src/runtime/channels/channel-receive-loops.ts +3 -3
  251. package/src/runtime/channels/channel-runtime-lifecycle.ts +7 -1
  252. package/src/runtime/channels/channel-runtime-manager.ts +29 -12
  253. package/src/runtime/channels/channel-socket-registry.ts +84 -130
  254. package/src/runtime/channels/channel-transports.ts +128 -60
  255. package/src/runtime/channels/local-spot-route-transport.ts +3 -1
  256. package/src/runtime/channels/router-socket-spot-route-transport.ts +13 -4
  257. package/src/runtime/channels/source-spot-router.ts +8 -4
  258. package/src/runtime/channels/spot-node-route-transport.ts +8 -4
  259. package/src/runtime/channels/spot-route-bridge-transport.ts +6 -4
  260. package/src/runtime/channels/spot-route-dispatch-strategy.ts +47 -18
  261. package/src/runtime/diagnostics/message-flow.ts +1 -1
  262. package/src/runtime/execution/serial-execution-queue.ts +2 -0
  263. package/src/runtime/foundation/actor-join-recovery-codec.ts +2 -2
  264. package/src/runtime/foundation/durable-service-request.ts +137 -0
  265. package/src/runtime/foundation/operation-identity.ts +5 -1
  266. package/src/runtime/foundation/raw-service-mesh-runtime.ts +642 -253
  267. package/src/runtime/foundation/service-liveness-registry.ts +68 -59
  268. package/src/runtime/foundation/service-mailbox.ts +7 -1
  269. package/src/runtime/foundation/service-relocation-object-owner.ts +2 -0
  270. package/src/runtime/foundation/service-relocation-runtime.ts +18 -1
  271. package/src/runtime/foundation/service-runtime-contracts.ts +7 -1
  272. package/src/runtime/foundation/service-stateful-runtime.ts +128 -160
  273. package/src/runtime/foundation/service-stateful-wire-codec.ts +55 -84
  274. package/src/runtime/foundation/service-topology-registry.ts +103 -42
  275. package/src/runtime/foundation/service-wire-m6a-codec.ts +57 -38
  276. package/src/runtime/handlers/handler-instance-scope.ts +67 -16
  277. package/src/runtime/host/actor-packet-relay.ts +7 -0
  278. package/src/runtime/host/actor-runtime-options-factory.ts +14 -2
  279. package/src/runtime/host/application-job-queue.ts +249 -48
  280. package/src/runtime/host/entry-actor-runtime.ts +5 -0
  281. package/src/runtime/host/index.ts +224 -160
  282. package/src/runtime/host/instance-activation-authority.ts +132 -27
  283. package/src/runtime/host/remote-bound-session-relay.ts +2 -23
  284. package/src/runtime/host/route-mesh-runtime.ts +1 -1
  285. package/src/runtime/host/service-relocation-control.ts +11 -5
  286. package/src/runtime/host/service-relocation-host-runtime.ts +317 -291
  287. package/src/runtime/host/spot-address-transport.ts +49 -24
  288. package/src/runtime/host/spot-runtime-options-factory.ts +4 -0
  289. package/src/runtime/host/user-spot-creation-coordinator.ts +8 -0
  290. package/src/runtime/locations/actor-location-claims.ts +52 -30
  291. package/src/runtime/locations/domain-store-contract.ts +6 -2
  292. package/src/runtime/locations/in-memory-authority-store.ts +113 -9
  293. package/src/runtime/locations/in-memory-location-store.ts +25 -3
  294. package/src/runtime/locations/internal-location-contracts.ts +4 -0
  295. package/src/runtime/locations/lifecycle.ts +8 -26
  296. package/src/runtime/locations/location-store-repository.ts +220 -15
  297. package/src/runtime/locations/resolvers.ts +25 -2
  298. package/src/runtime/locations/runtime.ts +28 -24
  299. package/src/runtime/messaging/framework-json-v1.ts +5 -325
  300. package/src/runtime/messaging/packet-name.ts +5 -25
  301. package/src/runtime/messaging/request-result.ts +58 -0
  302. package/src/runtime/messaging/submission-result.ts +7 -3
  303. package/src/runtime/protocol/service_wire_codec.generated.ts +131 -1
  304. package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +4 -4
  305. package/src/runtime/spots/formal-remote-actor-admission-registry.ts +45 -23
  306. package/src/runtime/spots/index.ts +30 -2
  307. package/src/runtime/spots/spot-activation.ts +33 -10
  308. package/src/runtime/spots/spot-actor-admission-coordinator.ts +13 -0
  309. package/src/runtime/spots/spot-actor-packet-dispatch.ts +10 -0
  310. package/src/runtime/spots/spot-actor-packet-drain.ts +2 -0
  311. package/src/runtime/spots/spot-actor-packet-relay-dispatch.ts +1 -0
  312. package/src/runtime/spots/spot-entry-activation.ts +12 -2
  313. package/src/runtime/spots/spot-handler-registry.ts +41 -8
  314. package/src/runtime/spots/spot-node-autoconnect.ts +6 -2
  315. package/src/runtime/spots/spot-node-runtime-manager.ts +7 -12
  316. package/src/runtime/spots/spot-outbound.ts +36 -16
  317. package/src/runtime/spots/spot-routed-spot-packet-dispatch.ts +2 -1
  318. package/src/runtime/spots/spot-routing-internal.ts +14 -0
  319. package/src/runtime/spots/spot-runtime-ports.ts +3 -0
  320. package/src/runtime/spots/spot-subscription-dispatch.ts +0 -3
  321. package/src/runtime/spots/spot-timer.ts +5 -1
  322. package/src/runtime/streams/stream-session-runtime.ts +13 -30
@@ -1,3 +1,4 @@
1
+ import type { ServiceInstanceColdActivationTarget } from '../foundation/service-stateful-wire-codec';
1
2
  import { ZLinkFrameworkException, ZLinkSpotKind, type RoutingId } from '../../contracts';
2
3
  import {
3
4
  ZLinkRuntimeDispatchErrorAction as ZLinkDispatchErrorAction,
@@ -44,7 +45,11 @@ import type {
44
45
  ZLinkSpotAddressTransport,
45
46
  ZLinkSpotRoutedTransport
46
47
  } from '../spots/spot-outbound';
47
- import type { ZLinkSpotRouteResolver, ZLinkSpotRouteTarget } from '../spots/spot-routing-internal';
48
+ import type {
49
+ ZLinkSpotRouteResolver,
50
+ ZLinkSpotRouteTarget,
51
+ ZLinkInstanceReactivationRoute
52
+ } from '../spots/spot-routing-internal';
48
53
 
49
54
  export interface ZLinkHostSpotAddressTransportOptions {
50
55
  readonly resolver: () => ZLinkSpotRouteResolver | undefined;
@@ -65,13 +70,7 @@ export function hasObjectClientCapability(role: 'none' | 'client' | 'server' | u
65
70
  type MissingTarget = {
66
71
  readonly meshName: string;
67
72
  readonly node: ZLinkBackendMeshNode;
68
- readonly target: {
69
- readonly targetNodeRid: string;
70
- readonly targetNodeGeneration: bigint;
71
- readonly targetSpotId: string;
72
- readonly stableType: string;
73
- readonly descriptorVersion: string;
74
- };
73
+ readonly target: ServiceInstanceColdActivationTarget;
75
74
  };
76
75
 
77
76
  type MissingTargetSelection =
@@ -106,7 +105,10 @@ export class ZLinkHostSpotAddressTransport implements ZLinkSpotAddressTransport
106
105
  const activationDeadlineUnixMs = BigInt(
107
106
  Math.round(Date.now() + this.options.defaultRequestTimeoutMs)
108
107
  );
109
- const existing = await this.resolveExisting(spotId);
108
+ const resolution = await this.resolveExisting(spotId, undefined, call);
109
+ const existing = resolution !== undefined && !('kind' in resolution) ? resolution : undefined;
110
+ if (resolution !== undefined && 'kind' in resolution)
111
+ call = this.reactivationCall(resolution, call);
110
112
  if (existing !== undefined) {
111
113
  this.validateExisting(existing, call);
112
114
  try {
@@ -166,7 +168,7 @@ export class ZLinkHostSpotAddressTransport implements ZLinkSpotAddressTransport
166
168
  if (!call.instanceSpot) {
167
169
  return { status: ZLinkSubmitStatus.TargetNotFound };
168
170
  }
169
- const selected = this.selectMissingTarget(spotId, call);
171
+ const selected = this.selectMissingTarget(spotId, call, resolution);
170
172
  if (selected.kind === 'unsupported') {
171
173
  this.traceInstanceAddress(
172
174
  ZLinkMessageFlowOutcome.Dropped,
@@ -252,10 +254,13 @@ export class ZLinkHostSpotAddressTransport implements ZLinkSpotAddressTransport
252
254
  const timeoutMs = call.timeoutMs ?? this.options.defaultRequestTimeoutMs;
253
255
  const deadline = createSpotAddressDeadline(timeoutMs, call.signal);
254
256
  try {
255
- const existing = await this.resolveExisting(spotId, deadline.signal);
257
+ const resolution = await this.resolveExisting(spotId, deadline.signal, call);
258
+ const existing = resolution !== undefined && !('kind' in resolution) ? resolution : undefined;
259
+ if (resolution !== undefined && 'kind' in resolution)
260
+ call = this.reactivationCall(resolution, call);
256
261
  deadline.requireRemaining();
257
262
  if (existing === undefined) {
258
- return await this.requestToMissingInstance(spotId, request, call, deadline);
263
+ return await this.requestToMissingInstance(spotId, request, call, deadline, resolution);
259
264
  }
260
265
  this.validateExisting(existing, call);
261
266
  try {
@@ -331,7 +336,8 @@ export class ZLinkHostSpotAddressTransport implements ZLinkSpotAddressTransport
331
336
  instanceSpot: call.instanceSpot,
332
337
  timeoutMs: deadline.requireRemaining(),
333
338
  signal: deadline.signal,
334
- metadata: call.metadata
339
+ metadata: call.metadata,
340
+ onAdmitted: call.onAdmitted
335
341
  }),
336
342
  deadline.signal
337
343
  );
@@ -351,7 +357,8 @@ export class ZLinkHostSpotAddressTransport implements ZLinkSpotAddressTransport
351
357
  spotId: RoutingId,
352
358
  request: unknown,
353
359
  call: ZLinkSpotAddressCallOptions,
354
- deadline: ZLinkSpotAddressDeadline
360
+ deadline: ZLinkSpotAddressDeadline,
361
+ current?: ZLinkSpotRouteTarget | ZLinkInstanceReactivationRoute
355
362
  ): Promise<TReply> {
356
363
  if (!call.instanceSpot) {
357
364
  throw createInternalFrameworkException(
@@ -359,7 +366,7 @@ export class ZLinkHostSpotAddressTransport implements ZLinkSpotAddressTransport
359
366
  `Spot '${String(spotId)}' has no Ready authority.`
360
367
  );
361
368
  }
362
- const selected = this.selectMissingTarget(spotId, call);
369
+ const selected = this.selectMissingTarget(spotId, call, current);
363
370
  if (selected.kind === 'capacity') {
364
371
  throw missingInstancePlacementCapacity(spotId, call.instanceSpotType);
365
372
  }
@@ -410,7 +417,8 @@ export class ZLinkHostSpotAddressTransport implements ZLinkSpotAddressTransport
410
417
  encoded,
411
418
  deadlineUnixMs,
412
419
  call.sourceSpot === undefined ? undefined : String(call.sourceSpot.routingId),
413
- call.metadata
420
+ call.metadata,
421
+ call.onAdmitted
414
422
  ),
415
423
  deadline.signal
416
424
  );
@@ -507,14 +515,20 @@ export class ZLinkHostSpotAddressTransport implements ZLinkSpotAddressTransport
507
515
 
508
516
  private async resolveExisting(
509
517
  spotId: RoutingId,
510
- signal?: AbortSignal
511
- ): Promise<import('../spots/spot-routing-internal').ZLinkSpotRouteTarget | undefined> {
518
+ signal?: AbortSignal,
519
+ call?: ZLinkSpotAddressCallOptions
520
+ ): Promise<ZLinkSpotRouteTarget | ZLinkInstanceReactivationRoute | undefined> {
512
521
  const resolver = this.options.resolver();
513
522
  if (resolver === undefined) {
514
523
  throw new Error('Global Spot address resolution requires a Location Store.');
515
524
  }
516
525
  try {
517
- return await awaitWithAbort(resolver.resolve(spotId, signal), signal);
526
+ return await awaitWithAbort(
527
+ call?.instanceSpot === true
528
+ ? resolver.resolve(spotId, signal, true)
529
+ : resolver.resolve(spotId, signal),
530
+ signal
531
+ );
518
532
  } catch (error) {
519
533
  if (
520
534
  error instanceof ZLinkFrameworkException &&
@@ -526,9 +540,18 @@ export class ZLinkHostSpotAddressTransport implements ZLinkSpotAddressTransport
526
540
  }
527
541
  }
528
542
 
543
+ private reactivationCall(
544
+ route: ZLinkInstanceReactivationRoute,
545
+ call: ZLinkSpotAddressCallOptions
546
+ ): ZLinkSpotAddressCallOptions {
547
+ this.validateExisting(route, call);
548
+ return { ...call, initialMeshName: route.meshName, instanceSpotType: route.stableType };
549
+ }
550
+
529
551
  private selectMissingTarget(
530
552
  spotId: RoutingId,
531
- call: ZLinkSpotAddressCallOptions
553
+ call: ZLinkSpotAddressCallOptions,
554
+ current?: ZLinkSpotRouteTarget | ZLinkInstanceReactivationRoute
532
555
  ): MissingTargetSelection {
533
556
  const configuredMeshes = this.options.meshNames();
534
557
  if (
@@ -574,14 +597,15 @@ export class ZLinkHostSpotAddressTransport implements ZLinkSpotAddressTransport
574
597
  const stableType =
575
598
  call.instanceSpotType ?? (distinctTypes.length === 1 ? distinctTypes[0] : undefined);
576
599
  if (stableType === undefined) {
577
- if (distinctTypes.length === 0) return { kind: 'unsupported' };
600
+ if (distinctTypes.length === 0)
601
+ return { kind: current === undefined ? 'unsupported' : 'unavailable' };
578
602
  throw createInternalFrameworkException(
579
603
  ZLinkFrameworkInternalErrorKind.InvalidOperation,
580
604
  'Instance Spot type is required when multiple types are registered.'
581
605
  );
582
606
  }
583
607
  if (canInspectPlacementTypes && !distinctTypes.includes(stableType)) {
584
- return { kind: 'unsupported' };
608
+ return { kind: current === undefined ? 'unsupported' : 'unavailable' };
585
609
  }
586
610
  let unavailable = false;
587
611
  let capacity = false;
@@ -600,6 +624,7 @@ export class ZLinkHostSpotAddressTransport implements ZLinkSpotAddressTransport
600
624
  node,
601
625
  target: {
602
626
  ...placement.target,
627
+ targetMeshName: meshName,
603
628
  targetSpotId: String(spotId),
604
629
  stableType
605
630
  }
@@ -611,12 +636,12 @@ export class ZLinkHostSpotAddressTransport implements ZLinkSpotAddressTransport
611
636
  }
612
637
  if (unavailable) return { kind: 'unavailable' };
613
638
  if (capacity) return { kind: 'capacity' };
614
- if (unsupported) return { kind: 'unsupported' };
639
+ if (unsupported) return { kind: current === undefined ? 'unsupported' : 'unavailable' };
615
640
  return { kind: 'unavailable' };
616
641
  }
617
642
 
618
643
  private validateExisting(
619
- target: import('../spots/spot-routing-internal').ZLinkSpotRouteTarget,
644
+ target: Pick<ZLinkSpotRouteTarget, 'spotId' | 'spotKind' | 'stableType'>,
620
645
  call: ZLinkSpotAddressCallOptions
621
646
  ): void {
622
647
  if (!call.instanceSpot) return;
@@ -102,6 +102,7 @@ export class ZLinkSpotRuntimeOptionsFactory {
102
102
  Promise.resolve()
103
103
  },
104
104
  dispatchEntryActorPacket: (
105
+ origin,
105
106
  actorId,
106
107
  parts,
107
108
  returnResponse,
@@ -117,6 +118,7 @@ export class ZLinkSpotRuntimeOptionsFactory {
117
118
  );
118
119
  }
119
120
  return runtime.dispatchEntryActorPacket(
121
+ origin,
120
122
  actorId,
121
123
  parts,
122
124
  returnResponse,
@@ -331,6 +333,8 @@ export class ZLinkSpotRuntimeOptionsFactory {
331
333
  );
332
334
  },
333
335
  actorTransferRuntime,
336
+ releaseActorMembers: (meshName, spotId) =>
337
+ this.options.actorManager()?.releaseSpotActorMembers(meshName, spotId) ?? Promise.resolve(),
334
338
  boundSessionRuntime: this.options.boundSessionRelay.boundSessions,
335
339
  actorHandoffRuntime: this.options.actorHandoff,
336
340
  metrics: this.options.metrics,
@@ -38,6 +38,10 @@ const DEFAULT_USER_SPOT_CLEANUP_TIMEOUT_MS = 1_000;
38
38
  const DEFAULT_USER_SPOT_POLL_INTERVAL_MS = 10;
39
39
 
40
40
  export interface ZLinkUserSpotCreationCoordinatorOptions {
41
+ readonly relocationPolicy?: (
42
+ meshName: string,
43
+ stableType: string
44
+ ) => import('../locations/internal-location-contracts').ZLinkObjectReserveRequest['actorRelocationPolicy'];
41
45
  readonly store: ZLinkObjectCreationStore & ZLinkAuthorityStore;
42
46
  readonly target: (
43
47
  request: Pick<ZLinkUserSpotCreationRequest, 'meshName' | 'stableType'>,
@@ -169,6 +173,10 @@ export class ZLinkUserSpotCreationCoordinator {
169
173
  reserved = await this.options.store.reserve(
170
174
  {
171
175
  key: { kind: 'user_spot', globalId: String(request.spotId) },
176
+ actorRelocationPolicy: this.options.relocationPolicy?.(
177
+ target.meshName,
178
+ request.stableType
179
+ ),
172
180
  intent: {
173
181
  stableType: request.stableType,
174
182
  requestContentReference: contentReference,
@@ -12,6 +12,10 @@ import { ZLinkSpotKind } from '../../contracts/Spots';
12
12
  import { ZLinkLocationKeyCodec } from './key-codec';
13
13
  import { encodeAuthorityKey } from './authority-key-codec';
14
14
  import { routingIdsEqual } from '../routing-id';
15
+ import {
16
+ decodeActorAuthorityIdentity,
17
+ rewriteActorAuthorityRoute
18
+ } from '../actors/actor-authority-publication';
15
19
  import type { IZLinkLocationLifecycleRuntime, ZLinkOwnershipLostEvent } from './lifecycle-runtime';
16
20
 
17
21
  export enum ZLinkActorClaimStatus {
@@ -203,41 +207,59 @@ export class ZLinkActorLocationClaims {
203
207
  return { status: ZLinkActorClaimStatus.Claimed, claimed, generation: result.generation };
204
208
  }
205
209
 
206
- async notifyJoinedSpot(
210
+ async commitMembership(
207
211
  actorType: string,
208
- actorId: string,
209
- _spotMeshName: string,
212
+ actorRef: ActorRef,
213
+ authorityOwnerGeneration: bigint,
210
214
  spotId: RoutingId,
211
215
  spotGeneration: bigint,
212
- membershipEpoch: bigint,
216
+ spotKind: ZLinkSpotKind.Entry | ZLinkSpotKind.User,
213
217
  ownerNodeGeneration: bigint
214
218
  ): Promise<void> {
215
- await this.renew(actorType, actorId, (row) => ({
216
- ...row,
217
- spotKind: ZLinkSpotKind.User,
218
- spotId,
219
- spotGeneration,
220
- membershipEpoch,
221
- ownerNodeGeneration
222
- }));
223
- }
224
-
225
- async notifyLeftSpot(
226
- actorType: string,
227
- actorId: string,
228
- entrySpotId: RoutingId,
229
- entrySpotGeneration: bigint,
230
- membershipEpoch: bigint,
231
- ownerNodeGeneration: bigint
232
- ): Promise<void> {
233
- await this.renew(actorType, actorId, (row) => ({
234
- ...row,
235
- spotKind: ZLinkSpotKind.Entry,
236
- spotId: entrySpotId,
237
- spotGeneration: entrySpotGeneration,
238
- membershipEpoch,
239
- ownerNodeGeneration
240
- }));
219
+ const actorId = actorRef.actorId;
220
+ const store = this.authorityStore;
221
+ const owner = this.runtime.currentOwnerToken;
222
+ if (store === undefined || owner === undefined) {
223
+ throw new Error('Actor membership commit requires Location Store authority and owner.');
224
+ }
225
+ const key = encodeAuthorityKey('actor', actorId);
226
+ const current = await store.readAuthority(key);
227
+ if (
228
+ !matchesActorAuthority(current, actorRef, owner) ||
229
+ current.allocation.stableType !== actorType ||
230
+ current.authorityOwnerGeneration !== authorityOwnerGeneration ||
231
+ current.allocation.descriptorLifecycleGeneration !== ownerNodeGeneration
232
+ ) {
233
+ throw new Error(`Actor '${actorId}' membership authority fence does not match.`);
234
+ }
235
+ const identity = decodeActorAuthorityIdentity(current.payload, current.objectGeneration);
236
+ if (
237
+ identity === undefined ||
238
+ identity.actorType !== actorType ||
239
+ identity.ownerNodeGeneration !== ownerNodeGeneration ||
240
+ identity.owner.ownerId !== owner.ownerId ||
241
+ identity.owner.leaseGeneration !== owner.leaseGeneration ||
242
+ !routingIdsEqual(identity.actor.nodeRid, actorRef.nodeRid) ||
243
+ identity.meshName !== actorRef.meshName
244
+ ) {
245
+ throw new Error(`Actor '${actorId}' membership authority identity does not match.`);
246
+ }
247
+ const result = await store.compareExchangeAuthority(key, current.storeVersion, {
248
+ kind: 'put',
249
+ generationTransition: 'preserve',
250
+ payload: rewriteActorAuthorityRoute(
251
+ current.payload,
252
+ actorRef,
253
+ String(spotId),
254
+ spotGeneration,
255
+ spotKind
256
+ )
257
+ });
258
+ if (result.kind !== 'stored') {
259
+ throw new Error(
260
+ `Actor '${actorId}' membership commit was rejected with status ${result.kind}.`
261
+ );
262
+ }
241
263
  }
242
264
 
243
265
  async release(_actorType: string, actorId: string, actorRef?: ActorRef): Promise<void> {
@@ -39,7 +39,10 @@ import type {
39
39
  ZLinkObjectCreationCompleteResult,
40
40
  ZLinkObjectReserveResult
41
41
  } from '../../contracts/Locations/Authority';
42
- import type { ZLinkObjectReserveRequest } from './internal-location-contracts';
42
+ import type {
43
+ ZLinkObjectReserveRequest,
44
+ ZLinkEndedOwnerReleaseIntent
45
+ } from './internal-location-contracts';
43
46
 
44
47
  /**
45
48
  * Framework-private domain repository. Provider implementations never
@@ -143,7 +146,8 @@ export interface ZLinkDomainLocationStore {
143
146
  releaseEndedReservation?(
144
147
  key: ZLinkAuthorityKey,
145
148
  expectedStoreVersion: string,
146
- signal?: AbortSignal
149
+ signal?: AbortSignal,
150
+ request?: ZLinkEndedOwnerReleaseIntent
147
151
  ): Promise<boolean>;
148
152
  abort(
149
153
  request: ZLinkObjectAbortRequest,
@@ -32,6 +32,7 @@ import type {
32
32
  ZLinkObjectCommitResult,
33
33
  ZLinkObjectCreationCompleteRequest,
34
34
  ZLinkObjectCreationCompleteResult,
35
+ ZLinkEndedOwnerReleaseIntent,
35
36
  ZLinkObjectReserveRequest,
36
37
  ZLinkObjectReserveResult,
37
38
  ZLinkCreationOperationIdentity,
@@ -42,7 +43,13 @@ import type {
42
43
  } from './internal-location-contracts';
43
44
  import { encodeAuthorityKey } from './authority-key-codec';
44
45
  import { creationTerminalPreimage } from './opaque-record-key';
45
- import { ServiceRelocationAuthorityPayloadCodec } from '../foundation/service-relocation-runtime';
46
+ import {
47
+ ServiceRelocationAuthorityPayloadCodec,
48
+ serviceRelocationAuthorityApplicationPayload
49
+ } from '../foundation/service-relocation-runtime';
50
+ import { decodeServiceReadySpotAuthority } from '../foundation/service-authority-payload-codec';
51
+ import { decodeActorAuthorityPayload } from '../actors/actor-authority-payload-codec';
52
+ import { ZLinkSpotKind } from '../../contracts';
46
53
 
47
54
  const MAX_GENERATION = 0x7fff_ffff_ffff_ffffn;
48
55
 
@@ -64,6 +71,7 @@ export interface ZLinkInMemoryAuthorityValidation {
64
71
  currentActive: ZLinkCapacityVector
65
72
  ): boolean;
66
73
  identityClaimed?(authorityKey: string): boolean;
74
+ hasSpotMembers?(spotId: string, objectGeneration: bigint): boolean;
67
75
  }
68
76
 
69
77
  interface AuthorityRow {
@@ -203,6 +211,26 @@ export class ZLinkInMemoryAuthorityStore {
203
211
  if (!this.isOwnerLive(row.snapshot)) {
204
212
  return { kind: 'conflict', current: this.read(keyValue) };
205
213
  }
214
+ const actor =
215
+ row.snapshot.allocation.objectKind === 'actor'
216
+ ? decodeActorAuthorityPayload(
217
+ serviceRelocationAuthorityApplicationPayload(mutation.payload)
218
+ )
219
+ : undefined;
220
+ const previousActor =
221
+ actor === undefined
222
+ ? undefined
223
+ : decodeActorAuthorityPayload(
224
+ serviceRelocationAuthorityApplicationPayload(row.snapshot.payload)
225
+ );
226
+ if (
227
+ actor?.currentSpotKind === ZLinkSpotKind.User &&
228
+ (previousActor?.currentSpotKind !== ZLinkSpotKind.User ||
229
+ previousActor.currentSpotId !== actor.currentSpotId ||
230
+ previousActor.currentSpotGeneration !== actor.currentSpotGeneration) &&
231
+ !this.acceptsUserSpotMembership(actor.currentSpotId, actor.currentSpotGeneration)
232
+ )
233
+ return { kind: 'conflict', current: this.read(keyValue) };
206
234
  if (
207
235
  mutation.generationTransition === 'reincarnate' &&
208
236
  (this.objectGeneration >= MAX_GENERATION || this.ownerGeneration >= MAX_GENERATION)
@@ -283,27 +311,41 @@ export class ZLinkInMemoryAuthorityStore {
283
311
  async releaseEndedReservation(
284
312
  key: ZLinkAuthorityKey,
285
313
  expectedStoreVersion: string,
286
- signal?: AbortSignal
314
+ signal?: AbortSignal,
315
+ request?: ZLinkEndedOwnerReleaseIntent
287
316
  ): Promise<boolean> {
288
317
  signal?.throwIfAborted();
289
- return this.tryReleaseEndedReservation(key, expectedStoreVersion);
318
+ return this.tryReleaseEndedReservation(key, expectedStoreVersion, request);
319
+ }
320
+
321
+ acceptsUserSpotMembership(spotId: string, objectGeneration: bigint): boolean {
322
+ const row = this.rows.get(encodeAuthorityKey('user_spot', spotId).value);
323
+ return (
324
+ row !== undefined &&
325
+ row.snapshot.allocation.objectKind === 'user_spot' &&
326
+ row.snapshot.allocation.state === 'active' &&
327
+ row.snapshot.objectGeneration === objectGeneration &&
328
+ decodeServiceReadySpotAuthority(row.snapshot.payload)?.kind === 'user_spot' &&
329
+ this.isOwnerLive(row.snapshot)
330
+ );
290
331
  }
291
332
 
292
333
  private tryReleaseEndedReservation(
293
334
  key: ZLinkAuthorityKey,
294
335
  expectedStoreVersion: string,
295
- request?: ZLinkObjectReserveRequest
336
+ request?: ZLinkEndedOwnerReleaseIntent
296
337
  ): boolean {
297
338
  const current = this.rows.get(key.value);
298
339
  if (
299
340
  current === undefined ||
300
341
  current.snapshot.storeVersion.value !== expectedStoreVersion ||
301
342
  (current.snapshot.allocation.state === 'active'
302
- ? request?.key.kind !== 'actor'
343
+ ? request === undefined
303
344
  : current.creation === undefined)
304
345
  )
305
346
  return false;
306
347
  if (current.snapshot.allocation.state === 'active') {
348
+ let unavailable = false;
307
349
  for (const aggregate of this.aggregates.values()) {
308
350
  if (
309
351
  aggregate.state === 'prepared' &&
@@ -311,9 +353,9 @@ export class ZLinkInMemoryAuthorityStore {
311
353
  (participant) => participant.authorityKey.value === key.value
312
354
  )
313
355
  )
314
- return false;
356
+ unavailable = true;
315
357
  }
316
- if (relocationAuthorityCodec.read(current.snapshot.payload) !== undefined) return false;
358
+ unavailable ||= relocationAuthorityCodec.read(current.snapshot.payload) !== undefined;
317
359
  if (
318
360
  this.validation.isOwnerLive({
319
361
  ownerId: current.snapshot.ownerId,
@@ -321,10 +363,37 @@ export class ZLinkInMemoryAuthorityStore {
321
363
  })
322
364
  )
323
365
  return false;
324
- if (request?.actorRelocationPolicy !== 'disabled')
366
+ const spot =
367
+ current.snapshot.allocation.objectKind === 'actor'
368
+ ? undefined
369
+ : decodeServiceReadySpotAuthority(current.snapshot.payload);
370
+ if (current.snapshot.allocation.objectKind !== 'actor') {
371
+ unavailable ||=
372
+ spot === undefined ||
373
+ spot.kind !== request?.key.kind ||
374
+ spot.stableType !== request.intent.stableType ||
375
+ spot.spotId !== request.key.globalId ||
376
+ spot.activationRecovery !== undefined;
377
+ if (spot?.kind === 'user_spot') {
378
+ unavailable ||=
379
+ this.validation.hasSpotMembers?.(spot.spotId, current.snapshot.objectGeneration) ===
380
+ true;
381
+ for (const row of this.rows.values()) {
382
+ if (row.snapshot.allocation.objectKind !== 'actor') continue;
383
+ const actor = decodeActorAuthorityPayload(
384
+ serviceRelocationAuthorityApplicationPayload(row.snapshot.payload)
385
+ );
386
+ unavailable ||=
387
+ actor?.currentSpotKind === ZLinkSpotKind.User &&
388
+ actor.currentSpotId === spot.spotId &&
389
+ actor.currentSpotGeneration === current.snapshot.objectGeneration;
390
+ }
391
+ }
392
+ }
393
+ if (unavailable || request?.actorRelocationPolicy !== 'disabled')
325
394
  throw new ZLinkFrameworkException(
326
395
  ZLinkFrameworkErrorKind.Unavailable,
327
- 'Actor owner lease is unavailable.'
396
+ 'Object owner lease is unavailable.'
328
397
  );
329
398
  } else if (
330
399
  this.validation.isTargetLive(
@@ -532,6 +601,17 @@ export class ZLinkInMemoryAuthorityStore {
532
601
  if (!this.creationTerminalAvailable(terminalRecord)) {
533
602
  return { kind: 'stale' };
534
603
  }
604
+ const actor =
605
+ request.completion.kind === 'created'
606
+ ? decodeActorAuthorityPayload(
607
+ serviceRelocationAuthorityApplicationPayload(request.completion.readyPayload)
608
+ )
609
+ : undefined;
610
+ if (
611
+ actor?.currentSpotKind === ZLinkSpotKind.User &&
612
+ !this.acceptsUserSpotMembership(actor.currentSpotId, actor.currentSpotGeneration)
613
+ )
614
+ return { kind: 'stale' };
535
615
  const nextVersion = this.tryNextStoreVersion();
536
616
  if (nextVersion === undefined) return { kind: 'generationExhausted' };
537
617
  const pending = row.snapshot.allocation;
@@ -698,6 +778,30 @@ export class ZLinkInMemoryAuthorityStore {
698
778
  ) {
699
779
  return { kind: 'stale' };
700
780
  }
781
+ const actor =
782
+ row.snapshot.allocation.objectKind === 'actor'
783
+ ? decodeActorAuthorityPayload(
784
+ serviceRelocationAuthorityApplicationPayload(participant.authorityPayload)
785
+ )
786
+ : undefined;
787
+ if (actor?.currentSpotKind === ZLinkSpotKind.User) {
788
+ const participantSpot = aggregate.request.participants.find(
789
+ (candidate) =>
790
+ candidate.authorityKey.value ===
791
+ encodeAuthorityKey('user_spot', actor.currentSpotId).value
792
+ );
793
+ if (participantSpot === undefined) {
794
+ if (!this.acceptsUserSpotMembership(actor.currentSpotId, actor.currentSpotGeneration))
795
+ return { kind: 'stale' };
796
+ } else {
797
+ const spot = this.rows.get(participantSpot.authorityKey.value);
798
+ if (
799
+ spot?.snapshot.allocation.objectKind !== 'user_spot' ||
800
+ spot.snapshot.objectGeneration !== actor.currentSpotGeneration
801
+ )
802
+ return { kind: 'stale' };
803
+ }
804
+ }
701
805
  if (participant.ownerTransition === 'newOwner') {
702
806
  if (
703
807
  !this.validation.isTargetLive(
@@ -1,4 +1,5 @@
1
1
  import type { RoutingId } from '../../contracts/Common';
2
+ import { ZLinkSpotKind } from '../../contracts';
2
3
  import { ZLINK_MAX_IDENTITY_TEXT_BYTES } from '../../contracts/Common/CoreTypes';
3
4
  import {
4
5
  isValidPublicWeight,
@@ -58,6 +59,7 @@ import {
58
59
  type ZLinkObjectCommitResult,
59
60
  type ZLinkObjectCreationCompleteRequest,
60
61
  type ZLinkObjectCreationCompleteResult,
62
+ type ZLinkEndedOwnerReleaseIntent,
61
63
  type ZLinkObjectReserveRequest,
62
64
  type ZLinkObjectReserveResult,
63
65
  type ZLinkOwnerLeaseClaimResult,
@@ -143,7 +145,18 @@ export class ZLinkInMemoryLocationStore
143
145
  typeCapacity.limit)))
144
146
  );
145
147
  },
146
- identityClaimed: (authorityKey) => this.entrySpotClaims.has(authorityKey)
148
+ identityClaimed: (authorityKey) => this.entrySpotClaims.has(authorityKey),
149
+ hasSpotMembers: (spotId, objectGeneration) => {
150
+ for (const actor of this.actors.rows.values()) {
151
+ if (
152
+ actor.spotKind === ZLinkSpotKind.User &&
153
+ String(actor.spotId) === spotId &&
154
+ actor.spotGeneration === objectGeneration
155
+ )
156
+ return true;
157
+ }
158
+ return false;
159
+ }
147
160
  },
148
161
  now
149
162
  );
@@ -205,9 +218,10 @@ export class ZLinkInMemoryLocationStore
205
218
  async releaseEndedReservation(
206
219
  key: ZLinkAuthorityKey,
207
220
  expectedStoreVersion: string,
208
- signal?: AbortSignal
221
+ signal?: AbortSignal,
222
+ request?: ZLinkEndedOwnerReleaseIntent
209
223
  ): Promise<boolean> {
210
- return this.authority.releaseEndedReservation(key, expectedStoreVersion, signal);
224
+ return this.authority.releaseEndedReservation(key, expectedStoreVersion, signal, request);
211
225
  }
212
226
 
213
227
  async abort(
@@ -705,6 +719,14 @@ export class ZLinkInMemoryLocationStore
705
719
  });
706
720
  const updatedAt = this.now();
707
721
  const current = this.actors.rows.get(key);
722
+ if (
723
+ actor.spotKind === ZLinkSpotKind.User &&
724
+ (current?.spotKind !== ZLinkSpotKind.User ||
725
+ String(current.spotId) !== String(actor.spotId) ||
726
+ current.spotGeneration !== actor.spotGeneration) &&
727
+ !this.authority.acceptsUserSpotMembership(String(actor.spotId), actor.spotGeneration)
728
+ )
729
+ return rejectedConflict();
708
730
  if (
709
731
  intent === ZLinkLocationWriteIntent.NewClaim &&
710
732
  current !== undefined &&
@@ -5,6 +5,10 @@ import type { ZLinkRelocationConfiguration } from '../../contracts/Configuration
5
5
  export interface ZLinkObjectReserveRequest extends ReserveRequest {
6
6
  readonly actorRelocationPolicy?: ZLinkRelocationConfiguration<unknown>['kind'];
7
7
  }
8
+ export type ZLinkEndedOwnerReleaseIntent = Pick<
9
+ ZLinkObjectReserveRequest,
10
+ 'key' | 'actorRelocationPolicy'
11
+ > & { readonly intent: Pick<ZLinkObjectReserveRequest['intent'], 'stableType'> };
8
12
  export type * from '../../contracts/Locations/Authority';
9
13
  export type {
10
14
  ZLinkActorLocation,