@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.
Files changed (32) hide show
  1. package/changelog.md +19 -0
  2. package/dist_ts/00_commitinfo_data.js +1 -1
  3. package/dist_ts/platform/index.d.ts +3 -1
  4. package/dist_ts/platform/index.js +4 -2
  5. package/dist_ts/platform/objectstorageretention.d.ts +63 -0
  6. package/dist_ts/platform/objectstorageretention.js +255 -0
  7. package/dist_ts/platform/types.d.ts +3 -0
  8. package/dist_ts/plugins.runtime.d.ts +2 -0
  9. package/dist_ts/plugins.runtime.js +4 -0
  10. package/dist_ts/requests/config.d.ts +3 -0
  11. package/dist_ts/runtime.cloudlylegacydeploymentsettlement.d.ts +394 -0
  12. package/dist_ts/runtime.cloudlylegacydeploymentsettlement.golden.d.ts +35 -0
  13. package/dist_ts/runtime.cloudlylegacydeploymentsettlement.golden.js +315 -0
  14. package/dist_ts/runtime.cloudlylegacydeploymentsettlement.js +1378 -0
  15. package/dist_ts/runtime.corestore.d.ts +204 -0
  16. package/dist_ts/runtime.corestore.js +620 -0
  17. package/dist_ts/runtime.d.ts +2 -0
  18. package/dist_ts/runtime.js +3 -1
  19. package/dist_ts/runtime.workloadinit.d.ts +1 -1
  20. package/package.json +5 -1
  21. package/readme.md +54 -0
  22. package/ts/00_commitinfo_data.ts +1 -1
  23. package/ts/platform/index.ts +3 -0
  24. package/ts/platform/objectstorageretention.ts +372 -0
  25. package/ts/platform/types.ts +3 -0
  26. package/ts/plugins.runtime.ts +4 -0
  27. package/ts/requests/config.ts +3 -0
  28. package/ts/runtime.cloudlylegacydeploymentsettlement.golden.ts +421 -0
  29. package/ts/runtime.cloudlylegacydeploymentsettlement.ts +2884 -0
  30. package/ts/runtime.corestore.ts +909 -0
  31. package/ts/runtime.ts +2 -0
  32. 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';