@serve.zone/interfaces 32.1.0 → 32.2.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,40 @@
1
+ /**
2
+ * The readers a storage control body is judged by, and the one normalizer that turns a storage
3
+ * request into the exact value its digest is taken over.
4
+ *
5
+ * Two modules judge the same bytes in their own error vocabulary — `platform/storage.ts` for a
6
+ * storage request on its own and `platform/storagemigration.ts` for the migration control plane
7
+ * that carries one — so the rules take the failure they report through. A second copy of them
8
+ * would be a second answer to what a request is, and a request digest that a control plane issues
9
+ * and a consumer re-derives would stop being one value.
10
+ */
11
+ import type { IAppStoreFilesystemStorageRequest, IAppStoreObjectStorageRequest, TAppStoreStorageRequest } from '../appstore/types.js';
12
+ import type { TObjectStorageDelivery } from '../platform/storage.js';
13
+ import type { TCanonicalJsonFailure } from './canonicaljson.js';
14
+ /** Byte bounds every reader of a storage control string applies. */
15
+ export declare const storageContractStringLimits: Readonly<{
16
+ maximumConfiguredStringBytes: 2048;
17
+ maximumEnvironmentKeyBytes: 256;
18
+ maximumSecretPathBytes: 2048;
19
+ }>;
20
+ export declare const createStorageContractReaders: (failArg: TCanonicalJsonFailure) => {
21
+ utf8ByteLength: (valueArg: string) => number;
22
+ readRecord: (valueArg: unknown, fieldNameArg: string) => Record<string, unknown>;
23
+ readDenseArray: (valueArg: unknown, fieldNameArg: string, minimumLengthArg: number, maximumLengthArg: number) => unknown[];
24
+ assertKeys: (recordArg: Record<string, unknown>, requiredKeysArg: readonly string[], optionalKeysArg: readonly string[], fieldNameArg: string) => void;
25
+ assertExactKeys: (recordArg: Record<string, unknown>, expectedKeysArg: readonly string[], fieldNameArg: string) => void;
26
+ readString: (valueArg: unknown, fieldNameArg: string, maximumBytesArg?: number) => string;
27
+ readIdentifier: (valueArg: unknown, fieldNameArg: string) => string;
28
+ readSha256: (valueArg: unknown, fieldNameArg: string) => string;
29
+ readSafeInteger: (valueArg: unknown, fieldNameArg: string, minimumArg: number, maximumArg?: number) => number;
30
+ readBoolean: (valueArg: unknown, fieldNameArg: string) => boolean;
31
+ readLiteral: <TLiteral extends string>(valueArg: unknown, allowedArg: readonly TLiteral[], fieldNameArg: string) => TLiteral;
32
+ readCapacityQuantity: (valueArg: unknown, fieldNameArg: string) => string;
33
+ capacityQuantityBytes: (valueArg: string) => bigint;
34
+ readEnvironmentKey: (valueArg: unknown, fieldNameArg: string) => string;
35
+ normalizeCapacityRequest: (valueArg: unknown, fieldNameArg: string) => NonNullable<TAppStoreStorageRequest["capacity"]>;
36
+ normalizeDelivery: (valueArg: unknown, fieldNameArg: string) => TObjectStorageDelivery;
37
+ normalizeObjectStorageRequest: (valueArg: unknown, fieldNameArg: string) => IAppStoreObjectStorageRequest;
38
+ normalizeFilesystemStorageRequest: (valueArg: unknown, fieldNameArg: string) => IAppStoreFilesystemStorageRequest;
39
+ normalizeStorageRequest: (valueArg: unknown, fieldNameArg: string) => TAppStoreStorageRequest;
40
+ };
@@ -0,0 +1,399 @@
1
+ import { normalizeServiceAbsolutePath } from '../data/service.js';
2
+ /** Byte bounds every reader of a storage control string applies. */
3
+ export const storageContractStringLimits = Object.freeze({
4
+ maximumConfiguredStringBytes: 2048,
5
+ maximumEnvironmentKeyBytes: 256,
6
+ maximumSecretPathBytes: 2048,
7
+ });
8
+ const canonicalIdPattern = /^[A-Za-z0-9][A-Za-z0-9._:@-]{0,191}$/;
9
+ const environmentKeyPattern = /^[A-Z_][A-Z0-9_]{0,255}$/;
10
+ const sha256Pattern = /^[a-f0-9]{64}$/;
11
+ const capacityPattern = /^[1-9][0-9]*(?:KiB|MiB|GiB|TiB)$/;
12
+ /**
13
+ * The mount a Secret file is delivered under. A filesystem request that mounts it, or anything
14
+ * containing it, would shadow every credential the platform writes for the same service.
15
+ */
16
+ const secretDeliveryRoot = '/run/secrets';
17
+ export const createStorageContractReaders = (failArg) => {
18
+ const utf8ByteLength = (valueArg) => {
19
+ return new TextEncoder().encode(valueArg).byteLength;
20
+ };
21
+ const readRecord = (valueArg, fieldNameArg) => {
22
+ if (!valueArg || typeof valueArg !== 'object' || Array.isArray(valueArg)) {
23
+ return failArg(`${fieldNameArg} must be a plain object`);
24
+ }
25
+ const prototype = Object.getPrototypeOf(valueArg);
26
+ if (prototype !== Object.prototype && prototype !== null) {
27
+ return failArg(`${fieldNameArg} must be a plain object`);
28
+ }
29
+ const record = valueArg;
30
+ const ownKeys = Reflect.ownKeys(record);
31
+ if (ownKeys.some((keyArg) => typeof keyArg !== 'string')) {
32
+ return failArg(`${fieldNameArg} must not contain symbol keys`);
33
+ }
34
+ for (const key of ownKeys) {
35
+ const descriptor = Object.getOwnPropertyDescriptor(record, key);
36
+ if (!descriptor ||
37
+ !descriptor.enumerable ||
38
+ !Object.hasOwn(descriptor, 'value') ||
39
+ descriptor.value === undefined) {
40
+ return failArg(`${fieldNameArg} must contain enumerable JSON data properties only`);
41
+ }
42
+ }
43
+ return record;
44
+ };
45
+ const readDenseArray = (valueArg, fieldNameArg, minimumLengthArg, maximumLengthArg) => {
46
+ if (!Array.isArray(valueArg) ||
47
+ Object.getPrototypeOf(valueArg) !== Array.prototype) {
48
+ return failArg(`${fieldNameArg} must be a dense plain array`);
49
+ }
50
+ if (valueArg.length < minimumLengthArg ||
51
+ valueArg.length > maximumLengthArg) {
52
+ return failArg(`${fieldNameArg} must contain between ${minimumLengthArg} and ${maximumLengthArg} entries`);
53
+ }
54
+ for (let index = 0; index < valueArg.length; index++) {
55
+ if (!Object.hasOwn(valueArg, index)) {
56
+ return failArg(`${fieldNameArg} must not contain sparse entries`);
57
+ }
58
+ const descriptor = Object.getOwnPropertyDescriptor(valueArg, String(index));
59
+ if (!descriptor ||
60
+ !descriptor.enumerable ||
61
+ !Object.hasOwn(descriptor, 'value') ||
62
+ descriptor.value === undefined) {
63
+ return failArg(`${fieldNameArg} must contain enumerable JSON data entries only`);
64
+ }
65
+ }
66
+ for (const key of Reflect.ownKeys(valueArg)) {
67
+ if (key === 'length')
68
+ continue;
69
+ if (typeof key !== 'string' ||
70
+ !/^(?:0|[1-9][0-9]*)$/.test(key) ||
71
+ Number(key) >= valueArg.length) {
72
+ return failArg(`${fieldNameArg} must not contain extra properties`);
73
+ }
74
+ }
75
+ return valueArg;
76
+ };
77
+ const assertKeys = (recordArg, requiredKeysArg, optionalKeysArg, fieldNameArg) => {
78
+ const actualKeys = Object.keys(recordArg).sort();
79
+ const allowedKeys = new Set([...requiredKeysArg, ...optionalKeysArg]);
80
+ if (requiredKeysArg.some((keyArg) => !Object.hasOwn(recordArg, keyArg)) ||
81
+ actualKeys.some((keyArg) => !allowedKeys.has(keyArg))) {
82
+ failArg(`${fieldNameArg} does not match its exact schema`);
83
+ }
84
+ };
85
+ const assertExactKeys = (recordArg, expectedKeysArg, fieldNameArg) => {
86
+ assertKeys(recordArg, expectedKeysArg, [], fieldNameArg);
87
+ };
88
+ const readString = (valueArg, fieldNameArg, maximumBytesArg = storageContractStringLimits.maximumConfiguredStringBytes) => {
89
+ if (typeof valueArg !== 'string' ||
90
+ valueArg.length === 0 ||
91
+ utf8ByteLength(valueArg) > maximumBytesArg ||
92
+ /[\u0000-\u001f\u007f]/u.test(valueArg)) {
93
+ return failArg(`${fieldNameArg} must be a bounded non-empty JSON string`);
94
+ }
95
+ for (let index = 0; index < valueArg.length; index++) {
96
+ const codeUnit = valueArg.charCodeAt(index);
97
+ if (codeUnit >= 0xd800 && codeUnit <= 0xdbff) {
98
+ const following = valueArg.charCodeAt(index + 1);
99
+ if (following < 0xdc00 || following > 0xdfff) {
100
+ return failArg(`${fieldNameArg} contains an unpaired UTF-16 surrogate`);
101
+ }
102
+ index++;
103
+ }
104
+ else if (codeUnit >= 0xdc00 && codeUnit <= 0xdfff) {
105
+ return failArg(`${fieldNameArg} contains an unpaired UTF-16 surrogate`);
106
+ }
107
+ }
108
+ return valueArg;
109
+ };
110
+ const readIdentifier = (valueArg, fieldNameArg) => {
111
+ if (typeof valueArg !== 'string' || !canonicalIdPattern.test(valueArg)) {
112
+ return failArg(`${fieldNameArg} must be a canonical identifier`);
113
+ }
114
+ return valueArg;
115
+ };
116
+ const readSha256 = (valueArg, fieldNameArg) => {
117
+ if (typeof valueArg !== 'string' || !sha256Pattern.test(valueArg)) {
118
+ return failArg(`${fieldNameArg} must be a bare lowercase 64-hex SHA-256 digest`);
119
+ }
120
+ return valueArg;
121
+ };
122
+ const readSafeInteger = (valueArg, fieldNameArg, minimumArg, maximumArg = Number.MAX_SAFE_INTEGER) => {
123
+ if (typeof valueArg !== 'number' ||
124
+ !Number.isSafeInteger(valueArg) ||
125
+ Object.is(valueArg, -0) ||
126
+ valueArg < minimumArg ||
127
+ valueArg > maximumArg) {
128
+ return failArg(`${fieldNameArg} must be a safe integer between ${minimumArg} and ${maximumArg}`);
129
+ }
130
+ return valueArg;
131
+ };
132
+ const readBoolean = (valueArg, fieldNameArg) => {
133
+ if (typeof valueArg !== 'boolean') {
134
+ return failArg(`${fieldNameArg} must be a boolean`);
135
+ }
136
+ return valueArg;
137
+ };
138
+ const readLiteral = (valueArg, allowedArg, fieldNameArg) => {
139
+ if (typeof valueArg !== 'string' ||
140
+ !allowedArg.includes(valueArg)) {
141
+ return failArg(`${fieldNameArg} is outside the supported values`);
142
+ }
143
+ return valueArg;
144
+ };
145
+ const readCapacityQuantity = (valueArg, fieldNameArg) => {
146
+ if (typeof valueArg !== 'string' || !capacityPattern.test(valueArg)) {
147
+ return failArg(`${fieldNameArg} must be a canonical base-2 capacity quantity`);
148
+ }
149
+ const numericPart = valueArg.replace(/(?:KiB|MiB|GiB|TiB)$/, '');
150
+ if (!Number.isSafeInteger(Number(numericPart))) {
151
+ return failArg(`${fieldNameArg} exceeds the safe integer quantity range`);
152
+ }
153
+ return valueArg;
154
+ };
155
+ const capacityQuantityBytes = (valueArg) => {
156
+ const units = {
157
+ KiB: 1024n,
158
+ MiB: 1024n ** 2n,
159
+ GiB: 1024n ** 3n,
160
+ TiB: 1024n ** 4n,
161
+ };
162
+ const unit = valueArg.slice(-3);
163
+ return BigInt(valueArg.slice(0, -3)) * units[unit];
164
+ };
165
+ const normalizeCapacityRequest = (valueArg, fieldNameArg) => {
166
+ const value = readRecord(valueArg, fieldNameArg);
167
+ assertKeys(value, ['request'], ['limit'], fieldNameArg);
168
+ const request = readCapacityQuantity(value.request, `${fieldNameArg}.request`);
169
+ const limit = Object.hasOwn(value, 'limit')
170
+ ? readCapacityQuantity(value.limit, `${fieldNameArg}.limit`)
171
+ : undefined;
172
+ if (limit && capacityQuantityBytes(limit) < capacityQuantityBytes(request)) {
173
+ return failArg(`${fieldNameArg}.limit must be at least request`);
174
+ }
175
+ return {
176
+ request,
177
+ ...(limit ? { limit } : {}),
178
+ };
179
+ };
180
+ const readEnvironmentKey = (valueArg, fieldNameArg) => {
181
+ if (typeof valueArg !== 'string' ||
182
+ utf8ByteLength(valueArg) >
183
+ storageContractStringLimits.maximumEnvironmentKeyBytes ||
184
+ !environmentKeyPattern.test(valueArg)) {
185
+ return failArg(`${fieldNameArg} must be a canonical environment key`);
186
+ }
187
+ return valueArg;
188
+ };
189
+ const normalizeDelivery = (valueArg, fieldNameArg) => {
190
+ const value = readRecord(valueArg, fieldNameArg);
191
+ if (value.type === 'launcher-environment') {
192
+ assertExactKeys(value, ['type', 'keys'], fieldNameArg);
193
+ const keys = readRecord(value.keys, `${fieldNameArg}.keys`);
194
+ assertKeys(keys, ['endpoint', 'bucket', 'region', 'accessKeyId', 'secretAccessKey'], ['sessionToken'], `${fieldNameArg}.keys`);
195
+ const normalizedKeys = {
196
+ endpoint: readEnvironmentKey(keys.endpoint, `${fieldNameArg}.keys.endpoint`),
197
+ bucket: readEnvironmentKey(keys.bucket, `${fieldNameArg}.keys.bucket`),
198
+ region: readEnvironmentKey(keys.region, `${fieldNameArg}.keys.region`),
199
+ accessKeyId: readEnvironmentKey(keys.accessKeyId, `${fieldNameArg}.keys.accessKeyId`),
200
+ secretAccessKey: readEnvironmentKey(keys.secretAccessKey, `${fieldNameArg}.keys.secretAccessKey`),
201
+ ...(Object.hasOwn(keys, 'sessionToken')
202
+ ? {
203
+ sessionToken: readEnvironmentKey(keys.sessionToken, `${fieldNameArg}.keys.sessionToken`),
204
+ }
205
+ : {}),
206
+ };
207
+ if (new Set(Object.values(normalizedKeys)).size !==
208
+ Object.keys(normalizedKeys).length) {
209
+ return failArg(`${fieldNameArg}.keys values must be distinct`);
210
+ }
211
+ return { type: 'launcher-environment', keys: normalizedKeys };
212
+ }
213
+ if (value.type === 'file') {
214
+ assertExactKeys(value, ['type', 'targetPath', 'format', 'uid', 'gid', 'mode'], fieldNameArg);
215
+ const targetPath = readString(value.targetPath, `${fieldNameArg}.targetPath`, storageContractStringLimits.maximumSecretPathBytes);
216
+ if (!targetPath.startsWith(`${secretDeliveryRoot}/`) ||
217
+ targetPath.includes('\\') ||
218
+ targetPath.split('/').some((segmentArg) => segmentArg === '.' || segmentArg === '..')) {
219
+ return failArg(`${fieldNameArg}.targetPath must be a canonical path below ${secretDeliveryRoot}`);
220
+ }
221
+ if (value.format !== 'servezone-object-storage') {
222
+ return failArg(`${fieldNameArg}.format is unsupported`);
223
+ }
224
+ return {
225
+ type: 'file',
226
+ targetPath,
227
+ format: 'servezone-object-storage',
228
+ uid: readSafeInteger(value.uid, `${fieldNameArg}.uid`, 0, 2_147_483_647),
229
+ gid: readSafeInteger(value.gid, `${fieldNameArg}.gid`, 0, 2_147_483_647),
230
+ mode: value.mode === 0o400 || value.mode === 0o440
231
+ ? value.mode
232
+ : failArg(`${fieldNameArg}.mode must be 0400 or 0440`),
233
+ };
234
+ }
235
+ return failArg(`${fieldNameArg}.type is unsupported`);
236
+ };
237
+ const normalizeObjectStorageProtection = (valueArg, fieldNameArg) => {
238
+ const value = readRecord(valueArg, fieldNameArg);
239
+ assertKeys(value, [], ['backup', 'versioning', 'retentionDays'], fieldNameArg);
240
+ if (Object.keys(value).length === 0) {
241
+ return failArg(`${fieldNameArg} must not be empty`);
242
+ }
243
+ return {
244
+ ...(Object.hasOwn(value, 'backup')
245
+ ? {
246
+ backup: value.backup === 'required'
247
+ ? 'required'
248
+ : failArg(`${fieldNameArg}.backup must be required`),
249
+ }
250
+ : {}),
251
+ ...(Object.hasOwn(value, 'versioning')
252
+ ? {
253
+ versioning: value.versioning === 'required'
254
+ ? 'required'
255
+ : failArg(`${fieldNameArg}.versioning must be required`),
256
+ }
257
+ : {}),
258
+ ...(Object.hasOwn(value, 'retentionDays')
259
+ ? {
260
+ retentionDays: readSafeInteger(value.retentionDays, `${fieldNameArg}.retentionDays`, 1, 365_000),
261
+ }
262
+ : {}),
263
+ };
264
+ };
265
+ const normalizeFilesystemProtection = (valueArg, fieldNameArg) => {
266
+ const value = readRecord(valueArg, fieldNameArg);
267
+ assertKeys(value, [], ['backup', 'snapshots', 'consistency'], fieldNameArg);
268
+ if (Object.keys(value).length === 0) {
269
+ return failArg(`${fieldNameArg} must not be empty`);
270
+ }
271
+ return {
272
+ ...(Object.hasOwn(value, 'backup')
273
+ ? {
274
+ backup: value.backup === 'required'
275
+ ? 'required'
276
+ : failArg(`${fieldNameArg}.backup must be required`),
277
+ }
278
+ : {}),
279
+ ...(Object.hasOwn(value, 'snapshots')
280
+ ? {
281
+ snapshots: readLiteral(value.snapshots, ['portable', 'native'], `${fieldNameArg}.snapshots`),
282
+ }
283
+ : {}),
284
+ ...(Object.hasOwn(value, 'consistency')
285
+ ? {
286
+ consistency: readLiteral(value.consistency, ['crashConsistent', 'applicationConsistent'], `${fieldNameArg}.consistency`),
287
+ }
288
+ : {}),
289
+ };
290
+ };
291
+ const readMountPath = (valueArg, fieldNameArg) => {
292
+ const value = readString(valueArg, fieldNameArg, storageContractStringLimits.maximumSecretPathBytes);
293
+ if (normalizeServiceAbsolutePath(value) !== value || value === '/') {
294
+ return failArg(`${fieldNameArg} must be a canonical non-root absolute path`);
295
+ }
296
+ if (value === secretDeliveryRoot ||
297
+ value.startsWith(`${secretDeliveryRoot}/`) ||
298
+ secretDeliveryRoot.startsWith(`${value}/`)) {
299
+ return failArg(`${fieldNameArg} must not overlap ${secretDeliveryRoot}`);
300
+ }
301
+ return value;
302
+ };
303
+ const normalizeObjectStorageRequest = (valueArg, fieldNameArg) => {
304
+ const value = readRecord(valueArg, fieldNameArg);
305
+ assertKeys(value, [
306
+ 'id',
307
+ 'kind',
308
+ 'storageClass',
309
+ 'accessMode',
310
+ 'reclaimPolicy',
311
+ 'delivery',
312
+ ], ['capacity', 'protection'], fieldNameArg);
313
+ if (value.kind !== 'objectStorage') {
314
+ return failArg(`${fieldNameArg}.kind must be objectStorage`);
315
+ }
316
+ return {
317
+ id: readIdentifier(value.id, `${fieldNameArg}.id`),
318
+ kind: 'objectStorage',
319
+ storageClass: readIdentifier(value.storageClass, `${fieldNameArg}.storageClass`),
320
+ accessMode: readLiteral(value.accessMode, ['readOnly', 'readWrite'], `${fieldNameArg}.accessMode`),
321
+ reclaimPolicy: readLiteral(value.reclaimPolicy, ['retain', 'delete'], `${fieldNameArg}.reclaimPolicy`),
322
+ delivery: normalizeDelivery(value.delivery, `${fieldNameArg}.delivery`),
323
+ ...(Object.hasOwn(value, 'capacity')
324
+ ? {
325
+ capacity: normalizeCapacityRequest(value.capacity, `${fieldNameArg}.capacity`),
326
+ }
327
+ : {}),
328
+ ...(Object.hasOwn(value, 'protection')
329
+ ? {
330
+ protection: normalizeObjectStorageProtection(value.protection, `${fieldNameArg}.protection`),
331
+ }
332
+ : {}),
333
+ };
334
+ };
335
+ const normalizeFilesystemStorageRequest = (valueArg, fieldNameArg) => {
336
+ const value = readRecord(valueArg, fieldNameArg);
337
+ assertKeys(value, [
338
+ 'id',
339
+ 'kind',
340
+ 'storageClass',
341
+ 'accessMode',
342
+ 'reclaimPolicy',
343
+ 'mountPath',
344
+ ], ['capacity', 'protection'], fieldNameArg);
345
+ if (value.kind !== 'filesystem') {
346
+ return failArg(`${fieldNameArg}.kind must be filesystem`);
347
+ }
348
+ return {
349
+ id: readIdentifier(value.id, `${fieldNameArg}.id`),
350
+ kind: 'filesystem',
351
+ storageClass: readIdentifier(value.storageClass, `${fieldNameArg}.storageClass`),
352
+ accessMode: readLiteral(value.accessMode, ['ReadWriteOnce', 'ReadOnlyMany', 'ReadWriteMany'], `${fieldNameArg}.accessMode`),
353
+ reclaimPolicy: readLiteral(value.reclaimPolicy, ['retain', 'delete'], `${fieldNameArg}.reclaimPolicy`),
354
+ mountPath: readMountPath(value.mountPath, `${fieldNameArg}.mountPath`),
355
+ ...(Object.hasOwn(value, 'capacity')
356
+ ? {
357
+ capacity: normalizeCapacityRequest(value.capacity, `${fieldNameArg}.capacity`),
358
+ }
359
+ : {}),
360
+ ...(Object.hasOwn(value, 'protection')
361
+ ? {
362
+ protection: normalizeFilesystemProtection(value.protection, `${fieldNameArg}.protection`),
363
+ }
364
+ : {}),
365
+ };
366
+ };
367
+ const normalizeStorageRequest = (valueArg, fieldNameArg) => {
368
+ const value = readRecord(valueArg, fieldNameArg);
369
+ if (value.kind === 'filesystem') {
370
+ return normalizeFilesystemStorageRequest(value, fieldNameArg);
371
+ }
372
+ if (value.kind === 'objectStorage') {
373
+ return normalizeObjectStorageRequest(value, fieldNameArg);
374
+ }
375
+ return failArg(`${fieldNameArg}.kind must be filesystem or objectStorage`);
376
+ };
377
+ return {
378
+ utf8ByteLength,
379
+ readRecord,
380
+ readDenseArray,
381
+ assertKeys,
382
+ assertExactKeys,
383
+ readString,
384
+ readIdentifier,
385
+ readSha256,
386
+ readSafeInteger,
387
+ readBoolean,
388
+ readLiteral,
389
+ readCapacityQuantity,
390
+ capacityQuantityBytes,
391
+ readEnvironmentKey,
392
+ normalizeCapacityRequest,
393
+ normalizeDelivery,
394
+ normalizeObjectStorageRequest,
395
+ normalizeFilesystemStorageRequest,
396
+ normalizeStorageRequest,
397
+ };
398
+ };
399
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RvcmFnZWNvbnRyYWN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvcHJpdmF0ZS9zdG9yYWdlY29udHJhY3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBZUEsT0FBTyxFQUFFLDRCQUE0QixFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFJbEUsb0VBQW9FO0FBQ3BFLE1BQU0sQ0FBQyxNQUFNLDJCQUEyQixHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUM7SUFDdkQsNEJBQTRCLEVBQUUsSUFBSTtJQUNsQywwQkFBMEIsRUFBRSxHQUFHO0lBQy9CLHNCQUFzQixFQUFFLElBQUk7Q0FDN0IsQ0FBQyxDQUFDO0FBRUgsTUFBTSxrQkFBa0IsR0FBRyxzQ0FBc0MsQ0FBQztBQUNsRSxNQUFNLHFCQUFxQixHQUFHLDBCQUEwQixDQUFDO0FBQ3pELE1BQU0sYUFBYSxHQUFHLGdCQUFnQixDQUFDO0FBQ3ZDLE1BQU0sZUFBZSxHQUFHLGtDQUFrQyxDQUFDO0FBQzNEOzs7R0FHRztBQUNILE1BQU0sa0JBQWtCLEdBQUcsY0FBYyxDQUFDO0FBRTFDLE1BQU0sQ0FBQyxNQUFNLDRCQUE0QixHQUFHLENBQUMsT0FBOEIsRUFBRSxFQUFFO0lBQzdFLE1BQU0sY0FBYyxHQUFHLENBQUMsUUFBZ0IsRUFBVSxFQUFFO1FBQ2xELE9BQU8sSUFBSSxXQUFXLEVBQUUsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUMsVUFBVSxDQUFDO0lBQ3ZELENBQUMsQ0FBQztJQUVGLE1BQU0sVUFBVSxHQUFHLENBQ2pCLFFBQWlCLEVBQ2pCLFlBQW9CLEVBQ0ssRUFBRTtRQUMzQixJQUFJLENBQUMsUUFBUSxJQUFJLE9BQU8sUUFBUSxLQUFLLFFBQVEsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUM7WUFDekUsT0FBTyxPQUFPLENBQUMsR0FBRyxZQUFZLHlCQUF5QixDQUFDLENBQUM7UUFDM0QsQ0FBQztRQUNELE1BQU0sU0FB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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@serve.zone/interfaces",
3
- "version": "32.1.0",
3
+ "version": "32.2.0",
4
4
  "private": false,
5
5
  "description": "Shared TypeScript interfaces and TypedRequest contracts for the serve.zone ecosystem.",
6
6
  "exports": {
package/readme.md CHANGED
@@ -1293,6 +1293,21 @@ metadata plus a service-owned credential management scope and delivery policy,
1293
1293
  never credential references or values. Filesystem
1294
1294
  bindings expose the container mount and access mode, never a host path.
1295
1295
 
1296
+ A binding's `requestDigest` is stated by one function, so the control plane that
1297
+ issues it and the consumer that re-derives it compute the same value:
1298
+
1299
+ ```typescript
1300
+ const requestDigest = await platform.createStorageRequestSha256(storageRequest);
1301
+ ```
1302
+
1303
+ It normalizes the request to its contract shape, canonicalizes it and returns
1304
+ bare lowercase hex over the request alone — no prefix, and nothing wrapped
1305
+ around the request. A body that is not a storage request is refused with
1306
+ `platform.StorageContractError` instead of hashed, and
1307
+ `platform.canonicalizeStorageRequest` returns the exact bytes the digest is
1308
+ taken over. `platform.storageRequestCanonicalDigestGoldenVectors` states both
1309
+ for a filesystem request and for both object-storage deliveries.
1310
+
1296
1311
  Portable manifests and resolved bindings intentionally have no fields for
1297
1312
  Synology, NFS, Kerberos, Corestore, Kubernetes, Docker drivers, servers,
1298
1313
  exports, mount options, provider credential values, or local fallback paths. Runtimes
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@serve.zone/interfaces',
6
- version: '32.1.0',
6
+ version: '32.2.0',
7
7
  description: 'Shared TypeScript interfaces and TypedRequest contracts for the serve.zone ecosystem.'
8
8
  }
@@ -0,0 +1,97 @@
1
+ import type {
2
+ IAppStoreFilesystemStorageRequest,
3
+ IAppStoreObjectStorageRequest,
4
+ } from '../appstore/types.js';
5
+ import { deepFreezeValue } from '../private/canonicaljson.js';
6
+
7
+ export interface IStorageRequestCanonicalDigestGoldenVector<TInput> {
8
+ input: TInput;
9
+ canonicalJson: string;
10
+ sha256: string;
11
+ }
12
+
13
+ const filesystemRequest: IAppStoreFilesystemStorageRequest = {
14
+ id: 'app-state',
15
+ kind: 'filesystem',
16
+ storageClass: 'databaseFast',
17
+ accessMode: 'ReadWriteOnce',
18
+ reclaimPolicy: 'delete',
19
+ mountPath: '/var/lib/app',
20
+ capacity: {
21
+ request: '20GiB',
22
+ limit: '40GiB',
23
+ },
24
+ protection: {
25
+ backup: 'required',
26
+ snapshots: 'portable',
27
+ consistency: 'applicationConsistent',
28
+ },
29
+ };
30
+
31
+ const objectStorageLauncherEnvironmentRequest: IAppStoreObjectStorageRequest = {
32
+ id: 'object-data',
33
+ kind: 'objectStorage',
34
+ storageClass: 'backupCapacity',
35
+ accessMode: 'readWrite',
36
+ reclaimPolicy: 'retain',
37
+ delivery: {
38
+ type: 'launcher-environment',
39
+ keys: {
40
+ endpoint: 'APP_S3_ENDPOINT',
41
+ bucket: 'APP_S3_BUCKET',
42
+ region: 'APP_S3_REGION',
43
+ accessKeyId: 'APP_S3_ACCESS_KEY',
44
+ secretAccessKey: 'APP_S3_SECRET_KEY',
45
+ },
46
+ },
47
+ capacity: {
48
+ request: '500GiB',
49
+ },
50
+ protection: {
51
+ backup: 'required',
52
+ versioning: 'required',
53
+ retentionDays: 30,
54
+ },
55
+ };
56
+
57
+ const objectStorageFileRequest: IAppStoreObjectStorageRequest = {
58
+ id: 'object-archive',
59
+ kind: 'objectStorage',
60
+ storageClass: 'archiveCapacity',
61
+ accessMode: 'readOnly',
62
+ reclaimPolicy: 'delete',
63
+ delivery: {
64
+ type: 'file',
65
+ targetPath: '/run/secrets/object-archive.json',
66
+ format: 'servezone-object-storage',
67
+ uid: 10_000,
68
+ gid: 10_000,
69
+ mode: 0o400,
70
+ },
71
+ };
72
+
73
+ /**
74
+ * The storage request digest, written down for both kinds and both deliveries.
75
+ *
76
+ * A control plane and its consumer compare this value, so it is stated here as bytes rather than
77
+ * as whatever the current normalizer happens to produce: a member that starts or stops
78
+ * participating, an optional member that starts being carried when it is absent, or a delivery
79
+ * mode written as anything but its number would move these digests and be caught here.
80
+ */
81
+ export const storageRequestCanonicalDigestGoldenVectors = deepFreezeValue({
82
+ filesystem: {
83
+ input: filesystemRequest,
84
+ canonicalJson: '{"accessMode":"ReadWriteOnce","capacity":{"limit":"40GiB","request":"20GiB"},"id":"app-state","kind":"filesystem","mountPath":"/var/lib/app","protection":{"backup":"required","consistency":"applicationConsistent","snapshots":"portable"},"reclaimPolicy":"delete","storageClass":"databaseFast"}',
85
+ sha256: '0f8dc2e480ade7110be1f1d95f666cc56d5b90110d1c4a1b8b8383e2eeda6fae',
86
+ },
87
+ objectStorageLauncherEnvironment: {
88
+ input: objectStorageLauncherEnvironmentRequest,
89
+ canonicalJson: '{"accessMode":"readWrite","capacity":{"request":"500GiB"},"delivery":{"keys":{"accessKeyId":"APP_S3_ACCESS_KEY","bucket":"APP_S3_BUCKET","endpoint":"APP_S3_ENDPOINT","region":"APP_S3_REGION","secretAccessKey":"APP_S3_SECRET_KEY"},"type":"launcher-environment"},"id":"object-data","kind":"objectStorage","protection":{"backup":"required","retentionDays":30,"versioning":"required"},"reclaimPolicy":"retain","storageClass":"backupCapacity"}',
90
+ sha256: '88bd943800bea75b576612b966484e66ddbf7ec9529a7f29dd1eadc9a36e2b79',
91
+ },
92
+ objectStorageFile: {
93
+ input: objectStorageFileRequest,
94
+ canonicalJson: '{"accessMode":"readOnly","delivery":{"format":"servezone-object-storage","gid":10000,"mode":256,"targetPath":"/run/secrets/object-archive.json","type":"file","uid":10000},"id":"object-archive","kind":"objectStorage","reclaimPolicy":"delete","storageClass":"archiveCapacity"}',
95
+ sha256: '13186abbfe733b3917363e0694d367f2d6aa87a4064445532d7c857ee274f795',
96
+ },
97
+ });