@serve.zone/interfaces 32.0.2 → 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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
@@ -5,6 +5,7 @@ import type { IClusterNode, INodeAction, INodeMetricsSample, TNodeActionName } f
5
5
  import type { IDeployment } from '../data/deployment.js';
6
6
  import type { IIdentity } from '../data/user.js';
7
7
  import type { INodeCredentialMetadata, INodeCredentialMutationPreconditions, INodeCredentialMutationResult, TNodeCredentialPurpose } from '../data/nodecredential.js';
8
+ import type { INodeRuntimeRetirement } from '../data/noderetirement.js';
8
9
  import type { INodeEnrollmentRequest, INodeEnrollmentAcknowledgement, INodeEnrollmentState } from '../data/nodeenrollment.js';
9
10
  /** Node-self adoption preconditions, not an admin or workload RBAC grant. */
10
11
  export interface IReq_Spark_Cloudly_GetNodeEnrollmentState extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Spark_Cloudly_GetNodeEnrollmentState> {
@@ -150,6 +151,30 @@ export interface IReq_Any_Cloudly_DeleteNodeById extends plugins.typedrequestInt
150
151
  ok: boolean;
151
152
  };
152
153
  }
154
+ /**
155
+ * An administrator retires one node from its cluster's Pallet runtime.
156
+ *
157
+ * Requires verified platform-infrastructure admin authority. This is the step that makes a node
158
+ * deletable: it writes the retirement row, on which the producer stops and removes the node's
159
+ * slots, the compiler quarantines its handoff, and both node credentials are revoked. Cloudly
160
+ * answers the row as it stands, which is `retiring` until all of that has settled.
161
+ *
162
+ * `expectedGeneration` is the cluster runtime generation the caller read with `getClusterRuntime`:
163
+ * retirement is a statement about a node of a Pallet cluster, so a cutover that moved the phase
164
+ * meanwhile refuses the write instead of retiring a node out of a runtime it no longer runs in.
165
+ * Every refusal is one of `data.nodeRuntimeRetirementRefusals` and takes nothing away.
166
+ */
167
+ export interface IReq_Any_Cloudly_RetireClusterNode extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Any_Cloudly_RetireClusterNode> {
168
+ method: 'retireClusterNode';
169
+ request: {
170
+ identity: IIdentity;
171
+ nodeId: string;
172
+ expectedGeneration: number;
173
+ };
174
+ response: {
175
+ retirement: INodeRuntimeRetirement;
176
+ };
177
+ }
153
178
  /**
154
179
  * An administrator states where one node's Corestore control API answers.
155
180
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@serve.zone/interfaces",
3
- "version": "32.0.2",
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
@@ -892,9 +892,14 @@ on one spec revision, and each reason belongs to exactly one state. `converged`
892
892
  carry `reason: null`. `waiting` carries a `TServiceRuntimeWaitingReason`: `node-network-pending`,
893
893
  `conflict` or `failure-backoff`. `refused` carries a `TServiceRuntimeRefusal`:
894
894
  `cluster-runtime-missing`, `organization-missing`, `image-plan-missing`, `platform-unsupported`,
895
- `secrets-unsupported`, `volumes-unsupported`, `port-protocol-unsupported`,
896
- `readiness-target-undeclared`, `environment-too-large`, `no-eligible-node` or `replica-limit`. A
897
- refusal never retires running slots. `snapshotServiceRuntimeStatus` enforces the pairing.
895
+ `secrets-unsupported`, `volumes-unsupported`, `port-protocol-unsupported`, `ports-too-many`,
896
+ `readiness-target-undeclared`, `environment-too-large`, `no-eligible-node`, `replica-limit` or
897
+ `node-authority-unsupported`. `ports-too-many` is a service declaring more target ports than the
898
+ `runtimeConfigContract.maximumTargetPorts` (64) a config carries, where `port-protocol-unsupported`
899
+ is about one port's protocol; `node-authority-unsupported` is a node whose session resolved fewer
900
+ workload authorities than the spec needs, refused at the admit step rather than handed to a node
901
+ that would silently park it. A refusal never retires running slots.
902
+ `snapshotServiceRuntimeStatus` enforces the pairing.
898
903
 
899
904
  ### Runtime Assignment Views
900
905
 
@@ -911,6 +916,23 @@ through every slot on a cluster's nodes; `limit` runs from 1 to
911
916
  `requests.service.pushServiceRuntimeChanged { serviceId }` tells admin UIs that a service's spec,
912
917
  status or assignments changed; it carries no state, so a late push never overwrites a newer read.
913
918
 
919
+ ### Node Retirement
920
+
921
+ `data.INodeRuntimeRetirement { id, clusterId, state, actorId, since }` records that one node leaves
922
+ its cluster's Pallet runtime. `TNodeRuntimeRetirementState` is `retiring` while the producer still
923
+ stops and removes the node's slots, the compiler quarantines its handoff and both node credentials
924
+ are revoked, and `retired` once that has settled. It is stored beside the node document, because a
925
+ node update merges caller data and no caller may retire a node with it. The producers read the row's
926
+ presence rather than its state: a node that has one is no longer an egress member and desires no
927
+ slots, so the row is written before anything is taken away and stays as long as the node document.
928
+ `snapshotNodeRuntimeRetirement` checks the record.
929
+
930
+ `requests.node.retireClusterNode { identity, nodeId, expectedGeneration }` answers `{ retirement }`.
931
+ `expectedGeneration` is the cluster runtime generation the caller read with `getClusterRuntime`, so a
932
+ cutover that moved the phase meanwhile refuses the write. Every refusal is one of
933
+ `data.nodeRuntimeRetirementRefusals` — `node-missing`, `cluster-runtime-not-pallet`,
934
+ `node-already-retired` or `conflict` — and takes nothing away.
935
+
914
936
  ### Corestore Database Export Packaging
915
937
 
916
938
  The Node-only `@serve.zone/interfaces/runtime` export provides metadata-only
@@ -1271,6 +1293,21 @@ metadata plus a service-owned credential management scope and delivery policy,
1271
1293
  never credential references or values. Filesystem
1272
1294
  bindings expose the container mount and access mode, never a host path.
1273
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
+
1274
1311
  Portable manifests and resolved bindings intentionally have no fields for
1275
1312
  Synology, NFS, Kerberos, Corestore, Kubernetes, Docker drivers, servers,
1276
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.0.2',
6
+ version: '32.2.0',
7
7
  description: 'Shared TypeScript interfaces and TypedRequest contracts for the serve.zone ecosystem.'
8
8
  }
package/ts/data/index.ts CHANGED
@@ -25,6 +25,7 @@ export * from './isolatedrestore.golden.js';
25
25
  export * from './mail.js';
26
26
  export * from './nodecredential.js';
27
27
  export * from './nodeenrollment.js';
28
+ export * from './noderetirement.js';
28
29
  export * from './networkaddressplan.js';
29
30
  export * from './networkauthority.js';
30
31
  export * from './networkcredential.js';