@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
@@ -0,0 +1,45 @@
1
+ import { captureNetwork, networkCounter, networkId, networkRecord, requireNetwork } from '../private/networkcontract.js';
2
+ import { isOneOf, producerSafe } from '../private/producercontract.js';
3
+
4
+ const clusterRuntimePhases = ['swarm', 'draining', 'switching', 'pallet'] as const;
5
+
6
+ /**
7
+ * Which runtime owns a cluster's workloads.
8
+ *
9
+ * `swarm` is Coreflow's; `draining` stops every service while its volumes stay; `switching` lets the
10
+ * cluster's nodes join the runtime network while nothing runs; `pallet` is Pallet's alone.
11
+ */
12
+ export type TClusterRuntimePhase = typeof clusterRuntimePhases[number];
13
+
14
+ /**
15
+ * The runtime phase of one cluster, stored beside the cluster document rather than inside it: a
16
+ * cluster update merges caller data, and no caller may move a phase with it.
17
+ */
18
+ export interface IClusterRuntime {
19
+ /** The cluster id. */
20
+ id: string;
21
+ phase: TClusterRuntimePhase;
22
+ /** Compare-and-swap counter; every phase write advances it by one. */
23
+ generation: number;
24
+ /** Unix milliseconds on Cloudly's clock. */
25
+ changedAt: number;
26
+ /** The administrator or producer that made the change. */
27
+ changedBy: string;
28
+ }
29
+
30
+ /**
31
+ * Why a cluster cannot leave `swarm` yet. Each blocker names the node or service it is about, so an
32
+ * administrator can act on it without a second query.
33
+ */
34
+ export type TClusterRuntimeBlocker =
35
+ | { code: 'relay-not-enabled' | 'relay-not-registered' | 'address-plan-missing' | 'vpn-unconfigured' }
36
+ | { code: 'node-without-pallet-credential' | 'node-arch-unsupported'; nodeId: string }
37
+ | { code: 'service-multi-cluster-scope' | 'service-authority-unsupported' | 'platform-binding-present'; serviceId: string };
38
+
39
+ /** Structural snapshot for exact persistence; which phase may follow which is the cutover's decision. */
40
+ export const snapshotClusterRuntime = (value: unknown): IClusterRuntime => producerSafe(() => {
41
+ const item = networkRecord(captureNetwork(value), ['id', 'phase', 'generation', 'changedAt', 'changedBy']);
42
+ requireNetwork(isOneOf(clusterRuntimePhases, item.phase));
43
+ return { id: networkId(item.id), phase: item.phase, generation: networkCounter(item.generation),
44
+ changedAt: networkCounter(item.changedAt), changedBy: networkId(item.changedBy) };
45
+ });
@@ -346,7 +346,7 @@ export const normalizeCoreMailCredentialVerifier = (
346
346
  /^\$argon2id\$v=19\$m=65536,t=3,p=1\$([A-Za-z0-9+/]+)\$([A-Za-z0-9+/]+)$/,
347
347
  );
348
348
  if (!match) {
349
- return fail(`${pathArg}.verificationHash must use the canonical argon2id-v1 PHC form`);
349
+ return fail(`${pathArg}.verificationHash must use the canonical argon2id PHC form`);
350
350
  }
351
351
  const [, saltBase64, digestBase64] = match;
352
352
  decodeCanonicalBase64(
@@ -1585,7 +1585,6 @@ const normalizeBinding = (
1585
1585
  record,
1586
1586
  pathArg,
1587
1587
  [
1588
- 'schemaVersion',
1589
1588
  'bindingId',
1590
1589
  'serviceId',
1591
1590
  'tenantId',
@@ -1599,9 +1598,6 @@ const normalizeBinding = (
1599
1598
  ],
1600
1599
  ['defaultSender'],
1601
1600
  );
1602
- if (record.schemaVersion !== 2) {
1603
- fail(`${pathArg}.schemaVersion must be 2`);
1604
- }
1605
1601
  const state = record.state === 'active'
1606
1602
  || record.state === 'draining'
1607
1603
  || record.state === 'disabled'
@@ -1628,7 +1624,6 @@ const normalizeBinding = (
1628
1624
  }
1629
1625
 
1630
1626
  const normalized: ICoreMailBindingDesiredState = {
1631
- schemaVersion: 2,
1632
1627
  bindingId: requireIdentifier(record.bindingId, `${pathArg}.bindingId`),
1633
1628
  serviceId: requireIdentifier(record.serviceId, `${pathArg}.serviceId`),
1634
1629
  tenantId: requireIdentifier(record.tenantId, `${pathArg}.tenantId`),
@@ -1771,12 +1766,9 @@ export const normalizeCoreMailDesiredState = (
1771
1766
  assertKeys(
1772
1767
  record,
1773
1768
  'desiredState',
1774
- ['schemaVersion', 'configEpoch', 'bindings', 'gateway', 'cursorKeys'],
1769
+ ['configEpoch', 'bindings', 'gateway', 'cursorKeys'],
1775
1770
  ['smtp'],
1776
1771
  );
1777
- if (record.schemaVersion !== 2) {
1778
- fail('desiredState.schemaVersion must be 2');
1779
- }
1780
1772
  const bindings = readArray(
1781
1773
  record.bindings,
1782
1774
  'desiredState.bindings',
@@ -1804,7 +1796,6 @@ export const normalizeCoreMailDesiredState = (
1804
1796
  compareStrings(leftArg.bindingId, rightArg.bindingId),
1805
1797
  );
1806
1798
  const normalized: ICoreMailDesiredState = {
1807
- schemaVersion: 2,
1808
1799
  configEpoch: requireSafeInteger(record.configEpoch, 'desiredState.configEpoch', 1),
1809
1800
  bindings,
1810
1801
  gateway: normalizeGateway(record.gateway, 'desiredState.gateway'),
@@ -1999,13 +1990,9 @@ export const normalizeCoreMailControlBootstrap = (
1999
1990
  assertKeys(
2000
1991
  record,
2001
1992
  'controlBootstrap',
2002
- ['schemaVersion', 'coreMailServiceId', 'credentials'],
1993
+ ['coreMailServiceId', 'credentials'],
2003
1994
  );
2004
- if (record.schemaVersion !== 1) {
2005
- fail('controlBootstrap.schemaVersion must be 1');
2006
- }
2007
1995
  return deepFreezeValue({
2008
- schemaVersion: 1,
2009
1996
  coreMailServiceId: requireIdentifier(
2010
1997
  record.coreMailServiceId,
2011
1998
  'controlBootstrap.coreMailServiceId',
@@ -2024,13 +2011,9 @@ export const normalizeCoreMailGatewayPeerDesiredState = (
2024
2011
  assertKeys(
2025
2012
  record,
2026
2013
  'gatewayPeer',
2027
- ['schemaVersion', 'coreMailServiceId', 'transferOrigin', 'credentials'],
2014
+ ['coreMailServiceId', 'transferOrigin', 'credentials'],
2028
2015
  );
2029
- if (record.schemaVersion !== 1) {
2030
- fail('gatewayPeer.schemaVersion must be 1');
2031
- }
2032
2016
  return deepFreezeValue({
2033
- schemaVersion: 1,
2034
2017
  coreMailServiceId: requireIdentifier(
2035
2018
  record.coreMailServiceId,
2036
2019
  'gatewayPeer.coreMailServiceId',
@@ -12,7 +12,7 @@ export type TCoreMailSha256 = `sha256:${string}`;
12
12
  export type TCoreMailCapability = 'outbound' | 'inbound';
13
13
  export type TCoreMailBindingState = 'active' | 'draining' | 'disabled';
14
14
  export type TCoreMailCredentialState = 'current' | 'retiring';
15
- export type TCoreMailCredentialVerifierFormat = 'argon2id-v1';
15
+ export type TCoreMailCredentialVerifierFormat = 'argon2id';
16
16
  export type TCoreMailPartKind = 'text' | 'html' | 'attachment';
17
17
  export type TCoreMailTransferMethod = 'PUT' | 'GET';
18
18
  export type TCoreMailSubmissionState =
@@ -195,7 +195,7 @@ export interface ICoreMailBindingCredentialVerifier {
195
195
  credentialId: string;
196
196
  version: number;
197
197
  state: TCoreMailCredentialState;
198
- /** Versioned verifier contract. CoreMail currently accepts only argon2id-v1. */
198
+ /** The verifier contract this hash follows. CoreMail accepts only argon2id. */
199
199
  format: TCoreMailCredentialVerifierFormat;
200
200
  /** Password-verifier string only. Plaintext credential material is never part of desired state. */
201
201
  verificationHash: string;
@@ -203,7 +203,6 @@ export interface ICoreMailBindingCredentialVerifier {
203
203
  }
204
204
 
205
205
  export interface ICoreMailBindingDesiredState {
206
- schemaVersion: 2;
207
206
  bindingId: string;
208
207
  serviceId: string;
209
208
  tenantId: string;
@@ -237,7 +236,6 @@ export interface ICoreMailGatewayDesiredState {
237
236
  * configuration; the matching plaintext is delivered only to Coreflow.
238
237
  */
239
238
  export interface ICoreMailControlBootstrap {
240
- schemaVersion: 1;
241
239
  coreMailServiceId: string;
242
240
  credentials: ICoreMailBindingCredentialVerifier[];
243
241
  }
@@ -247,7 +245,6 @@ export interface ICoreMailControlBootstrap {
247
245
  * transferOrigin is authoritative control-plane data, never peer supplied.
248
246
  */
249
247
  export interface ICoreMailGatewayPeerDesiredState {
250
- schemaVersion: 1;
251
248
  coreMailServiceId: string;
252
249
  transferOrigin: string;
253
250
  credentials: ICoreMailBindingCredentialVerifier[];
@@ -288,7 +285,6 @@ export interface ICoreMailSmtpDesiredState {
288
285
  }
289
286
 
290
287
  export interface ICoreMailDesiredState {
291
- schemaVersion: 2;
292
288
  configEpoch: number;
293
289
  bindings: ICoreMailBindingDesiredState[];
294
290
  gateway: ICoreMailGatewayDesiredState;
@@ -486,7 +482,7 @@ export const coreMailTransferProtocol = Object.freeze({
486
482
  });
487
483
 
488
484
  export const coreMailCredentialVerifierPolicy = Object.freeze({
489
- format: 'argon2id-v1' as const,
485
+ format: 'argon2id' as const,
490
486
  version: 19,
491
487
  memoryCost: 65_536,
492
488
  timeCost: 3,
@@ -12,12 +12,14 @@ import type {
12
12
  TSha256Digest,
13
13
  } from './immutableimage.js';
14
14
  import {
15
+ isCoreflowRuntimeCapabilityList,
15
16
  normalizeImmutableReleaseTag,
16
17
  normalizeSha256Digest,
17
18
  validateImageRolloutStatus,
18
19
  validateImmutableImageDeploymentPlan,
19
20
  } from './immutableimage.js';
20
21
  import type { IRegistryTarget } from './registry.js';
22
+ import { hasExactKeys } from '../private/dataproperties.js';
21
23
 
22
24
  export type TServiceDeploymentAdoptionDecision = 'GO' | 'NO-GO';
23
25
 
@@ -115,7 +117,6 @@ export interface IServiceDeploymentAdoptionRolloutResult {
115
117
  }
116
118
 
117
119
  interface IServiceDeploymentAdoptionReportBase {
118
- schemaVersion: 1;
119
120
  mutationPerformed: false;
120
121
  requestId: string;
121
122
  generatedAt: number;
@@ -202,7 +203,6 @@ export type TServiceDeploymentAdoptionRetentionPhase = 'prepare' | 'commit';
202
203
  * retained for the exact adoption plan without mutating the Docker service.
203
204
  */
204
205
  export interface IServiceDeploymentAdoptionRetentionAttestation {
205
- schemaVersion: 1;
206
206
  phase: TServiceDeploymentAdoptionRetentionPhase;
207
207
  retainedWithoutMutation: true;
208
208
  serviceId: string;
@@ -213,12 +213,26 @@ export interface IServiceDeploymentAdoptionRetentionAttestation {
213
213
  attestedAt: number;
214
214
  }
215
215
 
216
+ /** Every key a retention attestation carries; nothing else is admitted. */
217
+ const retentionAttestationKeys = [
218
+ 'phase',
219
+ 'retainedWithoutMutation',
220
+ 'serviceId',
221
+ 'operationId',
222
+ 'adoptionConfigurationDigest',
223
+ 'immutableReport',
224
+ 'deployments',
225
+ 'attestedAt',
226
+ ] as const;
227
+
216
228
  export const validateServiceDeploymentAdoptionRetentionAttestation = (
217
229
  attestationArg: unknown,
218
230
  ): string[] => {
219
231
  if (!isRecord(attestationArg)) return ['retention attestation must be an object'];
220
232
  const errors: string[] = [];
221
- if (attestationArg.schemaVersion !== 1) errors.push('retention attestation schemaVersion must be 1');
233
+ if (!hasExactKeys(attestationArg, retentionAttestationKeys)) {
234
+ errors.push('retention attestation must use its exact schema');
235
+ }
222
236
  if (attestationArg.phase !== 'prepare' && attestationArg.phase !== 'commit') {
223
237
  errors.push('retention attestation phase is invalid');
224
238
  }
@@ -237,6 +251,10 @@ export const validateServiceDeploymentAdoptionRetentionAttestation = (
237
251
  }
238
252
  if (!isRecord(attestationArg.immutableReport)) {
239
253
  errors.push('retention attestation requires an immutable report envelope');
254
+ } else if (!isCoreflowRuntimeCapabilityList(attestationArg.immutableReport.reporterCapabilities)) {
255
+ // The envelope states what the reporter can do; a list that is not canonical cannot be
256
+ // compared against the one its registration stated, so the attestation is refused here.
257
+ errors.push('retention attestation reporter capabilities must be a canonical capability list');
240
258
  }
241
259
  if (!Array.isArray(attestationArg.deployments) || attestationArg.deployments.length < 1) {
242
260
  errors.push('retention attestation requires at least one deployment');
@@ -500,10 +518,34 @@ export const validateServiceDeploymentAdoptionRolloutResult = (
500
518
  return errors;
501
519
  };
502
520
 
521
+ /** Every key an adoption report carries, whatever it decided. */
522
+ const reportKeys = [
523
+ 'mutationPerformed',
524
+ 'requestId',
525
+ 'generatedAt',
526
+ 'runtimeAttestation',
527
+ 'decision',
528
+ 'registry',
529
+ 'runtimeTasks',
530
+ 'blockers',
531
+ ] as const;
532
+
533
+ /** A GO report also states the scope it adopts into and the digest it adopted. */
534
+ const goReportKeys = [...reportKeys, 'service', 'targetScope', 'adoptionDigest'] as const;
535
+
536
+ /** A NO-GO report may have stopped before it read the service or resolved a scope. */
537
+ const noGoReportOptionalKeys = ['service', 'targetScope'] as const;
538
+
503
539
  export const validateServiceDeploymentAdoptionReport = (reportArg: unknown): string[] => {
504
540
  if (!isRecord(reportArg)) return ['adoption report must be an object'];
505
541
  const errors: string[] = [];
506
- if (reportArg.schemaVersion !== 1) errors.push('schemaVersion must be 1');
542
+ if (!hasExactKeys(
543
+ reportArg,
544
+ reportArg.decision === 'GO' ? goReportKeys : reportKeys,
545
+ reportArg.decision === 'GO' ? [] : noGoReportOptionalKeys,
546
+ )) {
547
+ errors.push('adoption report must use its exact decision schema');
548
+ }
507
549
  if (reportArg.mutationPerformed !== false) {
508
550
  errors.push('adoption preflight must be mutation-free');
509
551
  }
@@ -3,6 +3,7 @@ import type { IGatewayRouteDnsResult } from './gateway.js';
3
3
  import type { IImageRolloutStatus, IImmutableImageDeploymentPlan, TSha256Digest } from './immutableimage.js';
4
4
  import { normalizeImmutableReleaseTag, normalizeSha256Digest } from './immutableimage.js';
5
5
  import type { IRegistryTarget } from './registry.js';
6
+ import { hasExactKeys } from '../private/dataproperties.js';
6
7
  import { normalizeServiceAbsolutePath, validateServiceContainerArgs } from './service.js';
7
8
  import type { TServiceTargetPortRef } from './serviceports.js';
8
9
 
@@ -148,12 +149,26 @@ const validateStringArray = (
148
149
  && validatorArg(itemArg))
149
150
  && new Set(valueArg).size === valueArg.length;
150
151
 
152
+ /** Every key a proposed configuration carries; `containerArgs` is the one a template may omit. */
153
+ const proposedConfigurationKeys = [
154
+ 'declarationComplete',
155
+ 'projectName',
156
+ 'targetPlatforms',
157
+ 'publicDomains',
158
+ 'environmentVariableNames',
159
+ 'containerPorts',
160
+ 'volumeMounts',
161
+ 'requiredCapabilities',
162
+ ] as const;
163
+
151
164
  export const validateDeploymentProposedConfiguration = (
152
165
  configurationArg: unknown,
153
166
  ): string[] => {
154
167
  if (!isRecord(configurationArg)) return ['proposedConfiguration must be an object'];
155
168
  const errors: string[] = [];
156
- if (configurationArg.schemaVersion !== 1) errors.push('schemaVersion must be 1');
169
+ if (!hasExactKeys(configurationArg, proposedConfigurationKeys, ['containerArgs'])) {
170
+ errors.push('proposedConfiguration must use its exact schema');
171
+ }
157
172
  if (typeof configurationArg.declarationComplete !== 'boolean') {
158
173
  errors.push('declarationComplete must be boolean');
159
174
  }
@@ -142,7 +142,6 @@ export interface IDeploymentPreflightProposedVolumeMount {
142
142
  * cluster names through this contract.
143
143
  */
144
144
  export interface IDeploymentPreflightProposedConfiguration {
145
- schemaVersion: 1;
146
145
  declarationComplete: boolean;
147
146
  projectName: string;
148
147
  targetPlatforms: TImmutableContainerPlatform[];
@@ -194,7 +193,6 @@ export interface IDeploymentPreflightRequestData {
194
193
  }
195
194
 
196
195
  export interface IDeploymentPreflightReport {
197
- schemaVersion: 2;
198
196
  decision: TDeploymentPreflightDecision;
199
197
  mutationPerformed: false;
200
198
  generatedAt: number;
@@ -1,3 +1,5 @@
1
+ import { isCanonicalTokenList } from '../private/tokenlist.js';
2
+
1
3
  /** Canonical lower-case OCI sha256 digest. */
2
4
  export type TSha256Digest = `sha256:${string}`;
3
5
 
@@ -62,22 +64,70 @@ export type TImmutableImageRolloutStatus =
62
64
  | 'rolling-back'
63
65
  | 'rolled-back';
64
66
 
65
- export interface ICoreflowRuntimeCapabilities {
66
- immutableImageDeploymentVersion: 1;
67
- /** Coreflow can answer the versioned, node-scoped Corestore inventory probe. */
68
- corestoreInventoryVersion?: 1;
69
- /** Coreflow can consume exact, cluster-scoped resolved secret manifests. */
70
- secretManifestVersion: 2;
71
- sealedSecretMaterialVersion: 1;
72
- secretRecipientEnrollmentVersion: 1;
73
- workloadInitEnvironmentVersion: 1;
74
- /** Coreflow can submit replay-safe schema-v1 secret deployment reports. */
75
- secretDeploymentReportVersion?: 1;
76
- }
67
+ /**
68
+ * What a Coreflow build can do, named one capability at a time.
69
+ *
70
+ * A capability used to be advertised as the shape version the build spoke, which said two things
71
+ * at once: that the contract existed and which of its shapes was meant. The contract version is
72
+ * the interfaces version both peers exchange, so what is left to state is the capability itself.
73
+ */
74
+ export const coreflowRuntimeCapabilities = Object.freeze([
75
+ /** Answers the node-scoped Corestore inventory probe. */
76
+ 'corestore-inventory',
77
+ /** Deploys an image by its immutable digest and reports the rollout. */
78
+ 'immutable-image-deployment',
79
+ /** Opens sealed secret material addressed to its recipient key. */
80
+ 'sealed-secret-material',
81
+ /** Submits replay-safe secret deployment reports. */
82
+ 'secret-deployment-report',
83
+ /** Consumes exact, cluster-scoped resolved secret manifests. */
84
+ 'secret-manifest',
85
+ /** Enrolls as a secret recipient and answers the enrollment challenge. */
86
+ 'secret-recipient-enrollment',
87
+ /** Writes the WorkloadInit environment map and launches through the wrapper. */
88
+ 'workload-init-environment',
89
+ ] as const);
90
+
91
+ /** One capability a Coreflow build states in its secret-runtime registration. */
92
+ export type TCoreflowRuntimeCapability = typeof coreflowRuntimeCapabilities[number];
93
+
94
+ /**
95
+ * The capabilities a build may legitimately lack.
96
+ *
97
+ * `corestore-inventory` depends on the node's Corestore deployment rather than on the contracts
98
+ * the build was compiled against, so a build without one still registers.
99
+ */
100
+ export const optionalCoreflowRuntimeCapabilities = Object.freeze(
101
+ ['corestore-inventory'] as const satisfies readonly TCoreflowRuntimeCapability[],
102
+ );
103
+
104
+ /**
105
+ * The capabilities every build of this major has, so a registration that omits one is refused.
106
+ *
107
+ * Filtered out of the vocabulary rather than listed again: a capability added to the vocabulary is
108
+ * required from that moment unless it is named optional, which is the decision worth stating.
109
+ */
110
+ export const requiredCoreflowRuntimeCapabilities: readonly TCoreflowRuntimeCapability[] =
111
+ Object.freeze(coreflowRuntimeCapabilities.filter((capabilityArg) => (
112
+ !optionalCoreflowRuntimeCapabilities.some((optionalArg) => optionalArg === capabilityArg)
113
+ )));
114
+
115
+ /**
116
+ * True when a value is exactly a canonical capability list that carries every capability this
117
+ * major requires — the canonical-list rule plus this contract's own coverage clause.
118
+ */
119
+ export const isCoreflowRuntimeCapabilityList = (
120
+ valueArg: unknown,
121
+ ): valueArg is TCoreflowRuntimeCapability[] => (
122
+ isCanonicalTokenList(valueArg, coreflowRuntimeCapabilities)
123
+ && requiredCoreflowRuntimeCapabilities.every(
124
+ (capabilityArg) => valueArg.some((entryArg) => entryArg === capabilityArg),
125
+ )
126
+ );
77
127
 
78
128
  export type TImmutableContainerPlatform = 'linux/amd64' | 'linux/arm64';
79
129
 
80
- export interface IImmutableContainerInvocationPlatformEvidenceV1 {
130
+ export interface IImmutableContainerInvocationPlatformEvidence {
81
131
  platform: TImmutableContainerPlatform;
82
132
  platformManifestDigest: TSha256Digest;
83
133
  imageConfigDigest: TSha256Digest;
@@ -85,14 +135,13 @@ export interface IImmutableContainerInvocationPlatformEvidenceV1 {
85
135
  effectiveArgv: string[];
86
136
  }
87
137
 
88
- export interface IImmutableContainerInvocationV1 {
89
- schemaVersion: 1;
138
+ export interface IImmutableContainerInvocation {
90
139
  /** Sorted, unique, non-empty and limited to the authoritative platform union. */
91
140
  targetPlatforms: TImmutableContainerPlatform[];
92
141
  /** The one effective argv shared by every target platform. */
93
142
  argv: string[];
94
143
  /** Sorted exact one-to-one platform evidence. */
95
- evidence: IImmutableContainerInvocationPlatformEvidenceV1[];
144
+ evidence: IImmutableContainerInvocationPlatformEvidence[];
96
145
  digest: TSha256Digest;
97
146
  }
98
147
 
@@ -248,7 +297,7 @@ export interface IImmutableImageDeploymentPlan {
248
297
  digestPinnedImageReference: string;
249
298
  manifestMediaType: TOciManifestMediaType;
250
299
  /** Mandatory immutable command/config evidence for every target platform. */
251
- containerInvocation: IImmutableContainerInvocationV1;
300
+ containerInvocation: IImmutableContainerInvocation;
252
301
  createdAt: number;
253
302
  mode: TImmutableImageRolloutMode;
254
303
  /** Full pre-adoption service configuration fence, required only for adoption. */
@@ -313,7 +362,8 @@ export interface IImmutableRolloutReportEnvelope {
313
362
  rolloutGeneration: number;
314
363
  reporterSessionId: string;
315
364
  reportSequence: number;
316
- reporterCapabilities: ICoreflowRuntimeCapabilities;
365
+ /** Sorted and duplicate-free; every required capability of this major is present. */
366
+ reporterCapabilities: TCoreflowRuntimeCapability[];
317
367
  reporterNodeIds: string[];
318
368
  reporterNodeNames: string[];
319
369
  }
@@ -368,9 +418,8 @@ const validateImmutableArgv = (argvArg: unknown): argvArg is string[] => (
368
418
  );
369
419
 
370
420
  export const createImmutableContainerInvocationDigestInput = (
371
- invocationArg: Omit<IImmutableContainerInvocationV1, 'digest'> | IImmutableContainerInvocationV1,
421
+ invocationArg: Omit<IImmutableContainerInvocation, 'digest'> | IImmutableContainerInvocation,
372
422
  ): string => JSON.stringify({
373
- schemaVersion: invocationArg.schemaVersion,
374
423
  targetPlatforms: invocationArg.targetPlatforms,
375
424
  argv: invocationArg.argv,
376
425
  evidence: invocationArg.evidence.map((entryArg) => ({
@@ -382,7 +431,7 @@ export const createImmutableContainerInvocationDigestInput = (
382
431
  });
383
432
 
384
433
  export const computeImmutableContainerInvocationDigest = async (
385
- invocationArg: Omit<IImmutableContainerInvocationV1, 'digest'> | IImmutableContainerInvocationV1,
434
+ invocationArg: Omit<IImmutableContainerInvocation, 'digest'> | IImmutableContainerInvocation,
386
435
  ): Promise<TSha256Digest> => {
387
436
  const input = new TextEncoder().encode(createImmutableContainerInvocationDigestInput(invocationArg));
388
437
  const digest = new Uint8Array(await globalThis.crypto.subtle.digest(
@@ -395,7 +444,7 @@ export const computeImmutableContainerInvocationDigest = async (
395
444
  };
396
445
 
397
446
  export const verifyImmutableContainerInvocationDigest = async (
398
- invocationArg: IImmutableContainerInvocationV1,
447
+ invocationArg: IImmutableContainerInvocation,
399
448
  ): Promise<boolean> => invocationArg.digest
400
449
  === await computeImmutableContainerInvocationDigest(invocationArg);
401
450
 
@@ -411,12 +460,10 @@ export const validateImmutableContainerInvocation = (
411
460
  'argv',
412
461
  'digest',
413
462
  'evidence',
414
- 'schemaVersion',
415
463
  'targetPlatforms',
416
464
  ])) {
417
465
  errors.push('containerInvocation must use its exact schema');
418
466
  }
419
- if (invocation.schemaVersion !== 1) errors.push('containerInvocation schemaVersion must be 1');
420
467
  const platforms = Array.isArray(invocation.targetPlatforms)
421
468
  ? invocation.targetPlatforms
422
469
  : [];
package/ts/data/index.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from './cloudlyconfig.js';
2
2
  export * from './cluster.js';
3
+ export * from './clusterruntime.js';
3
4
  export * from './clusteringress.js';
4
5
  export * from './config.js';
5
6
  export * from './corestore.js';
@@ -24,12 +25,14 @@ export * from './isolatedrestore.golden.js';
24
25
  export * from './mail.js';
25
26
  export * from './nodecredential.js';
26
27
  export * from './nodeenrollment.js';
28
+ export * from './networkaddressplan.js';
27
29
  export * from './networkauthority.js';
28
30
  export * from './networkcredential.js';
29
31
  export * from './networkdelivery.js';
30
32
  export * from './networklease.js';
33
+ export * from './networknode.js';
31
34
  export * from './networkprojection.js';
32
- export type { IRuntimeNetworkRouterPacketGrantV1, IRuntimeNetworkRouterProjectionV1 } from './networkrouter.js';
35
+ export type { IRuntimeNetworkRouterPacketGrant, IRuntimeNetworkRouterProjection } from './networkrouter.js';
33
36
  export * from './networkprotection.js';
34
37
  export * from './networksigning.js';
35
38
  export * from './privatenetwork.js';
@@ -48,6 +51,7 @@ export * from './sparknodereport.js';
48
51
  export * from './service.js';
49
52
  export * from './servicecredential.js';
50
53
  export * from './serviceports.js';
54
+ export * from './serviceruntime.js';
51
55
  export * from './status.js';
52
56
  export * from './taskexecution.js';
53
57
  export * from './traffic.js';
@@ -29,7 +29,6 @@ const deepFreezeVector = <T>(valueArg: T): T => {
29
29
  * quote, and a backslash. Consumers compare both JSON and SHA-256 verbatim.
30
30
  */
31
31
  export const isolatedRestoreCanonicalDigestGoldenVectors: {
32
- version: 1;
33
32
  resourceMappings: IIsolatedRestoreCanonicalDigestGoldenVector<
34
33
  TIsolatedRestoreResourceMapping[]
35
34
  >;
@@ -40,7 +39,6 @@ export const isolatedRestoreCanonicalDigestGoldenVectors: {
40
39
  IIsolatedRestoreGrantClaims
41
40
  >;
42
41
  } = deepFreezeVector({
43
- version: 1,
44
42
  resourceMappings: {
45
43
  input: [
46
44
  {
@@ -91,7 +89,6 @@ export const isolatedRestoreCanonicalDigestGoldenVectors: {
91
89
  },
92
90
  archiveManifest: {
93
91
  input: {
94
- version: 1,
95
92
  backupId: 'backup-0001',
96
93
  createdAt: 1700000000123,
97
94
  objects: [
@@ -122,12 +119,11 @@ export const isolatedRestoreCanonicalDigestGoldenVectors: {
122
119
  '{"backupId":"backup-0001","createdAt":1700000000123,"objects":[{"path":"config.json","sha256":"0000000000000000000000000000000000000000000000000000000000000000","size":2},' +
123
120
  '{"path":"snapshots/snapshot-volume.json","sha256":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","size":3},' +
124
121
  '{"path":"snapshots/snapshot-database.json","sha256":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","size":5},' +
125
- '{"path":"snapshots/snapshot-objectstorage.json","sha256":"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb","size":7}],"totalSize":17,"version":1}',
126
- sha256: 'cd688de1a4b7e0f0b185c660a2c0c199ea4009832c5614a49e8a4dec411f3bd4',
122
+ '{"path":"snapshots/snapshot-objectstorage.json","sha256":"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb","size":7}],"totalSize":17}',
123
+ sha256: '5063bbb4e967fc01023fe498274039395bfb3dc82f85a35acd6cda64ac723cb9',
127
124
  },
128
125
  grantClaims: {
129
126
  input: {
130
- grantVersion: 1,
131
127
  iss: 'urn:foss:restore:šŸ˜€:Ć©:é:"quoted":\\backslash',
132
128
  aud: 'corestore.restore',
133
129
  sub: 'cloudly-control',
@@ -143,15 +139,15 @@ export const isolatedRestoreCanonicalDigestGoldenVectors: {
143
139
  stagingArchiveId: 'archive-0001',
144
140
  operation: 'prepare',
145
141
  resourceMappingsSha256: '3c084580fc258dcb5dc25b80d7331eb1d9072a124f640df3ce26eba4917afe70',
146
- archiveManifestSha256: 'cd688de1a4b7e0f0b185c660a2c0c199ea4009832c5614a49e8a4dec411f3bd4',
142
+ archiveManifestSha256: '5063bbb4e967fc01023fe498274039395bfb3dc82f85a35acd6cda64ac723cb9',
147
143
  iat: 2_000_000_000,
148
144
  nbf: 2_000_000_000,
149
145
  exp: 2_000_000_120,
150
146
  },
151
147
  canonicalJson:
152
- '{"archiveManifestSha256":"cd688de1a4b7e0f0b185c660a2c0c199ea4009832c5614a49e8a4dec411f3bd4","aud":"corestore.restore","authorizationId":"authorization-0001","clusterId":"cluster-eu-1","exp":2000000120,"grantVersion":1,"iat":2000000000,' +
148
+ '{"archiveManifestSha256":"5063bbb4e967fc01023fe498274039395bfb3dc82f85a35acd6cda64ac723cb9","aud":"corestore.restore","authorizationId":"authorization-0001","clusterId":"cluster-eu-1","exp":2000000120,"iat":2000000000,' +
153
149
  '"iss":"urn:foss:restore:šŸ˜€:Ć©:é:\\"quoted\\":\\\\backslash","jti":"grant-0001","nbf":2000000000,"operation":"prepare","resourceMappingsSha256":"3c084580fc258dcb5dc25b80d7331eb1d9072a124f640df3ce26eba4917afe70",' +
154
150
  '"restoreId":"restore-0001","scratchNamespaceId":"scratch-0001","sourceBackupId":"backup-0001","sourceServiceId":"service-source","stagingArchiveId":"archive-0001","sub":"cloudly-control","targetNodeName":"node-1","tenantId":"tenant-0001"}',
155
- sha256: '6fcc94b4c6498b9fa45ec41de197999bbb38b9f8437a9c41f9c9478bdf3af8bf',
151
+ sha256: '7346ba0b19a66535183c7afa6cb1f76236fd0c7f9f678a1695cca9874f8f3743',
156
152
  },
157
153
  });