@serve.zone/interfaces 31.9.0 → 32.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (203) hide show
  1. package/changelog.md +476 -0
  2. package/dist_ts/00_commitinfo_data.js +3 -3
  3. package/dist_ts/appstore/types.d.ts +4 -6
  4. package/dist_ts/appstore/types.js +5 -5
  5. package/dist_ts/data/backup.d.ts +3 -26
  6. package/dist_ts/data/cluster.d.ts +36 -11
  7. package/dist_ts/data/cluster.js +33 -22
  8. package/dist_ts/data/clusteringress.d.ts +8 -0
  9. package/dist_ts/data/clusteringress.js +13 -8
  10. package/dist_ts/data/clusternode.d.ts +121 -74
  11. package/dist_ts/data/clusternode.js +109 -132
  12. package/dist_ts/data/coremail.d.ts +3 -7
  13. package/dist_ts/data/coremail.js +2 -2
  14. package/dist_ts/data/coremail.runtime.d.ts +0 -1
  15. package/dist_ts/data/coremail.runtime.js +5 -22
  16. package/dist_ts/data/deploymentadoption.d.ts +0 -2
  17. package/dist_ts/data/deploymentadoption.js +40 -6
  18. package/dist_ts/data/deploymentoperation.js +16 -3
  19. package/dist_ts/data/deploymentpreflight.d.ts +0 -2
  20. package/dist_ts/data/deploymentpreflight.js +1 -1
  21. package/dist_ts/data/immutableimage.d.ts +38 -21
  22. package/dist_ts/data/immutableimage.js +45 -5
  23. package/dist_ts/data/index.d.ts +1 -1
  24. package/dist_ts/data/isolatedrestore.d.ts +139 -21
  25. package/dist_ts/data/isolatedrestore.golden.d.ts +0 -1
  26. package/dist_ts/data/isolatedrestore.golden.js +6 -9
  27. package/dist_ts/data/isolatedrestore.js +176 -40
  28. package/dist_ts/data/mail.d.ts +1 -1
  29. package/dist_ts/data/networkaddressplan.d.ts +8 -8
  30. package/dist_ts/data/networkaddressplan.js +4 -4
  31. package/dist_ts/data/networkauthority.d.ts +20 -22
  32. package/dist_ts/data/networkauthority.js +26 -28
  33. package/dist_ts/data/networkcredential.d.ts +10 -10
  34. package/dist_ts/data/networkcredential.js +16 -16
  35. package/dist_ts/data/networkdelivery.d.ts +18 -18
  36. package/dist_ts/data/networkdelivery.js +16 -16
  37. package/dist_ts/data/networklease.d.ts +18 -7
  38. package/dist_ts/data/networklease.js +29 -7
  39. package/dist_ts/data/networknode.d.ts +2 -2
  40. package/dist_ts/data/networkprojection.d.ts +59 -60
  41. package/dist_ts/data/networkprojection.js +53 -57
  42. package/dist_ts/data/networkprotection.d.ts +27 -28
  43. package/dist_ts/data/networkprotection.js +36 -36
  44. package/dist_ts/data/networkrouter.d.ts +11 -11
  45. package/dist_ts/data/networkrouter.js +1 -1
  46. package/dist_ts/data/networksigning.d.ts +16 -18
  47. package/dist_ts/data/networksigning.js +20 -21
  48. package/dist_ts/data/nodecredential.d.ts +4 -6
  49. package/dist_ts/data/nodeenrollment.d.ts +35 -40
  50. package/dist_ts/data/nodeenrollment.js +57 -72
  51. package/dist_ts/data/privatenetwork.d.ts +21 -24
  52. package/dist_ts/data/privatenetwork.js +39 -54
  53. package/dist_ts/data/runtimeassignment.d.ts +50 -34
  54. package/dist_ts/data/runtimeassignment.js +79 -45
  55. package/dist_ts/data/runtimeconfig.d.ts +21 -22
  56. package/dist_ts/data/runtimeconfig.js +24 -24
  57. package/dist_ts/data/runtimesession.d.ts +100 -62
  58. package/dist_ts/data/runtimesession.js +98 -79
  59. package/dist_ts/data/runtimeterminalreceipt.d.ts +28 -29
  60. package/dist_ts/data/runtimeterminalreceipt.js +42 -42
  61. package/dist_ts/data/secret.d.ts +18 -25
  62. package/dist_ts/data/secret.js +12 -52
  63. package/dist_ts/data/servicecredential.d.ts +14 -16
  64. package/dist_ts/data/servicecredential.js +17 -28
  65. package/dist_ts/data/serviceruntime.d.ts +7 -7
  66. package/dist_ts/data/serviceruntime.js +4 -4
  67. package/dist_ts/data/sparknodereport.d.ts +27 -14
  68. package/dist_ts/data/sparknodereport.js +35 -28
  69. package/dist_ts/data/webpush.d.ts +0 -1
  70. package/dist_ts/index.d.ts +2 -1
  71. package/dist_ts/index.js +3 -2
  72. package/dist_ts/platform/objectstorageretention.d.ts +21 -24
  73. package/dist_ts/platform/objectstorageretention.js +10 -17
  74. package/dist_ts/platform/storage.d.ts +1 -3
  75. package/dist_ts/platform/storagemigration.d.ts +0 -7
  76. package/dist_ts/platform/storagemigration.golden.d.ts +0 -1
  77. package/dist_ts/platform/storagemigration.golden.js +8 -12
  78. package/dist_ts/platform/storagemigration.js +6 -51
  79. package/dist_ts/platform/types.d.ts +2 -2
  80. package/dist_ts/private/canonicaljson.d.ts +9 -1
  81. package/dist_ts/private/canonicaljson.js +14 -2
  82. package/dist_ts/private/dataproperties.d.ts +62 -0
  83. package/dist_ts/private/dataproperties.js +117 -0
  84. package/dist_ts/private/networkcontract.d.ts +10 -10
  85. package/dist_ts/private/networkcontract.js +1 -1
  86. package/dist_ts/private/releaseversion.d.ts +37 -0
  87. package/dist_ts/private/releaseversion.js +48 -0
  88. package/dist_ts/private/runtimepolicy.d.ts +2 -2
  89. package/dist_ts/private/runtimepolicy.js +1 -1
  90. package/dist_ts/private/tokenlist.d.ts +9 -0
  91. package/dist_ts/private/tokenlist.js +23 -0
  92. package/dist_ts/protocol.d.ts +137 -0
  93. package/dist_ts/protocol.js +255 -0
  94. package/dist_ts/requests/admin.d.ts +8 -8
  95. package/dist_ts/requests/backup.d.ts +102 -112
  96. package/dist_ts/requests/cluster.d.ts +10 -10
  97. package/dist_ts/requests/clusteringress.d.ts +9 -0
  98. package/dist_ts/requests/clusteringress.js +1 -1
  99. package/dist_ts/requests/config.d.ts +3 -3
  100. package/dist_ts/requests/corestore.d.ts +0 -3
  101. package/dist_ts/requests/corestore.js +5 -9
  102. package/dist_ts/requests/network.d.ts +30 -30
  103. package/dist_ts/requests/node.d.ts +15 -28
  104. package/dist_ts/requests/pallet.d.ts +13 -13
  105. package/dist_ts/requests/runtimesession.d.ts +53 -41
  106. package/dist_ts/requests/secret.d.ts +4 -5
  107. package/dist_ts/requests/secret.js +1 -5
  108. package/dist_ts/runtime.corestore.d.ts +56 -74
  109. package/dist_ts/runtime.corestore.databaseexportpackage.d.ts +30 -36
  110. package/dist_ts/runtime.corestore.databaseexportpackage.golden.d.ts +11 -12
  111. package/dist_ts/runtime.corestore.databaseexportpackage.golden.js +54 -71
  112. package/dist_ts/runtime.corestore.databaseexportpackage.js +9 -25
  113. package/dist_ts/runtime.corestore.js +35 -135
  114. package/dist_ts/runtime.corestore.relay.js +2 -7
  115. package/dist_ts/runtime.d.ts +38 -48
  116. package/dist_ts/runtime.js +20 -77
  117. package/dist_ts/runtime.networkprojection.d.ts +4 -4
  118. package/dist_ts/runtime.networkprojection.js +18 -18
  119. package/dist_ts/runtime.workloadinit.d.ts +23 -24
  120. package/dist_ts/runtime.workloadinit.js +6 -13
  121. package/package.json +2 -2
  122. package/readme.md +421 -270
  123. package/ts/00_commitinfo_data.ts +3 -3
  124. package/ts/appstore/types.ts +4 -6
  125. package/ts/data/backup.ts +3 -38
  126. package/ts/data/cluster.ts +51 -34
  127. package/ts/data/clusteringress.ts +12 -12
  128. package/ts/data/clusternode.ts +204 -232
  129. package/ts/data/coremail.runtime.ts +4 -21
  130. package/ts/data/coremail.ts +3 -7
  131. package/ts/data/deploymentadoption.ts +46 -4
  132. package/ts/data/deploymentoperation.ts +16 -1
  133. package/ts/data/deploymentpreflight.ts +0 -2
  134. package/ts/data/immutableimage.ts +71 -24
  135. package/ts/data/index.ts +1 -1
  136. package/ts/data/isolatedrestore.golden.ts +5 -9
  137. package/ts/data/isolatedrestore.ts +339 -54
  138. package/ts/data/mail.ts +1 -1
  139. package/ts/data/networkaddressplan.ts +13 -13
  140. package/ts/data/networkauthority.ts +42 -46
  141. package/ts/data/networkcredential.ts +24 -24
  142. package/ts/data/networkdelivery.ts +27 -27
  143. package/ts/data/networklease.ts +40 -13
  144. package/ts/data/networknode.ts +2 -2
  145. package/ts/data/networkprojection.ts +119 -124
  146. package/ts/data/networkprotection.ts +54 -55
  147. package/ts/data/networkrouter.ts +14 -14
  148. package/ts/data/networksigning.ts +29 -32
  149. package/ts/data/nodecredential.ts +4 -6
  150. package/ts/data/nodeenrollment.ts +96 -114
  151. package/ts/data/privatenetwork.ts +58 -74
  152. package/ts/data/runtimeassignment.ts +143 -94
  153. package/ts/data/runtimeconfig.ts +45 -46
  154. package/ts/data/runtimesession.ts +185 -138
  155. package/ts/data/runtimeterminalreceipt.ts +72 -73
  156. package/ts/data/secret.ts +28 -76
  157. package/ts/data/servicecredential.ts +33 -43
  158. package/ts/data/serviceruntime.ts +11 -11
  159. package/ts/data/sparknodereport.ts +48 -36
  160. package/ts/data/webpush.ts +0 -1
  161. package/ts/index.ts +2 -0
  162. package/ts/platform/objectstorageretention.ts +40 -54
  163. package/ts/platform/storage.ts +1 -3
  164. package/ts/platform/storagemigration.golden.ts +7 -11
  165. package/ts/platform/storagemigration.ts +5 -55
  166. package/ts/platform/types.ts +2 -2
  167. package/ts/private/canonicaljson.ts +13 -1
  168. package/ts/private/dataproperties.ts +139 -0
  169. package/ts/private/networkcontract.ts +9 -9
  170. package/ts/private/releaseversion.ts +70 -0
  171. package/ts/private/runtimepolicy.ts +2 -2
  172. package/ts/private/tokenlist.ts +30 -0
  173. package/ts/protocol.ts +364 -0
  174. package/ts/requests/admin.ts +11 -11
  175. package/ts/requests/backup.ts +112 -117
  176. package/ts/requests/cluster.ts +13 -13
  177. package/ts/requests/clusteringress.ts +9 -0
  178. package/ts/requests/config.ts +3 -3
  179. package/ts/requests/corestore.ts +4 -16
  180. package/ts/requests/network.ts +40 -40
  181. package/ts/requests/node.ts +21 -38
  182. package/ts/requests/pallet.ts +17 -17
  183. package/ts/requests/runtimesession.ts +63 -51
  184. package/ts/requests/secret.ts +5 -10
  185. package/ts/runtime.corestore.databaseexportpackage.golden.ts +77 -95
  186. package/ts/runtime.corestore.databaseexportpackage.ts +51 -73
  187. package/ts/runtime.corestore.relay.ts +1 -10
  188. package/ts/runtime.corestore.ts +118 -268
  189. package/ts/runtime.networkprojection.ts +30 -30
  190. package/ts/runtime.ts +83 -158
  191. package/ts/runtime.workloadinit.ts +36 -48
  192. package/dist_ts/runtime.cloudlylegacydeploymentsettlement.d.ts +0 -902
  193. package/dist_ts/runtime.cloudlylegacydeploymentsettlement.golden.d.ts +0 -35
  194. package/dist_ts/runtime.cloudlylegacydeploymentsettlement.golden.js +0 -315
  195. package/dist_ts/runtime.cloudlylegacydeploymentsettlement.js +0 -3315
  196. package/dist_ts/runtime.cloudlylegacydeploymentsettlement.offlineexport.d.ts +0 -291
  197. package/dist_ts/runtime.cloudlylegacydeploymentsettlement.offlineexport.golden.d.ts +0 -30
  198. package/dist_ts/runtime.cloudlylegacydeploymentsettlement.offlineexport.golden.js +0 -408
  199. package/dist_ts/runtime.cloudlylegacydeploymentsettlement.offlineexport.js +0 -1126
  200. package/ts/runtime.cloudlylegacydeploymentsettlement.golden.ts +0 -421
  201. package/ts/runtime.cloudlylegacydeploymentsettlement.offlineexport.golden.ts +0 -510
  202. package/ts/runtime.cloudlylegacydeploymentsettlement.offlineexport.ts +0 -2470
  203. package/ts/runtime.cloudlylegacydeploymentsettlement.ts +0 -6630
@@ -5,8 +5,11 @@ import {
5
5
  createSha256Hex,
6
6
  deepFreezeValue,
7
7
  } from '../private/canonicaljson.js';
8
+ import {
9
+ readDataElements, readDataProperty, readExactDataRecord,
10
+ } from '../private/dataproperties.js';
8
11
 
9
- export interface INodeEnrollmentCredentialProposalV1 {
12
+ export interface INodeEnrollmentCredentialProposal {
10
13
  purpose: TNodeCredentialPurpose;
11
14
  installationId: string;
12
15
  mutationId: string;
@@ -17,8 +20,7 @@ export interface INodeEnrollmentCredentialProposalV1 {
17
20
  }
18
21
 
19
22
  /** Value-free, immutable proposal. Hashes are still sensitive transport fields. */
20
- export interface INodeEnrollmentV1 {
21
- schemaVersion: 1;
23
+ export interface INodeEnrollment {
22
24
  /** 32 CSPRNG bytes encoded as lowercase hexadecimal; retain across every retry. */
23
25
  enrollmentId: string;
24
26
  cloudlyOrigin: string;
@@ -27,18 +29,18 @@ export interface INodeEnrollmentV1 {
27
29
  | { kind: 'jump'; proofHash: string }
28
30
  | { kind: 'adopt-existing'; nodeId: string; proofHash: string };
29
31
  credentials: [
30
- INodeEnrollmentCredentialProposalV1 & { purpose: 'spark' },
31
- INodeEnrollmentCredentialProposalV1 & { purpose: 'pallet' },
32
+ INodeEnrollmentCredentialProposal & { purpose: 'spark' },
33
+ INodeEnrollmentCredentialProposal & { purpose: 'pallet' },
32
34
  ];
33
35
  }
34
36
 
35
- export interface INodeEnrollmentRequestV1 {
36
- enrollment: INodeEnrollmentV1;
37
+ export interface INodeEnrollmentRequest {
38
+ enrollment: INodeEnrollment;
37
39
  /** Never persist on the server, log, put in URLs, or expose in transport hooks. */
38
40
  proof: { kind: 'bootstrap' | 'pending-spark'; bearer: string };
39
41
  }
40
42
 
41
- export interface INodeEnrollmentCredentialAcknowledgementV1 {
43
+ export interface INodeEnrollmentCredentialAcknowledgement {
42
44
  purpose: TNodeCredentialPurpose;
43
45
  installationId: string;
44
46
  mutationId: string;
@@ -47,29 +49,26 @@ export interface INodeEnrollmentCredentialAcknowledgementV1 {
47
49
  }
48
50
 
49
51
  /** Immutable commit evidence, not authorization or workload readiness. */
50
- export interface INodeEnrollmentAcknowledgementV1 {
51
- schemaVersion: 1;
52
+ export interface INodeEnrollmentAcknowledgement {
52
53
  enrollmentId: string;
53
54
  cloudlyOrigin: string;
54
55
  nodeId: string;
55
56
  requestDigest: string;
56
57
  credentials: [
57
- INodeEnrollmentCredentialAcknowledgementV1 & { purpose: 'spark' },
58
- INodeEnrollmentCredentialAcknowledgementV1 & { purpose: 'pallet' },
58
+ INodeEnrollmentCredentialAcknowledgement & { purpose: 'spark' },
59
+ INodeEnrollmentCredentialAcknowledgement & { purpose: 'pallet' },
59
60
  ];
60
61
  }
61
62
 
62
63
  /** Returned only after current Spark authentication and proof that Pallet is absent. */
63
- export interface INodeEnrollmentStateV1 {
64
- schemaVersion: 1;
64
+ export interface INodeEnrollmentState {
65
65
  nodeId: string;
66
66
  spark: { generation: number; sessionEpoch: number };
67
67
  pallet: 'absent';
68
68
  }
69
69
 
70
70
  /** Root-authenticated, node-local IPC only. Initial Pallet authority is always absent. */
71
- export interface IPalletNodeEnrollmentPreparationV1 {
72
- schemaVersion: 1;
71
+ export interface IPalletNodeEnrollmentPreparation {
73
72
  purpose: 'pallet';
74
73
  installationId: string;
75
74
  mutationId: string;
@@ -78,13 +77,12 @@ export interface IPalletNodeEnrollmentPreparationV1 {
78
77
  }
79
78
 
80
79
  /** Full exact activation wire body; Cloudly authentication remains the coordinator's responsibility. */
81
- export interface IPalletNodeEnrollmentActivationV1 {
82
- enrollment: INodeEnrollmentV1;
83
- acknowledgement: INodeEnrollmentAcknowledgementV1;
80
+ export interface IPalletNodeEnrollmentActivation {
81
+ enrollment: INodeEnrollment;
82
+ acknowledgement: INodeEnrollmentAcknowledgement;
84
83
  }
85
84
 
86
- interface IPalletNodeEnrollmentConfirmationBaseV1 {
87
- schemaVersion: 1;
85
+ interface IPalletNodeEnrollmentConfirmationBase {
88
86
  purpose: 'pallet';
89
87
  enrollmentId: string;
90
88
  cloudlyOrigin: string;
@@ -92,23 +90,23 @@ interface IPalletNodeEnrollmentConfirmationBaseV1 {
92
90
  }
93
91
 
94
92
  /** The exact pending binding is durable now, not merely a historical receipt. */
95
- export interface IPalletNodeEnrollmentBoundV1 extends IPalletNodeEnrollmentConfirmationBaseV1 {
93
+ export interface IPalletNodeEnrollmentBound extends IPalletNodeEnrollmentConfirmationBase {
96
94
  phase: 'bound';
97
95
  /** Null before Cloudly assigns a fresh Jump node; exact existing node for adoption. */
98
96
  nodeId: string | null;
99
97
  }
100
98
 
101
99
  /** Exact CURRENT local Pallet identity, not Spark activation or remote authorization. */
102
- export interface IPalletNodeEnrollmentActiveV1 extends IPalletNodeEnrollmentConfirmationBaseV1 {
100
+ export interface IPalletNodeEnrollmentActive extends IPalletNodeEnrollmentConfirmationBase {
103
101
  phase: 'active';
104
102
  nodeId: string;
105
103
  }
106
104
 
107
- export type TPalletNodeEnrollmentConfirmationV1 =
108
- | IPalletNodeEnrollmentBoundV1 | IPalletNodeEnrollmentActiveV1;
105
+ export type TPalletNodeEnrollmentConfirmation =
106
+ | IPalletNodeEnrollmentBound | IPalletNodeEnrollmentActive;
109
107
 
110
108
  /** Wire bounds, not a listener, permission check, timeout implementation or storage API. */
111
- export const palletNodeEnrollmentV1Contract = Object.freeze({
109
+ export const palletNodeEnrollmentContract = Object.freeze({
112
110
  socketPath: '/run/serve.zone/pallet/control.sock',
113
111
  frame: 'u32be-length-prefixed-utf8-json-then-write-half-close',
114
112
  requestsPerConnection: 1,
@@ -116,8 +114,8 @@ export const palletNodeEnrollmentV1Contract = Object.freeze({
116
114
  maxResponseBytes: 16384,
117
115
  } as const);
118
116
 
119
- export const nodeEnrollmentV1Contract = Object.freeze({
120
- digestDomain: 'serve.zone/node-enrollment-v1',
117
+ export const nodeEnrollmentContract = Object.freeze({
118
+ digestDomain: 'serve.zone/node-enrollment',
121
119
  localActivation: 'independently-durable-convergence',
122
120
  bootstrapProof: 'first-commit-only',
123
121
  pendingSparkProof: 'committed-exact-receipt-only',
@@ -128,31 +126,18 @@ function requireValue(valueArg: unknown): asserts valueArg {
128
126
  if (!valueArg) fail();
129
127
  }
130
128
 
131
- /** Decoded JSON/data records only. No input accessor is executed or preserved. */
129
+ /** Exactly this shape's keys, read once as data; an accessor is refused, never invoked. */
132
130
  const record = (valueArg: unknown, keysArg: readonly string[]): Record<string, unknown> => {
133
- requireValue(valueArg !== null && typeof valueArg === 'object' && !Array.isArray(valueArg));
134
- const prototype = Object.getPrototypeOf(valueArg);
135
- requireValue(prototype === Object.prototype || prototype === null);
136
- const keys = Reflect.ownKeys(valueArg);
137
- requireValue(keys.length === keysArg.length);
138
- const snapshot: Record<string, unknown> = Object.create(null);
139
- for (const key of keys) {
140
- requireValue(typeof key === 'string' && keysArg.includes(key));
141
- const descriptor = Object.getOwnPropertyDescriptor(valueArg, key);
142
- requireValue(descriptor?.enumerable && Object.hasOwn(descriptor, 'value'));
143
- snapshot[key] = descriptor.value;
144
- }
131
+ const snapshot = readExactDataRecord(valueArg, keysArg);
132
+ requireValue(snapshot !== null);
145
133
  return snapshot;
146
134
  };
147
135
 
136
+ /** The dense two-element credential tuple, read the same way as a record. */
148
137
  const pair = (valueArg: unknown): [unknown, unknown] => {
149
- requireValue(Array.isArray(valueArg) && Object.getPrototypeOf(valueArg) === Array.prototype);
150
- requireValue(Reflect.ownKeys(valueArg).length === 3 && valueArg.length === 2);
151
- const first = Object.getOwnPropertyDescriptor(valueArg, '0');
152
- const second = Object.getOwnPropertyDescriptor(valueArg, '1');
153
- requireValue(first?.enumerable && Object.hasOwn(first, 'value'));
154
- requireValue(second?.enumerable && Object.hasOwn(second, 'value'));
155
- return [first.value, second.value];
138
+ const elements = readDataElements(valueArg, 2);
139
+ requireValue(elements !== null && elements.length === 2);
140
+ return [elements[0], elements[1]];
156
141
  };
157
142
  const id = (valueArg: unknown): string => {
158
143
  requireValue(typeof valueArg === 'string' && /^[A-Za-z0-9_-]{1,128}$/.test(valueArg));
@@ -184,7 +169,7 @@ const hostname = (valueArg: unknown): string => {
184
169
 
185
170
  const proposal = <TPurpose extends TNodeCredentialPurpose>(
186
171
  valueArg: unknown, purposeArg: TPurpose,
187
- ): INodeEnrollmentCredentialProposalV1 & { purpose: TPurpose } => {
172
+ ): INodeEnrollmentCredentialProposal & { purpose: TPurpose } => {
188
173
  const value = record(valueArg, ['purpose', 'installationId', 'mutationId', 'tokenHash',
189
174
  'expectedGeneration', 'expectedSessionEpoch']);
190
175
  requireValue(value.purpose === purposeArg);
@@ -194,22 +179,20 @@ const proposal = <TPurpose extends TNodeCredentialPurpose>(
194
179
  };
195
180
 
196
181
  const distinctOwners = (
197
- sparkArg: INodeEnrollmentCredentialAcknowledgementV1 | INodeEnrollmentCredentialProposalV1,
198
- palletArg: INodeEnrollmentCredentialAcknowledgementV1 | INodeEnrollmentCredentialProposalV1,
182
+ sparkArg: INodeEnrollmentCredentialAcknowledgement | INodeEnrollmentCredentialProposal,
183
+ palletArg: INodeEnrollmentCredentialAcknowledgement | INodeEnrollmentCredentialProposal,
199
184
  ): void => {
200
185
  requireValue(sparkArg.installationId !== palletArg.installationId
201
186
  && sparkArg.mutationId !== palletArg.mutationId && sparkArg.tokenHash !== palletArg.tokenHash);
202
187
  };
203
188
 
204
189
  /** Detached frozen snapshot, captured synchronously before hashing or other awaits. */
205
- export const snapshotNodeEnrollmentV1 = (valueArg: unknown): INodeEnrollmentV1 => {
206
- const value = record(valueArg, ['schemaVersion', 'enrollmentId', 'cloudlyOrigin', 'hostname',
190
+ export const snapshotNodeEnrollment = (valueArg: unknown): INodeEnrollment => {
191
+ const value = record(valueArg, ['enrollmentId', 'cloudlyOrigin', 'hostname',
207
192
  'bootstrap', 'credentials']);
208
- requireValue(value.schemaVersion === 1);
209
- // Read the discriminant from its data descriptor, never an input getter.
210
- requireValue(value.bootstrap !== null && typeof value.bootstrap === 'object');
211
- const kind = Object.getOwnPropertyDescriptor(value.bootstrap, 'kind');
212
- requireValue(kind && Object.hasOwn(kind, 'value'));
193
+ // Read the discriminant as data, never through an input getter.
194
+ const kind = readDataProperty(value.bootstrap, 'kind');
195
+ requireValue(kind !== null);
213
196
  const bootstrap = record(value.bootstrap, kind.value === 'jump'
214
197
  ? ['kind', 'proofHash'] : ['kind', 'nodeId', 'proofHash']);
215
198
  requireValue(bootstrap.kind === 'jump' || bootstrap.kind === 'adopt-existing');
@@ -221,7 +204,7 @@ export const snapshotNodeEnrollmentV1 = (valueArg: unknown): INodeEnrollmentV1 =
221
204
  requireValue(bootstrap.kind === 'jump'
222
205
  ? spark.expectedGeneration === 0 && spark.expectedSessionEpoch === 0
223
206
  : spark.expectedGeneration > 0);
224
- return deepFreezeValue({ schemaVersion: 1, enrollmentId: hash(value.enrollmentId),
207
+ return deepFreezeValue({ enrollmentId: hash(value.enrollmentId),
225
208
  cloudlyOrigin: origin(value.cloudlyOrigin), hostname: hostname(value.hostname),
226
209
  bootstrap: bootstrap.kind === 'jump'
227
210
  ? { kind: 'jump', proofHash: hash(bootstrap.proofHash) }
@@ -229,16 +212,16 @@ export const snapshotNodeEnrollmentV1 = (valueArg: unknown): INodeEnrollmentV1 =
229
212
  credentials: [spark, pallet] });
230
213
  };
231
214
 
232
- export const computeNodeEnrollmentV1Digest = async (valueArg: INodeEnrollmentV1): Promise<string> => {
233
- const payload = snapshotNodeEnrollmentV1(valueArg);
215
+ export const computeNodeEnrollmentDigest = async (valueArg: INodeEnrollment): Promise<string> => {
216
+ const payload = snapshotNodeEnrollment(valueArg);
234
217
  return createCanonicalJsonSha256Hex(canonicalizeStrictJson({
235
- domain: nodeEnrollmentV1Contract.digestDomain, payload,
218
+ domain: nodeEnrollmentContract.digestDomain, payload,
236
219
  }, fail), fail);
237
220
  };
238
221
 
239
- export const snapshotNodeEnrollmentRequestV1 = (valueArg: unknown): INodeEnrollmentRequestV1 => {
222
+ export const snapshotNodeEnrollmentRequest = (valueArg: unknown): INodeEnrollmentRequest => {
240
223
  const value = record(valueArg, ['enrollment', 'proof']);
241
- const enrollment = snapshotNodeEnrollmentV1(value.enrollment);
224
+ const enrollment = snapshotNodeEnrollment(value.enrollment);
242
225
  const proof = record(value.proof, ['kind', 'bearer']);
243
226
  requireValue(proof.kind === 'bootstrap' || proof.kind === 'pending-spark');
244
227
  requireValue(typeof proof.bearer === 'string');
@@ -252,11 +235,11 @@ export const snapshotNodeEnrollmentRequestV1 = (valueArg: unknown): INodeEnrollm
252
235
  * receiptState from its owned transaction, compare the complete stored proposal,
253
236
  * and fence current Jump/Spark/Pallet authority before any commit or replay.
254
237
  */
255
- export const verifyNodeEnrollmentProofV1 = async (
256
- valueArg: INodeEnrollmentRequestV1, receiptStateArg: 'absent' | 'committed',
238
+ export const verifyNodeEnrollmentProof = async (
239
+ valueArg: INodeEnrollmentRequest, receiptStateArg: 'absent' | 'committed',
257
240
  ): Promise<boolean> => {
258
241
  try {
259
- const { enrollment, proof } = snapshotNodeEnrollmentRequestV1(valueArg);
242
+ const { enrollment, proof } = snapshotNodeEnrollmentRequest(valueArg);
260
243
  if (!(proof.kind === 'bootstrap' && receiptStateArg === 'absent')
261
244
  && !(proof.kind === 'pending-spark' && receiptStateArg === 'committed')) return false;
262
245
  // This helper hashes exact UTF-8 text; no JSON quoting or normalization.
@@ -268,35 +251,34 @@ export const verifyNodeEnrollmentProofV1 = async (
268
251
 
269
252
  const credentialAcknowledgement = <TPurpose extends TNodeCredentialPurpose>(
270
253
  valueArg: unknown, purposeArg: TPurpose,
271
- ): INodeEnrollmentCredentialAcknowledgementV1 & { purpose: TPurpose } => {
254
+ ): INodeEnrollmentCredentialAcknowledgement & { purpose: TPurpose } => {
272
255
  const value = record(valueArg, ['purpose', 'installationId', 'mutationId', 'tokenHash', 'generation']);
273
256
  requireValue(value.purpose === purposeArg);
274
257
  return { purpose: purposeArg, installationId: id(value.installationId), mutationId: id(value.mutationId),
275
258
  tokenHash: hash(value.tokenHash), generation: counter(value.generation, 1) };
276
259
  };
277
260
 
278
- export const snapshotNodeEnrollmentAcknowledgementV1 = (
261
+ export const snapshotNodeEnrollmentAcknowledgement = (
279
262
  valueArg: unknown,
280
- ): INodeEnrollmentAcknowledgementV1 => {
281
- const value = record(valueArg, ['schemaVersion', 'enrollmentId', 'cloudlyOrigin', 'nodeId',
263
+ ): INodeEnrollmentAcknowledgement => {
264
+ const value = record(valueArg, ['enrollmentId', 'cloudlyOrigin', 'nodeId',
282
265
  'requestDigest', 'credentials']);
283
- requireValue(value.schemaVersion === 1);
284
266
  const [sparkInput, palletInput] = pair(value.credentials);
285
267
  const spark = credentialAcknowledgement(sparkInput, 'spark');
286
268
  const pallet = credentialAcknowledgement(palletInput, 'pallet');
287
269
  distinctOwners(spark, pallet);
288
270
  requireValue(pallet.generation === 1);
289
- return deepFreezeValue({ schemaVersion: 1, enrollmentId: hash(value.enrollmentId),
271
+ return deepFreezeValue({ enrollmentId: hash(value.enrollmentId),
290
272
  cloudlyOrigin: origin(value.cloudlyOrigin), nodeId: id(value.nodeId),
291
273
  requestDigest: hash(value.requestDigest), credentials: [spark, pallet] });
292
274
  };
293
275
 
294
276
  /** Content binding only. Authenticate Cloudly first; persist only the returned snapshot. */
295
- export const bindNodeEnrollmentAcknowledgementV1 = async (
296
- enrollmentArg: INodeEnrollmentV1, acknowledgementArg: INodeEnrollmentAcknowledgementV1,
297
- ): Promise<INodeEnrollmentAcknowledgementV1> => {
298
- const enrollment = snapshotNodeEnrollmentV1(enrollmentArg);
299
- const ack = snapshotNodeEnrollmentAcknowledgementV1(acknowledgementArg);
277
+ export const bindNodeEnrollmentAcknowledgement = async (
278
+ enrollmentArg: INodeEnrollment, acknowledgementArg: INodeEnrollmentAcknowledgement,
279
+ ): Promise<INodeEnrollmentAcknowledgement> => {
280
+ const enrollment = snapshotNodeEnrollment(enrollmentArg);
281
+ const ack = snapshotNodeEnrollmentAcknowledgement(acknowledgementArg);
300
282
  requireValue(ack.enrollmentId === enrollment.enrollmentId && ack.cloudlyOrigin === enrollment.cloudlyOrigin
301
283
  && (enrollment.bootstrap.kind === 'jump' || ack.nodeId === enrollment.bootstrap.nodeId));
302
284
  for (const index of [0, 1] as const) {
@@ -306,35 +288,35 @@ export const bindNodeEnrollmentAcknowledgementV1 = async (
306
288
  && actual.mutationId === expected.mutationId && actual.tokenHash === expected.tokenHash
307
289
  && actual.generation === expected.expectedGeneration + 1);
308
290
  }
309
- requireValue(ack.requestDigest === await computeNodeEnrollmentV1Digest(enrollment));
291
+ requireValue(ack.requestDigest === await computeNodeEnrollmentDigest(enrollment));
310
292
  return ack;
311
293
  };
312
294
 
313
- export const snapshotNodeEnrollmentStateV1 = (valueArg: unknown): INodeEnrollmentStateV1 => {
314
- const value = record(valueArg, ['schemaVersion', 'nodeId', 'spark', 'pallet']);
315
- requireValue(value.schemaVersion === 1 && value.pallet === 'absent');
295
+ export const snapshotNodeEnrollmentState = (valueArg: unknown): INodeEnrollmentState => {
296
+ const value = record(valueArg, ['nodeId', 'spark', 'pallet']);
297
+ requireValue(value.pallet === 'absent');
316
298
  const spark = record(value.spark, ['generation', 'sessionEpoch']);
317
- return deepFreezeValue({ schemaVersion: 1, nodeId: id(value.nodeId), pallet: 'absent',
299
+ return deepFreezeValue({ nodeId: id(value.nodeId), pallet: 'absent',
318
300
  spark: { generation: counter(spark.generation, 1, true), sessionEpoch: counter(spark.sessionEpoch, 0, true) } });
319
301
  };
320
302
 
321
303
  /** Decoded JSON/data records only, captured synchronously; never invokes getters. */
322
- export const snapshotPalletNodeEnrollmentPreparationV1 = (
304
+ export const snapshotPalletNodeEnrollmentPreparation = (
323
305
  valueArg: unknown,
324
- ): IPalletNodeEnrollmentPreparationV1 => {
325
- const value = record(valueArg, ['schemaVersion', 'purpose', 'installationId', 'mutationId',
306
+ ): IPalletNodeEnrollmentPreparation => {
307
+ const value = record(valueArg, ['purpose', 'installationId', 'mutationId',
326
308
  'cloudlyOrigin', 'nodeId']);
327
- requireValue(value.schemaVersion === 1 && value.purpose === 'pallet');
328
- return deepFreezeValue({ schemaVersion: 1, purpose: 'pallet',
309
+ requireValue(value.purpose === 'pallet');
310
+ return deepFreezeValue({ purpose: 'pallet',
329
311
  installationId: id(value.installationId), mutationId: id(value.mutationId),
330
312
  cloudlyOrigin: origin(value.cloudlyOrigin), nodeId: value.nodeId === null ? null : id(value.nodeId) });
331
313
  };
332
314
 
333
315
  /** Content binding only. Authenticate the local Pallet transport before trusting this proposal. */
334
- export const bindPalletNodeEnrollmentPreparationV1 = (
335
- preparationArg: IPalletNodeEnrollmentPreparationV1, proposalArg: unknown,
336
- ): INodeEnrollmentV1['credentials'][1] => {
337
- const preparation = snapshotPalletNodeEnrollmentPreparationV1(preparationArg);
316
+ export const bindPalletNodeEnrollmentPreparation = (
317
+ preparationArg: IPalletNodeEnrollmentPreparation, proposalArg: unknown,
318
+ ): INodeEnrollment['credentials'][1] => {
319
+ const preparation = snapshotPalletNodeEnrollmentPreparation(preparationArg);
338
320
  const result = proposal(proposalArg, 'pallet');
339
321
  requireValue(result.installationId === preparation.installationId
340
322
  && result.mutationId === preparation.mutationId
@@ -343,22 +325,22 @@ export const bindPalletNodeEnrollmentPreparationV1 = (
343
325
  };
344
326
 
345
327
  /** Capture the exact wrapper and both nested values before any asynchronous content binding. */
346
- export const snapshotPalletNodeEnrollmentActivationV1 = (
328
+ export const snapshotPalletNodeEnrollmentActivation = (
347
329
  valueArg: unknown,
348
- ): IPalletNodeEnrollmentActivationV1 => {
330
+ ): IPalletNodeEnrollmentActivation => {
349
331
  const value = record(valueArg, ['enrollment', 'acknowledgement']);
350
- return deepFreezeValue({ enrollment: snapshotNodeEnrollmentV1(value.enrollment),
351
- acknowledgement: snapshotNodeEnrollmentAcknowledgementV1(value.acknowledgement) });
332
+ return deepFreezeValue({ enrollment: snapshotNodeEnrollment(value.enrollment),
333
+ acknowledgement: snapshotNodeEnrollmentAcknowledgement(value.acknowledgement) });
352
334
  };
353
335
 
354
- export const snapshotPalletNodeEnrollmentConfirmationV1 = (
336
+ export const snapshotPalletNodeEnrollmentConfirmation = (
355
337
  valueArg: unknown,
356
- ): TPalletNodeEnrollmentConfirmationV1 => {
357
- const value = record(valueArg, ['schemaVersion', 'purpose', 'enrollmentId', 'cloudlyOrigin',
338
+ ): TPalletNodeEnrollmentConfirmation => {
339
+ const value = record(valueArg, ['purpose', 'enrollmentId', 'cloudlyOrigin',
358
340
  'requestDigest', 'phase', 'nodeId']);
359
- requireValue(value.schemaVersion === 1 && value.purpose === 'pallet'
341
+ requireValue(value.purpose === 'pallet'
360
342
  && (value.phase === 'bound' || value.phase === 'active'));
361
- const common = { schemaVersion: 1 as const, purpose: 'pallet' as const,
343
+ const common = { purpose: 'pallet' as const,
362
344
  enrollmentId: hash(value.enrollmentId), cloudlyOrigin: origin(value.cloudlyOrigin),
363
345
  requestDigest: hash(value.requestDigest) };
364
346
  return deepFreezeValue(value.phase === 'bound'
@@ -367,15 +349,15 @@ export const snapshotPalletNodeEnrollmentConfirmationV1 = (
367
349
  };
368
350
 
369
351
  /** Pure binding only. Pallet must prove its durable pending binding before issuing this response. */
370
- export const bindPalletNodeEnrollmentBoundV1 = async (
371
- enrollmentArg: INodeEnrollmentV1, confirmationArg: IPalletNodeEnrollmentBoundV1,
372
- ): Promise<IPalletNodeEnrollmentBoundV1> => {
373
- const enrollment = snapshotNodeEnrollmentV1(enrollmentArg);
374
- const confirmation = snapshotPalletNodeEnrollmentConfirmationV1(confirmationArg);
352
+ export const bindPalletNodeEnrollmentBound = async (
353
+ enrollmentArg: INodeEnrollment, confirmationArg: IPalletNodeEnrollmentBound,
354
+ ): Promise<IPalletNodeEnrollmentBound> => {
355
+ const enrollment = snapshotNodeEnrollment(enrollmentArg);
356
+ const confirmation = snapshotPalletNodeEnrollmentConfirmation(confirmationArg);
375
357
  requireValue(confirmation.phase === 'bound' && confirmation.enrollmentId === enrollment.enrollmentId
376
358
  && confirmation.cloudlyOrigin === enrollment.cloudlyOrigin
377
359
  && confirmation.nodeId === (enrollment.bootstrap.kind === 'jump' ? null : enrollment.bootstrap.nodeId));
378
- requireValue(confirmation.requestDigest === await computeNodeEnrollmentV1Digest(enrollment));
360
+ requireValue(confirmation.requestDigest === await computeNodeEnrollmentDigest(enrollment));
379
361
  return confirmation;
380
362
  };
381
363
 
@@ -384,15 +366,15 @@ export const bindPalletNodeEnrollmentBoundV1 = async (
384
366
  * Pallet owner must first prove its exact CURRENT local identity, not just a receipt.
385
367
  * This does not assert Spark activation, current Cloudly authority or workload readiness.
386
368
  */
387
- export const bindPalletNodeEnrollmentActiveV1 = async (
388
- activationArg: IPalletNodeEnrollmentActivationV1,
389
- confirmationArg: IPalletNodeEnrollmentActiveV1,
390
- ): Promise<IPalletNodeEnrollmentActiveV1> => {
369
+ export const bindPalletNodeEnrollmentActive = async (
370
+ activationArg: IPalletNodeEnrollmentActivation,
371
+ confirmationArg: IPalletNodeEnrollmentActive,
372
+ ): Promise<IPalletNodeEnrollmentActive> => {
391
373
  // Capture every caller-owned value before the asynchronous shared acknowledgement binder.
392
- const { enrollment, acknowledgement } = snapshotPalletNodeEnrollmentActivationV1(activationArg);
393
- const confirmation = snapshotPalletNodeEnrollmentConfirmationV1(confirmationArg);
374
+ const { enrollment, acknowledgement } = snapshotPalletNodeEnrollmentActivation(activationArg);
375
+ const confirmation = snapshotPalletNodeEnrollmentConfirmation(confirmationArg);
394
376
  requireValue(confirmation.phase === 'active');
395
- const ack = await bindNodeEnrollmentAcknowledgementV1(enrollment, acknowledgement);
377
+ const ack = await bindNodeEnrollmentAcknowledgement(enrollment, acknowledgement);
396
378
  requireValue(confirmation.enrollmentId === ack.enrollmentId && confirmation.cloudlyOrigin === ack.cloudlyOrigin
397
379
  && confirmation.nodeId === ack.nodeId && confirmation.requestDigest === ack.requestDigest);
398
380
  return confirmation;