@serve.zone/interfaces 27.3.1 → 27.4.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.
@@ -0,0 +1,2470 @@
1
+ import * as plugins from './plugins.runtime.js';
2
+
3
+ import {
4
+ canonicalizeStrictJson,
5
+ deepFreezeValue,
6
+ } from './private/canonicaljson.js';
7
+ import {
8
+ cloudlyLegacyDeploymentSettlementLimits,
9
+ } from './runtime.cloudlylegacydeploymentsettlement.js';
10
+ import type {
11
+ ICorestoreDatabaseAllocationReference,
12
+ } from './runtime.corestore.js';
13
+ import {
14
+ normalizeCorestoreDatabaseAllocationReference,
15
+ } from './runtime.corestore.js';
16
+
17
+ const maximumExactExportBytes = 96 * 1024 * 1024 + 1;
18
+
19
+ export const cloudlyLegacyDeploymentSettlementOfflineExportLimits = Object.freeze({
20
+ maximumIdentifierLength:
21
+ cloudlyLegacyDeploymentSettlementLimits.maximumIdentifierLength,
22
+ maximumSourceDocuments:
23
+ cloudlyLegacyDeploymentSettlementLimits.maximumSourceDocuments,
24
+ maximumOperations: cloudlyLegacyDeploymentSettlementLimits.maximumOperations,
25
+ maximumExactExportBytes,
26
+ maximumJournalGrowthBytes: 64 * 1024,
27
+ maximumJournalCanonicalBytes: 32 * 1024,
28
+ maximumReceiptBytes: 16 * 1024,
29
+ maximumResultBytes: 16 * 1024,
30
+ maximumAuthorityBytes: 16 * 1024,
31
+ maximumPlanBytes: 768 * 1024,
32
+ maximumAuthenticatedArtifactBytes: 768 * 1024,
33
+ maximumAuthorityLifetimeMs:
34
+ cloudlyLegacyDeploymentSettlementLimits.maximumAuthorityLifetimeMs,
35
+ } as const);
36
+
37
+ export const cloudlyLegacyDeploymentSettlementOfflineExportDomains = Object.freeze({
38
+ rehearsalAttestationHmac:
39
+ 'serve.zone/cloudly-legacy-deployment-settlement/offline-export/rehearsal-attestation-hmac-v1\0',
40
+ productionTransformAuthorizationHmac:
41
+ 'serve.zone/cloudly-legacy-deployment-settlement/offline-export/production-transform-authorization-hmac-v1\0',
42
+ attemptJournalHmac:
43
+ 'serve.zone/cloudly-legacy-deployment-settlement/offline-export/attempt-journal-hmac-v1\0',
44
+ completeOutputReceiptHmac:
45
+ 'serve.zone/cloudly-legacy-deployment-settlement/offline-export/complete-output-receipt-hmac-v1\0',
46
+ } as const);
47
+
48
+ export const cloudlyLegacyDeploymentSettlementOfflineExportJournalCollectionName =
49
+ 'cloudly_legacy_deployment_settlement_export_attempt_v1' as const;
50
+
51
+ export type TCloudlyLegacyDeploymentSettlementOfflineExportCodecErrorCode =
52
+ | 'INVALID_DATA'
53
+ | 'INVALID_SCHEMA'
54
+ | 'INVALID_VALUE'
55
+ | 'LIMIT_EXCEEDED'
56
+ | 'ORDERING_REQUIRED'
57
+ | 'CROSS_FIELD_MISMATCH';
58
+
59
+ export class CloudlyLegacyDeploymentSettlementOfflineExportCodecError extends Error {
60
+ public readonly code: TCloudlyLegacyDeploymentSettlementOfflineExportCodecErrorCode;
61
+ public readonly path: string;
62
+
63
+ public constructor(
64
+ codeArg: TCloudlyLegacyDeploymentSettlementOfflineExportCodecErrorCode,
65
+ pathArg: string,
66
+ ) {
67
+ super(`${codeArg}:${pathArg}`);
68
+ this.name = 'CloudlyLegacyDeploymentSettlementOfflineExportCodecError';
69
+ this.code = codeArg;
70
+ this.path = pathArg;
71
+ }
72
+ }
73
+
74
+ export type TCloudlyLegacyDeploymentSettlementOfflineExportClassification =
75
+ | 'image-recorded-not-current'
76
+ | 'image-recorded-current-failed'
77
+ | 'rolling-out-current-failed'
78
+ | 'rolling-out-superseded';
79
+
80
+ export interface ICloudlyLegacyDeploymentSettlementOfflineExportClassificationCountsV1 {
81
+ 'image-recorded-not-current': number;
82
+ 'image-recorded-current-failed': number;
83
+ 'rolling-out-current-failed': number;
84
+ 'rolling-out-superseded': number;
85
+ }
86
+
87
+ export interface ICloudlyLegacyDeploymentSettlementOfflineExportSourceCensusV1 {
88
+ operations: number;
89
+ services: number;
90
+ images: number;
91
+ releases: number;
92
+ rolloutOperations: number;
93
+ routeClaims: number;
94
+ resourceClaims: number;
95
+ }
96
+
97
+ export interface ICloudlyLegacyDeploymentSettlementOfflineExportMutationCountsV1 {
98
+ operationCount: number;
99
+ routeClaimsStabilized: number;
100
+ routeClaimsRemoved: number;
101
+ resourceClaimsRemoved: number;
102
+ }
103
+
104
+ export interface ICloudlyLegacyDeploymentSettlementOfflineExportPlanEntryV1 {
105
+ operationId: string;
106
+ serviceId: string;
107
+ sourceRevision: number;
108
+ sourceState: 'image-recorded' | 'rolling-out';
109
+ classification: TCloudlyLegacyDeploymentSettlementOfflineExportClassification;
110
+ finalRevision: number;
111
+ sourceDocumentHmac: `hmac-sha256:${string}`;
112
+ finalDocumentHmac: `hmac-sha256:${string}`;
113
+ routeClaimsStabilized: number;
114
+ routeClaimsRemoved: number;
115
+ resourceClaimsRemoved: number;
116
+ }
117
+
118
+ export interface ICloudlyLegacyDeploymentSettlementOfflineExportFileIdentityV1 {
119
+ format: 'smartdb.database.export.v1';
120
+ databaseName: string;
121
+ byteLength: number;
122
+ sha256: string;
123
+ lineFeedTerminator: 'single-lf';
124
+ }
125
+
126
+ export interface ICloudlyLegacyDeploymentSettlementOfflineExportApprovedSourceBackupIdentityV1 {
127
+ backupId: string;
128
+ sourceServiceId: string;
129
+ snapshotId: string;
130
+ backupReceiptSha256: string;
131
+ }
132
+
133
+ export interface ICloudlyLegacyDeploymentSettlementOfflineExportPlanV1 {
134
+ schemaVersion: 1;
135
+ kind: 'cloudly-legacy-deployment-settlement-offline-export-plan';
136
+ operationId: string;
137
+ settlementId: string;
138
+ sourceFile: ICloudlyLegacyDeploymentSettlementOfflineExportFileIdentityV1;
139
+ effectiveAt: number;
140
+ sourceStateHmac: `hmac-sha256:${string}`;
141
+ finalStateHmac: `hmac-sha256:${string}`;
142
+ sourceCensus: ICloudlyLegacyDeploymentSettlementOfflineExportSourceCensusV1;
143
+ entries: ICloudlyLegacyDeploymentSettlementOfflineExportPlanEntryV1[];
144
+ counts: ICloudlyLegacyDeploymentSettlementOfflineExportMutationCountsV1;
145
+ classificationCounts:
146
+ ICloudlyLegacyDeploymentSettlementOfflineExportClassificationCountsV1;
147
+ }
148
+
149
+ interface ICloudlyLegacyDeploymentSettlementOfflineExportAuthorityReferenceBaseV1 {
150
+ schemaVersion: 1;
151
+ kind: 'cloudly-legacy-deployment-settlement-offline-export-authority-reference';
152
+ operationId: string;
153
+ settlementId: string;
154
+ authorityId: string;
155
+ keyId: string;
156
+ keyVersion: 1;
157
+ authorityMetadataSha256: string;
158
+ }
159
+
160
+ export interface ICloudlyLegacyDeploymentSettlementOfflineExportSourceAuthorityReferenceV1
161
+ extends ICloudlyLegacyDeploymentSettlementOfflineExportAuthorityReferenceBaseV1 {
162
+ role: 'source-rehearsal';
163
+ }
164
+
165
+ export interface ICloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthorityReferenceV1
166
+ extends ICloudlyLegacyDeploymentSettlementOfflineExportAuthorityReferenceBaseV1 {
167
+ role: 'production-transform';
168
+ }
169
+
170
+ export type TCloudlyLegacyDeploymentSettlementOfflineExportAuthorityReferenceV1 =
171
+ | ICloudlyLegacyDeploymentSettlementOfflineExportSourceAuthorityReferenceV1
172
+ | ICloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthorityReferenceV1;
173
+
174
+ export interface ICloudlyLegacyDeploymentSettlementOfflineExportSourceAuthorityV1 {
175
+ schemaVersion: 1;
176
+ kind: 'cloudly-legacy-deployment-settlement-offline-export-source-authority';
177
+ role: 'source-rehearsal';
178
+ operationId: string;
179
+ settlementId: string;
180
+ authorityId: string;
181
+ keyId: string;
182
+ keyVersion: 1;
183
+ issuedAt: number;
184
+ expiresAt: number;
185
+ sourceFile: ICloudlyLegacyDeploymentSettlementOfflineExportFileIdentityV1;
186
+ approvedSourceBackup:
187
+ ICloudlyLegacyDeploymentSettlementOfflineExportApprovedSourceBackupIdentityV1;
188
+ planSha256: string;
189
+ rehearsalRequestSha256: string;
190
+ }
191
+
192
+ export interface ICloudlyLegacyDeploymentSettlementOfflineExportRehearsalAttestationPayloadV1 {
193
+ schemaVersion: 1;
194
+ kind: 'cloudly-legacy-deployment-settlement-offline-export-rehearsal-attestation';
195
+ sourceAuthority:
196
+ ICloudlyLegacyDeploymentSettlementOfflineExportSourceAuthorityReferenceV1;
197
+ plan: ICloudlyLegacyDeploymentSettlementOfflineExportPlanV1;
198
+ planSha256: string;
199
+ rehearsalRequestSha256: string;
200
+ scratchAllocation: ICorestoreDatabaseAllocationReference;
201
+ outcome: 'transform-required' | 'no-op';
202
+ observedFinalStateHmac: `hmac-sha256:${string}`;
203
+ observedCounts: ICloudlyLegacyDeploymentSettlementOfflineExportMutationCountsV1;
204
+ observedClassificationCounts:
205
+ ICloudlyLegacyDeploymentSettlementOfflineExportClassificationCountsV1;
206
+ completedAt: number;
207
+ }
208
+
209
+ export interface ICloudlyLegacyDeploymentSettlementOfflineExportRehearsalAttestationV1
210
+ extends ICloudlyLegacyDeploymentSettlementOfflineExportRehearsalAttestationPayloadV1 {
211
+ payloadSha256: string;
212
+ mac: string;
213
+ }
214
+
215
+ export type TCloudlyLegacyDeploymentSettlementOfflineExportUnsignedRehearsalAttestationV1 =
216
+ Omit<ICloudlyLegacyDeploymentSettlementOfflineExportRehearsalAttestationV1, 'mac'>;
217
+
218
+ export interface ICloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthorityV1 {
219
+ schemaVersion: 1;
220
+ kind: 'cloudly-legacy-deployment-settlement-offline-export-production-transform-authority';
221
+ role: 'production-transform';
222
+ operationId: string;
223
+ settlementId: string;
224
+ authorityId: string;
225
+ keyId: string;
226
+ keyVersion: 1;
227
+ issuedAt: number;
228
+ expiresAt: number;
229
+ sourceAuthority:
230
+ ICloudlyLegacyDeploymentSettlementOfflineExportSourceAuthorityReferenceV1;
231
+ authenticatedRehearsalAttestationSha256: string;
232
+ }
233
+
234
+ export interface ICloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthorizationPayloadV1 {
235
+ schemaVersion: 1;
236
+ kind: 'cloudly-legacy-deployment-settlement-offline-export-production-transform-authorization';
237
+ authority:
238
+ ICloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthorityReferenceV1;
239
+ sourceAuthority:
240
+ ICloudlyLegacyDeploymentSettlementOfflineExportSourceAuthorityReferenceV1;
241
+ attemptId: string;
242
+ authenticatedRehearsalAttestationSha256: string;
243
+ planSha256: string;
244
+ requestSha256: string;
245
+ requestedAt: number;
246
+ authorizedAt: number;
247
+ }
248
+
249
+ export interface ICloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthorizationV1
250
+ extends ICloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthorizationPayloadV1 {
251
+ payloadSha256: string;
252
+ mac: string;
253
+ }
254
+
255
+ export type TCloudlyLegacyDeploymentSettlementOfflineExportUnsignedProductionTransformAuthorizationV1 =
256
+ Omit<
257
+ ICloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthorizationV1,
258
+ 'mac'
259
+ >;
260
+
261
+ export interface ICloudlyLegacyDeploymentSettlementOfflineExportAttemptJournalSeedV1 {
262
+ schemaVersion: 1;
263
+ kind: typeof cloudlyLegacyDeploymentSettlementOfflineExportJournalCollectionName;
264
+ purpose: 'production-transform';
265
+ operationId: string;
266
+ settlementId: string;
267
+ attemptId: string;
268
+ sourceAuthority:
269
+ ICloudlyLegacyDeploymentSettlementOfflineExportSourceAuthorityReferenceV1;
270
+ productionTransformAuthority:
271
+ ICloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthorityReferenceV1;
272
+ authenticatedRehearsalAttestationSha256: string;
273
+ transformAuthorizationSha256: string;
274
+ planSha256: string;
275
+ requestSha256: string;
276
+ sourceFile: ICloudlyLegacyDeploymentSettlementOfflineExportFileIdentityV1;
277
+ transformedCoreFile: ICloudlyLegacyDeploymentSettlementOfflineExportFileIdentityV1;
278
+ sourceStateHmac: `hmac-sha256:${string}`;
279
+ finalStateHmac: `hmac-sha256:${string}`;
280
+ outcome: 'transformed' | 'no-op';
281
+ counts: ICloudlyLegacyDeploymentSettlementOfflineExportMutationCountsV1;
282
+ classificationCounts:
283
+ ICloudlyLegacyDeploymentSettlementOfflineExportClassificationCountsV1;
284
+ completedAt: number;
285
+ }
286
+
287
+ export interface ICloudlyLegacyDeploymentSettlementOfflineExportAttemptJournalV1
288
+ extends ICloudlyLegacyDeploymentSettlementOfflineExportAttemptJournalSeedV1 {
289
+ _id: string;
290
+ mac: string;
291
+ }
292
+
293
+ export type TCloudlyLegacyDeploymentSettlementOfflineExportUnsignedAttemptJournalV1 =
294
+ Omit<ICloudlyLegacyDeploymentSettlementOfflineExportAttemptJournalV1, 'mac'>;
295
+
296
+ export interface ICloudlyLegacyDeploymentSettlementOfflineExportCompleteOutputReceiptPayloadV1 {
297
+ schemaVersion: 1;
298
+ kind: 'cloudly-legacy-deployment-settlement-offline-export-complete-output-receipt';
299
+ authority:
300
+ ICloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthorityReferenceV1;
301
+ sourceAuthority:
302
+ ICloudlyLegacyDeploymentSettlementOfflineExportSourceAuthorityReferenceV1;
303
+ operationId: string;
304
+ settlementId: string;
305
+ attemptId: string;
306
+ journalSha256: string;
307
+ transformedCoreFile: ICloudlyLegacyDeploymentSettlementOfflineExportFileIdentityV1;
308
+ completeOutputFile: ICloudlyLegacyDeploymentSettlementOfflineExportFileIdentityV1;
309
+ journalGrowthBytes: number;
310
+ completedAt: number;
311
+ }
312
+
313
+ export interface ICloudlyLegacyDeploymentSettlementOfflineExportCompleteOutputReceiptV1
314
+ extends ICloudlyLegacyDeploymentSettlementOfflineExportCompleteOutputReceiptPayloadV1 {
315
+ payloadSha256: string;
316
+ mac: string;
317
+ }
318
+
319
+ export type TCloudlyLegacyDeploymentSettlementOfflineExportUnsignedCompleteOutputReceiptV1 =
320
+ Omit<ICloudlyLegacyDeploymentSettlementOfflineExportCompleteOutputReceiptV1, 'mac'>;
321
+
322
+ export interface ICloudlyLegacyDeploymentSettlementOfflineExportTransformResultV1 {
323
+ schemaVersion: 1;
324
+ kind: 'cloudly-legacy-deployment-settlement-offline-export-transform-result';
325
+ status: 'completed';
326
+ operationId: string;
327
+ settlementId: string;
328
+ attemptId: string;
329
+ sourceAuthority:
330
+ ICloudlyLegacyDeploymentSettlementOfflineExportSourceAuthorityReferenceV1;
331
+ productionTransformAuthority:
332
+ ICloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthorityReferenceV1;
333
+ planSha256: string;
334
+ requestSha256: string;
335
+ completeOutputReceiptSha256: string;
336
+ outcome: 'transformed' | 'no-op';
337
+ counts: ICloudlyLegacyDeploymentSettlementOfflineExportMutationCountsV1;
338
+ classificationCounts:
339
+ ICloudlyLegacyDeploymentSettlementOfflineExportClassificationCountsV1;
340
+ completedAt: number;
341
+ }
342
+
343
+ export interface ICloudlyLegacyDeploymentSettlementOfflineExportHmacVerificationInputV1 {
344
+ authority: TCloudlyLegacyDeploymentSettlementOfflineExportAuthorityReferenceV1;
345
+ domain: typeof cloudlyLegacyDeploymentSettlementOfflineExportDomains[keyof
346
+ typeof cloudlyLegacyDeploymentSettlementOfflineExportDomains];
347
+ hmacInput: Uint8Array;
348
+ mac: string;
349
+ }
350
+
351
+ export type TCloudlyLegacyDeploymentSettlementOfflineExportHmacVerifier = (
352
+ inputArg: ICloudlyLegacyDeploymentSettlementOfflineExportHmacVerificationInputV1,
353
+ ) => boolean | Promise<boolean>;
354
+
355
+ const classificationKeys = [
356
+ 'image-recorded-not-current',
357
+ 'image-recorded-current-failed',
358
+ 'rolling-out-current-failed',
359
+ 'rolling-out-superseded',
360
+ ] as const;
361
+ const censusKeys = [
362
+ 'operations',
363
+ 'services',
364
+ 'images',
365
+ 'releases',
366
+ 'rolloutOperations',
367
+ 'routeClaims',
368
+ 'resourceClaims',
369
+ ] as const;
370
+ const mutationCountKeys = [
371
+ 'operationCount',
372
+ 'routeClaimsStabilized',
373
+ 'routeClaimsRemoved',
374
+ 'resourceClaimsRemoved',
375
+ ] as const;
376
+ const planEntryKeys = [
377
+ 'operationId',
378
+ 'serviceId',
379
+ 'sourceRevision',
380
+ 'sourceState',
381
+ 'classification',
382
+ 'finalRevision',
383
+ 'sourceDocumentHmac',
384
+ 'finalDocumentHmac',
385
+ 'routeClaimsStabilized',
386
+ 'routeClaimsRemoved',
387
+ 'resourceClaimsRemoved',
388
+ ] as const;
389
+ const fileIdentityKeys = [
390
+ 'format',
391
+ 'databaseName',
392
+ 'byteLength',
393
+ 'sha256',
394
+ 'lineFeedTerminator',
395
+ ] as const;
396
+ const approvedSourceBackupKeys = [
397
+ 'backupId',
398
+ 'sourceServiceId',
399
+ 'snapshotId',
400
+ 'backupReceiptSha256',
401
+ ] as const;
402
+ const authorityReferenceKeys = [
403
+ 'schemaVersion',
404
+ 'kind',
405
+ 'role',
406
+ 'operationId',
407
+ 'settlementId',
408
+ 'authorityId',
409
+ 'keyId',
410
+ 'keyVersion',
411
+ 'authorityMetadataSha256',
412
+ ] as const;
413
+ const sourceAuthorityKeys = [
414
+ 'schemaVersion',
415
+ 'kind',
416
+ 'role',
417
+ 'operationId',
418
+ 'settlementId',
419
+ 'authorityId',
420
+ 'keyId',
421
+ 'keyVersion',
422
+ 'issuedAt',
423
+ 'expiresAt',
424
+ 'sourceFile',
425
+ 'approvedSourceBackup',
426
+ 'planSha256',
427
+ 'rehearsalRequestSha256',
428
+ ] as const;
429
+ const productionTransformAuthorityKeys = [
430
+ 'schemaVersion',
431
+ 'kind',
432
+ 'role',
433
+ 'operationId',
434
+ 'settlementId',
435
+ 'authorityId',
436
+ 'keyId',
437
+ 'keyVersion',
438
+ 'issuedAt',
439
+ 'expiresAt',
440
+ 'sourceAuthority',
441
+ 'authenticatedRehearsalAttestationSha256',
442
+ ] as const;
443
+ const rehearsalPayloadKeys = [
444
+ 'schemaVersion',
445
+ 'kind',
446
+ 'sourceAuthority',
447
+ 'plan',
448
+ 'planSha256',
449
+ 'rehearsalRequestSha256',
450
+ 'scratchAllocation',
451
+ 'outcome',
452
+ 'observedFinalStateHmac',
453
+ 'observedCounts',
454
+ 'observedClassificationCounts',
455
+ 'completedAt',
456
+ ] as const;
457
+ const rehearsalUnsignedKeys = [...rehearsalPayloadKeys, 'payloadSha256'] as const;
458
+ const rehearsalKeys = [...rehearsalUnsignedKeys, 'mac'] as const;
459
+ const authorizationPayloadKeys = [
460
+ 'schemaVersion',
461
+ 'kind',
462
+ 'authority',
463
+ 'sourceAuthority',
464
+ 'attemptId',
465
+ 'authenticatedRehearsalAttestationSha256',
466
+ 'planSha256',
467
+ 'requestSha256',
468
+ 'requestedAt',
469
+ 'authorizedAt',
470
+ ] as const;
471
+ const authorizationUnsignedKeys = [...authorizationPayloadKeys, 'payloadSha256'] as const;
472
+ const authorizationKeys = [...authorizationUnsignedKeys, 'mac'] as const;
473
+ const journalSeedKeys = [
474
+ 'schemaVersion',
475
+ 'kind',
476
+ 'purpose',
477
+ 'operationId',
478
+ 'settlementId',
479
+ 'attemptId',
480
+ 'sourceAuthority',
481
+ 'productionTransformAuthority',
482
+ 'authenticatedRehearsalAttestationSha256',
483
+ 'transformAuthorizationSha256',
484
+ 'planSha256',
485
+ 'requestSha256',
486
+ 'sourceFile',
487
+ 'transformedCoreFile',
488
+ 'sourceStateHmac',
489
+ 'finalStateHmac',
490
+ 'outcome',
491
+ 'counts',
492
+ 'classificationCounts',
493
+ 'completedAt',
494
+ ] as const;
495
+ const journalUnsignedKeys = ['_id', ...journalSeedKeys] as const;
496
+ const journalKeys = [...journalUnsignedKeys, 'mac'] as const;
497
+ const completeOutputReceiptPayloadKeys = [
498
+ 'schemaVersion',
499
+ 'kind',
500
+ 'authority',
501
+ 'sourceAuthority',
502
+ 'operationId',
503
+ 'settlementId',
504
+ 'attemptId',
505
+ 'journalSha256',
506
+ 'transformedCoreFile',
507
+ 'completeOutputFile',
508
+ 'journalGrowthBytes',
509
+ 'completedAt',
510
+ ] as const;
511
+ const completeOutputReceiptUnsignedKeys = [
512
+ ...completeOutputReceiptPayloadKeys,
513
+ 'payloadSha256',
514
+ ] as const;
515
+ const completeOutputReceiptKeys = [...completeOutputReceiptUnsignedKeys, 'mac'] as const;
516
+
517
+ const identifierPattern = /^[A-Za-z0-9][A-Za-z0-9:._@-]{0,199}$/;
518
+ const sha256Pattern = /^[a-f0-9]{64}$/;
519
+ const stateHmacPattern = /^hmac-sha256:[a-f0-9]{64}$/;
520
+ const macPattern = /^[A-Za-z0-9_-]{42}[AEIMQUYcgkosw048]$/;
521
+
522
+ const fail = (
523
+ codeArg: TCloudlyLegacyDeploymentSettlementOfflineExportCodecErrorCode,
524
+ pathArg: string,
525
+ ): never => {
526
+ throw new CloudlyLegacyDeploymentSettlementOfflineExportCodecError(codeArg, pathArg);
527
+ };
528
+
529
+ const normalizeScratchAllocation = (
530
+ valueArg: unknown,
531
+ pathArg: string,
532
+ ): ICorestoreDatabaseAllocationReference => {
533
+ try {
534
+ return normalizeCorestoreDatabaseAllocationReference(
535
+ valueArg,
536
+ ) as ICorestoreDatabaseAllocationReference;
537
+ } catch {
538
+ return fail('INVALID_VALUE', pathArg);
539
+ }
540
+ };
541
+
542
+ const readRecord = (valueArg: unknown, pathArg: string): Record<string, unknown> => {
543
+ if (!valueArg || typeof valueArg !== 'object' || Array.isArray(valueArg)) {
544
+ return fail('INVALID_DATA', pathArg);
545
+ }
546
+ const prototype = Object.getPrototypeOf(valueArg);
547
+ if (prototype !== Object.prototype && prototype !== null) {
548
+ return fail('INVALID_DATA', pathArg);
549
+ }
550
+ const value = valueArg as Record<string, unknown>;
551
+ for (const key of Reflect.ownKeys(value)) {
552
+ if (typeof key !== 'string') return fail('INVALID_DATA', pathArg);
553
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
554
+ if (!descriptor || !descriptor.enumerable || !Object.hasOwn(descriptor, 'value')) {
555
+ return fail('INVALID_DATA', pathArg);
556
+ }
557
+ }
558
+ return value;
559
+ };
560
+
561
+ const readArray = (
562
+ valueArg: unknown,
563
+ pathArg: string,
564
+ maximumLengthArg: number,
565
+ ): unknown[] => {
566
+ if (!Array.isArray(valueArg) || Object.getPrototypeOf(valueArg) !== Array.prototype
567
+ || valueArg.length > maximumLengthArg) {
568
+ return fail(
569
+ Array.isArray(valueArg) ? 'LIMIT_EXCEEDED' : 'INVALID_DATA',
570
+ pathArg,
571
+ );
572
+ }
573
+ for (let index = 0; index < valueArg.length; index++) {
574
+ if (!Object.hasOwn(valueArg, index)) return fail('INVALID_DATA', `${pathArg}[${index}]`);
575
+ const descriptor = Object.getOwnPropertyDescriptor(valueArg, String(index));
576
+ if (!descriptor || !descriptor.enumerable || !Object.hasOwn(descriptor, 'value')) {
577
+ return fail('INVALID_DATA', `${pathArg}[${index}]`);
578
+ }
579
+ }
580
+ for (const key of Reflect.ownKeys(valueArg)) {
581
+ if (key === 'length') continue;
582
+ if (typeof key !== 'string'
583
+ || !/^(?:0|[1-9][0-9]*)$/.test(key)
584
+ || Number(key) >= valueArg.length) {
585
+ return fail('INVALID_DATA', pathArg);
586
+ }
587
+ }
588
+ return valueArg;
589
+ };
590
+
591
+ const assertExactKeys = (
592
+ valueArg: Record<string, unknown>,
593
+ keysArg: readonly string[],
594
+ pathArg: string,
595
+ ): void => {
596
+ const actual = Object.keys(valueArg).sort();
597
+ const expected = [...keysArg].sort();
598
+ if (actual.length !== expected.length
599
+ || actual.some((keyArg, indexArg) => keyArg !== expected[indexArg])) {
600
+ fail('INVALID_SCHEMA', pathArg);
601
+ }
602
+ };
603
+
604
+ const readIdentifier = (valueArg: unknown, pathArg: string): string => {
605
+ if (typeof valueArg !== 'string' || !identifierPattern.test(valueArg)) {
606
+ return fail('INVALID_VALUE', pathArg);
607
+ }
608
+ return valueArg;
609
+ };
610
+
611
+ const readSha256 = (valueArg: unknown, pathArg: string): string => {
612
+ if (typeof valueArg !== 'string' || !sha256Pattern.test(valueArg)) {
613
+ return fail('INVALID_VALUE', pathArg);
614
+ }
615
+ return valueArg;
616
+ };
617
+
618
+ const readStateHmac = (
619
+ valueArg: unknown,
620
+ pathArg: string,
621
+ ): `hmac-sha256:${string}` => {
622
+ if (typeof valueArg !== 'string' || !stateHmacPattern.test(valueArg)) {
623
+ return fail('INVALID_VALUE', pathArg);
624
+ }
625
+ return valueArg as `hmac-sha256:${string}`;
626
+ };
627
+
628
+ const readMac = (valueArg: unknown, pathArg: string): string => {
629
+ if (typeof valueArg !== 'string' || !macPattern.test(valueArg)) {
630
+ return fail('INVALID_VALUE', pathArg);
631
+ }
632
+ const bytes = Buffer.from(valueArg, 'base64url');
633
+ if (bytes.byteLength !== 32 || bytes.toString('base64url') !== valueArg) {
634
+ return fail('INVALID_VALUE', pathArg);
635
+ }
636
+ return valueArg;
637
+ };
638
+
639
+ const readInteger = (
640
+ valueArg: unknown,
641
+ pathArg: string,
642
+ minimumArg = 0,
643
+ maximumArg = Number.MAX_SAFE_INTEGER,
644
+ ): number => {
645
+ if (typeof valueArg !== 'number'
646
+ || !Number.isSafeInteger(valueArg)
647
+ || Object.is(valueArg, -0)
648
+ || valueArg < minimumArg
649
+ || valueArg > maximumArg) {
650
+ return fail('INVALID_VALUE', pathArg);
651
+ }
652
+ return valueArg;
653
+ };
654
+
655
+ const readLiteral = <TLiteral extends string>(
656
+ valueArg: unknown,
657
+ literalsArg: readonly TLiteral[],
658
+ pathArg: string,
659
+ ): TLiteral => {
660
+ if (typeof valueArg !== 'string' || !literalsArg.includes(valueArg as TLiteral)) {
661
+ return fail('INVALID_VALUE', pathArg);
662
+ }
663
+ return valueArg as TLiteral;
664
+ };
665
+
666
+ const canonicalize = (valueArg: unknown, pathArg: string): string => canonicalizeStrictJson(
667
+ valueArg,
668
+ () => fail('INVALID_DATA', pathArg),
669
+ pathArg,
670
+ );
671
+
672
+ const finalize = <T>(
673
+ valueArg: T,
674
+ maximumBytesArg: number,
675
+ pathArg: string,
676
+ ): Readonly<T> => {
677
+ const canonical = canonicalize(valueArg, pathArg);
678
+ if (Buffer.byteLength(canonical, 'utf8') > maximumBytesArg) {
679
+ return fail('LIMIT_EXCEEDED', pathArg);
680
+ }
681
+ return deepFreezeValue(valueArg);
682
+ };
683
+
684
+ const encodeNormalized = (valueArg: unknown, pathArg: string): Uint8Array => (
685
+ Buffer.from(canonicalize(valueArg, pathArg), 'utf8')
686
+ );
687
+
688
+ const digestBytes = (valueArg: Uint8Array): string => plugins.crypto
689
+ .createHash('sha256')
690
+ .update(new Uint8Array(valueArg))
691
+ .digest('hex');
692
+
693
+ const frame = (domainArg: string, payloadArg: Uint8Array): Uint8Array => {
694
+ const domain = Buffer.from(domainArg, 'utf8');
695
+ const output = new Uint8Array(domain.byteLength + payloadArg.byteLength);
696
+ output.set(domain, 0);
697
+ output.set(payloadArg, domain.byteLength);
698
+ return output;
699
+ };
700
+
701
+ const canonicalEqual = (leftArg: unknown, rightArg: unknown, pathArg: string): boolean => (
702
+ canonicalize(leftArg, `${pathArg}.left`) === canonicalize(rightArg, `${pathArg}.right`)
703
+ );
704
+
705
+ const normalizeFileIdentityInternal = (
706
+ valueArg: unknown,
707
+ pathArg: string,
708
+ ): ICloudlyLegacyDeploymentSettlementOfflineExportFileIdentityV1 => {
709
+ const value = readRecord(valueArg, pathArg);
710
+ assertExactKeys(value, fileIdentityKeys, pathArg);
711
+ if (value.format !== 'smartdb.database.export.v1'
712
+ || value.lineFeedTerminator !== 'single-lf') {
713
+ fail('INVALID_VALUE', `${pathArg}.format`);
714
+ }
715
+ return {
716
+ format: 'smartdb.database.export.v1',
717
+ databaseName: readIdentifier(value.databaseName, `${pathArg}.databaseName`),
718
+ byteLength: readInteger(
719
+ value.byteLength,
720
+ `${pathArg}.byteLength`,
721
+ 1,
722
+ cloudlyLegacyDeploymentSettlementOfflineExportLimits.maximumExactExportBytes,
723
+ ),
724
+ sha256: readSha256(value.sha256, `${pathArg}.sha256`),
725
+ lineFeedTerminator: 'single-lf',
726
+ };
727
+ };
728
+
729
+ export const normalizeCloudlyLegacyDeploymentSettlementOfflineExportFileIdentity = (
730
+ valueArg: unknown,
731
+ ): Readonly<ICloudlyLegacyDeploymentSettlementOfflineExportFileIdentityV1> => finalize(
732
+ normalizeFileIdentityInternal(valueArg, 'offlineExportFileIdentity'),
733
+ cloudlyLegacyDeploymentSettlementOfflineExportLimits.maximumAuthorityBytes,
734
+ 'offlineExportFileIdentity',
735
+ );
736
+
737
+ export const encodeCloudlyLegacyDeploymentSettlementOfflineExportFileIdentity = (
738
+ valueArg: unknown,
739
+ ): Uint8Array => encodeNormalized(
740
+ normalizeCloudlyLegacyDeploymentSettlementOfflineExportFileIdentity(valueArg),
741
+ 'offlineExportFileIdentity',
742
+ );
743
+
744
+ export const digestCloudlyLegacyDeploymentSettlementOfflineExportFileIdentity = (
745
+ valueArg: unknown,
746
+ ): string => digestBytes(
747
+ encodeCloudlyLegacyDeploymentSettlementOfflineExportFileIdentity(valueArg),
748
+ );
749
+
750
+ const normalizeApprovedSourceBackupInternal = (
751
+ valueArg: unknown,
752
+ pathArg: string,
753
+ ): ICloudlyLegacyDeploymentSettlementOfflineExportApprovedSourceBackupIdentityV1 => {
754
+ const value = readRecord(valueArg, pathArg);
755
+ assertExactKeys(value, approvedSourceBackupKeys, pathArg);
756
+ return {
757
+ backupId: readIdentifier(value.backupId, `${pathArg}.backupId`),
758
+ sourceServiceId: readIdentifier(value.sourceServiceId, `${pathArg}.sourceServiceId`),
759
+ snapshotId: readIdentifier(value.snapshotId, `${pathArg}.snapshotId`),
760
+ backupReceiptSha256: readSha256(
761
+ value.backupReceiptSha256,
762
+ `${pathArg}.backupReceiptSha256`,
763
+ ),
764
+ };
765
+ };
766
+
767
+ export const normalizeCloudlyLegacyDeploymentSettlementOfflineExportApprovedSourceBackupIdentity = (
768
+ valueArg: unknown,
769
+ ): Readonly<
770
+ ICloudlyLegacyDeploymentSettlementOfflineExportApprovedSourceBackupIdentityV1
771
+ > => finalize(
772
+ normalizeApprovedSourceBackupInternal(valueArg, 'approvedSourceBackup'),
773
+ cloudlyLegacyDeploymentSettlementOfflineExportLimits.maximumAuthorityBytes,
774
+ 'approvedSourceBackup',
775
+ );
776
+
777
+ const normalizeClassificationCounts = (
778
+ valueArg: unknown,
779
+ pathArg: string,
780
+ ): ICloudlyLegacyDeploymentSettlementOfflineExportClassificationCountsV1 => {
781
+ const value = readRecord(valueArg, pathArg);
782
+ assertExactKeys(value, classificationKeys, pathArg);
783
+ return {
784
+ 'image-recorded-not-current': readInteger(
785
+ value['image-recorded-not-current'],
786
+ `${pathArg}.image-recorded-not-current`,
787
+ 0,
788
+ cloudlyLegacyDeploymentSettlementOfflineExportLimits.maximumOperations,
789
+ ),
790
+ 'image-recorded-current-failed': readInteger(
791
+ value['image-recorded-current-failed'],
792
+ `${pathArg}.image-recorded-current-failed`,
793
+ 0,
794
+ cloudlyLegacyDeploymentSettlementOfflineExportLimits.maximumOperations,
795
+ ),
796
+ 'rolling-out-current-failed': readInteger(
797
+ value['rolling-out-current-failed'],
798
+ `${pathArg}.rolling-out-current-failed`,
799
+ 0,
800
+ cloudlyLegacyDeploymentSettlementOfflineExportLimits.maximumOperations,
801
+ ),
802
+ 'rolling-out-superseded': readInteger(
803
+ value['rolling-out-superseded'],
804
+ `${pathArg}.rolling-out-superseded`,
805
+ 0,
806
+ cloudlyLegacyDeploymentSettlementOfflineExportLimits.maximumOperations,
807
+ ),
808
+ };
809
+ };
810
+
811
+ const sumClassificationCounts = (
812
+ valueArg: ICloudlyLegacyDeploymentSettlementOfflineExportClassificationCountsV1,
813
+ ): number => classificationKeys.reduce((sumArg, keyArg) => sumArg + valueArg[keyArg], 0);
814
+
815
+ const normalizeSourceCensus = (
816
+ valueArg: unknown,
817
+ pathArg: string,
818
+ ): ICloudlyLegacyDeploymentSettlementOfflineExportSourceCensusV1 => {
819
+ const value = readRecord(valueArg, pathArg);
820
+ assertExactKeys(value, censusKeys, pathArg);
821
+ const output = Object.fromEntries(censusKeys.map((keyArg) => [
822
+ keyArg,
823
+ readInteger(
824
+ value[keyArg],
825
+ `${pathArg}.${keyArg}`,
826
+ 0,
827
+ cloudlyLegacyDeploymentSettlementOfflineExportLimits.maximumSourceDocuments,
828
+ ),
829
+ ])) as unknown as ICloudlyLegacyDeploymentSettlementOfflineExportSourceCensusV1;
830
+ if (censusKeys.reduce((sumArg, keyArg) => sumArg + output[keyArg], 0)
831
+ > cloudlyLegacyDeploymentSettlementOfflineExportLimits.maximumSourceDocuments) {
832
+ fail('LIMIT_EXCEEDED', pathArg);
833
+ }
834
+ return output;
835
+ };
836
+
837
+ const normalizeMutationCounts = (
838
+ valueArg: unknown,
839
+ pathArg: string,
840
+ ): ICloudlyLegacyDeploymentSettlementOfflineExportMutationCountsV1 => {
841
+ const value = readRecord(valueArg, pathArg);
842
+ assertExactKeys(value, mutationCountKeys, pathArg);
843
+ const counts = {
844
+ operationCount: readInteger(
845
+ value.operationCount,
846
+ `${pathArg}.operationCount`,
847
+ 0,
848
+ cloudlyLegacyDeploymentSettlementOfflineExportLimits.maximumOperations,
849
+ ),
850
+ routeClaimsStabilized: readInteger(
851
+ value.routeClaimsStabilized,
852
+ `${pathArg}.routeClaimsStabilized`,
853
+ ),
854
+ routeClaimsRemoved: readInteger(
855
+ value.routeClaimsRemoved,
856
+ `${pathArg}.routeClaimsRemoved`,
857
+ ),
858
+ resourceClaimsRemoved: readInteger(
859
+ value.resourceClaimsRemoved,
860
+ `${pathArg}.resourceClaimsRemoved`,
861
+ ),
862
+ };
863
+ if (counts.operationCount === 0
864
+ && mutationCountKeys.some((keyArg) => counts[keyArg] !== 0)) {
865
+ fail('CROSS_FIELD_MISMATCH', pathArg);
866
+ }
867
+ return counts;
868
+ };
869
+
870
+ const hasNoMutations = (
871
+ valueArg: ICloudlyLegacyDeploymentSettlementOfflineExportMutationCountsV1,
872
+ ): boolean => mutationCountKeys.every((keyArg) => valueArg[keyArg] === 0);
873
+
874
+ const assertCountsMatchClassifications = (
875
+ countsArg: ICloudlyLegacyDeploymentSettlementOfflineExportMutationCountsV1,
876
+ classificationCountsArg:
877
+ ICloudlyLegacyDeploymentSettlementOfflineExportClassificationCountsV1,
878
+ pathArg: string,
879
+ ): void => {
880
+ if (countsArg.operationCount !== sumClassificationCounts(classificationCountsArg)) {
881
+ fail('CROSS_FIELD_MISMATCH', pathArg);
882
+ }
883
+ };
884
+
885
+ const normalizePlanEntry = (
886
+ valueArg: unknown,
887
+ pathArg: string,
888
+ ): ICloudlyLegacyDeploymentSettlementOfflineExportPlanEntryV1 => {
889
+ const value = readRecord(valueArg, pathArg);
890
+ assertExactKeys(value, planEntryKeys, pathArg);
891
+ const sourceRevision = readInteger(value.sourceRevision, `${pathArg}.sourceRevision`);
892
+ const finalRevision = readInteger(value.finalRevision, `${pathArg}.finalRevision`);
893
+ if (!Number.isSafeInteger(sourceRevision + 3) || finalRevision !== sourceRevision + 3) {
894
+ fail('CROSS_FIELD_MISMATCH', `${pathArg}.finalRevision`);
895
+ }
896
+ const sourceState = readLiteral(
897
+ value.sourceState,
898
+ ['image-recorded', 'rolling-out'],
899
+ `${pathArg}.sourceState`,
900
+ );
901
+ const classification = readLiteral(
902
+ value.classification,
903
+ classificationKeys,
904
+ `${pathArg}.classification`,
905
+ );
906
+ if ((classification.startsWith('image-recorded-') && sourceState !== 'image-recorded')
907
+ || (classification.startsWith('rolling-out-') && sourceState !== 'rolling-out')) {
908
+ fail('CROSS_FIELD_MISMATCH', `${pathArg}.classification`);
909
+ }
910
+ return {
911
+ operationId: readIdentifier(value.operationId, `${pathArg}.operationId`),
912
+ serviceId: readIdentifier(value.serviceId, `${pathArg}.serviceId`),
913
+ sourceRevision,
914
+ sourceState,
915
+ classification,
916
+ finalRevision,
917
+ sourceDocumentHmac: readStateHmac(
918
+ value.sourceDocumentHmac,
919
+ `${pathArg}.sourceDocumentHmac`,
920
+ ),
921
+ finalDocumentHmac: readStateHmac(
922
+ value.finalDocumentHmac,
923
+ `${pathArg}.finalDocumentHmac`,
924
+ ),
925
+ routeClaimsStabilized: readInteger(
926
+ value.routeClaimsStabilized,
927
+ `${pathArg}.routeClaimsStabilized`,
928
+ ),
929
+ routeClaimsRemoved: readInteger(
930
+ value.routeClaimsRemoved,
931
+ `${pathArg}.routeClaimsRemoved`,
932
+ ),
933
+ resourceClaimsRemoved: readInteger(
934
+ value.resourceClaimsRemoved,
935
+ `${pathArg}.resourceClaimsRemoved`,
936
+ ),
937
+ };
938
+ };
939
+
940
+ export const normalizeCloudlyLegacyDeploymentSettlementOfflineExportPlan = (
941
+ valueArg: unknown,
942
+ ): Readonly<ICloudlyLegacyDeploymentSettlementOfflineExportPlanV1> => {
943
+ const value = readRecord(valueArg, 'offlineExportPlan');
944
+ assertExactKeys(value, [
945
+ 'schemaVersion',
946
+ 'kind',
947
+ 'operationId',
948
+ 'settlementId',
949
+ 'sourceFile',
950
+ 'effectiveAt',
951
+ 'sourceStateHmac',
952
+ 'finalStateHmac',
953
+ 'sourceCensus',
954
+ 'entries',
955
+ 'counts',
956
+ 'classificationCounts',
957
+ ], 'offlineExportPlan');
958
+ if (value.schemaVersion !== 1
959
+ || value.kind !== 'cloudly-legacy-deployment-settlement-offline-export-plan') {
960
+ fail('INVALID_VALUE', 'offlineExportPlan.kind');
961
+ }
962
+ const entries = readArray(
963
+ value.entries,
964
+ 'offlineExportPlan.entries',
965
+ cloudlyLegacyDeploymentSettlementOfflineExportLimits.maximumOperations,
966
+ ).map((entryArg, indexArg) => normalizePlanEntry(
967
+ entryArg,
968
+ `offlineExportPlan.entries[${indexArg}]`,
969
+ ));
970
+ for (let index = 1; index < entries.length; index++) {
971
+ if (entries[index - 1].operationId >= entries[index].operationId) {
972
+ fail('ORDERING_REQUIRED', `offlineExportPlan.entries[${index}].operationId`);
973
+ }
974
+ }
975
+ const counts = normalizeMutationCounts(value.counts, 'offlineExportPlan.counts');
976
+ const classificationCounts = normalizeClassificationCounts(
977
+ value.classificationCounts,
978
+ 'offlineExportPlan.classificationCounts',
979
+ );
980
+ const sourceStateHmac = readStateHmac(
981
+ value.sourceStateHmac,
982
+ 'offlineExportPlan.sourceStateHmac',
983
+ );
984
+ const finalStateHmac = readStateHmac(
985
+ value.finalStateHmac,
986
+ 'offlineExportPlan.finalStateHmac',
987
+ );
988
+ const expectedCounts = {
989
+ operationCount: entries.length,
990
+ routeClaimsStabilized: entries.reduce(
991
+ (sumArg, entryArg) => sumArg + entryArg.routeClaimsStabilized,
992
+ 0,
993
+ ),
994
+ routeClaimsRemoved: entries.reduce(
995
+ (sumArg, entryArg) => sumArg + entryArg.routeClaimsRemoved,
996
+ 0,
997
+ ),
998
+ resourceClaimsRemoved: entries.reduce(
999
+ (sumArg, entryArg) => sumArg + entryArg.resourceClaimsRemoved,
1000
+ 0,
1001
+ ),
1002
+ };
1003
+ const actualClassifications = Object.fromEntries(classificationKeys.map((keyArg) => [
1004
+ keyArg,
1005
+ entries.filter((entryArg) => entryArg.classification === keyArg).length,
1006
+ ]));
1007
+ if (!Object.values(expectedCounts).every((valueArg) => Number.isSafeInteger(valueArg))
1008
+ || !canonicalEqual(counts, expectedCounts, 'offlineExportPlan.counts')
1009
+ || classificationKeys.some((keyArg) => (
1010
+ classificationCounts[keyArg] !== actualClassifications[keyArg]
1011
+ ))
1012
+ || (entries.length === 0) !== (sourceStateHmac === finalStateHmac)) {
1013
+ fail('CROSS_FIELD_MISMATCH', 'offlineExportPlan.counts');
1014
+ }
1015
+ assertCountsMatchClassifications(
1016
+ counts,
1017
+ classificationCounts,
1018
+ 'offlineExportPlan.classificationCounts',
1019
+ );
1020
+ return finalize({
1021
+ schemaVersion: 1,
1022
+ kind: 'cloudly-legacy-deployment-settlement-offline-export-plan',
1023
+ operationId: readIdentifier(value.operationId, 'offlineExportPlan.operationId'),
1024
+ settlementId: readIdentifier(value.settlementId, 'offlineExportPlan.settlementId'),
1025
+ sourceFile: normalizeFileIdentityInternal(value.sourceFile, 'offlineExportPlan.sourceFile'),
1026
+ effectiveAt: readInteger(value.effectiveAt, 'offlineExportPlan.effectiveAt', 1),
1027
+ sourceStateHmac,
1028
+ finalStateHmac,
1029
+ sourceCensus: normalizeSourceCensus(
1030
+ value.sourceCensus,
1031
+ 'offlineExportPlan.sourceCensus',
1032
+ ),
1033
+ entries,
1034
+ counts,
1035
+ classificationCounts,
1036
+ } satisfies ICloudlyLegacyDeploymentSettlementOfflineExportPlanV1,
1037
+ cloudlyLegacyDeploymentSettlementOfflineExportLimits.maximumPlanBytes,
1038
+ 'offlineExportPlan');
1039
+ };
1040
+
1041
+ export const encodeCloudlyLegacyDeploymentSettlementOfflineExportPlan = (
1042
+ valueArg: unknown,
1043
+ ): Uint8Array => encodeNormalized(
1044
+ normalizeCloudlyLegacyDeploymentSettlementOfflineExportPlan(valueArg),
1045
+ 'offlineExportPlan',
1046
+ );
1047
+
1048
+ export const digestCloudlyLegacyDeploymentSettlementOfflineExportPlan = (
1049
+ valueArg: unknown,
1050
+ ): string => digestBytes(encodeCloudlyLegacyDeploymentSettlementOfflineExportPlan(valueArg));
1051
+
1052
+ const normalizeAuthorityReferenceInternal = <
1053
+ TRole extends TCloudlyLegacyDeploymentSettlementOfflineExportAuthorityReferenceV1['role'],
1054
+ >(
1055
+ valueArg: unknown,
1056
+ pathArg: string,
1057
+ roleArg: TRole,
1058
+ ): Extract<
1059
+ TCloudlyLegacyDeploymentSettlementOfflineExportAuthorityReferenceV1,
1060
+ { role: TRole }
1061
+ > => {
1062
+ const value = readRecord(valueArg, pathArg);
1063
+ assertExactKeys(value, authorityReferenceKeys, pathArg);
1064
+ if (value.schemaVersion !== 1
1065
+ || value.kind
1066
+ !== 'cloudly-legacy-deployment-settlement-offline-export-authority-reference'
1067
+ || value.role !== roleArg
1068
+ || value.keyVersion !== 1) {
1069
+ fail('INVALID_VALUE', `${pathArg}.role`);
1070
+ }
1071
+ return {
1072
+ schemaVersion: 1,
1073
+ kind: 'cloudly-legacy-deployment-settlement-offline-export-authority-reference',
1074
+ role: roleArg,
1075
+ operationId: readIdentifier(value.operationId, `${pathArg}.operationId`),
1076
+ settlementId: readIdentifier(value.settlementId, `${pathArg}.settlementId`),
1077
+ authorityId: readIdentifier(value.authorityId, `${pathArg}.authorityId`),
1078
+ keyId: readIdentifier(value.keyId, `${pathArg}.keyId`),
1079
+ keyVersion: 1,
1080
+ authorityMetadataSha256: readSha256(
1081
+ value.authorityMetadataSha256,
1082
+ `${pathArg}.authorityMetadataSha256`,
1083
+ ),
1084
+ } as Extract<
1085
+ TCloudlyLegacyDeploymentSettlementOfflineExportAuthorityReferenceV1,
1086
+ { role: TRole }
1087
+ >;
1088
+ };
1089
+
1090
+ export const normalizeCloudlyLegacyDeploymentSettlementOfflineExportSourceAuthorityReference = (
1091
+ valueArg: unknown,
1092
+ ): Readonly<
1093
+ ICloudlyLegacyDeploymentSettlementOfflineExportSourceAuthorityReferenceV1
1094
+ > => finalize(
1095
+ normalizeAuthorityReferenceInternal(valueArg, 'offlineExportSourceAuthorityReference', 'source-rehearsal'),
1096
+ cloudlyLegacyDeploymentSettlementOfflineExportLimits.maximumAuthorityBytes,
1097
+ 'offlineExportSourceAuthorityReference',
1098
+ );
1099
+
1100
+ export const normalizeCloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthorityReference = (
1101
+ valueArg: unknown,
1102
+ ): Readonly<
1103
+ ICloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthorityReferenceV1
1104
+ > => finalize(
1105
+ normalizeAuthorityReferenceInternal(
1106
+ valueArg,
1107
+ 'offlineExportProductionTransformAuthorityReference',
1108
+ 'production-transform',
1109
+ ),
1110
+ cloudlyLegacyDeploymentSettlementOfflineExportLimits.maximumAuthorityBytes,
1111
+ 'offlineExportProductionTransformAuthorityReference',
1112
+ );
1113
+
1114
+ const normalizeAuthorityWindow = (
1115
+ valueArg: Record<string, unknown>,
1116
+ pathArg: string,
1117
+ ): { issuedAt: number; expiresAt: number } => {
1118
+ const issuedAt = readInteger(valueArg.issuedAt, `${pathArg}.issuedAt`, 1);
1119
+ const expiresAt = readInteger(valueArg.expiresAt, `${pathArg}.expiresAt`, 1);
1120
+ if (expiresAt <= issuedAt
1121
+ || expiresAt - issuedAt
1122
+ > cloudlyLegacyDeploymentSettlementOfflineExportLimits.maximumAuthorityLifetimeMs) {
1123
+ fail('CROSS_FIELD_MISMATCH', `${pathArg}.expiresAt`);
1124
+ }
1125
+ return { issuedAt, expiresAt };
1126
+ };
1127
+
1128
+ const assertTimestampWithinAuthority = (
1129
+ timestampArg: number,
1130
+ authorityArg: { issuedAt: number; expiresAt: number },
1131
+ pathArg: string,
1132
+ ): void => {
1133
+ if (timestampArg < authorityArg.issuedAt || timestampArg >= authorityArg.expiresAt) {
1134
+ fail('CROSS_FIELD_MISMATCH', pathArg);
1135
+ }
1136
+ };
1137
+
1138
+ export const normalizeCloudlyLegacyDeploymentSettlementOfflineExportSourceAuthority = (
1139
+ valueArg: unknown,
1140
+ ): Readonly<ICloudlyLegacyDeploymentSettlementOfflineExportSourceAuthorityV1> => {
1141
+ const value = readRecord(valueArg, 'offlineExportSourceAuthority');
1142
+ assertExactKeys(value, sourceAuthorityKeys, 'offlineExportSourceAuthority');
1143
+ if (value.schemaVersion !== 1
1144
+ || value.kind
1145
+ !== 'cloudly-legacy-deployment-settlement-offline-export-source-authority'
1146
+ || value.role !== 'source-rehearsal'
1147
+ || value.keyVersion !== 1) {
1148
+ fail('INVALID_VALUE', 'offlineExportSourceAuthority.kind');
1149
+ }
1150
+ const window = normalizeAuthorityWindow(value, 'offlineExportSourceAuthority');
1151
+ return finalize({
1152
+ schemaVersion: 1,
1153
+ kind: 'cloudly-legacy-deployment-settlement-offline-export-source-authority',
1154
+ role: 'source-rehearsal',
1155
+ operationId: readIdentifier(value.operationId, 'offlineExportSourceAuthority.operationId'),
1156
+ settlementId: readIdentifier(value.settlementId, 'offlineExportSourceAuthority.settlementId'),
1157
+ authorityId: readIdentifier(value.authorityId, 'offlineExportSourceAuthority.authorityId'),
1158
+ keyId: readIdentifier(value.keyId, 'offlineExportSourceAuthority.keyId'),
1159
+ keyVersion: 1,
1160
+ ...window,
1161
+ sourceFile: normalizeFileIdentityInternal(
1162
+ value.sourceFile,
1163
+ 'offlineExportSourceAuthority.sourceFile',
1164
+ ),
1165
+ approvedSourceBackup: normalizeApprovedSourceBackupInternal(
1166
+ value.approvedSourceBackup,
1167
+ 'offlineExportSourceAuthority.approvedSourceBackup',
1168
+ ),
1169
+ planSha256: readSha256(value.planSha256, 'offlineExportSourceAuthority.planSha256'),
1170
+ rehearsalRequestSha256: readSha256(
1171
+ value.rehearsalRequestSha256,
1172
+ 'offlineExportSourceAuthority.rehearsalRequestSha256',
1173
+ ),
1174
+ } satisfies ICloudlyLegacyDeploymentSettlementOfflineExportSourceAuthorityV1,
1175
+ cloudlyLegacyDeploymentSettlementOfflineExportLimits.maximumAuthorityBytes,
1176
+ 'offlineExportSourceAuthority');
1177
+ };
1178
+
1179
+ export const encodeCloudlyLegacyDeploymentSettlementOfflineExportSourceAuthority = (
1180
+ valueArg: unknown,
1181
+ ): Uint8Array => encodeNormalized(
1182
+ normalizeCloudlyLegacyDeploymentSettlementOfflineExportSourceAuthority(valueArg),
1183
+ 'offlineExportSourceAuthority',
1184
+ );
1185
+
1186
+ export const digestCloudlyLegacyDeploymentSettlementOfflineExportSourceAuthority = (
1187
+ valueArg: unknown,
1188
+ ): string => digestBytes(
1189
+ encodeCloudlyLegacyDeploymentSettlementOfflineExportSourceAuthority(valueArg),
1190
+ );
1191
+
1192
+ export const createCloudlyLegacyDeploymentSettlementOfflineExportSourceAuthorityReference = (
1193
+ authorityArg: unknown,
1194
+ ): Readonly<
1195
+ ICloudlyLegacyDeploymentSettlementOfflineExportSourceAuthorityReferenceV1
1196
+ > => {
1197
+ const authority = normalizeCloudlyLegacyDeploymentSettlementOfflineExportSourceAuthority(
1198
+ authorityArg,
1199
+ );
1200
+ return finalize({
1201
+ schemaVersion: 1,
1202
+ kind: 'cloudly-legacy-deployment-settlement-offline-export-authority-reference',
1203
+ role: 'source-rehearsal',
1204
+ operationId: authority.operationId,
1205
+ settlementId: authority.settlementId,
1206
+ authorityId: authority.authorityId,
1207
+ keyId: authority.keyId,
1208
+ keyVersion: 1,
1209
+ authorityMetadataSha256:
1210
+ digestCloudlyLegacyDeploymentSettlementOfflineExportSourceAuthority(authority),
1211
+ }, cloudlyLegacyDeploymentSettlementOfflineExportLimits.maximumAuthorityBytes,
1212
+ 'offlineExportSourceAuthorityReference');
1213
+ };
1214
+
1215
+ const assertSourceReferenceMatchesAuthority = (
1216
+ referenceArg: unknown,
1217
+ authorityArg: unknown,
1218
+ pathArg: string,
1219
+ ): void => {
1220
+ const reference = normalizeCloudlyLegacyDeploymentSettlementOfflineExportSourceAuthorityReference(
1221
+ referenceArg,
1222
+ );
1223
+ const expected = createCloudlyLegacyDeploymentSettlementOfflineExportSourceAuthorityReference(
1224
+ authorityArg,
1225
+ );
1226
+ if (!canonicalEqual(reference, expected, pathArg)) {
1227
+ fail('CROSS_FIELD_MISMATCH', pathArg);
1228
+ }
1229
+ };
1230
+
1231
+ const normalizeRehearsalPayloadInternal = (
1232
+ valueArg: unknown,
1233
+ pathArg: string,
1234
+ ): ICloudlyLegacyDeploymentSettlementOfflineExportRehearsalAttestationPayloadV1 => {
1235
+ const value = readRecord(valueArg, pathArg);
1236
+ assertExactKeys(value, rehearsalPayloadKeys, pathArg);
1237
+ if (value.schemaVersion !== 1
1238
+ || value.kind
1239
+ !== 'cloudly-legacy-deployment-settlement-offline-export-rehearsal-attestation') {
1240
+ fail('INVALID_VALUE', `${pathArg}.kind`);
1241
+ }
1242
+ const sourceAuthority = normalizeAuthorityReferenceInternal(
1243
+ value.sourceAuthority,
1244
+ `${pathArg}.sourceAuthority`,
1245
+ 'source-rehearsal',
1246
+ );
1247
+ const plan = normalizeCloudlyLegacyDeploymentSettlementOfflineExportPlan(value.plan);
1248
+ const planSha256 = readSha256(value.planSha256, `${pathArg}.planSha256`);
1249
+ const outcome = readLiteral(
1250
+ value.outcome,
1251
+ ['transform-required', 'no-op'],
1252
+ `${pathArg}.outcome`,
1253
+ );
1254
+ const observedCounts = normalizeMutationCounts(
1255
+ value.observedCounts,
1256
+ `${pathArg}.observedCounts`,
1257
+ );
1258
+ const observedClassificationCounts = normalizeClassificationCounts(
1259
+ value.observedClassificationCounts,
1260
+ `${pathArg}.observedClassificationCounts`,
1261
+ );
1262
+ if (sourceAuthority.operationId !== plan.operationId
1263
+ || sourceAuthority.settlementId !== plan.settlementId
1264
+ || planSha256 !== digestCloudlyLegacyDeploymentSettlementOfflineExportPlan(plan)
1265
+ || value.observedFinalStateHmac !== plan.finalStateHmac
1266
+ || !canonicalEqual(observedCounts, plan.counts, `${pathArg}.observedCounts`)
1267
+ || !canonicalEqual(
1268
+ observedClassificationCounts,
1269
+ plan.classificationCounts,
1270
+ `${pathArg}.observedClassificationCounts`,
1271
+ )
1272
+ || (outcome === 'no-op') !== hasNoMutations(plan.counts)) {
1273
+ fail('CROSS_FIELD_MISMATCH', `${pathArg}.plan`);
1274
+ }
1275
+ return {
1276
+ schemaVersion: 1,
1277
+ kind: 'cloudly-legacy-deployment-settlement-offline-export-rehearsal-attestation',
1278
+ sourceAuthority,
1279
+ plan: plan as ICloudlyLegacyDeploymentSettlementOfflineExportPlanV1,
1280
+ planSha256,
1281
+ rehearsalRequestSha256: readSha256(
1282
+ value.rehearsalRequestSha256,
1283
+ `${pathArg}.rehearsalRequestSha256`,
1284
+ ),
1285
+ scratchAllocation: normalizeScratchAllocation(
1286
+ value.scratchAllocation,
1287
+ `${pathArg}.scratchAllocation`,
1288
+ ),
1289
+ outcome,
1290
+ observedFinalStateHmac: readStateHmac(
1291
+ value.observedFinalStateHmac,
1292
+ `${pathArg}.observedFinalStateHmac`,
1293
+ ),
1294
+ observedCounts,
1295
+ observedClassificationCounts,
1296
+ completedAt: readInteger(value.completedAt, `${pathArg}.completedAt`, 1),
1297
+ };
1298
+ };
1299
+
1300
+ const rehearsalPayload = (
1301
+ valueArg: ICloudlyLegacyDeploymentSettlementOfflineExportRehearsalAttestationPayloadV1,
1302
+ ): unknown => Object.fromEntries(rehearsalPayloadKeys.map((keyArg) => [
1303
+ keyArg,
1304
+ valueArg[keyArg],
1305
+ ]));
1306
+
1307
+ export const digestCloudlyLegacyDeploymentSettlementOfflineExportRehearsalAttestationPayload = (
1308
+ valueArg: unknown,
1309
+ ): string => digestBytes(encodeNormalized(
1310
+ rehearsalPayload(normalizeRehearsalPayloadInternal(
1311
+ valueArg,
1312
+ 'offlineExportRehearsalAttestationPayload',
1313
+ )),
1314
+ 'offlineExportRehearsalAttestationPayload',
1315
+ ));
1316
+
1317
+ const normalizeUnsignedRehearsalInternal = (
1318
+ valueArg: unknown,
1319
+ pathArg: string,
1320
+ ): TCloudlyLegacyDeploymentSettlementOfflineExportUnsignedRehearsalAttestationV1 => {
1321
+ const value = readRecord(valueArg, pathArg);
1322
+ assertExactKeys(value, rehearsalUnsignedKeys, pathArg);
1323
+ const payload = normalizeRehearsalPayloadInternal(
1324
+ Object.fromEntries(rehearsalPayloadKeys.map((keyArg) => [keyArg, value[keyArg]])),
1325
+ `${pathArg}.payload`,
1326
+ );
1327
+ const payloadSha256 = readSha256(value.payloadSha256, `${pathArg}.payloadSha256`);
1328
+ if (payloadSha256
1329
+ !== digestCloudlyLegacyDeploymentSettlementOfflineExportRehearsalAttestationPayload(
1330
+ payload,
1331
+ )) {
1332
+ fail('CROSS_FIELD_MISMATCH', `${pathArg}.payloadSha256`);
1333
+ }
1334
+ return { ...payload, payloadSha256 };
1335
+ };
1336
+
1337
+ export const normalizeCloudlyLegacyDeploymentSettlementOfflineExportRehearsalAttestation = (
1338
+ valueArg: unknown,
1339
+ ): Readonly<
1340
+ ICloudlyLegacyDeploymentSettlementOfflineExportRehearsalAttestationV1
1341
+ > => {
1342
+ const value = readRecord(valueArg, 'offlineExportRehearsalAttestation');
1343
+ assertExactKeys(value, rehearsalKeys, 'offlineExportRehearsalAttestation');
1344
+ return finalize({
1345
+ ...normalizeUnsignedRehearsalInternal(
1346
+ Object.fromEntries(rehearsalUnsignedKeys.map((keyArg) => [keyArg, value[keyArg]])),
1347
+ 'offlineExportRehearsalAttestation.unsigned',
1348
+ ),
1349
+ mac: readMac(value.mac, 'offlineExportRehearsalAttestation.mac'),
1350
+ }, cloudlyLegacyDeploymentSettlementOfflineExportLimits.maximumAuthenticatedArtifactBytes,
1351
+ 'offlineExportRehearsalAttestation');
1352
+ };
1353
+
1354
+ export const encodeCloudlyLegacyDeploymentSettlementOfflineExportRehearsalAttestation = (
1355
+ valueArg: unknown,
1356
+ ): Uint8Array => encodeNormalized(
1357
+ normalizeCloudlyLegacyDeploymentSettlementOfflineExportRehearsalAttestation(valueArg),
1358
+ 'offlineExportRehearsalAttestation',
1359
+ );
1360
+
1361
+ export const digestCloudlyLegacyDeploymentSettlementOfflineExportRehearsalAttestation = (
1362
+ valueArg: unknown,
1363
+ ): string => digestBytes(
1364
+ encodeCloudlyLegacyDeploymentSettlementOfflineExportRehearsalAttestation(valueArg),
1365
+ );
1366
+
1367
+ export const encodeCloudlyLegacyDeploymentSettlementOfflineExportRehearsalAttestationHmacInput = (
1368
+ valueArg: unknown,
1369
+ ): Uint8Array => frame(
1370
+ cloudlyLegacyDeploymentSettlementOfflineExportDomains.rehearsalAttestationHmac,
1371
+ encodeNormalized(
1372
+ finalize(
1373
+ normalizeUnsignedRehearsalInternal(
1374
+ valueArg,
1375
+ 'offlineExportUnsignedRehearsalAttestation',
1376
+ ),
1377
+ cloudlyLegacyDeploymentSettlementOfflineExportLimits.maximumAuthenticatedArtifactBytes,
1378
+ 'offlineExportUnsignedRehearsalAttestation',
1379
+ ),
1380
+ 'offlineExportUnsignedRehearsalAttestation',
1381
+ ),
1382
+ );
1383
+
1384
+ const requireVerifiedHmac = async (
1385
+ authorityArg: TCloudlyLegacyDeploymentSettlementOfflineExportAuthorityReferenceV1,
1386
+ domainArg: ICloudlyLegacyDeploymentSettlementOfflineExportHmacVerificationInputV1['domain'],
1387
+ hmacInputArg: Uint8Array,
1388
+ macArg: string,
1389
+ verifierArg: TCloudlyLegacyDeploymentSettlementOfflineExportHmacVerifier,
1390
+ pathArg: string,
1391
+ ): Promise<void> => {
1392
+ let verified = false;
1393
+ try {
1394
+ verified = await verifierArg({
1395
+ authority: authorityArg,
1396
+ domain: domainArg,
1397
+ hmacInput: new Uint8Array(hmacInputArg),
1398
+ mac: macArg,
1399
+ });
1400
+ } catch {
1401
+ verified = false;
1402
+ }
1403
+ if (!verified) fail('INVALID_VALUE', pathArg);
1404
+ };
1405
+
1406
+ const withoutMac = <TValue extends { mac: string }>(
1407
+ valueArg: TValue,
1408
+ ): Omit<TValue, 'mac'> => {
1409
+ const { mac: _mac, ...unsigned } = valueArg;
1410
+ return unsigned;
1411
+ };
1412
+
1413
+ export const normalizeCloudlyLegacyDeploymentSettlementOfflineExportRehearsalAttestationForAuthority = async (
1414
+ attestationArg: unknown,
1415
+ sourceAuthorityArg: unknown,
1416
+ verifierArg: TCloudlyLegacyDeploymentSettlementOfflineExportHmacVerifier,
1417
+ ): Promise<Readonly<
1418
+ ICloudlyLegacyDeploymentSettlementOfflineExportRehearsalAttestationV1
1419
+ >> => {
1420
+ const sourceAuthority = normalizeCloudlyLegacyDeploymentSettlementOfflineExportSourceAuthority(
1421
+ sourceAuthorityArg,
1422
+ );
1423
+ const attestation =
1424
+ normalizeCloudlyLegacyDeploymentSettlementOfflineExportRehearsalAttestation(
1425
+ attestationArg,
1426
+ );
1427
+ assertSourceReferenceMatchesAuthority(
1428
+ attestation.sourceAuthority,
1429
+ sourceAuthority,
1430
+ 'offlineExportRehearsalAttestation.sourceAuthority',
1431
+ );
1432
+ if (attestation.planSha256 !== sourceAuthority.planSha256
1433
+ || attestation.rehearsalRequestSha256 !== sourceAuthority.rehearsalRequestSha256
1434
+ || !canonicalEqual(
1435
+ attestation.plan.sourceFile,
1436
+ sourceAuthority.sourceFile,
1437
+ 'offlineExportRehearsalAttestation.plan.sourceFile',
1438
+ )
1439
+ || attestation.plan.operationId !== sourceAuthority.operationId
1440
+ || attestation.plan.settlementId !== sourceAuthority.settlementId) {
1441
+ fail('CROSS_FIELD_MISMATCH', 'offlineExportRehearsalAttestation.sourceProof');
1442
+ }
1443
+ assertTimestampWithinAuthority(
1444
+ attestation.plan.effectiveAt,
1445
+ sourceAuthority,
1446
+ 'offlineExportRehearsalAttestation.plan.effectiveAt',
1447
+ );
1448
+ assertTimestampWithinAuthority(
1449
+ attestation.completedAt,
1450
+ sourceAuthority,
1451
+ 'offlineExportRehearsalAttestation.completedAt',
1452
+ );
1453
+ if (attestation.completedAt < attestation.plan.effectiveAt) {
1454
+ fail('CROSS_FIELD_MISMATCH', 'offlineExportRehearsalAttestation.completedAt');
1455
+ }
1456
+ await requireVerifiedHmac(
1457
+ attestation.sourceAuthority,
1458
+ cloudlyLegacyDeploymentSettlementOfflineExportDomains.rehearsalAttestationHmac,
1459
+ encodeCloudlyLegacyDeploymentSettlementOfflineExportRehearsalAttestationHmacInput(
1460
+ withoutMac(attestation),
1461
+ ),
1462
+ attestation.mac,
1463
+ verifierArg,
1464
+ 'offlineExportRehearsalAttestation.mac',
1465
+ );
1466
+ return attestation;
1467
+ };
1468
+
1469
+ export const normalizeCloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthority = (
1470
+ valueArg: unknown,
1471
+ ): Readonly<
1472
+ ICloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthorityV1
1473
+ > => {
1474
+ const value = readRecord(valueArg, 'offlineExportProductionTransformAuthority');
1475
+ assertExactKeys(
1476
+ value,
1477
+ productionTransformAuthorityKeys,
1478
+ 'offlineExportProductionTransformAuthority',
1479
+ );
1480
+ if (value.schemaVersion !== 1
1481
+ || value.kind
1482
+ !== 'cloudly-legacy-deployment-settlement-offline-export-production-transform-authority'
1483
+ || value.role !== 'production-transform'
1484
+ || value.keyVersion !== 1) {
1485
+ fail('INVALID_VALUE', 'offlineExportProductionTransformAuthority.kind');
1486
+ }
1487
+ const sourceAuthority = normalizeAuthorityReferenceInternal(
1488
+ value.sourceAuthority,
1489
+ 'offlineExportProductionTransformAuthority.sourceAuthority',
1490
+ 'source-rehearsal',
1491
+ );
1492
+ const operationId = readIdentifier(
1493
+ value.operationId,
1494
+ 'offlineExportProductionTransformAuthority.operationId',
1495
+ );
1496
+ const settlementId = readIdentifier(
1497
+ value.settlementId,
1498
+ 'offlineExportProductionTransformAuthority.settlementId',
1499
+ );
1500
+ const authorityId = readIdentifier(
1501
+ value.authorityId,
1502
+ 'offlineExportProductionTransformAuthority.authorityId',
1503
+ );
1504
+ const keyId = readIdentifier(
1505
+ value.keyId,
1506
+ 'offlineExportProductionTransformAuthority.keyId',
1507
+ );
1508
+ if (operationId !== sourceAuthority.operationId
1509
+ || settlementId !== sourceAuthority.settlementId
1510
+ || authorityId === sourceAuthority.authorityId
1511
+ || keyId === sourceAuthority.keyId) {
1512
+ fail('CROSS_FIELD_MISMATCH', 'offlineExportProductionTransformAuthority.sourceAuthority');
1513
+ }
1514
+ return finalize({
1515
+ schemaVersion: 1,
1516
+ kind: 'cloudly-legacy-deployment-settlement-offline-export-production-transform-authority',
1517
+ role: 'production-transform',
1518
+ operationId,
1519
+ settlementId,
1520
+ authorityId,
1521
+ keyId,
1522
+ keyVersion: 1,
1523
+ ...normalizeAuthorityWindow(value, 'offlineExportProductionTransformAuthority'),
1524
+ sourceAuthority,
1525
+ authenticatedRehearsalAttestationSha256: readSha256(
1526
+ value.authenticatedRehearsalAttestationSha256,
1527
+ 'offlineExportProductionTransformAuthority.authenticatedRehearsalAttestationSha256',
1528
+ ),
1529
+ } satisfies ICloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthorityV1,
1530
+ cloudlyLegacyDeploymentSettlementOfflineExportLimits.maximumAuthorityBytes,
1531
+ 'offlineExportProductionTransformAuthority');
1532
+ };
1533
+
1534
+ export const encodeCloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthority = (
1535
+ valueArg: unknown,
1536
+ ): Uint8Array => encodeNormalized(
1537
+ normalizeCloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthority(valueArg),
1538
+ 'offlineExportProductionTransformAuthority',
1539
+ );
1540
+
1541
+ export const digestCloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthority = (
1542
+ valueArg: unknown,
1543
+ ): string => digestBytes(
1544
+ encodeCloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthority(valueArg),
1545
+ );
1546
+
1547
+ export const createCloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthorityReference = (
1548
+ authorityArg: unknown,
1549
+ ): Readonly<
1550
+ ICloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthorityReferenceV1
1551
+ > => {
1552
+ const authority =
1553
+ normalizeCloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthority(
1554
+ authorityArg,
1555
+ );
1556
+ return finalize({
1557
+ schemaVersion: 1,
1558
+ kind: 'cloudly-legacy-deployment-settlement-offline-export-authority-reference',
1559
+ role: 'production-transform',
1560
+ operationId: authority.operationId,
1561
+ settlementId: authority.settlementId,
1562
+ authorityId: authority.authorityId,
1563
+ keyId: authority.keyId,
1564
+ keyVersion: 1,
1565
+ authorityMetadataSha256:
1566
+ digestCloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthority(
1567
+ authority,
1568
+ ),
1569
+ }, cloudlyLegacyDeploymentSettlementOfflineExportLimits.maximumAuthorityBytes,
1570
+ 'offlineExportProductionTransformAuthorityReference');
1571
+ };
1572
+
1573
+ const assertProductionReferenceMatchesAuthority = (
1574
+ referenceArg: unknown,
1575
+ authorityArg: unknown,
1576
+ pathArg: string,
1577
+ ): void => {
1578
+ const reference =
1579
+ normalizeCloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthorityReference(
1580
+ referenceArg,
1581
+ );
1582
+ const expected =
1583
+ createCloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthorityReference(
1584
+ authorityArg,
1585
+ );
1586
+ if (!canonicalEqual(reference, expected, pathArg)) {
1587
+ fail('CROSS_FIELD_MISMATCH', pathArg);
1588
+ }
1589
+ };
1590
+
1591
+ export const normalizeCloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthorityForRehearsal = async (
1592
+ productionAuthorityArg: unknown,
1593
+ sourceAuthorityArg: unknown,
1594
+ rehearsalAttestationArg: unknown,
1595
+ verifierArg: TCloudlyLegacyDeploymentSettlementOfflineExportHmacVerifier,
1596
+ ): Promise<Readonly<
1597
+ ICloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthorityV1
1598
+ >> => {
1599
+ const sourceAuthority = normalizeCloudlyLegacyDeploymentSettlementOfflineExportSourceAuthority(
1600
+ sourceAuthorityArg,
1601
+ );
1602
+ const rehearsal =
1603
+ await normalizeCloudlyLegacyDeploymentSettlementOfflineExportRehearsalAttestationForAuthority(
1604
+ rehearsalAttestationArg,
1605
+ sourceAuthority,
1606
+ verifierArg,
1607
+ );
1608
+ const productionAuthority =
1609
+ normalizeCloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthority(
1610
+ productionAuthorityArg,
1611
+ );
1612
+ assertSourceReferenceMatchesAuthority(
1613
+ productionAuthority.sourceAuthority,
1614
+ sourceAuthority,
1615
+ 'offlineExportProductionTransformAuthority.sourceAuthority',
1616
+ );
1617
+ if (productionAuthority.authenticatedRehearsalAttestationSha256
1618
+ !== digestCloudlyLegacyDeploymentSettlementOfflineExportRehearsalAttestation(rehearsal)
1619
+ || productionAuthority.issuedAt <= rehearsal.completedAt) {
1620
+ fail('CROSS_FIELD_MISMATCH', 'offlineExportProductionTransformAuthority.rehearsal');
1621
+ }
1622
+ return productionAuthority;
1623
+ };
1624
+
1625
+ const normalizeAuthorizationPayloadInternal = (
1626
+ valueArg: unknown,
1627
+ pathArg: string,
1628
+ ): ICloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthorizationPayloadV1 => {
1629
+ const value = readRecord(valueArg, pathArg);
1630
+ assertExactKeys(value, authorizationPayloadKeys, pathArg);
1631
+ if (value.schemaVersion !== 1
1632
+ || value.kind
1633
+ !== 'cloudly-legacy-deployment-settlement-offline-export-production-transform-authorization') {
1634
+ fail('INVALID_VALUE', `${pathArg}.kind`);
1635
+ }
1636
+ const authority = normalizeAuthorityReferenceInternal(
1637
+ value.authority,
1638
+ `${pathArg}.authority`,
1639
+ 'production-transform',
1640
+ );
1641
+ const sourceAuthority = normalizeAuthorityReferenceInternal(
1642
+ value.sourceAuthority,
1643
+ `${pathArg}.sourceAuthority`,
1644
+ 'source-rehearsal',
1645
+ );
1646
+ const requestedAt = readInteger(value.requestedAt, `${pathArg}.requestedAt`, 1);
1647
+ const authorizedAt = readInteger(value.authorizedAt, `${pathArg}.authorizedAt`, requestedAt);
1648
+ if (authority.operationId !== sourceAuthority.operationId
1649
+ || authority.settlementId !== sourceAuthority.settlementId
1650
+ || authority.authorityId === sourceAuthority.authorityId
1651
+ || authority.keyId === sourceAuthority.keyId
1652
+ || canonicalEqual(authority, sourceAuthority, `${pathArg}.authorities`)) {
1653
+ fail('CROSS_FIELD_MISMATCH', `${pathArg}.authority`);
1654
+ }
1655
+ return {
1656
+ schemaVersion: 1,
1657
+ kind: 'cloudly-legacy-deployment-settlement-offline-export-production-transform-authorization',
1658
+ authority,
1659
+ sourceAuthority,
1660
+ attemptId: readIdentifier(value.attemptId, `${pathArg}.attemptId`),
1661
+ authenticatedRehearsalAttestationSha256: readSha256(
1662
+ value.authenticatedRehearsalAttestationSha256,
1663
+ `${pathArg}.authenticatedRehearsalAttestationSha256`,
1664
+ ),
1665
+ planSha256: readSha256(value.planSha256, `${pathArg}.planSha256`),
1666
+ requestSha256: readSha256(value.requestSha256, `${pathArg}.requestSha256`),
1667
+ requestedAt,
1668
+ authorizedAt,
1669
+ };
1670
+ };
1671
+
1672
+ const authorizationPayload = (
1673
+ valueArg:
1674
+ ICloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthorizationPayloadV1,
1675
+ ): unknown => Object.fromEntries(authorizationPayloadKeys.map((keyArg) => [
1676
+ keyArg,
1677
+ valueArg[keyArg],
1678
+ ]));
1679
+
1680
+ export const digestCloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthorizationPayload = (
1681
+ valueArg: unknown,
1682
+ ): string => digestBytes(encodeNormalized(
1683
+ authorizationPayload(normalizeAuthorizationPayloadInternal(
1684
+ valueArg,
1685
+ 'offlineExportProductionTransformAuthorizationPayload',
1686
+ )),
1687
+ 'offlineExportProductionTransformAuthorizationPayload',
1688
+ ));
1689
+
1690
+ const normalizeUnsignedAuthorizationInternal = (
1691
+ valueArg: unknown,
1692
+ pathArg: string,
1693
+ ): TCloudlyLegacyDeploymentSettlementOfflineExportUnsignedProductionTransformAuthorizationV1 => {
1694
+ const value = readRecord(valueArg, pathArg);
1695
+ assertExactKeys(value, authorizationUnsignedKeys, pathArg);
1696
+ const payload = normalizeAuthorizationPayloadInternal(
1697
+ Object.fromEntries(authorizationPayloadKeys.map((keyArg) => [keyArg, value[keyArg]])),
1698
+ `${pathArg}.payload`,
1699
+ );
1700
+ const payloadSha256 = readSha256(value.payloadSha256, `${pathArg}.payloadSha256`);
1701
+ if (payloadSha256
1702
+ !== digestCloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthorizationPayload(
1703
+ payload,
1704
+ )) {
1705
+ fail('CROSS_FIELD_MISMATCH', `${pathArg}.payloadSha256`);
1706
+ }
1707
+ return { ...payload, payloadSha256 };
1708
+ };
1709
+
1710
+ export const normalizeCloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthorization = (
1711
+ valueArg: unknown,
1712
+ ): Readonly<
1713
+ ICloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthorizationV1
1714
+ > => {
1715
+ const value = readRecord(valueArg, 'offlineExportProductionTransformAuthorization');
1716
+ assertExactKeys(value, authorizationKeys, 'offlineExportProductionTransformAuthorization');
1717
+ return finalize({
1718
+ ...normalizeUnsignedAuthorizationInternal(
1719
+ Object.fromEntries(authorizationUnsignedKeys.map((keyArg) => [keyArg, value[keyArg]])),
1720
+ 'offlineExportProductionTransformAuthorization.unsigned',
1721
+ ),
1722
+ mac: readMac(value.mac, 'offlineExportProductionTransformAuthorization.mac'),
1723
+ }, cloudlyLegacyDeploymentSettlementOfflineExportLimits.maximumAuthenticatedArtifactBytes,
1724
+ 'offlineExportProductionTransformAuthorization');
1725
+ };
1726
+
1727
+ export const encodeCloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthorization = (
1728
+ valueArg: unknown,
1729
+ ): Uint8Array => encodeNormalized(
1730
+ normalizeCloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthorization(
1731
+ valueArg,
1732
+ ),
1733
+ 'offlineExportProductionTransformAuthorization',
1734
+ );
1735
+
1736
+ export const digestCloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthorization = (
1737
+ valueArg: unknown,
1738
+ ): string => digestBytes(
1739
+ encodeCloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthorization(valueArg),
1740
+ );
1741
+
1742
+ export const encodeCloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthorizationHmacInput = (
1743
+ valueArg: unknown,
1744
+ ): Uint8Array => frame(
1745
+ cloudlyLegacyDeploymentSettlementOfflineExportDomains
1746
+ .productionTransformAuthorizationHmac,
1747
+ encodeNormalized(
1748
+ finalize(
1749
+ normalizeUnsignedAuthorizationInternal(
1750
+ valueArg,
1751
+ 'offlineExportUnsignedProductionTransformAuthorization',
1752
+ ),
1753
+ cloudlyLegacyDeploymentSettlementOfflineExportLimits.maximumAuthenticatedArtifactBytes,
1754
+ 'offlineExportUnsignedProductionTransformAuthorization',
1755
+ ),
1756
+ 'offlineExportUnsignedProductionTransformAuthorization',
1757
+ ),
1758
+ );
1759
+
1760
+ export const normalizeCloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthorizationForAuthorities = async (
1761
+ authorizationArg: unknown,
1762
+ productionAuthorityArg: unknown,
1763
+ sourceAuthorityArg: unknown,
1764
+ rehearsalAttestationArg: unknown,
1765
+ verifierArg: TCloudlyLegacyDeploymentSettlementOfflineExportHmacVerifier,
1766
+ ): Promise<Readonly<
1767
+ ICloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthorizationV1
1768
+ >> => {
1769
+ const sourceAuthority = normalizeCloudlyLegacyDeploymentSettlementOfflineExportSourceAuthority(
1770
+ sourceAuthorityArg,
1771
+ );
1772
+ const rehearsal =
1773
+ await normalizeCloudlyLegacyDeploymentSettlementOfflineExportRehearsalAttestationForAuthority(
1774
+ rehearsalAttestationArg,
1775
+ sourceAuthority,
1776
+ verifierArg,
1777
+ );
1778
+ const productionAuthority =
1779
+ await normalizeCloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthorityForRehearsal(
1780
+ productionAuthorityArg,
1781
+ sourceAuthority,
1782
+ rehearsal,
1783
+ verifierArg,
1784
+ );
1785
+ const authorization =
1786
+ normalizeCloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthorization(
1787
+ authorizationArg,
1788
+ );
1789
+ assertProductionReferenceMatchesAuthority(
1790
+ authorization.authority,
1791
+ productionAuthority,
1792
+ 'offlineExportProductionTransformAuthorization.authority',
1793
+ );
1794
+ assertSourceReferenceMatchesAuthority(
1795
+ authorization.sourceAuthority,
1796
+ sourceAuthority,
1797
+ 'offlineExportProductionTransformAuthorization.sourceAuthority',
1798
+ );
1799
+ if (authorization.authenticatedRehearsalAttestationSha256
1800
+ !== productionAuthority.authenticatedRehearsalAttestationSha256
1801
+ || authorization.planSha256 !== rehearsal.planSha256
1802
+ || authorization.requestedAt < productionAuthority.issuedAt) {
1803
+ fail('CROSS_FIELD_MISMATCH', 'offlineExportProductionTransformAuthorization.sourceProof');
1804
+ }
1805
+ assertTimestampWithinAuthority(
1806
+ authorization.requestedAt,
1807
+ productionAuthority,
1808
+ 'offlineExportProductionTransformAuthorization.requestedAt',
1809
+ );
1810
+ assertTimestampWithinAuthority(
1811
+ authorization.authorizedAt,
1812
+ productionAuthority,
1813
+ 'offlineExportProductionTransformAuthorization.authorizedAt',
1814
+ );
1815
+ await requireVerifiedHmac(
1816
+ authorization.authority,
1817
+ cloudlyLegacyDeploymentSettlementOfflineExportDomains
1818
+ .productionTransformAuthorizationHmac,
1819
+ encodeCloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthorizationHmacInput(
1820
+ withoutMac(authorization),
1821
+ ),
1822
+ authorization.mac,
1823
+ verifierArg,
1824
+ 'offlineExportProductionTransformAuthorization.mac',
1825
+ );
1826
+ return authorization;
1827
+ };
1828
+
1829
+ const normalizeJournalSeedInternal = (
1830
+ valueArg: unknown,
1831
+ pathArg: string,
1832
+ ): ICloudlyLegacyDeploymentSettlementOfflineExportAttemptJournalSeedV1 => {
1833
+ const value = readRecord(valueArg, pathArg);
1834
+ assertExactKeys(value, journalSeedKeys, pathArg);
1835
+ if (value.schemaVersion !== 1
1836
+ || value.kind !== cloudlyLegacyDeploymentSettlementOfflineExportJournalCollectionName
1837
+ || value.purpose !== 'production-transform') {
1838
+ fail('INVALID_VALUE', `${pathArg}.kind`);
1839
+ }
1840
+ const operationId = readIdentifier(value.operationId, `${pathArg}.operationId`);
1841
+ const settlementId = readIdentifier(value.settlementId, `${pathArg}.settlementId`);
1842
+ const sourceAuthority = normalizeAuthorityReferenceInternal(
1843
+ value.sourceAuthority,
1844
+ `${pathArg}.sourceAuthority`,
1845
+ 'source-rehearsal',
1846
+ );
1847
+ const productionTransformAuthority = normalizeAuthorityReferenceInternal(
1848
+ value.productionTransformAuthority,
1849
+ `${pathArg}.productionTransformAuthority`,
1850
+ 'production-transform',
1851
+ );
1852
+ const sourceFile = normalizeFileIdentityInternal(value.sourceFile, `${pathArg}.sourceFile`);
1853
+ const transformedCoreFile = normalizeFileIdentityInternal(
1854
+ value.transformedCoreFile,
1855
+ `${pathArg}.transformedCoreFile`,
1856
+ );
1857
+ const sourceStateHmac = readStateHmac(
1858
+ value.sourceStateHmac,
1859
+ `${pathArg}.sourceStateHmac`,
1860
+ );
1861
+ const finalStateHmac = readStateHmac(
1862
+ value.finalStateHmac,
1863
+ `${pathArg}.finalStateHmac`,
1864
+ );
1865
+ const outcome = readLiteral(
1866
+ value.outcome,
1867
+ ['transformed', 'no-op'],
1868
+ `${pathArg}.outcome`,
1869
+ );
1870
+ const counts = normalizeMutationCounts(value.counts, `${pathArg}.counts`);
1871
+ const classificationCounts = normalizeClassificationCounts(
1872
+ value.classificationCounts,
1873
+ `${pathArg}.classificationCounts`,
1874
+ );
1875
+ assertCountsMatchClassifications(counts, classificationCounts, `${pathArg}.counts`);
1876
+ if (operationId !== sourceAuthority.operationId
1877
+ || operationId !== productionTransformAuthority.operationId
1878
+ || settlementId !== sourceAuthority.settlementId
1879
+ || settlementId !== productionTransformAuthority.settlementId
1880
+ || sourceAuthority.authorityId === productionTransformAuthority.authorityId
1881
+ || sourceAuthority.keyId === productionTransformAuthority.keyId
1882
+ || sourceFile.databaseName !== transformedCoreFile.databaseName
1883
+ || (outcome === 'no-op') !== hasNoMutations(counts)
1884
+ || (outcome === 'no-op') !== (sourceStateHmac === finalStateHmac)
1885
+ || (outcome === 'no-op') !== canonicalEqual(
1886
+ sourceFile,
1887
+ transformedCoreFile,
1888
+ `${pathArg}.fileIdentity`,
1889
+ )) {
1890
+ fail('CROSS_FIELD_MISMATCH', `${pathArg}.sourceProof`);
1891
+ }
1892
+ return {
1893
+ schemaVersion: 1,
1894
+ kind: cloudlyLegacyDeploymentSettlementOfflineExportJournalCollectionName,
1895
+ purpose: 'production-transform',
1896
+ operationId,
1897
+ settlementId,
1898
+ attemptId: readIdentifier(value.attemptId, `${pathArg}.attemptId`),
1899
+ sourceAuthority,
1900
+ productionTransformAuthority,
1901
+ authenticatedRehearsalAttestationSha256: readSha256(
1902
+ value.authenticatedRehearsalAttestationSha256,
1903
+ `${pathArg}.authenticatedRehearsalAttestationSha256`,
1904
+ ),
1905
+ transformAuthorizationSha256: readSha256(
1906
+ value.transformAuthorizationSha256,
1907
+ `${pathArg}.transformAuthorizationSha256`,
1908
+ ),
1909
+ planSha256: readSha256(value.planSha256, `${pathArg}.planSha256`),
1910
+ requestSha256: readSha256(value.requestSha256, `${pathArg}.requestSha256`),
1911
+ sourceFile,
1912
+ transformedCoreFile,
1913
+ sourceStateHmac,
1914
+ finalStateHmac,
1915
+ outcome,
1916
+ counts,
1917
+ classificationCounts,
1918
+ completedAt: readInteger(value.completedAt, `${pathArg}.completedAt`, 1),
1919
+ };
1920
+ };
1921
+
1922
+ export const createCloudlyLegacyDeploymentSettlementOfflineExportAttemptJournalId = (
1923
+ seedArg: unknown,
1924
+ ): string => {
1925
+ const seed = normalizeJournalSeedInternal(seedArg, 'offlineExportAttemptJournal.seed');
1926
+ return `offline-export-attempt-${digestBytes(encodeNormalized(
1927
+ seed,
1928
+ 'offlineExportAttemptJournal.seed',
1929
+ )).slice(0, 40)}`;
1930
+ };
1931
+
1932
+ const normalizeUnsignedJournalInternal = (
1933
+ valueArg: unknown,
1934
+ pathArg: string,
1935
+ ): TCloudlyLegacyDeploymentSettlementOfflineExportUnsignedAttemptJournalV1 => {
1936
+ const value = readRecord(valueArg, pathArg);
1937
+ assertExactKeys(value, journalUnsignedKeys, pathArg);
1938
+ const seed = normalizeJournalSeedInternal(
1939
+ Object.fromEntries(journalSeedKeys.map((keyArg) => [keyArg, value[keyArg]])),
1940
+ `${pathArg}.seed`,
1941
+ );
1942
+ const id = readIdentifier(value._id, `${pathArg}._id`);
1943
+ if (id !== createCloudlyLegacyDeploymentSettlementOfflineExportAttemptJournalId(seed)) {
1944
+ fail('CROSS_FIELD_MISMATCH', `${pathArg}._id`);
1945
+ }
1946
+ return { _id: id, ...seed };
1947
+ };
1948
+
1949
+ export const normalizeCloudlyLegacyDeploymentSettlementOfflineExportAttemptJournal = (
1950
+ valueArg: unknown,
1951
+ ): Readonly<ICloudlyLegacyDeploymentSettlementOfflineExportAttemptJournalV1> => {
1952
+ const value = readRecord(valueArg, 'offlineExportAttemptJournal');
1953
+ assertExactKeys(value, journalKeys, 'offlineExportAttemptJournal');
1954
+ return finalize({
1955
+ ...normalizeUnsignedJournalInternal(
1956
+ Object.fromEntries(journalUnsignedKeys.map((keyArg) => [keyArg, value[keyArg]])),
1957
+ 'offlineExportAttemptJournal.unsigned',
1958
+ ),
1959
+ mac: readMac(value.mac, 'offlineExportAttemptJournal.mac'),
1960
+ }, cloudlyLegacyDeploymentSettlementOfflineExportLimits.maximumJournalCanonicalBytes,
1961
+ 'offlineExportAttemptJournal');
1962
+ };
1963
+
1964
+ export const encodeCloudlyLegacyDeploymentSettlementOfflineExportAttemptJournal = (
1965
+ valueArg: unknown,
1966
+ ): Uint8Array => encodeNormalized(
1967
+ normalizeCloudlyLegacyDeploymentSettlementOfflineExportAttemptJournal(valueArg),
1968
+ 'offlineExportAttemptJournal',
1969
+ );
1970
+
1971
+ export const digestCloudlyLegacyDeploymentSettlementOfflineExportAttemptJournal = (
1972
+ valueArg: unknown,
1973
+ ): string => digestBytes(
1974
+ encodeCloudlyLegacyDeploymentSettlementOfflineExportAttemptJournal(valueArg),
1975
+ );
1976
+
1977
+ export const encodeCloudlyLegacyDeploymentSettlementOfflineExportAttemptJournalHmacInput = (
1978
+ valueArg: unknown,
1979
+ ): Uint8Array => frame(
1980
+ cloudlyLegacyDeploymentSettlementOfflineExportDomains.attemptJournalHmac,
1981
+ encodeNormalized(
1982
+ finalize(
1983
+ normalizeUnsignedJournalInternal(valueArg, 'offlineExportUnsignedAttemptJournal'),
1984
+ cloudlyLegacyDeploymentSettlementOfflineExportLimits.maximumJournalCanonicalBytes,
1985
+ 'offlineExportUnsignedAttemptJournal',
1986
+ ),
1987
+ 'offlineExportUnsignedAttemptJournal',
1988
+ ),
1989
+ );
1990
+
1991
+ export const normalizeCloudlyLegacyDeploymentSettlementOfflineExportAttemptJournalForAuthorities = async (
1992
+ journalArg: unknown,
1993
+ authorizationArg: unknown,
1994
+ productionAuthorityArg: unknown,
1995
+ sourceAuthorityArg: unknown,
1996
+ rehearsalAttestationArg: unknown,
1997
+ verifierArg: TCloudlyLegacyDeploymentSettlementOfflineExportHmacVerifier,
1998
+ ): Promise<Readonly<ICloudlyLegacyDeploymentSettlementOfflineExportAttemptJournalV1>> => {
1999
+ const authorization =
2000
+ await normalizeCloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthorizationForAuthorities(
2001
+ authorizationArg,
2002
+ productionAuthorityArg,
2003
+ sourceAuthorityArg,
2004
+ rehearsalAttestationArg,
2005
+ verifierArg,
2006
+ );
2007
+ const productionAuthority =
2008
+ normalizeCloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthority(
2009
+ productionAuthorityArg,
2010
+ );
2011
+ const rehearsal =
2012
+ normalizeCloudlyLegacyDeploymentSettlementOfflineExportRehearsalAttestation(
2013
+ rehearsalAttestationArg,
2014
+ );
2015
+ const journal = normalizeCloudlyLegacyDeploymentSettlementOfflineExportAttemptJournal(
2016
+ journalArg,
2017
+ );
2018
+ if (!canonicalEqual(
2019
+ journal.sourceAuthority,
2020
+ authorization.sourceAuthority,
2021
+ 'offlineExportAttemptJournal.sourceAuthority',
2022
+ )
2023
+ || !canonicalEqual(
2024
+ journal.productionTransformAuthority,
2025
+ authorization.authority,
2026
+ 'offlineExportAttemptJournal.productionTransformAuthority',
2027
+ )
2028
+ || journal.attemptId !== authorization.attemptId
2029
+ || journal.authenticatedRehearsalAttestationSha256
2030
+ !== authorization.authenticatedRehearsalAttestationSha256
2031
+ || journal.transformAuthorizationSha256
2032
+ !== digestCloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthorization(
2033
+ authorization,
2034
+ )
2035
+ || journal.planSha256 !== authorization.planSha256
2036
+ || journal.requestSha256 !== authorization.requestSha256
2037
+ || !canonicalEqual(
2038
+ journal.sourceFile,
2039
+ rehearsal.plan.sourceFile,
2040
+ 'offlineExportAttemptJournal.sourceFile',
2041
+ )
2042
+ || journal.sourceStateHmac !== rehearsal.plan.sourceStateHmac
2043
+ || journal.finalStateHmac !== rehearsal.plan.finalStateHmac
2044
+ || !canonicalEqual(journal.counts, rehearsal.plan.counts, 'offlineExportAttemptJournal.counts')
2045
+ || !canonicalEqual(
2046
+ journal.classificationCounts,
2047
+ rehearsal.plan.classificationCounts,
2048
+ 'offlineExportAttemptJournal.classificationCounts',
2049
+ )
2050
+ || journal.completedAt < authorization.authorizedAt) {
2051
+ fail('CROSS_FIELD_MISMATCH', 'offlineExportAttemptJournal.sourceProof');
2052
+ }
2053
+ assertTimestampWithinAuthority(
2054
+ journal.completedAt,
2055
+ productionAuthority,
2056
+ 'offlineExportAttemptJournal.completedAt',
2057
+ );
2058
+ await requireVerifiedHmac(
2059
+ journal.productionTransformAuthority,
2060
+ cloudlyLegacyDeploymentSettlementOfflineExportDomains.attemptJournalHmac,
2061
+ encodeCloudlyLegacyDeploymentSettlementOfflineExportAttemptJournalHmacInput(
2062
+ withoutMac(journal),
2063
+ ),
2064
+ journal.mac,
2065
+ verifierArg,
2066
+ 'offlineExportAttemptJournal.mac',
2067
+ );
2068
+ return journal;
2069
+ };
2070
+
2071
+ const normalizeCompleteOutputReceiptPayloadInternal = (
2072
+ valueArg: unknown,
2073
+ pathArg: string,
2074
+ ): ICloudlyLegacyDeploymentSettlementOfflineExportCompleteOutputReceiptPayloadV1 => {
2075
+ const value = readRecord(valueArg, pathArg);
2076
+ assertExactKeys(value, completeOutputReceiptPayloadKeys, pathArg);
2077
+ if (value.schemaVersion !== 1
2078
+ || value.kind
2079
+ !== 'cloudly-legacy-deployment-settlement-offline-export-complete-output-receipt') {
2080
+ fail('INVALID_VALUE', `${pathArg}.kind`);
2081
+ }
2082
+ const authority = normalizeAuthorityReferenceInternal(
2083
+ value.authority,
2084
+ `${pathArg}.authority`,
2085
+ 'production-transform',
2086
+ );
2087
+ const sourceAuthority = normalizeAuthorityReferenceInternal(
2088
+ value.sourceAuthority,
2089
+ `${pathArg}.sourceAuthority`,
2090
+ 'source-rehearsal',
2091
+ );
2092
+ const operationId = readIdentifier(value.operationId, `${pathArg}.operationId`);
2093
+ const settlementId = readIdentifier(value.settlementId, `${pathArg}.settlementId`);
2094
+ const transformedCoreFile = normalizeFileIdentityInternal(
2095
+ value.transformedCoreFile,
2096
+ `${pathArg}.transformedCoreFile`,
2097
+ );
2098
+ const completeOutputFile = normalizeFileIdentityInternal(
2099
+ value.completeOutputFile,
2100
+ `${pathArg}.completeOutputFile`,
2101
+ );
2102
+ const journalGrowthBytes = readInteger(
2103
+ value.journalGrowthBytes,
2104
+ `${pathArg}.journalGrowthBytes`,
2105
+ 1,
2106
+ cloudlyLegacyDeploymentSettlementOfflineExportLimits.maximumJournalGrowthBytes,
2107
+ );
2108
+ if (operationId !== authority.operationId
2109
+ || operationId !== sourceAuthority.operationId
2110
+ || settlementId !== authority.settlementId
2111
+ || settlementId !== sourceAuthority.settlementId
2112
+ || authority.authorityId === sourceAuthority.authorityId
2113
+ || authority.keyId === sourceAuthority.keyId
2114
+ || transformedCoreFile.databaseName !== completeOutputFile.databaseName
2115
+ || completeOutputFile.byteLength - transformedCoreFile.byteLength !== journalGrowthBytes) {
2116
+ fail('CROSS_FIELD_MISMATCH', `${pathArg}.completeOutputFile`);
2117
+ }
2118
+ return {
2119
+ schemaVersion: 1,
2120
+ kind: 'cloudly-legacy-deployment-settlement-offline-export-complete-output-receipt',
2121
+ authority,
2122
+ sourceAuthority,
2123
+ operationId,
2124
+ settlementId,
2125
+ attemptId: readIdentifier(value.attemptId, `${pathArg}.attemptId`),
2126
+ journalSha256: readSha256(value.journalSha256, `${pathArg}.journalSha256`),
2127
+ transformedCoreFile,
2128
+ completeOutputFile,
2129
+ journalGrowthBytes,
2130
+ completedAt: readInteger(value.completedAt, `${pathArg}.completedAt`, 1),
2131
+ };
2132
+ };
2133
+
2134
+ const completeOutputReceiptPayload = (
2135
+ valueArg:
2136
+ ICloudlyLegacyDeploymentSettlementOfflineExportCompleteOutputReceiptPayloadV1,
2137
+ ): unknown => Object.fromEntries(completeOutputReceiptPayloadKeys.map((keyArg) => [
2138
+ keyArg,
2139
+ valueArg[keyArg],
2140
+ ]));
2141
+
2142
+ export const digestCloudlyLegacyDeploymentSettlementOfflineExportCompleteOutputReceiptPayload = (
2143
+ valueArg: unknown,
2144
+ ): string => digestBytes(encodeNormalized(
2145
+ completeOutputReceiptPayload(normalizeCompleteOutputReceiptPayloadInternal(
2146
+ valueArg,
2147
+ 'offlineExportCompleteOutputReceiptPayload',
2148
+ )),
2149
+ 'offlineExportCompleteOutputReceiptPayload',
2150
+ ));
2151
+
2152
+ const normalizeUnsignedCompleteOutputReceiptInternal = (
2153
+ valueArg: unknown,
2154
+ pathArg: string,
2155
+ ): TCloudlyLegacyDeploymentSettlementOfflineExportUnsignedCompleteOutputReceiptV1 => {
2156
+ const value = readRecord(valueArg, pathArg);
2157
+ assertExactKeys(value, completeOutputReceiptUnsignedKeys, pathArg);
2158
+ const payload = normalizeCompleteOutputReceiptPayloadInternal(
2159
+ Object.fromEntries(completeOutputReceiptPayloadKeys.map((keyArg) => [keyArg, value[keyArg]])),
2160
+ `${pathArg}.payload`,
2161
+ );
2162
+ const payloadSha256 = readSha256(value.payloadSha256, `${pathArg}.payloadSha256`);
2163
+ if (payloadSha256
2164
+ !== digestCloudlyLegacyDeploymentSettlementOfflineExportCompleteOutputReceiptPayload(
2165
+ payload,
2166
+ )) {
2167
+ fail('CROSS_FIELD_MISMATCH', `${pathArg}.payloadSha256`);
2168
+ }
2169
+ return { ...payload, payloadSha256 };
2170
+ };
2171
+
2172
+ export const normalizeCloudlyLegacyDeploymentSettlementOfflineExportCompleteOutputReceipt = (
2173
+ valueArg: unknown,
2174
+ ): Readonly<
2175
+ ICloudlyLegacyDeploymentSettlementOfflineExportCompleteOutputReceiptV1
2176
+ > => {
2177
+ const value = readRecord(valueArg, 'offlineExportCompleteOutputReceipt');
2178
+ assertExactKeys(value, completeOutputReceiptKeys, 'offlineExportCompleteOutputReceipt');
2179
+ return finalize({
2180
+ ...normalizeUnsignedCompleteOutputReceiptInternal(
2181
+ Object.fromEntries(completeOutputReceiptUnsignedKeys.map((keyArg) => [
2182
+ keyArg,
2183
+ value[keyArg],
2184
+ ])),
2185
+ 'offlineExportCompleteOutputReceipt.unsigned',
2186
+ ),
2187
+ mac: readMac(value.mac, 'offlineExportCompleteOutputReceipt.mac'),
2188
+ }, cloudlyLegacyDeploymentSettlementOfflineExportLimits.maximumReceiptBytes,
2189
+ 'offlineExportCompleteOutputReceipt');
2190
+ };
2191
+
2192
+ export const encodeCloudlyLegacyDeploymentSettlementOfflineExportCompleteOutputReceipt = (
2193
+ valueArg: unknown,
2194
+ ): Uint8Array => encodeNormalized(
2195
+ normalizeCloudlyLegacyDeploymentSettlementOfflineExportCompleteOutputReceipt(valueArg),
2196
+ 'offlineExportCompleteOutputReceipt',
2197
+ );
2198
+
2199
+ export const digestCloudlyLegacyDeploymentSettlementOfflineExportCompleteOutputReceipt = (
2200
+ valueArg: unknown,
2201
+ ): string => digestBytes(
2202
+ encodeCloudlyLegacyDeploymentSettlementOfflineExportCompleteOutputReceipt(valueArg),
2203
+ );
2204
+
2205
+ const assertCompleteOutputReceiptMatchesJournal = (
2206
+ receiptArg: Readonly<
2207
+ ICloudlyLegacyDeploymentSettlementOfflineExportCompleteOutputReceiptV1
2208
+ >,
2209
+ journalArg: Readonly<ICloudlyLegacyDeploymentSettlementOfflineExportAttemptJournalV1>,
2210
+ pathArg: string,
2211
+ ): void => {
2212
+ if (!canonicalEqual(receiptArg.authority, journalArg.productionTransformAuthority, pathArg)
2213
+ || !canonicalEqual(receiptArg.sourceAuthority, journalArg.sourceAuthority, pathArg)
2214
+ || receiptArg.operationId !== journalArg.operationId
2215
+ || receiptArg.settlementId !== journalArg.settlementId
2216
+ || receiptArg.attemptId !== journalArg.attemptId
2217
+ || receiptArg.journalSha256
2218
+ !== digestCloudlyLegacyDeploymentSettlementOfflineExportAttemptJournal(journalArg)
2219
+ || !canonicalEqual(receiptArg.transformedCoreFile, journalArg.transformedCoreFile, pathArg)
2220
+ || receiptArg.journalGrowthBytes
2221
+ < encodeCloudlyLegacyDeploymentSettlementOfflineExportAttemptJournal(journalArg).byteLength
2222
+ || receiptArg.completedAt < journalArg.completedAt) {
2223
+ fail('CROSS_FIELD_MISMATCH', pathArg);
2224
+ }
2225
+ };
2226
+
2227
+ export const encodeCloudlyLegacyDeploymentSettlementOfflineExportCompleteOutputReceiptHmacInput = (
2228
+ valueArg: unknown,
2229
+ ): Uint8Array => frame(
2230
+ cloudlyLegacyDeploymentSettlementOfflineExportDomains.completeOutputReceiptHmac,
2231
+ encodeNormalized(
2232
+ finalize(
2233
+ normalizeUnsignedCompleteOutputReceiptInternal(
2234
+ valueArg,
2235
+ 'offlineExportUnsignedCompleteOutputReceipt',
2236
+ ),
2237
+ cloudlyLegacyDeploymentSettlementOfflineExportLimits.maximumReceiptBytes,
2238
+ 'offlineExportUnsignedCompleteOutputReceipt',
2239
+ ),
2240
+ 'offlineExportUnsignedCompleteOutputReceipt',
2241
+ ),
2242
+ );
2243
+
2244
+ export const normalizeCloudlyLegacyDeploymentSettlementOfflineExportCompleteOutputReceiptForAuthorities = async (
2245
+ receiptArg: unknown,
2246
+ journalArg: unknown,
2247
+ authorizationArg: unknown,
2248
+ productionAuthorityArg: unknown,
2249
+ sourceAuthorityArg: unknown,
2250
+ rehearsalAttestationArg: unknown,
2251
+ verifierArg: TCloudlyLegacyDeploymentSettlementOfflineExportHmacVerifier,
2252
+ ): Promise<Readonly<
2253
+ ICloudlyLegacyDeploymentSettlementOfflineExportCompleteOutputReceiptV1
2254
+ >> => {
2255
+ const journal =
2256
+ await normalizeCloudlyLegacyDeploymentSettlementOfflineExportAttemptJournalForAuthorities(
2257
+ journalArg,
2258
+ authorizationArg,
2259
+ productionAuthorityArg,
2260
+ sourceAuthorityArg,
2261
+ rehearsalAttestationArg,
2262
+ verifierArg,
2263
+ );
2264
+ const productionAuthority =
2265
+ normalizeCloudlyLegacyDeploymentSettlementOfflineExportProductionTransformAuthority(
2266
+ productionAuthorityArg,
2267
+ );
2268
+ const receipt =
2269
+ normalizeCloudlyLegacyDeploymentSettlementOfflineExportCompleteOutputReceipt(receiptArg);
2270
+ assertCompleteOutputReceiptMatchesJournal(
2271
+ receipt,
2272
+ journal,
2273
+ 'offlineExportCompleteOutputReceipt.sourceProof',
2274
+ );
2275
+ assertTimestampWithinAuthority(
2276
+ receipt.completedAt,
2277
+ productionAuthority,
2278
+ 'offlineExportCompleteOutputReceipt.completedAt',
2279
+ );
2280
+ await requireVerifiedHmac(
2281
+ receipt.authority,
2282
+ cloudlyLegacyDeploymentSettlementOfflineExportDomains.completeOutputReceiptHmac,
2283
+ encodeCloudlyLegacyDeploymentSettlementOfflineExportCompleteOutputReceiptHmacInput(
2284
+ withoutMac(receipt),
2285
+ ),
2286
+ receipt.mac,
2287
+ verifierArg,
2288
+ 'offlineExportCompleteOutputReceipt.mac',
2289
+ );
2290
+ return receipt;
2291
+ };
2292
+
2293
+ export const normalizeCloudlyLegacyDeploymentSettlementOfflineExportTransformResult = (
2294
+ valueArg: unknown,
2295
+ ): Readonly<ICloudlyLegacyDeploymentSettlementOfflineExportTransformResultV1> => {
2296
+ const value = readRecord(valueArg, 'offlineExportTransformResult');
2297
+ assertExactKeys(value, [
2298
+ 'schemaVersion',
2299
+ 'kind',
2300
+ 'status',
2301
+ 'operationId',
2302
+ 'settlementId',
2303
+ 'attemptId',
2304
+ 'sourceAuthority',
2305
+ 'productionTransformAuthority',
2306
+ 'planSha256',
2307
+ 'requestSha256',
2308
+ 'completeOutputReceiptSha256',
2309
+ 'outcome',
2310
+ 'counts',
2311
+ 'classificationCounts',
2312
+ 'completedAt',
2313
+ ], 'offlineExportTransformResult');
2314
+ if (value.schemaVersion !== 1
2315
+ || value.kind
2316
+ !== 'cloudly-legacy-deployment-settlement-offline-export-transform-result'
2317
+ || value.status !== 'completed') {
2318
+ fail('INVALID_VALUE', 'offlineExportTransformResult.kind');
2319
+ }
2320
+ const sourceAuthority = normalizeAuthorityReferenceInternal(
2321
+ value.sourceAuthority,
2322
+ 'offlineExportTransformResult.sourceAuthority',
2323
+ 'source-rehearsal',
2324
+ );
2325
+ const productionTransformAuthority = normalizeAuthorityReferenceInternal(
2326
+ value.productionTransformAuthority,
2327
+ 'offlineExportTransformResult.productionTransformAuthority',
2328
+ 'production-transform',
2329
+ );
2330
+ const operationId = readIdentifier(value.operationId, 'offlineExportTransformResult.operationId');
2331
+ const settlementId = readIdentifier(
2332
+ value.settlementId,
2333
+ 'offlineExportTransformResult.settlementId',
2334
+ );
2335
+ const counts = normalizeMutationCounts(value.counts, 'offlineExportTransformResult.counts');
2336
+ const classificationCounts = normalizeClassificationCounts(
2337
+ value.classificationCounts,
2338
+ 'offlineExportTransformResult.classificationCounts',
2339
+ );
2340
+ const outcome = readLiteral(
2341
+ value.outcome,
2342
+ ['transformed', 'no-op'],
2343
+ 'offlineExportTransformResult.outcome',
2344
+ );
2345
+ assertCountsMatchClassifications(counts, classificationCounts, 'offlineExportTransformResult.counts');
2346
+ if (operationId !== sourceAuthority.operationId
2347
+ || operationId !== productionTransformAuthority.operationId
2348
+ || settlementId !== sourceAuthority.settlementId
2349
+ || settlementId !== productionTransformAuthority.settlementId
2350
+ || sourceAuthority.authorityId === productionTransformAuthority.authorityId
2351
+ || sourceAuthority.keyId === productionTransformAuthority.keyId
2352
+ || (outcome === 'no-op') !== hasNoMutations(counts)) {
2353
+ fail('CROSS_FIELD_MISMATCH', 'offlineExportTransformResult.authority');
2354
+ }
2355
+ return finalize({
2356
+ schemaVersion: 1,
2357
+ kind: 'cloudly-legacy-deployment-settlement-offline-export-transform-result',
2358
+ status: 'completed',
2359
+ operationId,
2360
+ settlementId,
2361
+ attemptId: readIdentifier(value.attemptId, 'offlineExportTransformResult.attemptId'),
2362
+ sourceAuthority,
2363
+ productionTransformAuthority,
2364
+ planSha256: readSha256(value.planSha256, 'offlineExportTransformResult.planSha256'),
2365
+ requestSha256: readSha256(
2366
+ value.requestSha256,
2367
+ 'offlineExportTransformResult.requestSha256',
2368
+ ),
2369
+ completeOutputReceiptSha256: readSha256(
2370
+ value.completeOutputReceiptSha256,
2371
+ 'offlineExportTransformResult.completeOutputReceiptSha256',
2372
+ ),
2373
+ outcome,
2374
+ counts,
2375
+ classificationCounts,
2376
+ completedAt: readInteger(value.completedAt, 'offlineExportTransformResult.completedAt', 1),
2377
+ } satisfies ICloudlyLegacyDeploymentSettlementOfflineExportTransformResultV1,
2378
+ cloudlyLegacyDeploymentSettlementOfflineExportLimits.maximumResultBytes,
2379
+ 'offlineExportTransformResult');
2380
+ };
2381
+
2382
+ export const encodeCloudlyLegacyDeploymentSettlementOfflineExportTransformResult = (
2383
+ valueArg: unknown,
2384
+ ): Uint8Array => encodeNormalized(
2385
+ normalizeCloudlyLegacyDeploymentSettlementOfflineExportTransformResult(valueArg),
2386
+ 'offlineExportTransformResult',
2387
+ );
2388
+
2389
+ export const digestCloudlyLegacyDeploymentSettlementOfflineExportTransformResult = (
2390
+ valueArg: unknown,
2391
+ ): string => digestBytes(
2392
+ encodeCloudlyLegacyDeploymentSettlementOfflineExportTransformResult(valueArg),
2393
+ );
2394
+
2395
+ export const normalizeCloudlyLegacyDeploymentSettlementOfflineExportTransformResultForCompleteOutputReceipt = (
2396
+ resultArg: unknown,
2397
+ receiptArg: unknown,
2398
+ journalArg: unknown,
2399
+ ): Readonly<ICloudlyLegacyDeploymentSettlementOfflineExportTransformResultV1> => {
2400
+ const result = normalizeCloudlyLegacyDeploymentSettlementOfflineExportTransformResult(resultArg);
2401
+ const receipt =
2402
+ normalizeCloudlyLegacyDeploymentSettlementOfflineExportCompleteOutputReceipt(receiptArg);
2403
+ const journal = normalizeCloudlyLegacyDeploymentSettlementOfflineExportAttemptJournal(journalArg);
2404
+ assertCompleteOutputReceiptMatchesJournal(
2405
+ receipt,
2406
+ journal,
2407
+ 'offlineExportTransformResult.completeOutputReceipt',
2408
+ );
2409
+ if (result.completeOutputReceiptSha256
2410
+ !== digestCloudlyLegacyDeploymentSettlementOfflineExportCompleteOutputReceipt(receipt)
2411
+ || !canonicalEqual(
2412
+ result.sourceAuthority,
2413
+ receipt.sourceAuthority,
2414
+ 'offlineExportTransformResult.sourceAuthority',
2415
+ )
2416
+ || !canonicalEqual(
2417
+ result.productionTransformAuthority,
2418
+ receipt.authority,
2419
+ 'offlineExportTransformResult.productionTransformAuthority',
2420
+ )
2421
+ || result.operationId !== receipt.operationId
2422
+ || result.settlementId !== receipt.settlementId
2423
+ || result.attemptId !== receipt.attemptId
2424
+ || result.planSha256 !== journal.planSha256
2425
+ || result.requestSha256 !== journal.requestSha256
2426
+ || result.outcome !== journal.outcome
2427
+ || !canonicalEqual(result.counts, journal.counts, 'offlineExportTransformResult.counts')
2428
+ || !canonicalEqual(
2429
+ result.classificationCounts,
2430
+ journal.classificationCounts,
2431
+ 'offlineExportTransformResult.classificationCounts',
2432
+ )
2433
+ || result.completedAt !== receipt.completedAt) {
2434
+ fail('CROSS_FIELD_MISMATCH', 'offlineExportTransformResult.completeOutputReceipt');
2435
+ }
2436
+ return result;
2437
+ };
2438
+
2439
+ export const normalizeCloudlyLegacyDeploymentSettlementOfflineExportTransformResultForAuthorities = async (
2440
+ resultArg: unknown,
2441
+ receiptArg: unknown,
2442
+ journalArg: unknown,
2443
+ authorizationArg: unknown,
2444
+ productionAuthorityArg: unknown,
2445
+ sourceAuthorityArg: unknown,
2446
+ rehearsalAttestationArg: unknown,
2447
+ verifierArg: TCloudlyLegacyDeploymentSettlementOfflineExportHmacVerifier,
2448
+ ): Promise<Readonly<
2449
+ ICloudlyLegacyDeploymentSettlementOfflineExportTransformResultV1
2450
+ >> => {
2451
+ const receipt =
2452
+ await normalizeCloudlyLegacyDeploymentSettlementOfflineExportCompleteOutputReceiptForAuthorities(
2453
+ receiptArg,
2454
+ journalArg,
2455
+ authorizationArg,
2456
+ productionAuthorityArg,
2457
+ sourceAuthorityArg,
2458
+ rehearsalAttestationArg,
2459
+ verifierArg,
2460
+ );
2461
+ return normalizeCloudlyLegacyDeploymentSettlementOfflineExportTransformResultForCompleteOutputReceipt(
2462
+ resultArg,
2463
+ receipt,
2464
+ journalArg,
2465
+ );
2466
+ };
2467
+
2468
+ export {
2469
+ cloudlyLegacyDeploymentSettlementOfflineExportGoldenVectors,
2470
+ } from './runtime.cloudlylegacydeploymentsettlement.offlineexport.golden.js';