@serve.zone/interfaces 20.0.0 → 20.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/changelog.md +14 -0
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/data/isolatedrestore.js +7 -82
- package/dist_ts/platform/index.d.ts +3 -1
- package/dist_ts/platform/index.js +4 -2
- package/dist_ts/platform/storagemigration.d.ts +346 -0
- package/dist_ts/platform/storagemigration.golden.d.ts +49 -0
- package/dist_ts/platform/storagemigration.golden.js +207 -0
- package/dist_ts/platform/storagemigration.js +1554 -0
- package/dist_ts/private/canonicaljson.d.ts +14 -0
- package/dist_ts/private/canonicaljson.js +154 -0
- package/package.json +1 -1
- package/readme.md +126 -0
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/data/isolatedrestore.ts +12 -93
- package/ts/platform/index.ts +3 -0
- package/ts/platform/storagemigration.golden.ts +241 -0
- package/ts/platform/storagemigration.ts +3082 -0
- package/ts/private/canonicaljson.ts +221 -0
|
@@ -0,0 +1,1554 @@
|
|
|
1
|
+
import { canonicalizeStrictJson, createCanonicalJsonSha256Hex, deepFreezeValue, strictCanonicalJsonRules, } from '../private/canonicaljson.js';
|
|
2
|
+
export const storageMigrationContractLimits = Object.freeze({
|
|
3
|
+
version: 1,
|
|
4
|
+
maximumControlJsonBytes: 256 * 1024,
|
|
5
|
+
maximumConfiguredStringBytes: 2048,
|
|
6
|
+
maximumIssueMessageBytes: 4096,
|
|
7
|
+
maximumAbortReasonBytes: 4096,
|
|
8
|
+
maximumEnvironmentKeyBytes: 256,
|
|
9
|
+
maximumSecretPathBytes: 2048,
|
|
10
|
+
});
|
|
11
|
+
export const storageMigrationCanonicalJsonRules = strictCanonicalJsonRules;
|
|
12
|
+
export class StorageMigrationContractError extends Error {
|
|
13
|
+
constructor(reasonArg) {
|
|
14
|
+
super(`storage migration contract error: ${reasonArg}`);
|
|
15
|
+
this.name = 'StorageMigrationContractError';
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
const fail = (reasonArg) => {
|
|
19
|
+
throw new StorageMigrationContractError(reasonArg);
|
|
20
|
+
};
|
|
21
|
+
const utf8ByteLength = (valueArg) => {
|
|
22
|
+
return new TextEncoder().encode(valueArg).byteLength;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Enforce this against Content-Length and the running request byte count
|
|
26
|
+
* before buffering or decoding a storage-migration control body.
|
|
27
|
+
*/
|
|
28
|
+
export const assertStorageMigrationControlIngressByteLength = (valueArg) => {
|
|
29
|
+
return readSafeInteger(valueArg, 'storage migration raw control ingress byte length', 0, storageMigrationContractLimits.maximumControlJsonBytes);
|
|
30
|
+
};
|
|
31
|
+
const readRecord = (valueArg, fieldNameArg) => {
|
|
32
|
+
if (!valueArg || typeof valueArg !== 'object' || Array.isArray(valueArg)) {
|
|
33
|
+
return fail(`${fieldNameArg} must be a plain object`);
|
|
34
|
+
}
|
|
35
|
+
const prototype = Object.getPrototypeOf(valueArg);
|
|
36
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
37
|
+
return fail(`${fieldNameArg} must be a plain object`);
|
|
38
|
+
}
|
|
39
|
+
const record = valueArg;
|
|
40
|
+
const ownKeys = Reflect.ownKeys(record);
|
|
41
|
+
if (ownKeys.some((keyArg) => typeof keyArg !== 'string')) {
|
|
42
|
+
return fail(`${fieldNameArg} must not contain symbol keys`);
|
|
43
|
+
}
|
|
44
|
+
for (const key of ownKeys) {
|
|
45
|
+
const descriptor = Object.getOwnPropertyDescriptor(record, key);
|
|
46
|
+
if (!descriptor ||
|
|
47
|
+
!descriptor.enumerable ||
|
|
48
|
+
!Object.hasOwn(descriptor, 'value') ||
|
|
49
|
+
descriptor.value === undefined) {
|
|
50
|
+
return fail(`${fieldNameArg} must contain enumerable JSON data properties only`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return record;
|
|
54
|
+
};
|
|
55
|
+
const readDenseArray = (valueArg, fieldNameArg, minimumLengthArg, maximumLengthArg) => {
|
|
56
|
+
if (!Array.isArray(valueArg) ||
|
|
57
|
+
Object.getPrototypeOf(valueArg) !== Array.prototype) {
|
|
58
|
+
return fail(`${fieldNameArg} must be a dense plain array`);
|
|
59
|
+
}
|
|
60
|
+
if (valueArg.length < minimumLengthArg ||
|
|
61
|
+
valueArg.length > maximumLengthArg) {
|
|
62
|
+
return fail(`${fieldNameArg} must contain between ${minimumLengthArg} and ${maximumLengthArg} entries`);
|
|
63
|
+
}
|
|
64
|
+
for (let index = 0; index < valueArg.length; index++) {
|
|
65
|
+
if (!Object.hasOwn(valueArg, index)) {
|
|
66
|
+
return fail(`${fieldNameArg} must not contain sparse entries`);
|
|
67
|
+
}
|
|
68
|
+
const descriptor = Object.getOwnPropertyDescriptor(valueArg, String(index));
|
|
69
|
+
if (!descriptor ||
|
|
70
|
+
!descriptor.enumerable ||
|
|
71
|
+
!Object.hasOwn(descriptor, 'value') ||
|
|
72
|
+
descriptor.value === undefined) {
|
|
73
|
+
return fail(`${fieldNameArg} must contain enumerable JSON data entries only`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
for (const key of Reflect.ownKeys(valueArg)) {
|
|
77
|
+
if (key === 'length')
|
|
78
|
+
continue;
|
|
79
|
+
if (typeof key !== 'string' ||
|
|
80
|
+
!/^(?:0|[1-9][0-9]*)$/.test(key) ||
|
|
81
|
+
Number(key) >= valueArg.length) {
|
|
82
|
+
return fail(`${fieldNameArg} must not contain extra properties`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return valueArg;
|
|
86
|
+
};
|
|
87
|
+
const assertKeys = (recordArg, requiredKeysArg, optionalKeysArg, fieldNameArg) => {
|
|
88
|
+
const actualKeys = Object.keys(recordArg).sort();
|
|
89
|
+
const allowedKeys = new Set([...requiredKeysArg, ...optionalKeysArg]);
|
|
90
|
+
if (requiredKeysArg.some((keyArg) => !Object.hasOwn(recordArg, keyArg)) ||
|
|
91
|
+
actualKeys.some((keyArg) => !allowedKeys.has(keyArg))) {
|
|
92
|
+
fail(`${fieldNameArg} does not match its exact versioned schema`);
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
const assertExactKeys = (recordArg, expectedKeysArg, fieldNameArg) => {
|
|
96
|
+
assertKeys(recordArg, expectedKeysArg, [], fieldNameArg);
|
|
97
|
+
};
|
|
98
|
+
const readString = (valueArg, fieldNameArg, maximumBytesArg = storageMigrationContractLimits.maximumConfiguredStringBytes) => {
|
|
99
|
+
if (typeof valueArg !== 'string' ||
|
|
100
|
+
valueArg.length === 0 ||
|
|
101
|
+
utf8ByteLength(valueArg) > maximumBytesArg ||
|
|
102
|
+
/[\u0000-\u001f\u007f]/u.test(valueArg)) {
|
|
103
|
+
return fail(`${fieldNameArg} must be a bounded non-empty JSON string`);
|
|
104
|
+
}
|
|
105
|
+
for (let index = 0; index < valueArg.length; index++) {
|
|
106
|
+
const codeUnit = valueArg.charCodeAt(index);
|
|
107
|
+
if (codeUnit >= 0xd800 && codeUnit <= 0xdbff) {
|
|
108
|
+
const following = valueArg.charCodeAt(index + 1);
|
|
109
|
+
if (following < 0xdc00 || following > 0xdfff) {
|
|
110
|
+
return fail(`${fieldNameArg} contains an unpaired UTF-16 surrogate`);
|
|
111
|
+
}
|
|
112
|
+
index++;
|
|
113
|
+
}
|
|
114
|
+
else if (codeUnit >= 0xdc00 && codeUnit <= 0xdfff) {
|
|
115
|
+
return fail(`${fieldNameArg} contains an unpaired UTF-16 surrogate`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return valueArg;
|
|
119
|
+
};
|
|
120
|
+
const canonicalIdPattern = /^[A-Za-z0-9][A-Za-z0-9._:@-]{0,191}$/;
|
|
121
|
+
const environmentKeyPattern = /^[A-Z_][A-Z0-9_]{0,255}$/;
|
|
122
|
+
const sha256Pattern = /^[a-f0-9]{64}$/;
|
|
123
|
+
const capacityPattern = /^[1-9][0-9]*(?:KiB|MiB|GiB|TiB)$/;
|
|
124
|
+
const readIdentifier = (valueArg, fieldNameArg) => {
|
|
125
|
+
if (typeof valueArg !== 'string' || !canonicalIdPattern.test(valueArg)) {
|
|
126
|
+
return fail(`${fieldNameArg} must be a canonical identifier`);
|
|
127
|
+
}
|
|
128
|
+
return valueArg;
|
|
129
|
+
};
|
|
130
|
+
const readSha256 = (valueArg, fieldNameArg) => {
|
|
131
|
+
if (typeof valueArg !== 'string' || !sha256Pattern.test(valueArg)) {
|
|
132
|
+
return fail(`${fieldNameArg} must be a bare lowercase 64-hex SHA-256 digest`);
|
|
133
|
+
}
|
|
134
|
+
return valueArg;
|
|
135
|
+
};
|
|
136
|
+
const readSafeInteger = (valueArg, fieldNameArg, minimumArg, maximumArg = Number.MAX_SAFE_INTEGER) => {
|
|
137
|
+
if (typeof valueArg !== 'number' ||
|
|
138
|
+
!Number.isSafeInteger(valueArg) ||
|
|
139
|
+
Object.is(valueArg, -0) ||
|
|
140
|
+
valueArg < minimumArg ||
|
|
141
|
+
valueArg > maximumArg) {
|
|
142
|
+
return fail(`${fieldNameArg} must be a safe integer between ${minimumArg} and ${maximumArg}`);
|
|
143
|
+
}
|
|
144
|
+
return valueArg;
|
|
145
|
+
};
|
|
146
|
+
const readBoolean = (valueArg, fieldNameArg) => {
|
|
147
|
+
if (typeof valueArg !== 'boolean') {
|
|
148
|
+
return fail(`${fieldNameArg} must be a boolean`);
|
|
149
|
+
}
|
|
150
|
+
return valueArg;
|
|
151
|
+
};
|
|
152
|
+
const readLiteral = (valueArg, allowedArg, fieldNameArg) => {
|
|
153
|
+
if (typeof valueArg !== 'string' ||
|
|
154
|
+
!allowedArg.includes(valueArg)) {
|
|
155
|
+
return fail(`${fieldNameArg} is outside the supported versioned values`);
|
|
156
|
+
}
|
|
157
|
+
return valueArg;
|
|
158
|
+
};
|
|
159
|
+
const canonicalize = (valueArg) => {
|
|
160
|
+
return canonicalizeStrictJson(valueArg, fail);
|
|
161
|
+
};
|
|
162
|
+
const createCanonicalSha256 = async (valueArg) => {
|
|
163
|
+
return createCanonicalJsonSha256Hex(canonicalize(valueArg), fail);
|
|
164
|
+
};
|
|
165
|
+
const assertControlJsonLimit = (valueArg, fieldNameArg) => {
|
|
166
|
+
const json = JSON.stringify(valueArg);
|
|
167
|
+
if (typeof json !== 'string' ||
|
|
168
|
+
utf8ByteLength(json) > storageMigrationContractLimits.maximumControlJsonBytes) {
|
|
169
|
+
return fail(`${fieldNameArg} exceeds the control JSON byte limit`);
|
|
170
|
+
}
|
|
171
|
+
return deepFreezeValue(valueArg);
|
|
172
|
+
};
|
|
173
|
+
const normalizePolicy = (valueArg, fieldNameArg) => {
|
|
174
|
+
const value = readRecord(valueArg, fieldNameArg);
|
|
175
|
+
assertExactKeys(value, ['classId', 'revision'], fieldNameArg);
|
|
176
|
+
return {
|
|
177
|
+
classId: readIdentifier(value.classId, `${fieldNameArg}.classId`),
|
|
178
|
+
revision: readIdentifier(value.revision, `${fieldNameArg}.revision`),
|
|
179
|
+
};
|
|
180
|
+
};
|
|
181
|
+
const normalizeRequirement = (valueArg, fieldNameArg) => {
|
|
182
|
+
const value = readRecord(valueArg, fieldNameArg);
|
|
183
|
+
assertKeys(value, [], [
|
|
184
|
+
'performanceTier',
|
|
185
|
+
'durability',
|
|
186
|
+
'topology',
|
|
187
|
+
'hardQuota',
|
|
188
|
+
'snapshots',
|
|
189
|
+
'backup',
|
|
190
|
+
'encryptedInTransit',
|
|
191
|
+
], fieldNameArg);
|
|
192
|
+
if (Object.keys(value).length === 0) {
|
|
193
|
+
return fail(`${fieldNameArg} must not be empty`);
|
|
194
|
+
}
|
|
195
|
+
return {
|
|
196
|
+
...(Object.hasOwn(value, 'performanceTier')
|
|
197
|
+
? {
|
|
198
|
+
performanceTier: readLiteral(value.performanceTier, ['standard', 'highIops', 'capacity'], `${fieldNameArg}.performanceTier`),
|
|
199
|
+
}
|
|
200
|
+
: {}),
|
|
201
|
+
...(Object.hasOwn(value, 'durability')
|
|
202
|
+
? {
|
|
203
|
+
durability: readLiteral(value.durability, ['ephemeral', 'persistent'], `${fieldNameArg}.durability`),
|
|
204
|
+
}
|
|
205
|
+
: {}),
|
|
206
|
+
...(Object.hasOwn(value, 'topology')
|
|
207
|
+
? {
|
|
208
|
+
topology: readLiteral(value.topology, ['singleNode', 'multiNode'], `${fieldNameArg}.topology`),
|
|
209
|
+
}
|
|
210
|
+
: {}),
|
|
211
|
+
...(Object.hasOwn(value, 'hardQuota')
|
|
212
|
+
? {
|
|
213
|
+
hardQuota: value.hardQuota === true
|
|
214
|
+
? true
|
|
215
|
+
: fail(`${fieldNameArg}.hardQuota must be true when present`),
|
|
216
|
+
}
|
|
217
|
+
: {}),
|
|
218
|
+
...(Object.hasOwn(value, 'snapshots')
|
|
219
|
+
? {
|
|
220
|
+
snapshots: readLiteral(value.snapshots, ['portable', 'native'], `${fieldNameArg}.snapshots`),
|
|
221
|
+
}
|
|
222
|
+
: {}),
|
|
223
|
+
...(Object.hasOwn(value, 'backup')
|
|
224
|
+
? {
|
|
225
|
+
backup: value.backup === true
|
|
226
|
+
? true
|
|
227
|
+
: fail(`${fieldNameArg}.backup must be true when present`),
|
|
228
|
+
}
|
|
229
|
+
: {}),
|
|
230
|
+
...(Object.hasOwn(value, 'encryptedInTransit')
|
|
231
|
+
? {
|
|
232
|
+
encryptedInTransit: value.encryptedInTransit === true
|
|
233
|
+
? true
|
|
234
|
+
: fail(`${fieldNameArg}.encryptedInTransit must be true when present`),
|
|
235
|
+
}
|
|
236
|
+
: {}),
|
|
237
|
+
};
|
|
238
|
+
};
|
|
239
|
+
const normalizeStorageClass = (valueArg, fieldNameArg) => {
|
|
240
|
+
const value = readRecord(valueArg, fieldNameArg);
|
|
241
|
+
assertKeys(value, ['kind', 'purpose'], ['required', 'preferred'], fieldNameArg);
|
|
242
|
+
if (value.kind !== 'objectStorage') {
|
|
243
|
+
return fail(`${fieldNameArg}.kind must be objectStorage`);
|
|
244
|
+
}
|
|
245
|
+
return {
|
|
246
|
+
kind: 'objectStorage',
|
|
247
|
+
purpose: readLiteral(value.purpose, ['runtime', 'database', 'registry', 'backup'], `${fieldNameArg}.purpose`),
|
|
248
|
+
...(Object.hasOwn(value, 'required')
|
|
249
|
+
? {
|
|
250
|
+
required: normalizeRequirement(value.required, `${fieldNameArg}.required`),
|
|
251
|
+
}
|
|
252
|
+
: {}),
|
|
253
|
+
...(Object.hasOwn(value, 'preferred')
|
|
254
|
+
? {
|
|
255
|
+
preferred: normalizeRequirement(value.preferred, `${fieldNameArg}.preferred`),
|
|
256
|
+
}
|
|
257
|
+
: {}),
|
|
258
|
+
};
|
|
259
|
+
};
|
|
260
|
+
const readCapacityQuantity = (valueArg, fieldNameArg) => {
|
|
261
|
+
if (typeof valueArg !== 'string' || !capacityPattern.test(valueArg)) {
|
|
262
|
+
return fail(`${fieldNameArg} must be a canonical base-2 capacity quantity`);
|
|
263
|
+
}
|
|
264
|
+
const numericPart = valueArg.replace(/(?:KiB|MiB|GiB|TiB)$/, '');
|
|
265
|
+
if (!Number.isSafeInteger(Number(numericPart))) {
|
|
266
|
+
return fail(`${fieldNameArg} exceeds the safe integer quantity range`);
|
|
267
|
+
}
|
|
268
|
+
return valueArg;
|
|
269
|
+
};
|
|
270
|
+
const capacityQuantityBytes = (valueArg) => {
|
|
271
|
+
const units = {
|
|
272
|
+
KiB: 1024n,
|
|
273
|
+
MiB: 1024n ** 2n,
|
|
274
|
+
GiB: 1024n ** 3n,
|
|
275
|
+
TiB: 1024n ** 4n,
|
|
276
|
+
};
|
|
277
|
+
const unit = valueArg.slice(-3);
|
|
278
|
+
return BigInt(valueArg.slice(0, -3)) * units[unit];
|
|
279
|
+
};
|
|
280
|
+
const normalizeCapacityRequest = (valueArg, fieldNameArg) => {
|
|
281
|
+
const value = readRecord(valueArg, fieldNameArg);
|
|
282
|
+
assertKeys(value, ['request'], ['limit'], fieldNameArg);
|
|
283
|
+
const request = readCapacityQuantity(value.request, `${fieldNameArg}.request`);
|
|
284
|
+
const limit = Object.hasOwn(value, 'limit')
|
|
285
|
+
? readCapacityQuantity(value.limit, `${fieldNameArg}.limit`)
|
|
286
|
+
: undefined;
|
|
287
|
+
if (limit && capacityQuantityBytes(limit) < capacityQuantityBytes(request)) {
|
|
288
|
+
return fail(`${fieldNameArg}.limit must be at least request`);
|
|
289
|
+
}
|
|
290
|
+
return {
|
|
291
|
+
request,
|
|
292
|
+
...(limit ? { limit } : {}),
|
|
293
|
+
};
|
|
294
|
+
};
|
|
295
|
+
const normalizeResolvedCapacity = (valueArg, fieldNameArg) => {
|
|
296
|
+
const value = readRecord(valueArg, fieldNameArg);
|
|
297
|
+
assertKeys(value, [], ['requested', 'granted', 'limit'], fieldNameArg);
|
|
298
|
+
if (Object.keys(value).length === 0) {
|
|
299
|
+
return fail(`${fieldNameArg} must not be empty`);
|
|
300
|
+
}
|
|
301
|
+
const requested = Object.hasOwn(value, 'requested')
|
|
302
|
+
? readCapacityQuantity(value.requested, `${fieldNameArg}.requested`)
|
|
303
|
+
: undefined;
|
|
304
|
+
const granted = Object.hasOwn(value, 'granted')
|
|
305
|
+
? readCapacityQuantity(value.granted, `${fieldNameArg}.granted`)
|
|
306
|
+
: undefined;
|
|
307
|
+
const limit = Object.hasOwn(value, 'limit')
|
|
308
|
+
? readCapacityQuantity(value.limit, `${fieldNameArg}.limit`)
|
|
309
|
+
: undefined;
|
|
310
|
+
if (requested &&
|
|
311
|
+
granted &&
|
|
312
|
+
capacityQuantityBytes(granted) < capacityQuantityBytes(requested)) {
|
|
313
|
+
return fail(`${fieldNameArg}.granted must be at least requested`);
|
|
314
|
+
}
|
|
315
|
+
if (requested &&
|
|
316
|
+
limit &&
|
|
317
|
+
capacityQuantityBytes(limit) < capacityQuantityBytes(requested)) {
|
|
318
|
+
return fail(`${fieldNameArg}.limit must be at least requested`);
|
|
319
|
+
}
|
|
320
|
+
if (granted &&
|
|
321
|
+
limit &&
|
|
322
|
+
capacityQuantityBytes(limit) < capacityQuantityBytes(granted)) {
|
|
323
|
+
return fail(`${fieldNameArg}.limit must be at least granted`);
|
|
324
|
+
}
|
|
325
|
+
return {
|
|
326
|
+
...(requested ? { requested } : {}),
|
|
327
|
+
...(granted ? { granted } : {}),
|
|
328
|
+
...(limit ? { limit } : {}),
|
|
329
|
+
};
|
|
330
|
+
};
|
|
331
|
+
const readEnvironmentKey = (valueArg, fieldNameArg) => {
|
|
332
|
+
if (typeof valueArg !== 'string' ||
|
|
333
|
+
utf8ByteLength(valueArg) >
|
|
334
|
+
storageMigrationContractLimits.maximumEnvironmentKeyBytes ||
|
|
335
|
+
!environmentKeyPattern.test(valueArg)) {
|
|
336
|
+
return fail(`${fieldNameArg} must be a canonical environment key`);
|
|
337
|
+
}
|
|
338
|
+
return valueArg;
|
|
339
|
+
};
|
|
340
|
+
const normalizeDelivery = (valueArg, fieldNameArg) => {
|
|
341
|
+
const value = readRecord(valueArg, fieldNameArg);
|
|
342
|
+
if (value.type === 'environment') {
|
|
343
|
+
assertExactKeys(value, ['type', 'keys'], fieldNameArg);
|
|
344
|
+
const keys = readRecord(value.keys, `${fieldNameArg}.keys`);
|
|
345
|
+
assertKeys(keys, ['endpoint', 'bucket', 'region', 'accessKeyId', 'secretAccessKey'], ['sessionToken'], `${fieldNameArg}.keys`);
|
|
346
|
+
const normalizedKeys = {
|
|
347
|
+
endpoint: readEnvironmentKey(keys.endpoint, `${fieldNameArg}.keys.endpoint`),
|
|
348
|
+
bucket: readEnvironmentKey(keys.bucket, `${fieldNameArg}.keys.bucket`),
|
|
349
|
+
region: readEnvironmentKey(keys.region, `${fieldNameArg}.keys.region`),
|
|
350
|
+
accessKeyId: readEnvironmentKey(keys.accessKeyId, `${fieldNameArg}.keys.accessKeyId`),
|
|
351
|
+
secretAccessKey: readEnvironmentKey(keys.secretAccessKey, `${fieldNameArg}.keys.secretAccessKey`),
|
|
352
|
+
...(Object.hasOwn(keys, 'sessionToken')
|
|
353
|
+
? {
|
|
354
|
+
sessionToken: readEnvironmentKey(keys.sessionToken, `${fieldNameArg}.keys.sessionToken`),
|
|
355
|
+
}
|
|
356
|
+
: {}),
|
|
357
|
+
};
|
|
358
|
+
if (new Set(Object.values(normalizedKeys)).size !==
|
|
359
|
+
Object.keys(normalizedKeys).length) {
|
|
360
|
+
return fail(`${fieldNameArg}.keys values must be distinct`);
|
|
361
|
+
}
|
|
362
|
+
return { type: 'environment', keys: normalizedKeys };
|
|
363
|
+
}
|
|
364
|
+
if (value.type === 'secretFile') {
|
|
365
|
+
assertExactKeys(value, ['type', 'targetPath', 'format'], fieldNameArg);
|
|
366
|
+
const targetPath = readString(value.targetPath, `${fieldNameArg}.targetPath`, storageMigrationContractLimits.maximumSecretPathBytes);
|
|
367
|
+
if (!targetPath.startsWith('/run/secrets/') ||
|
|
368
|
+
targetPath.includes('\\') ||
|
|
369
|
+
targetPath.split('/').some((segmentArg) => segmentArg === '.' || segmentArg === '..')) {
|
|
370
|
+
return fail(`${fieldNameArg}.targetPath must be a canonical path below /run/secrets`);
|
|
371
|
+
}
|
|
372
|
+
if (value.format !== 'servezone-object-storage-v1') {
|
|
373
|
+
return fail(`${fieldNameArg}.format is unsupported`);
|
|
374
|
+
}
|
|
375
|
+
return {
|
|
376
|
+
type: 'secretFile',
|
|
377
|
+
targetPath,
|
|
378
|
+
format: 'servezone-object-storage-v1',
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
return fail(`${fieldNameArg}.type is unsupported`);
|
|
382
|
+
};
|
|
383
|
+
const normalizeCredentials = (valueArg, fieldNameArg) => {
|
|
384
|
+
const value = readRecord(valueArg, fieldNameArg);
|
|
385
|
+
assertKeys(value, ['secretBundleId', 'accessKeyIdKey', 'secretAccessKeyKey'], ['sessionTokenKey'], fieldNameArg);
|
|
386
|
+
const result = {
|
|
387
|
+
secretBundleId: readIdentifier(value.secretBundleId, `${fieldNameArg}.secretBundleId`),
|
|
388
|
+
accessKeyIdKey: readIdentifier(value.accessKeyIdKey, `${fieldNameArg}.accessKeyIdKey`),
|
|
389
|
+
secretAccessKeyKey: readIdentifier(value.secretAccessKeyKey, `${fieldNameArg}.secretAccessKeyKey`),
|
|
390
|
+
...(Object.hasOwn(value, 'sessionTokenKey')
|
|
391
|
+
? {
|
|
392
|
+
sessionTokenKey: readIdentifier(value.sessionTokenKey, `${fieldNameArg}.sessionTokenKey`),
|
|
393
|
+
}
|
|
394
|
+
: {}),
|
|
395
|
+
};
|
|
396
|
+
const keyNames = [
|
|
397
|
+
result.accessKeyIdKey,
|
|
398
|
+
result.secretAccessKeyKey,
|
|
399
|
+
...(result.sessionTokenKey ? [result.sessionTokenKey] : []),
|
|
400
|
+
];
|
|
401
|
+
if (new Set(keyNames).size !== keyNames.length) {
|
|
402
|
+
return fail(`${fieldNameArg} credential key references must be distinct`);
|
|
403
|
+
}
|
|
404
|
+
return result;
|
|
405
|
+
};
|
|
406
|
+
const normalizeObjectStorageProtection = (valueArg, fieldNameArg) => {
|
|
407
|
+
const value = readRecord(valueArg, fieldNameArg);
|
|
408
|
+
assertKeys(value, [], ['backup', 'versioning', 'retentionDays'], fieldNameArg);
|
|
409
|
+
if (Object.keys(value).length === 0) {
|
|
410
|
+
return fail(`${fieldNameArg} must not be empty`);
|
|
411
|
+
}
|
|
412
|
+
return {
|
|
413
|
+
...(Object.hasOwn(value, 'backup')
|
|
414
|
+
? {
|
|
415
|
+
backup: value.backup === 'required'
|
|
416
|
+
? 'required'
|
|
417
|
+
: fail(`${fieldNameArg}.backup must be required`),
|
|
418
|
+
}
|
|
419
|
+
: {}),
|
|
420
|
+
...(Object.hasOwn(value, 'versioning')
|
|
421
|
+
? {
|
|
422
|
+
versioning: value.versioning === 'required'
|
|
423
|
+
? 'required'
|
|
424
|
+
: fail(`${fieldNameArg}.versioning must be required`),
|
|
425
|
+
}
|
|
426
|
+
: {}),
|
|
427
|
+
...(Object.hasOwn(value, 'retentionDays')
|
|
428
|
+
? {
|
|
429
|
+
retentionDays: readSafeInteger(value.retentionDays, `${fieldNameArg}.retentionDays`, 1, 365_000),
|
|
430
|
+
}
|
|
431
|
+
: {}),
|
|
432
|
+
};
|
|
433
|
+
};
|
|
434
|
+
const normalizeObjectStorageRequest = (valueArg, fieldNameArg) => {
|
|
435
|
+
const value = readRecord(valueArg, fieldNameArg);
|
|
436
|
+
assertKeys(value, [
|
|
437
|
+
'id',
|
|
438
|
+
'kind',
|
|
439
|
+
'storageClass',
|
|
440
|
+
'accessMode',
|
|
441
|
+
'reclaimPolicy',
|
|
442
|
+
'delivery',
|
|
443
|
+
], ['capacity', 'protection'], fieldNameArg);
|
|
444
|
+
if (value.kind !== 'objectStorage') {
|
|
445
|
+
return fail(`${fieldNameArg}.kind must be objectStorage`);
|
|
446
|
+
}
|
|
447
|
+
return {
|
|
448
|
+
id: readIdentifier(value.id, `${fieldNameArg}.id`),
|
|
449
|
+
kind: 'objectStorage',
|
|
450
|
+
storageClass: readIdentifier(value.storageClass, `${fieldNameArg}.storageClass`),
|
|
451
|
+
accessMode: readLiteral(value.accessMode, ['readOnly', 'readWrite'], `${fieldNameArg}.accessMode`),
|
|
452
|
+
reclaimPolicy: readLiteral(value.reclaimPolicy, ['retain', 'delete'], `${fieldNameArg}.reclaimPolicy`),
|
|
453
|
+
delivery: normalizeDelivery(value.delivery, `${fieldNameArg}.delivery`),
|
|
454
|
+
...(Object.hasOwn(value, 'capacity')
|
|
455
|
+
? {
|
|
456
|
+
capacity: normalizeCapacityRequest(value.capacity, `${fieldNameArg}.capacity`),
|
|
457
|
+
}
|
|
458
|
+
: {}),
|
|
459
|
+
...(Object.hasOwn(value, 'protection')
|
|
460
|
+
? {
|
|
461
|
+
protection: normalizeObjectStorageProtection(value.protection, `${fieldNameArg}.protection`),
|
|
462
|
+
}
|
|
463
|
+
: {}),
|
|
464
|
+
};
|
|
465
|
+
};
|
|
466
|
+
const normalizeCapabilities = (valueArg, fieldNameArg) => {
|
|
467
|
+
const value = readRecord(valueArg, fieldNameArg);
|
|
468
|
+
assertExactKeys(value, [
|
|
469
|
+
'performanceTier',
|
|
470
|
+
'durability',
|
|
471
|
+
'topology',
|
|
472
|
+
'hardQuota',
|
|
473
|
+
'snapshots',
|
|
474
|
+
'backup',
|
|
475
|
+
'encryptedInTransit',
|
|
476
|
+
], fieldNameArg);
|
|
477
|
+
return {
|
|
478
|
+
performanceTier: readLiteral(value.performanceTier, ['standard', 'highIops', 'capacity'], `${fieldNameArg}.performanceTier`),
|
|
479
|
+
durability: readLiteral(value.durability, ['ephemeral', 'persistent'], `${fieldNameArg}.durability`),
|
|
480
|
+
topology: readLiteral(value.topology, ['singleNode', 'multiNode'], `${fieldNameArg}.topology`),
|
|
481
|
+
hardQuota: readBoolean(value.hardQuota, `${fieldNameArg}.hardQuota`),
|
|
482
|
+
snapshots: readLiteral(value.snapshots, ['none', 'portable', 'native'], `${fieldNameArg}.snapshots`),
|
|
483
|
+
backup: readBoolean(value.backup, `${fieldNameArg}.backup`),
|
|
484
|
+
encryptedInTransit: readBoolean(value.encryptedInTransit, `${fieldNameArg}.encryptedInTransit`),
|
|
485
|
+
};
|
|
486
|
+
};
|
|
487
|
+
const normalizeConnection = (valueArg, fieldNameArg) => {
|
|
488
|
+
const value = readRecord(valueArg, fieldNameArg);
|
|
489
|
+
assertExactKeys(value, ['endpoint', 'bucket', 'region'], fieldNameArg);
|
|
490
|
+
return {
|
|
491
|
+
endpoint: readString(value.endpoint, `${fieldNameArg}.endpoint`),
|
|
492
|
+
bucket: readIdentifier(value.bucket, `${fieldNameArg}.bucket`),
|
|
493
|
+
region: readIdentifier(value.region, `${fieldNameArg}.region`),
|
|
494
|
+
};
|
|
495
|
+
};
|
|
496
|
+
const normalizeObjectStorageBinding = (valueArg, expectedStatusArg, fieldNameArg) => {
|
|
497
|
+
const value = readRecord(valueArg, fieldNameArg);
|
|
498
|
+
assertKeys(value, [
|
|
499
|
+
'schemaVersion',
|
|
500
|
+
'id',
|
|
501
|
+
'serviceId',
|
|
502
|
+
'requestId',
|
|
503
|
+
'requestDigest',
|
|
504
|
+
'kind',
|
|
505
|
+
'generation',
|
|
506
|
+
'observedGeneration',
|
|
507
|
+
'status',
|
|
508
|
+
'policy',
|
|
509
|
+
'capabilities',
|
|
510
|
+
'resourceRef',
|
|
511
|
+
'accessMode',
|
|
512
|
+
'connection',
|
|
513
|
+
'credentials',
|
|
514
|
+
'delivery',
|
|
515
|
+
'versioning',
|
|
516
|
+
], ['capacity', 'createdAt', 'updatedAt', 'retentionDays'], fieldNameArg);
|
|
517
|
+
if (value.schemaVersion !== 1) {
|
|
518
|
+
return fail(`${fieldNameArg}.schemaVersion must be 1`);
|
|
519
|
+
}
|
|
520
|
+
if (value.kind !== 'objectStorage') {
|
|
521
|
+
return fail(`${fieldNameArg}.kind must be objectStorage`);
|
|
522
|
+
}
|
|
523
|
+
if (value.status !== expectedStatusArg) {
|
|
524
|
+
return fail(`${fieldNameArg}.status must be ${expectedStatusArg}`);
|
|
525
|
+
}
|
|
526
|
+
const generation = readSafeInteger(value.generation, `${fieldNameArg}.generation`, 1);
|
|
527
|
+
const observedGeneration = readSafeInteger(value.observedGeneration, `${fieldNameArg}.observedGeneration`, 0, generation);
|
|
528
|
+
if (expectedStatusArg === 'ready' && observedGeneration !== generation) {
|
|
529
|
+
return fail(`${fieldNameArg}.observedGeneration must equal generation when ready`);
|
|
530
|
+
}
|
|
531
|
+
const createdAt = Object.hasOwn(value, 'createdAt')
|
|
532
|
+
? readSafeInteger(value.createdAt, `${fieldNameArg}.createdAt`, 1)
|
|
533
|
+
: undefined;
|
|
534
|
+
const updatedAt = Object.hasOwn(value, 'updatedAt')
|
|
535
|
+
? readSafeInteger(value.updatedAt, `${fieldNameArg}.updatedAt`, 1)
|
|
536
|
+
: undefined;
|
|
537
|
+
if (createdAt && updatedAt && updatedAt < createdAt) {
|
|
538
|
+
return fail(`${fieldNameArg}.updatedAt must not precede createdAt`);
|
|
539
|
+
}
|
|
540
|
+
return {
|
|
541
|
+
schemaVersion: 1,
|
|
542
|
+
id: readIdentifier(value.id, `${fieldNameArg}.id`),
|
|
543
|
+
serviceId: readIdentifier(value.serviceId, `${fieldNameArg}.serviceId`),
|
|
544
|
+
requestId: readIdentifier(value.requestId, `${fieldNameArg}.requestId`),
|
|
545
|
+
requestDigest: readSha256(value.requestDigest, `${fieldNameArg}.requestDigest`),
|
|
546
|
+
kind: 'objectStorage',
|
|
547
|
+
generation,
|
|
548
|
+
observedGeneration,
|
|
549
|
+
status: expectedStatusArg,
|
|
550
|
+
policy: normalizePolicy(value.policy, `${fieldNameArg}.policy`),
|
|
551
|
+
capabilities: normalizeCapabilities(value.capabilities, `${fieldNameArg}.capabilities`),
|
|
552
|
+
resourceRef: readIdentifier(value.resourceRef, `${fieldNameArg}.resourceRef`),
|
|
553
|
+
...(Object.hasOwn(value, 'capacity')
|
|
554
|
+
? {
|
|
555
|
+
capacity: normalizeResolvedCapacity(value.capacity, `${fieldNameArg}.capacity`),
|
|
556
|
+
}
|
|
557
|
+
: {}),
|
|
558
|
+
accessMode: readLiteral(value.accessMode, ['readOnly', 'readWrite'], `${fieldNameArg}.accessMode`),
|
|
559
|
+
connection: normalizeConnection(value.connection, `${fieldNameArg}.connection`),
|
|
560
|
+
credentials: normalizeCredentials(value.credentials, `${fieldNameArg}.credentials`),
|
|
561
|
+
delivery: normalizeDelivery(value.delivery, `${fieldNameArg}.delivery`),
|
|
562
|
+
versioning: readBoolean(value.versioning, `${fieldNameArg}.versioning`),
|
|
563
|
+
...(Object.hasOwn(value, 'retentionDays')
|
|
564
|
+
? {
|
|
565
|
+
retentionDays: readSafeInteger(value.retentionDays, `${fieldNameArg}.retentionDays`, 1, 365_000),
|
|
566
|
+
}
|
|
567
|
+
: {}),
|
|
568
|
+
...(createdAt ? { createdAt } : {}),
|
|
569
|
+
...(updatedAt ? { updatedAt } : {}),
|
|
570
|
+
};
|
|
571
|
+
};
|
|
572
|
+
const normalizeTarget = (valueArg, fieldNameArg) => {
|
|
573
|
+
const value = readRecord(valueArg, fieldNameArg);
|
|
574
|
+
assertExactKeys(value, ['policy', 'storageClass', 'request', 'credentials'], fieldNameArg);
|
|
575
|
+
return {
|
|
576
|
+
policy: normalizePolicy(value.policy, `${fieldNameArg}.policy`),
|
|
577
|
+
storageClass: normalizeStorageClass(value.storageClass, `${fieldNameArg}.storageClass`),
|
|
578
|
+
request: normalizeObjectStorageRequest(value.request, `${fieldNameArg}.request`),
|
|
579
|
+
credentials: normalizeCredentials(value.credentials, `${fieldNameArg}.credentials`),
|
|
580
|
+
};
|
|
581
|
+
};
|
|
582
|
+
const normalizeMigrationOwner = (valueArg, fieldNameArg) => {
|
|
583
|
+
const value = readRecord(valueArg, fieldNameArg);
|
|
584
|
+
assertExactKeys(value, ['migrationId', 'migrationDigest'], fieldNameArg);
|
|
585
|
+
return {
|
|
586
|
+
migrationId: readIdentifier(value.migrationId, `${fieldNameArg}.migrationId`),
|
|
587
|
+
migrationDigest: readSha256(value.migrationDigest, `${fieldNameArg}.migrationDigest`),
|
|
588
|
+
};
|
|
589
|
+
};
|
|
590
|
+
export const normalizeStorageBindingMigrationOwner = (valueArg) => {
|
|
591
|
+
return assertControlJsonLimit(normalizeMigrationOwner(valueArg, 'storage binding migration owner'), 'storage binding migration owner');
|
|
592
|
+
};
|
|
593
|
+
const normalizeUnfencedSnapshotShape = (valueArg, fieldNameArg) => {
|
|
594
|
+
const value = readRecord(valueArg, fieldNameArg);
|
|
595
|
+
assertExactKeys(value, [
|
|
596
|
+
'schemaVersion',
|
|
597
|
+
'binding',
|
|
598
|
+
'recordRevision',
|
|
599
|
+
'snapshotDigest',
|
|
600
|
+
'capturedAt',
|
|
601
|
+
], fieldNameArg);
|
|
602
|
+
if (value.schemaVersion !== 1) {
|
|
603
|
+
return fail(`${fieldNameArg}.schemaVersion must be 1`);
|
|
604
|
+
}
|
|
605
|
+
return {
|
|
606
|
+
schemaVersion: 1,
|
|
607
|
+
binding: normalizeObjectStorageBinding(value.binding, 'ready', `${fieldNameArg}.binding`),
|
|
608
|
+
recordRevision: readSafeInteger(value.recordRevision, `${fieldNameArg}.recordRevision`, 1),
|
|
609
|
+
snapshotDigest: readSha256(value.snapshotDigest, `${fieldNameArg}.snapshotDigest`),
|
|
610
|
+
capturedAt: readSafeInteger(value.capturedAt, `${fieldNameArg}.capturedAt`, 1),
|
|
611
|
+
};
|
|
612
|
+
};
|
|
613
|
+
const normalizeFencedSnapshotShape = (valueArg, fieldNameArg) => {
|
|
614
|
+
const value = readRecord(valueArg, fieldNameArg);
|
|
615
|
+
assertExactKeys(value, [
|
|
616
|
+
'schemaVersion',
|
|
617
|
+
'binding',
|
|
618
|
+
'recordRevision',
|
|
619
|
+
'snapshotDigest',
|
|
620
|
+
'capturedAt',
|
|
621
|
+
'activeMigration',
|
|
622
|
+
], fieldNameArg);
|
|
623
|
+
if (value.schemaVersion !== 1) {
|
|
624
|
+
return fail(`${fieldNameArg}.schemaVersion must be 1`);
|
|
625
|
+
}
|
|
626
|
+
return {
|
|
627
|
+
schemaVersion: 1,
|
|
628
|
+
binding: normalizeObjectStorageBinding(value.binding, 'ready', `${fieldNameArg}.binding`),
|
|
629
|
+
recordRevision: readSafeInteger(value.recordRevision, `${fieldNameArg}.recordRevision`, 1),
|
|
630
|
+
snapshotDigest: readSha256(value.snapshotDigest, `${fieldNameArg}.snapshotDigest`),
|
|
631
|
+
capturedAt: readSafeInteger(value.capturedAt, `${fieldNameArg}.capturedAt`, 1),
|
|
632
|
+
activeMigration: normalizeMigrationOwner(value.activeMigration, `${fieldNameArg}.activeMigration`),
|
|
633
|
+
};
|
|
634
|
+
};
|
|
635
|
+
const createUnfencedSnapshotDigestPayload = (snapshotArg) => ({
|
|
636
|
+
schemaVersion: 1,
|
|
637
|
+
binding: snapshotArg.binding,
|
|
638
|
+
recordRevision: snapshotArg.recordRevision,
|
|
639
|
+
capturedAt: snapshotArg.capturedAt,
|
|
640
|
+
});
|
|
641
|
+
const createFencedSnapshotDigestPayload = (snapshotArg) => ({
|
|
642
|
+
schemaVersion: 1,
|
|
643
|
+
binding: snapshotArg.binding,
|
|
644
|
+
recordRevision: snapshotArg.recordRevision,
|
|
645
|
+
capturedAt: snapshotArg.capturedAt,
|
|
646
|
+
activeMigration: snapshotArg.activeMigration,
|
|
647
|
+
});
|
|
648
|
+
export const canonicalizeUnfencedObjectStorageBindingControlSnapshotPayload = (valueArg) => {
|
|
649
|
+
const value = readRecord(valueArg, 'unfenced object-storage control snapshot digest payload');
|
|
650
|
+
assertExactKeys(value, ['schemaVersion', 'binding', 'recordRevision', 'capturedAt'], 'unfenced object-storage control snapshot digest payload');
|
|
651
|
+
const normalized = normalizeUnfencedSnapshotShape({
|
|
652
|
+
...value,
|
|
653
|
+
snapshotDigest: '0'.repeat(64),
|
|
654
|
+
}, 'unfenced object-storage control snapshot digest payload');
|
|
655
|
+
return canonicalize(createUnfencedSnapshotDigestPayload(normalized));
|
|
656
|
+
};
|
|
657
|
+
export const canonicalizeFencedObjectStorageBindingControlSnapshotPayload = (valueArg) => {
|
|
658
|
+
const value = readRecord(valueArg, 'fenced object-storage control snapshot digest payload');
|
|
659
|
+
assertExactKeys(value, [
|
|
660
|
+
'schemaVersion',
|
|
661
|
+
'binding',
|
|
662
|
+
'recordRevision',
|
|
663
|
+
'capturedAt',
|
|
664
|
+
'activeMigration',
|
|
665
|
+
], 'fenced object-storage control snapshot digest payload');
|
|
666
|
+
const normalized = normalizeFencedSnapshotShape({
|
|
667
|
+
...value,
|
|
668
|
+
snapshotDigest: '0'.repeat(64),
|
|
669
|
+
}, 'fenced object-storage control snapshot digest payload');
|
|
670
|
+
return canonicalize(createFencedSnapshotDigestPayload(normalized));
|
|
671
|
+
};
|
|
672
|
+
export const createUnfencedObjectStorageBindingControlSnapshotSha256 = async (valueArg) => {
|
|
673
|
+
return createCanonicalJsonSha256Hex(canonicalizeUnfencedObjectStorageBindingControlSnapshotPayload(valueArg), fail);
|
|
674
|
+
};
|
|
675
|
+
export const createFencedObjectStorageBindingControlSnapshotSha256 = async (valueArg) => {
|
|
676
|
+
return createCanonicalJsonSha256Hex(canonicalizeFencedObjectStorageBindingControlSnapshotPayload(valueArg), fail);
|
|
677
|
+
};
|
|
678
|
+
export const normalizeUnfencedObjectStorageBindingControlSnapshot = async (valueArg) => {
|
|
679
|
+
const normalized = normalizeUnfencedSnapshotShape(valueArg, 'unfenced object-storage control snapshot');
|
|
680
|
+
const actualDigest = await createCanonicalSha256(createUnfencedSnapshotDigestPayload(normalized));
|
|
681
|
+
if (normalized.snapshotDigest !== actualDigest) {
|
|
682
|
+
return fail('unfenced object-storage control snapshot.snapshotDigest does not match its canonical payload');
|
|
683
|
+
}
|
|
684
|
+
return assertControlJsonLimit(normalized, 'unfenced object-storage control snapshot');
|
|
685
|
+
};
|
|
686
|
+
export const normalizeFencedObjectStorageBindingControlSnapshot = async (valueArg) => {
|
|
687
|
+
const normalized = normalizeFencedSnapshotShape(valueArg, 'fenced object-storage control snapshot');
|
|
688
|
+
const actualDigest = await createCanonicalSha256(createFencedSnapshotDigestPayload(normalized));
|
|
689
|
+
if (normalized.snapshotDigest !== actualDigest) {
|
|
690
|
+
return fail('fenced object-storage control snapshot.snapshotDigest does not match its canonical payload');
|
|
691
|
+
}
|
|
692
|
+
return assertControlJsonLimit(normalized, 'fenced object-storage control snapshot');
|
|
693
|
+
};
|
|
694
|
+
export const normalizeObjectStorageMigrationTarget = (valueArg) => {
|
|
695
|
+
return assertControlJsonLimit(normalizeTarget(valueArg, 'object-storage migration target'), 'object-storage migration target');
|
|
696
|
+
};
|
|
697
|
+
export const normalizeStagedObjectStorageBinding = (valueArg) => {
|
|
698
|
+
return assertControlJsonLimit(normalizeObjectStorageBinding(valueArg, 'provisioning', 'staged object-storage binding'), 'staged object-storage binding');
|
|
699
|
+
};
|
|
700
|
+
export const normalizeActiveObjectStorageBinding = (valueArg) => {
|
|
701
|
+
return assertControlJsonLimit(normalizeObjectStorageBinding(valueArg, 'ready', 'active object-storage binding'), 'active object-storage binding');
|
|
702
|
+
};
|
|
703
|
+
export const canonicalizeObjectStorageMigrationTargetRequest = (valueArg) => {
|
|
704
|
+
return canonicalize(normalizeObjectStorageRequest(valueArg, 'object-storage migration target request'));
|
|
705
|
+
};
|
|
706
|
+
export const createObjectStorageMigrationTargetRequestSha256 = async (valueArg) => {
|
|
707
|
+
return createCanonicalJsonSha256Hex(canonicalizeObjectStorageMigrationTargetRequest(valueArg), fail);
|
|
708
|
+
};
|
|
709
|
+
export const canonicalizeObjectStorageMigrationBinding = (valueArg) => {
|
|
710
|
+
const value = readRecord(valueArg, 'object-storage migration binding');
|
|
711
|
+
const status = readLiteral(value.status, ['provisioning', 'ready'], 'object-storage migration binding.status');
|
|
712
|
+
return canonicalize(normalizeObjectStorageBinding(value, status, 'object-storage migration binding'));
|
|
713
|
+
};
|
|
714
|
+
export const createObjectStorageMigrationBindingSha256 = async (valueArg) => {
|
|
715
|
+
return createCanonicalJsonSha256Hex(canonicalizeObjectStorageMigrationBinding(valueArg), fail);
|
|
716
|
+
};
|
|
717
|
+
const assertTargetIdentity = async (targetArg, sourceBindingArg, fieldNameArg) => {
|
|
718
|
+
if (targetArg.request.id !== sourceBindingArg.requestId) {
|
|
719
|
+
fail(`${fieldNameArg}.request.id must equal the source binding requestId`);
|
|
720
|
+
}
|
|
721
|
+
if (targetArg.request.storageClass.length === 0) {
|
|
722
|
+
fail(`${fieldNameArg}.request.storageClass must not be empty`);
|
|
723
|
+
}
|
|
724
|
+
const required = targetArg.storageClass.required;
|
|
725
|
+
if (required?.durability === 'ephemeral') {
|
|
726
|
+
fail(`${fieldNameArg}.storageClass cannot request ephemeral migration storage`);
|
|
727
|
+
}
|
|
728
|
+
};
|
|
729
|
+
const normalizePrepareRequestShape = (valueArg) => {
|
|
730
|
+
const value = readRecord(valueArg, 'object-storage migration prepare request');
|
|
731
|
+
assertExactKeys(value, [
|
|
732
|
+
'schemaVersion',
|
|
733
|
+
'migrationId',
|
|
734
|
+
'sourceControlSnapshot',
|
|
735
|
+
'workloadGeneration',
|
|
736
|
+
'target',
|
|
737
|
+
], 'object-storage migration prepare request');
|
|
738
|
+
if (value.schemaVersion !== 1) {
|
|
739
|
+
return fail('object-storage migration prepare request.schemaVersion must be 1');
|
|
740
|
+
}
|
|
741
|
+
return {
|
|
742
|
+
schemaVersion: 1,
|
|
743
|
+
migrationId: readIdentifier(value.migrationId, 'object-storage migration prepare request.migrationId'),
|
|
744
|
+
sourceControlSnapshot: normalizeUnfencedSnapshotShape(value.sourceControlSnapshot, 'object-storage migration prepare request.sourceControlSnapshot'),
|
|
745
|
+
workloadGeneration: readSafeInteger(value.workloadGeneration, 'object-storage migration prepare request.workloadGeneration', 1),
|
|
746
|
+
target: normalizeTarget(value.target, 'object-storage migration prepare request.target'),
|
|
747
|
+
};
|
|
748
|
+
};
|
|
749
|
+
export const normalizeObjectStorageMigrationPrepareRequest = async (valueArg) => {
|
|
750
|
+
const normalized = normalizePrepareRequestShape(valueArg);
|
|
751
|
+
await normalizeUnfencedObjectStorageBindingControlSnapshot(normalized.sourceControlSnapshot);
|
|
752
|
+
await assertTargetIdentity(normalized.target, normalized.sourceControlSnapshot.binding, 'object-storage migration prepare request.target');
|
|
753
|
+
return assertControlJsonLimit(normalized, 'object-storage migration prepare request');
|
|
754
|
+
};
|
|
755
|
+
export const canonicalizeObjectStorageMigrationPrepareRequest = async (valueArg) => {
|
|
756
|
+
return canonicalize(await normalizeObjectStorageMigrationPrepareRequest(valueArg));
|
|
757
|
+
};
|
|
758
|
+
export const createObjectStorageMigrationSha256 = async (valueArg) => {
|
|
759
|
+
return createCanonicalJsonSha256Hex(await canonicalizeObjectStorageMigrationPrepareRequest(valueArg), fail);
|
|
760
|
+
};
|
|
761
|
+
const normalizeProgress = (valueArg, fieldNameArg) => {
|
|
762
|
+
const value = readRecord(valueArg, fieldNameArg);
|
|
763
|
+
assertKeys(value, ['objectsCopied', 'logicalBytesCopied', 'updatedAt'], [
|
|
764
|
+
'physicalBytesCopied',
|
|
765
|
+
'objectsTotal',
|
|
766
|
+
'logicalBytesTotal',
|
|
767
|
+
'physicalBytesTotal',
|
|
768
|
+
], fieldNameArg);
|
|
769
|
+
const objectsCopied = readSafeInteger(value.objectsCopied, `${fieldNameArg}.objectsCopied`, 0);
|
|
770
|
+
const logicalBytesCopied = readSafeInteger(value.logicalBytesCopied, `${fieldNameArg}.logicalBytesCopied`, 0);
|
|
771
|
+
const physicalBytesCopied = Object.hasOwn(value, 'physicalBytesCopied')
|
|
772
|
+
? readSafeInteger(value.physicalBytesCopied, `${fieldNameArg}.physicalBytesCopied`, 0)
|
|
773
|
+
: undefined;
|
|
774
|
+
const objectsTotal = Object.hasOwn(value, 'objectsTotal')
|
|
775
|
+
? readSafeInteger(value.objectsTotal, `${fieldNameArg}.objectsTotal`, 0)
|
|
776
|
+
: undefined;
|
|
777
|
+
const logicalBytesTotal = Object.hasOwn(value, 'logicalBytesTotal')
|
|
778
|
+
? readSafeInteger(value.logicalBytesTotal, `${fieldNameArg}.logicalBytesTotal`, 0)
|
|
779
|
+
: undefined;
|
|
780
|
+
const physicalBytesTotal = Object.hasOwn(value, 'physicalBytesTotal')
|
|
781
|
+
? readSafeInteger(value.physicalBytesTotal, `${fieldNameArg}.physicalBytesTotal`, 0)
|
|
782
|
+
: undefined;
|
|
783
|
+
if (objectsTotal !== undefined && objectsCopied > objectsTotal) {
|
|
784
|
+
return fail(`${fieldNameArg}.objectsCopied exceeds objectsTotal`);
|
|
785
|
+
}
|
|
786
|
+
if (logicalBytesTotal !== undefined &&
|
|
787
|
+
logicalBytesCopied > logicalBytesTotal) {
|
|
788
|
+
return fail(`${fieldNameArg}.logicalBytesCopied exceeds logicalBytesTotal`);
|
|
789
|
+
}
|
|
790
|
+
if (physicalBytesTotal !== undefined &&
|
|
791
|
+
physicalBytesCopied !== undefined &&
|
|
792
|
+
physicalBytesCopied > physicalBytesTotal) {
|
|
793
|
+
return fail(`${fieldNameArg}.physicalBytesCopied exceeds physicalBytesTotal`);
|
|
794
|
+
}
|
|
795
|
+
return {
|
|
796
|
+
objectsCopied,
|
|
797
|
+
logicalBytesCopied,
|
|
798
|
+
...(physicalBytesCopied !== undefined ? { physicalBytesCopied } : {}),
|
|
799
|
+
...(objectsTotal !== undefined ? { objectsTotal } : {}),
|
|
800
|
+
...(logicalBytesTotal !== undefined ? { logicalBytesTotal } : {}),
|
|
801
|
+
...(physicalBytesTotal !== undefined ? { physicalBytesTotal } : {}),
|
|
802
|
+
updatedAt: readSafeInteger(value.updatedAt, `${fieldNameArg}.updatedAt`, 1),
|
|
803
|
+
};
|
|
804
|
+
};
|
|
805
|
+
const normalizeIssue = (valueArg, kindArg, fieldNameArg) => {
|
|
806
|
+
const value = readRecord(valueArg, fieldNameArg);
|
|
807
|
+
assertExactKeys(value, ['code', 'message', 'retryable', 'observedAt', 'allowedRecoveryActions'], fieldNameArg);
|
|
808
|
+
const entries = readDenseArray(value.allowedRecoveryActions, `${fieldNameArg}.allowedRecoveryActions`, 1, 2);
|
|
809
|
+
const allowed = kindArg === 'pre'
|
|
810
|
+
? ['retry', 'abort']
|
|
811
|
+
: ['retry', 'rollForward'];
|
|
812
|
+
const actions = entries.map((entryArg, indexArg) => readLiteral(entryArg, allowed, `${fieldNameArg}.allowedRecoveryActions[${indexArg}]`));
|
|
813
|
+
if (new Set(actions).size !== actions.length) {
|
|
814
|
+
return fail(`${fieldNameArg}.allowedRecoveryActions must be distinct`);
|
|
815
|
+
}
|
|
816
|
+
const retryable = readBoolean(value.retryable, `${fieldNameArg}.retryable`);
|
|
817
|
+
if (retryable !== actions.includes('retry')) {
|
|
818
|
+
return fail(`${fieldNameArg}.retryable must match whether retry is an allowed action`);
|
|
819
|
+
}
|
|
820
|
+
return {
|
|
821
|
+
code: readIdentifier(value.code, `${fieldNameArg}.code`),
|
|
822
|
+
message: readString(value.message, `${fieldNameArg}.message`, storageMigrationContractLimits.maximumIssueMessageBytes),
|
|
823
|
+
retryable,
|
|
824
|
+
observedAt: readSafeInteger(value.observedAt, `${fieldNameArg}.observedAt`, 1),
|
|
825
|
+
allowedRecoveryActions: actions,
|
|
826
|
+
};
|
|
827
|
+
};
|
|
828
|
+
const normalizeMutationFence = (valueArg, fieldNameArg) => {
|
|
829
|
+
if (valueArg.schemaVersion !== 1) {
|
|
830
|
+
return fail(`${fieldNameArg}.schemaVersion must be 1`);
|
|
831
|
+
}
|
|
832
|
+
return {
|
|
833
|
+
schemaVersion: 1,
|
|
834
|
+
migrationId: readIdentifier(valueArg.migrationId, `${fieldNameArg}.migrationId`),
|
|
835
|
+
migrationDigest: readSha256(valueArg.migrationDigest, `${fieldNameArg}.migrationDigest`),
|
|
836
|
+
expectedMigrationRevision: readSafeInteger(valueArg.expectedMigrationRevision, `${fieldNameArg}.expectedMigrationRevision`, 1),
|
|
837
|
+
mutationId: readIdentifier(valueArg.mutationId, `${fieldNameArg}.mutationId`),
|
|
838
|
+
};
|
|
839
|
+
};
|
|
840
|
+
export const normalizeStorageMigrationMutationFence = (valueArg) => {
|
|
841
|
+
const fieldName = 'storage migration mutation fence';
|
|
842
|
+
const value = readRecord(valueArg, fieldName);
|
|
843
|
+
assertExactKeys(value, [
|
|
844
|
+
'schemaVersion',
|
|
845
|
+
'migrationId',
|
|
846
|
+
'migrationDigest',
|
|
847
|
+
'expectedMigrationRevision',
|
|
848
|
+
'mutationId',
|
|
849
|
+
], fieldName);
|
|
850
|
+
return assertControlJsonLimit(normalizeMutationFence(value, fieldName), fieldName);
|
|
851
|
+
};
|
|
852
|
+
const normalizeQuiesceRequestShape = (valueArg) => {
|
|
853
|
+
const fieldName = 'object-storage migration consumer quiesce request';
|
|
854
|
+
const value = readRecord(valueArg, fieldName);
|
|
855
|
+
assertExactKeys(value, [
|
|
856
|
+
'schemaVersion',
|
|
857
|
+
'migrationId',
|
|
858
|
+
'migrationDigest',
|
|
859
|
+
'expectedMigrationRevision',
|
|
860
|
+
'mutationId',
|
|
861
|
+
'sourceRecordRevision',
|
|
862
|
+
'sourceControlSnapshotDigest',
|
|
863
|
+
'candidateDigest',
|
|
864
|
+
'workloadGeneration',
|
|
865
|
+
'persistedStagingDigest',
|
|
866
|
+
'persistedStagingRevision',
|
|
867
|
+
'consumerStoppedAt',
|
|
868
|
+
], fieldName);
|
|
869
|
+
return {
|
|
870
|
+
...normalizeMutationFence(value, fieldName),
|
|
871
|
+
sourceRecordRevision: readSafeInteger(value.sourceRecordRevision, `${fieldName}.sourceRecordRevision`, 1),
|
|
872
|
+
sourceControlSnapshotDigest: readSha256(value.sourceControlSnapshotDigest, `${fieldName}.sourceControlSnapshotDigest`),
|
|
873
|
+
candidateDigest: readSha256(value.candidateDigest, `${fieldName}.candidateDigest`),
|
|
874
|
+
workloadGeneration: readSafeInteger(value.workloadGeneration, `${fieldName}.workloadGeneration`, 1),
|
|
875
|
+
persistedStagingDigest: readSha256(value.persistedStagingDigest, `${fieldName}.persistedStagingDigest`),
|
|
876
|
+
persistedStagingRevision: readSafeInteger(value.persistedStagingRevision, `${fieldName}.persistedStagingRevision`, 1),
|
|
877
|
+
consumerStoppedAt: readSafeInteger(value.consumerStoppedAt, `${fieldName}.consumerStoppedAt`, 1),
|
|
878
|
+
};
|
|
879
|
+
};
|
|
880
|
+
const createPersistedStagingDigestPayload = (requestArg) => ({
|
|
881
|
+
schemaVersion: 1,
|
|
882
|
+
migrationId: requestArg.migrationId,
|
|
883
|
+
migrationDigest: requestArg.migrationDigest,
|
|
884
|
+
expectedMigrationRevision: requestArg.expectedMigrationRevision,
|
|
885
|
+
mutationId: requestArg.mutationId,
|
|
886
|
+
sourceRecordRevision: requestArg.sourceRecordRevision,
|
|
887
|
+
sourceControlSnapshotDigest: requestArg.sourceControlSnapshotDigest,
|
|
888
|
+
candidateDigest: requestArg.candidateDigest,
|
|
889
|
+
workloadGeneration: requestArg.workloadGeneration,
|
|
890
|
+
persistedStagingRevision: requestArg.persistedStagingRevision,
|
|
891
|
+
consumerStoppedAt: requestArg.consumerStoppedAt,
|
|
892
|
+
});
|
|
893
|
+
export const createObjectStorageMigrationPersistedStagingSha256 = async (valueArg) => {
|
|
894
|
+
const value = readRecord(valueArg, 'persisted staging digest payload');
|
|
895
|
+
assertExactKeys(value, [
|
|
896
|
+
'schemaVersion',
|
|
897
|
+
'migrationId',
|
|
898
|
+
'migrationDigest',
|
|
899
|
+
'expectedMigrationRevision',
|
|
900
|
+
'mutationId',
|
|
901
|
+
'sourceRecordRevision',
|
|
902
|
+
'sourceControlSnapshotDigest',
|
|
903
|
+
'candidateDigest',
|
|
904
|
+
'workloadGeneration',
|
|
905
|
+
'persistedStagingRevision',
|
|
906
|
+
'consumerStoppedAt',
|
|
907
|
+
], 'persisted staging digest payload');
|
|
908
|
+
const request = normalizeQuiesceRequestShape({
|
|
909
|
+
...value,
|
|
910
|
+
persistedStagingDigest: '0'.repeat(64),
|
|
911
|
+
});
|
|
912
|
+
return createCanonicalSha256(createPersistedStagingDigestPayload(request));
|
|
913
|
+
};
|
|
914
|
+
export const normalizeObjectStorageMigrationConsumerQuiesceRequest = async (valueArg) => {
|
|
915
|
+
const normalized = normalizeQuiesceRequestShape(valueArg);
|
|
916
|
+
const actualDigest = await createCanonicalSha256(createPersistedStagingDigestPayload(normalized));
|
|
917
|
+
if (normalized.persistedStagingDigest !== actualDigest) {
|
|
918
|
+
return fail('object-storage migration consumer quiesce request.persistedStagingDigest does not match its canonical payload');
|
|
919
|
+
}
|
|
920
|
+
return assertControlJsonLimit(normalized, 'object-storage migration consumer quiesce request');
|
|
921
|
+
};
|
|
922
|
+
const normalizeActivationRequestShape = (valueArg) => {
|
|
923
|
+
const fieldName = 'object-storage migration consumer activation request';
|
|
924
|
+
const value = readRecord(valueArg, fieldName);
|
|
925
|
+
assertExactKeys(value, [
|
|
926
|
+
'schemaVersion',
|
|
927
|
+
'migrationId',
|
|
928
|
+
'migrationDigest',
|
|
929
|
+
'expectedMigrationRevision',
|
|
930
|
+
'mutationId',
|
|
931
|
+
'candidateDigest',
|
|
932
|
+
'activeBindingDigest',
|
|
933
|
+
'workloadGeneration',
|
|
934
|
+
'persistedActivationDigest',
|
|
935
|
+
'persistedActivationRevision',
|
|
936
|
+
'consumerStartedAt',
|
|
937
|
+
], fieldName);
|
|
938
|
+
return {
|
|
939
|
+
...normalizeMutationFence(value, fieldName),
|
|
940
|
+
candidateDigest: readSha256(value.candidateDigest, `${fieldName}.candidateDigest`),
|
|
941
|
+
activeBindingDigest: readSha256(value.activeBindingDigest, `${fieldName}.activeBindingDigest`),
|
|
942
|
+
workloadGeneration: readSafeInteger(value.workloadGeneration, `${fieldName}.workloadGeneration`, 1),
|
|
943
|
+
persistedActivationDigest: readSha256(value.persistedActivationDigest, `${fieldName}.persistedActivationDigest`),
|
|
944
|
+
persistedActivationRevision: readSafeInteger(value.persistedActivationRevision, `${fieldName}.persistedActivationRevision`, 1),
|
|
945
|
+
consumerStartedAt: readSafeInteger(value.consumerStartedAt, `${fieldName}.consumerStartedAt`, 1),
|
|
946
|
+
};
|
|
947
|
+
};
|
|
948
|
+
const createPersistedActivationDigestPayload = (requestArg) => ({
|
|
949
|
+
schemaVersion: 1,
|
|
950
|
+
migrationId: requestArg.migrationId,
|
|
951
|
+
migrationDigest: requestArg.migrationDigest,
|
|
952
|
+
expectedMigrationRevision: requestArg.expectedMigrationRevision,
|
|
953
|
+
mutationId: requestArg.mutationId,
|
|
954
|
+
candidateDigest: requestArg.candidateDigest,
|
|
955
|
+
activeBindingDigest: requestArg.activeBindingDigest,
|
|
956
|
+
workloadGeneration: requestArg.workloadGeneration,
|
|
957
|
+
persistedActivationRevision: requestArg.persistedActivationRevision,
|
|
958
|
+
consumerStartedAt: requestArg.consumerStartedAt,
|
|
959
|
+
});
|
|
960
|
+
export const createObjectStorageMigrationPersistedActivationSha256 = async (valueArg) => {
|
|
961
|
+
const value = readRecord(valueArg, 'persisted activation digest payload');
|
|
962
|
+
assertExactKeys(value, [
|
|
963
|
+
'schemaVersion',
|
|
964
|
+
'migrationId',
|
|
965
|
+
'migrationDigest',
|
|
966
|
+
'expectedMigrationRevision',
|
|
967
|
+
'mutationId',
|
|
968
|
+
'candidateDigest',
|
|
969
|
+
'activeBindingDigest',
|
|
970
|
+
'workloadGeneration',
|
|
971
|
+
'persistedActivationRevision',
|
|
972
|
+
'consumerStartedAt',
|
|
973
|
+
], 'persisted activation digest payload');
|
|
974
|
+
const request = normalizeActivationRequestShape({
|
|
975
|
+
...value,
|
|
976
|
+
persistedActivationDigest: '0'.repeat(64),
|
|
977
|
+
});
|
|
978
|
+
return createCanonicalSha256(createPersistedActivationDigestPayload(request));
|
|
979
|
+
};
|
|
980
|
+
export const normalizeObjectStorageMigrationConsumerActivationRequest = async (valueArg) => {
|
|
981
|
+
const normalized = normalizeActivationRequestShape(valueArg);
|
|
982
|
+
const actualDigest = await createCanonicalSha256(createPersistedActivationDigestPayload(normalized));
|
|
983
|
+
if (normalized.persistedActivationDigest !== actualDigest) {
|
|
984
|
+
return fail('object-storage migration consumer activation request.persistedActivationDigest does not match its canonical payload');
|
|
985
|
+
}
|
|
986
|
+
return assertControlJsonLimit(normalized, 'object-storage migration consumer activation request');
|
|
987
|
+
};
|
|
988
|
+
const normalizeQuiesceEvidence = async (valueArg, fieldNameArg) => {
|
|
989
|
+
const value = readRecord(valueArg, fieldNameArg);
|
|
990
|
+
assertExactKeys(value, ['request', 'acceptedMigrationRevision', 'acceptedAt'], fieldNameArg);
|
|
991
|
+
const request = await normalizeObjectStorageMigrationConsumerQuiesceRequest(value.request);
|
|
992
|
+
const acceptedMigrationRevision = readSafeInteger(value.acceptedMigrationRevision, `${fieldNameArg}.acceptedMigrationRevision`, 1);
|
|
993
|
+
if (acceptedMigrationRevision <= request.expectedMigrationRevision) {
|
|
994
|
+
return fail(`${fieldNameArg}.acceptedMigrationRevision must advance the requested revision`);
|
|
995
|
+
}
|
|
996
|
+
const acceptedAt = readSafeInteger(value.acceptedAt, `${fieldNameArg}.acceptedAt`, request.consumerStoppedAt);
|
|
997
|
+
return { request, acceptedMigrationRevision, acceptedAt };
|
|
998
|
+
};
|
|
999
|
+
const normalizeActivationEvidence = async (valueArg, fieldNameArg) => {
|
|
1000
|
+
const value = readRecord(valueArg, fieldNameArg);
|
|
1001
|
+
assertExactKeys(value, ['request', 'acceptedMigrationRevision', 'acceptedAt'], fieldNameArg);
|
|
1002
|
+
const request = await normalizeObjectStorageMigrationConsumerActivationRequest(value.request);
|
|
1003
|
+
const acceptedMigrationRevision = readSafeInteger(value.acceptedMigrationRevision, `${fieldNameArg}.acceptedMigrationRevision`, 1);
|
|
1004
|
+
if (acceptedMigrationRevision <= request.expectedMigrationRevision) {
|
|
1005
|
+
return fail(`${fieldNameArg}.acceptedMigrationRevision must advance the requested revision`);
|
|
1006
|
+
}
|
|
1007
|
+
const acceptedAt = readSafeInteger(value.acceptedAt, `${fieldNameArg}.acceptedAt`, request.consumerStartedAt);
|
|
1008
|
+
return { request, acceptedMigrationRevision, acceptedAt };
|
|
1009
|
+
};
|
|
1010
|
+
export const normalizeStorageMigrationConsumerQuiesceEvidence = async (valueArg) => {
|
|
1011
|
+
return assertControlJsonLimit(await normalizeQuiesceEvidence(valueArg, 'storage migration consumer quiesce evidence'), 'storage migration consumer quiesce evidence');
|
|
1012
|
+
};
|
|
1013
|
+
export const normalizeStorageMigrationConsumerActivationEvidence = async (valueArg) => {
|
|
1014
|
+
return assertControlJsonLimit(await normalizeActivationEvidence(valueArg, 'storage migration consumer activation evidence'), 'storage migration consumer activation evidence');
|
|
1015
|
+
};
|
|
1016
|
+
export const normalizeObjectStorageMigrationAbortRequest = (valueArg) => {
|
|
1017
|
+
const fieldName = 'object-storage migration abort request';
|
|
1018
|
+
const value = readRecord(valueArg, fieldName);
|
|
1019
|
+
assertExactKeys(value, [
|
|
1020
|
+
'schemaVersion',
|
|
1021
|
+
'migrationId',
|
|
1022
|
+
'migrationDigest',
|
|
1023
|
+
'expectedMigrationRevision',
|
|
1024
|
+
'mutationId',
|
|
1025
|
+
'reason',
|
|
1026
|
+
], fieldName);
|
|
1027
|
+
return assertControlJsonLimit({
|
|
1028
|
+
...normalizeMutationFence(value, fieldName),
|
|
1029
|
+
reason: readString(value.reason, `${fieldName}.reason`, storageMigrationContractLimits.maximumAbortReasonBytes),
|
|
1030
|
+
}, fieldName);
|
|
1031
|
+
};
|
|
1032
|
+
export const normalizeObjectStorageMigrationResumeRequest = (valueArg) => {
|
|
1033
|
+
const fieldName = 'object-storage migration resume request';
|
|
1034
|
+
const value = readRecord(valueArg, fieldName);
|
|
1035
|
+
assertExactKeys(value, [
|
|
1036
|
+
'schemaVersion',
|
|
1037
|
+
'migrationId',
|
|
1038
|
+
'migrationDigest',
|
|
1039
|
+
'expectedMigrationRevision',
|
|
1040
|
+
'mutationId',
|
|
1041
|
+
'action',
|
|
1042
|
+
], fieldName);
|
|
1043
|
+
return assertControlJsonLimit({
|
|
1044
|
+
...normalizeMutationFence(value, fieldName),
|
|
1045
|
+
action: readLiteral(value.action, ['retry', 'abort', 'rollForward'], `${fieldName}.action`),
|
|
1046
|
+
}, fieldName);
|
|
1047
|
+
};
|
|
1048
|
+
export const normalizeObjectStorageMigrationCleanupRequest = (valueArg) => {
|
|
1049
|
+
const fieldName = 'object-storage migration cleanup request';
|
|
1050
|
+
const value = readRecord(valueArg, fieldName);
|
|
1051
|
+
assertExactKeys(value, [
|
|
1052
|
+
'schemaVersion',
|
|
1053
|
+
'migrationId',
|
|
1054
|
+
'migrationDigest',
|
|
1055
|
+
'expectedMigrationRevision',
|
|
1056
|
+
'mutationId',
|
|
1057
|
+
], fieldName);
|
|
1058
|
+
return assertControlJsonLimit(normalizeMutationFence(value, fieldName), fieldName);
|
|
1059
|
+
};
|
|
1060
|
+
const assertCapabilitiesSatisfyTarget = (bindingArg, targetArg, fieldNameArg) => {
|
|
1061
|
+
const required = targetArg.storageClass.required;
|
|
1062
|
+
const capabilities = bindingArg.capabilities;
|
|
1063
|
+
if (required) {
|
|
1064
|
+
for (const key of [
|
|
1065
|
+
'performanceTier',
|
|
1066
|
+
'durability',
|
|
1067
|
+
'topology',
|
|
1068
|
+
'snapshots',
|
|
1069
|
+
]) {
|
|
1070
|
+
const requirement = required[key];
|
|
1071
|
+
if (requirement !== undefined && capabilities[key] !== requirement) {
|
|
1072
|
+
fail(`${fieldNameArg}.capabilities.${key} does not satisfy target requirements`);
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
for (const key of [
|
|
1076
|
+
'hardQuota',
|
|
1077
|
+
'backup',
|
|
1078
|
+
'encryptedInTransit',
|
|
1079
|
+
]) {
|
|
1080
|
+
if (required[key] === true && capabilities[key] !== true) {
|
|
1081
|
+
fail(`${fieldNameArg}.capabilities.${key} does not satisfy target requirements`);
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
};
|
|
1086
|
+
const assertCandidateIdentity = async (candidateArg, sourceArg, targetArg, fieldNameArg) => {
|
|
1087
|
+
if (candidateArg.id !== sourceArg.id ||
|
|
1088
|
+
candidateArg.serviceId !== sourceArg.serviceId ||
|
|
1089
|
+
candidateArg.requestId !== sourceArg.requestId) {
|
|
1090
|
+
fail(`${fieldNameArg} must preserve binding, service, and request identity`);
|
|
1091
|
+
}
|
|
1092
|
+
if (candidateArg.requestId !== targetArg.request.id) {
|
|
1093
|
+
fail(`${fieldNameArg}.requestId must equal target.request.id`);
|
|
1094
|
+
}
|
|
1095
|
+
const targetRequestDigest = await createObjectStorageMigrationTargetRequestSha256(targetArg.request);
|
|
1096
|
+
if (candidateArg.requestDigest !== targetRequestDigest) {
|
|
1097
|
+
fail(`${fieldNameArg}.requestDigest does not match target.request`);
|
|
1098
|
+
}
|
|
1099
|
+
if (canonicalize(candidateArg.policy) !== canonicalize(targetArg.policy) ||
|
|
1100
|
+
canonicalize(candidateArg.credentials) !==
|
|
1101
|
+
canonicalize(targetArg.credentials) ||
|
|
1102
|
+
canonicalize(candidateArg.delivery) !==
|
|
1103
|
+
canonicalize(targetArg.request.delivery)) {
|
|
1104
|
+
fail(`${fieldNameArg} does not match the target policy and delivery intent`);
|
|
1105
|
+
}
|
|
1106
|
+
if (candidateArg.accessMode !== targetArg.request.accessMode) {
|
|
1107
|
+
fail(`${fieldNameArg}.accessMode does not match target.request.accessMode`);
|
|
1108
|
+
}
|
|
1109
|
+
if (candidateArg.resourceRef === sourceArg.resourceRef) {
|
|
1110
|
+
fail(`${fieldNameArg}.resourceRef must differ from the source resource`);
|
|
1111
|
+
}
|
|
1112
|
+
if (candidateArg.generation <= sourceArg.generation) {
|
|
1113
|
+
fail(`${fieldNameArg}.generation must advance the source generation`);
|
|
1114
|
+
}
|
|
1115
|
+
if (targetArg.request.capacity) {
|
|
1116
|
+
if (candidateArg.capacity?.requested !== targetArg.request.capacity.request ||
|
|
1117
|
+
candidateArg.capacity?.limit !== targetArg.request.capacity.limit) {
|
|
1118
|
+
fail(`${fieldNameArg}.capacity must preserve the target request bounds`);
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
if (targetArg.request.protection?.backup === 'required' &&
|
|
1122
|
+
candidateArg.capabilities.backup !== true) {
|
|
1123
|
+
fail(`${fieldNameArg}.capabilities.backup does not satisfy target protection`);
|
|
1124
|
+
}
|
|
1125
|
+
if (targetArg.request.capacity?.limit !== undefined &&
|
|
1126
|
+
candidateArg.capabilities.hardQuota !== true) {
|
|
1127
|
+
fail(`${fieldNameArg}.capabilities.hardQuota is required by target capacity.limit`);
|
|
1128
|
+
}
|
|
1129
|
+
if (targetArg.request.protection?.versioning === 'required' &&
|
|
1130
|
+
candidateArg.versioning !== true) {
|
|
1131
|
+
fail(`${fieldNameArg}.versioning does not satisfy target protection`);
|
|
1132
|
+
}
|
|
1133
|
+
if (targetArg.request.protection?.retentionDays !== undefined &&
|
|
1134
|
+
(candidateArg.retentionDays ?? 0) <
|
|
1135
|
+
targetArg.request.protection.retentionDays) {
|
|
1136
|
+
fail(`${fieldNameArg}.retentionDays does not satisfy target protection`);
|
|
1137
|
+
}
|
|
1138
|
+
assertCapabilitiesSatisfyTarget(candidateArg, targetArg, fieldNameArg);
|
|
1139
|
+
};
|
|
1140
|
+
const assertActiveMatchesCandidate = (activeArg, candidateArg, fieldNameArg) => {
|
|
1141
|
+
const immutableKeys = [
|
|
1142
|
+
'schemaVersion',
|
|
1143
|
+
'id',
|
|
1144
|
+
'serviceId',
|
|
1145
|
+
'requestId',
|
|
1146
|
+
'requestDigest',
|
|
1147
|
+
'kind',
|
|
1148
|
+
'generation',
|
|
1149
|
+
'policy',
|
|
1150
|
+
'capabilities',
|
|
1151
|
+
'resourceRef',
|
|
1152
|
+
'capacity',
|
|
1153
|
+
'accessMode',
|
|
1154
|
+
'connection',
|
|
1155
|
+
'credentials',
|
|
1156
|
+
'delivery',
|
|
1157
|
+
'versioning',
|
|
1158
|
+
'retentionDays',
|
|
1159
|
+
'createdAt',
|
|
1160
|
+
];
|
|
1161
|
+
for (const key of immutableKeys) {
|
|
1162
|
+
if (canonicalize(activeArg[key] ?? null) !== canonicalize(candidateArg[key] ?? null)) {
|
|
1163
|
+
fail(`${fieldNameArg}.${key} must match the issued candidate`);
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
};
|
|
1167
|
+
const normalizeSourceEvidence = async (valueArg, fieldNameArg) => {
|
|
1168
|
+
const value = readRecord(valueArg, fieldNameArg);
|
|
1169
|
+
assertExactKeys(value, ['preparationSnapshot', 'fencedSnapshot'], fieldNameArg);
|
|
1170
|
+
const preparationSnapshot = await normalizeUnfencedObjectStorageBindingControlSnapshot(value.preparationSnapshot);
|
|
1171
|
+
const fencedSnapshot = await normalizeFencedObjectStorageBindingControlSnapshot(value.fencedSnapshot);
|
|
1172
|
+
if (fencedSnapshot.recordRevision <= preparationSnapshot.recordRevision ||
|
|
1173
|
+
fencedSnapshot.capturedAt < preparationSnapshot.capturedAt) {
|
|
1174
|
+
return fail(`${fieldNameArg}.fencedSnapshot must be captured at a later record revision`);
|
|
1175
|
+
}
|
|
1176
|
+
if (canonicalize(fencedSnapshot.binding) !==
|
|
1177
|
+
canonicalize(preparationSnapshot.binding)) {
|
|
1178
|
+
return fail(`${fieldNameArg}.fencedSnapshot.binding must exactly preserve the prepared source binding`);
|
|
1179
|
+
}
|
|
1180
|
+
return {
|
|
1181
|
+
preparationSnapshot,
|
|
1182
|
+
fencedSnapshot,
|
|
1183
|
+
};
|
|
1184
|
+
};
|
|
1185
|
+
export const normalizeStorageMigrationSourceEvidence = async (valueArg) => {
|
|
1186
|
+
return assertControlJsonLimit(await normalizeSourceEvidence(valueArg, 'storage migration source evidence'), 'storage migration source evidence');
|
|
1187
|
+
};
|
|
1188
|
+
const assertEvidenceFence = (fenceArg, migrationIdArg, migrationDigestArg, migrationRevisionArg, fieldNameArg) => {
|
|
1189
|
+
if (fenceArg.migrationId !== migrationIdArg ||
|
|
1190
|
+
fenceArg.migrationDigest !== migrationDigestArg) {
|
|
1191
|
+
fail(`${fieldNameArg} does not match the migration identity`);
|
|
1192
|
+
}
|
|
1193
|
+
if (fenceArg.expectedMigrationRevision >= migrationRevisionArg) {
|
|
1194
|
+
fail(`${fieldNameArg}.expectedMigrationRevision must precede status revision`);
|
|
1195
|
+
}
|
|
1196
|
+
};
|
|
1197
|
+
const statusBaseRequiredKeys = [
|
|
1198
|
+
'schemaVersion',
|
|
1199
|
+
'migrationId',
|
|
1200
|
+
'migrationDigest',
|
|
1201
|
+
'migrationRevision',
|
|
1202
|
+
'bindingId',
|
|
1203
|
+
'serviceId',
|
|
1204
|
+
'requestId',
|
|
1205
|
+
'workloadGeneration',
|
|
1206
|
+
'target',
|
|
1207
|
+
'source',
|
|
1208
|
+
'createdAt',
|
|
1209
|
+
'updatedAt',
|
|
1210
|
+
'phase',
|
|
1211
|
+
'bindingFenceActive',
|
|
1212
|
+
'candidateIssued',
|
|
1213
|
+
'commitPointCrossed',
|
|
1214
|
+
'destinationBindingStartAuthorized',
|
|
1215
|
+
'authority',
|
|
1216
|
+
'consumerAction',
|
|
1217
|
+
];
|
|
1218
|
+
const assertFieldValue = (recordArg, keyArg, expectedArg, fieldNameArg) => {
|
|
1219
|
+
if (recordArg[keyArg] !== expectedArg) {
|
|
1220
|
+
fail(`${fieldNameArg}.${keyArg} must be ${String(expectedArg)}`);
|
|
1221
|
+
}
|
|
1222
|
+
};
|
|
1223
|
+
export const normalizeObjectStorageMigrationStatus = async (valueArg) => {
|
|
1224
|
+
const fieldName = 'object-storage migration status';
|
|
1225
|
+
const value = readRecord(valueArg, fieldName);
|
|
1226
|
+
const phase = readLiteral(value.phase, [
|
|
1227
|
+
'preparing',
|
|
1228
|
+
'transferring',
|
|
1229
|
+
'awaitingConsumerQuiesce',
|
|
1230
|
+
'finalizing',
|
|
1231
|
+
'committing',
|
|
1232
|
+
'readyToStart',
|
|
1233
|
+
'cleanupPending',
|
|
1234
|
+
'complete',
|
|
1235
|
+
'aborting',
|
|
1236
|
+
'aborted',
|
|
1237
|
+
], `${fieldName}.phase`);
|
|
1238
|
+
const candidateIssued = readBoolean(value.candidateIssued, `${fieldName}.candidateIssued`);
|
|
1239
|
+
const phaseRequired = [];
|
|
1240
|
+
const phaseOptional = ['progress'];
|
|
1241
|
+
if (phase !== 'complete' && phase !== 'aborted') {
|
|
1242
|
+
phaseOptional.push('issue');
|
|
1243
|
+
}
|
|
1244
|
+
if (['awaitingConsumerQuiesce', 'finalizing', 'committing', 'readyToStart',
|
|
1245
|
+
'cleanupPending', 'complete'].includes(phase)) {
|
|
1246
|
+
phaseRequired.push('candidateBinding', 'candidateDigest');
|
|
1247
|
+
}
|
|
1248
|
+
else if ((phase === 'aborting' || phase === 'aborted') &&
|
|
1249
|
+
candidateIssued) {
|
|
1250
|
+
phaseRequired.push('candidateDigest');
|
|
1251
|
+
}
|
|
1252
|
+
if (['finalizing', 'committing', 'readyToStart', 'cleanupPending', 'complete']
|
|
1253
|
+
.includes(phase)) {
|
|
1254
|
+
phaseRequired.push('consumerQuiesceEvidence');
|
|
1255
|
+
}
|
|
1256
|
+
else if ((phase === 'aborting' || phase === 'aborted') &&
|
|
1257
|
+
candidateIssued) {
|
|
1258
|
+
phaseOptional.push('consumerQuiesceEvidence');
|
|
1259
|
+
}
|
|
1260
|
+
if (phase === 'cleanupPending' || phase === 'complete') {
|
|
1261
|
+
phaseRequired.push('consumerActivationEvidence');
|
|
1262
|
+
}
|
|
1263
|
+
if (phase === 'readyToStart' ||
|
|
1264
|
+
phase === 'cleanupPending' ||
|
|
1265
|
+
phase === 'complete' ||
|
|
1266
|
+
phase === 'aborted') {
|
|
1267
|
+
phaseRequired.push('activeBinding', 'activeBindingDigest');
|
|
1268
|
+
}
|
|
1269
|
+
if (phase === 'complete' || phase === 'aborted') {
|
|
1270
|
+
phaseRequired.push('terminalAt');
|
|
1271
|
+
}
|
|
1272
|
+
assertKeys(value, [...statusBaseRequiredKeys, ...phaseRequired], phaseOptional, fieldName);
|
|
1273
|
+
if (value.schemaVersion !== 1) {
|
|
1274
|
+
return fail(`${fieldName}.schemaVersion must be 1`);
|
|
1275
|
+
}
|
|
1276
|
+
const migrationId = readIdentifier(value.migrationId, `${fieldName}.migrationId`);
|
|
1277
|
+
const migrationDigest = readSha256(value.migrationDigest, `${fieldName}.migrationDigest`);
|
|
1278
|
+
const migrationRevision = readSafeInteger(value.migrationRevision, `${fieldName}.migrationRevision`, 1);
|
|
1279
|
+
const bindingId = readIdentifier(value.bindingId, `${fieldName}.bindingId`);
|
|
1280
|
+
const serviceId = readIdentifier(value.serviceId, `${fieldName}.serviceId`);
|
|
1281
|
+
const requestId = readIdentifier(value.requestId, `${fieldName}.requestId`);
|
|
1282
|
+
const workloadGeneration = readSafeInteger(value.workloadGeneration, `${fieldName}.workloadGeneration`, 1);
|
|
1283
|
+
const target = normalizeTarget(value.target, `${fieldName}.target`);
|
|
1284
|
+
const source = await normalizeSourceEvidence(value.source, `${fieldName}.source`);
|
|
1285
|
+
const sourceBinding = source.preparationSnapshot.binding;
|
|
1286
|
+
if (bindingId !== sourceBinding.id ||
|
|
1287
|
+
serviceId !== sourceBinding.serviceId ||
|
|
1288
|
+
requestId !== sourceBinding.requestId ||
|
|
1289
|
+
target.request.id !== requestId) {
|
|
1290
|
+
return fail(`${fieldName} identity must match source and target bindings`);
|
|
1291
|
+
}
|
|
1292
|
+
await assertTargetIdentity(target, sourceBinding, `${fieldName}.target`);
|
|
1293
|
+
const recomputedMigrationDigest = await createObjectStorageMigrationSha256({
|
|
1294
|
+
schemaVersion: 1,
|
|
1295
|
+
migrationId,
|
|
1296
|
+
sourceControlSnapshot: source.preparationSnapshot,
|
|
1297
|
+
workloadGeneration,
|
|
1298
|
+
target,
|
|
1299
|
+
});
|
|
1300
|
+
if (migrationDigest !== recomputedMigrationDigest ||
|
|
1301
|
+
source.fencedSnapshot.activeMigration.migrationId !== migrationId ||
|
|
1302
|
+
source.fencedSnapshot.activeMigration.migrationDigest !== migrationDigest) {
|
|
1303
|
+
return fail(`${fieldName}.migrationDigest and fenced owner must match canonical prepare intent`);
|
|
1304
|
+
}
|
|
1305
|
+
const createdAt = readSafeInteger(value.createdAt, `${fieldName}.createdAt`, 1);
|
|
1306
|
+
const updatedAt = readSafeInteger(value.updatedAt, `${fieldName}.updatedAt`, createdAt);
|
|
1307
|
+
const progress = Object.hasOwn(value, 'progress')
|
|
1308
|
+
? normalizeProgress(value.progress, `${fieldName}.progress`)
|
|
1309
|
+
: undefined;
|
|
1310
|
+
if (progress && (progress.updatedAt < createdAt || progress.updatedAt > updatedAt)) {
|
|
1311
|
+
return fail(`${fieldName}.progress.updatedAt must be within status time bounds`);
|
|
1312
|
+
}
|
|
1313
|
+
const preIssuePhase = [
|
|
1314
|
+
'preparing',
|
|
1315
|
+
'transferring',
|
|
1316
|
+
'awaitingConsumerQuiesce',
|
|
1317
|
+
'finalizing',
|
|
1318
|
+
'aborting',
|
|
1319
|
+
].includes(phase);
|
|
1320
|
+
const issue = Object.hasOwn(value, 'issue')
|
|
1321
|
+
? normalizeIssue(value.issue, preIssuePhase ? 'pre' : 'post', `${fieldName}.issue`)
|
|
1322
|
+
: undefined;
|
|
1323
|
+
if (issue && (issue.observedAt < createdAt || issue.observedAt > updatedAt)) {
|
|
1324
|
+
return fail(`${fieldName}.issue.observedAt must be within status time bounds`);
|
|
1325
|
+
}
|
|
1326
|
+
const expectedByPhase = {
|
|
1327
|
+
preparing: [true, false, false, false, 'source', 'wait'],
|
|
1328
|
+
transferring: [true, false, false, false, 'source', 'wait'],
|
|
1329
|
+
awaitingConsumerQuiesce: [
|
|
1330
|
+
true, true, false, false, 'source', 'stageCandidateAndStop',
|
|
1331
|
+
],
|
|
1332
|
+
finalizing: [true, true, false, false, 'source', 'wait'],
|
|
1333
|
+
committing: [true, true, true, false, 'transitioning', 'wait'],
|
|
1334
|
+
readyToStart: [true, true, true, true, 'destination', 'startDestination'],
|
|
1335
|
+
cleanupPending: [true, true, true, true, 'destination', 'none'],
|
|
1336
|
+
complete: [false, true, true, true, 'destination', 'none'],
|
|
1337
|
+
aborting: [true, candidateIssued, false, false, 'source', 'wait'],
|
|
1338
|
+
aborted: [false, candidateIssued, false, false, 'source', 'startSource'],
|
|
1339
|
+
};
|
|
1340
|
+
const expected = expectedByPhase[phase];
|
|
1341
|
+
assertFieldValue(value, 'bindingFenceActive', expected[0], fieldName);
|
|
1342
|
+
assertFieldValue(value, 'candidateIssued', expected[1], fieldName);
|
|
1343
|
+
assertFieldValue(value, 'commitPointCrossed', expected[2], fieldName);
|
|
1344
|
+
assertFieldValue(value, 'destinationBindingStartAuthorized', expected[3], fieldName);
|
|
1345
|
+
assertFieldValue(value, 'authority', expected[4], fieldName);
|
|
1346
|
+
assertFieldValue(value, 'consumerAction', expected[5], fieldName);
|
|
1347
|
+
let candidateBinding;
|
|
1348
|
+
let candidateDigest;
|
|
1349
|
+
if (Object.hasOwn(value, 'candidateBinding')) {
|
|
1350
|
+
candidateBinding = normalizeObjectStorageBinding(value.candidateBinding, 'provisioning', `${fieldName}.candidateBinding`);
|
|
1351
|
+
candidateDigest = readSha256(value.candidateDigest, `${fieldName}.candidateDigest`);
|
|
1352
|
+
const recomputedCandidateDigest = await createObjectStorageMigrationBindingSha256(candidateBinding);
|
|
1353
|
+
if (candidateDigest !== recomputedCandidateDigest) {
|
|
1354
|
+
return fail(`${fieldName}.candidateDigest does not match candidateBinding`);
|
|
1355
|
+
}
|
|
1356
|
+
await assertCandidateIdentity(candidateBinding, sourceBinding, target, `${fieldName}.candidateBinding`);
|
|
1357
|
+
}
|
|
1358
|
+
else if (Object.hasOwn(value, 'candidateDigest')) {
|
|
1359
|
+
candidateDigest = readSha256(value.candidateDigest, `${fieldName}.candidateDigest`);
|
|
1360
|
+
}
|
|
1361
|
+
const quiesceEvidence = Object.hasOwn(value, 'consumerQuiesceEvidence')
|
|
1362
|
+
? await normalizeQuiesceEvidence(value.consumerQuiesceEvidence, `${fieldName}.consumerQuiesceEvidence`)
|
|
1363
|
+
: undefined;
|
|
1364
|
+
if (quiesceEvidence) {
|
|
1365
|
+
assertEvidenceFence(quiesceEvidence.request, migrationId, migrationDigest, migrationRevision, `${fieldName}.consumerQuiesceEvidence.request`);
|
|
1366
|
+
if (quiesceEvidence.acceptedMigrationRevision > migrationRevision ||
|
|
1367
|
+
quiesceEvidence.request.sourceRecordRevision !==
|
|
1368
|
+
source.fencedSnapshot.recordRevision ||
|
|
1369
|
+
quiesceEvidence.request.sourceControlSnapshotDigest !==
|
|
1370
|
+
source.fencedSnapshot.snapshotDigest ||
|
|
1371
|
+
quiesceEvidence.request.candidateDigest !== candidateDigest ||
|
|
1372
|
+
quiesceEvidence.request.workloadGeneration !== workloadGeneration ||
|
|
1373
|
+
quiesceEvidence.acceptedAt < createdAt ||
|
|
1374
|
+
quiesceEvidence.acceptedAt > updatedAt) {
|
|
1375
|
+
return fail(`${fieldName}.consumerQuiesceEvidence does not match status`);
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1378
|
+
let activeBinding;
|
|
1379
|
+
let activeBindingDigest;
|
|
1380
|
+
if (Object.hasOwn(value, 'activeBinding')) {
|
|
1381
|
+
activeBinding = normalizeObjectStorageBinding(value.activeBinding, 'ready', `${fieldName}.activeBinding`);
|
|
1382
|
+
activeBindingDigest = readSha256(value.activeBindingDigest, `${fieldName}.activeBindingDigest`);
|
|
1383
|
+
const recomputedActiveDigest = await createObjectStorageMigrationBindingSha256(activeBinding);
|
|
1384
|
+
if (activeBindingDigest !== recomputedActiveDigest) {
|
|
1385
|
+
return fail(`${fieldName}.activeBindingDigest does not match activeBinding`);
|
|
1386
|
+
}
|
|
1387
|
+
if (phase === 'aborted') {
|
|
1388
|
+
if (canonicalize(activeBinding) !== canonicalize(sourceBinding)) {
|
|
1389
|
+
return fail(`${fieldName}.activeBinding must be the exact source binding after abort`);
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
else {
|
|
1393
|
+
if (!candidateBinding) {
|
|
1394
|
+
return fail(`${fieldName}.activeBinding requires candidateBinding`);
|
|
1395
|
+
}
|
|
1396
|
+
assertActiveMatchesCandidate(activeBinding, candidateBinding, `${fieldName}.activeBinding`);
|
|
1397
|
+
}
|
|
1398
|
+
}
|
|
1399
|
+
const activationEvidence = Object.hasOwn(value, 'consumerActivationEvidence')
|
|
1400
|
+
? await normalizeActivationEvidence(value.consumerActivationEvidence, `${fieldName}.consumerActivationEvidence`)
|
|
1401
|
+
: undefined;
|
|
1402
|
+
if (activationEvidence) {
|
|
1403
|
+
assertEvidenceFence(activationEvidence.request, migrationId, migrationDigest, migrationRevision, `${fieldName}.consumerActivationEvidence.request`);
|
|
1404
|
+
if (activationEvidence.acceptedMigrationRevision > migrationRevision ||
|
|
1405
|
+
activationEvidence.request.candidateDigest !== candidateDigest ||
|
|
1406
|
+
activationEvidence.request.activeBindingDigest !== activeBindingDigest ||
|
|
1407
|
+
activationEvidence.request.workloadGeneration !== workloadGeneration ||
|
|
1408
|
+
!quiesceEvidence ||
|
|
1409
|
+
activationEvidence.request.expectedMigrationRevision <
|
|
1410
|
+
quiesceEvidence.acceptedMigrationRevision ||
|
|
1411
|
+
activationEvidence.request.consumerStartedAt <
|
|
1412
|
+
quiesceEvidence.acceptedAt ||
|
|
1413
|
+
activationEvidence.acceptedAt < createdAt ||
|
|
1414
|
+
activationEvidence.acceptedAt > updatedAt) {
|
|
1415
|
+
return fail(`${fieldName}.consumerActivationEvidence does not match status`);
|
|
1416
|
+
}
|
|
1417
|
+
}
|
|
1418
|
+
const terminalAt = Object.hasOwn(value, 'terminalAt')
|
|
1419
|
+
? readSafeInteger(value.terminalAt, `${fieldName}.terminalAt`, createdAt)
|
|
1420
|
+
: undefined;
|
|
1421
|
+
if (terminalAt !== undefined && terminalAt > updatedAt) {
|
|
1422
|
+
return fail(`${fieldName}.terminalAt must not exceed updatedAt`);
|
|
1423
|
+
}
|
|
1424
|
+
const normalized = {
|
|
1425
|
+
schemaVersion: 1,
|
|
1426
|
+
migrationId,
|
|
1427
|
+
migrationDigest,
|
|
1428
|
+
migrationRevision,
|
|
1429
|
+
bindingId,
|
|
1430
|
+
serviceId,
|
|
1431
|
+
requestId,
|
|
1432
|
+
workloadGeneration,
|
|
1433
|
+
target,
|
|
1434
|
+
source,
|
|
1435
|
+
...(progress ? { progress } : {}),
|
|
1436
|
+
createdAt,
|
|
1437
|
+
updatedAt,
|
|
1438
|
+
phase,
|
|
1439
|
+
bindingFenceActive: expected[0],
|
|
1440
|
+
candidateIssued: expected[1],
|
|
1441
|
+
...(candidateBinding ? { candidateBinding } : {}),
|
|
1442
|
+
...(candidateDigest ? { candidateDigest } : {}),
|
|
1443
|
+
...(quiesceEvidence ? { consumerQuiesceEvidence: quiesceEvidence } : {}),
|
|
1444
|
+
...(activationEvidence
|
|
1445
|
+
? { consumerActivationEvidence: activationEvidence }
|
|
1446
|
+
: {}),
|
|
1447
|
+
commitPointCrossed: expected[2],
|
|
1448
|
+
destinationBindingStartAuthorized: expected[3],
|
|
1449
|
+
authority: expected[4],
|
|
1450
|
+
consumerAction: expected[5],
|
|
1451
|
+
...(activeBinding ? { activeBinding } : {}),
|
|
1452
|
+
...(activeBindingDigest ? { activeBindingDigest } : {}),
|
|
1453
|
+
...(terminalAt !== undefined ? { terminalAt } : {}),
|
|
1454
|
+
...(issue ? { issue } : {}),
|
|
1455
|
+
};
|
|
1456
|
+
return assertControlJsonLimit(normalized, fieldName);
|
|
1457
|
+
};
|
|
1458
|
+
const assertCurrentMutationFence = (requestArg, statusArg, fieldNameArg) => {
|
|
1459
|
+
if (requestArg.migrationId !== statusArg.migrationId ||
|
|
1460
|
+
requestArg.migrationDigest !== statusArg.migrationDigest) {
|
|
1461
|
+
fail(`${fieldNameArg} does not match current migration identity`);
|
|
1462
|
+
}
|
|
1463
|
+
if (requestArg.expectedMigrationRevision !== statusArg.migrationRevision) {
|
|
1464
|
+
fail(`${fieldNameArg}.expectedMigrationRevision is stale`);
|
|
1465
|
+
}
|
|
1466
|
+
};
|
|
1467
|
+
export const bindObjectStorageMigrationConsumerQuiesceRequest = async (requestArg, statusArg) => {
|
|
1468
|
+
const request = await normalizeObjectStorageMigrationConsumerQuiesceRequest(requestArg);
|
|
1469
|
+
const status = await normalizeObjectStorageMigrationStatus(statusArg);
|
|
1470
|
+
if (status.phase !== 'awaitingConsumerQuiesce') {
|
|
1471
|
+
return fail('consumer quiesce request is accepted only while awaiting consumer quiescence');
|
|
1472
|
+
}
|
|
1473
|
+
assertCurrentMutationFence(request, status, 'consumer quiesce request');
|
|
1474
|
+
if (request.sourceRecordRevision !== status.source.fencedSnapshot.recordRevision ||
|
|
1475
|
+
request.sourceControlSnapshotDigest !==
|
|
1476
|
+
status.source.fencedSnapshot.snapshotDigest ||
|
|
1477
|
+
request.candidateDigest !== status.candidateDigest ||
|
|
1478
|
+
request.workloadGeneration !== status.workloadGeneration) {
|
|
1479
|
+
return fail('consumer quiesce request does not match the current fences');
|
|
1480
|
+
}
|
|
1481
|
+
return request;
|
|
1482
|
+
};
|
|
1483
|
+
export const bindObjectStorageMigrationConsumerActivationRequest = async (requestArg, statusArg) => {
|
|
1484
|
+
const request = await normalizeObjectStorageMigrationConsumerActivationRequest(requestArg);
|
|
1485
|
+
const status = await normalizeObjectStorageMigrationStatus(statusArg);
|
|
1486
|
+
if (status.phase !== 'readyToStart' ||
|
|
1487
|
+
status.consumerAction !== 'startDestination' ||
|
|
1488
|
+
status.destinationBindingStartAuthorized !== true) {
|
|
1489
|
+
return fail('consumer activation request is accepted only for an authorized ready-to-start destination');
|
|
1490
|
+
}
|
|
1491
|
+
assertCurrentMutationFence(request, status, 'consumer activation request');
|
|
1492
|
+
if (request.candidateDigest !== status.candidateDigest ||
|
|
1493
|
+
request.activeBindingDigest !== status.activeBindingDigest ||
|
|
1494
|
+
request.workloadGeneration !== status.workloadGeneration ||
|
|
1495
|
+
request.consumerStartedAt <
|
|
1496
|
+
status.consumerQuiesceEvidence.request.consumerStoppedAt) {
|
|
1497
|
+
return fail('consumer activation request does not match destination fences');
|
|
1498
|
+
}
|
|
1499
|
+
return request;
|
|
1500
|
+
};
|
|
1501
|
+
export const bindObjectStorageMigrationAbortRequest = async (requestArg, statusArg) => {
|
|
1502
|
+
const request = normalizeObjectStorageMigrationAbortRequest(requestArg);
|
|
1503
|
+
const status = await normalizeObjectStorageMigrationStatus(statusArg);
|
|
1504
|
+
if (status.bindingFenceActive !== true ||
|
|
1505
|
+
status.commitPointCrossed !== false ||
|
|
1506
|
+
![
|
|
1507
|
+
'preparing',
|
|
1508
|
+
'transferring',
|
|
1509
|
+
'awaitingConsumerQuiesce',
|
|
1510
|
+
'finalizing',
|
|
1511
|
+
'aborting',
|
|
1512
|
+
].includes(status.phase)) {
|
|
1513
|
+
return fail('abort request is forbidden after the migration commit point');
|
|
1514
|
+
}
|
|
1515
|
+
assertCurrentMutationFence(request, status, 'abort request');
|
|
1516
|
+
return request;
|
|
1517
|
+
};
|
|
1518
|
+
export const bindObjectStorageMigrationResumeRequest = async (requestArg, statusArg) => {
|
|
1519
|
+
const request = normalizeObjectStorageMigrationResumeRequest(requestArg);
|
|
1520
|
+
const status = await normalizeObjectStorageMigrationStatus(statusArg);
|
|
1521
|
+
if (status.bindingFenceActive !== true) {
|
|
1522
|
+
return fail('resume request requires a live nonterminal migration binding fence');
|
|
1523
|
+
}
|
|
1524
|
+
assertCurrentMutationFence(request, status, 'resume request');
|
|
1525
|
+
const issue = 'issue' in status ? status.issue : undefined;
|
|
1526
|
+
if (!issue) {
|
|
1527
|
+
return fail('resume request requires a current migration issue');
|
|
1528
|
+
}
|
|
1529
|
+
if (!issue.allowedRecoveryActions.some((actionArg) => actionArg === request.action)) {
|
|
1530
|
+
return fail('resume request action is not advertised by the current issue');
|
|
1531
|
+
}
|
|
1532
|
+
return request;
|
|
1533
|
+
};
|
|
1534
|
+
export const bindObjectStorageMigrationCleanupRequest = async (requestArg, statusArg) => {
|
|
1535
|
+
const request = normalizeObjectStorageMigrationCleanupRequest(requestArg);
|
|
1536
|
+
const status = await normalizeObjectStorageMigrationStatus(statusArg);
|
|
1537
|
+
if (status.phase !== 'cleanupPending' ||
|
|
1538
|
+
!status.consumerActivationEvidence) {
|
|
1539
|
+
return fail('cleanup request is accepted only after destination activation acknowledgement');
|
|
1540
|
+
}
|
|
1541
|
+
assertCurrentMutationFence(request, status, 'cleanup request');
|
|
1542
|
+
return request;
|
|
1543
|
+
};
|
|
1544
|
+
export const normalizeStorageMigrationProgress = (valueArg) => {
|
|
1545
|
+
return assertControlJsonLimit(normalizeProgress(valueArg, 'storage migration progress'), 'storage migration progress');
|
|
1546
|
+
};
|
|
1547
|
+
export const normalizeStorageMigrationPreCutoverIssue = (valueArg) => {
|
|
1548
|
+
return assertControlJsonLimit(normalizeIssue(valueArg, 'pre', 'storage migration pre-cutover issue'), 'storage migration pre-cutover issue');
|
|
1549
|
+
};
|
|
1550
|
+
export const normalizeStorageMigrationPostCutoverIssue = (valueArg) => {
|
|
1551
|
+
return assertControlJsonLimit(normalizeIssue(valueArg, 'post', 'storage migration post-cutover issue'), 'storage migration post-cutover issue');
|
|
1552
|
+
};
|
|
1553
|
+
export { storageMigrationCanonicalDigestGoldenVectors, } from './storagemigration.golden.js';
|
|
1554
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RvcmFnZW1pZ3JhdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL3BsYXRmb3JtL3N0b3JhZ2VtaWdyYXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBSUEsT0FBTyxFQUNMLHNCQUFzQixFQUN0Qiw0QkFBNEIsRUFDNUIsZUFBZSxFQUNmLHdCQUF3QixHQUN6QixNQUFNLDZCQUE2QixDQUFDO0FBUXJDLE1BQU0sQ0FBQyxNQUFNLDhCQUE4QixHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUM7SUFDMUQsT0FBTyxFQUFFLENBQVU7SUFDbkIsdUJBQXVCLEVBQUUsR0FBRyxHQUFHLElBQUk7SUFDbkMsNEJBQTRCLEVBQUUsSUFBSTtJQUNsQyx3QkFBd0IsRUFBRSxJQUFJO0lBQzlCLHVCQUF1QixFQUFFLElBQUk7SUFDN0IsMEJBQTBCLEVBQUUsR0FBRztJQUMvQixzQkFBc0IsRUFBRSxJQUFJO0NBQzdCLENBQUMsQ0FBQztBQUVILE1BQU0sQ0FBQyxNQUFNLGtDQUFrQyxHQUFHLHdCQUF3QixDQUFDO0FBRTNFLE1BQU0sT0FBTyw2QkFBOEIsU0FBUSxLQUFLO0lBQ3RELFlBQW1CLFNBQWlCO1FBQ2xDLEtBQUssQ0FBQyxxQ0FBcUMsU0FBUyxFQUFFLENBQUMsQ0FBQztRQUN4RCxJQUFJLENBQUMsSUFBSSxHQUFHLCtCQUErQixDQUFDO0lBQzlDLENBQUM7Q0FDRjtBQTJYRCxNQUFNLElBQUksR0FBRyxDQUFDLFNBQWlCLEVBQVMsRUFBRTtJQUN4QyxNQUFNLElBQUksNkJBQTZCLENBQUMsU0FBUyxDQUFDLENBQUM7QUFDckQsQ0FBQyxDQUFDO0FBRUYsTUFBTSxjQUFjLEdBQUcsQ0FBQyxRQUFnQixFQUFVLEVBQUU7SUFDbEQsT0FBTyxJQUFJLFdBQVcsRUFBRSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxVQUFVLENBQUM7QUFDdkQsQ0FBQyxDQUFDO0FBRUY7OztHQUdHO0FBQ0gsTUFBTSxDQUFDLE1BQU0s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
|