@serve.zone/interfaces 31.8.0 → 32.0.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 (215) hide show
  1. package/.smartconfig.json +1 -0
  2. package/changelog.md +512 -0
  3. package/dist_ts/00_commitinfo_data.js +3 -3
  4. package/dist_ts/appstore/types.d.ts +4 -6
  5. package/dist_ts/appstore/types.js +5 -5
  6. package/dist_ts/data/backup.d.ts +3 -26
  7. package/dist_ts/data/cluster.d.ts +36 -11
  8. package/dist_ts/data/cluster.js +33 -22
  9. package/dist_ts/data/clusteringress.d.ts +8 -0
  10. package/dist_ts/data/clusteringress.js +13 -8
  11. package/dist_ts/data/clusternode.d.ts +121 -74
  12. package/dist_ts/data/clusternode.js +109 -132
  13. package/dist_ts/data/clusterruntime.d.ts +39 -0
  14. package/dist_ts/data/clusterruntime.js +11 -0
  15. package/dist_ts/data/coremail.d.ts +3 -7
  16. package/dist_ts/data/coremail.js +2 -2
  17. package/dist_ts/data/coremail.runtime.d.ts +0 -1
  18. package/dist_ts/data/coremail.runtime.js +5 -22
  19. package/dist_ts/data/deploymentadoption.d.ts +0 -2
  20. package/dist_ts/data/deploymentadoption.js +40 -6
  21. package/dist_ts/data/deploymentoperation.js +16 -3
  22. package/dist_ts/data/deploymentpreflight.d.ts +0 -2
  23. package/dist_ts/data/deploymentpreflight.js +1 -1
  24. package/dist_ts/data/immutableimage.d.ts +38 -21
  25. package/dist_ts/data/immutableimage.js +45 -5
  26. package/dist_ts/data/index.d.ts +5 -1
  27. package/dist_ts/data/index.js +5 -1
  28. package/dist_ts/data/isolatedrestore.d.ts +139 -21
  29. package/dist_ts/data/isolatedrestore.golden.d.ts +0 -1
  30. package/dist_ts/data/isolatedrestore.golden.js +6 -9
  31. package/dist_ts/data/isolatedrestore.js +176 -40
  32. package/dist_ts/data/mail.d.ts +1 -1
  33. package/dist_ts/data/networkaddressplan.d.ts +78 -0
  34. package/dist_ts/data/networkaddressplan.js +114 -0
  35. package/dist_ts/data/networkauthority.d.ts +20 -22
  36. package/dist_ts/data/networkauthority.js +29 -43
  37. package/dist_ts/data/networkcredential.d.ts +10 -10
  38. package/dist_ts/data/networkcredential.js +16 -16
  39. package/dist_ts/data/networkdelivery.d.ts +18 -18
  40. package/dist_ts/data/networkdelivery.js +16 -16
  41. package/dist_ts/data/networklease.d.ts +18 -7
  42. package/dist_ts/data/networklease.js +29 -7
  43. package/dist_ts/data/networknode.d.ts +37 -0
  44. package/dist_ts/data/networknode.js +6 -0
  45. package/dist_ts/data/networkprojection.d.ts +59 -60
  46. package/dist_ts/data/networkprojection.js +53 -57
  47. package/dist_ts/data/networkprotection.d.ts +27 -28
  48. package/dist_ts/data/networkprotection.js +36 -36
  49. package/dist_ts/data/networkrouter.d.ts +11 -11
  50. package/dist_ts/data/networkrouter.js +1 -1
  51. package/dist_ts/data/networksigning.d.ts +16 -18
  52. package/dist_ts/data/networksigning.js +20 -21
  53. package/dist_ts/data/nodecredential.d.ts +4 -6
  54. package/dist_ts/data/nodeenrollment.d.ts +35 -40
  55. package/dist_ts/data/nodeenrollment.js +57 -72
  56. package/dist_ts/data/privatenetwork.d.ts +21 -24
  57. package/dist_ts/data/privatenetwork.js +39 -54
  58. package/dist_ts/data/runtimeassignment.d.ts +50 -34
  59. package/dist_ts/data/runtimeassignment.js +79 -45
  60. package/dist_ts/data/runtimeconfig.d.ts +21 -22
  61. package/dist_ts/data/runtimeconfig.js +37 -100
  62. package/dist_ts/data/runtimesession.d.ts +100 -62
  63. package/dist_ts/data/runtimesession.js +98 -79
  64. package/dist_ts/data/runtimeterminalreceipt.d.ts +28 -29
  65. package/dist_ts/data/runtimeterminalreceipt.js +42 -42
  66. package/dist_ts/data/secret.d.ts +18 -25
  67. package/dist_ts/data/secret.js +12 -52
  68. package/dist_ts/data/servicecredential.d.ts +14 -16
  69. package/dist_ts/data/servicecredential.js +17 -28
  70. package/dist_ts/data/serviceruntime.d.ts +128 -0
  71. package/dist_ts/data/serviceruntime.js +92 -0
  72. package/dist_ts/data/sparknodereport.d.ts +27 -14
  73. package/dist_ts/data/sparknodereport.js +35 -28
  74. package/dist_ts/data/webpush.d.ts +0 -1
  75. package/dist_ts/index.d.ts +2 -1
  76. package/dist_ts/index.js +3 -2
  77. package/dist_ts/platform/objectstorageretention.d.ts +21 -24
  78. package/dist_ts/platform/objectstorageretention.js +6 -18
  79. package/dist_ts/platform/storage.d.ts +1 -3
  80. package/dist_ts/platform/storagemigration.d.ts +0 -7
  81. package/dist_ts/platform/storagemigration.golden.d.ts +0 -1
  82. package/dist_ts/platform/storagemigration.golden.js +8 -12
  83. package/dist_ts/platform/storagemigration.js +6 -51
  84. package/dist_ts/platform/types.d.ts +2 -2
  85. package/dist_ts/private/canonicaljson.d.ts +9 -1
  86. package/dist_ts/private/canonicaljson.js +14 -2
  87. package/dist_ts/private/dataproperties.d.ts +62 -0
  88. package/dist_ts/private/dataproperties.js +117 -0
  89. package/dist_ts/private/networkcontract.d.ts +14 -10
  90. package/dist_ts/private/networkcontract.js +15 -1
  91. package/dist_ts/private/producercontract.d.ts +11 -0
  92. package/dist_ts/private/producercontract.js +21 -0
  93. package/dist_ts/private/releaseversion.d.ts +37 -0
  94. package/dist_ts/private/releaseversion.js +48 -0
  95. package/dist_ts/private/runtimepolicy.d.ts +31 -0
  96. package/dist_ts/private/runtimepolicy.js +90 -0
  97. package/dist_ts/private/tokenlist.d.ts +9 -0
  98. package/dist_ts/private/tokenlist.js +23 -0
  99. package/dist_ts/protocol.d.ts +137 -0
  100. package/dist_ts/protocol.js +255 -0
  101. package/dist_ts/requests/admin.d.ts +8 -8
  102. package/dist_ts/requests/backup.d.ts +102 -112
  103. package/dist_ts/requests/cluster.d.ts +47 -10
  104. package/dist_ts/requests/cluster.js +1 -1
  105. package/dist_ts/requests/clusteringress.d.ts +9 -0
  106. package/dist_ts/requests/clusteringress.js +1 -1
  107. package/dist_ts/requests/config.d.ts +3 -3
  108. package/dist_ts/requests/corestore.d.ts +0 -3
  109. package/dist_ts/requests/corestore.js +5 -9
  110. package/dist_ts/requests/network.d.ts +87 -31
  111. package/dist_ts/requests/node.d.ts +15 -28
  112. package/dist_ts/requests/pallet.d.ts +13 -13
  113. package/dist_ts/requests/runtimesession.d.ts +53 -41
  114. package/dist_ts/requests/secret.d.ts +4 -5
  115. package/dist_ts/requests/secret.js +1 -5
  116. package/dist_ts/requests/service.d.ts +60 -0
  117. package/dist_ts/runtime.corestore.d.ts +56 -74
  118. package/dist_ts/runtime.corestore.databaseexportpackage.d.ts +30 -36
  119. package/dist_ts/runtime.corestore.databaseexportpackage.golden.d.ts +11 -12
  120. package/dist_ts/runtime.corestore.databaseexportpackage.golden.js +54 -71
  121. package/dist_ts/runtime.corestore.databaseexportpackage.js +9 -25
  122. package/dist_ts/runtime.corestore.js +35 -135
  123. package/dist_ts/runtime.corestore.relay.js +2 -7
  124. package/dist_ts/runtime.d.ts +38 -48
  125. package/dist_ts/runtime.js +20 -77
  126. package/dist_ts/runtime.networkprojection.d.ts +4 -4
  127. package/dist_ts/runtime.networkprojection.js +18 -18
  128. package/dist_ts/runtime.workloadinit.d.ts +23 -24
  129. package/dist_ts/runtime.workloadinit.js +6 -13
  130. package/package.json +2 -2
  131. package/readme.md +540 -269
  132. package/ts/00_commitinfo_data.ts +3 -3
  133. package/ts/appstore/types.ts +4 -6
  134. package/ts/data/backup.ts +3 -38
  135. package/ts/data/cluster.ts +51 -34
  136. package/ts/data/clusteringress.ts +12 -12
  137. package/ts/data/clusternode.ts +204 -232
  138. package/ts/data/clusterruntime.ts +45 -0
  139. package/ts/data/coremail.runtime.ts +4 -21
  140. package/ts/data/coremail.ts +3 -7
  141. package/ts/data/deploymentadoption.ts +46 -4
  142. package/ts/data/deploymentoperation.ts +16 -1
  143. package/ts/data/deploymentpreflight.ts +0 -2
  144. package/ts/data/immutableimage.ts +71 -24
  145. package/ts/data/index.ts +5 -1
  146. package/ts/data/isolatedrestore.golden.ts +5 -9
  147. package/ts/data/isolatedrestore.ts +339 -54
  148. package/ts/data/mail.ts +1 -1
  149. package/ts/data/networkaddressplan.ts +175 -0
  150. package/ts/data/networkauthority.ts +45 -61
  151. package/ts/data/networkcredential.ts +24 -24
  152. package/ts/data/networkdelivery.ts +27 -27
  153. package/ts/data/networklease.ts +40 -13
  154. package/ts/data/networknode.ts +37 -0
  155. package/ts/data/networkprojection.ts +119 -124
  156. package/ts/data/networkprotection.ts +54 -55
  157. package/ts/data/networkrouter.ts +14 -14
  158. package/ts/data/networksigning.ts +29 -32
  159. package/ts/data/nodecredential.ts +4 -6
  160. package/ts/data/nodeenrollment.ts +96 -114
  161. package/ts/data/privatenetwork.ts +58 -74
  162. package/ts/data/runtimeassignment.ts +143 -94
  163. package/ts/data/runtimeconfig.ts +62 -122
  164. package/ts/data/runtimesession.ts +185 -138
  165. package/ts/data/runtimeterminalreceipt.ts +72 -73
  166. package/ts/data/secret.ts +28 -76
  167. package/ts/data/servicecredential.ts +33 -43
  168. package/ts/data/serviceruntime.ts +208 -0
  169. package/ts/data/sparknodereport.ts +48 -36
  170. package/ts/data/webpush.ts +0 -1
  171. package/ts/index.ts +2 -0
  172. package/ts/platform/objectstorageretention.ts +36 -55
  173. package/ts/platform/storage.ts +1 -3
  174. package/ts/platform/storagemigration.golden.ts +7 -11
  175. package/ts/platform/storagemigration.ts +5 -55
  176. package/ts/platform/types.ts +2 -2
  177. package/ts/private/canonicaljson.ts +13 -1
  178. package/ts/private/dataproperties.ts +139 -0
  179. package/ts/private/networkcontract.ts +23 -9
  180. package/ts/private/producercontract.ts +19 -0
  181. package/ts/private/releaseversion.ts +70 -0
  182. package/ts/private/runtimepolicy.ts +105 -0
  183. package/ts/private/tokenlist.ts +30 -0
  184. package/ts/protocol.ts +364 -0
  185. package/ts/requests/admin.ts +11 -11
  186. package/ts/requests/backup.ts +112 -117
  187. package/ts/requests/cluster.ts +58 -13
  188. package/ts/requests/clusteringress.ts +9 -0
  189. package/ts/requests/config.ts +3 -3
  190. package/ts/requests/corestore.ts +4 -16
  191. package/ts/requests/network.ts +90 -41
  192. package/ts/requests/node.ts +21 -38
  193. package/ts/requests/pallet.ts +17 -17
  194. package/ts/requests/runtimesession.ts +63 -51
  195. package/ts/requests/secret.ts +5 -10
  196. package/ts/requests/service.ts +81 -0
  197. package/ts/runtime.corestore.databaseexportpackage.golden.ts +77 -95
  198. package/ts/runtime.corestore.databaseexportpackage.ts +51 -73
  199. package/ts/runtime.corestore.relay.ts +1 -10
  200. package/ts/runtime.corestore.ts +118 -268
  201. package/ts/runtime.networkprojection.ts +30 -30
  202. package/ts/runtime.ts +83 -158
  203. package/ts/runtime.workloadinit.ts +36 -48
  204. package/dist_ts/runtime.cloudlylegacydeploymentsettlement.d.ts +0 -902
  205. package/dist_ts/runtime.cloudlylegacydeploymentsettlement.golden.d.ts +0 -35
  206. package/dist_ts/runtime.cloudlylegacydeploymentsettlement.golden.js +0 -315
  207. package/dist_ts/runtime.cloudlylegacydeploymentsettlement.js +0 -3315
  208. package/dist_ts/runtime.cloudlylegacydeploymentsettlement.offlineexport.d.ts +0 -291
  209. package/dist_ts/runtime.cloudlylegacydeploymentsettlement.offlineexport.golden.d.ts +0 -30
  210. package/dist_ts/runtime.cloudlylegacydeploymentsettlement.offlineexport.golden.js +0 -408
  211. package/dist_ts/runtime.cloudlylegacydeploymentsettlement.offlineexport.js +0 -1126
  212. package/ts/runtime.cloudlylegacydeploymentsettlement.golden.ts +0 -421
  213. package/ts/runtime.cloudlylegacydeploymentsettlement.offlineexport.golden.ts +0 -510
  214. package/ts/runtime.cloudlylegacydeploymentsettlement.offlineexport.ts +0 -2470
  215. package/ts/runtime.cloudlylegacydeploymentsettlement.ts +0 -6630
@@ -1,8 +1,11 @@
1
1
  import type { TSha256Digest, TImmutableContainerPlatform } from './immutableimage.js';
2
2
  import { buildDigestPinnedImageReference, isSha256Digest } from './immutableimage.js';
3
- import { canonicalizeStrictJson, createCanonicalJsonSha256Hex } from '../private/canonicaljson.js';
3
+ import {
4
+ canonicalizeStrictJson, compareWireTokens, createCanonicalJsonSha256Hex,
5
+ } from '../private/canonicaljson.js';
6
+ import { isCanonicalTokenList } from '../private/tokenlist.js';
4
7
 
5
- export interface IRuntimeControllerV1 {
8
+ export interface IRuntimeController {
6
9
  kind: 'cloudly' | 'onebox';
7
10
  id: string;
8
11
  /** Persisted authority incarnation; changing it requires explicit re-admission. */
@@ -10,33 +13,32 @@ export interface IRuntimeControllerV1 {
10
13
  }
11
14
 
12
15
  /** Content-bound reference, not a credential, mount path or permission grant. */
13
- export interface IRuntimeAuthorityReferenceV1 {
16
+ export interface IRuntimeAuthorityReference {
14
17
  id: string;
15
18
  generation: number;
16
19
  digest: TSha256Digest;
17
20
  }
18
21
 
19
- export interface IRuntimeAssignmentReferenceV1 {
22
+ export interface IRuntimeAssignmentReference {
20
23
  assignmentId: string;
21
24
  generation: number;
22
25
  digest: TSha256Digest;
23
26
  }
24
27
 
25
28
  /** Derived from authenticated transport and locally configured ownership. */
26
- export interface IRuntimeAssignmentScopeV1 {
27
- controller: IRuntimeControllerV1;
29
+ export interface IRuntimeAssignmentScope {
30
+ controller: IRuntimeController;
28
31
  organizationId: string;
29
32
  nodeId: string;
30
33
  runtimeNamespace: string;
31
34
  }
32
35
 
33
- export type TRuntimeAssignmentDispositionV1 =
36
+ export type TRuntimeAssignmentDisposition =
34
37
  | 'run'
35
38
  | 'stop-preserve'
36
39
  | 'remove-runtime-preserve-storage';
37
40
 
38
- export interface IRuntimeAssignmentV1 extends IRuntimeAssignmentScopeV1 {
39
- schemaVersion: 1;
41
+ export interface IRuntimeAssignment extends IRuntimeAssignmentScope {
40
42
  assignmentId: string;
41
43
  serviceId: string;
42
44
  /** Stable logical replica; independent of container IDs and execution attempts. */
@@ -48,8 +50,8 @@ export interface IRuntimeAssignmentV1 extends IRuntimeAssignmentScopeV1 {
48
50
  siteId: string | null;
49
51
  generation: number;
50
52
  /** Exact CAS predecessor; null only at generation 1. */
51
- previous: IRuntimeAssignmentReferenceV1 | null;
52
- disposition: TRuntimeAssignmentDispositionV1;
53
+ previous: IRuntimeAssignmentReference | null;
54
+ disposition: TRuntimeAssignmentDisposition;
53
55
  /** No automatic relocation or expiry-based claim of a stopped writer. */
54
56
  offlinePolicy: 'continue-node-bound';
55
57
  workload: {
@@ -58,24 +60,67 @@ export interface IRuntimeAssignmentV1 extends IRuntimeAssignmentScopeV1 {
58
60
  imageDigest: TSha256Digest;
59
61
  platform: TImmutableContainerPlatform;
60
62
  /** Immutable complete invocation/configuration owned by the controller. */
61
- config: IRuntimeAuthorityReferenceV1;
62
- network: IRuntimeAuthorityReferenceV1 | null;
63
- secrets: IRuntimeAuthorityReferenceV1 | null;
63
+ config: IRuntimeAuthorityReference;
64
+ network: IRuntimeAuthorityReference | null;
65
+ secrets: IRuntimeAuthorityReference | null;
64
66
  /** Sorted unique reference IDs. Empty means no persistent storage claims. */
65
- storage: IRuntimeAuthorityReferenceV1[];
67
+ storage: IRuntimeAuthorityReference[];
66
68
  };
67
69
  digest: TSha256Digest;
68
70
  }
69
71
 
70
- export type TRuntimeAssignmentDecisionV1 =
71
- | { status: 'accept' | 'replay'; assignment: IRuntimeAssignmentV1 }
72
+ /**
73
+ * What a node must be able to resolve before it may run a workload, named by the workload keys
74
+ * that carry it. One vocabulary, so a node, a controller and a producer all mean the same thing.
75
+ */
76
+ export const runtimeWorkloadAuthorities = ['network', 'secrets', 'storage'] as const;
77
+
78
+ export type TRuntimeWorkloadAuthority = (typeof runtimeWorkloadAuthorities)[number];
79
+
80
+ /** What each authority looks at on the workload; a record over the union, so none can be missed. */
81
+ const workloadAuthorityDemands: Readonly<Record<
82
+ TRuntimeWorkloadAuthority,
83
+ (workloadArg: IRuntimeAssignment['workload']) => boolean
84
+ >> = Object.freeze({
85
+ network: (workloadArg) => workloadArg.network !== null,
86
+ secrets: (workloadArg) => workloadArg.secrets !== null,
87
+ storage: (workloadArg) => workloadArg.storage.length > 0,
88
+ });
89
+
90
+ /**
91
+ * The authorities this workload cannot run without.
92
+ *
93
+ * Filtered out of the vocabulary and ordered by the canonical comparison, so the result is sorted
94
+ * and duplicate-free whatever order the vocabulary is declared in, and compares byte-equal against
95
+ * the list a node resolved. A controller calls this with a workload it read from an assignment on
96
+ * the wire, so one the demands cannot read is refused by this family's error rather than by a
97
+ * `TypeError` out of a member read.
98
+ */
99
+ export const requiredWorkloadAuthorities = (
100
+ workloadArg: IRuntimeAssignment['workload'],
101
+ ): TRuntimeWorkloadAuthority[] => {
102
+ if (!isExactRecord(workloadArg, workloadKeys) || !Array.isArray(workloadArg.storage)) {
103
+ fail(workloadSchemaMessage);
104
+ }
105
+ return runtimeWorkloadAuthorities
106
+ .filter((authorityArg) => workloadAuthorityDemands[authorityArg](workloadArg))
107
+ .sort(compareWireTokens);
108
+ };
109
+
110
+ /** True when a value is exactly a canonical authority list drawn from the authority vocabulary. */
111
+ export const isResolvedWorkloadAuthorities = (
112
+ valueArg: unknown,
113
+ ): valueArg is TRuntimeWorkloadAuthority[] =>
114
+ isCanonicalTokenList(valueArg, runtimeWorkloadAuthorities);
115
+
116
+ export type TRuntimeAssignmentDecision =
117
+ | { status: 'accept' | 'replay'; assignment: IRuntimeAssignment }
72
118
  | { status: 'reject'; reason: 'invalid' | 'scope-mismatch' | 'conflict' | 'stale'
73
119
  | 'predecessor-mismatch' | 'attempt-mismatch' | 'disposition-regression' };
74
120
 
75
121
  /** Value-free execution evidence. Receipt/acceptance alone never means ready. */
76
- export interface IRuntimeAssignmentObservationV1 {
77
- schemaVersion: 1;
78
- assignment: IRuntimeAssignmentReferenceV1;
122
+ export interface IRuntimeAssignmentObservation {
123
+ assignment: IRuntimeAssignmentReference;
79
124
  /** Authenticated reporter session; its authority is verified by the receiver. */
80
125
  reporterSessionId: string;
81
126
  /** Durable per-assignment counter; never resets when a reporter reconnects. */
@@ -91,9 +136,9 @@ export interface IRuntimeAssignmentObservationV1 {
91
136
  digest: TSha256Digest;
92
137
  }
93
138
 
94
- export const runtimeAssignmentV1Contract = Object.freeze({
95
- assignmentDigestDomain: 'serve.zone/runtime-assignment-v1',
96
- observationDigestDomain: 'serve.zone/runtime-assignment-observation-v1',
139
+ export const runtimeAssignmentContract = Object.freeze({
140
+ assignmentDigestDomain: 'serve.zone/runtime-assignment',
141
+ observationDigestDomain: 'serve.zone/runtime-assignment-observation',
97
142
  maximumStorageReferences: 64,
98
143
  omission: 'no-effect',
99
144
  removal: 'retain-assignment-tombstone-and-storage',
@@ -123,32 +168,37 @@ const isExactRecord = (
123
168
  });
124
169
  };
125
170
 
126
- const isController = (valueArg: unknown): valueArg is IRuntimeControllerV1 =>
171
+ const isController = (valueArg: unknown): valueArg is IRuntimeController =>
127
172
  isExactRecord(valueArg, ['kind', 'id', 'epoch'])
128
173
  && (valueArg.kind === 'cloudly' || valueArg.kind === 'onebox')
129
174
  && isIdentifier(valueArg.id) && isIdentifier(valueArg.epoch);
130
- const isAuthorityReference = (valueArg: unknown): valueArg is IRuntimeAuthorityReferenceV1 =>
175
+ const isAuthorityReference = (valueArg: unknown): valueArg is IRuntimeAuthorityReference =>
131
176
  isExactRecord(valueArg, ['id', 'generation', 'digest'])
132
177
  && isIdentifier(valueArg.id) && isPositiveInteger(valueArg.generation) && isDigest(valueArg.digest);
133
- const isAssignmentReference = (valueArg: unknown): valueArg is IRuntimeAssignmentReferenceV1 =>
178
+ const isAssignmentReference = (valueArg: unknown): valueArg is IRuntimeAssignmentReference =>
134
179
  isExactRecord(valueArg, ['assignmentId', 'generation', 'digest'])
135
180
  && isIdentifier(valueArg.assignmentId) && isPositiveInteger(valueArg.generation)
136
181
  && isDigest(valueArg.digest);
137
182
 
183
+ /** The workload's exact members, read by the authority vocabulary and by the snapshot alike. */
184
+ const workloadKeys = ['registryHost', 'repository', 'imageDigest', 'platform',
185
+ 'config', 'network', 'secrets', 'storage'] as const;
186
+ const workloadSchemaMessage = 'runtime assignment workload must use exact immutable references';
187
+
138
188
  const assignmentKeys = [
139
- 'schemaVersion', 'controller', 'organizationId', 'nodeId', 'runtimeNamespace',
189
+ 'controller', 'organizationId', 'nodeId', 'runtimeNamespace',
140
190
  'assignmentId', 'serviceId', 'replicaId', 'attemptId', 'workerGroupId', 'siteId',
141
191
  'generation', 'previous', 'disposition', 'offlinePolicy', 'workload', 'digest',
142
192
  ] as const;
143
193
 
144
- const assertAssignment = (valueArg: unknown): IRuntimeAssignmentV1 => {
194
+ const assertAssignment = (valueArg: unknown): IRuntimeAssignment => {
145
195
  if (!isExactRecord(valueArg, assignmentKeys)
146
- || valueArg.schemaVersion !== 1 || !isController(valueArg.controller)
196
+ || !isController(valueArg.controller)
147
197
  || !isPositiveInteger(valueArg.generation) || !isDigest(valueArg.digest)
148
198
  || valueArg.offlinePolicy !== 'continue-node-bound'
149
199
  || !['run', 'stop-preserve', 'remove-runtime-preserve-storage'].includes(
150
200
  valueArg.disposition as string,
151
- )) fail('runtime assignment must use its exact v1 schema');
201
+ )) fail('runtime assignment must use its exact schema');
152
202
  for (const key of ['organizationId', 'nodeId', 'runtimeNamespace', 'assignmentId',
153
203
  'serviceId', 'replicaId', 'attemptId']) {
154
204
  if (!isIdentifier(valueArg[key])) fail(`runtime assignment ${key} must be a canonical identifier`);
@@ -163,8 +213,7 @@ const assertAssignment = (valueArg: unknown): IRuntimeAssignmentV1 => {
163
213
  fail('runtime assignment must bind its exact preceding generation');
164
214
  }
165
215
  const workload = valueArg.workload;
166
- if (!isExactRecord(workload, ['registryHost', 'repository', 'imageDigest', 'platform',
167
- 'config', 'network', 'secrets', 'storage'])
216
+ if (!isExactRecord(workload, workloadKeys)
168
217
  || typeof workload.registryHost !== 'string' || workload.registryHost.length > 253
169
218
  || typeof workload.repository !== 'string' || workload.repository.length > 255
170
219
  || !isDigest(workload.imageDigest)
@@ -173,8 +222,8 @@ const assertAssignment = (valueArg: unknown): IRuntimeAssignmentV1 => {
173
222
  || (workload.network !== null && !isAuthorityReference(workload.network))
174
223
  || (workload.secrets !== null && !isAuthorityReference(workload.secrets))
175
224
  || !Array.isArray(workload.storage)
176
- || workload.storage.length > runtimeAssignmentV1Contract.maximumStorageReferences) {
177
- fail('runtime assignment workload must use exact immutable references');
225
+ || workload.storage.length > runtimeAssignmentContract.maximumStorageReferences) {
226
+ fail(workloadSchemaMessage);
178
227
  }
179
228
  buildDigestPinnedImageReference(workload.registryHost as string,
180
229
  workload.repository as string, workload.imageDigest as TSha256Digest);
@@ -188,7 +237,7 @@ const assertAssignment = (valueArg: unknown): IRuntimeAssignmentV1 => {
188
237
  previousId = descriptor.value.id;
189
238
  }
190
239
  canonicalizeStrictJson(valueArg, fail);
191
- return valueArg as unknown as IRuntimeAssignmentV1;
240
+ return valueArg as unknown as IRuntimeAssignment;
192
241
  };
193
242
 
194
243
  const digestPayload = async (domainArg: string, valueArg: { digest: TSha256Digest }): Promise<TSha256Digest> => {
@@ -199,41 +248,41 @@ const digestPayload = async (domainArg: string, valueArg: { digest: TSha256Diges
199
248
  };
200
249
 
201
250
  /** Digest helpers validate structure and exclude only the object's own digest. */
202
- export const computeRuntimeAssignmentV1Digest = async (
203
- assignmentArg: IRuntimeAssignmentV1,
251
+ export const computeRuntimeAssignmentDigest = async (
252
+ assignmentArg: IRuntimeAssignment,
204
253
  ): Promise<TSha256Digest> => digestPayload(
205
- runtimeAssignmentV1Contract.assignmentDigestDomain, assertAssignment(assignmentArg),
254
+ runtimeAssignmentContract.assignmentDigestDomain, assertAssignment(assignmentArg),
206
255
  );
207
256
 
208
- export const validateRuntimeAssignmentV1 = async (valueArg: unknown): Promise<string[]> => {
257
+ export const validateRuntimeAssignment = async (valueArg: unknown): Promise<string[]> => {
209
258
  try {
210
- const assignment = snapshotRuntimeAssignmentV1(valueArg);
211
- return assignment.digest === await computeRuntimeAssignmentV1Digest(assignment)
259
+ const assignment = snapshotRuntimeAssignment(valueArg);
260
+ return assignment.digest === await computeRuntimeAssignmentDigest(assignment)
212
261
  ? [] : ['runtime assignment digest does not match'];
213
262
  } catch {
214
- return ['runtime assignment must use its exact canonical v1 schema'];
263
+ return ['runtime assignment must use its exact canonical schema'];
215
264
  }
216
265
  };
217
266
 
218
267
  /**
219
268
  * Synchronous exact-schema validation and detached canonical copy for persistence
220
269
  * assertions. This does not verify the digest, authenticate scope, or admit an
221
- * attempt. Use validateRuntimeAssignmentV1/evaluateRuntimeAssignmentV1 before
270
+ * attempt. Use validateRuntimeAssignment/evaluateRuntimeAssignment before
222
271
  * acceptance or effects.
223
272
  */
224
- export const snapshotRuntimeAssignmentV1 = (valueArg: unknown): IRuntimeAssignmentV1 =>
225
- JSON.parse(canonicalizeStrictJson(assertAssignment(valueArg), fail)) as IRuntimeAssignmentV1;
273
+ export const snapshotRuntimeAssignment = (valueArg: unknown): IRuntimeAssignment =>
274
+ JSON.parse(canonicalizeStrictJson(assertAssignment(valueArg), fail)) as IRuntimeAssignment;
226
275
 
227
- export const getRuntimeAssignmentV1Reference = (
228
- assignmentArg: IRuntimeAssignmentV1,
229
- ): IRuntimeAssignmentReferenceV1 => ({
276
+ export const getRuntimeAssignmentReference = (
277
+ assignmentArg: IRuntimeAssignment,
278
+ ): IRuntimeAssignmentReference => ({
230
279
  assignmentId: assignmentArg.assignmentId,
231
280
  generation: assignmentArg.generation,
232
281
  digest: assignmentArg.digest,
233
282
  });
234
283
 
235
284
  const canonical = (valueArg: unknown): string => canonicalizeStrictJson(valueArg, fail);
236
- const immutableAttempt = (assignmentArg: IRuntimeAssignmentV1): string => {
285
+ const immutableAttempt = (assignmentArg: IRuntimeAssignment): string => {
237
286
  const { generation, previous, disposition, digest, ...attempt } = assignmentArg;
238
287
  return canonical(attempt);
239
288
  };
@@ -245,27 +294,27 @@ const immutableAttempt = (assignmentArg: IRuntimeAssignmentV1): string => {
245
294
  * admission for every older writer. An omitted assignment causes no transition.
246
295
  * Persist only the returned detached snapshot, never the mutable input object.
247
296
  */
248
- export const evaluateRuntimeAssignmentV1 = async (
249
- incomingArg: IRuntimeAssignmentV1,
250
- acceptedArg: IRuntimeAssignmentV1 | null,
251
- trustedScopeArg: IRuntimeAssignmentScopeV1,
252
- ): Promise<TRuntimeAssignmentDecisionV1> => {
297
+ export const evaluateRuntimeAssignment = async (
298
+ incomingArg: IRuntimeAssignment,
299
+ acceptedArg: IRuntimeAssignment | null,
300
+ trustedScopeArg: IRuntimeAssignmentScope,
301
+ ): Promise<TRuntimeAssignmentDecision> => {
253
302
  try {
254
- incomingArg = snapshotRuntimeAssignmentV1(incomingArg);
255
- acceptedArg = acceptedArg === null ? null : snapshotRuntimeAssignmentV1(acceptedArg);
303
+ incomingArg = snapshotRuntimeAssignment(incomingArg);
304
+ acceptedArg = acceptedArg === null ? null : snapshotRuntimeAssignment(acceptedArg);
256
305
  if (!isExactRecord(trustedScopeArg, ['controller', 'organizationId', 'nodeId', 'runtimeNamespace'])
257
306
  || !isController(trustedScopeArg.controller)
258
307
  || !isIdentifier(trustedScopeArg.organizationId) || !isIdentifier(trustedScopeArg.nodeId)
259
308
  || !isIdentifier(trustedScopeArg.runtimeNamespace)) return { status: 'reject', reason: 'invalid' };
260
- trustedScopeArg = JSON.parse(canonical(trustedScopeArg)) as IRuntimeAssignmentScopeV1;
309
+ trustedScopeArg = JSON.parse(canonical(trustedScopeArg)) as IRuntimeAssignmentScope;
261
310
  } catch {
262
311
  return { status: 'reject', reason: 'invalid' };
263
312
  }
264
- if ((await validateRuntimeAssignmentV1(incomingArg)).length
265
- || (acceptedArg !== null && (await validateRuntimeAssignmentV1(acceptedArg)).length)) {
313
+ if ((await validateRuntimeAssignment(incomingArg)).length
314
+ || (acceptedArg !== null && (await validateRuntimeAssignment(acceptedArg)).length)) {
266
315
  return { status: 'reject', reason: 'invalid' };
267
316
  }
268
- const matchesScope = (assignmentArg: IRuntimeAssignmentV1): boolean =>
317
+ const matchesScope = (assignmentArg: IRuntimeAssignment): boolean =>
269
318
  assignmentArg.controller.kind === trustedScopeArg.controller.kind
270
319
  && assignmentArg.controller.id === trustedScopeArg.controller.id
271
320
  && assignmentArg.controller.epoch === trustedScopeArg.controller.epoch
@@ -289,13 +338,13 @@ export const evaluateRuntimeAssignmentV1 = async (
289
338
  return incomingArg.digest === acceptedArg.digest
290
339
  ? { status: 'replay', assignment: acceptedArg } : { status: 'reject', reason: 'conflict' };
291
340
  }
292
- if (canonical(incomingArg.previous) !== canonical(getRuntimeAssignmentV1Reference(acceptedArg))) {
341
+ if (canonical(incomingArg.previous) !== canonical(getRuntimeAssignmentReference(acceptedArg))) {
293
342
  return { status: 'reject', reason: 'predecessor-mismatch' };
294
343
  }
295
344
  if (immutableAttempt(incomingArg) !== immutableAttempt(acceptedArg)) {
296
345
  return { status: 'reject', reason: 'attempt-mismatch' };
297
346
  }
298
- const order: Record<TRuntimeAssignmentDispositionV1, number> = {
347
+ const order: Record<TRuntimeAssignmentDisposition, number> = {
299
348
  run: 0, 'stop-preserve': 1, 'remove-runtime-preserve-storage': 2,
300
349
  };
301
350
  if (order[incomingArg.disposition] !== order[acceptedArg.disposition] + 1) {
@@ -304,15 +353,15 @@ export const evaluateRuntimeAssignmentV1 = async (
304
353
  return { status: 'accept', assignment: incomingArg };
305
354
  };
306
355
 
307
- const assertObservation = (valueArg: unknown): IRuntimeAssignmentObservationV1 => {
308
- if (!isExactRecord(valueArg, ['schemaVersion', 'assignment', 'reporterSessionId',
356
+ const assertObservation = (valueArg: unknown): IRuntimeAssignmentObservation => {
357
+ if (!isExactRecord(valueArg, ['assignment', 'reporterSessionId',
309
358
  'sequence', 'observedAt', 'phase', 'ready', 'runtime', 'digest'])
310
- || valueArg.schemaVersion !== 1 || !isAssignmentReference(valueArg.assignment)
359
+ || !isAssignmentReference(valueArg.assignment)
311
360
  || !isIdentifier(valueArg.reporterSessionId) || !isPositiveInteger(valueArg.sequence)
312
361
  || !isPositiveInteger(valueArg.observedAt) || !isDigest(valueArg.digest)
313
362
  || typeof valueArg.ready !== 'boolean'
314
363
  || !['pending', 'running', 'stopped', 'removed', 'failed', 'unknown'].includes(valueArg.phase as string)) {
315
- fail('runtime observation must use its exact v1 schema');
364
+ fail('runtime observation must use its exact schema');
316
365
  }
317
366
  if (valueArg.runtime !== null && (!isExactRecord(valueArg.runtime, [
318
367
  'sandboxId', 'containerId', 'imageDigest',
@@ -324,13 +373,13 @@ const assertObservation = (valueArg: unknown): IRuntimeAssignmentObservationV1 =
324
373
  fail('runtime observation readiness and identity contradict its phase');
325
374
  }
326
375
  canonical(valueArg);
327
- return valueArg as unknown as IRuntimeAssignmentObservationV1;
376
+ return valueArg as unknown as IRuntimeAssignmentObservation;
328
377
  };
329
378
 
330
- export const computeRuntimeAssignmentObservationV1Digest = async (
331
- observationArg: IRuntimeAssignmentObservationV1,
379
+ export const computeRuntimeAssignmentObservationDigest = async (
380
+ observationArg: IRuntimeAssignmentObservation,
332
381
  ): Promise<TSha256Digest> => digestPayload(
333
- runtimeAssignmentV1Contract.observationDigestDomain, assertObservation(observationArg),
382
+ runtimeAssignmentContract.observationDigestDomain, assertObservation(observationArg),
334
383
  );
335
384
 
336
385
  /**
@@ -338,24 +387,24 @@ export const computeRuntimeAssignmentObservationV1Digest = async (
338
387
  * assignment and reporter authority still require the observation validator and
339
388
  * evaluator; a structurally valid observation is never a writer fence.
340
389
  */
341
- export const snapshotRuntimeAssignmentObservationV1 = (
390
+ export const snapshotRuntimeAssignmentObservation = (
342
391
  valueArg: unknown,
343
- ): IRuntimeAssignmentObservationV1 =>
344
- JSON.parse(canonical(assertObservation(valueArg))) as IRuntimeAssignmentObservationV1;
392
+ ): IRuntimeAssignmentObservation =>
393
+ JSON.parse(canonical(assertObservation(valueArg))) as IRuntimeAssignmentObservation;
345
394
 
346
395
  /** Checks exact assignment evidence; transport must separately bind reporter/session. */
347
- export const validateRuntimeAssignmentObservationV1 = async (
396
+ export const validateRuntimeAssignmentObservation = async (
348
397
  observationArg: unknown,
349
- assignmentArg: IRuntimeAssignmentV1,
398
+ assignmentArg: IRuntimeAssignment,
350
399
  ): Promise<string[]> => {
351
400
  try {
352
- const observation = snapshotRuntimeAssignmentObservationV1(observationArg);
353
- assignmentArg = snapshotRuntimeAssignmentV1(assignmentArg);
354
- if ((await validateRuntimeAssignmentV1(assignmentArg)).length) return ['invalid assignment'];
355
- if (canonical(observation.assignment) !== canonical(getRuntimeAssignmentV1Reference(assignmentArg))) {
401
+ const observation = snapshotRuntimeAssignmentObservation(observationArg);
402
+ assignmentArg = snapshotRuntimeAssignment(assignmentArg);
403
+ if ((await validateRuntimeAssignment(assignmentArg)).length) return ['invalid assignment'];
404
+ if (canonical(observation.assignment) !== canonical(getRuntimeAssignmentReference(assignmentArg))) {
356
405
  return ['runtime observation does not match the exact assignment'];
357
406
  }
358
- if (observation.digest !== await computeRuntimeAssignmentObservationV1Digest(observation)) {
407
+ if (observation.digest !== await computeRuntimeAssignmentObservationDigest(observation)) {
359
408
  return ['runtime observation digest does not match'];
360
409
  }
361
410
  if (observation.ready && (assignmentArg.disposition !== 'run'
@@ -364,12 +413,12 @@ export const validateRuntimeAssignmentObservationV1 = async (
364
413
  }
365
414
  return [];
366
415
  } catch {
367
- return ['runtime observation must use its exact canonical v1 schema'];
416
+ return ['runtime observation must use its exact canonical schema'];
368
417
  }
369
418
  };
370
419
 
371
- export type TRuntimeObservationDecisionV1 =
372
- | { status: 'accept' | 'replay'; observation: IRuntimeAssignmentObservationV1 }
420
+ export type TRuntimeObservationDecision =
421
+ | { status: 'accept' | 'replay'; observation: IRuntimeAssignmentObservation }
373
422
  | { status: 'reject'; reason: 'invalid' | 'session-mismatch' | 'stale' | 'conflict' | 'sequence-gap' };
374
423
 
375
424
  /**
@@ -380,23 +429,23 @@ export type TRuntimeObservationDecisionV1 =
380
429
  * receivers must process each revision's observations in order.
381
430
  * These observations are never sufficient authority to relocate a storage writer.
382
431
  */
383
- export const evaluateRuntimeAssignmentObservationV1 = async (
384
- incomingArg: IRuntimeAssignmentObservationV1,
385
- acceptedArg: IRuntimeAssignmentObservationV1 | null,
386
- assignmentArg: IRuntimeAssignmentV1,
432
+ export const evaluateRuntimeAssignmentObservation = async (
433
+ incomingArg: IRuntimeAssignmentObservation,
434
+ acceptedArg: IRuntimeAssignmentObservation | null,
435
+ assignmentArg: IRuntimeAssignment,
387
436
  trustedReporterSessionIdArg: string,
388
- ): Promise<TRuntimeObservationDecisionV1> => {
437
+ ): Promise<TRuntimeObservationDecision> => {
389
438
  try {
390
- incomingArg = snapshotRuntimeAssignmentObservationV1(incomingArg);
439
+ incomingArg = snapshotRuntimeAssignmentObservation(incomingArg);
391
440
  acceptedArg = acceptedArg === null ? null
392
- : snapshotRuntimeAssignmentObservationV1(acceptedArg);
393
- assignmentArg = snapshotRuntimeAssignmentV1(assignmentArg);
441
+ : snapshotRuntimeAssignmentObservation(acceptedArg);
442
+ assignmentArg = snapshotRuntimeAssignment(assignmentArg);
394
443
  if (!isIdentifier(trustedReporterSessionIdArg)
395
- || (await validateRuntimeAssignmentObservationV1(incomingArg, assignmentArg)).length
444
+ || (await validateRuntimeAssignmentObservation(incomingArg, assignmentArg)).length
396
445
  || (acceptedArg !== null && (
397
- acceptedArg.digest !== await computeRuntimeAssignmentObservationV1Digest(acceptedArg)
446
+ acceptedArg.digest !== await computeRuntimeAssignmentObservationDigest(acceptedArg)
398
447
  || acceptedArg.assignment.assignmentId !== assignmentArg.assignmentId
399
- || (canonical(acceptedArg.assignment) !== canonical(getRuntimeAssignmentV1Reference(assignmentArg))
448
+ || (canonical(acceptedArg.assignment) !== canonical(getRuntimeAssignmentReference(assignmentArg))
400
449
  && canonical(acceptedArg.assignment) !== canonical(assignmentArg.previous))
401
450
  ))) return { status: 'reject', reason: 'invalid' };
402
451
  if (incomingArg.reporterSessionId !== trustedReporterSessionIdArg) {