@serve.zone/interfaces 25.1.1 → 25.3.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.
- package/changelog.md +19 -0
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/platform/index.d.ts +3 -1
- package/dist_ts/platform/index.js +4 -2
- package/dist_ts/platform/objectstorageretention.d.ts +63 -0
- package/dist_ts/platform/objectstorageretention.js +255 -0
- package/dist_ts/platform/types.d.ts +3 -0
- package/dist_ts/plugins.runtime.d.ts +2 -0
- package/dist_ts/plugins.runtime.js +4 -0
- package/dist_ts/requests/config.d.ts +3 -0
- package/dist_ts/runtime.cloudlylegacydeploymentsettlement.d.ts +394 -0
- package/dist_ts/runtime.cloudlylegacydeploymentsettlement.golden.d.ts +35 -0
- package/dist_ts/runtime.cloudlylegacydeploymentsettlement.golden.js +315 -0
- package/dist_ts/runtime.cloudlylegacydeploymentsettlement.js +1378 -0
- package/dist_ts/runtime.corestore.d.ts +204 -0
- package/dist_ts/runtime.corestore.js +620 -0
- package/dist_ts/runtime.d.ts +2 -0
- package/dist_ts/runtime.js +3 -1
- package/dist_ts/runtime.workloadinit.d.ts +1 -1
- package/package.json +5 -1
- package/readme.md +54 -0
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/platform/index.ts +3 -0
- package/ts/platform/objectstorageretention.ts +372 -0
- package/ts/platform/types.ts +3 -0
- package/ts/plugins.runtime.ts +4 -0
- package/ts/requests/config.ts +3 -0
- package/ts/runtime.cloudlylegacydeploymentsettlement.golden.ts +421 -0
- package/ts/runtime.cloudlylegacydeploymentsettlement.ts +2884 -0
- package/ts/runtime.corestore.ts +909 -0
- package/ts/runtime.ts +2 -0
- package/ts/runtime.workloadinit.ts +1 -1
|
@@ -0,0 +1,2884 @@
|
|
|
1
|
+
import * as plugins from './plugins.runtime.js';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
canonicalizeStrictJson,
|
|
5
|
+
deepFreezeValue,
|
|
6
|
+
} from './private/canonicaljson.js';
|
|
7
|
+
|
|
8
|
+
export const cloudlyLegacyDeploymentSettlementLimits = Object.freeze({
|
|
9
|
+
maximumIdentifierLength: 200,
|
|
10
|
+
maximumSourceDocuments: 2000,
|
|
11
|
+
maximumOperations: 500,
|
|
12
|
+
maximumPlanBytes: 512 * 1024,
|
|
13
|
+
maximumSafeResultBytes: 16 * 1024,
|
|
14
|
+
maximumReceiptBytes: 512 * 1024,
|
|
15
|
+
maximumAuthorityBytes: 16 * 1024,
|
|
16
|
+
maximumAuthenticatedArtifactBytes: 768 * 1024,
|
|
17
|
+
maximumAuthorityLifetimeMs: 24 * 60 * 60 * 1000,
|
|
18
|
+
maximumFailureReasons: 32,
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
export const cloudlyLegacyDeploymentSettlementDomains = Object.freeze({
|
|
22
|
+
authorityAad:
|
|
23
|
+
'serve.zone/cloudly-legacy-deployment-settlement/authority-aad-v1\0',
|
|
24
|
+
rehearsalBindingHmac:
|
|
25
|
+
'serve.zone/cloudly-legacy-deployment-settlement/rehearsal-binding-hmac-v1\0',
|
|
26
|
+
planHmac:
|
|
27
|
+
'serve.zone/cloudly-legacy-deployment-settlement/plan-hmac-v1\0',
|
|
28
|
+
productionRequestHmac:
|
|
29
|
+
'serve.zone/cloudly-legacy-deployment-settlement/production-request-hmac-v1\0',
|
|
30
|
+
checkResultHmac:
|
|
31
|
+
'serve.zone/cloudly-legacy-deployment-settlement/check-result-hmac-v1\0',
|
|
32
|
+
applyResultHmac:
|
|
33
|
+
'serve.zone/cloudly-legacy-deployment-settlement/apply-result-hmac-v1\0',
|
|
34
|
+
stableOutcomeHmac:
|
|
35
|
+
'serve.zone/cloudly-legacy-deployment-settlement/stable-outcome-hmac-v1\0',
|
|
36
|
+
scratchReceiptHmac:
|
|
37
|
+
'serve.zone/cloudly-legacy-deployment-settlement/scratch-receipt-hmac-v1\0',
|
|
38
|
+
productionReceiptHmac:
|
|
39
|
+
'serve.zone/cloudly-legacy-deployment-settlement/production-receipt-hmac-v1\0',
|
|
40
|
+
} as const);
|
|
41
|
+
|
|
42
|
+
export type TCloudlyLegacyDeploymentSettlementCodecErrorCode =
|
|
43
|
+
| 'INVALID_DATA'
|
|
44
|
+
| 'INVALID_SCHEMA'
|
|
45
|
+
| 'INVALID_VALUE'
|
|
46
|
+
| 'LIMIT_EXCEEDED'
|
|
47
|
+
| 'ORDERING_REQUIRED'
|
|
48
|
+
| 'CROSS_FIELD_MISMATCH';
|
|
49
|
+
|
|
50
|
+
/** Safe error surface: code and schema path are finite and never contain values. */
|
|
51
|
+
export class CloudlyLegacyDeploymentSettlementCodecError extends Error {
|
|
52
|
+
public readonly code: TCloudlyLegacyDeploymentSettlementCodecErrorCode;
|
|
53
|
+
public readonly path: string;
|
|
54
|
+
|
|
55
|
+
public constructor(
|
|
56
|
+
codeArg: TCloudlyLegacyDeploymentSettlementCodecErrorCode,
|
|
57
|
+
pathArg: string,
|
|
58
|
+
) {
|
|
59
|
+
super(`${codeArg}:${pathArg}`);
|
|
60
|
+
this.name = 'CloudlyLegacyDeploymentSettlementCodecError';
|
|
61
|
+
this.code = codeArg;
|
|
62
|
+
this.path = pathArg;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export type TCloudlyLegacyDeploymentSettlementClassification =
|
|
67
|
+
| 'image-recorded-not-current'
|
|
68
|
+
| 'image-recorded-current-failed'
|
|
69
|
+
| 'rolling-out-current-failed'
|
|
70
|
+
| 'rolling-out-superseded';
|
|
71
|
+
|
|
72
|
+
export interface ICloudlyLegacyDeploymentSettlementClassificationCountsV1 {
|
|
73
|
+
'image-recorded-not-current': number;
|
|
74
|
+
'image-recorded-current-failed': number;
|
|
75
|
+
'rolling-out-current-failed': number;
|
|
76
|
+
'rolling-out-superseded': number;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export interface ICloudlyLegacyDeploymentSettlementAuthorityReferenceV1 {
|
|
80
|
+
operationId: string;
|
|
81
|
+
authorityId: string;
|
|
82
|
+
keyId: string;
|
|
83
|
+
keyVersion: 1;
|
|
84
|
+
authorityMetadataSha256: string;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export interface ICloudlyLegacyDeploymentSettlementAuthorityMetadataV1
|
|
88
|
+
{
|
|
89
|
+
schemaVersion: 1;
|
|
90
|
+
operationId: string;
|
|
91
|
+
authorityId: string;
|
|
92
|
+
keyId: string;
|
|
93
|
+
keyVersion: 1;
|
|
94
|
+
settlementId: string;
|
|
95
|
+
issuedAt: number;
|
|
96
|
+
expiresAt: number;
|
|
97
|
+
maintenanceImageDigest: `sha256:${string}`;
|
|
98
|
+
sourceImageDigest: `sha256:${string}`;
|
|
99
|
+
targetImageDigest: `sha256:${string}`;
|
|
100
|
+
targetVersion: string;
|
|
101
|
+
targetManifestSha256: string;
|
|
102
|
+
targetConfigSha256: string;
|
|
103
|
+
backupId: string;
|
|
104
|
+
backupSnapshotIdSha256: string;
|
|
105
|
+
backupProofSha256: string;
|
|
106
|
+
runId: string;
|
|
107
|
+
rehearsalId: string;
|
|
108
|
+
scratchServiceId: string;
|
|
109
|
+
allocationId: string;
|
|
110
|
+
allocationGeneration: number;
|
|
111
|
+
allocationBindingSha256: string;
|
|
112
|
+
allocationReceiptSha256: string;
|
|
113
|
+
sourceDataSha256: string;
|
|
114
|
+
restoredDataSha256: string;
|
|
115
|
+
digestProofSha256: string;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** Private plaintext HMAC key. Never persist, log, or place in summaries or receipts. */
|
|
119
|
+
export interface ICloudlyLegacyDeploymentSettlementHmacKeyPlaintextV1 {
|
|
120
|
+
format: 'raw-32-byte-base64url';
|
|
121
|
+
value: string;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Exact private-file handoff parsed by pinned maintenance containers.
|
|
126
|
+
* Interfaces only parses and encodes it; consumers own secure generation,
|
|
127
|
+
* storage, use, and destruction of the plaintext key.
|
|
128
|
+
* This package never generates, stores, logs, or performs HMAC with the key.
|
|
129
|
+
*/
|
|
130
|
+
export interface ICloudlyLegacyDeploymentSettlementAuthorityHandoffPlaintextV1 {
|
|
131
|
+
schemaVersion: 1;
|
|
132
|
+
kind: 'cloudly-legacy-deployment-settlement-authority-handoff-plaintext';
|
|
133
|
+
authorityMetadata: ICloudlyLegacyDeploymentSettlementAuthorityMetadataV1;
|
|
134
|
+
authorityReference: ICloudlyLegacyDeploymentSettlementAuthorityReferenceV1;
|
|
135
|
+
hmacKeyPlaintext: ICloudlyLegacyDeploymentSettlementHmacKeyPlaintextV1;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export interface ICloudlyLegacyDeploymentSettlementSourceCensusV1 {
|
|
139
|
+
operations: number;
|
|
140
|
+
services: number;
|
|
141
|
+
images: number;
|
|
142
|
+
releases: number;
|
|
143
|
+
rolloutOperations: number;
|
|
144
|
+
routeClaims: number;
|
|
145
|
+
resourceClaims: number;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export interface ICloudlyLegacyDeploymentSettlementPlanEntryV1 {
|
|
149
|
+
operationId: string;
|
|
150
|
+
serviceId: string;
|
|
151
|
+
sourceRevision: number;
|
|
152
|
+
sourceState: 'image-recorded' | 'rolling-out';
|
|
153
|
+
classification: TCloudlyLegacyDeploymentSettlementClassification;
|
|
154
|
+
finalRevision: number;
|
|
155
|
+
sourceDocumentHmac: `hmac-sha256:${string}`;
|
|
156
|
+
finalDocumentHmac: `hmac-sha256:${string}`;
|
|
157
|
+
routeClaimsStabilized: number;
|
|
158
|
+
routeClaimsRemoved: number;
|
|
159
|
+
resourceClaimsRemoved: number;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export interface ICloudlyLegacyDeploymentSettlementPlanV1 {
|
|
163
|
+
schemaVersion: 1;
|
|
164
|
+
kind: 'cloudly-legacy-deployment-settlement-plan';
|
|
165
|
+
authority: ICloudlyLegacyDeploymentSettlementAuthorityReferenceV1;
|
|
166
|
+
settlementId: string;
|
|
167
|
+
effectiveAt: number;
|
|
168
|
+
sourceStateHmac: `hmac-sha256:${string}`;
|
|
169
|
+
finalStateHmac: `hmac-sha256:${string}`;
|
|
170
|
+
sourceCensus: ICloudlyLegacyDeploymentSettlementSourceCensusV1;
|
|
171
|
+
entries: ICloudlyLegacyDeploymentSettlementPlanEntryV1[];
|
|
172
|
+
classificationCounts: ICloudlyLegacyDeploymentSettlementClassificationCountsV1;
|
|
173
|
+
operationCount: number;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export interface ICloudlyLegacyDeploymentSettlementProductionRequestV1 {
|
|
177
|
+
schemaVersion: 1;
|
|
178
|
+
kind: 'cloudly-legacy-deployment-settlement-production-request';
|
|
179
|
+
authority: ICloudlyLegacyDeploymentSettlementAuthorityReferenceV1;
|
|
180
|
+
plan: ICloudlyLegacyDeploymentSettlementPlanV1;
|
|
181
|
+
planSha256: string;
|
|
182
|
+
rehearsalBinding: ICloudlyLegacyDeploymentSettlementRehearsalBindingV1;
|
|
183
|
+
rehearsalBindingSha256: string;
|
|
184
|
+
requestedAt: number;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export interface ICloudlyLegacyDeploymentSettlementMutationCountsV1 {
|
|
188
|
+
operationCount: number;
|
|
189
|
+
routeClaimsStabilized: number;
|
|
190
|
+
routeClaimsRemoved: number;
|
|
191
|
+
resourceClaimsRemoved: number;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export type TCloudlyLegacyDeploymentSettlementFailureReason =
|
|
195
|
+
| 'AUTHORITY_INVALID'
|
|
196
|
+
| 'AUTHORITY_EXPIRED'
|
|
197
|
+
| 'REQUEST_MISMATCH'
|
|
198
|
+
| 'PLAN_MISMATCH'
|
|
199
|
+
| 'SOURCE_STATE_MISMATCH'
|
|
200
|
+
| 'FINAL_STATE_MISMATCH'
|
|
201
|
+
| 'TRANSACTIONS_UNSUPPORTED'
|
|
202
|
+
| 'OPERATION_DRIFT'
|
|
203
|
+
| 'CLAIM_DRIFT'
|
|
204
|
+
| 'CLASSIFICATION_MISMATCH';
|
|
205
|
+
|
|
206
|
+
interface ICloudlyLegacyDeploymentSettlementSafeResultBaseV1 {
|
|
207
|
+
schemaVersion: 1;
|
|
208
|
+
requestSha256: string;
|
|
209
|
+
planSha256: string;
|
|
210
|
+
settlementId: string;
|
|
211
|
+
sourceStateHmac: `hmac-sha256:${string}`;
|
|
212
|
+
finalStateHmac: `hmac-sha256:${string}`;
|
|
213
|
+
transactionSupported: boolean;
|
|
214
|
+
counts: ICloudlyLegacyDeploymentSettlementMutationCountsV1;
|
|
215
|
+
classificationCounts: ICloudlyLegacyDeploymentSettlementClassificationCountsV1;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export type TCloudlyLegacyDeploymentSettlementCheckResultV1 =
|
|
219
|
+
| (ICloudlyLegacyDeploymentSettlementSafeResultBaseV1 & {
|
|
220
|
+
kind: 'cloudly-legacy-deployment-settlement-check-result';
|
|
221
|
+
status: 'ready';
|
|
222
|
+
disposition: 'unapplied' | 'exact-replay' | 'no-op';
|
|
223
|
+
checkedAt: number;
|
|
224
|
+
})
|
|
225
|
+
| (ICloudlyLegacyDeploymentSettlementSafeResultBaseV1 & {
|
|
226
|
+
kind: 'cloudly-legacy-deployment-settlement-check-result';
|
|
227
|
+
status: 'blocked';
|
|
228
|
+
disposition: 'unapplied';
|
|
229
|
+
failureReasons: TCloudlyLegacyDeploymentSettlementFailureReason[];
|
|
230
|
+
checkedAt: number;
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
export type TCloudlyLegacyDeploymentSettlementApplyResultV1 =
|
|
234
|
+
| (ICloudlyLegacyDeploymentSettlementSafeResultBaseV1 & {
|
|
235
|
+
kind: 'cloudly-legacy-deployment-settlement-apply-result';
|
|
236
|
+
status: 'completed';
|
|
237
|
+
disposition: 'applied' | 'exact-replay' | 'no-op';
|
|
238
|
+
completedAt: number;
|
|
239
|
+
})
|
|
240
|
+
| (ICloudlyLegacyDeploymentSettlementSafeResultBaseV1 & {
|
|
241
|
+
kind: 'cloudly-legacy-deployment-settlement-apply-result';
|
|
242
|
+
status: 'rejected';
|
|
243
|
+
disposition: 'unapplied';
|
|
244
|
+
failureReasons: TCloudlyLegacyDeploymentSettlementFailureReason[];
|
|
245
|
+
rejectedAt: number;
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
export interface ICloudlyLegacyDeploymentSettlementRehearsalBindingV1 {
|
|
249
|
+
schemaVersion: 1;
|
|
250
|
+
kind: 'cloudly-legacy-deployment-settlement-rehearsal-binding';
|
|
251
|
+
settlementId: string;
|
|
252
|
+
runId: string;
|
|
253
|
+
rehearsalId: string;
|
|
254
|
+
scratchServiceId: string;
|
|
255
|
+
allocationId: string;
|
|
256
|
+
allocationGeneration: number;
|
|
257
|
+
allocationBindingSha256: string;
|
|
258
|
+
allocationReceiptSha256: string;
|
|
259
|
+
backupId: string;
|
|
260
|
+
backupSnapshotIdSha256: string;
|
|
261
|
+
backupProofSha256: string;
|
|
262
|
+
sourceDataSha256: string;
|
|
263
|
+
restoredDataSha256: string;
|
|
264
|
+
digestProofSha256: string;
|
|
265
|
+
targetImageDigest: `sha256:${string}`;
|
|
266
|
+
targetVersion: string;
|
|
267
|
+
targetManifestSha256: string;
|
|
268
|
+
targetConfigSha256: string;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
export interface ICloudlyLegacyDeploymentSettlementStableOutcomeV1 {
|
|
272
|
+
schemaVersion: 1;
|
|
273
|
+
kind: 'cloudly-legacy-deployment-settlement-stable-outcome';
|
|
274
|
+
settlementId: string;
|
|
275
|
+
runId: string;
|
|
276
|
+
rehearsalBindingSha256: string;
|
|
277
|
+
effectiveAt: number;
|
|
278
|
+
planSha256: string;
|
|
279
|
+
sourceStateHmac: `hmac-sha256:${string}`;
|
|
280
|
+
finalStateHmac: `hmac-sha256:${string}`;
|
|
281
|
+
settlements: ICloudlyLegacyDeploymentSettlementStableOutcomeEntryV1[];
|
|
282
|
+
counts: ICloudlyLegacyDeploymentSettlementMutationCountsV1;
|
|
283
|
+
classificationCounts: ICloudlyLegacyDeploymentSettlementClassificationCountsV1;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
export interface ICloudlyLegacyDeploymentSettlementStableOutcomeEntryV1 {
|
|
287
|
+
operationId: string;
|
|
288
|
+
finalRevision: number;
|
|
289
|
+
finalDocumentHmac: `hmac-sha256:${string}`;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
export interface IAuthenticatedCloudlyLegacyDeploymentSettlementRehearsalBindingV1 {
|
|
293
|
+
schemaVersion: 1;
|
|
294
|
+
kind: 'authenticated-cloudly-legacy-deployment-settlement-rehearsal-binding';
|
|
295
|
+
authority: ICloudlyLegacyDeploymentSettlementAuthorityReferenceV1;
|
|
296
|
+
payload: ICloudlyLegacyDeploymentSettlementRehearsalBindingV1;
|
|
297
|
+
payloadSha256: string;
|
|
298
|
+
mac: string;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
export interface IAuthenticatedCloudlyLegacyDeploymentSettlementPlanV1 {
|
|
302
|
+
schemaVersion: 1;
|
|
303
|
+
kind: 'authenticated-cloudly-legacy-deployment-settlement-plan';
|
|
304
|
+
authority: ICloudlyLegacyDeploymentSettlementAuthorityReferenceV1;
|
|
305
|
+
payload: ICloudlyLegacyDeploymentSettlementPlanV1;
|
|
306
|
+
payloadSha256: string;
|
|
307
|
+
mac: string;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
export interface IAuthenticatedCloudlyLegacyDeploymentSettlementProductionRequestV1 {
|
|
311
|
+
schemaVersion: 1;
|
|
312
|
+
kind: 'authenticated-cloudly-legacy-deployment-settlement-production-request';
|
|
313
|
+
authority: ICloudlyLegacyDeploymentSettlementAuthorityReferenceV1;
|
|
314
|
+
payload: ICloudlyLegacyDeploymentSettlementProductionRequestV1;
|
|
315
|
+
payloadSha256: string;
|
|
316
|
+
mac: string;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
export interface IAuthenticatedCloudlyLegacyDeploymentSettlementCheckResultV1 {
|
|
320
|
+
schemaVersion: 1;
|
|
321
|
+
kind: 'authenticated-cloudly-legacy-deployment-settlement-check-result';
|
|
322
|
+
authority: ICloudlyLegacyDeploymentSettlementAuthorityReferenceV1;
|
|
323
|
+
payload: TCloudlyLegacyDeploymentSettlementCheckResultV1;
|
|
324
|
+
payloadSha256: string;
|
|
325
|
+
mac: string;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
export interface IAuthenticatedCloudlyLegacyDeploymentSettlementApplyResultV1 {
|
|
329
|
+
schemaVersion: 1;
|
|
330
|
+
kind: 'authenticated-cloudly-legacy-deployment-settlement-apply-result';
|
|
331
|
+
authority: ICloudlyLegacyDeploymentSettlementAuthorityReferenceV1;
|
|
332
|
+
payload: TCloudlyLegacyDeploymentSettlementApplyResultV1;
|
|
333
|
+
payloadSha256: string;
|
|
334
|
+
mac: string;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
export interface IAuthenticatedCloudlyLegacyDeploymentSettlementStableOutcomeV1 {
|
|
338
|
+
schemaVersion: 1;
|
|
339
|
+
kind: 'authenticated-cloudly-legacy-deployment-settlement-stable-outcome';
|
|
340
|
+
authority: ICloudlyLegacyDeploymentSettlementAuthorityReferenceV1;
|
|
341
|
+
payload: ICloudlyLegacyDeploymentSettlementStableOutcomeV1;
|
|
342
|
+
payloadSha256: string;
|
|
343
|
+
mac: string;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
export type TUnsignedAuthenticatedCloudlyLegacyDeploymentSettlementRehearsalBindingV1 =
|
|
347
|
+
Omit<IAuthenticatedCloudlyLegacyDeploymentSettlementRehearsalBindingV1, 'mac'>;
|
|
348
|
+
export type TUnsignedAuthenticatedCloudlyLegacyDeploymentSettlementPlanV1 =
|
|
349
|
+
Omit<IAuthenticatedCloudlyLegacyDeploymentSettlementPlanV1, 'mac'>;
|
|
350
|
+
export type TUnsignedAuthenticatedCloudlyLegacyDeploymentSettlementProductionRequestV1 =
|
|
351
|
+
Omit<IAuthenticatedCloudlyLegacyDeploymentSettlementProductionRequestV1, 'mac'>;
|
|
352
|
+
export type TUnsignedAuthenticatedCloudlyLegacyDeploymentSettlementCheckResultV1 =
|
|
353
|
+
Omit<IAuthenticatedCloudlyLegacyDeploymentSettlementCheckResultV1, 'mac'>;
|
|
354
|
+
export type TUnsignedAuthenticatedCloudlyLegacyDeploymentSettlementApplyResultV1 =
|
|
355
|
+
Omit<IAuthenticatedCloudlyLegacyDeploymentSettlementApplyResultV1, 'mac'>;
|
|
356
|
+
export type TUnsignedAuthenticatedCloudlyLegacyDeploymentSettlementStableOutcomeV1 =
|
|
357
|
+
Omit<IAuthenticatedCloudlyLegacyDeploymentSettlementStableOutcomeV1, 'mac'>;
|
|
358
|
+
|
|
359
|
+
export interface ICloudlyLegacyDeploymentSettlementHmacVerificationInputV1 {
|
|
360
|
+
authority: ICloudlyLegacyDeploymentSettlementAuthorityReferenceV1;
|
|
361
|
+
domain: typeof cloudlyLegacyDeploymentSettlementDomains[keyof
|
|
362
|
+
typeof cloudlyLegacyDeploymentSettlementDomains];
|
|
363
|
+
hmacInput: Uint8Array;
|
|
364
|
+
mac: string;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/** Consumer-owned verification keeps all HMAC key use outside Interfaces. */
|
|
368
|
+
export type TCloudlyLegacyDeploymentSettlementHmacVerifier = (
|
|
369
|
+
inputArg: ICloudlyLegacyDeploymentSettlementHmacVerificationInputV1,
|
|
370
|
+
) => boolean | Promise<boolean>;
|
|
371
|
+
|
|
372
|
+
export interface ICloudlyLegacyDeploymentSettlementScratchReceiptV1 {
|
|
373
|
+
schemaVersion: 1;
|
|
374
|
+
kind: 'cloudly-legacy-deployment-settlement-scratch-receipt';
|
|
375
|
+
authority: ICloudlyLegacyDeploymentSettlementAuthorityReferenceV1;
|
|
376
|
+
requestSha256: string;
|
|
377
|
+
stableOutcome: ICloudlyLegacyDeploymentSettlementStableOutcomeV1;
|
|
378
|
+
stableOutcomeSha256: string;
|
|
379
|
+
transactionCommitted: true;
|
|
380
|
+
disposition: 'applied' | 'exact-replay' | 'no-op';
|
|
381
|
+
completedAt: number;
|
|
382
|
+
payloadSha256: string;
|
|
383
|
+
mac: string;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
export interface ICloudlyLegacyDeploymentSettlementProductionReceiptV1 {
|
|
387
|
+
schemaVersion: 1;
|
|
388
|
+
kind: 'cloudly-legacy-deployment-settlement-production-receipt';
|
|
389
|
+
authority: ICloudlyLegacyDeploymentSettlementAuthorityReferenceV1;
|
|
390
|
+
requestSha256: string;
|
|
391
|
+
scratchReceipt: ICloudlyLegacyDeploymentSettlementScratchReceiptV1;
|
|
392
|
+
scratchReceiptSha256: string;
|
|
393
|
+
stableOutcome: ICloudlyLegacyDeploymentSettlementStableOutcomeV1;
|
|
394
|
+
stableOutcomeSha256: string;
|
|
395
|
+
transactionCommitted: true;
|
|
396
|
+
disposition: 'applied' | 'exact-replay' | 'no-op';
|
|
397
|
+
completedAt: number;
|
|
398
|
+
payloadSha256: string;
|
|
399
|
+
mac: string;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
export type TCloudlyLegacyDeploymentSettlementScratchReceiptPayloadV1 = Omit<
|
|
403
|
+
ICloudlyLegacyDeploymentSettlementScratchReceiptV1,
|
|
404
|
+
'payloadSha256' | 'mac'
|
|
405
|
+
>;
|
|
406
|
+
export type TCloudlyLegacyDeploymentSettlementUnsignedScratchReceiptV1 = Omit<
|
|
407
|
+
ICloudlyLegacyDeploymentSettlementScratchReceiptV1,
|
|
408
|
+
'mac'
|
|
409
|
+
>;
|
|
410
|
+
export type TCloudlyLegacyDeploymentSettlementProductionReceiptPayloadV1 = Omit<
|
|
411
|
+
ICloudlyLegacyDeploymentSettlementProductionReceiptV1,
|
|
412
|
+
'payloadSha256' | 'mac'
|
|
413
|
+
>;
|
|
414
|
+
export type TCloudlyLegacyDeploymentSettlementUnsignedProductionReceiptV1 = Omit<
|
|
415
|
+
ICloudlyLegacyDeploymentSettlementProductionReceiptV1,
|
|
416
|
+
'mac'
|
|
417
|
+
>;
|
|
418
|
+
|
|
419
|
+
const authorityCoreKeys = ['operationId', 'authorityId', 'keyId', 'keyVersion'] as const;
|
|
420
|
+
const authorityReferenceKeys = [...authorityCoreKeys, 'authorityMetadataSha256'] as const;
|
|
421
|
+
const authorityMetadataKeys = [
|
|
422
|
+
'schemaVersion',
|
|
423
|
+
...authorityCoreKeys,
|
|
424
|
+
'settlementId',
|
|
425
|
+
'issuedAt',
|
|
426
|
+
'expiresAt',
|
|
427
|
+
'maintenanceImageDigest',
|
|
428
|
+
'sourceImageDigest',
|
|
429
|
+
'targetImageDigest',
|
|
430
|
+
'targetVersion',
|
|
431
|
+
'targetManifestSha256',
|
|
432
|
+
'targetConfigSha256',
|
|
433
|
+
'backupId',
|
|
434
|
+
'backupSnapshotIdSha256',
|
|
435
|
+
'backupProofSha256',
|
|
436
|
+
'runId',
|
|
437
|
+
'rehearsalId',
|
|
438
|
+
'scratchServiceId',
|
|
439
|
+
'allocationId',
|
|
440
|
+
'allocationGeneration',
|
|
441
|
+
'allocationBindingSha256',
|
|
442
|
+
'allocationReceiptSha256',
|
|
443
|
+
'sourceDataSha256',
|
|
444
|
+
'restoredDataSha256',
|
|
445
|
+
'digestProofSha256',
|
|
446
|
+
] as const;
|
|
447
|
+
const classificationKeys = [
|
|
448
|
+
'image-recorded-not-current',
|
|
449
|
+
'image-recorded-current-failed',
|
|
450
|
+
'rolling-out-current-failed',
|
|
451
|
+
'rolling-out-superseded',
|
|
452
|
+
] as const;
|
|
453
|
+
const censusKeys = [
|
|
454
|
+
'operations',
|
|
455
|
+
'services',
|
|
456
|
+
'images',
|
|
457
|
+
'releases',
|
|
458
|
+
'rolloutOperations',
|
|
459
|
+
'routeClaims',
|
|
460
|
+
'resourceClaims',
|
|
461
|
+
] as const;
|
|
462
|
+
const mutationCountKeys = [
|
|
463
|
+
'operationCount',
|
|
464
|
+
'routeClaimsStabilized',
|
|
465
|
+
'routeClaimsRemoved',
|
|
466
|
+
'resourceClaimsRemoved',
|
|
467
|
+
] as const;
|
|
468
|
+
const planEntryKeys = [
|
|
469
|
+
'operationId',
|
|
470
|
+
'serviceId',
|
|
471
|
+
'sourceRevision',
|
|
472
|
+
'sourceState',
|
|
473
|
+
'classification',
|
|
474
|
+
'finalRevision',
|
|
475
|
+
'sourceDocumentHmac',
|
|
476
|
+
'finalDocumentHmac',
|
|
477
|
+
'routeClaimsStabilized',
|
|
478
|
+
'routeClaimsRemoved',
|
|
479
|
+
'resourceClaimsRemoved',
|
|
480
|
+
] as const;
|
|
481
|
+
const failureReasons = new Set<TCloudlyLegacyDeploymentSettlementFailureReason>([
|
|
482
|
+
'AUTHORITY_INVALID',
|
|
483
|
+
'AUTHORITY_EXPIRED',
|
|
484
|
+
'REQUEST_MISMATCH',
|
|
485
|
+
'PLAN_MISMATCH',
|
|
486
|
+
'SOURCE_STATE_MISMATCH',
|
|
487
|
+
'FINAL_STATE_MISMATCH',
|
|
488
|
+
'TRANSACTIONS_UNSUPPORTED',
|
|
489
|
+
'OPERATION_DRIFT',
|
|
490
|
+
'CLAIM_DRIFT',
|
|
491
|
+
'CLASSIFICATION_MISMATCH',
|
|
492
|
+
]);
|
|
493
|
+
const identifierPattern = /^[A-Za-z0-9][A-Za-z0-9:._@-]{0,199}$/;
|
|
494
|
+
const sha256Pattern = /^[a-f0-9]{64}$/;
|
|
495
|
+
const ociDigestPattern = /^sha256:[a-f0-9]{64}$/;
|
|
496
|
+
const stateHmacPattern = /^hmac-sha256:[a-f0-9]{64}$/;
|
|
497
|
+
const macPattern = /^[A-Za-z0-9_-]{42}[AEIMQUYcgkosw048]$/;
|
|
498
|
+
const raw32ByteBase64UrlPattern = /^[A-Za-z0-9_-]{42}[AEIMQUYcgkosw048]$/;
|
|
499
|
+
|
|
500
|
+
const fail = (
|
|
501
|
+
codeArg: TCloudlyLegacyDeploymentSettlementCodecErrorCode,
|
|
502
|
+
pathArg: string,
|
|
503
|
+
): never => {
|
|
504
|
+
throw new CloudlyLegacyDeploymentSettlementCodecError(codeArg, pathArg);
|
|
505
|
+
};
|
|
506
|
+
|
|
507
|
+
const readRecord = (valueArg: unknown, pathArg: string): Record<string, unknown> => {
|
|
508
|
+
if (!valueArg || typeof valueArg !== 'object' || Array.isArray(valueArg)) {
|
|
509
|
+
return fail('INVALID_DATA', pathArg);
|
|
510
|
+
}
|
|
511
|
+
const prototype = Object.getPrototypeOf(valueArg);
|
|
512
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
513
|
+
return fail('INVALID_DATA', pathArg);
|
|
514
|
+
}
|
|
515
|
+
const record = valueArg as Record<string, unknown>;
|
|
516
|
+
for (const key of Reflect.ownKeys(record)) {
|
|
517
|
+
if (typeof key !== 'string') return fail('INVALID_DATA', pathArg);
|
|
518
|
+
const descriptor = Object.getOwnPropertyDescriptor(record, key);
|
|
519
|
+
if (!descriptor || !descriptor.enumerable || !Object.hasOwn(descriptor, 'value')) {
|
|
520
|
+
return fail('INVALID_DATA', pathArg);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
return record;
|
|
524
|
+
};
|
|
525
|
+
|
|
526
|
+
const readArray = (
|
|
527
|
+
valueArg: unknown,
|
|
528
|
+
pathArg: string,
|
|
529
|
+
maximumLengthArg: number,
|
|
530
|
+
minimumLengthArg = 0,
|
|
531
|
+
): unknown[] => {
|
|
532
|
+
if (!Array.isArray(valueArg) || Object.getPrototypeOf(valueArg) !== Array.prototype) {
|
|
533
|
+
return fail('INVALID_DATA', pathArg);
|
|
534
|
+
}
|
|
535
|
+
if (valueArg.length < minimumLengthArg || valueArg.length > maximumLengthArg) {
|
|
536
|
+
return fail('LIMIT_EXCEEDED', pathArg);
|
|
537
|
+
}
|
|
538
|
+
for (let index = 0; index < valueArg.length; index++) {
|
|
539
|
+
if (!Object.hasOwn(valueArg, index)) return fail('INVALID_DATA', `${pathArg}[${index}]`);
|
|
540
|
+
const descriptor = Object.getOwnPropertyDescriptor(valueArg, String(index));
|
|
541
|
+
if (!descriptor || !descriptor.enumerable || !Object.hasOwn(descriptor, 'value')) {
|
|
542
|
+
return fail('INVALID_DATA', `${pathArg}[${index}]`);
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
for (const key of Reflect.ownKeys(valueArg)) {
|
|
546
|
+
if (key === 'length') continue;
|
|
547
|
+
if (typeof key !== 'string'
|
|
548
|
+
|| !/^(?:0|[1-9][0-9]*)$/.test(key)
|
|
549
|
+
|| Number(key) >= valueArg.length) {
|
|
550
|
+
return fail('INVALID_DATA', pathArg);
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
return valueArg;
|
|
554
|
+
};
|
|
555
|
+
|
|
556
|
+
const assertExactKeys = (
|
|
557
|
+
valueArg: Record<string, unknown>,
|
|
558
|
+
keysArg: readonly string[],
|
|
559
|
+
pathArg: string,
|
|
560
|
+
): void => {
|
|
561
|
+
const actual = Object.keys(valueArg).sort((leftArg, rightArg) => (
|
|
562
|
+
leftArg < rightArg ? -1 : leftArg > rightArg ? 1 : 0
|
|
563
|
+
));
|
|
564
|
+
const expected = [...keysArg].sort((leftArg, rightArg) => (
|
|
565
|
+
leftArg < rightArg ? -1 : leftArg > rightArg ? 1 : 0
|
|
566
|
+
));
|
|
567
|
+
if (actual.length !== expected.length
|
|
568
|
+
|| actual.some((keyArg, indexArg) => keyArg !== expected[indexArg])) {
|
|
569
|
+
fail('INVALID_SCHEMA', pathArg);
|
|
570
|
+
}
|
|
571
|
+
};
|
|
572
|
+
|
|
573
|
+
const readIdentifier = (valueArg: unknown, pathArg: string): string => {
|
|
574
|
+
if (typeof valueArg !== 'string' || !identifierPattern.test(valueArg)) {
|
|
575
|
+
return fail('INVALID_VALUE', pathArg);
|
|
576
|
+
}
|
|
577
|
+
return valueArg;
|
|
578
|
+
};
|
|
579
|
+
|
|
580
|
+
const readSha256 = (valueArg: unknown, pathArg: string): string => {
|
|
581
|
+
if (typeof valueArg !== 'string' || !sha256Pattern.test(valueArg)) {
|
|
582
|
+
return fail('INVALID_VALUE', pathArg);
|
|
583
|
+
}
|
|
584
|
+
return valueArg;
|
|
585
|
+
};
|
|
586
|
+
|
|
587
|
+
const readOciDigest = (valueArg: unknown, pathArg: string): `sha256:${string}` => {
|
|
588
|
+
if (typeof valueArg !== 'string' || !ociDigestPattern.test(valueArg)) {
|
|
589
|
+
return fail('INVALID_VALUE', pathArg);
|
|
590
|
+
}
|
|
591
|
+
return valueArg as `sha256:${string}`;
|
|
592
|
+
};
|
|
593
|
+
|
|
594
|
+
const readStateHmac = (valueArg: unknown, pathArg: string): `hmac-sha256:${string}` => {
|
|
595
|
+
if (typeof valueArg !== 'string' || !stateHmacPattern.test(valueArg)) {
|
|
596
|
+
return fail('INVALID_VALUE', pathArg);
|
|
597
|
+
}
|
|
598
|
+
return valueArg as `hmac-sha256:${string}`;
|
|
599
|
+
};
|
|
600
|
+
|
|
601
|
+
const readMac = (valueArg: unknown, pathArg: string): string => {
|
|
602
|
+
if (typeof valueArg !== 'string' || !macPattern.test(valueArg)) {
|
|
603
|
+
return fail('INVALID_VALUE', pathArg);
|
|
604
|
+
}
|
|
605
|
+
const bytes = Buffer.from(valueArg, 'base64url');
|
|
606
|
+
if (bytes.byteLength !== 32 || bytes.toString('base64url') !== valueArg) {
|
|
607
|
+
return fail('INVALID_VALUE', pathArg);
|
|
608
|
+
}
|
|
609
|
+
return valueArg;
|
|
610
|
+
};
|
|
611
|
+
|
|
612
|
+
const readInteger = (
|
|
613
|
+
valueArg: unknown,
|
|
614
|
+
pathArg: string,
|
|
615
|
+
minimumArg = 0,
|
|
616
|
+
maximumArg = Number.MAX_SAFE_INTEGER,
|
|
617
|
+
): number => {
|
|
618
|
+
if (typeof valueArg !== 'number'
|
|
619
|
+
|| !Number.isSafeInteger(valueArg)
|
|
620
|
+
|| Object.is(valueArg, -0)
|
|
621
|
+
|| valueArg < minimumArg
|
|
622
|
+
|| valueArg > maximumArg) {
|
|
623
|
+
return fail('INVALID_VALUE', pathArg);
|
|
624
|
+
}
|
|
625
|
+
return valueArg;
|
|
626
|
+
};
|
|
627
|
+
|
|
628
|
+
const readBoolean = (valueArg: unknown, pathArg: string): boolean => {
|
|
629
|
+
if (typeof valueArg !== 'boolean') return fail('INVALID_VALUE', pathArg);
|
|
630
|
+
return valueArg;
|
|
631
|
+
};
|
|
632
|
+
|
|
633
|
+
const readLiteral = <TLiteral extends string>(
|
|
634
|
+
valueArg: unknown,
|
|
635
|
+
literalsArg: readonly TLiteral[],
|
|
636
|
+
pathArg: string,
|
|
637
|
+
): TLiteral => {
|
|
638
|
+
if (typeof valueArg !== 'string' || !literalsArg.includes(valueArg as TLiteral)) {
|
|
639
|
+
return fail('INVALID_VALUE', pathArg);
|
|
640
|
+
}
|
|
641
|
+
return valueArg as TLiteral;
|
|
642
|
+
};
|
|
643
|
+
|
|
644
|
+
const canonicalize = (valueArg: unknown, pathArg: string): string => (
|
|
645
|
+
canonicalizeStrictJson(
|
|
646
|
+
valueArg,
|
|
647
|
+
() => fail('INVALID_DATA', pathArg),
|
|
648
|
+
pathArg,
|
|
649
|
+
)
|
|
650
|
+
);
|
|
651
|
+
|
|
652
|
+
const finalize = <T>(
|
|
653
|
+
valueArg: T,
|
|
654
|
+
maximumBytesArg: number,
|
|
655
|
+
pathArg: string,
|
|
656
|
+
): Readonly<T> => {
|
|
657
|
+
const json = canonicalize(valueArg, pathArg);
|
|
658
|
+
if (Buffer.byteLength(json, 'utf8') > maximumBytesArg) {
|
|
659
|
+
return fail('LIMIT_EXCEEDED', pathArg);
|
|
660
|
+
}
|
|
661
|
+
return deepFreezeValue(valueArg);
|
|
662
|
+
};
|
|
663
|
+
|
|
664
|
+
const encodeNormalized = (valueArg: unknown, pathArg: string): Uint8Array => (
|
|
665
|
+
new Uint8Array(Buffer.from(canonicalize(valueArg, pathArg), 'utf8'))
|
|
666
|
+
);
|
|
667
|
+
|
|
668
|
+
const frame = (domainArg: string, payloadArg: Uint8Array): Uint8Array => {
|
|
669
|
+
const domain = Buffer.from(domainArg, 'utf8');
|
|
670
|
+
const output = new Uint8Array(domain.byteLength + payloadArg.byteLength);
|
|
671
|
+
output.set(domain, 0);
|
|
672
|
+
output.set(new Uint8Array(payloadArg), domain.byteLength);
|
|
673
|
+
return output;
|
|
674
|
+
};
|
|
675
|
+
|
|
676
|
+
const digestBytes = (valueArg: Uint8Array): string => (
|
|
677
|
+
plugins.crypto.createHash('sha256').update(new Uint8Array(valueArg)).digest('hex')
|
|
678
|
+
);
|
|
679
|
+
|
|
680
|
+
const normalizeAuthorityReferenceInternal = (
|
|
681
|
+
valueArg: unknown,
|
|
682
|
+
pathArg: string,
|
|
683
|
+
): ICloudlyLegacyDeploymentSettlementAuthorityReferenceV1 => {
|
|
684
|
+
const value = readRecord(valueArg, pathArg);
|
|
685
|
+
assertExactKeys(value, authorityReferenceKeys, pathArg);
|
|
686
|
+
if (value.keyVersion !== 1) fail('INVALID_VALUE', `${pathArg}.keyVersion`);
|
|
687
|
+
return {
|
|
688
|
+
operationId: readIdentifier(value.operationId, `${pathArg}.operationId`),
|
|
689
|
+
authorityId: readIdentifier(value.authorityId, `${pathArg}.authorityId`),
|
|
690
|
+
keyId: readIdentifier(value.keyId, `${pathArg}.keyId`),
|
|
691
|
+
keyVersion: 1,
|
|
692
|
+
authorityMetadataSha256: readSha256(
|
|
693
|
+
value.authorityMetadataSha256,
|
|
694
|
+
`${pathArg}.authorityMetadataSha256`,
|
|
695
|
+
),
|
|
696
|
+
};
|
|
697
|
+
};
|
|
698
|
+
|
|
699
|
+
export const normalizeCloudlyLegacyDeploymentSettlementAuthorityReference = (
|
|
700
|
+
valueArg: unknown,
|
|
701
|
+
): Readonly<ICloudlyLegacyDeploymentSettlementAuthorityReferenceV1> => finalize(
|
|
702
|
+
normalizeAuthorityReferenceInternal(valueArg, 'authorityReference'),
|
|
703
|
+
cloudlyLegacyDeploymentSettlementLimits.maximumAuthorityBytes,
|
|
704
|
+
'authorityReference',
|
|
705
|
+
);
|
|
706
|
+
|
|
707
|
+
const normalizeAuthorityMetadataInternal = (
|
|
708
|
+
valueArg: unknown,
|
|
709
|
+
pathArg: string,
|
|
710
|
+
): ICloudlyLegacyDeploymentSettlementAuthorityMetadataV1 => {
|
|
711
|
+
const value = readRecord(valueArg, pathArg);
|
|
712
|
+
assertExactKeys(value, authorityMetadataKeys, pathArg);
|
|
713
|
+
if (value.schemaVersion !== 1 || value.keyVersion !== 1) {
|
|
714
|
+
fail('INVALID_VALUE', `${pathArg}.schemaVersion`);
|
|
715
|
+
}
|
|
716
|
+
const issuedAt = readInteger(value.issuedAt, `${pathArg}.issuedAt`, 1);
|
|
717
|
+
const expiresAt = readInteger(value.expiresAt, `${pathArg}.expiresAt`, 1);
|
|
718
|
+
if (expiresAt <= issuedAt
|
|
719
|
+
|| expiresAt - issuedAt
|
|
720
|
+
> cloudlyLegacyDeploymentSettlementLimits.maximumAuthorityLifetimeMs) {
|
|
721
|
+
fail('CROSS_FIELD_MISMATCH', `${pathArg}.expiresAt`);
|
|
722
|
+
}
|
|
723
|
+
const sourceDataSha256 = readSha256(
|
|
724
|
+
value.sourceDataSha256,
|
|
725
|
+
`${pathArg}.sourceDataSha256`,
|
|
726
|
+
);
|
|
727
|
+
const restoredDataSha256 = readSha256(
|
|
728
|
+
value.restoredDataSha256,
|
|
729
|
+
`${pathArg}.restoredDataSha256`,
|
|
730
|
+
);
|
|
731
|
+
if (sourceDataSha256 !== restoredDataSha256) {
|
|
732
|
+
fail('CROSS_FIELD_MISMATCH', `${pathArg}.restoredDataSha256`);
|
|
733
|
+
}
|
|
734
|
+
return {
|
|
735
|
+
schemaVersion: 1,
|
|
736
|
+
operationId: readIdentifier(value.operationId, `${pathArg}.operationId`),
|
|
737
|
+
authorityId: readIdentifier(value.authorityId, `${pathArg}.authorityId`),
|
|
738
|
+
keyId: readIdentifier(value.keyId, `${pathArg}.keyId`),
|
|
739
|
+
keyVersion: 1,
|
|
740
|
+
settlementId: readIdentifier(value.settlementId, `${pathArg}.settlementId`),
|
|
741
|
+
issuedAt,
|
|
742
|
+
expiresAt,
|
|
743
|
+
maintenanceImageDigest: readOciDigest(
|
|
744
|
+
value.maintenanceImageDigest,
|
|
745
|
+
`${pathArg}.maintenanceImageDigest`,
|
|
746
|
+
),
|
|
747
|
+
sourceImageDigest: readOciDigest(value.sourceImageDigest, `${pathArg}.sourceImageDigest`),
|
|
748
|
+
targetImageDigest: readOciDigest(value.targetImageDigest, `${pathArg}.targetImageDigest`),
|
|
749
|
+
targetVersion: readIdentifier(value.targetVersion, `${pathArg}.targetVersion`),
|
|
750
|
+
targetManifestSha256: readSha256(
|
|
751
|
+
value.targetManifestSha256,
|
|
752
|
+
`${pathArg}.targetManifestSha256`,
|
|
753
|
+
),
|
|
754
|
+
targetConfigSha256: readSha256(value.targetConfigSha256, `${pathArg}.targetConfigSha256`),
|
|
755
|
+
backupId: readIdentifier(value.backupId, `${pathArg}.backupId`),
|
|
756
|
+
backupSnapshotIdSha256: readSha256(
|
|
757
|
+
value.backupSnapshotIdSha256,
|
|
758
|
+
`${pathArg}.backupSnapshotIdSha256`,
|
|
759
|
+
),
|
|
760
|
+
backupProofSha256: readSha256(value.backupProofSha256, `${pathArg}.backupProofSha256`),
|
|
761
|
+
runId: readIdentifier(value.runId, `${pathArg}.runId`),
|
|
762
|
+
rehearsalId: readIdentifier(value.rehearsalId, `${pathArg}.rehearsalId`),
|
|
763
|
+
scratchServiceId: readIdentifier(value.scratchServiceId, `${pathArg}.scratchServiceId`),
|
|
764
|
+
allocationId: readIdentifier(value.allocationId, `${pathArg}.allocationId`),
|
|
765
|
+
allocationGeneration: readInteger(
|
|
766
|
+
value.allocationGeneration,
|
|
767
|
+
`${pathArg}.allocationGeneration`,
|
|
768
|
+
1,
|
|
769
|
+
),
|
|
770
|
+
allocationBindingSha256: readSha256(
|
|
771
|
+
value.allocationBindingSha256,
|
|
772
|
+
`${pathArg}.allocationBindingSha256`,
|
|
773
|
+
),
|
|
774
|
+
allocationReceiptSha256: readSha256(
|
|
775
|
+
value.allocationReceiptSha256,
|
|
776
|
+
`${pathArg}.allocationReceiptSha256`,
|
|
777
|
+
),
|
|
778
|
+
sourceDataSha256,
|
|
779
|
+
restoredDataSha256,
|
|
780
|
+
digestProofSha256: readSha256(value.digestProofSha256, `${pathArg}.digestProofSha256`),
|
|
781
|
+
};
|
|
782
|
+
};
|
|
783
|
+
|
|
784
|
+
export const normalizeCloudlyLegacyDeploymentSettlementAuthorityMetadata = (
|
|
785
|
+
valueArg: unknown,
|
|
786
|
+
): Readonly<ICloudlyLegacyDeploymentSettlementAuthorityMetadataV1> => finalize(
|
|
787
|
+
normalizeAuthorityMetadataInternal(valueArg, 'authorityMetadata'),
|
|
788
|
+
cloudlyLegacyDeploymentSettlementLimits.maximumAuthorityBytes,
|
|
789
|
+
'authorityMetadata',
|
|
790
|
+
);
|
|
791
|
+
|
|
792
|
+
export const encodeCloudlyLegacyDeploymentSettlementAuthorityMetadata = (
|
|
793
|
+
valueArg: unknown,
|
|
794
|
+
): Uint8Array => encodeNormalized(
|
|
795
|
+
normalizeCloudlyLegacyDeploymentSettlementAuthorityMetadata(valueArg),
|
|
796
|
+
'authorityMetadata',
|
|
797
|
+
);
|
|
798
|
+
|
|
799
|
+
export const encodeCloudlyLegacyDeploymentSettlementAuthorityMetadataAad = (
|
|
800
|
+
valueArg: unknown,
|
|
801
|
+
): Uint8Array => frame(
|
|
802
|
+
cloudlyLegacyDeploymentSettlementDomains.authorityAad,
|
|
803
|
+
encodeCloudlyLegacyDeploymentSettlementAuthorityMetadata(valueArg),
|
|
804
|
+
);
|
|
805
|
+
|
|
806
|
+
export const digestCloudlyLegacyDeploymentSettlementAuthorityMetadata = (
|
|
807
|
+
valueArg: unknown,
|
|
808
|
+
): string => digestBytes(encodeCloudlyLegacyDeploymentSettlementAuthorityMetadata(valueArg));
|
|
809
|
+
|
|
810
|
+
export const createCloudlyLegacyDeploymentSettlementAuthorityReference = (
|
|
811
|
+
metadataArg: unknown,
|
|
812
|
+
): Readonly<ICloudlyLegacyDeploymentSettlementAuthorityReferenceV1> => {
|
|
813
|
+
const metadata = normalizeCloudlyLegacyDeploymentSettlementAuthorityMetadata(metadataArg);
|
|
814
|
+
return finalize({
|
|
815
|
+
operationId: metadata.operationId,
|
|
816
|
+
authorityId: metadata.authorityId,
|
|
817
|
+
keyId: metadata.keyId,
|
|
818
|
+
keyVersion: metadata.keyVersion,
|
|
819
|
+
authorityMetadataSha256:
|
|
820
|
+
digestCloudlyLegacyDeploymentSettlementAuthorityMetadata(metadata),
|
|
821
|
+
}, cloudlyLegacyDeploymentSettlementLimits.maximumAuthorityBytes, 'authorityReference');
|
|
822
|
+
};
|
|
823
|
+
|
|
824
|
+
export const normalizeCloudlyLegacyDeploymentSettlementAuthorityReferenceForMetadata = (
|
|
825
|
+
referenceArg: unknown,
|
|
826
|
+
metadataArg: unknown,
|
|
827
|
+
): Readonly<ICloudlyLegacyDeploymentSettlementAuthorityReferenceV1> => {
|
|
828
|
+
const reference = normalizeCloudlyLegacyDeploymentSettlementAuthorityReference(referenceArg);
|
|
829
|
+
const expected = createCloudlyLegacyDeploymentSettlementAuthorityReference(metadataArg);
|
|
830
|
+
if (canonicalize(reference, 'authorityReference')
|
|
831
|
+
!== canonicalize(expected, 'authorityReference.expected')) {
|
|
832
|
+
fail('CROSS_FIELD_MISMATCH', 'authorityReference');
|
|
833
|
+
}
|
|
834
|
+
return reference;
|
|
835
|
+
};
|
|
836
|
+
|
|
837
|
+
export const normalizeCloudlyLegacyDeploymentSettlementAuthorityHandoffPlaintext = (
|
|
838
|
+
valueArg: unknown,
|
|
839
|
+
): Readonly<ICloudlyLegacyDeploymentSettlementAuthorityHandoffPlaintextV1> => {
|
|
840
|
+
const value = readRecord(valueArg, 'authorityHandoffPlaintext');
|
|
841
|
+
assertExactKeys(value, [
|
|
842
|
+
'schemaVersion',
|
|
843
|
+
'kind',
|
|
844
|
+
'authorityMetadata',
|
|
845
|
+
'authorityReference',
|
|
846
|
+
'hmacKeyPlaintext',
|
|
847
|
+
], 'authorityHandoffPlaintext');
|
|
848
|
+
if (value.schemaVersion !== 1
|
|
849
|
+
|| value.kind
|
|
850
|
+
!== 'cloudly-legacy-deployment-settlement-authority-handoff-plaintext') {
|
|
851
|
+
fail('INVALID_VALUE', 'authorityHandoffPlaintext.kind');
|
|
852
|
+
}
|
|
853
|
+
const authorityMetadata = normalizeAuthorityMetadataInternal(
|
|
854
|
+
value.authorityMetadata,
|
|
855
|
+
'authorityHandoffPlaintext.authorityMetadata',
|
|
856
|
+
);
|
|
857
|
+
const authorityReference = normalizeCloudlyLegacyDeploymentSettlementAuthorityReferenceForMetadata(
|
|
858
|
+
value.authorityReference,
|
|
859
|
+
authorityMetadata,
|
|
860
|
+
);
|
|
861
|
+
const key = readRecord(
|
|
862
|
+
value.hmacKeyPlaintext,
|
|
863
|
+
'authorityHandoffPlaintext.hmacKeyPlaintext',
|
|
864
|
+
);
|
|
865
|
+
assertExactKeys(
|
|
866
|
+
key,
|
|
867
|
+
['format', 'value'],
|
|
868
|
+
'authorityHandoffPlaintext.hmacKeyPlaintext',
|
|
869
|
+
);
|
|
870
|
+
const keyValue = typeof key.value === 'string'
|
|
871
|
+
? key.value
|
|
872
|
+
: fail('INVALID_VALUE', 'authorityHandoffPlaintext.hmacKeyPlaintext.value');
|
|
873
|
+
if (key.format !== 'raw-32-byte-base64url'
|
|
874
|
+
|| !raw32ByteBase64UrlPattern.test(keyValue)) {
|
|
875
|
+
fail('INVALID_VALUE', 'authorityHandoffPlaintext.hmacKeyPlaintext');
|
|
876
|
+
}
|
|
877
|
+
const keyBytes = Buffer.from(keyValue, 'base64url');
|
|
878
|
+
if (keyBytes.byteLength !== 32 || keyBytes.toString('base64url') !== keyValue) {
|
|
879
|
+
fail('INVALID_VALUE', 'authorityHandoffPlaintext.hmacKeyPlaintext.value');
|
|
880
|
+
}
|
|
881
|
+
return finalize({
|
|
882
|
+
schemaVersion: 1,
|
|
883
|
+
kind: 'cloudly-legacy-deployment-settlement-authority-handoff-plaintext',
|
|
884
|
+
authorityMetadata,
|
|
885
|
+
authorityReference,
|
|
886
|
+
hmacKeyPlaintext: { format: 'raw-32-byte-base64url', value: keyValue },
|
|
887
|
+
}, cloudlyLegacyDeploymentSettlementLimits.maximumAuthorityBytes, 'authorityHandoffPlaintext');
|
|
888
|
+
};
|
|
889
|
+
|
|
890
|
+
export const encodeCloudlyLegacyDeploymentSettlementAuthorityHandoffPlaintext = (
|
|
891
|
+
valueArg: unknown,
|
|
892
|
+
): Uint8Array => encodeNormalized(
|
|
893
|
+
normalizeCloudlyLegacyDeploymentSettlementAuthorityHandoffPlaintext(valueArg),
|
|
894
|
+
'authorityHandoffPlaintext',
|
|
895
|
+
);
|
|
896
|
+
|
|
897
|
+
const normalizeClassificationCounts = (
|
|
898
|
+
valueArg: unknown,
|
|
899
|
+
pathArg: string,
|
|
900
|
+
): ICloudlyLegacyDeploymentSettlementClassificationCountsV1 => {
|
|
901
|
+
const value = readRecord(valueArg, pathArg);
|
|
902
|
+
assertExactKeys(value, classificationKeys, pathArg);
|
|
903
|
+
return {
|
|
904
|
+
'image-recorded-not-current': readInteger(
|
|
905
|
+
value['image-recorded-not-current'],
|
|
906
|
+
`${pathArg}.image-recorded-not-current`,
|
|
907
|
+
0,
|
|
908
|
+
cloudlyLegacyDeploymentSettlementLimits.maximumOperations,
|
|
909
|
+
),
|
|
910
|
+
'image-recorded-current-failed': readInteger(
|
|
911
|
+
value['image-recorded-current-failed'],
|
|
912
|
+
`${pathArg}.image-recorded-current-failed`,
|
|
913
|
+
0,
|
|
914
|
+
cloudlyLegacyDeploymentSettlementLimits.maximumOperations,
|
|
915
|
+
),
|
|
916
|
+
'rolling-out-current-failed': readInteger(
|
|
917
|
+
value['rolling-out-current-failed'],
|
|
918
|
+
`${pathArg}.rolling-out-current-failed`,
|
|
919
|
+
0,
|
|
920
|
+
cloudlyLegacyDeploymentSettlementLimits.maximumOperations,
|
|
921
|
+
),
|
|
922
|
+
'rolling-out-superseded': readInteger(
|
|
923
|
+
value['rolling-out-superseded'],
|
|
924
|
+
`${pathArg}.rolling-out-superseded`,
|
|
925
|
+
0,
|
|
926
|
+
cloudlyLegacyDeploymentSettlementLimits.maximumOperations,
|
|
927
|
+
),
|
|
928
|
+
};
|
|
929
|
+
};
|
|
930
|
+
|
|
931
|
+
const sumClassificationCounts = (
|
|
932
|
+
valueArg: ICloudlyLegacyDeploymentSettlementClassificationCountsV1,
|
|
933
|
+
): number => classificationKeys.reduce((sumArg, keyArg) => sumArg + valueArg[keyArg], 0);
|
|
934
|
+
|
|
935
|
+
const normalizeSourceCensus = (
|
|
936
|
+
valueArg: unknown,
|
|
937
|
+
pathArg: string,
|
|
938
|
+
): ICloudlyLegacyDeploymentSettlementSourceCensusV1 => {
|
|
939
|
+
const value = readRecord(valueArg, pathArg);
|
|
940
|
+
assertExactKeys(value, censusKeys, pathArg);
|
|
941
|
+
const output = Object.fromEntries(censusKeys.map((keyArg) => [
|
|
942
|
+
keyArg,
|
|
943
|
+
readInteger(
|
|
944
|
+
value[keyArg],
|
|
945
|
+
`${pathArg}.${keyArg}`,
|
|
946
|
+
0,
|
|
947
|
+
cloudlyLegacyDeploymentSettlementLimits.maximumSourceDocuments,
|
|
948
|
+
),
|
|
949
|
+
])) as unknown as ICloudlyLegacyDeploymentSettlementSourceCensusV1;
|
|
950
|
+
if (censusKeys.reduce((sumArg, keyArg) => sumArg + output[keyArg], 0)
|
|
951
|
+
> cloudlyLegacyDeploymentSettlementLimits.maximumSourceDocuments) {
|
|
952
|
+
fail('LIMIT_EXCEEDED', pathArg);
|
|
953
|
+
}
|
|
954
|
+
return output;
|
|
955
|
+
};
|
|
956
|
+
|
|
957
|
+
const normalizeMutationCounts = (
|
|
958
|
+
valueArg: unknown,
|
|
959
|
+
pathArg: string,
|
|
960
|
+
): ICloudlyLegacyDeploymentSettlementMutationCountsV1 => {
|
|
961
|
+
const value = readRecord(valueArg, pathArg);
|
|
962
|
+
assertExactKeys(value, mutationCountKeys, pathArg);
|
|
963
|
+
return {
|
|
964
|
+
operationCount: readInteger(
|
|
965
|
+
value.operationCount,
|
|
966
|
+
`${pathArg}.operationCount`,
|
|
967
|
+
0,
|
|
968
|
+
cloudlyLegacyDeploymentSettlementLimits.maximumOperations,
|
|
969
|
+
),
|
|
970
|
+
routeClaimsStabilized: readInteger(value.routeClaimsStabilized, `${pathArg}.routeClaimsStabilized`),
|
|
971
|
+
routeClaimsRemoved: readInteger(value.routeClaimsRemoved, `${pathArg}.routeClaimsRemoved`),
|
|
972
|
+
resourceClaimsRemoved: readInteger(value.resourceClaimsRemoved, `${pathArg}.resourceClaimsRemoved`),
|
|
973
|
+
};
|
|
974
|
+
};
|
|
975
|
+
|
|
976
|
+
const assertCountsMatchClassifications = (
|
|
977
|
+
countsArg: ICloudlyLegacyDeploymentSettlementMutationCountsV1,
|
|
978
|
+
classificationsArg: ICloudlyLegacyDeploymentSettlementClassificationCountsV1,
|
|
979
|
+
pathArg: string,
|
|
980
|
+
): void => {
|
|
981
|
+
if (countsArg.operationCount !== sumClassificationCounts(classificationsArg)) {
|
|
982
|
+
fail('CROSS_FIELD_MISMATCH', pathArg);
|
|
983
|
+
}
|
|
984
|
+
};
|
|
985
|
+
|
|
986
|
+
const normalizePlanEntry = (
|
|
987
|
+
valueArg: unknown,
|
|
988
|
+
pathArg: string,
|
|
989
|
+
): ICloudlyLegacyDeploymentSettlementPlanEntryV1 => {
|
|
990
|
+
const value = readRecord(valueArg, pathArg);
|
|
991
|
+
assertExactKeys(value, planEntryKeys, pathArg);
|
|
992
|
+
const sourceRevision = readInteger(value.sourceRevision, `${pathArg}.sourceRevision`, 0);
|
|
993
|
+
const finalRevision = readInteger(value.finalRevision, `${pathArg}.finalRevision`, 0);
|
|
994
|
+
if (finalRevision !== sourceRevision + 3 || !Number.isSafeInteger(sourceRevision + 3)) {
|
|
995
|
+
fail('CROSS_FIELD_MISMATCH', `${pathArg}.finalRevision`);
|
|
996
|
+
}
|
|
997
|
+
const sourceState = readLiteral(
|
|
998
|
+
value.sourceState,
|
|
999
|
+
['image-recorded', 'rolling-out'],
|
|
1000
|
+
`${pathArg}.sourceState`,
|
|
1001
|
+
);
|
|
1002
|
+
const classification = readLiteral(
|
|
1003
|
+
value.classification,
|
|
1004
|
+
classificationKeys,
|
|
1005
|
+
`${pathArg}.classification`,
|
|
1006
|
+
);
|
|
1007
|
+
if ((classification.startsWith('image-recorded-') && sourceState !== 'image-recorded')
|
|
1008
|
+
|| (classification.startsWith('rolling-out-') && sourceState !== 'rolling-out')) {
|
|
1009
|
+
fail('CROSS_FIELD_MISMATCH', `${pathArg}.classification`);
|
|
1010
|
+
}
|
|
1011
|
+
return {
|
|
1012
|
+
operationId: readIdentifier(value.operationId, `${pathArg}.operationId`),
|
|
1013
|
+
serviceId: readIdentifier(value.serviceId, `${pathArg}.serviceId`),
|
|
1014
|
+
sourceRevision,
|
|
1015
|
+
sourceState,
|
|
1016
|
+
classification,
|
|
1017
|
+
finalRevision,
|
|
1018
|
+
sourceDocumentHmac: readStateHmac(value.sourceDocumentHmac, `${pathArg}.sourceDocumentHmac`),
|
|
1019
|
+
finalDocumentHmac: readStateHmac(value.finalDocumentHmac, `${pathArg}.finalDocumentHmac`),
|
|
1020
|
+
routeClaimsStabilized: readInteger(value.routeClaimsStabilized, `${pathArg}.routeClaimsStabilized`),
|
|
1021
|
+
routeClaimsRemoved: readInteger(value.routeClaimsRemoved, `${pathArg}.routeClaimsRemoved`),
|
|
1022
|
+
resourceClaimsRemoved: readInteger(value.resourceClaimsRemoved, `${pathArg}.resourceClaimsRemoved`),
|
|
1023
|
+
};
|
|
1024
|
+
};
|
|
1025
|
+
|
|
1026
|
+
export const normalizeCloudlyLegacyDeploymentSettlementPlan = (
|
|
1027
|
+
valueArg: unknown,
|
|
1028
|
+
): Readonly<ICloudlyLegacyDeploymentSettlementPlanV1> => {
|
|
1029
|
+
const value = readRecord(valueArg, 'plan');
|
|
1030
|
+
assertExactKeys(value, [
|
|
1031
|
+
'schemaVersion',
|
|
1032
|
+
'kind',
|
|
1033
|
+
'authority',
|
|
1034
|
+
'settlementId',
|
|
1035
|
+
'effectiveAt',
|
|
1036
|
+
'sourceStateHmac',
|
|
1037
|
+
'finalStateHmac',
|
|
1038
|
+
'sourceCensus',
|
|
1039
|
+
'entries',
|
|
1040
|
+
'classificationCounts',
|
|
1041
|
+
'operationCount',
|
|
1042
|
+
], 'plan');
|
|
1043
|
+
if (value.schemaVersion !== 1
|
|
1044
|
+
|| value.kind !== 'cloudly-legacy-deployment-settlement-plan') {
|
|
1045
|
+
fail('INVALID_VALUE', 'plan.kind');
|
|
1046
|
+
}
|
|
1047
|
+
const entries = readArray(
|
|
1048
|
+
value.entries,
|
|
1049
|
+
'plan.entries',
|
|
1050
|
+
cloudlyLegacyDeploymentSettlementLimits.maximumOperations,
|
|
1051
|
+
).map((entryArg, indexArg) => normalizePlanEntry(entryArg, `plan.entries[${indexArg}]`));
|
|
1052
|
+
for (let index = 1; index < entries.length; index++) {
|
|
1053
|
+
if (entries[index - 1].operationId >= entries[index].operationId) {
|
|
1054
|
+
fail('ORDERING_REQUIRED', `plan.entries[${index}].operationId`);
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
const classificationCounts = normalizeClassificationCounts(
|
|
1058
|
+
value.classificationCounts,
|
|
1059
|
+
'plan.classificationCounts',
|
|
1060
|
+
);
|
|
1061
|
+
const operationCount = readInteger(
|
|
1062
|
+
value.operationCount,
|
|
1063
|
+
'plan.operationCount',
|
|
1064
|
+
0,
|
|
1065
|
+
cloudlyLegacyDeploymentSettlementLimits.maximumOperations,
|
|
1066
|
+
);
|
|
1067
|
+
if (operationCount !== entries.length
|
|
1068
|
+
|| operationCount !== sumClassificationCounts(classificationCounts)) {
|
|
1069
|
+
fail('CROSS_FIELD_MISMATCH', 'plan.operationCount');
|
|
1070
|
+
}
|
|
1071
|
+
const actualCounts = Object.fromEntries(classificationKeys.map((keyArg) => [
|
|
1072
|
+
keyArg,
|
|
1073
|
+
entries.filter((entryArg) => entryArg.classification === keyArg).length,
|
|
1074
|
+
]));
|
|
1075
|
+
if (classificationKeys.some((keyArg) => actualCounts[keyArg] !== classificationCounts[keyArg])) {
|
|
1076
|
+
fail('CROSS_FIELD_MISMATCH', 'plan.classificationCounts');
|
|
1077
|
+
}
|
|
1078
|
+
return finalize({
|
|
1079
|
+
schemaVersion: 1,
|
|
1080
|
+
kind: 'cloudly-legacy-deployment-settlement-plan',
|
|
1081
|
+
authority: normalizeAuthorityReferenceInternal(value.authority, 'plan.authority'),
|
|
1082
|
+
settlementId: readIdentifier(value.settlementId, 'plan.settlementId'),
|
|
1083
|
+
effectiveAt: readInteger(value.effectiveAt, 'plan.effectiveAt', 1),
|
|
1084
|
+
sourceStateHmac: readStateHmac(value.sourceStateHmac, 'plan.sourceStateHmac'),
|
|
1085
|
+
finalStateHmac: readStateHmac(value.finalStateHmac, 'plan.finalStateHmac'),
|
|
1086
|
+
sourceCensus: normalizeSourceCensus(value.sourceCensus, 'plan.sourceCensus'),
|
|
1087
|
+
entries,
|
|
1088
|
+
classificationCounts,
|
|
1089
|
+
operationCount,
|
|
1090
|
+
}, cloudlyLegacyDeploymentSettlementLimits.maximumPlanBytes, 'plan');
|
|
1091
|
+
};
|
|
1092
|
+
|
|
1093
|
+
export const encodeCloudlyLegacyDeploymentSettlementPlan = (
|
|
1094
|
+
valueArg: unknown,
|
|
1095
|
+
): Uint8Array => encodeNormalized(normalizeCloudlyLegacyDeploymentSettlementPlan(valueArg), 'plan');
|
|
1096
|
+
|
|
1097
|
+
export const encodeCloudlyLegacyDeploymentSettlementPlanHmacInput = (
|
|
1098
|
+
valueArg: unknown,
|
|
1099
|
+
): Uint8Array => frame(
|
|
1100
|
+
cloudlyLegacyDeploymentSettlementDomains.planHmac,
|
|
1101
|
+
encodeNormalized(
|
|
1102
|
+
normalizeUnsignedAuthenticatedPlanInternal(valueArg, 'unsignedAuthenticatedPlan'),
|
|
1103
|
+
'unsignedAuthenticatedPlan',
|
|
1104
|
+
),
|
|
1105
|
+
);
|
|
1106
|
+
|
|
1107
|
+
export const digestCloudlyLegacyDeploymentSettlementPlan = (
|
|
1108
|
+
valueArg: unknown,
|
|
1109
|
+
): string => digestBytes(encodeCloudlyLegacyDeploymentSettlementPlan(valueArg));
|
|
1110
|
+
|
|
1111
|
+
const normalizeFailureReasons = (
|
|
1112
|
+
valueArg: unknown,
|
|
1113
|
+
pathArg: string,
|
|
1114
|
+
): TCloudlyLegacyDeploymentSettlementFailureReason[] => {
|
|
1115
|
+
const values = readArray(
|
|
1116
|
+
valueArg,
|
|
1117
|
+
pathArg,
|
|
1118
|
+
cloudlyLegacyDeploymentSettlementLimits.maximumFailureReasons,
|
|
1119
|
+
1,
|
|
1120
|
+
);
|
|
1121
|
+
const output = values.map((entryArg, indexArg) => {
|
|
1122
|
+
if (typeof entryArg !== 'string'
|
|
1123
|
+
|| !failureReasons.has(entryArg as TCloudlyLegacyDeploymentSettlementFailureReason)) {
|
|
1124
|
+
return fail('INVALID_VALUE', `${pathArg}[${indexArg}]`);
|
|
1125
|
+
}
|
|
1126
|
+
return entryArg as TCloudlyLegacyDeploymentSettlementFailureReason;
|
|
1127
|
+
});
|
|
1128
|
+
for (let index = 1; index < output.length; index++) {
|
|
1129
|
+
if (output[index - 1] >= output[index]) {
|
|
1130
|
+
fail('ORDERING_REQUIRED', `${pathArg}[${index}]`);
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
1133
|
+
return output;
|
|
1134
|
+
};
|
|
1135
|
+
|
|
1136
|
+
const normalizeSafeResultBase = (
|
|
1137
|
+
valueArg: Record<string, unknown>,
|
|
1138
|
+
pathArg: string,
|
|
1139
|
+
): Omit<ICloudlyLegacyDeploymentSettlementSafeResultBaseV1, 'schemaVersion'> => {
|
|
1140
|
+
const counts = normalizeMutationCounts(valueArg.counts, `${pathArg}.counts`);
|
|
1141
|
+
const classificationCounts = normalizeClassificationCounts(
|
|
1142
|
+
valueArg.classificationCounts,
|
|
1143
|
+
`${pathArg}.classificationCounts`,
|
|
1144
|
+
);
|
|
1145
|
+
assertCountsMatchClassifications(counts, classificationCounts, `${pathArg}.counts.operationCount`);
|
|
1146
|
+
return {
|
|
1147
|
+
requestSha256: readSha256(valueArg.requestSha256, `${pathArg}.requestSha256`),
|
|
1148
|
+
planSha256: readSha256(valueArg.planSha256, `${pathArg}.planSha256`),
|
|
1149
|
+
settlementId: readIdentifier(valueArg.settlementId, `${pathArg}.settlementId`),
|
|
1150
|
+
sourceStateHmac: readStateHmac(valueArg.sourceStateHmac, `${pathArg}.sourceStateHmac`),
|
|
1151
|
+
finalStateHmac: readStateHmac(valueArg.finalStateHmac, `${pathArg}.finalStateHmac`),
|
|
1152
|
+
transactionSupported: readBoolean(
|
|
1153
|
+
valueArg.transactionSupported,
|
|
1154
|
+
`${pathArg}.transactionSupported`,
|
|
1155
|
+
),
|
|
1156
|
+
counts,
|
|
1157
|
+
classificationCounts,
|
|
1158
|
+
};
|
|
1159
|
+
};
|
|
1160
|
+
|
|
1161
|
+
export const normalizeCloudlyLegacyDeploymentSettlementCheckResult = (
|
|
1162
|
+
valueArg: unknown,
|
|
1163
|
+
): Readonly<TCloudlyLegacyDeploymentSettlementCheckResultV1> => {
|
|
1164
|
+
const value = readRecord(valueArg, 'checkResult');
|
|
1165
|
+
const status = readLiteral(value.status, ['ready', 'blocked'], 'checkResult.status');
|
|
1166
|
+
assertExactKeys(value, [
|
|
1167
|
+
'schemaVersion',
|
|
1168
|
+
'kind',
|
|
1169
|
+
'status',
|
|
1170
|
+
'requestSha256',
|
|
1171
|
+
'planSha256',
|
|
1172
|
+
'settlementId',
|
|
1173
|
+
'sourceStateHmac',
|
|
1174
|
+
'finalStateHmac',
|
|
1175
|
+
'transactionSupported',
|
|
1176
|
+
'disposition',
|
|
1177
|
+
'counts',
|
|
1178
|
+
'classificationCounts',
|
|
1179
|
+
...(status === 'blocked' ? ['failureReasons'] : []),
|
|
1180
|
+
'checkedAt',
|
|
1181
|
+
], 'checkResult');
|
|
1182
|
+
if (value.schemaVersion !== 1
|
|
1183
|
+
|| value.kind !== 'cloudly-legacy-deployment-settlement-check-result') {
|
|
1184
|
+
fail('INVALID_VALUE', 'checkResult.kind');
|
|
1185
|
+
}
|
|
1186
|
+
const base = normalizeSafeResultBase(value, 'checkResult');
|
|
1187
|
+
const result: TCloudlyLegacyDeploymentSettlementCheckResultV1 = status === 'ready'
|
|
1188
|
+
? {
|
|
1189
|
+
schemaVersion: 1,
|
|
1190
|
+
kind: 'cloudly-legacy-deployment-settlement-check-result',
|
|
1191
|
+
status,
|
|
1192
|
+
...base,
|
|
1193
|
+
disposition: readLiteral(
|
|
1194
|
+
value.disposition,
|
|
1195
|
+
['unapplied', 'exact-replay', 'no-op'],
|
|
1196
|
+
'checkResult.disposition',
|
|
1197
|
+
),
|
|
1198
|
+
checkedAt: readInteger(value.checkedAt, 'checkResult.checkedAt', 1),
|
|
1199
|
+
}
|
|
1200
|
+
: {
|
|
1201
|
+
schemaVersion: 1,
|
|
1202
|
+
kind: 'cloudly-legacy-deployment-settlement-check-result',
|
|
1203
|
+
status,
|
|
1204
|
+
...base,
|
|
1205
|
+
disposition: readLiteral(value.disposition, ['unapplied'], 'checkResult.disposition'),
|
|
1206
|
+
failureReasons: normalizeFailureReasons(value.failureReasons, 'checkResult.failureReasons'),
|
|
1207
|
+
checkedAt: readInteger(value.checkedAt, 'checkResult.checkedAt', 1),
|
|
1208
|
+
};
|
|
1209
|
+
const transactionFailurePresent = result.status === 'blocked'
|
|
1210
|
+
&& result.failureReasons.includes('TRANSACTIONS_UNSUPPORTED');
|
|
1211
|
+
if ((result.status === 'ready' && !result.transactionSupported)
|
|
1212
|
+
|| (result.status === 'blocked'
|
|
1213
|
+
&& transactionFailurePresent === result.transactionSupported)) {
|
|
1214
|
+
fail('CROSS_FIELD_MISMATCH', 'checkResult.transactionSupported');
|
|
1215
|
+
}
|
|
1216
|
+
return finalize(
|
|
1217
|
+
result,
|
|
1218
|
+
cloudlyLegacyDeploymentSettlementLimits.maximumSafeResultBytes,
|
|
1219
|
+
'checkResult',
|
|
1220
|
+
);
|
|
1221
|
+
};
|
|
1222
|
+
|
|
1223
|
+
export const encodeCloudlyLegacyDeploymentSettlementCheckResult = (
|
|
1224
|
+
valueArg: unknown,
|
|
1225
|
+
): Uint8Array => encodeNormalized(
|
|
1226
|
+
normalizeCloudlyLegacyDeploymentSettlementCheckResult(valueArg),
|
|
1227
|
+
'checkResult',
|
|
1228
|
+
);
|
|
1229
|
+
|
|
1230
|
+
export const encodeCloudlyLegacyDeploymentSettlementCheckResultHmacInput = (
|
|
1231
|
+
valueArg: unknown,
|
|
1232
|
+
): Uint8Array => frame(
|
|
1233
|
+
cloudlyLegacyDeploymentSettlementDomains.checkResultHmac,
|
|
1234
|
+
encodeNormalized(
|
|
1235
|
+
normalizeUnsignedAuthenticatedCheckResultInternal(
|
|
1236
|
+
valueArg,
|
|
1237
|
+
'unsignedAuthenticatedCheckResult',
|
|
1238
|
+
),
|
|
1239
|
+
'unsignedAuthenticatedCheckResult',
|
|
1240
|
+
),
|
|
1241
|
+
);
|
|
1242
|
+
|
|
1243
|
+
export const digestCloudlyLegacyDeploymentSettlementCheckResult = (
|
|
1244
|
+
valueArg: unknown,
|
|
1245
|
+
): string => digestBytes(encodeCloudlyLegacyDeploymentSettlementCheckResult(valueArg));
|
|
1246
|
+
|
|
1247
|
+
export const normalizeCloudlyLegacyDeploymentSettlementApplyResult = (
|
|
1248
|
+
valueArg: unknown,
|
|
1249
|
+
): Readonly<TCloudlyLegacyDeploymentSettlementApplyResultV1> => {
|
|
1250
|
+
const value = readRecord(valueArg, 'applyResult');
|
|
1251
|
+
const status = readLiteral(value.status, ['completed', 'rejected'], 'applyResult.status');
|
|
1252
|
+
assertExactKeys(value, [
|
|
1253
|
+
'schemaVersion',
|
|
1254
|
+
'kind',
|
|
1255
|
+
'status',
|
|
1256
|
+
'requestSha256',
|
|
1257
|
+
'planSha256',
|
|
1258
|
+
'settlementId',
|
|
1259
|
+
'sourceStateHmac',
|
|
1260
|
+
'finalStateHmac',
|
|
1261
|
+
'transactionSupported',
|
|
1262
|
+
'disposition',
|
|
1263
|
+
'counts',
|
|
1264
|
+
'classificationCounts',
|
|
1265
|
+
...(status === 'rejected' ? ['failureReasons', 'rejectedAt'] : ['completedAt']),
|
|
1266
|
+
], 'applyResult');
|
|
1267
|
+
if (value.schemaVersion !== 1
|
|
1268
|
+
|| value.kind !== 'cloudly-legacy-deployment-settlement-apply-result') {
|
|
1269
|
+
fail('INVALID_VALUE', 'applyResult.kind');
|
|
1270
|
+
}
|
|
1271
|
+
const base = normalizeSafeResultBase(value, 'applyResult');
|
|
1272
|
+
const result: TCloudlyLegacyDeploymentSettlementApplyResultV1 = status === 'completed'
|
|
1273
|
+
? {
|
|
1274
|
+
schemaVersion: 1,
|
|
1275
|
+
kind: 'cloudly-legacy-deployment-settlement-apply-result',
|
|
1276
|
+
status,
|
|
1277
|
+
...base,
|
|
1278
|
+
disposition: readLiteral(
|
|
1279
|
+
value.disposition,
|
|
1280
|
+
['applied', 'exact-replay', 'no-op'],
|
|
1281
|
+
'applyResult.disposition',
|
|
1282
|
+
),
|
|
1283
|
+
completedAt: readInteger(value.completedAt, 'applyResult.completedAt', 1),
|
|
1284
|
+
}
|
|
1285
|
+
: {
|
|
1286
|
+
schemaVersion: 1,
|
|
1287
|
+
kind: 'cloudly-legacy-deployment-settlement-apply-result',
|
|
1288
|
+
status,
|
|
1289
|
+
...base,
|
|
1290
|
+
disposition: readLiteral(value.disposition, ['unapplied'], 'applyResult.disposition'),
|
|
1291
|
+
failureReasons: normalizeFailureReasons(value.failureReasons, 'applyResult.failureReasons'),
|
|
1292
|
+
rejectedAt: readInteger(value.rejectedAt, 'applyResult.rejectedAt', 1),
|
|
1293
|
+
};
|
|
1294
|
+
const transactionFailurePresent = result.status === 'rejected'
|
|
1295
|
+
&& result.failureReasons.includes('TRANSACTIONS_UNSUPPORTED');
|
|
1296
|
+
if ((result.status === 'completed' && !result.transactionSupported)
|
|
1297
|
+
|| (result.status === 'rejected'
|
|
1298
|
+
&& transactionFailurePresent === result.transactionSupported)) {
|
|
1299
|
+
fail('CROSS_FIELD_MISMATCH', 'applyResult.transactionSupported');
|
|
1300
|
+
}
|
|
1301
|
+
return finalize(
|
|
1302
|
+
result,
|
|
1303
|
+
cloudlyLegacyDeploymentSettlementLimits.maximumSafeResultBytes,
|
|
1304
|
+
'applyResult',
|
|
1305
|
+
);
|
|
1306
|
+
};
|
|
1307
|
+
|
|
1308
|
+
export const encodeCloudlyLegacyDeploymentSettlementApplyResult = (
|
|
1309
|
+
valueArg: unknown,
|
|
1310
|
+
): Uint8Array => encodeNormalized(
|
|
1311
|
+
normalizeCloudlyLegacyDeploymentSettlementApplyResult(valueArg),
|
|
1312
|
+
'applyResult',
|
|
1313
|
+
);
|
|
1314
|
+
|
|
1315
|
+
export const encodeCloudlyLegacyDeploymentSettlementApplyResultHmacInput = (
|
|
1316
|
+
valueArg: unknown,
|
|
1317
|
+
): Uint8Array => frame(
|
|
1318
|
+
cloudlyLegacyDeploymentSettlementDomains.applyResultHmac,
|
|
1319
|
+
encodeNormalized(
|
|
1320
|
+
normalizeUnsignedAuthenticatedApplyResultInternal(
|
|
1321
|
+
valueArg,
|
|
1322
|
+
'unsignedAuthenticatedApplyResult',
|
|
1323
|
+
),
|
|
1324
|
+
'unsignedAuthenticatedApplyResult',
|
|
1325
|
+
),
|
|
1326
|
+
);
|
|
1327
|
+
|
|
1328
|
+
export const digestCloudlyLegacyDeploymentSettlementApplyResult = (
|
|
1329
|
+
valueArg: unknown,
|
|
1330
|
+
): string => digestBytes(encodeCloudlyLegacyDeploymentSettlementApplyResult(valueArg));
|
|
1331
|
+
|
|
1332
|
+
const rehearsalBindingKeys = [
|
|
1333
|
+
'schemaVersion',
|
|
1334
|
+
'kind',
|
|
1335
|
+
'settlementId',
|
|
1336
|
+
'runId',
|
|
1337
|
+
'rehearsalId',
|
|
1338
|
+
'scratchServiceId',
|
|
1339
|
+
'allocationId',
|
|
1340
|
+
'allocationGeneration',
|
|
1341
|
+
'allocationBindingSha256',
|
|
1342
|
+
'allocationReceiptSha256',
|
|
1343
|
+
'backupId',
|
|
1344
|
+
'backupSnapshotIdSha256',
|
|
1345
|
+
'backupProofSha256',
|
|
1346
|
+
'sourceDataSha256',
|
|
1347
|
+
'restoredDataSha256',
|
|
1348
|
+
'digestProofSha256',
|
|
1349
|
+
'targetImageDigest',
|
|
1350
|
+
'targetVersion',
|
|
1351
|
+
'targetManifestSha256',
|
|
1352
|
+
'targetConfigSha256',
|
|
1353
|
+
] as const;
|
|
1354
|
+
|
|
1355
|
+
const normalizeRehearsalBindingInternal = (
|
|
1356
|
+
valueArg: unknown,
|
|
1357
|
+
pathArg: string,
|
|
1358
|
+
): ICloudlyLegacyDeploymentSettlementRehearsalBindingV1 => {
|
|
1359
|
+
const value = readRecord(valueArg, pathArg);
|
|
1360
|
+
assertExactKeys(value, rehearsalBindingKeys, pathArg);
|
|
1361
|
+
if (value.schemaVersion !== 1
|
|
1362
|
+
|| value.kind !== 'cloudly-legacy-deployment-settlement-rehearsal-binding') {
|
|
1363
|
+
fail('INVALID_VALUE', `${pathArg}.kind`);
|
|
1364
|
+
}
|
|
1365
|
+
const sourceDataSha256 = readSha256(value.sourceDataSha256, `${pathArg}.sourceDataSha256`);
|
|
1366
|
+
const restoredDataSha256 = readSha256(
|
|
1367
|
+
value.restoredDataSha256,
|
|
1368
|
+
`${pathArg}.restoredDataSha256`,
|
|
1369
|
+
);
|
|
1370
|
+
if (sourceDataSha256 !== restoredDataSha256) {
|
|
1371
|
+
fail('CROSS_FIELD_MISMATCH', `${pathArg}.restoredDataSha256`);
|
|
1372
|
+
}
|
|
1373
|
+
return {
|
|
1374
|
+
schemaVersion: 1,
|
|
1375
|
+
kind: 'cloudly-legacy-deployment-settlement-rehearsal-binding',
|
|
1376
|
+
settlementId: readIdentifier(value.settlementId, `${pathArg}.settlementId`),
|
|
1377
|
+
runId: readIdentifier(value.runId, `${pathArg}.runId`),
|
|
1378
|
+
rehearsalId: readIdentifier(value.rehearsalId, `${pathArg}.rehearsalId`),
|
|
1379
|
+
scratchServiceId: readIdentifier(value.scratchServiceId, `${pathArg}.scratchServiceId`),
|
|
1380
|
+
allocationId: readIdentifier(value.allocationId, `${pathArg}.allocationId`),
|
|
1381
|
+
allocationGeneration: readInteger(
|
|
1382
|
+
value.allocationGeneration,
|
|
1383
|
+
`${pathArg}.allocationGeneration`,
|
|
1384
|
+
1,
|
|
1385
|
+
),
|
|
1386
|
+
allocationBindingSha256: readSha256(
|
|
1387
|
+
value.allocationBindingSha256,
|
|
1388
|
+
`${pathArg}.allocationBindingSha256`,
|
|
1389
|
+
),
|
|
1390
|
+
allocationReceiptSha256: readSha256(
|
|
1391
|
+
value.allocationReceiptSha256,
|
|
1392
|
+
`${pathArg}.allocationReceiptSha256`,
|
|
1393
|
+
),
|
|
1394
|
+
backupId: readIdentifier(value.backupId, `${pathArg}.backupId`),
|
|
1395
|
+
backupSnapshotIdSha256: readSha256(
|
|
1396
|
+
value.backupSnapshotIdSha256,
|
|
1397
|
+
`${pathArg}.backupSnapshotIdSha256`,
|
|
1398
|
+
),
|
|
1399
|
+
backupProofSha256: readSha256(value.backupProofSha256, `${pathArg}.backupProofSha256`),
|
|
1400
|
+
sourceDataSha256,
|
|
1401
|
+
restoredDataSha256,
|
|
1402
|
+
digestProofSha256: readSha256(value.digestProofSha256, `${pathArg}.digestProofSha256`),
|
|
1403
|
+
targetImageDigest: readOciDigest(value.targetImageDigest, `${pathArg}.targetImageDigest`),
|
|
1404
|
+
targetVersion: readIdentifier(value.targetVersion, `${pathArg}.targetVersion`),
|
|
1405
|
+
targetManifestSha256: readSha256(
|
|
1406
|
+
value.targetManifestSha256,
|
|
1407
|
+
`${pathArg}.targetManifestSha256`,
|
|
1408
|
+
),
|
|
1409
|
+
targetConfigSha256: readSha256(value.targetConfigSha256, `${pathArg}.targetConfigSha256`),
|
|
1410
|
+
};
|
|
1411
|
+
};
|
|
1412
|
+
|
|
1413
|
+
export const normalizeCloudlyLegacyDeploymentSettlementRehearsalBinding = (
|
|
1414
|
+
valueArg: unknown,
|
|
1415
|
+
): Readonly<ICloudlyLegacyDeploymentSettlementRehearsalBindingV1> => finalize(
|
|
1416
|
+
normalizeRehearsalBindingInternal(valueArg, 'rehearsalBinding'),
|
|
1417
|
+
cloudlyLegacyDeploymentSettlementLimits.maximumAuthorityBytes,
|
|
1418
|
+
'rehearsalBinding',
|
|
1419
|
+
);
|
|
1420
|
+
|
|
1421
|
+
export const encodeCloudlyLegacyDeploymentSettlementRehearsalBinding = (
|
|
1422
|
+
valueArg: unknown,
|
|
1423
|
+
): Uint8Array => encodeNormalized(
|
|
1424
|
+
normalizeCloudlyLegacyDeploymentSettlementRehearsalBinding(valueArg),
|
|
1425
|
+
'rehearsalBinding',
|
|
1426
|
+
);
|
|
1427
|
+
|
|
1428
|
+
export const encodeCloudlyLegacyDeploymentSettlementRehearsalBindingHmacInput = (
|
|
1429
|
+
valueArg: unknown,
|
|
1430
|
+
): Uint8Array => frame(
|
|
1431
|
+
cloudlyLegacyDeploymentSettlementDomains.rehearsalBindingHmac,
|
|
1432
|
+
encodeNormalized(
|
|
1433
|
+
normalizeUnsignedAuthenticatedRehearsalBindingInternal(
|
|
1434
|
+
valueArg,
|
|
1435
|
+
'unsignedAuthenticatedRehearsalBinding',
|
|
1436
|
+
),
|
|
1437
|
+
'unsignedAuthenticatedRehearsalBinding',
|
|
1438
|
+
),
|
|
1439
|
+
);
|
|
1440
|
+
|
|
1441
|
+
export const digestCloudlyLegacyDeploymentSettlementRehearsalBinding = (
|
|
1442
|
+
valueArg: unknown,
|
|
1443
|
+
): string => digestBytes(encodeCloudlyLegacyDeploymentSettlementRehearsalBinding(valueArg));
|
|
1444
|
+
|
|
1445
|
+
export const normalizeCloudlyLegacyDeploymentSettlementProductionRequest = (
|
|
1446
|
+
valueArg: unknown,
|
|
1447
|
+
): Readonly<ICloudlyLegacyDeploymentSettlementProductionRequestV1> => {
|
|
1448
|
+
const value = readRecord(valueArg, 'productionRequest');
|
|
1449
|
+
assertExactKeys(value, [
|
|
1450
|
+
'schemaVersion',
|
|
1451
|
+
'kind',
|
|
1452
|
+
'authority',
|
|
1453
|
+
'plan',
|
|
1454
|
+
'planSha256',
|
|
1455
|
+
'rehearsalBinding',
|
|
1456
|
+
'rehearsalBindingSha256',
|
|
1457
|
+
'requestedAt',
|
|
1458
|
+
], 'productionRequest');
|
|
1459
|
+
if (value.schemaVersion !== 1
|
|
1460
|
+
|| value.kind !== 'cloudly-legacy-deployment-settlement-production-request') {
|
|
1461
|
+
fail('INVALID_VALUE', 'productionRequest.kind');
|
|
1462
|
+
}
|
|
1463
|
+
const authority = normalizeAuthorityReferenceInternal(
|
|
1464
|
+
value.authority,
|
|
1465
|
+
'productionRequest.authority',
|
|
1466
|
+
);
|
|
1467
|
+
const plan = normalizeCloudlyLegacyDeploymentSettlementPlan(value.plan);
|
|
1468
|
+
const planSha256 = readSha256(value.planSha256, 'productionRequest.planSha256');
|
|
1469
|
+
const rehearsalBinding = normalizeRehearsalBindingInternal(
|
|
1470
|
+
value.rehearsalBinding,
|
|
1471
|
+
'productionRequest.rehearsalBinding',
|
|
1472
|
+
);
|
|
1473
|
+
const rehearsalBindingSha256 = readSha256(
|
|
1474
|
+
value.rehearsalBindingSha256,
|
|
1475
|
+
'productionRequest.rehearsalBindingSha256',
|
|
1476
|
+
);
|
|
1477
|
+
if (canonicalize(authority, 'productionRequest.authority')
|
|
1478
|
+
!== canonicalize(plan.authority, 'productionRequest.plan.authority')) {
|
|
1479
|
+
fail('CROSS_FIELD_MISMATCH', 'productionRequest.authority');
|
|
1480
|
+
}
|
|
1481
|
+
if (planSha256 !== digestCloudlyLegacyDeploymentSettlementPlan(plan)) {
|
|
1482
|
+
fail('CROSS_FIELD_MISMATCH', 'productionRequest.planSha256');
|
|
1483
|
+
}
|
|
1484
|
+
if (rehearsalBindingSha256
|
|
1485
|
+
!== digestCloudlyLegacyDeploymentSettlementRehearsalBinding(rehearsalBinding)) {
|
|
1486
|
+
fail('CROSS_FIELD_MISMATCH', 'productionRequest.rehearsalBindingSha256');
|
|
1487
|
+
}
|
|
1488
|
+
if (plan.settlementId !== rehearsalBinding.settlementId) {
|
|
1489
|
+
fail('CROSS_FIELD_MISMATCH', 'productionRequest.rehearsalBinding.settlementId');
|
|
1490
|
+
}
|
|
1491
|
+
const requestedAt = readInteger(value.requestedAt, 'productionRequest.requestedAt', 1);
|
|
1492
|
+
if (requestedAt < plan.effectiveAt) {
|
|
1493
|
+
fail('CROSS_FIELD_MISMATCH', 'productionRequest.requestedAt');
|
|
1494
|
+
}
|
|
1495
|
+
return finalize({
|
|
1496
|
+
schemaVersion: 1,
|
|
1497
|
+
kind: 'cloudly-legacy-deployment-settlement-production-request',
|
|
1498
|
+
authority,
|
|
1499
|
+
plan,
|
|
1500
|
+
planSha256,
|
|
1501
|
+
rehearsalBinding,
|
|
1502
|
+
rehearsalBindingSha256,
|
|
1503
|
+
requestedAt,
|
|
1504
|
+
}, cloudlyLegacyDeploymentSettlementLimits.maximumAuthenticatedArtifactBytes, 'productionRequest');
|
|
1505
|
+
};
|
|
1506
|
+
|
|
1507
|
+
export const encodeCloudlyLegacyDeploymentSettlementProductionRequest = (
|
|
1508
|
+
valueArg: unknown,
|
|
1509
|
+
): Uint8Array => encodeNormalized(
|
|
1510
|
+
normalizeCloudlyLegacyDeploymentSettlementProductionRequest(valueArg),
|
|
1511
|
+
'productionRequest',
|
|
1512
|
+
);
|
|
1513
|
+
|
|
1514
|
+
export const digestCloudlyLegacyDeploymentSettlementProductionRequest = (
|
|
1515
|
+
valueArg: unknown,
|
|
1516
|
+
): string => digestBytes(encodeCloudlyLegacyDeploymentSettlementProductionRequest(valueArg));
|
|
1517
|
+
|
|
1518
|
+
const stableOutcomeKeys = [
|
|
1519
|
+
'schemaVersion',
|
|
1520
|
+
'kind',
|
|
1521
|
+
'settlementId',
|
|
1522
|
+
'runId',
|
|
1523
|
+
'rehearsalBindingSha256',
|
|
1524
|
+
'effectiveAt',
|
|
1525
|
+
'planSha256',
|
|
1526
|
+
'sourceStateHmac',
|
|
1527
|
+
'finalStateHmac',
|
|
1528
|
+
'settlements',
|
|
1529
|
+
'counts',
|
|
1530
|
+
'classificationCounts',
|
|
1531
|
+
] as const;
|
|
1532
|
+
|
|
1533
|
+
const normalizeStableOutcomeInternal = (
|
|
1534
|
+
valueArg: unknown,
|
|
1535
|
+
pathArg: string,
|
|
1536
|
+
): ICloudlyLegacyDeploymentSettlementStableOutcomeV1 => {
|
|
1537
|
+
const value = readRecord(valueArg, pathArg);
|
|
1538
|
+
assertExactKeys(value, stableOutcomeKeys, pathArg);
|
|
1539
|
+
if (value.schemaVersion !== 1
|
|
1540
|
+
|| value.kind !== 'cloudly-legacy-deployment-settlement-stable-outcome') {
|
|
1541
|
+
fail('INVALID_VALUE', `${pathArg}.kind`);
|
|
1542
|
+
}
|
|
1543
|
+
const counts = normalizeMutationCounts(value.counts, `${pathArg}.counts`);
|
|
1544
|
+
const classificationCounts = normalizeClassificationCounts(
|
|
1545
|
+
value.classificationCounts,
|
|
1546
|
+
`${pathArg}.classificationCounts`,
|
|
1547
|
+
);
|
|
1548
|
+
assertCountsMatchClassifications(counts, classificationCounts, `${pathArg}.counts.operationCount`);
|
|
1549
|
+
const settlements = readArray(
|
|
1550
|
+
value.settlements,
|
|
1551
|
+
`${pathArg}.settlements`,
|
|
1552
|
+
cloudlyLegacyDeploymentSettlementLimits.maximumOperations,
|
|
1553
|
+
).map((entryArg, indexArg) => {
|
|
1554
|
+
const entryPath = `${pathArg}.settlements[${indexArg}]`;
|
|
1555
|
+
const entry = readRecord(entryArg, entryPath);
|
|
1556
|
+
assertExactKeys(entry, ['operationId', 'finalRevision', 'finalDocumentHmac'], entryPath);
|
|
1557
|
+
return {
|
|
1558
|
+
operationId: readIdentifier(entry.operationId, `${entryPath}.operationId`),
|
|
1559
|
+
finalRevision: readInteger(entry.finalRevision, `${entryPath}.finalRevision`, 1),
|
|
1560
|
+
finalDocumentHmac: readStateHmac(
|
|
1561
|
+
entry.finalDocumentHmac,
|
|
1562
|
+
`${entryPath}.finalDocumentHmac`,
|
|
1563
|
+
),
|
|
1564
|
+
};
|
|
1565
|
+
});
|
|
1566
|
+
for (let index = 1; index < settlements.length; index++) {
|
|
1567
|
+
if (settlements[index - 1].operationId >= settlements[index].operationId) {
|
|
1568
|
+
fail('ORDERING_REQUIRED', `${pathArg}.settlements[${index}].operationId`);
|
|
1569
|
+
}
|
|
1570
|
+
}
|
|
1571
|
+
if (settlements.length !== counts.operationCount) {
|
|
1572
|
+
fail('CROSS_FIELD_MISMATCH', `${pathArg}.settlements`);
|
|
1573
|
+
}
|
|
1574
|
+
return {
|
|
1575
|
+
schemaVersion: 1,
|
|
1576
|
+
kind: 'cloudly-legacy-deployment-settlement-stable-outcome',
|
|
1577
|
+
settlementId: readIdentifier(value.settlementId, `${pathArg}.settlementId`),
|
|
1578
|
+
runId: readIdentifier(value.runId, `${pathArg}.runId`),
|
|
1579
|
+
rehearsalBindingSha256: readSha256(
|
|
1580
|
+
value.rehearsalBindingSha256,
|
|
1581
|
+
`${pathArg}.rehearsalBindingSha256`,
|
|
1582
|
+
),
|
|
1583
|
+
effectiveAt: readInteger(value.effectiveAt, `${pathArg}.effectiveAt`, 1),
|
|
1584
|
+
planSha256: readSha256(value.planSha256, `${pathArg}.planSha256`),
|
|
1585
|
+
sourceStateHmac: readStateHmac(value.sourceStateHmac, `${pathArg}.sourceStateHmac`),
|
|
1586
|
+
finalStateHmac: readStateHmac(value.finalStateHmac, `${pathArg}.finalStateHmac`),
|
|
1587
|
+
settlements,
|
|
1588
|
+
counts,
|
|
1589
|
+
classificationCounts,
|
|
1590
|
+
};
|
|
1591
|
+
};
|
|
1592
|
+
|
|
1593
|
+
export const normalizeCloudlyLegacyDeploymentSettlementStableOutcome = (
|
|
1594
|
+
valueArg: unknown,
|
|
1595
|
+
): Readonly<ICloudlyLegacyDeploymentSettlementStableOutcomeV1> => finalize(
|
|
1596
|
+
normalizeStableOutcomeInternal(valueArg, 'stableOutcome'),
|
|
1597
|
+
cloudlyLegacyDeploymentSettlementLimits.maximumReceiptBytes,
|
|
1598
|
+
'stableOutcome',
|
|
1599
|
+
);
|
|
1600
|
+
|
|
1601
|
+
export const encodeCloudlyLegacyDeploymentSettlementStableOutcome = (
|
|
1602
|
+
valueArg: unknown,
|
|
1603
|
+
): Uint8Array => encodeNormalized(
|
|
1604
|
+
normalizeCloudlyLegacyDeploymentSettlementStableOutcome(valueArg),
|
|
1605
|
+
'stableOutcome',
|
|
1606
|
+
);
|
|
1607
|
+
|
|
1608
|
+
export const encodeCloudlyLegacyDeploymentSettlementStableOutcomeHmacInput = (
|
|
1609
|
+
valueArg: unknown,
|
|
1610
|
+
): Uint8Array => frame(
|
|
1611
|
+
cloudlyLegacyDeploymentSettlementDomains.stableOutcomeHmac,
|
|
1612
|
+
encodeNormalized(
|
|
1613
|
+
normalizeUnsignedAuthenticatedStableOutcomeInternal(
|
|
1614
|
+
valueArg,
|
|
1615
|
+
'unsignedAuthenticatedStableOutcome',
|
|
1616
|
+
),
|
|
1617
|
+
'unsignedAuthenticatedStableOutcome',
|
|
1618
|
+
),
|
|
1619
|
+
);
|
|
1620
|
+
|
|
1621
|
+
export const digestCloudlyLegacyDeploymentSettlementStableOutcome = (
|
|
1622
|
+
valueArg: unknown,
|
|
1623
|
+
): string => digestBytes(encodeCloudlyLegacyDeploymentSettlementStableOutcome(valueArg));
|
|
1624
|
+
|
|
1625
|
+
type TAuthenticatedSettlementArtifactKind =
|
|
1626
|
+
| 'authenticated-cloudly-legacy-deployment-settlement-rehearsal-binding'
|
|
1627
|
+
| 'authenticated-cloudly-legacy-deployment-settlement-plan'
|
|
1628
|
+
| 'authenticated-cloudly-legacy-deployment-settlement-production-request'
|
|
1629
|
+
| 'authenticated-cloudly-legacy-deployment-settlement-check-result'
|
|
1630
|
+
| 'authenticated-cloudly-legacy-deployment-settlement-apply-result'
|
|
1631
|
+
| 'authenticated-cloudly-legacy-deployment-settlement-stable-outcome';
|
|
1632
|
+
|
|
1633
|
+
interface IUnsignedAuthenticatedSettlementArtifact<TPayload> {
|
|
1634
|
+
schemaVersion: 1;
|
|
1635
|
+
kind: TAuthenticatedSettlementArtifactKind;
|
|
1636
|
+
authority: ICloudlyLegacyDeploymentSettlementAuthorityReferenceV1;
|
|
1637
|
+
payload: TPayload;
|
|
1638
|
+
payloadSha256: string;
|
|
1639
|
+
}
|
|
1640
|
+
|
|
1641
|
+
const authenticatedArtifactKeys = [
|
|
1642
|
+
'schemaVersion',
|
|
1643
|
+
'kind',
|
|
1644
|
+
'authority',
|
|
1645
|
+
'payload',
|
|
1646
|
+
'payloadSha256',
|
|
1647
|
+
'mac',
|
|
1648
|
+
] as const;
|
|
1649
|
+
const unsignedAuthenticatedArtifactKeys = authenticatedArtifactKeys.filter(
|
|
1650
|
+
(keyArg) => keyArg !== 'mac',
|
|
1651
|
+
);
|
|
1652
|
+
|
|
1653
|
+
const normalizeUnsignedAuthenticatedArtifactInternal = <TPayload>(
|
|
1654
|
+
valueArg: unknown,
|
|
1655
|
+
pathArg: string,
|
|
1656
|
+
kindArg: TAuthenticatedSettlementArtifactKind,
|
|
1657
|
+
normalizePayloadArg: (valueArg: unknown) => Readonly<TPayload>,
|
|
1658
|
+
getPayloadAuthorityArg?: (
|
|
1659
|
+
payloadArg: Readonly<TPayload>,
|
|
1660
|
+
) => ICloudlyLegacyDeploymentSettlementAuthorityReferenceV1,
|
|
1661
|
+
): IUnsignedAuthenticatedSettlementArtifact<TPayload> => {
|
|
1662
|
+
const value = readRecord(valueArg, pathArg);
|
|
1663
|
+
assertExactKeys(value, unsignedAuthenticatedArtifactKeys, pathArg);
|
|
1664
|
+
if (value.schemaVersion !== 1 || value.kind !== kindArg) {
|
|
1665
|
+
fail('INVALID_VALUE', `${pathArg}.kind`);
|
|
1666
|
+
}
|
|
1667
|
+
const authority = normalizeAuthorityReferenceInternal(value.authority, `${pathArg}.authority`);
|
|
1668
|
+
const payload = normalizePayloadArg(value.payload);
|
|
1669
|
+
const payloadSha256 = readSha256(value.payloadSha256, `${pathArg}.payloadSha256`);
|
|
1670
|
+
if (payloadSha256 !== digestBytes(encodeNormalized(payload, `${pathArg}.payload`))) {
|
|
1671
|
+
fail('CROSS_FIELD_MISMATCH', `${pathArg}.payloadSha256`);
|
|
1672
|
+
}
|
|
1673
|
+
if (getPayloadAuthorityArg
|
|
1674
|
+
&& canonicalize(authority, `${pathArg}.authority`)
|
|
1675
|
+
!== canonicalize(getPayloadAuthorityArg(payload), `${pathArg}.payload.authority`)) {
|
|
1676
|
+
fail('CROSS_FIELD_MISMATCH', `${pathArg}.authority`);
|
|
1677
|
+
}
|
|
1678
|
+
return {
|
|
1679
|
+
schemaVersion: 1,
|
|
1680
|
+
kind: kindArg,
|
|
1681
|
+
authority,
|
|
1682
|
+
payload: payload as TPayload,
|
|
1683
|
+
payloadSha256,
|
|
1684
|
+
};
|
|
1685
|
+
};
|
|
1686
|
+
|
|
1687
|
+
const normalizeAuthenticatedArtifactInternal = <TPayload>(
|
|
1688
|
+
valueArg: unknown,
|
|
1689
|
+
pathArg: string,
|
|
1690
|
+
kindArg: TAuthenticatedSettlementArtifactKind,
|
|
1691
|
+
normalizePayloadArg: (valueArg: unknown) => Readonly<TPayload>,
|
|
1692
|
+
getPayloadAuthorityArg?: (
|
|
1693
|
+
payloadArg: Readonly<TPayload>,
|
|
1694
|
+
) => ICloudlyLegacyDeploymentSettlementAuthorityReferenceV1,
|
|
1695
|
+
): IUnsignedAuthenticatedSettlementArtifact<TPayload> & { mac: string } => {
|
|
1696
|
+
const value = readRecord(valueArg, pathArg);
|
|
1697
|
+
assertExactKeys(value, authenticatedArtifactKeys, pathArg);
|
|
1698
|
+
const unsignedInput = Object.fromEntries(unsignedAuthenticatedArtifactKeys.map((keyArg) => [
|
|
1699
|
+
keyArg,
|
|
1700
|
+
value[keyArg],
|
|
1701
|
+
]));
|
|
1702
|
+
return {
|
|
1703
|
+
...normalizeUnsignedAuthenticatedArtifactInternal(
|
|
1704
|
+
unsignedInput,
|
|
1705
|
+
`${pathArg}.unsigned`,
|
|
1706
|
+
kindArg,
|
|
1707
|
+
normalizePayloadArg,
|
|
1708
|
+
getPayloadAuthorityArg,
|
|
1709
|
+
),
|
|
1710
|
+
mac: readMac(value.mac, `${pathArg}.mac`),
|
|
1711
|
+
};
|
|
1712
|
+
};
|
|
1713
|
+
|
|
1714
|
+
const normalizeUnsignedAuthenticatedRehearsalBindingInternal = (
|
|
1715
|
+
valueArg: unknown,
|
|
1716
|
+
pathArg: string,
|
|
1717
|
+
): TUnsignedAuthenticatedCloudlyLegacyDeploymentSettlementRehearsalBindingV1 => (
|
|
1718
|
+
normalizeUnsignedAuthenticatedArtifactInternal(
|
|
1719
|
+
valueArg,
|
|
1720
|
+
pathArg,
|
|
1721
|
+
'authenticated-cloudly-legacy-deployment-settlement-rehearsal-binding',
|
|
1722
|
+
normalizeCloudlyLegacyDeploymentSettlementRehearsalBinding,
|
|
1723
|
+
) as TUnsignedAuthenticatedCloudlyLegacyDeploymentSettlementRehearsalBindingV1
|
|
1724
|
+
);
|
|
1725
|
+
|
|
1726
|
+
const normalizeUnsignedAuthenticatedPlanInternal = (
|
|
1727
|
+
valueArg: unknown,
|
|
1728
|
+
pathArg: string,
|
|
1729
|
+
): TUnsignedAuthenticatedCloudlyLegacyDeploymentSettlementPlanV1 => (
|
|
1730
|
+
normalizeUnsignedAuthenticatedArtifactInternal(
|
|
1731
|
+
valueArg,
|
|
1732
|
+
pathArg,
|
|
1733
|
+
'authenticated-cloudly-legacy-deployment-settlement-plan',
|
|
1734
|
+
normalizeCloudlyLegacyDeploymentSettlementPlan,
|
|
1735
|
+
(payloadArg) => payloadArg.authority,
|
|
1736
|
+
) as TUnsignedAuthenticatedCloudlyLegacyDeploymentSettlementPlanV1
|
|
1737
|
+
);
|
|
1738
|
+
|
|
1739
|
+
const normalizeUnsignedAuthenticatedProductionRequestInternal = (
|
|
1740
|
+
valueArg: unknown,
|
|
1741
|
+
pathArg: string,
|
|
1742
|
+
): TUnsignedAuthenticatedCloudlyLegacyDeploymentSettlementProductionRequestV1 => (
|
|
1743
|
+
normalizeUnsignedAuthenticatedArtifactInternal(
|
|
1744
|
+
valueArg,
|
|
1745
|
+
pathArg,
|
|
1746
|
+
'authenticated-cloudly-legacy-deployment-settlement-production-request',
|
|
1747
|
+
normalizeCloudlyLegacyDeploymentSettlementProductionRequest,
|
|
1748
|
+
(payloadArg) => payloadArg.authority,
|
|
1749
|
+
) as TUnsignedAuthenticatedCloudlyLegacyDeploymentSettlementProductionRequestV1
|
|
1750
|
+
);
|
|
1751
|
+
|
|
1752
|
+
const normalizeUnsignedAuthenticatedCheckResultInternal = (
|
|
1753
|
+
valueArg: unknown,
|
|
1754
|
+
pathArg: string,
|
|
1755
|
+
): TUnsignedAuthenticatedCloudlyLegacyDeploymentSettlementCheckResultV1 => (
|
|
1756
|
+
normalizeUnsignedAuthenticatedArtifactInternal(
|
|
1757
|
+
valueArg,
|
|
1758
|
+
pathArg,
|
|
1759
|
+
'authenticated-cloudly-legacy-deployment-settlement-check-result',
|
|
1760
|
+
normalizeCloudlyLegacyDeploymentSettlementCheckResult,
|
|
1761
|
+
) as TUnsignedAuthenticatedCloudlyLegacyDeploymentSettlementCheckResultV1
|
|
1762
|
+
);
|
|
1763
|
+
|
|
1764
|
+
const normalizeUnsignedAuthenticatedApplyResultInternal = (
|
|
1765
|
+
valueArg: unknown,
|
|
1766
|
+
pathArg: string,
|
|
1767
|
+
): TUnsignedAuthenticatedCloudlyLegacyDeploymentSettlementApplyResultV1 => (
|
|
1768
|
+
normalizeUnsignedAuthenticatedArtifactInternal(
|
|
1769
|
+
valueArg,
|
|
1770
|
+
pathArg,
|
|
1771
|
+
'authenticated-cloudly-legacy-deployment-settlement-apply-result',
|
|
1772
|
+
normalizeCloudlyLegacyDeploymentSettlementApplyResult,
|
|
1773
|
+
) as TUnsignedAuthenticatedCloudlyLegacyDeploymentSettlementApplyResultV1
|
|
1774
|
+
);
|
|
1775
|
+
|
|
1776
|
+
const normalizeUnsignedAuthenticatedStableOutcomeInternal = (
|
|
1777
|
+
valueArg: unknown,
|
|
1778
|
+
pathArg: string,
|
|
1779
|
+
): TUnsignedAuthenticatedCloudlyLegacyDeploymentSettlementStableOutcomeV1 => (
|
|
1780
|
+
normalizeUnsignedAuthenticatedArtifactInternal(
|
|
1781
|
+
valueArg,
|
|
1782
|
+
pathArg,
|
|
1783
|
+
'authenticated-cloudly-legacy-deployment-settlement-stable-outcome',
|
|
1784
|
+
normalizeCloudlyLegacyDeploymentSettlementStableOutcome,
|
|
1785
|
+
) as TUnsignedAuthenticatedCloudlyLegacyDeploymentSettlementStableOutcomeV1
|
|
1786
|
+
);
|
|
1787
|
+
|
|
1788
|
+
const finalizeAuthenticatedArtifact = <T>(valueArg: T, pathArg: string): Readonly<T> => finalize(
|
|
1789
|
+
valueArg,
|
|
1790
|
+
cloudlyLegacyDeploymentSettlementLimits.maximumAuthenticatedArtifactBytes,
|
|
1791
|
+
pathArg,
|
|
1792
|
+
);
|
|
1793
|
+
|
|
1794
|
+
/** Structural only. Use the async ForAuthority variant to authenticate its MAC. */
|
|
1795
|
+
export const normalizeCloudlyLegacyDeploymentSettlementAuthenticatedRehearsalBindingStructure = (
|
|
1796
|
+
valueArg: unknown,
|
|
1797
|
+
): Readonly<IAuthenticatedCloudlyLegacyDeploymentSettlementRehearsalBindingV1> => (
|
|
1798
|
+
finalizeAuthenticatedArtifact(normalizeAuthenticatedArtifactInternal(
|
|
1799
|
+
valueArg,
|
|
1800
|
+
'authenticatedRehearsalBinding',
|
|
1801
|
+
'authenticated-cloudly-legacy-deployment-settlement-rehearsal-binding',
|
|
1802
|
+
normalizeCloudlyLegacyDeploymentSettlementRehearsalBinding,
|
|
1803
|
+
) as IAuthenticatedCloudlyLegacyDeploymentSettlementRehearsalBindingV1,
|
|
1804
|
+
'authenticatedRehearsalBinding')
|
|
1805
|
+
);
|
|
1806
|
+
|
|
1807
|
+
export const normalizeCloudlyLegacyDeploymentSettlementAuthenticatedPlanStructure = (
|
|
1808
|
+
valueArg: unknown,
|
|
1809
|
+
): Readonly<IAuthenticatedCloudlyLegacyDeploymentSettlementPlanV1> => (
|
|
1810
|
+
finalizeAuthenticatedArtifact(normalizeAuthenticatedArtifactInternal(
|
|
1811
|
+
valueArg,
|
|
1812
|
+
'authenticatedPlan',
|
|
1813
|
+
'authenticated-cloudly-legacy-deployment-settlement-plan',
|
|
1814
|
+
normalizeCloudlyLegacyDeploymentSettlementPlan,
|
|
1815
|
+
(payloadArg) => payloadArg.authority,
|
|
1816
|
+
) as IAuthenticatedCloudlyLegacyDeploymentSettlementPlanV1, 'authenticatedPlan')
|
|
1817
|
+
);
|
|
1818
|
+
|
|
1819
|
+
export const normalizeCloudlyLegacyDeploymentSettlementAuthenticatedProductionRequestStructure = (
|
|
1820
|
+
valueArg: unknown,
|
|
1821
|
+
): Readonly<IAuthenticatedCloudlyLegacyDeploymentSettlementProductionRequestV1> => (
|
|
1822
|
+
finalizeAuthenticatedArtifact(normalizeAuthenticatedArtifactInternal(
|
|
1823
|
+
valueArg,
|
|
1824
|
+
'authenticatedProductionRequest',
|
|
1825
|
+
'authenticated-cloudly-legacy-deployment-settlement-production-request',
|
|
1826
|
+
normalizeCloudlyLegacyDeploymentSettlementProductionRequest,
|
|
1827
|
+
(payloadArg) => payloadArg.authority,
|
|
1828
|
+
) as IAuthenticatedCloudlyLegacyDeploymentSettlementProductionRequestV1,
|
|
1829
|
+
'authenticatedProductionRequest')
|
|
1830
|
+
);
|
|
1831
|
+
|
|
1832
|
+
export const normalizeCloudlyLegacyDeploymentSettlementAuthenticatedCheckResultStructure = (
|
|
1833
|
+
valueArg: unknown,
|
|
1834
|
+
): Readonly<IAuthenticatedCloudlyLegacyDeploymentSettlementCheckResultV1> => (
|
|
1835
|
+
finalizeAuthenticatedArtifact(normalizeAuthenticatedArtifactInternal(
|
|
1836
|
+
valueArg,
|
|
1837
|
+
'authenticatedCheckResult',
|
|
1838
|
+
'authenticated-cloudly-legacy-deployment-settlement-check-result',
|
|
1839
|
+
normalizeCloudlyLegacyDeploymentSettlementCheckResult,
|
|
1840
|
+
) as IAuthenticatedCloudlyLegacyDeploymentSettlementCheckResultV1, 'authenticatedCheckResult')
|
|
1841
|
+
);
|
|
1842
|
+
|
|
1843
|
+
export const normalizeCloudlyLegacyDeploymentSettlementAuthenticatedApplyResultStructure = (
|
|
1844
|
+
valueArg: unknown,
|
|
1845
|
+
): Readonly<IAuthenticatedCloudlyLegacyDeploymentSettlementApplyResultV1> => (
|
|
1846
|
+
finalizeAuthenticatedArtifact(normalizeAuthenticatedArtifactInternal(
|
|
1847
|
+
valueArg,
|
|
1848
|
+
'authenticatedApplyResult',
|
|
1849
|
+
'authenticated-cloudly-legacy-deployment-settlement-apply-result',
|
|
1850
|
+
normalizeCloudlyLegacyDeploymentSettlementApplyResult,
|
|
1851
|
+
) as IAuthenticatedCloudlyLegacyDeploymentSettlementApplyResultV1, 'authenticatedApplyResult')
|
|
1852
|
+
);
|
|
1853
|
+
|
|
1854
|
+
export const normalizeCloudlyLegacyDeploymentSettlementAuthenticatedStableOutcomeStructure = (
|
|
1855
|
+
valueArg: unknown,
|
|
1856
|
+
): Readonly<IAuthenticatedCloudlyLegacyDeploymentSettlementStableOutcomeV1> => (
|
|
1857
|
+
finalizeAuthenticatedArtifact(normalizeAuthenticatedArtifactInternal(
|
|
1858
|
+
valueArg,
|
|
1859
|
+
'authenticatedStableOutcome',
|
|
1860
|
+
'authenticated-cloudly-legacy-deployment-settlement-stable-outcome',
|
|
1861
|
+
normalizeCloudlyLegacyDeploymentSettlementStableOutcome,
|
|
1862
|
+
) as IAuthenticatedCloudlyLegacyDeploymentSettlementStableOutcomeV1,
|
|
1863
|
+
'authenticatedStableOutcome')
|
|
1864
|
+
);
|
|
1865
|
+
|
|
1866
|
+
export const encodeCloudlyLegacyDeploymentSettlementProductionRequestHmacInput = (
|
|
1867
|
+
valueArg: unknown,
|
|
1868
|
+
): Uint8Array => frame(
|
|
1869
|
+
cloudlyLegacyDeploymentSettlementDomains.productionRequestHmac,
|
|
1870
|
+
encodeNormalized(
|
|
1871
|
+
normalizeUnsignedAuthenticatedProductionRequestInternal(
|
|
1872
|
+
valueArg,
|
|
1873
|
+
'unsignedAuthenticatedProductionRequest',
|
|
1874
|
+
),
|
|
1875
|
+
'unsignedAuthenticatedProductionRequest',
|
|
1876
|
+
),
|
|
1877
|
+
);
|
|
1878
|
+
|
|
1879
|
+
const encodeAuthenticatedArtifact = <T>(
|
|
1880
|
+
valueArg: unknown,
|
|
1881
|
+
normalizeArg: (valueArg: unknown) => Readonly<T>,
|
|
1882
|
+
pathArg: string,
|
|
1883
|
+
): Uint8Array => encodeNormalized(normalizeArg(valueArg), pathArg);
|
|
1884
|
+
|
|
1885
|
+
export const encodeAuthenticatedCloudlyLegacyDeploymentSettlementRehearsalBinding = (
|
|
1886
|
+
valueArg: unknown,
|
|
1887
|
+
): Uint8Array => encodeAuthenticatedArtifact(
|
|
1888
|
+
valueArg,
|
|
1889
|
+
normalizeCloudlyLegacyDeploymentSettlementAuthenticatedRehearsalBindingStructure,
|
|
1890
|
+
'authenticatedRehearsalBinding',
|
|
1891
|
+
);
|
|
1892
|
+
export const encodeAuthenticatedCloudlyLegacyDeploymentSettlementPlan = (
|
|
1893
|
+
valueArg: unknown,
|
|
1894
|
+
): Uint8Array => encodeAuthenticatedArtifact(
|
|
1895
|
+
valueArg,
|
|
1896
|
+
normalizeCloudlyLegacyDeploymentSettlementAuthenticatedPlanStructure,
|
|
1897
|
+
'authenticatedPlan',
|
|
1898
|
+
);
|
|
1899
|
+
export const encodeAuthenticatedCloudlyLegacyDeploymentSettlementProductionRequest = (
|
|
1900
|
+
valueArg: unknown,
|
|
1901
|
+
): Uint8Array => encodeAuthenticatedArtifact(
|
|
1902
|
+
valueArg,
|
|
1903
|
+
normalizeCloudlyLegacyDeploymentSettlementAuthenticatedProductionRequestStructure,
|
|
1904
|
+
'authenticatedProductionRequest',
|
|
1905
|
+
);
|
|
1906
|
+
export const encodeAuthenticatedCloudlyLegacyDeploymentSettlementCheckResult = (
|
|
1907
|
+
valueArg: unknown,
|
|
1908
|
+
): Uint8Array => encodeAuthenticatedArtifact(
|
|
1909
|
+
valueArg,
|
|
1910
|
+
normalizeCloudlyLegacyDeploymentSettlementAuthenticatedCheckResultStructure,
|
|
1911
|
+
'authenticatedCheckResult',
|
|
1912
|
+
);
|
|
1913
|
+
export const encodeAuthenticatedCloudlyLegacyDeploymentSettlementApplyResult = (
|
|
1914
|
+
valueArg: unknown,
|
|
1915
|
+
): Uint8Array => encodeAuthenticatedArtifact(
|
|
1916
|
+
valueArg,
|
|
1917
|
+
normalizeCloudlyLegacyDeploymentSettlementAuthenticatedApplyResultStructure,
|
|
1918
|
+
'authenticatedApplyResult',
|
|
1919
|
+
);
|
|
1920
|
+
export const encodeAuthenticatedCloudlyLegacyDeploymentSettlementStableOutcome = (
|
|
1921
|
+
valueArg: unknown,
|
|
1922
|
+
): Uint8Array => encodeAuthenticatedArtifact(
|
|
1923
|
+
valueArg,
|
|
1924
|
+
normalizeCloudlyLegacyDeploymentSettlementAuthenticatedStableOutcomeStructure,
|
|
1925
|
+
'authenticatedStableOutcome',
|
|
1926
|
+
);
|
|
1927
|
+
|
|
1928
|
+
export const digestAuthenticatedCloudlyLegacyDeploymentSettlementRehearsalBinding = (
|
|
1929
|
+
valueArg: unknown,
|
|
1930
|
+
): string => digestBytes(
|
|
1931
|
+
encodeAuthenticatedCloudlyLegacyDeploymentSettlementRehearsalBinding(valueArg),
|
|
1932
|
+
);
|
|
1933
|
+
export const digestAuthenticatedCloudlyLegacyDeploymentSettlementPlan = (
|
|
1934
|
+
valueArg: unknown,
|
|
1935
|
+
): string => digestBytes(encodeAuthenticatedCloudlyLegacyDeploymentSettlementPlan(valueArg));
|
|
1936
|
+
export const digestAuthenticatedCloudlyLegacyDeploymentSettlementProductionRequest = (
|
|
1937
|
+
valueArg: unknown,
|
|
1938
|
+
): string => digestBytes(
|
|
1939
|
+
encodeAuthenticatedCloudlyLegacyDeploymentSettlementProductionRequest(valueArg),
|
|
1940
|
+
);
|
|
1941
|
+
export const digestAuthenticatedCloudlyLegacyDeploymentSettlementCheckResult = (
|
|
1942
|
+
valueArg: unknown,
|
|
1943
|
+
): string => digestBytes(
|
|
1944
|
+
encodeAuthenticatedCloudlyLegacyDeploymentSettlementCheckResult(valueArg),
|
|
1945
|
+
);
|
|
1946
|
+
export const digestAuthenticatedCloudlyLegacyDeploymentSettlementApplyResult = (
|
|
1947
|
+
valueArg: unknown,
|
|
1948
|
+
): string => digestBytes(
|
|
1949
|
+
encodeAuthenticatedCloudlyLegacyDeploymentSettlementApplyResult(valueArg),
|
|
1950
|
+
);
|
|
1951
|
+
export const digestAuthenticatedCloudlyLegacyDeploymentSettlementStableOutcome = (
|
|
1952
|
+
valueArg: unknown,
|
|
1953
|
+
): string => digestBytes(
|
|
1954
|
+
encodeAuthenticatedCloudlyLegacyDeploymentSettlementStableOutcome(valueArg),
|
|
1955
|
+
);
|
|
1956
|
+
|
|
1957
|
+
const scratchReceiptKeys = [
|
|
1958
|
+
'schemaVersion',
|
|
1959
|
+
'kind',
|
|
1960
|
+
'authority',
|
|
1961
|
+
'requestSha256',
|
|
1962
|
+
'stableOutcome',
|
|
1963
|
+
'stableOutcomeSha256',
|
|
1964
|
+
'transactionCommitted',
|
|
1965
|
+
'disposition',
|
|
1966
|
+
'completedAt',
|
|
1967
|
+
'payloadSha256',
|
|
1968
|
+
'mac',
|
|
1969
|
+
] as const;
|
|
1970
|
+
const scratchReceiptPayloadKeys = scratchReceiptKeys.filter((keyArg) => (
|
|
1971
|
+
keyArg !== 'payloadSha256' && keyArg !== 'mac'
|
|
1972
|
+
));
|
|
1973
|
+
const unsignedScratchReceiptKeys = scratchReceiptKeys.filter((keyArg) => keyArg !== 'mac');
|
|
1974
|
+
|
|
1975
|
+
const scratchReceiptPayload = (
|
|
1976
|
+
valueArg: Omit<ICloudlyLegacyDeploymentSettlementScratchReceiptV1, 'payloadSha256' | 'mac'>,
|
|
1977
|
+
): unknown => ({
|
|
1978
|
+
schemaVersion: valueArg.schemaVersion,
|
|
1979
|
+
kind: valueArg.kind,
|
|
1980
|
+
authority: valueArg.authority,
|
|
1981
|
+
requestSha256: valueArg.requestSha256,
|
|
1982
|
+
stableOutcome: valueArg.stableOutcome,
|
|
1983
|
+
stableOutcomeSha256: valueArg.stableOutcomeSha256,
|
|
1984
|
+
transactionCommitted: valueArg.transactionCommitted,
|
|
1985
|
+
disposition: valueArg.disposition,
|
|
1986
|
+
completedAt: valueArg.completedAt,
|
|
1987
|
+
});
|
|
1988
|
+
|
|
1989
|
+
const normalizeScratchReceiptPayloadInternal = (
|
|
1990
|
+
valueArg: unknown,
|
|
1991
|
+
pathArg: string,
|
|
1992
|
+
): TCloudlyLegacyDeploymentSettlementScratchReceiptPayloadV1 => {
|
|
1993
|
+
const value = readRecord(valueArg, pathArg);
|
|
1994
|
+
assertExactKeys(value, scratchReceiptPayloadKeys, pathArg);
|
|
1995
|
+
if (value.schemaVersion !== 1
|
|
1996
|
+
|| value.kind !== 'cloudly-legacy-deployment-settlement-scratch-receipt'
|
|
1997
|
+
|| value.transactionCommitted !== true) {
|
|
1998
|
+
fail('INVALID_VALUE', `${pathArg}.kind`);
|
|
1999
|
+
}
|
|
2000
|
+
const output = {
|
|
2001
|
+
schemaVersion: 1 as const,
|
|
2002
|
+
kind: 'cloudly-legacy-deployment-settlement-scratch-receipt' as const,
|
|
2003
|
+
authority: normalizeAuthorityReferenceInternal(value.authority, `${pathArg}.authority`),
|
|
2004
|
+
requestSha256: readSha256(value.requestSha256, `${pathArg}.requestSha256`),
|
|
2005
|
+
stableOutcome: normalizeStableOutcomeInternal(value.stableOutcome, `${pathArg}.stableOutcome`),
|
|
2006
|
+
stableOutcomeSha256: readSha256(
|
|
2007
|
+
value.stableOutcomeSha256,
|
|
2008
|
+
`${pathArg}.stableOutcomeSha256`,
|
|
2009
|
+
),
|
|
2010
|
+
transactionCommitted: true as const,
|
|
2011
|
+
disposition: readLiteral(
|
|
2012
|
+
value.disposition,
|
|
2013
|
+
['applied', 'exact-replay', 'no-op'],
|
|
2014
|
+
`${pathArg}.disposition`,
|
|
2015
|
+
),
|
|
2016
|
+
completedAt: readInteger(value.completedAt, `${pathArg}.completedAt`, 1),
|
|
2017
|
+
};
|
|
2018
|
+
if (output.stableOutcomeSha256
|
|
2019
|
+
!== digestBytes(encodeNormalized(output.stableOutcome, `${pathArg}.stableOutcome`))) {
|
|
2020
|
+
fail('CROSS_FIELD_MISMATCH', `${pathArg}.stableOutcomeSha256`);
|
|
2021
|
+
}
|
|
2022
|
+
return output;
|
|
2023
|
+
};
|
|
2024
|
+
|
|
2025
|
+
const normalizeUnsignedScratchReceiptInternal = (
|
|
2026
|
+
valueArg: unknown,
|
|
2027
|
+
pathArg: string,
|
|
2028
|
+
): TCloudlyLegacyDeploymentSettlementUnsignedScratchReceiptV1 => {
|
|
2029
|
+
const value = readRecord(valueArg, pathArg);
|
|
2030
|
+
assertExactKeys(value, unsignedScratchReceiptKeys, pathArg);
|
|
2031
|
+
const payloadInput = Object.fromEntries(scratchReceiptPayloadKeys.map((keyArg) => [
|
|
2032
|
+
keyArg,
|
|
2033
|
+
value[keyArg],
|
|
2034
|
+
]));
|
|
2035
|
+
const payload = normalizeScratchReceiptPayloadInternal(payloadInput, `${pathArg}.payload`);
|
|
2036
|
+
const payloadSha256 = readSha256(value.payloadSha256, `${pathArg}.payloadSha256`);
|
|
2037
|
+
if (payloadSha256 !== digestBytes(encodeNormalized(
|
|
2038
|
+
scratchReceiptPayload(payload),
|
|
2039
|
+
`${pathArg}.payload`,
|
|
2040
|
+
))) {
|
|
2041
|
+
fail('CROSS_FIELD_MISMATCH', `${pathArg}.payloadSha256`);
|
|
2042
|
+
}
|
|
2043
|
+
return { ...payload, payloadSha256 };
|
|
2044
|
+
};
|
|
2045
|
+
|
|
2046
|
+
const normalizeScratchReceiptInternal = (
|
|
2047
|
+
valueArg: unknown,
|
|
2048
|
+
pathArg: string,
|
|
2049
|
+
): ICloudlyLegacyDeploymentSettlementScratchReceiptV1 => {
|
|
2050
|
+
const value = readRecord(valueArg, pathArg);
|
|
2051
|
+
assertExactKeys(value, scratchReceiptKeys, pathArg);
|
|
2052
|
+
const unsignedInput = Object.fromEntries(unsignedScratchReceiptKeys.map((keyArg) => [
|
|
2053
|
+
keyArg,
|
|
2054
|
+
value[keyArg],
|
|
2055
|
+
]));
|
|
2056
|
+
const unsigned = normalizeUnsignedScratchReceiptInternal(unsignedInput, `${pathArg}.unsigned`);
|
|
2057
|
+
return {
|
|
2058
|
+
...unsigned,
|
|
2059
|
+
mac: readMac(value.mac, `${pathArg}.mac`),
|
|
2060
|
+
};
|
|
2061
|
+
};
|
|
2062
|
+
|
|
2063
|
+
export const digestCloudlyLegacyDeploymentSettlementScratchReceiptPayload = (
|
|
2064
|
+
valueArg: unknown,
|
|
2065
|
+
): string => {
|
|
2066
|
+
const payload = normalizeScratchReceiptPayloadInternal(valueArg, 'scratchReceiptPayload');
|
|
2067
|
+
return digestBytes(encodeNormalized(
|
|
2068
|
+
scratchReceiptPayload(payload),
|
|
2069
|
+
'scratchReceiptPayload',
|
|
2070
|
+
));
|
|
2071
|
+
};
|
|
2072
|
+
|
|
2073
|
+
export const normalizeCloudlyLegacyDeploymentSettlementScratchReceipt = (
|
|
2074
|
+
valueArg: unknown,
|
|
2075
|
+
): Readonly<ICloudlyLegacyDeploymentSettlementScratchReceiptV1> => finalize(
|
|
2076
|
+
normalizeScratchReceiptInternal(valueArg, 'scratchReceipt'),
|
|
2077
|
+
cloudlyLegacyDeploymentSettlementLimits.maximumReceiptBytes,
|
|
2078
|
+
'scratchReceipt',
|
|
2079
|
+
);
|
|
2080
|
+
|
|
2081
|
+
export const encodeCloudlyLegacyDeploymentSettlementScratchReceipt = (
|
|
2082
|
+
valueArg: unknown,
|
|
2083
|
+
): Uint8Array => encodeNormalized(
|
|
2084
|
+
normalizeCloudlyLegacyDeploymentSettlementScratchReceipt(valueArg),
|
|
2085
|
+
'scratchReceipt',
|
|
2086
|
+
);
|
|
2087
|
+
|
|
2088
|
+
export const encodeCloudlyLegacyDeploymentSettlementScratchReceiptHmacInput = (
|
|
2089
|
+
valueArg: unknown,
|
|
2090
|
+
): Uint8Array => {
|
|
2091
|
+
const authenticated = finalize(
|
|
2092
|
+
normalizeUnsignedScratchReceiptInternal(valueArg, 'unsignedScratchReceipt'),
|
|
2093
|
+
cloudlyLegacyDeploymentSettlementLimits.maximumReceiptBytes,
|
|
2094
|
+
'unsignedScratchReceipt',
|
|
2095
|
+
);
|
|
2096
|
+
return frame(
|
|
2097
|
+
cloudlyLegacyDeploymentSettlementDomains.scratchReceiptHmac,
|
|
2098
|
+
encodeNormalized(authenticated, 'scratchReceipt.authenticated'),
|
|
2099
|
+
);
|
|
2100
|
+
};
|
|
2101
|
+
|
|
2102
|
+
export const digestCloudlyLegacyDeploymentSettlementScratchReceipt = (
|
|
2103
|
+
valueArg: unknown,
|
|
2104
|
+
): string => digestBytes(encodeCloudlyLegacyDeploymentSettlementScratchReceipt(valueArg));
|
|
2105
|
+
|
|
2106
|
+
const productionReceiptKeys = [
|
|
2107
|
+
'schemaVersion',
|
|
2108
|
+
'kind',
|
|
2109
|
+
'authority',
|
|
2110
|
+
'requestSha256',
|
|
2111
|
+
'scratchReceipt',
|
|
2112
|
+
'scratchReceiptSha256',
|
|
2113
|
+
'stableOutcome',
|
|
2114
|
+
'stableOutcomeSha256',
|
|
2115
|
+
'transactionCommitted',
|
|
2116
|
+
'disposition',
|
|
2117
|
+
'completedAt',
|
|
2118
|
+
'payloadSha256',
|
|
2119
|
+
'mac',
|
|
2120
|
+
] as const;
|
|
2121
|
+
const productionReceiptPayloadKeys = productionReceiptKeys.filter((keyArg) => (
|
|
2122
|
+
keyArg !== 'payloadSha256' && keyArg !== 'mac'
|
|
2123
|
+
));
|
|
2124
|
+
const unsignedProductionReceiptKeys = productionReceiptKeys.filter((keyArg) => keyArg !== 'mac');
|
|
2125
|
+
|
|
2126
|
+
const productionReceiptPayload = (
|
|
2127
|
+
valueArg: Omit<ICloudlyLegacyDeploymentSettlementProductionReceiptV1, 'payloadSha256' | 'mac'>,
|
|
2128
|
+
): unknown => ({
|
|
2129
|
+
schemaVersion: valueArg.schemaVersion,
|
|
2130
|
+
kind: valueArg.kind,
|
|
2131
|
+
authority: valueArg.authority,
|
|
2132
|
+
requestSha256: valueArg.requestSha256,
|
|
2133
|
+
scratchReceipt: valueArg.scratchReceipt,
|
|
2134
|
+
scratchReceiptSha256: valueArg.scratchReceiptSha256,
|
|
2135
|
+
stableOutcome: valueArg.stableOutcome,
|
|
2136
|
+
stableOutcomeSha256: valueArg.stableOutcomeSha256,
|
|
2137
|
+
transactionCommitted: valueArg.transactionCommitted,
|
|
2138
|
+
disposition: valueArg.disposition,
|
|
2139
|
+
completedAt: valueArg.completedAt,
|
|
2140
|
+
});
|
|
2141
|
+
|
|
2142
|
+
const normalizeProductionReceiptPayloadInternal = (
|
|
2143
|
+
valueArg: unknown,
|
|
2144
|
+
pathArg: string,
|
|
2145
|
+
): TCloudlyLegacyDeploymentSettlementProductionReceiptPayloadV1 => {
|
|
2146
|
+
const value = readRecord(valueArg, pathArg);
|
|
2147
|
+
assertExactKeys(value, productionReceiptPayloadKeys, pathArg);
|
|
2148
|
+
if (value.schemaVersion !== 1
|
|
2149
|
+
|| value.kind !== 'cloudly-legacy-deployment-settlement-production-receipt'
|
|
2150
|
+
|| value.transactionCommitted !== true) {
|
|
2151
|
+
fail('INVALID_VALUE', `${pathArg}.kind`);
|
|
2152
|
+
}
|
|
2153
|
+
const scratchReceipt = normalizeScratchReceiptInternal(
|
|
2154
|
+
value.scratchReceipt,
|
|
2155
|
+
`${pathArg}.scratchReceipt`,
|
|
2156
|
+
);
|
|
2157
|
+
const stableOutcome = normalizeStableOutcomeInternal(
|
|
2158
|
+
value.stableOutcome,
|
|
2159
|
+
`${pathArg}.stableOutcome`,
|
|
2160
|
+
);
|
|
2161
|
+
const stableOutcomeSha256 = readSha256(
|
|
2162
|
+
value.stableOutcomeSha256,
|
|
2163
|
+
`${pathArg}.stableOutcomeSha256`,
|
|
2164
|
+
);
|
|
2165
|
+
const authority = normalizeAuthorityReferenceInternal(value.authority, `${pathArg}.authority`);
|
|
2166
|
+
if (canonicalize(authority, `${pathArg}.authority`)
|
|
2167
|
+
!== canonicalize(scratchReceipt.authority, `${pathArg}.scratchReceipt.authority`)) {
|
|
2168
|
+
fail('CROSS_FIELD_MISMATCH', `${pathArg}.authority`);
|
|
2169
|
+
}
|
|
2170
|
+
const requestSha256 = readSha256(value.requestSha256, `${pathArg}.requestSha256`);
|
|
2171
|
+
const disposition = readLiteral(
|
|
2172
|
+
value.disposition,
|
|
2173
|
+
['applied', 'exact-replay', 'no-op'],
|
|
2174
|
+
`${pathArg}.disposition`,
|
|
2175
|
+
);
|
|
2176
|
+
if (requestSha256 !== scratchReceipt.requestSha256
|
|
2177
|
+
|| disposition !== scratchReceipt.disposition) {
|
|
2178
|
+
fail('CROSS_FIELD_MISMATCH', `${pathArg}.scratchReceipt`);
|
|
2179
|
+
}
|
|
2180
|
+
if (canonicalize(stableOutcome, `${pathArg}.stableOutcome`)
|
|
2181
|
+
!== canonicalize(scratchReceipt.stableOutcome, `${pathArg}.scratchReceipt.stableOutcome`)
|
|
2182
|
+
|| stableOutcomeSha256 !== scratchReceipt.stableOutcomeSha256
|
|
2183
|
+
|| stableOutcomeSha256
|
|
2184
|
+
!== digestBytes(encodeNormalized(stableOutcome, `${pathArg}.stableOutcome`))) {
|
|
2185
|
+
fail('CROSS_FIELD_MISMATCH', `${pathArg}.stableOutcome`);
|
|
2186
|
+
}
|
|
2187
|
+
const scratchReceiptSha256 = readSha256(
|
|
2188
|
+
value.scratchReceiptSha256,
|
|
2189
|
+
`${pathArg}.scratchReceiptSha256`,
|
|
2190
|
+
);
|
|
2191
|
+
if (scratchReceiptSha256
|
|
2192
|
+
!== digestBytes(encodeNormalized(scratchReceipt, `${pathArg}.scratchReceipt`))) {
|
|
2193
|
+
fail('CROSS_FIELD_MISMATCH', `${pathArg}.scratchReceiptSha256`);
|
|
2194
|
+
}
|
|
2195
|
+
return {
|
|
2196
|
+
schemaVersion: 1,
|
|
2197
|
+
kind: 'cloudly-legacy-deployment-settlement-production-receipt',
|
|
2198
|
+
authority,
|
|
2199
|
+
requestSha256,
|
|
2200
|
+
scratchReceipt,
|
|
2201
|
+
scratchReceiptSha256,
|
|
2202
|
+
stableOutcome,
|
|
2203
|
+
stableOutcomeSha256,
|
|
2204
|
+
transactionCommitted: true,
|
|
2205
|
+
disposition,
|
|
2206
|
+
completedAt: readInteger(
|
|
2207
|
+
value.completedAt,
|
|
2208
|
+
`${pathArg}.completedAt`,
|
|
2209
|
+
scratchReceipt.completedAt,
|
|
2210
|
+
),
|
|
2211
|
+
};
|
|
2212
|
+
};
|
|
2213
|
+
|
|
2214
|
+
const normalizeUnsignedProductionReceiptInternal = (
|
|
2215
|
+
valueArg: unknown,
|
|
2216
|
+
pathArg: string,
|
|
2217
|
+
): TCloudlyLegacyDeploymentSettlementUnsignedProductionReceiptV1 => {
|
|
2218
|
+
const value = readRecord(valueArg, pathArg);
|
|
2219
|
+
assertExactKeys(value, unsignedProductionReceiptKeys, pathArg);
|
|
2220
|
+
const payloadInput = Object.fromEntries(productionReceiptPayloadKeys.map((keyArg) => [
|
|
2221
|
+
keyArg,
|
|
2222
|
+
value[keyArg],
|
|
2223
|
+
]));
|
|
2224
|
+
const payload = normalizeProductionReceiptPayloadInternal(payloadInput, `${pathArg}.payload`);
|
|
2225
|
+
const payloadSha256 = readSha256(value.payloadSha256, `${pathArg}.payloadSha256`);
|
|
2226
|
+
if (payloadSha256 !== digestBytes(encodeNormalized(
|
|
2227
|
+
productionReceiptPayload(payload),
|
|
2228
|
+
`${pathArg}.payload`,
|
|
2229
|
+
))) {
|
|
2230
|
+
fail('CROSS_FIELD_MISMATCH', `${pathArg}.payloadSha256`);
|
|
2231
|
+
}
|
|
2232
|
+
return { ...payload, payloadSha256 };
|
|
2233
|
+
};
|
|
2234
|
+
|
|
2235
|
+
export const digestCloudlyLegacyDeploymentSettlementProductionReceiptPayload = (
|
|
2236
|
+
valueArg: unknown,
|
|
2237
|
+
): string => {
|
|
2238
|
+
const payload = normalizeProductionReceiptPayloadInternal(
|
|
2239
|
+
valueArg,
|
|
2240
|
+
'productionReceiptPayload',
|
|
2241
|
+
);
|
|
2242
|
+
return digestBytes(encodeNormalized(
|
|
2243
|
+
productionReceiptPayload(payload),
|
|
2244
|
+
'productionReceiptPayload',
|
|
2245
|
+
));
|
|
2246
|
+
};
|
|
2247
|
+
|
|
2248
|
+
export const normalizeCloudlyLegacyDeploymentSettlementProductionReceipt = (
|
|
2249
|
+
valueArg: unknown,
|
|
2250
|
+
): Readonly<ICloudlyLegacyDeploymentSettlementProductionReceiptV1> => {
|
|
2251
|
+
const value = readRecord(valueArg, 'productionReceipt');
|
|
2252
|
+
assertExactKeys(value, productionReceiptKeys, 'productionReceipt');
|
|
2253
|
+
const unsignedInput = Object.fromEntries(unsignedProductionReceiptKeys.map((keyArg) => [
|
|
2254
|
+
keyArg,
|
|
2255
|
+
value[keyArg],
|
|
2256
|
+
]));
|
|
2257
|
+
const unsigned = normalizeUnsignedProductionReceiptInternal(
|
|
2258
|
+
unsignedInput,
|
|
2259
|
+
'productionReceipt.unsigned',
|
|
2260
|
+
);
|
|
2261
|
+
return finalize({
|
|
2262
|
+
...unsigned,
|
|
2263
|
+
mac: readMac(value.mac, 'productionReceipt.mac'),
|
|
2264
|
+
}, cloudlyLegacyDeploymentSettlementLimits.maximumReceiptBytes, 'productionReceipt');
|
|
2265
|
+
};
|
|
2266
|
+
|
|
2267
|
+
export const encodeCloudlyLegacyDeploymentSettlementProductionReceipt = (
|
|
2268
|
+
valueArg: unknown,
|
|
2269
|
+
): Uint8Array => encodeNormalized(
|
|
2270
|
+
normalizeCloudlyLegacyDeploymentSettlementProductionReceipt(valueArg),
|
|
2271
|
+
'productionReceipt',
|
|
2272
|
+
);
|
|
2273
|
+
|
|
2274
|
+
export const encodeCloudlyLegacyDeploymentSettlementProductionReceiptHmacInput = (
|
|
2275
|
+
valueArg: unknown,
|
|
2276
|
+
): Uint8Array => {
|
|
2277
|
+
const authenticated = finalize(
|
|
2278
|
+
normalizeUnsignedProductionReceiptInternal(valueArg, 'unsignedProductionReceipt'),
|
|
2279
|
+
cloudlyLegacyDeploymentSettlementLimits.maximumReceiptBytes,
|
|
2280
|
+
'unsignedProductionReceipt',
|
|
2281
|
+
);
|
|
2282
|
+
return frame(
|
|
2283
|
+
cloudlyLegacyDeploymentSettlementDomains.productionReceiptHmac,
|
|
2284
|
+
encodeNormalized(authenticated, 'productionReceipt.authenticated'),
|
|
2285
|
+
);
|
|
2286
|
+
};
|
|
2287
|
+
|
|
2288
|
+
export const digestCloudlyLegacyDeploymentSettlementProductionReceipt = (
|
|
2289
|
+
valueArg: unknown,
|
|
2290
|
+
): string => digestBytes(encodeCloudlyLegacyDeploymentSettlementProductionReceipt(valueArg));
|
|
2291
|
+
|
|
2292
|
+
const withoutArtifactMac = <TArtifact extends { mac: string }>(
|
|
2293
|
+
artifactArg: TArtifact,
|
|
2294
|
+
): Omit<TArtifact, 'mac'> => {
|
|
2295
|
+
const { mac: _mac, ...unsigned } = artifactArg;
|
|
2296
|
+
return unsigned;
|
|
2297
|
+
};
|
|
2298
|
+
|
|
2299
|
+
const requireConsumerVerifiedHmac = async (
|
|
2300
|
+
authorityArg: ICloudlyLegacyDeploymentSettlementAuthorityReferenceV1,
|
|
2301
|
+
domainArg: ICloudlyLegacyDeploymentSettlementHmacVerificationInputV1['domain'],
|
|
2302
|
+
hmacInputArg: Uint8Array,
|
|
2303
|
+
macArg: string,
|
|
2304
|
+
verifierArg: TCloudlyLegacyDeploymentSettlementHmacVerifier,
|
|
2305
|
+
pathArg: string,
|
|
2306
|
+
): Promise<void> => {
|
|
2307
|
+
let verified = false;
|
|
2308
|
+
try {
|
|
2309
|
+
verified = await verifierArg({
|
|
2310
|
+
authority: authorityArg,
|
|
2311
|
+
domain: domainArg,
|
|
2312
|
+
hmacInput: new Uint8Array(hmacInputArg),
|
|
2313
|
+
mac: macArg,
|
|
2314
|
+
});
|
|
2315
|
+
} catch {
|
|
2316
|
+
verified = false;
|
|
2317
|
+
}
|
|
2318
|
+
if (!verified) fail('INVALID_VALUE', pathArg);
|
|
2319
|
+
};
|
|
2320
|
+
|
|
2321
|
+
const assertAuthorityTimestamp = (
|
|
2322
|
+
timestampArg: number,
|
|
2323
|
+
metadataArg: ICloudlyLegacyDeploymentSettlementAuthorityMetadataV1,
|
|
2324
|
+
pathArg: string,
|
|
2325
|
+
): void => {
|
|
2326
|
+
if (timestampArg < metadataArg.issuedAt || timestampArg >= metadataArg.expiresAt) {
|
|
2327
|
+
fail('CROSS_FIELD_MISMATCH', pathArg);
|
|
2328
|
+
}
|
|
2329
|
+
};
|
|
2330
|
+
|
|
2331
|
+
const assertAuthorityReferenceMatchesMetadata = (
|
|
2332
|
+
referenceArg: unknown,
|
|
2333
|
+
metadataArg: ICloudlyLegacyDeploymentSettlementAuthorityMetadataV1,
|
|
2334
|
+
pathArg: string,
|
|
2335
|
+
): void => {
|
|
2336
|
+
try {
|
|
2337
|
+
normalizeCloudlyLegacyDeploymentSettlementAuthorityReferenceForMetadata(
|
|
2338
|
+
referenceArg,
|
|
2339
|
+
metadataArg,
|
|
2340
|
+
);
|
|
2341
|
+
} catch {
|
|
2342
|
+
fail('CROSS_FIELD_MISMATCH', pathArg);
|
|
2343
|
+
}
|
|
2344
|
+
};
|
|
2345
|
+
|
|
2346
|
+
const assertRehearsalBindingMatchesAuthorityMetadata = (
|
|
2347
|
+
bindingArg: ICloudlyLegacyDeploymentSettlementRehearsalBindingV1,
|
|
2348
|
+
metadataArg: ICloudlyLegacyDeploymentSettlementAuthorityMetadataV1,
|
|
2349
|
+
pathArg: string,
|
|
2350
|
+
): void => {
|
|
2351
|
+
const expected = {
|
|
2352
|
+
settlementId: metadataArg.settlementId,
|
|
2353
|
+
runId: metadataArg.runId,
|
|
2354
|
+
rehearsalId: metadataArg.rehearsalId,
|
|
2355
|
+
scratchServiceId: metadataArg.scratchServiceId,
|
|
2356
|
+
allocationId: metadataArg.allocationId,
|
|
2357
|
+
allocationGeneration: metadataArg.allocationGeneration,
|
|
2358
|
+
allocationBindingSha256: metadataArg.allocationBindingSha256,
|
|
2359
|
+
allocationReceiptSha256: metadataArg.allocationReceiptSha256,
|
|
2360
|
+
backupId: metadataArg.backupId,
|
|
2361
|
+
backupSnapshotIdSha256: metadataArg.backupSnapshotIdSha256,
|
|
2362
|
+
backupProofSha256: metadataArg.backupProofSha256,
|
|
2363
|
+
sourceDataSha256: metadataArg.sourceDataSha256,
|
|
2364
|
+
restoredDataSha256: metadataArg.restoredDataSha256,
|
|
2365
|
+
digestProofSha256: metadataArg.digestProofSha256,
|
|
2366
|
+
targetImageDigest: metadataArg.targetImageDigest,
|
|
2367
|
+
targetVersion: metadataArg.targetVersion,
|
|
2368
|
+
targetManifestSha256: metadataArg.targetManifestSha256,
|
|
2369
|
+
targetConfigSha256: metadataArg.targetConfigSha256,
|
|
2370
|
+
};
|
|
2371
|
+
const actual = {
|
|
2372
|
+
settlementId: bindingArg.settlementId,
|
|
2373
|
+
runId: bindingArg.runId,
|
|
2374
|
+
rehearsalId: bindingArg.rehearsalId,
|
|
2375
|
+
scratchServiceId: bindingArg.scratchServiceId,
|
|
2376
|
+
allocationId: bindingArg.allocationId,
|
|
2377
|
+
allocationGeneration: bindingArg.allocationGeneration,
|
|
2378
|
+
allocationBindingSha256: bindingArg.allocationBindingSha256,
|
|
2379
|
+
allocationReceiptSha256: bindingArg.allocationReceiptSha256,
|
|
2380
|
+
backupId: bindingArg.backupId,
|
|
2381
|
+
backupSnapshotIdSha256: bindingArg.backupSnapshotIdSha256,
|
|
2382
|
+
backupProofSha256: bindingArg.backupProofSha256,
|
|
2383
|
+
sourceDataSha256: bindingArg.sourceDataSha256,
|
|
2384
|
+
restoredDataSha256: bindingArg.restoredDataSha256,
|
|
2385
|
+
digestProofSha256: bindingArg.digestProofSha256,
|
|
2386
|
+
targetImageDigest: bindingArg.targetImageDigest,
|
|
2387
|
+
targetVersion: bindingArg.targetVersion,
|
|
2388
|
+
targetManifestSha256: bindingArg.targetManifestSha256,
|
|
2389
|
+
targetConfigSha256: bindingArg.targetConfigSha256,
|
|
2390
|
+
};
|
|
2391
|
+
if (canonicalize(actual, pathArg) !== canonicalize(expected, `${pathArg}.expected`)) {
|
|
2392
|
+
fail('CROSS_FIELD_MISMATCH', pathArg);
|
|
2393
|
+
}
|
|
2394
|
+
};
|
|
2395
|
+
|
|
2396
|
+
export const normalizeCloudlyLegacyDeploymentSettlementRehearsalBindingForAuthority = (
|
|
2397
|
+
bindingArg: unknown,
|
|
2398
|
+
metadataArg: unknown,
|
|
2399
|
+
): Readonly<ICloudlyLegacyDeploymentSettlementRehearsalBindingV1> => {
|
|
2400
|
+
const metadata = normalizeCloudlyLegacyDeploymentSettlementAuthorityMetadata(metadataArg);
|
|
2401
|
+
const binding = normalizeCloudlyLegacyDeploymentSettlementRehearsalBinding(bindingArg);
|
|
2402
|
+
assertRehearsalBindingMatchesAuthorityMetadata(binding, metadata, 'rehearsalBinding.authority');
|
|
2403
|
+
return binding;
|
|
2404
|
+
};
|
|
2405
|
+
|
|
2406
|
+
export const normalizeCloudlyLegacyDeploymentSettlementPlanForAuthority = (
|
|
2407
|
+
planArg: unknown,
|
|
2408
|
+
metadataArg: unknown,
|
|
2409
|
+
): Readonly<ICloudlyLegacyDeploymentSettlementPlanV1> => {
|
|
2410
|
+
const metadata = normalizeCloudlyLegacyDeploymentSettlementAuthorityMetadata(metadataArg);
|
|
2411
|
+
const plan = normalizeCloudlyLegacyDeploymentSettlementPlan(planArg);
|
|
2412
|
+
assertAuthorityReferenceMatchesMetadata(plan.authority, metadata, 'plan.authority');
|
|
2413
|
+
if (plan.settlementId !== metadata.settlementId) {
|
|
2414
|
+
fail('CROSS_FIELD_MISMATCH', 'plan.settlementId');
|
|
2415
|
+
}
|
|
2416
|
+
assertAuthorityTimestamp(plan.effectiveAt, metadata, 'plan.effectiveAt');
|
|
2417
|
+
return plan;
|
|
2418
|
+
};
|
|
2419
|
+
|
|
2420
|
+
export const normalizeCloudlyLegacyDeploymentSettlementProductionRequestForAuthority = (
|
|
2421
|
+
requestArg: unknown,
|
|
2422
|
+
metadataArg: unknown,
|
|
2423
|
+
): Readonly<ICloudlyLegacyDeploymentSettlementProductionRequestV1> => {
|
|
2424
|
+
const metadata = normalizeCloudlyLegacyDeploymentSettlementAuthorityMetadata(metadataArg);
|
|
2425
|
+
const request = normalizeCloudlyLegacyDeploymentSettlementProductionRequest(requestArg);
|
|
2426
|
+
assertAuthorityReferenceMatchesMetadata(
|
|
2427
|
+
request.authority,
|
|
2428
|
+
metadata,
|
|
2429
|
+
'productionRequest.authority',
|
|
2430
|
+
);
|
|
2431
|
+
normalizeCloudlyLegacyDeploymentSettlementPlanForAuthority(request.plan, metadata);
|
|
2432
|
+
normalizeCloudlyLegacyDeploymentSettlementRehearsalBindingForAuthority(
|
|
2433
|
+
request.rehearsalBinding,
|
|
2434
|
+
metadata,
|
|
2435
|
+
);
|
|
2436
|
+
assertAuthorityTimestamp(request.requestedAt, metadata, 'productionRequest.requestedAt');
|
|
2437
|
+
return request;
|
|
2438
|
+
};
|
|
2439
|
+
|
|
2440
|
+
export const normalizeAuthenticatedCloudlyLegacyDeploymentSettlementRehearsalBindingForAuthority = async (
|
|
2441
|
+
bindingArg: unknown,
|
|
2442
|
+
metadataArg: unknown,
|
|
2443
|
+
verifierArg: TCloudlyLegacyDeploymentSettlementHmacVerifier,
|
|
2444
|
+
): Promise<Readonly<IAuthenticatedCloudlyLegacyDeploymentSettlementRehearsalBindingV1>> => {
|
|
2445
|
+
const metadata = normalizeCloudlyLegacyDeploymentSettlementAuthorityMetadata(metadataArg);
|
|
2446
|
+
const binding = normalizeCloudlyLegacyDeploymentSettlementAuthenticatedRehearsalBindingStructure(
|
|
2447
|
+
bindingArg,
|
|
2448
|
+
);
|
|
2449
|
+
assertAuthorityReferenceMatchesMetadata(binding.authority, metadata, 'rehearsalBinding.authority');
|
|
2450
|
+
normalizeCloudlyLegacyDeploymentSettlementRehearsalBindingForAuthority(
|
|
2451
|
+
binding.payload,
|
|
2452
|
+
metadata,
|
|
2453
|
+
);
|
|
2454
|
+
await requireConsumerVerifiedHmac(
|
|
2455
|
+
binding.authority,
|
|
2456
|
+
cloudlyLegacyDeploymentSettlementDomains.rehearsalBindingHmac,
|
|
2457
|
+
encodeCloudlyLegacyDeploymentSettlementRehearsalBindingHmacInput(
|
|
2458
|
+
withoutArtifactMac(binding),
|
|
2459
|
+
),
|
|
2460
|
+
binding.mac,
|
|
2461
|
+
verifierArg,
|
|
2462
|
+
'rehearsalBinding.mac',
|
|
2463
|
+
);
|
|
2464
|
+
return binding;
|
|
2465
|
+
};
|
|
2466
|
+
|
|
2467
|
+
export const normalizeAuthenticatedCloudlyLegacyDeploymentSettlementPlanForAuthority = async (
|
|
2468
|
+
planArg: unknown,
|
|
2469
|
+
metadataArg: unknown,
|
|
2470
|
+
verifierArg: TCloudlyLegacyDeploymentSettlementHmacVerifier,
|
|
2471
|
+
): Promise<Readonly<IAuthenticatedCloudlyLegacyDeploymentSettlementPlanV1>> => {
|
|
2472
|
+
const metadata = normalizeCloudlyLegacyDeploymentSettlementAuthorityMetadata(metadataArg);
|
|
2473
|
+
const plan = normalizeCloudlyLegacyDeploymentSettlementAuthenticatedPlanStructure(planArg);
|
|
2474
|
+
assertAuthorityReferenceMatchesMetadata(plan.authority, metadata, 'plan.authority');
|
|
2475
|
+
normalizeCloudlyLegacyDeploymentSettlementPlanForAuthority(plan.payload, metadata);
|
|
2476
|
+
await requireConsumerVerifiedHmac(
|
|
2477
|
+
plan.authority,
|
|
2478
|
+
cloudlyLegacyDeploymentSettlementDomains.planHmac,
|
|
2479
|
+
encodeCloudlyLegacyDeploymentSettlementPlanHmacInput(withoutArtifactMac(plan)),
|
|
2480
|
+
plan.mac,
|
|
2481
|
+
verifierArg,
|
|
2482
|
+
'plan.mac',
|
|
2483
|
+
);
|
|
2484
|
+
return plan;
|
|
2485
|
+
};
|
|
2486
|
+
|
|
2487
|
+
export const normalizeAuthenticatedCloudlyLegacyDeploymentSettlementProductionRequestForAuthority = async (
|
|
2488
|
+
requestArg: unknown,
|
|
2489
|
+
metadataArg: unknown,
|
|
2490
|
+
verifierArg: TCloudlyLegacyDeploymentSettlementHmacVerifier,
|
|
2491
|
+
): Promise<Readonly<IAuthenticatedCloudlyLegacyDeploymentSettlementProductionRequestV1>> => {
|
|
2492
|
+
const metadata = normalizeCloudlyLegacyDeploymentSettlementAuthorityMetadata(metadataArg);
|
|
2493
|
+
const request = normalizeCloudlyLegacyDeploymentSettlementAuthenticatedProductionRequestStructure(
|
|
2494
|
+
requestArg,
|
|
2495
|
+
);
|
|
2496
|
+
assertAuthorityReferenceMatchesMetadata(
|
|
2497
|
+
request.authority,
|
|
2498
|
+
metadata,
|
|
2499
|
+
'productionRequest.authority',
|
|
2500
|
+
);
|
|
2501
|
+
normalizeCloudlyLegacyDeploymentSettlementProductionRequestForAuthority(
|
|
2502
|
+
request.payload,
|
|
2503
|
+
metadata,
|
|
2504
|
+
);
|
|
2505
|
+
await requireConsumerVerifiedHmac(
|
|
2506
|
+
request.authority,
|
|
2507
|
+
cloudlyLegacyDeploymentSettlementDomains.productionRequestHmac,
|
|
2508
|
+
encodeCloudlyLegacyDeploymentSettlementProductionRequestHmacInput(
|
|
2509
|
+
withoutArtifactMac(request),
|
|
2510
|
+
),
|
|
2511
|
+
request.mac,
|
|
2512
|
+
verifierArg,
|
|
2513
|
+
'productionRequest.mac',
|
|
2514
|
+
);
|
|
2515
|
+
return request;
|
|
2516
|
+
};
|
|
2517
|
+
|
|
2518
|
+
export const normalizeAuthenticatedCloudlyLegacyDeploymentSettlementCheckResultForAuthority = async (
|
|
2519
|
+
resultArg: unknown,
|
|
2520
|
+
metadataArg: unknown,
|
|
2521
|
+
requestArg: unknown,
|
|
2522
|
+
verifierArg: TCloudlyLegacyDeploymentSettlementHmacVerifier,
|
|
2523
|
+
): Promise<Readonly<IAuthenticatedCloudlyLegacyDeploymentSettlementCheckResultV1>> => {
|
|
2524
|
+
const metadata = normalizeCloudlyLegacyDeploymentSettlementAuthorityMetadata(metadataArg);
|
|
2525
|
+
const request = await normalizeAuthenticatedCloudlyLegacyDeploymentSettlementProductionRequestForAuthority(
|
|
2526
|
+
requestArg,
|
|
2527
|
+
metadata,
|
|
2528
|
+
verifierArg,
|
|
2529
|
+
);
|
|
2530
|
+
const result = normalizeCloudlyLegacyDeploymentSettlementAuthenticatedCheckResultStructureForRequest(
|
|
2531
|
+
resultArg,
|
|
2532
|
+
request,
|
|
2533
|
+
);
|
|
2534
|
+
assertAuthorityReferenceMatchesMetadata(result.authority, metadata, 'checkResult.authority');
|
|
2535
|
+
assertAuthorityTimestamp(result.payload.checkedAt, metadata, 'checkResult.checkedAt');
|
|
2536
|
+
await requireConsumerVerifiedHmac(
|
|
2537
|
+
result.authority,
|
|
2538
|
+
cloudlyLegacyDeploymentSettlementDomains.checkResultHmac,
|
|
2539
|
+
encodeCloudlyLegacyDeploymentSettlementCheckResultHmacInput(withoutArtifactMac(result)),
|
|
2540
|
+
result.mac,
|
|
2541
|
+
verifierArg,
|
|
2542
|
+
'checkResult.mac',
|
|
2543
|
+
);
|
|
2544
|
+
return result;
|
|
2545
|
+
};
|
|
2546
|
+
|
|
2547
|
+
export const normalizeAuthenticatedCloudlyLegacyDeploymentSettlementApplyResultForAuthority = async (
|
|
2548
|
+
resultArg: unknown,
|
|
2549
|
+
metadataArg: unknown,
|
|
2550
|
+
requestArg: unknown,
|
|
2551
|
+
verifierArg: TCloudlyLegacyDeploymentSettlementHmacVerifier,
|
|
2552
|
+
): Promise<Readonly<IAuthenticatedCloudlyLegacyDeploymentSettlementApplyResultV1>> => {
|
|
2553
|
+
const metadata = normalizeCloudlyLegacyDeploymentSettlementAuthorityMetadata(metadataArg);
|
|
2554
|
+
const request = await normalizeAuthenticatedCloudlyLegacyDeploymentSettlementProductionRequestForAuthority(
|
|
2555
|
+
requestArg,
|
|
2556
|
+
metadata,
|
|
2557
|
+
verifierArg,
|
|
2558
|
+
);
|
|
2559
|
+
const result = normalizeCloudlyLegacyDeploymentSettlementAuthenticatedApplyResultStructureForRequest(
|
|
2560
|
+
resultArg,
|
|
2561
|
+
request,
|
|
2562
|
+
);
|
|
2563
|
+
assertAuthorityReferenceMatchesMetadata(result.authority, metadata, 'applyResult.authority');
|
|
2564
|
+
assertAuthorityTimestamp(
|
|
2565
|
+
result.payload.status === 'completed'
|
|
2566
|
+
? result.payload.completedAt
|
|
2567
|
+
: result.payload.rejectedAt,
|
|
2568
|
+
metadata,
|
|
2569
|
+
'applyResult.completedAt',
|
|
2570
|
+
);
|
|
2571
|
+
await requireConsumerVerifiedHmac(
|
|
2572
|
+
result.authority,
|
|
2573
|
+
cloudlyLegacyDeploymentSettlementDomains.applyResultHmac,
|
|
2574
|
+
encodeCloudlyLegacyDeploymentSettlementApplyResultHmacInput(withoutArtifactMac(result)),
|
|
2575
|
+
result.mac,
|
|
2576
|
+
verifierArg,
|
|
2577
|
+
'applyResult.mac',
|
|
2578
|
+
);
|
|
2579
|
+
return result;
|
|
2580
|
+
};
|
|
2581
|
+
|
|
2582
|
+
export const normalizeAuthenticatedCloudlyLegacyDeploymentSettlementStableOutcomeForAuthority = async (
|
|
2583
|
+
outcomeArg: unknown,
|
|
2584
|
+
metadataArg: unknown,
|
|
2585
|
+
requestArg: unknown,
|
|
2586
|
+
verifierArg: TCloudlyLegacyDeploymentSettlementHmacVerifier,
|
|
2587
|
+
): Promise<Readonly<IAuthenticatedCloudlyLegacyDeploymentSettlementStableOutcomeV1>> => {
|
|
2588
|
+
const metadata = normalizeCloudlyLegacyDeploymentSettlementAuthorityMetadata(metadataArg);
|
|
2589
|
+
const request = await normalizeAuthenticatedCloudlyLegacyDeploymentSettlementProductionRequestForAuthority(
|
|
2590
|
+
requestArg,
|
|
2591
|
+
metadata,
|
|
2592
|
+
verifierArg,
|
|
2593
|
+
);
|
|
2594
|
+
const outcome = normalizeCloudlyLegacyDeploymentSettlementAuthenticatedStableOutcomeStructureForRequest(
|
|
2595
|
+
outcomeArg,
|
|
2596
|
+
request,
|
|
2597
|
+
);
|
|
2598
|
+
assertAuthorityReferenceMatchesMetadata(outcome.authority, metadata, 'stableOutcome.authority');
|
|
2599
|
+
if (outcome.payload.settlementId !== metadata.settlementId
|
|
2600
|
+
|| outcome.payload.runId !== metadata.runId) {
|
|
2601
|
+
fail('CROSS_FIELD_MISMATCH', 'stableOutcome.authority');
|
|
2602
|
+
}
|
|
2603
|
+
assertAuthorityTimestamp(outcome.payload.effectiveAt, metadata, 'stableOutcome.effectiveAt');
|
|
2604
|
+
await requireConsumerVerifiedHmac(
|
|
2605
|
+
outcome.authority,
|
|
2606
|
+
cloudlyLegacyDeploymentSettlementDomains.stableOutcomeHmac,
|
|
2607
|
+
encodeCloudlyLegacyDeploymentSettlementStableOutcomeHmacInput(
|
|
2608
|
+
withoutArtifactMac(outcome),
|
|
2609
|
+
),
|
|
2610
|
+
outcome.mac,
|
|
2611
|
+
verifierArg,
|
|
2612
|
+
'stableOutcome.mac',
|
|
2613
|
+
);
|
|
2614
|
+
return outcome;
|
|
2615
|
+
};
|
|
2616
|
+
|
|
2617
|
+
export const normalizeCloudlyLegacyDeploymentSettlementScratchReceiptForAuthority = async (
|
|
2618
|
+
receiptArg: unknown,
|
|
2619
|
+
metadataArg: unknown,
|
|
2620
|
+
requestArg: unknown,
|
|
2621
|
+
verifierArg: TCloudlyLegacyDeploymentSettlementHmacVerifier,
|
|
2622
|
+
): Promise<Readonly<ICloudlyLegacyDeploymentSettlementScratchReceiptV1>> => {
|
|
2623
|
+
const metadata = normalizeCloudlyLegacyDeploymentSettlementAuthorityMetadata(metadataArg);
|
|
2624
|
+
const request = await normalizeAuthenticatedCloudlyLegacyDeploymentSettlementProductionRequestForAuthority(
|
|
2625
|
+
requestArg,
|
|
2626
|
+
metadata,
|
|
2627
|
+
verifierArg,
|
|
2628
|
+
);
|
|
2629
|
+
const receipt = normalizeCloudlyLegacyDeploymentSettlementScratchReceiptStructureForRequest(
|
|
2630
|
+
receiptArg,
|
|
2631
|
+
request,
|
|
2632
|
+
);
|
|
2633
|
+
assertAuthorityReferenceMatchesMetadata(receipt.authority, metadata, 'scratchReceipt.authority');
|
|
2634
|
+
if (receipt.stableOutcome.settlementId !== metadata.settlementId
|
|
2635
|
+
|| receipt.stableOutcome.runId !== metadata.runId) {
|
|
2636
|
+
fail('CROSS_FIELD_MISMATCH', 'scratchReceipt.stableOutcome');
|
|
2637
|
+
}
|
|
2638
|
+
assertAuthorityTimestamp(receipt.stableOutcome.effectiveAt, metadata, 'scratchReceipt.effectiveAt');
|
|
2639
|
+
assertAuthorityTimestamp(receipt.completedAt, metadata, 'scratchReceipt.completedAt');
|
|
2640
|
+
await requireConsumerVerifiedHmac(
|
|
2641
|
+
receipt.authority,
|
|
2642
|
+
cloudlyLegacyDeploymentSettlementDomains.scratchReceiptHmac,
|
|
2643
|
+
encodeCloudlyLegacyDeploymentSettlementScratchReceiptHmacInput(
|
|
2644
|
+
withoutArtifactMac(receipt),
|
|
2645
|
+
),
|
|
2646
|
+
receipt.mac,
|
|
2647
|
+
verifierArg,
|
|
2648
|
+
'scratchReceipt.mac',
|
|
2649
|
+
);
|
|
2650
|
+
return receipt;
|
|
2651
|
+
};
|
|
2652
|
+
|
|
2653
|
+
export const normalizeCloudlyLegacyDeploymentSettlementProductionReceiptForAuthority = async (
|
|
2654
|
+
receiptArg: unknown,
|
|
2655
|
+
metadataArg: unknown,
|
|
2656
|
+
requestArg: unknown,
|
|
2657
|
+
verifierArg: TCloudlyLegacyDeploymentSettlementHmacVerifier,
|
|
2658
|
+
): Promise<Readonly<ICloudlyLegacyDeploymentSettlementProductionReceiptV1>> => {
|
|
2659
|
+
const metadata = normalizeCloudlyLegacyDeploymentSettlementAuthorityMetadata(metadataArg);
|
|
2660
|
+
const request = await normalizeAuthenticatedCloudlyLegacyDeploymentSettlementProductionRequestForAuthority(
|
|
2661
|
+
requestArg,
|
|
2662
|
+
metadata,
|
|
2663
|
+
verifierArg,
|
|
2664
|
+
);
|
|
2665
|
+
const receipt = normalizeCloudlyLegacyDeploymentSettlementProductionReceiptStructureForRequest(
|
|
2666
|
+
receiptArg,
|
|
2667
|
+
request,
|
|
2668
|
+
);
|
|
2669
|
+
assertAuthorityReferenceMatchesMetadata(
|
|
2670
|
+
receipt.authority,
|
|
2671
|
+
metadata,
|
|
2672
|
+
'productionReceipt.authority',
|
|
2673
|
+
);
|
|
2674
|
+
await normalizeCloudlyLegacyDeploymentSettlementScratchReceiptForAuthority(
|
|
2675
|
+
receipt.scratchReceipt,
|
|
2676
|
+
metadata,
|
|
2677
|
+
request,
|
|
2678
|
+
verifierArg,
|
|
2679
|
+
);
|
|
2680
|
+
if (receipt.stableOutcome.settlementId !== metadata.settlementId
|
|
2681
|
+
|| receipt.stableOutcome.runId !== metadata.runId) {
|
|
2682
|
+
fail('CROSS_FIELD_MISMATCH', 'productionReceipt.stableOutcome');
|
|
2683
|
+
}
|
|
2684
|
+
assertAuthorityTimestamp(receipt.completedAt, metadata, 'productionReceipt.completedAt');
|
|
2685
|
+
await requireConsumerVerifiedHmac(
|
|
2686
|
+
receipt.authority,
|
|
2687
|
+
cloudlyLegacyDeploymentSettlementDomains.productionReceiptHmac,
|
|
2688
|
+
encodeCloudlyLegacyDeploymentSettlementProductionReceiptHmacInput(
|
|
2689
|
+
withoutArtifactMac(receipt),
|
|
2690
|
+
),
|
|
2691
|
+
receipt.mac,
|
|
2692
|
+
verifierArg,
|
|
2693
|
+
'productionReceipt.mac',
|
|
2694
|
+
);
|
|
2695
|
+
return receipt;
|
|
2696
|
+
};
|
|
2697
|
+
|
|
2698
|
+
const assertAuthenticatedAuthorityMatches = (
|
|
2699
|
+
authorityArg: ICloudlyLegacyDeploymentSettlementAuthorityReferenceV1,
|
|
2700
|
+
expectedArg: ICloudlyLegacyDeploymentSettlementAuthorityReferenceV1,
|
|
2701
|
+
pathArg: string,
|
|
2702
|
+
): void => {
|
|
2703
|
+
if (canonicalize(authorityArg, pathArg) !== canonicalize(expectedArg, `${pathArg}.expected`)) {
|
|
2704
|
+
fail('CROSS_FIELD_MISMATCH', pathArg);
|
|
2705
|
+
}
|
|
2706
|
+
};
|
|
2707
|
+
|
|
2708
|
+
const assertSummaryMatchesProductionRequest = (
|
|
2709
|
+
summaryArg: ICloudlyLegacyDeploymentSettlementSafeResultBaseV1,
|
|
2710
|
+
requestArg: ICloudlyLegacyDeploymentSettlementProductionRequestV1,
|
|
2711
|
+
pathArg: string,
|
|
2712
|
+
): void => {
|
|
2713
|
+
if (summaryArg.requestSha256
|
|
2714
|
+
!== digestCloudlyLegacyDeploymentSettlementProductionRequest(requestArg)
|
|
2715
|
+
|| summaryArg.planSha256 !== requestArg.planSha256
|
|
2716
|
+
|| summaryArg.settlementId !== requestArg.plan.settlementId
|
|
2717
|
+
|| summaryArg.sourceStateHmac !== requestArg.plan.sourceStateHmac
|
|
2718
|
+
|| summaryArg.finalStateHmac !== requestArg.plan.finalStateHmac
|
|
2719
|
+
|| canonicalize(summaryArg.counts, `${pathArg}.counts`)
|
|
2720
|
+
!== canonicalize({
|
|
2721
|
+
operationCount: requestArg.plan.operationCount,
|
|
2722
|
+
routeClaimsStabilized: requestArg.plan.entries.reduce(
|
|
2723
|
+
(sumArg, entryArg) => sumArg + entryArg.routeClaimsStabilized,
|
|
2724
|
+
0,
|
|
2725
|
+
),
|
|
2726
|
+
routeClaimsRemoved: requestArg.plan.entries.reduce(
|
|
2727
|
+
(sumArg, entryArg) => sumArg + entryArg.routeClaimsRemoved,
|
|
2728
|
+
0,
|
|
2729
|
+
),
|
|
2730
|
+
resourceClaimsRemoved: requestArg.plan.entries.reduce(
|
|
2731
|
+
(sumArg, entryArg) => sumArg + entryArg.resourceClaimsRemoved,
|
|
2732
|
+
0,
|
|
2733
|
+
),
|
|
2734
|
+
}, `${pathArg}.expectedCounts`)
|
|
2735
|
+
|| canonicalize(summaryArg.classificationCounts, `${pathArg}.classificationCounts`)
|
|
2736
|
+
!== canonicalize(
|
|
2737
|
+
requestArg.plan.classificationCounts,
|
|
2738
|
+
`${pathArg}.expectedClassificationCounts`,
|
|
2739
|
+
)) {
|
|
2740
|
+
fail('CROSS_FIELD_MISMATCH', pathArg);
|
|
2741
|
+
}
|
|
2742
|
+
};
|
|
2743
|
+
|
|
2744
|
+
const assertStableOutcomeMatchesProductionRequest = (
|
|
2745
|
+
stableOutcomeArg: ICloudlyLegacyDeploymentSettlementStableOutcomeV1,
|
|
2746
|
+
requestArg: ICloudlyLegacyDeploymentSettlementProductionRequestV1,
|
|
2747
|
+
pathArg: string,
|
|
2748
|
+
): void => {
|
|
2749
|
+
const expectedSettlements: ICloudlyLegacyDeploymentSettlementStableOutcomeEntryV1[] =
|
|
2750
|
+
requestArg.plan.entries.map((entryArg) => ({
|
|
2751
|
+
operationId: entryArg.operationId,
|
|
2752
|
+
finalRevision: entryArg.finalRevision,
|
|
2753
|
+
finalDocumentHmac: entryArg.finalDocumentHmac,
|
|
2754
|
+
}));
|
|
2755
|
+
if (stableOutcomeArg.settlementId !== requestArg.plan.settlementId
|
|
2756
|
+
|| stableOutcomeArg.runId !== requestArg.rehearsalBinding.runId
|
|
2757
|
+
|| stableOutcomeArg.rehearsalBindingSha256 !== requestArg.rehearsalBindingSha256
|
|
2758
|
+
|| stableOutcomeArg.effectiveAt !== requestArg.plan.effectiveAt
|
|
2759
|
+
|| stableOutcomeArg.planSha256 !== requestArg.planSha256
|
|
2760
|
+
|| stableOutcomeArg.sourceStateHmac !== requestArg.plan.sourceStateHmac
|
|
2761
|
+
|| stableOutcomeArg.finalStateHmac !== requestArg.plan.finalStateHmac
|
|
2762
|
+
|| canonicalize(stableOutcomeArg.settlements, `${pathArg}.settlements`)
|
|
2763
|
+
!== canonicalize(expectedSettlements, `${pathArg}.expectedSettlements`)) {
|
|
2764
|
+
fail('CROSS_FIELD_MISMATCH', pathArg);
|
|
2765
|
+
}
|
|
2766
|
+
assertSummaryMatchesProductionRequest({
|
|
2767
|
+
schemaVersion: 1,
|
|
2768
|
+
requestSha256: digestCloudlyLegacyDeploymentSettlementProductionRequest(requestArg),
|
|
2769
|
+
planSha256: stableOutcomeArg.planSha256,
|
|
2770
|
+
settlementId: stableOutcomeArg.settlementId,
|
|
2771
|
+
sourceStateHmac: stableOutcomeArg.sourceStateHmac,
|
|
2772
|
+
finalStateHmac: stableOutcomeArg.finalStateHmac,
|
|
2773
|
+
transactionSupported: true,
|
|
2774
|
+
counts: stableOutcomeArg.counts,
|
|
2775
|
+
classificationCounts: stableOutcomeArg.classificationCounts,
|
|
2776
|
+
}, requestArg, pathArg);
|
|
2777
|
+
};
|
|
2778
|
+
|
|
2779
|
+
/** Structural/request binding only; this function does not authenticate MACs. */
|
|
2780
|
+
export const normalizeCloudlyLegacyDeploymentSettlementAuthenticatedCheckResultStructureForRequest = (
|
|
2781
|
+
resultArg: unknown,
|
|
2782
|
+
requestArg: unknown,
|
|
2783
|
+
): Readonly<IAuthenticatedCloudlyLegacyDeploymentSettlementCheckResultV1> => {
|
|
2784
|
+
const request = normalizeCloudlyLegacyDeploymentSettlementAuthenticatedProductionRequestStructure(
|
|
2785
|
+
requestArg,
|
|
2786
|
+
);
|
|
2787
|
+
const result = normalizeCloudlyLegacyDeploymentSettlementAuthenticatedCheckResultStructure(resultArg);
|
|
2788
|
+
assertAuthenticatedAuthorityMatches(result.authority, request.authority, 'checkResult.authority');
|
|
2789
|
+
assertSummaryMatchesProductionRequest(result.payload, request.payload, 'checkResult.payload');
|
|
2790
|
+
if (result.payload.checkedAt < request.payload.requestedAt) {
|
|
2791
|
+
fail('CROSS_FIELD_MISMATCH', 'checkResult.payload.checkedAt');
|
|
2792
|
+
}
|
|
2793
|
+
return result;
|
|
2794
|
+
};
|
|
2795
|
+
|
|
2796
|
+
export const normalizeCloudlyLegacyDeploymentSettlementAuthenticatedApplyResultStructureForRequest = (
|
|
2797
|
+
resultArg: unknown,
|
|
2798
|
+
requestArg: unknown,
|
|
2799
|
+
): Readonly<IAuthenticatedCloudlyLegacyDeploymentSettlementApplyResultV1> => {
|
|
2800
|
+
const request = normalizeCloudlyLegacyDeploymentSettlementAuthenticatedProductionRequestStructure(
|
|
2801
|
+
requestArg,
|
|
2802
|
+
);
|
|
2803
|
+
const result = normalizeCloudlyLegacyDeploymentSettlementAuthenticatedApplyResultStructure(resultArg);
|
|
2804
|
+
assertAuthenticatedAuthorityMatches(result.authority, request.authority, 'applyResult.authority');
|
|
2805
|
+
assertSummaryMatchesProductionRequest(result.payload, request.payload, 'applyResult.payload');
|
|
2806
|
+
const resultAt = result.payload.status === 'completed'
|
|
2807
|
+
? result.payload.completedAt
|
|
2808
|
+
: result.payload.rejectedAt;
|
|
2809
|
+
if (resultAt < request.payload.requestedAt) {
|
|
2810
|
+
fail('CROSS_FIELD_MISMATCH', 'applyResult.payload.completedAt');
|
|
2811
|
+
}
|
|
2812
|
+
return result;
|
|
2813
|
+
};
|
|
2814
|
+
|
|
2815
|
+
export const normalizeCloudlyLegacyDeploymentSettlementAuthenticatedStableOutcomeStructureForRequest = (
|
|
2816
|
+
outcomeArg: unknown,
|
|
2817
|
+
requestArg: unknown,
|
|
2818
|
+
): Readonly<IAuthenticatedCloudlyLegacyDeploymentSettlementStableOutcomeV1> => {
|
|
2819
|
+
const request = normalizeCloudlyLegacyDeploymentSettlementAuthenticatedProductionRequestStructure(
|
|
2820
|
+
requestArg,
|
|
2821
|
+
);
|
|
2822
|
+
const outcome = normalizeCloudlyLegacyDeploymentSettlementAuthenticatedStableOutcomeStructure(outcomeArg);
|
|
2823
|
+
assertAuthenticatedAuthorityMatches(
|
|
2824
|
+
outcome.authority,
|
|
2825
|
+
request.authority,
|
|
2826
|
+
'stableOutcome.authority',
|
|
2827
|
+
);
|
|
2828
|
+
assertStableOutcomeMatchesProductionRequest(
|
|
2829
|
+
outcome.payload,
|
|
2830
|
+
request.payload,
|
|
2831
|
+
'stableOutcome.payload',
|
|
2832
|
+
);
|
|
2833
|
+
return outcome;
|
|
2834
|
+
};
|
|
2835
|
+
|
|
2836
|
+
/** Structural/request binding only; this function does not authenticate MACs. */
|
|
2837
|
+
export const normalizeCloudlyLegacyDeploymentSettlementScratchReceiptStructureForRequest = (
|
|
2838
|
+
receiptArg: unknown,
|
|
2839
|
+
requestArg: unknown,
|
|
2840
|
+
): Readonly<ICloudlyLegacyDeploymentSettlementScratchReceiptV1> => {
|
|
2841
|
+
const request = normalizeCloudlyLegacyDeploymentSettlementAuthenticatedProductionRequestStructure(
|
|
2842
|
+
requestArg,
|
|
2843
|
+
);
|
|
2844
|
+
const receipt = normalizeCloudlyLegacyDeploymentSettlementScratchReceipt(receiptArg);
|
|
2845
|
+
assertAuthenticatedAuthorityMatches(receipt.authority, request.authority, 'scratchReceipt.authority');
|
|
2846
|
+
if (receipt.requestSha256
|
|
2847
|
+
!== digestCloudlyLegacyDeploymentSettlementProductionRequest(request.payload)
|
|
2848
|
+
|| receipt.completedAt < request.payload.requestedAt) {
|
|
2849
|
+
fail('CROSS_FIELD_MISMATCH', 'scratchReceipt.requestSha256');
|
|
2850
|
+
}
|
|
2851
|
+
assertStableOutcomeMatchesProductionRequest(
|
|
2852
|
+
receipt.stableOutcome,
|
|
2853
|
+
request.payload,
|
|
2854
|
+
'scratchReceipt.stableOutcome',
|
|
2855
|
+
);
|
|
2856
|
+
return receipt;
|
|
2857
|
+
};
|
|
2858
|
+
|
|
2859
|
+
export const normalizeCloudlyLegacyDeploymentSettlementProductionReceiptStructureForRequest = (
|
|
2860
|
+
receiptArg: unknown,
|
|
2861
|
+
requestArg: unknown,
|
|
2862
|
+
): Readonly<ICloudlyLegacyDeploymentSettlementProductionReceiptV1> => {
|
|
2863
|
+
const request = normalizeCloudlyLegacyDeploymentSettlementAuthenticatedProductionRequestStructure(
|
|
2864
|
+
requestArg,
|
|
2865
|
+
);
|
|
2866
|
+
const receipt = normalizeCloudlyLegacyDeploymentSettlementProductionReceipt(receiptArg);
|
|
2867
|
+
normalizeCloudlyLegacyDeploymentSettlementScratchReceiptStructureForRequest(
|
|
2868
|
+
receipt.scratchReceipt,
|
|
2869
|
+
request,
|
|
2870
|
+
);
|
|
2871
|
+
assertAuthenticatedAuthorityMatches(
|
|
2872
|
+
receipt.authority,
|
|
2873
|
+
request.authority,
|
|
2874
|
+
'productionReceipt.authority',
|
|
2875
|
+
);
|
|
2876
|
+
if (receipt.requestSha256
|
|
2877
|
+
!== digestCloudlyLegacyDeploymentSettlementProductionRequest(request.payload)
|
|
2878
|
+
|| receipt.completedAt < request.payload.requestedAt) {
|
|
2879
|
+
fail('CROSS_FIELD_MISMATCH', 'productionReceipt.requestSha256');
|
|
2880
|
+
}
|
|
2881
|
+
return receipt;
|
|
2882
|
+
};
|
|
2883
|
+
|
|
2884
|
+
export { cloudlyLegacyDeploymentSettlementGoldenVectors } from './runtime.cloudlylegacydeploymentsettlement.golden.js';
|