@zlink-systems/framework 0.29.0 → 0.30.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 (168) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/contracts/Configuration/Builders.d.ts +1 -2
  3. package/dist/contracts/Configuration/Configs.d.ts +0 -5
  4. package/dist/contracts/Configuration/RegistrationBuilders.js +6 -4
  5. package/dist/contracts/Configuration/RegistrationTypes.d.ts +1 -6
  6. package/dist/contracts/Configuration/RegistrationValidators.js +4 -4
  7. package/dist/contracts/Configuration/index.d.ts +1 -1
  8. package/dist/internal.d.ts +1 -0
  9. package/dist/internal.js +3 -1
  10. package/dist/runtime/actors/actor-handoff.d.ts +3 -2
  11. package/dist/runtime/actors/actor-handoff.js +9 -4
  12. package/dist/runtime/actors/actor-runtime-contracts.d.ts +1 -0
  13. package/dist/runtime/actors/index.d.ts +2 -0
  14. package/dist/runtime/actors/index.js +21 -6
  15. package/dist/runtime/application-jobs/application-ingress-record-owner.d.ts +3 -1
  16. package/dist/runtime/application-jobs/application-ingress-record-owner.js +6 -1
  17. package/dist/runtime/application-jobs/application-job-queue-scope.d.ts +3 -1
  18. package/dist/runtime/application-jobs/application-job-queue-scope.js +5 -0
  19. package/dist/runtime/application-jobs/contracts.d.ts +5 -1
  20. package/dist/runtime/backend/contracts/index.d.ts +10 -19
  21. package/dist/runtime/backend/mesh-completion-table.d.ts +6 -4
  22. package/dist/runtime/backend/mesh-completion-table.js +28 -18
  23. package/dist/runtime/backend/mesh-dispatch-pump.js +21 -25
  24. package/dist/runtime/backend/node/node-backend-adapter-factory.js +6 -1
  25. package/dist/runtime/backend/node/node-backend-adapter-support.d.ts +3 -3
  26. package/dist/runtime/backend/node/node-backend-adapter-support.js +24 -29
  27. package/dist/runtime/backend/node/node-mesh-backend-adapter.d.ts +1 -9
  28. package/dist/runtime/backend/node/node-mesh-backend-adapter.js +1 -1
  29. package/dist/runtime/backend/node/node-raw-binding-port.js +11 -6
  30. package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +10 -12
  31. package/dist/runtime/backend/node/node-raw-mesh-backend.js +64 -98
  32. package/dist/runtime/backend/node/node-socket-backend-adapter.js +10 -5
  33. package/dist/runtime/backend/raw-binding-port.d.ts +9 -2
  34. package/dist/runtime/channels/channel-receive-loops.js +3 -3
  35. package/dist/runtime/channels/channel-runtime-lifecycle.js +2 -1
  36. package/dist/runtime/channels/channel-socket-registry.d.ts +10 -3
  37. package/dist/runtime/channels/channel-socket-registry.js +59 -82
  38. package/dist/runtime/diagnostics/message-flow.d.ts +1 -0
  39. package/dist/runtime/diagnostics/message-flow.js +3 -3
  40. package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +15 -1
  41. package/dist/runtime/foundation/raw-service-mesh-runtime.js +193 -64
  42. package/dist/runtime/foundation/service-liveness-registry.d.ts +20 -8
  43. package/dist/runtime/foundation/service-liveness-registry.js +57 -44
  44. package/dist/runtime/foundation/service-mailbox.d.ts +3 -0
  45. package/dist/runtime/foundation/service-mailbox.js +2 -1
  46. package/dist/runtime/foundation/service-stateful-runtime.d.ts +7 -6
  47. package/dist/runtime/foundation/service-stateful-runtime.js +60 -41
  48. package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +5 -2
  49. package/dist/runtime/foundation/service-stateful-wire-codec.js +43 -61
  50. package/dist/runtime/foundation/service-topology-registry.d.ts +5 -3
  51. package/dist/runtime/foundation/service-topology-registry.js +9 -4
  52. package/dist/runtime/handlers/handler-instance-scope.js +1 -1
  53. package/dist/runtime/host/actor-packet-relay.js +7 -7
  54. package/dist/runtime/host/actor-placement-coordinator.d.ts +2 -1
  55. package/dist/runtime/host/actor-placement-coordinator.js +2 -1
  56. package/dist/runtime/host/actor-runtime-options-factory.d.ts +2 -1
  57. package/dist/runtime/host/actor-runtime-options-factory.js +2 -1
  58. package/dist/runtime/host/application-job-queue.d.ts +11 -4
  59. package/dist/runtime/host/application-job-queue.js +66 -10
  60. package/dist/runtime/host/entry-actor-runtime.js +1 -1
  61. package/dist/runtime/host/index.d.ts +1 -1
  62. package/dist/runtime/host/index.js +18 -13
  63. package/dist/runtime/host/instance-activation-authority.d.ts +2 -1
  64. package/dist/runtime/host/instance-activation-authority.js +89 -25
  65. package/dist/runtime/host/service-relocation-host-runtime.js +2 -2
  66. package/dist/runtime/host/spot-address-transport.d.ts +1 -0
  67. package/dist/runtime/host/spot-address-transport.js +25 -12
  68. package/dist/runtime/host/spot-runtime-options-factory.js +2 -2
  69. package/dist/runtime/host/user-spot-creation-coordinator.d.ts +1 -0
  70. package/dist/runtime/host/user-spot-creation-coordinator.js +1 -0
  71. package/dist/runtime/locations/domain-store-contract.d.ts +3 -2
  72. package/dist/runtime/locations/in-memory-authority-store.d.ts +5 -2
  73. package/dist/runtime/locations/in-memory-authority-store.js +107 -14
  74. package/dist/runtime/locations/in-memory-location-store.d.ts +3 -3
  75. package/dist/runtime/locations/in-memory-location-store.js +31 -13
  76. package/dist/runtime/locations/internal-location-contracts.d.ts +8 -0
  77. package/dist/runtime/locations/location-store-repository.d.ts +4 -2
  78. package/dist/runtime/locations/location-store-repository.js +209 -33
  79. package/dist/runtime/locations/resolvers.d.ts +2 -1
  80. package/dist/runtime/locations/resolvers.js +10 -1
  81. package/dist/runtime/messaging/submission-result.d.ts +1 -1
  82. package/dist/runtime/messaging/submission-result.js +2 -2
  83. package/dist/runtime/spots/formal-remote-actor-admission-registry.d.ts +2 -0
  84. package/dist/runtime/spots/index.d.ts +4 -3
  85. package/dist/runtime/spots/index.js +14 -14
  86. package/dist/runtime/spots/spot-activation.d.ts +2 -1
  87. package/dist/runtime/spots/spot-activation.js +4 -4
  88. package/dist/runtime/spots/spot-actor-admission-coordinator.d.ts +2 -1
  89. package/dist/runtime/spots/spot-actor-admission-coordinator.js +11 -10
  90. package/dist/runtime/spots/spot-actor-packet-dispatch.d.ts +4 -1
  91. package/dist/runtime/spots/spot-actor-packet-dispatch.js +7 -5
  92. package/dist/runtime/spots/spot-actor-packet-drain.js +2 -0
  93. package/dist/runtime/spots/spot-actor-packet-relay-dispatch.js +1 -0
  94. package/dist/runtime/spots/spot-entry-activation.d.ts +1 -0
  95. package/dist/runtime/spots/spot-entry-activation.js +6 -1
  96. package/dist/runtime/spots/spot-node-runtime-manager.d.ts +3 -1
  97. package/dist/runtime/spots/spot-node-runtime-manager.js +10 -11
  98. package/dist/runtime/spots/spot-routing-internal.d.ts +6 -0
  99. package/dist/runtime/spots/spot-runtime-ports.d.ts +2 -1
  100. package/dist/runtime/spots/spot-serial-executor.d.ts +1 -0
  101. package/dist/runtime/spots/spot-serial-executor.js +10 -1
  102. package/dist/runtime/streams/stream-session-runtime.js +1 -1
  103. package/package.json +3 -3
  104. package/src/contracts/Configuration/Builders.ts +1 -2
  105. package/src/contracts/Configuration/Configs.ts +0 -6
  106. package/src/contracts/Configuration/RegistrationBuilders.ts +8 -12
  107. package/src/contracts/Configuration/RegistrationTypes.ts +1 -6
  108. package/src/contracts/Configuration/RegistrationValidators.ts +9 -10
  109. package/src/contracts/Configuration/index.ts +1 -6
  110. package/src/internal.ts +1 -0
  111. package/src/runtime/actors/actor-handoff.ts +13 -4
  112. package/src/runtime/actors/actor-runtime-contracts.ts +4 -0
  113. package/src/runtime/actors/index.ts +77 -42
  114. package/src/runtime/application-jobs/application-ingress-record-owner.ts +12 -2
  115. package/src/runtime/application-jobs/application-job-queue-scope.ts +6 -1
  116. package/src/runtime/application-jobs/contracts.ts +14 -1
  117. package/src/runtime/backend/contracts/index.ts +10 -18
  118. package/src/runtime/backend/mesh-completion-table.ts +36 -19
  119. package/src/runtime/backend/mesh-dispatch-pump.ts +19 -22
  120. package/src/runtime/backend/node/node-backend-adapter-factory.ts +12 -5
  121. package/src/runtime/backend/node/node-backend-adapter-support.ts +31 -29
  122. package/src/runtime/backend/node/node-mesh-backend-adapter.ts +3 -10
  123. package/src/runtime/backend/node/node-raw-binding-port.ts +19 -10
  124. package/src/runtime/backend/node/node-raw-mesh-backend.ts +81 -111
  125. package/src/runtime/backend/node/node-socket-backend-adapter.ts +12 -8
  126. package/src/runtime/backend/raw-binding-port.ts +12 -2
  127. package/src/runtime/channels/channel-receive-loops.ts +3 -3
  128. package/src/runtime/channels/channel-runtime-lifecycle.ts +7 -1
  129. package/src/runtime/channels/channel-socket-registry.ts +84 -130
  130. package/src/runtime/diagnostics/message-flow.ts +1 -1
  131. package/src/runtime/foundation/raw-service-mesh-runtime.ts +268 -70
  132. package/src/runtime/foundation/service-liveness-registry.ts +68 -59
  133. package/src/runtime/foundation/service-mailbox.ts +7 -1
  134. package/src/runtime/foundation/service-stateful-runtime.ts +109 -77
  135. package/src/runtime/foundation/service-stateful-wire-codec.ts +55 -79
  136. package/src/runtime/foundation/service-topology-registry.ts +13 -7
  137. package/src/runtime/handlers/handler-instance-scope.ts +2 -1
  138. package/src/runtime/host/actor-packet-relay.ts +7 -0
  139. package/src/runtime/host/actor-placement-coordinator.ts +8 -2
  140. package/src/runtime/host/actor-runtime-options-factory.ts +7 -0
  141. package/src/runtime/host/application-job-queue.ts +77 -10
  142. package/src/runtime/host/entry-actor-runtime.ts +1 -0
  143. package/src/runtime/host/index.ts +30 -7
  144. package/src/runtime/host/instance-activation-authority.ts +132 -27
  145. package/src/runtime/host/service-relocation-host-runtime.ts +2 -0
  146. package/src/runtime/host/spot-address-transport.ts +45 -22
  147. package/src/runtime/host/spot-runtime-options-factory.ts +2 -0
  148. package/src/runtime/host/user-spot-creation-coordinator.ts +8 -0
  149. package/src/runtime/locations/domain-store-contract.ts +6 -2
  150. package/src/runtime/locations/in-memory-authority-store.ts +153 -12
  151. package/src/runtime/locations/in-memory-location-store.ts +39 -13
  152. package/src/runtime/locations/internal-location-contracts.ts +10 -0
  153. package/src/runtime/locations/location-store-repository.ts +295 -36
  154. package/src/runtime/locations/resolvers.ts +25 -2
  155. package/src/runtime/messaging/submission-result.ts +2 -2
  156. package/src/runtime/spots/formal-remote-actor-admission-registry.ts +2 -0
  157. package/src/runtime/spots/index.ts +16 -0
  158. package/src/runtime/spots/spot-activation.ts +5 -0
  159. package/src/runtime/spots/spot-actor-admission-coordinator.ts +13 -0
  160. package/src/runtime/spots/spot-actor-packet-dispatch.ts +10 -0
  161. package/src/runtime/spots/spot-actor-packet-drain.ts +2 -0
  162. package/src/runtime/spots/spot-actor-packet-relay-dispatch.ts +1 -0
  163. package/src/runtime/spots/spot-entry-activation.ts +7 -0
  164. package/src/runtime/spots/spot-node-runtime-manager.ts +14 -12
  165. package/src/runtime/spots/spot-routing-internal.ts +14 -0
  166. package/src/runtime/spots/spot-runtime-ports.ts +2 -0
  167. package/src/runtime/spots/spot-serial-executor.ts +10 -4
  168. package/src/runtime/streams/stream-session-runtime.ts +1 -1
@@ -2,10 +2,13 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ZLinkLocationStoreRepository = void 0;
4
4
  const service_relocation_runtime_1 = require("../foundation/service-relocation-runtime");
5
+ const service_authority_payload_codec_1 = require("../foundation/service-authority-payload-codec");
6
+ const actor_authority_payload_codec_1 = require("../actors/actor-authority-payload-codec");
7
+ const contracts_1 = require("../../contracts");
5
8
  const stream_wire_1 = require("@zlink-systems/stream-wire");
6
9
  const node_crypto_1 = require("node:crypto");
7
10
  const Options_1 = require("../../contracts/Locations/Options");
8
- const contracts_1 = require("../../contracts");
11
+ const contracts_2 = require("../../contracts");
9
12
  const CoreTypes_1 = require("../../contracts/Common/CoreTypes");
10
13
  const InternalDefaults_1 = require("../../contracts/Configuration/InternalDefaults");
11
14
  const RegistrationBuilderPolicy_1 = require("../../contracts/Configuration/RegistrationBuilderPolicy");
@@ -215,9 +218,27 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
215
218
  payload: Buffer.from(mutation.payload)
216
219
  }
217
220
  };
221
+ const actor = mutation.kind !== 'delete' && record.snapshot.allocation.objectKind === 'actor'
222
+ ? (0, actor_authority_payload_codec_1.decodeActorAuthorityPayload)((0, service_relocation_runtime_1.serviceRelocationAuthorityApplicationPayload)(mutation.payload))
223
+ : undefined;
224
+ const previousActor = actor === undefined
225
+ ? undefined
226
+ : (0, actor_authority_payload_codec_1.decodeActorAuthorityPayload)((0, service_relocation_runtime_1.serviceRelocationAuthorityApplicationPayload)(record.snapshot.payload));
227
+ const membershipConditions = actor?.currentSpotKind === contracts_1.ZLinkSpotKind.User &&
228
+ (previousActor?.currentSpotKind !== contracts_1.ZLinkSpotKind.User ||
229
+ previousActor.currentSpotId !== actor.currentSpotId ||
230
+ previousActor.currentSpotGeneration !== actor.currentSpotGeneration)
231
+ ? await this.userSpotMembershipConditions(actor.currentSpotId, actor.currentSpotGeneration, signal, {
232
+ ownerId: record.snapshot.ownerId,
233
+ leaseGeneration: record.snapshot.ownerLeaseGeneration
234
+ })
235
+ : [];
236
+ if (membershipConditions === undefined)
237
+ return { kind: 'conflict', current: snapshot };
218
238
  const result = await this.provider.write({
219
239
  conditions: [
220
240
  { kind: 'version', key: rowKey, expected: current.value.version },
241
+ ...membershipConditions,
221
242
  ...(mutation.kind === 'restore'
222
243
  ? []
223
244
  : [
@@ -654,7 +675,7 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
654
675
  sha256Hex(membership) !== entry.membershipMutationSha256) {
655
676
  throw new Error('Aggregate participant staging checksum does not match inventory.');
656
677
  }
657
- authorityRows.push({ key: rowKeyForParticipant, current, record, entry });
678
+ authorityRows.push({ key: rowKeyForParticipant, current, record, entry, payload });
658
679
  }
659
680
  const targetDescriptorKey = meshKey(aggregate.targetDescriptor.meshName, aggregate.targetDescriptor.rid);
660
681
  const targetLeaseKey = ownerKey(aggregate.targetOwner.ownerId);
@@ -717,11 +738,34 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
717
738
  bytes: encodeJson(capacity)
718
739
  });
719
740
  }
741
+ const membershipConditions = [];
742
+ for (const row of authorityRows) {
743
+ if (row.record.snapshot.allocation.objectKind !== 'actor')
744
+ continue;
745
+ const actor = (0, actor_authority_payload_codec_1.decodeActorAuthorityPayload)((0, service_relocation_runtime_1.serviceRelocationAuthorityApplicationPayload)(row.payload));
746
+ if (actor?.currentSpotKind !== contracts_1.ZLinkSpotKind.User)
747
+ continue;
748
+ const spotKey = (0, authority_key_codec_1.encodeAuthorityKey)('user_spot', actor.currentSpotId);
749
+ const participantSpot = authorityRows.find((candidate) => candidate.entry.authorityKey === spotKey.value);
750
+ if (participantSpot !== undefined) {
751
+ if (participantSpot.record.snapshot.allocation.objectKind !== 'user_spot' ||
752
+ participantSpot.record.snapshot.objectGeneration !== actor.currentSpotGeneration)
753
+ return { kind: 'stale' };
754
+ continue;
755
+ }
756
+ if (membershipConditions.some((condition) => condition.key.value === authorityKey(spotKey.value).value))
757
+ continue;
758
+ const conditions = await this.userSpotMembershipConditions(actor.currentSpotId, actor.currentSpotGeneration, signal, aggregate.targetOwner);
759
+ if (conditions === undefined)
760
+ return { kind: 'stale' };
761
+ membershipConditions.push(...conditions.filter((condition) => !membershipConditions.some((existing) => existing.key.value === condition.key.value)));
762
+ }
720
763
  const published = await this.provider.write({
721
764
  conditions: [
722
765
  { kind: 'version', key: rowKey, expected: aggregateRead.value.version },
723
766
  versionCondition(targetDescriptorKey, descriptorRead),
724
767
  leaseValueCondition(targetLeaseKey, aggregate.targetOwner),
768
+ ...membershipConditions,
725
769
  ...[...capacityReads.entries()].map(([value, read]) => ({
726
770
  kind: 'version',
727
771
  key: capacityKeys.get(value),
@@ -814,18 +858,21 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
814
858
  return { kind: 'aborted' };
815
859
  }
816
860
  }
817
- async releaseEndedReservation(key, expectedStoreVersion, signal) {
861
+ async releaseEndedReservation(key, expectedStoreVersion, signal, request) {
862
+ return ((await this.tryReleaseEndedReservation(key, expectedStoreVersion, signal, request)) ===
863
+ 'reclaimed');
864
+ }
865
+ async tryReleaseEndedReservation(key, expectedStoreVersion, signal, request) {
818
866
  const rowKey = authorityKey(key.value);
819
867
  const current = await this.provider.read(rowKey, signal);
820
868
  if (current.kind === 'missing' || current.value.version.value !== expectedStoreVersion)
821
- return false;
869
+ return 'conflict';
822
870
  const record = decodeAuthorityRecord(current.value.bytes);
823
871
  const snapshot = record.snapshot;
824
- if (snapshot.allocation.state !== 'reserved' ||
825
- snapshot.pendingCreation === undefined ||
826
- record.aggregate !== undefined ||
827
- hasRelocationAuthority(snapshot.payload))
828
- return false;
872
+ if (snapshot.allocation.state === 'active'
873
+ ? request === undefined
874
+ : snapshot.pendingCreation === undefined)
875
+ return 'notReclaimable';
829
876
  const leaseKey = ownerKey(snapshot.ownerId);
830
877
  const descriptorKey = meshKey(snapshot.allocation.descriptor.meshName, snapshot.allocation.descriptor.rid);
831
878
  const capacityRowKey = capacityKey(snapshot.allocation.descriptor.meshName, String(snapshot.allocation.descriptor.rid));
@@ -836,23 +883,95 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
836
883
  ]);
837
884
  if (lease.kind === 'found' && lease.value.expiresAt === undefined)
838
885
  throw new Error('Location Store owner lease record is invalid.');
839
- if (sameLiveOwner(lease, snapshot) &&
886
+ const ownerLive = sameLiveOwner(lease, snapshot);
887
+ if (snapshot.allocation.state === 'active') {
888
+ if (ownerLive)
889
+ return 'notReclaimable';
890
+ let unavailable = record.aggregate !== undefined || hasRelocationAuthority(snapshot.payload);
891
+ if (snapshot.allocation.objectKind !== 'actor') {
892
+ const spot = (0, service_authority_payload_codec_1.decodeServiceReadySpotAuthority)(snapshot.payload);
893
+ unavailable ||=
894
+ spot === undefined ||
895
+ spot.kind !== request?.key.kind ||
896
+ spot.stableType !== request.intent.stableType ||
897
+ spot.spotId !== request.key.globalId ||
898
+ spot.activationRecovery !== undefined;
899
+ if (spot?.kind === 'user_spot') {
900
+ // The snapshot starts only after the old owner's lease was found invalid.
901
+ for (const prefix of [`${PREFIX}actor:`, `${AUTHORITY_PREIMAGE_PREFIX}actor\0`]) {
902
+ membershipSnapshot: for (;;) {
903
+ let snapshotHasMember = false;
904
+ let cursor;
905
+ do {
906
+ const page = await this.provider.scan({ prefix, cursor, limit: Stores_1.ZLINK_PROVIDER_MAX_PAGE_SIZE }, signal);
907
+ if (page.kind === 'expired')
908
+ continue membershipSnapshot;
909
+ for (const item of page.value.items) {
910
+ if (prefix === `${PREFIX}actor:`) {
911
+ const actor = normalizeActor(decodeJson(item.value.bytes).descriptor);
912
+ snapshotHasMember ||=
913
+ actor.spotKind === contracts_1.ZLinkSpotKind.User &&
914
+ String(actor.spotId) === spot.spotId &&
915
+ actor.spotGeneration === snapshot.objectGeneration;
916
+ }
917
+ else {
918
+ const authority = decodeAuthorityRecord(item.value.bytes).snapshot;
919
+ if (authority.allocation.objectKind !== 'actor')
920
+ continue;
921
+ const actor = (0, actor_authority_payload_codec_1.decodeActorAuthorityPayload)((0, service_relocation_runtime_1.serviceRelocationAuthorityApplicationPayload)(authority.payload));
922
+ snapshotHasMember ||=
923
+ actor?.currentSpotKind === contracts_1.ZLinkSpotKind.User &&
924
+ actor.currentSpotId === spot.spotId &&
925
+ actor.currentSpotGeneration === snapshot.objectGeneration;
926
+ }
927
+ }
928
+ cursor = page.value.nextCursor;
929
+ } while (cursor !== undefined);
930
+ unavailable ||= snapshotHasMember;
931
+ break;
932
+ }
933
+ }
934
+ }
935
+ }
936
+ if (unavailable || request?.actorRelocationPolicy !== 'disabled')
937
+ throw new contracts_2.ZLinkFrameworkException(contracts_2.ZLinkFrameworkErrorKind.Unavailable, 'Object owner lease is unavailable.');
938
+ }
939
+ else if (ownerLive &&
840
940
  descriptor.kind === 'found' &&
841
941
  reviveMeshDescriptor(decodeCanonicalDescriptorRecord(descriptor.value.bytes).descriptor).lifecycleGeneration === snapshot.allocation.descriptorLifecycleGeneration)
842
- return false;
942
+ return 'notReclaimable';
943
+ if (snapshot.allocation.state !== 'active' &&
944
+ (record.aggregate !== undefined || hasRelocationAuthority(snapshot.payload)))
945
+ return 'notReclaimable';
843
946
  const mutations = [
844
947
  { kind: 'delete', key: rowKey }
845
948
  ];
846
949
  if (capacity.kind === 'found') {
847
950
  const stored = decodeJson(capacity.value.bytes);
848
- mutations.push({
849
- kind: 'put',
850
- key: capacityRowKey,
851
- bytes: encodeJson({
852
- active: stored.active,
853
- pending: subtractCapacity(stored.pending, snapshot.allocation.capacity)
854
- })
855
- });
951
+ try {
952
+ mutations.push({
953
+ kind: 'put',
954
+ key: capacityRowKey,
955
+ bytes: encodeJson({
956
+ active: snapshot.allocation.state === 'active'
957
+ ? subtractCapacity(stored.active, snapshot.allocation.capacity)
958
+ : stored.active,
959
+ pending: snapshot.allocation.state === 'reserved'
960
+ ? subtractCapacity(stored.pending, snapshot.allocation.capacity)
961
+ : stored.pending
962
+ })
963
+ });
964
+ }
965
+ catch (error) {
966
+ if (!(error instanceof contracts_2.ZLinkFrameworkException) ||
967
+ error.kind !== contracts_2.ZLinkFrameworkErrorKind.DataLost)
968
+ throw error;
969
+ const observed = await this.provider.read(rowKey, signal);
970
+ if (observed.kind === 'missing' ||
971
+ observed.value.version.value !== current.value.version.value)
972
+ return 'conflict';
973
+ throw error;
974
+ }
856
975
  }
857
976
  const result = await this.provider.write({
858
977
  conditions: [
@@ -863,11 +982,12 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
863
982
  ],
864
983
  mutations
865
984
  }, signal);
866
- return result.kind === 'applied';
985
+ return result.kind === 'applied' ? 'reclaimed' : 'conflict';
867
986
  }
868
987
  async reserve(request, signal, deadlineUnixMs) {
869
988
  const encodedAuthorityKey = (0, authority_key_codec_1.encodeAuthorityKey)(request.key.kind, request.key.globalId);
870
989
  const reservationId = (0, node_crypto_1.randomUUID)();
990
+ let reclaimVersion;
871
991
  for (;;) {
872
992
  throwIfOperationExpired(signal, deadlineUnixMs);
873
993
  const rowKey = authorityKey(encodedAuthorityKey.value);
@@ -882,19 +1002,24 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
882
1002
  snapshot.allocation.stableType !== request.intent.stableType) {
883
1003
  return { kind: 'typeMismatch', current: snapshot };
884
1004
  }
885
- if (snapshot.allocation.state === 'active') {
886
- return { kind: 'alreadyExists', current: snapshot };
887
- }
888
- if (!(await this.releaseEndedReservation(encodedAuthorityKey, current.value.version.value, signal)))
1005
+ if (reclaimVersion !== undefined && snapshot.storeVersion.value !== reclaimVersion)
889
1006
  return { kind: 'conflict', current: snapshot };
1007
+ const reclaim = await this.tryReleaseEndedReservation(encodedAuthorityKey, current.value.version.value, signal, request);
1008
+ if (reclaim === 'notReclaimable')
1009
+ return snapshot.allocation.state === 'active'
1010
+ ? { kind: 'alreadyExists', current: snapshot }
1011
+ : { kind: 'conflict', current: snapshot };
1012
+ reclaimVersion = reclaim === 'conflict' ? snapshot.storeVersion.value : undefined;
890
1013
  continue;
891
1014
  }
1015
+ if (reclaimVersion !== undefined)
1016
+ return { kind: 'conflict', current: { kind: 'missing', storeNow: current.storeNow } };
892
1017
  const [descriptorRead, leaseRead] = await Promise.all([
893
1018
  this.provider.read(descriptorKey, signal),
894
1019
  this.provider.read(leaseKey, signal)
895
1020
  ]);
896
1021
  const descriptor = liveTargetDescriptor(descriptorRead, leaseRead, request.target);
897
- if (descriptor === undefined || descriptor.state !== contracts_1.ZLinkFrameworkRuntimeState.Serving) {
1022
+ if (descriptor === undefined || descriptor.state !== contracts_2.ZLinkFrameworkRuntimeState.Serving) {
898
1023
  return { kind: 'conflict', current: { kind: 'missing', storeNow: current.storeNow } };
899
1024
  }
900
1025
  const [capacityRead, objectGenerationRead, authorityOwnerGenerationRead] = await Promise.all([
@@ -1171,6 +1296,14 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
1171
1296
  if (retentionMs <= 0) {
1172
1297
  throw new RangeError('Creation terminal expiry must be the live operation deadline plus five minutes.');
1173
1298
  }
1299
+ const actor = request.completion.kind === 'created'
1300
+ ? (0, actor_authority_payload_codec_1.decodeActorAuthorityPayload)((0, service_relocation_runtime_1.serviceRelocationAuthorityApplicationPayload)(request.completion.readyPayload))
1301
+ : undefined;
1302
+ const membershipConditions = actor?.currentSpotKind === contracts_1.ZLinkSpotKind.User
1303
+ ? await this.userSpotMembershipConditions(actor.currentSpotId, actor.currentSpotGeneration, signal, request.target.owner)
1304
+ : [];
1305
+ if (membershipConditions === undefined)
1306
+ return { kind: 'stale' };
1174
1307
  const mutations = request.completion.kind === 'created'
1175
1308
  ? [
1176
1309
  {
@@ -1210,6 +1343,7 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
1210
1343
  conditions: [
1211
1344
  { kind: 'version', key: rowKey, expected: current.value.version },
1212
1345
  { kind: 'missing', key: terminalRowKey },
1346
+ ...membershipConditions,
1213
1347
  versionCondition(descriptorKey, descriptorRead),
1214
1348
  leaseValueCondition(leaseKey, request.target.owner),
1215
1349
  conditionFor(capacityRowKey, capacityRead)
@@ -1472,7 +1606,7 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
1472
1606
  return this.listOwnedLocations(`${PREFIX}spot:`, page, normalizeSpot, (value) => matchesSpot(value, filter), signal);
1473
1607
  }
1474
1608
  async updateActor(location, intent, signal) {
1475
- return this.updateOwnedLocation(actorKey(location.meshName, location.actorId), normalizeActor(location), intent, signal);
1609
+ return this.updateOwnedLocation(actorKey(location.meshName, location.actorId), normalizeActor(location), intent, signal, location);
1476
1610
  }
1477
1611
  async removeActor(key, owner, signal) {
1478
1612
  return this.removeOwnedLocation(actorKey(key.meshName, key.actorId), owner, signal);
@@ -1841,7 +1975,37 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
1841
1975
  continuationToken: result.value.nextCursor?.value
1842
1976
  };
1843
1977
  }
1844
- async updateOwnedLocation(rowKey, location, intent, signal) {
1978
+ async userSpotMembershipConditions(spotId, objectGeneration, signal, conditionedOwner) {
1979
+ const key = authorityKey((0, authority_key_codec_1.encodeAuthorityKey)('user_spot', spotId).value);
1980
+ const read = await this.provider.read(key, signal);
1981
+ if (read.kind === 'missing')
1982
+ return undefined;
1983
+ const record = decodeAuthorityRecord(read.value.bytes);
1984
+ const snapshot = record.snapshot;
1985
+ if (record.aggregate !== undefined ||
1986
+ snapshot.allocation.objectKind !== 'user_spot' ||
1987
+ snapshot.allocation.state !== 'active' ||
1988
+ snapshot.objectGeneration !== objectGeneration ||
1989
+ (0, service_authority_payload_codec_1.decodeServiceReadySpotAuthority)(snapshot.payload)?.kind !== 'user_spot')
1990
+ return undefined;
1991
+ const leaseKey = ownerKey(snapshot.ownerId);
1992
+ const lease = await this.provider.read(leaseKey, signal);
1993
+ if (!sameLiveOwner(lease, snapshot))
1994
+ return undefined;
1995
+ return [
1996
+ { kind: 'version', key, expected: read.value.version },
1997
+ ...(conditionedOwner?.ownerId === snapshot.ownerId &&
1998
+ conditionedOwner.leaseGeneration === snapshot.ownerLeaseGeneration
1999
+ ? []
2000
+ : [
2001
+ leaseValueCondition(leaseKey, {
2002
+ ownerId: snapshot.ownerId,
2003
+ leaseGeneration: snapshot.ownerLeaseGeneration
2004
+ })
2005
+ ])
2006
+ ];
2007
+ }
2008
+ async updateOwnedLocation(rowKey, location, intent, signal, membership) {
1845
2009
  const leaseKey = ownerKey(location.ownerId);
1846
2010
  const [lease, current] = await Promise.all([
1847
2011
  this.provider.read(leaseKey, signal),
@@ -1886,13 +2050,25 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
1886
2050
  else if (intent === 2) {
1887
2051
  return rejected(lease.value.storeNow);
1888
2052
  }
2053
+ const previousMembership = current.kind === 'found' && membership !== undefined
2054
+ ? decodeJson(current.value.bytes).descriptor
2055
+ : undefined;
2056
+ const membershipConditions = membership?.spotKind === contracts_1.ZLinkSpotKind.User &&
2057
+ (previousMembership?.spotKind !== contracts_1.ZLinkSpotKind.User ||
2058
+ String(previousMembership.spotId) !== String(membership.spotId) ||
2059
+ BigInt(previousMembership.spotGeneration) !== membership.spotGeneration)
2060
+ ? await this.userSpotMembershipConditions(String(membership.spotId), membership.spotGeneration, signal, { ownerId: location.ownerId, leaseGeneration: locationOwnerGeneration(location) })
2061
+ : [];
2062
+ if (membershipConditions === undefined)
2063
+ return rejected(lease.value.storeNow);
1889
2064
  const result = await this.provider.write({
1890
2065
  conditions: [
1891
2066
  leaseValueCondition(leaseKey, {
1892
2067
  ownerId: location.ownerId,
1893
2068
  leaseGeneration: locationOwnerGeneration(location)
1894
2069
  }),
1895
- rowCondition
2070
+ rowCondition,
2071
+ ...membershipConditions
1896
2072
  ],
1897
2073
  mutations: [
1898
2074
  {
@@ -2880,7 +3056,7 @@ function liveTargetDescriptor(descriptorRead, leaseRead, target) {
2880
3056
  descriptor.lifecycleGeneration === target.nodeLifecycleGeneration &&
2881
3057
  descriptor.ownerId === target.owner.ownerId &&
2882
3058
  descriptor.leaseGeneration === target.owner.leaseGeneration &&
2883
- descriptor.objectRole === contracts_1.ZLinkObjectRole.Server &&
3059
+ descriptor.objectRole === contracts_2.ZLinkObjectRole.Server &&
2884
3060
  lease.ownerId === target.owner.ownerId &&
2885
3061
  BigInt(lease.leaseGeneration) === target.owner.leaseGeneration &&
2886
3062
  leaseRead.value.expiresAt !== undefined &&
@@ -2941,7 +3117,7 @@ function adjustCapacity(usage, delta, direction) {
2941
3117
  const key = capacityTypeKey(delta.spotType);
2942
3118
  const next = (spotTypes[key] ?? 0) + direction * delta.spotType.count;
2943
3119
  if (next < 0)
2944
- throw new Error('Provider capacity counter underflow.');
3120
+ throw new contracts_2.ZLinkFrameworkException(contracts_2.ZLinkFrameworkErrorKind.DataLost, 'Provider capacity counter underflow.');
2945
3121
  if (next === 0)
2946
3122
  delete spotTypes[key];
2947
3123
  else
@@ -2950,7 +3126,7 @@ function adjustCapacity(usage, delta, direction) {
2950
3126
  const actors = usage.actors + direction * delta.actors;
2951
3127
  const spots = usage.spots + direction * delta.spots;
2952
3128
  if (actors < 0 || spots < 0)
2953
- throw new Error('Provider capacity counter underflow.');
3129
+ throw new contracts_2.ZLinkFrameworkException(contracts_2.ZLinkFrameworkErrorKind.DataLost, 'Provider capacity counter underflow.');
2954
3130
  return { actors, spots, spotTypes };
2955
3131
  }
2956
3132
  function capacityTypeKey(value) {
@@ -3275,10 +3451,10 @@ function throwIfOperationExpired(signal, deadlineUnixMs) {
3275
3451
  }
3276
3452
  // Store SPI §6: preserve caller failures and classify provider failures once.
3277
3453
  function locationStoreProviderFailure(error, signal) {
3278
- if (error instanceof contracts_1.ZLinkFrameworkException ||
3454
+ if (error instanceof contracts_2.ZLinkFrameworkException ||
3279
3455
  error instanceof TypeError ||
3280
3456
  error instanceof RangeError ||
3281
3457
  signal?.aborted === true)
3282
3458
  return error;
3283
- return new contracts_1.ZLinkFrameworkException(contracts_1.ZLinkFrameworkErrorKind.Unavailable, 'Location Store provider is unavailable.', error);
3459
+ return new contracts_2.ZLinkFrameworkException(contracts_2.ZLinkFrameworkErrorKind.Unavailable, 'Location Store provider is unavailable.', error);
3284
3460
  }
@@ -1,6 +1,6 @@
1
1
  import type { ActorRef, RoutingId, SpotId } from '../../contracts/Common';
2
2
  import { type SpotHandle, type ZLinkActorSpotHandleResolver, type ZLinkSpotHandleResolver, type ResolvedSpotHandle } from '../spots/spot-handle';
3
- import type { ZLinkSpotRouteResolver, ZLinkSpotRouteTarget } from '../spots/spot-routing-internal';
3
+ import type { ZLinkSpotRouteResolver, ZLinkSpotRouteTarget, ZLinkInstanceReactivationRoute } from '../spots/spot-routing-internal';
4
4
  import { ZLinkFrameworkRuntimeState, ZLinkLocationRole, type ZLinkActorLocation, type ZLinkActorLocationKey, type ZLinkLocationReadiness, type ZLinkLocationRuntimeQuery, type ZLinkPeerLocation, type ZLinkPeerLocationFilter, type ZLinkPeerLocationResolver, type ZLinkRouteLocation, type ZLinkRouteLocationKey, type ZLinkSpotLocation, type ZLinkSpotLocationKey } from './internal-location-contracts';
5
5
  import type { ZLinkActorLocationStore, ZLinkAuthorityStore, ZLinkMeshNodeLocationStore, ZLinkPeerLocationStore, ZLinkRouteLocationStore, ZLinkSpotLocationStore } from './internal-store-contracts';
6
6
  import { ZLinkOwnerLeaseTracker } from './lease-tracker';
@@ -135,6 +135,7 @@ export declare class ZLinkAuthoritySpotRouteResolver implements ZLinkSpotRouteRe
135
135
  private readonly routeEpochs;
136
136
  private readonly activeResolutions;
137
137
  constructor(store: ZLinkAuthorityStore, routerChannelIdForMesh: (meshName: string) => string, fallback?: ZLinkSpotRouteResolver | undefined, leaseTracker?: ZLinkOwnerLeaseTracker | undefined, routeCacheMaxAgeMs?: number, monotonicNowMs?: () => number, targetNodeStateResolver?: ((meshName: string, nodeRid: RoutingId, expectedLifecycleGeneration: bigint, signal?: AbortSignal) => Promise<ZLinkFrameworkRuntimeState | undefined>) | undefined);
138
+ resolve(spotId: RoutingId, signal: AbortSignal | undefined, instanceIntent: true): Promise<ZLinkSpotRouteTarget | ZLinkInstanceReactivationRoute>;
138
139
  resolve(spotId: RoutingId, signal?: AbortSignal): Promise<ZLinkSpotRouteTarget>;
139
140
  invalidate(spotId: RoutingId): void;
140
141
  private invalidateCore;
@@ -583,7 +583,7 @@ class ZLinkAuthoritySpotRouteResolver {
583
583
  this.monotonicNowMs = monotonicNowMs;
584
584
  this.targetNodeStateResolver = targetNodeStateResolver;
585
585
  }
586
- async resolve(spotId, signal) {
586
+ async resolve(spotId, signal, instanceIntent) {
587
587
  const key = String(spotId);
588
588
  const prepared = await this.lane.run(() => this.beginResolutionCore(key));
589
589
  try {
@@ -606,6 +606,15 @@ class ZLinkAuthoritySpotRouteResolver {
606
606
  leaseGeneration: current.ownerLeaseGeneration
607
607
  }, signal);
608
608
  if (remainingLeaseMs !== undefined && remainingLeaseMs <= 0) {
609
+ if (instanceIntent === true && ready?.kind === 'instance_spot') {
610
+ return {
611
+ kind: 'coldActivation',
612
+ spotId,
613
+ spotKind: Spots_1.ZLinkSpotKind.Instance,
614
+ meshName: ready.ownerMeshName,
615
+ stableType: ready.stableType
616
+ };
617
+ }
609
618
  throw new Errors_1.ZLinkFrameworkException(Errors_1.ZLinkFrameworkErrorKind.Unavailable, `SPOT '${spotId}' Ready authority owner lease is unavailable.`);
610
619
  }
611
620
  const target = {
@@ -10,7 +10,7 @@ export declare enum ZLinkSubmitStatus {
10
10
  export interface ZLinkSubmitResult {
11
11
  readonly status: ZLinkSubmitStatus;
12
12
  }
13
- /** Projects immediate refusal and pending admission failure from their Core phase. */
13
+ /** Projects typed submit failure; capacity refusal has no admission wait token. */
14
14
  export declare function submitToRequestResult(result: number, phase: 'submit' | 'completion'): number;
15
15
  export declare function classifySubmitResult(result: number, operation: string, phase?: 'submit' | 'completion'): ZLinkSubmitResult;
16
16
  export declare function requireOneWayCompletion(result: ZLinkSubmitResult, operation: string, notFoundKind?: ZLinkFrameworkInternalErrorKind): void;
@@ -19,13 +19,13 @@ var ZLinkSubmitStatus;
19
19
  ZLinkSubmitStatus["RouteNotConnected"] = "routeNotConnected";
20
20
  ZLinkSubmitStatus["Shutdown"] = "shutdown";
21
21
  })(ZLinkSubmitStatus || (exports.ZLinkSubmitStatus = ZLinkSubmitStatus = {}));
22
- /** Projects immediate refusal and pending admission failure from their Core phase. */
22
+ /** Projects typed submit failure; capacity refusal has no admission wait token. */
23
23
  function submitToRequestResult(result, phase) {
24
24
  switch (result) {
25
25
  case runtime_values_1.SubmitResult.Ok:
26
26
  return runtime_values_1.RequestResult.Ok;
27
27
  case runtime_values_1.SubmitResult.Backpressured:
28
- return phase === 'submit' ? runtime_values_1.RequestResult.NotConnected : runtime_values_1.RequestResult.TimedOut;
28
+ return runtime_values_1.RequestResult.NotConnected;
29
29
  case runtime_values_1.SubmitResult.NotConnected:
30
30
  return runtime_values_1.RequestResult.NotConnected;
31
31
  case runtime_values_1.SubmitResult.NotFound:
@@ -1,3 +1,4 @@
1
+ import type { ApplicationJobOrigin } from '../application-jobs/contracts';
1
2
  import type { ActorRef, RoutingId, ZLinkActor, ZLinkActorJoinOperationId } from '../../contracts';
2
3
  import type { ZLinkRemoteBoundSessionTarget } from '../actors/actor-runtime-state';
3
4
  import type { ZLinkDeferredJoinCompletion } from '../actors/deferred-join-completion';
@@ -10,6 +11,7 @@ import type { ZLinkActorRequestTerminal } from './spot-actor-packet-dispatch';
10
11
  * how long the underlying buffer stays valid.
11
12
  */
12
13
  export interface ZLinkParkedActorArrival {
14
+ readonly origin: ApplicationJobOrigin;
13
15
  readonly header: Buffer;
14
16
  readonly payload: Buffer;
15
17
  readonly returnResponse: boolean;
@@ -1,3 +1,4 @@
1
+ import type { ApplicationJobOrigin } from '../application-jobs/contracts';
1
2
  import type { ActorRef, RoutingId, Type, ZLinkMessageSerializer, ZLinkInstanceSpot, ZLinkActor, ZLinkChannelClient, ZLinkFanoutClient, ZLinkSpot, ZLinkSpotActorJoinResult, ZLinkSpotInfo, ZLinkSpotPublisherClient } from '../../contracts';
2
3
  import type { ZLinkProviderResolver } from '../../contracts/Common/ZLinkProviderResolver';
3
4
  import type { ZLinkSpotActorRequestHandlerRegistration, ZLinkSpotActorSendHandlerRegistration, ZLinkSpotPacketHandlerRegistration, ZLinkSpotSubscriptionHandlerRegistration, ZLinkSpotTimerHandlerRegistration } from '../../contracts/Configuration/RegistrationTypes';
@@ -55,7 +56,7 @@ export interface ZLinkSpotManagerOptions {
55
56
  readonly entrySpotCallbacks?: {
56
57
  onLeaveActor(actor: ZLinkActor, signal?: AbortSignal, actorRef?: ActorRef, membershipEpoch?: bigint): Promise<void>;
57
58
  };
58
- readonly dispatchEntryActorPacket?: (actorId: string, parts: readonly Message[], returnResponse?: boolean, remoteBoundSessionTarget?: ZLinkRemoteBoundSessionTarget, fallbackActorRef?: ActorRef, requestTerminal?: (response: unknown) => Promise<void> | void, messageFollowOrigin?: ZLinkMessageFollowOrigin) => Promise<unknown>;
59
+ readonly dispatchEntryActorPacket?: (origin: ApplicationJobOrigin, actorId: string, parts: readonly Message[], returnResponse?: boolean, remoteBoundSessionTarget?: ZLinkRemoteBoundSessionTarget, fallbackActorRef?: ActorRef, requestTerminal?: (response: unknown) => Promise<void> | void, messageFollowOrigin?: ZLinkMessageFollowOrigin) => Promise<unknown>;
59
60
  /**
60
61
  * Commits a stateful MeshNode Actor return to the Entry Spot after the
61
62
  * stateful reply has committed Core membership.
@@ -200,7 +201,7 @@ export declare class DefaultZLinkSpotManager {
200
201
  beginActorTransfer(spotId: RoutingId, actorId: string): Promise<void>;
201
202
  cancelActorTransfer(spotId: RoutingId, actorId: string): Promise<void>;
202
203
  notifyJoinedSpotActorDisconnected(spotId: RoutingId, actor: ZLinkActor, signal?: AbortSignal): Promise<boolean>;
203
- dispatchRoutedActorPacket(spotId: RoutingId, actorId: string, parts: readonly Message[], returnResponse?: boolean, remoteBoundSessionTarget?: ZLinkRemoteBoundSessionTarget, fallbackActorRef?: ActorRef): Promise<unknown>;
204
+ dispatchRoutedActorPacket(origin: ApplicationJobOrigin, spotId: RoutingId, actorId: string, parts: readonly Message[], returnResponse?: boolean, remoteBoundSessionTarget?: ZLinkRemoteBoundSessionTarget, fallbackActorRef?: ActorRef): Promise<unknown>;
204
205
  dispatchRoutedSpotSend(spotId: RoutingId, packetName: string | undefined, message: unknown, context: {
205
206
  readonly channelName: string;
206
207
  readonly contentType?: string;
@@ -220,7 +221,7 @@ export declare class DefaultZLinkSpotManager {
220
221
  dispatchMeshInstance(meshName: string, owner: ReadyRecord, record: ReceiveRecord): Promise<void>;
221
222
  private reportInstanceDispatchFailure;
222
223
  private traceInstanceMessage;
223
- dispatchMeshActor(meshName: string, owner: ReadyRecord, record: ReceiveRecord): Promise<void>;
224
+ dispatchMeshActor(origin: ApplicationJobOrigin, meshName: string, owner: ReadyRecord, record: ReceiveRecord): Promise<void>;
224
225
  dispatchMeshActorJoin(meshName: string, owner: ReadyRecord, record: ReceiveRecord): Promise<void>;
225
226
  private dispatchMeshActorJoinCore;
226
227
  dispatchMeshSpotControl(meshName: string, owner: ReadyRecord, record: ReceiveRecord): Promise<void>;
@@ -860,20 +860,20 @@ class DefaultZLinkSpotManager {
860
860
  async notifyJoinedSpotActorDisconnected(spotId, actor, signal) {
861
861
  return await this.actorMembership.notifyJoinedActorDisconnected(spotId, actor, signal);
862
862
  }
863
- dispatchRoutedActorPacket(spotId, actorId, parts, returnResponse = false, remoteBoundSessionTarget, fallbackActorRef) {
863
+ dispatchRoutedActorPacket(origin, spotId, actorId, parts, returnResponse = false, remoteBoundSessionTarget, fallbackActorRef) {
864
864
  const activation = this.activations.resolveUnique(spotId);
865
865
  if (activation === undefined) {
866
866
  throw new configuration_1.ZLinkConfigurationException(`Spot '${spotId}' is not active.`);
867
867
  }
868
- return this.dispatchActorPacket(activation, actorId, parts, returnResponse, remoteBoundSessionTarget, fallbackActorRef);
868
+ return this.dispatchActorPacket(origin, activation, actorId, parts, returnResponse, remoteBoundSessionTarget, fallbackActorRef);
869
869
  }
870
870
  /** @internal Replays a record already owned by the Actor handoff queue. */
871
- dispatchRoutedActorPacketDirect(spotId, actorId, parts, returnResponse = false, remoteBoundSessionTarget, fallbackActorRef) {
871
+ dispatchRoutedActorPacketDirect(origin, spotId, actorId, parts, returnResponse = false, remoteBoundSessionTarget, fallbackActorRef) {
872
872
  const activation = this.activations.resolveUnique(spotId);
873
873
  if (activation === undefined) {
874
874
  throw new configuration_1.ZLinkConfigurationException(`Spot '${spotId}' is not active.`);
875
875
  }
876
- return this.activationLifecycle.dispatchActorPacketDirect(activation, actorId, parts, returnResponse, remoteBoundSessionTarget, fallbackActorRef);
876
+ return this.activationLifecycle.dispatchActorPacketDirect(origin, activation, actorId, parts, returnResponse, remoteBoundSessionTarget, fallbackActorRef);
877
877
  }
878
878
  /** @internal Atomically restores one durable packet prefix to an Actor FIFO. */
879
879
  admitRoutedActorPacketPrefix(spotId, actorId, records) {
@@ -1071,7 +1071,7 @@ class DefaultZLinkSpotManager {
1071
1071
  errorReason
1072
1072
  });
1073
1073
  }
1074
- async dispatchMeshActor(meshName, owner, record) {
1074
+ async dispatchMeshActor(origin, meshName, owner, record) {
1075
1075
  const spotId = owner.spotId;
1076
1076
  const entrySpotId = this.options.entryNodeRidProvider?.() ?? this.options.entryNodeRid;
1077
1077
  const targetsEntrySpot = spotId === null || (entrySpotId !== undefined && spotId === entrySpotId);
@@ -1115,8 +1115,8 @@ class DefaultZLinkSpotManager {
1115
1115
  throw new Error(`Actor '${actor.actorId}' target transfer reconciliation is not complete.`);
1116
1116
  }
1117
1117
  const response = targetsEntrySpot
1118
- ? await this.options.dispatchEntryActorPacket?.(actor.actorId, record.parts, request, undefined, ownerActorRef, requestTerminal, record.messageFollowOrigin)
1119
- : await this.dispatchMeshActorPacket(meshName, spotId, actor.actorId, record.parts, request, ownerActorRef, requestTerminal, record.messageFollowOrigin);
1118
+ ? await this.options.dispatchEntryActorPacket?.(origin, actor.actorId, record.parts, request, undefined, ownerActorRef, requestTerminal, record.messageFollowOrigin)
1119
+ : await this.dispatchMeshActorPacket(origin, meshName, spotId, actor.actorId, record.parts, request, ownerActorRef, requestTerminal, record.messageFollowOrigin);
1120
1120
  if (targetsEntrySpot && this.options.dispatchEntryActorPacket === undefined) {
1121
1121
  throw new configuration_1.ZLinkConfigurationException('MeshNode Entry Spot Actor dispatch is not configured.');
1122
1122
  }
@@ -1631,7 +1631,7 @@ class DefaultZLinkSpotManager {
1631
1631
  if (this.options.dispatchEntryActorPacket === undefined) {
1632
1632
  throw new Error('Entry Spot saved handoff replay requires its Actor packet runtime.');
1633
1633
  }
1634
- return await this.options.dispatchEntryActorPacket(entryActor.context.actorId, parts, returnResponse, remoteBoundSessionTarget, fallbackActorRef);
1634
+ return await this.options.dispatchEntryActorPacket('remote', entryActor.context.actorId, parts, returnResponse, remoteBoundSessionTarget, fallbackActorRef);
1635
1635
  }, (index) => this.options.runtimeEventPublisher?.publish({
1636
1636
  sourceName: 'zlink.framework.actor-handoff',
1637
1637
  timestamp: new Date(),
@@ -1790,7 +1790,7 @@ class DefaultZLinkSpotManager {
1790
1790
  };
1791
1791
  const completeTargetReady = async () => {
1792
1792
  if (pendingTransfer !== undefined) {
1793
- const handoffResults = await (0, actor_handoff_1.replayActorHandoffBacklog)(pendingTransfer.handoffBacklog, (parts, returnResponse, remoteBoundSessionTarget, _fallbackActorRef) => this.dispatchActorPacket(activation, actor.context.actorId, parts, returnResponse, remoteBoundSessionTarget, undefined), (index) => this.options.runtimeEventPublisher?.publish({
1793
+ const handoffResults = await (0, actor_handoff_1.replayActorHandoffBacklog)(pendingTransfer.handoffBacklog, (parts, returnResponse, remoteBoundSessionTarget, _fallbackActorRef) => this.dispatchActorPacket('remote', activation, actor.context.actorId, parts, returnResponse, remoteBoundSessionTarget, undefined), (index) => this.options.runtimeEventPublisher?.publish({
1794
1794
  sourceName: 'zlink.framework.actor-handoff',
1795
1795
  timestamp: new Date(),
1796
1796
  marker: 'backlog_enqueued',
@@ -2033,8 +2033,8 @@ class DefaultZLinkSpotManager {
2033
2033
  throw new configuration_1.ZLinkConfigurationException('Spot type is not registered as a spot factory.');
2034
2034
  }
2035
2035
  }
2036
- async dispatchActorPacket(activation, actorId, parts, returnResponse = false, remoteBoundSessionTarget, fallbackActorRef, requestTerminal, messageFollowOrigin) {
2037
- return await this.activationLifecycle.dispatchActorPacket(activation, actorId, parts, returnResponse, remoteBoundSessionTarget, fallbackActorRef, requestTerminal, messageFollowOrigin);
2036
+ async dispatchActorPacket(origin, activation, actorId, parts, returnResponse = false, remoteBoundSessionTarget, fallbackActorRef, requestTerminal, messageFollowOrigin) {
2037
+ return await this.activationLifecycle.dispatchActorPacket(origin, activation, actorId, parts, returnResponse, remoteBoundSessionTarget, fallbackActorRef, requestTerminal, messageFollowOrigin);
2038
2038
  }
2039
2039
  /**
2040
2040
  * Spec 15 §4.2 relocation temporary queue: drains every arrival parked
@@ -2050,7 +2050,7 @@ class DefaultZLinkSpotManager {
2050
2050
  const drained = this.formalRemoteActorAdmissions.completeMigration(transferId);
2051
2051
  for (const arrival of drained) {
2052
2052
  try {
2053
- const response = await this.dispatchActorPacket(activation, actor.context.actorId, [runtime_message_1.ZLinkBufferMessage.from(arrival.header), runtime_message_1.ZLinkBufferMessage.from(arrival.payload)], arrival.returnResponse, arrival.remoteBoundSessionTarget, arrival.fallbackActorRef, arrival.requestTerminal);
2053
+ const response = await this.dispatchActorPacket(arrival.origin, activation, actor.context.actorId, [runtime_message_1.ZLinkBufferMessage.from(arrival.header), runtime_message_1.ZLinkBufferMessage.from(arrival.payload)], arrival.returnResponse, arrival.remoteBoundSessionTarget, arrival.fallbackActorRef, arrival.requestTerminal);
2054
2054
  arrival.resolve(response);
2055
2055
  }
2056
2056
  catch (error) {
@@ -2058,12 +2058,12 @@ class DefaultZLinkSpotManager {
2058
2058
  }
2059
2059
  }
2060
2060
  }
2061
- async dispatchMeshActorPacket(meshName, spotId, actorId, parts, returnResponse, fallbackActorRef, requestTerminal, messageFollowOrigin) {
2061
+ async dispatchMeshActorPacket(origin, meshName, spotId, actorId, parts, returnResponse, fallbackActorRef, requestTerminal, messageFollowOrigin) {
2062
2062
  const activation = this.activations.resolve(meshName, spotId);
2063
2063
  if (activation === undefined) {
2064
2064
  throw new configuration_1.ZLinkConfigurationException(`Spot '${String(spotId)}' is not active in mesh '${meshName}'.`);
2065
2065
  }
2066
- return await this.dispatchActorPacket(activation, actorId, parts, returnResponse, undefined, fallbackActorRef, requestTerminal, messageFollowOrigin);
2066
+ return await this.dispatchActorPacket(origin, activation, actorId, parts, returnResponse, undefined, fallbackActorRef, requestTerminal, messageFollowOrigin);
2067
2067
  }
2068
2068
  }
2069
2069
  exports.DefaultZLinkSpotManager = DefaultZLinkSpotManager;
@@ -1,3 +1,4 @@
1
+ import type { ApplicationJobOrigin } from '../application-jobs/contracts';
1
2
  import type { ActorRef, RoutingId, Type, ZLinkActor, ZLinkChannelClient, ZLinkFanoutClient, ZLinkMessageSerializer, ZLinkInstanceSpot, ZLinkSpot, ZLinkSpotPublisherClient } from '../../contracts';
2
3
  import type { ZLinkProviderResolver } from '../../contracts/Common/ZLinkProviderResolver';
3
4
  import type { ZLinkRuntimeAdmissionGate } from '../admission';
@@ -82,7 +83,7 @@ export declare class ZLinkSpotActivationLifecycle {
82
83
  /** Returns the OnClosing failure, which cleanup records and does not rethrow. */
83
84
  cleanupClosedActivation(activation: ZLinkSpotActivation, reason?: ZLinkSpotCloseReason, deadline?: Date): Promise<unknown>;
84
85
  cleanupFailedIncarnation(activation: ZLinkSpotActivation): Promise<void>;
85
- dispatchActorPacket(activation: ZLinkSpotActivation, actorId: string, parts: readonly Message[], returnResponse?: boolean, remoteBoundSessionTarget?: ZLinkRemoteBoundSessionTarget, fallbackActorRef?: ActorRef, requestTerminal?: (response: unknown) => Promise<void> | void, messageFollowOrigin?: ZLinkMessageFollowOrigin): Promise<unknown>;
86
+ dispatchActorPacket(origin: ApplicationJobOrigin, activation: ZLinkSpotActivation, actorId: string, parts: readonly Message[], returnResponse?: boolean, remoteBoundSessionTarget?: ZLinkRemoteBoundSessionTarget, fallbackActorRef?: ActorRef, requestTerminal?: (response: unknown) => Promise<void> | void, messageFollowOrigin?: ZLinkMessageFollowOrigin): Promise<unknown>;
86
87
  private runCreateLifecycle;
87
88
  private cleanupActivation;
88
89
  private runCleanup;