@serve.zone/appstore 32.27.0 → 33.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/.smartconfig.json +4 -1
- package/changelog.md +70 -0
- package/dist_catalog/catalog.digest +1 -0
- package/dist_catalog/catalog.envelope.json +7617 -0
- package/{dist_ts_client/data.generated.js → dist_catalog/catalog.json} +6912 -6908
- package/dist_ts_client/catalog.d.ts +16 -0
- package/dist_ts_client/catalog.js +12 -0
- package/dist_ts_client/index.d.ts +3 -1
- package/dist_ts_client/index.js +4 -2
- package/dist_ts_client/loader.d.ts +69 -0
- package/dist_ts_client/loader.js +361 -0
- package/dist_ts_client/plugins.d.ts +5 -0
- package/dist_ts_client/plugins.js +8 -0
- package/dist_ts_client/projection.d.ts +59 -0
- package/dist_ts_client/projection.js +83 -0
- package/dist_ts_client/storage.d.ts +15 -9
- package/dist_ts_client/storage.js +81 -657
- package/dist_ts_client/types.d.ts +86 -41
- package/dist_ts_client/types.js +1 -1
- package/dist_ts_testing/fixtures.d.ts +83 -0
- package/dist_ts_testing/fixtures.js +146 -0
- package/dist_ts_testing/index.d.ts +1 -0
- package/dist_ts_testing/index.js +2 -0
- package/dist_ts_testing/plugins.d.ts +7 -0
- package/dist_ts_testing/plugins.js +11 -0
- package/package.json +16 -11
- package/readme.md +162 -93
- package/ts_client/catalog.ts +26 -0
- package/ts_client/index.ts +3 -1
- package/ts_client/loader.ts +414 -0
- package/ts_client/plugins.ts +10 -0
- package/ts_client/projection.ts +148 -0
- package/ts_client/readme.md +17 -27
- package/ts_client/storage.ts +93 -882
- package/ts_client/types.ts +102 -42
- package/ts_testing/fixtures.ts +230 -0
- package/ts_testing/index.ts +1 -0
- package/ts_testing/plugins.ts +15 -0
- package/ts_testing/tspublish.json +3 -0
- package/apps/adminer/app.json +0 -10
- package/apps/adminer/versions/1.0.0/config.json +0 -6
- package/apps/cloudly/app.json +0 -14
- package/apps/cloudly/versions/1.0.0/config.json +0 -120
- package/apps/cloudly/versions/1.1.0/config.json +0 -120
- package/apps/cloudly/versions/1.1.1/config.json +0 -120
- package/apps/cloudly/versions/1.1.10/config.json +0 -173
- package/apps/cloudly/versions/1.1.2/config.json +0 -130
- package/apps/cloudly/versions/1.1.3/config.json +0 -130
- package/apps/cloudly/versions/1.1.4/config.json +0 -130
- package/apps/cloudly/versions/1.1.5/config.json +0 -149
- package/apps/cloudly/versions/1.1.6/config.json +0 -149
- package/apps/cloudly/versions/1.1.7/config.json +0 -149
- package/apps/cloudly/versions/1.1.8/config.json +0 -173
- package/apps/cloudly/versions/1.1.9/config.json +0 -173
- package/apps/cloudly/versions/1.10.0/config.json +0 -173
- package/apps/cloudly/versions/1.11.0/config.json +0 -173
- package/apps/cloudly/versions/1.12.0/config.json +0 -173
- package/apps/cloudly/versions/1.13.0/config.json +0 -173
- package/apps/cloudly/versions/1.14.0/config.json +0 -173
- package/apps/cloudly/versions/1.15.0/config.json +0 -173
- package/apps/cloudly/versions/1.16.0/config.json +0 -173
- package/apps/cloudly/versions/1.17.0/config.json +0 -173
- package/apps/cloudly/versions/1.18.0/config.json +0 -173
- package/apps/cloudly/versions/1.19.0/config.json +0 -173
- package/apps/cloudly/versions/1.2.0/config.json +0 -173
- package/apps/cloudly/versions/1.2.1/config.json +0 -173
- package/apps/cloudly/versions/1.20.0/config.json +0 -173
- package/apps/cloudly/versions/1.21.0/config.json +0 -173
- package/apps/cloudly/versions/1.22.0/config.json +0 -173
- package/apps/cloudly/versions/1.23.0/config.json +0 -173
- package/apps/cloudly/versions/1.24.0/config.json +0 -173
- package/apps/cloudly/versions/1.25.0/config.json +0 -173
- package/apps/cloudly/versions/1.26.0/config.json +0 -173
- package/apps/cloudly/versions/1.27.0/config.json +0 -173
- package/apps/cloudly/versions/1.3.0/config.json +0 -173
- package/apps/cloudly/versions/1.4.0/config.json +0 -173
- package/apps/cloudly/versions/1.5.0/config.json +0 -173
- package/apps/cloudly/versions/1.6.0/config.json +0 -173
- package/apps/cloudly/versions/1.7.0/config.json +0 -173
- package/apps/cloudly/versions/1.8.0/config.json +0 -173
- package/apps/cloudly/versions/1.9.0/config.json +0 -173
- package/apps/ghost/app.json +0 -10
- package/apps/ghost/versions/1.0.0/config.json +0 -18
- package/apps/gitea/app.json +0 -10
- package/apps/gitea/versions/1.0.0/config.json +0 -16
- package/apps/gitops/app.json +0 -14
- package/apps/gitops/versions/1.0.0/config.json +0 -28
- package/apps/grafana/app.json +0 -10
- package/apps/grafana/versions/1.0.0/config.json +0 -9
- package/apps/mariadb/app.json +0 -10
- package/apps/mariadb/versions/1.0.0/config.json +0 -9
- package/apps/mattermost/app.json +0 -10
- package/apps/mattermost/versions/1.0.0/config.json +0 -6
- package/apps/n8n/app.json +0 -10
- package/apps/n8n/versions/1.0.0/config.json +0 -6
- package/apps/nextcloud/app.json +0 -10
- package/apps/nextcloud/versions/1.0.0/config.json +0 -16
- package/apps/nginx/app.json +0 -10
- package/apps/nginx/versions/1.0.0/config.json +0 -6
- package/apps/openbao/app.json +0 -16
- package/apps/openbao/versions/1.0.0/config.json +0 -52
- package/apps/plausible/app.json +0 -10
- package/apps/plausible/versions/1.0.0/config.json +0 -9
- package/apps/portainer/app.json +0 -10
- package/apps/portainer/versions/1.0.0/config.json +0 -6
- package/apps/postgres/app.json +0 -10
- package/apps/postgres/versions/1.0.0/config.json +0 -11
- package/apps/rustdesk-server/app.json +0 -14
- package/apps/rustdesk-server/versions/1.0.0/config.json +0 -19
- package/apps/siprouter/app.json +0 -14
- package/apps/siprouter/versions/1.0.0/config.json +0 -84
- package/apps/uptime-kuma/app.json +0 -10
- package/apps/uptime-kuma/versions/1.0.0/config.json +0 -6
- package/apps/valkey/app.json +0 -10
- package/apps/valkey/versions/1.0.0/config.json +0 -6
- package/apps/vaultwarden/app.json +0 -10
- package/apps/vaultwarden/versions/1.0.0/config.json +0 -6
- package/apps/wordpress/app.json +0 -10
- package/apps/wordpress/versions/1.0.0/config.json +0 -15
- package/appstore.json +0 -194
- package/dist_ts_client/classes.appstoreresolver.d.ts +0 -59
- package/dist_ts_client/classes.appstoreresolver.js +0 -736
- package/dist_ts_client/data.generated.d.ts +0 -2
- package/ts_client/classes.appstoreresolver.ts +0 -896
- package/ts_client/data.generated.ts +0 -7606
|
@@ -1,190 +1,96 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
const storageFeatureIds =
|
|
3
|
-
const knownStorageFeatureIds = new Set(Object.values(storageFeatureIds));
|
|
4
|
-
const storageClassKeyPattern = /^[A-Za-z][A-Za-z0-9-]{0,62}$/;
|
|
5
|
-
const storageRequestIdPattern = /^[a-z][a-z0-9-]{0,62}$/;
|
|
6
|
-
const environmentKeyPattern = /^[A-Z_][A-Z0-9_]{0,252}$/;
|
|
7
|
-
const capacityPattern = /^([1-9][0-9]*)(KiB|MiB|GiB|TiB)$/;
|
|
8
|
-
const capacityMultipliers = {
|
|
9
|
-
KiB: 1024n,
|
|
10
|
-
MiB: 1024n ** 2n,
|
|
11
|
-
GiB: 1024n ** 3n,
|
|
12
|
-
TiB: 1024n ** 4n,
|
|
13
|
-
};
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
const storageFeatureIds = plugins.servezoneInterfaces.appstore.appStoreStorageFeatureIds;
|
|
14
3
|
const legacyFilesystemClassKey = 'legacyFilesystem';
|
|
15
4
|
const legacyObjectStorageClassKey = 'legacyObjectStorage';
|
|
16
5
|
const legacyObjectStorageRequestId = 'legacy-s3';
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
'
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
if (
|
|
48
|
-
throw new Error(`Invalid ${labelArg}:
|
|
6
|
+
const storageRequestIdPattern = /^[a-z][a-z0-9-]{0,62}$/;
|
|
7
|
+
const defaultLabel = 'appstore config';
|
|
8
|
+
/**
|
|
9
|
+
* Throws the first storage violation of a version config, judged by the interfaces contract
|
|
10
|
+
* (`appstore.validateAppStoreVersionStorage`), which owns every storage rule.
|
|
11
|
+
*/
|
|
12
|
+
const assertValidStorage = (configArg, labelArg) => {
|
|
13
|
+
const errors = plugins.servezoneInterfaces.appstore.validateAppStoreVersionStorage(configArg, labelArg);
|
|
14
|
+
if (errors.length > 0)
|
|
15
|
+
throw new Error(errors.join('; '));
|
|
16
|
+
};
|
|
17
|
+
const normalizeVolumes = (volumesArg) => (volumesArg ?? []).map((volumeArg) => {
|
|
18
|
+
const volume = typeof volumeArg === 'string' ? { mountPath: volumeArg } : volumeArg;
|
|
19
|
+
return {
|
|
20
|
+
...(volume.name === undefined ? {} : { name: volume.name }),
|
|
21
|
+
mountPath: volume.mountPath,
|
|
22
|
+
...(volume.readOnly === undefined ? {} : { readOnly: volume.readOnly }),
|
|
23
|
+
...(volume.backup === undefined ? {} : { backup: volume.backup }),
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
/** The stable request id a legacy volume becomes: its name, or its mount path flattened. */
|
|
27
|
+
const createLegacyVolumeRequestId = (volumeArg, indexArg, labelArg) => {
|
|
28
|
+
const stablePart = volumeArg.name || volumeArg.mountPath
|
|
29
|
+
.toLowerCase()
|
|
30
|
+
.split('/')
|
|
31
|
+
.filter(Boolean)
|
|
32
|
+
.join('-')
|
|
33
|
+
.replace(/[^a-z0-9-]+/g, '-')
|
|
34
|
+
.replace(/^-+|-+$/g, '');
|
|
35
|
+
const requestId = `legacy-volume-${stablePart}`;
|
|
36
|
+
if (!stablePart || !storageRequestIdPattern.test(requestId)) {
|
|
37
|
+
throw new Error(`Invalid ${labelArg} volumes[${indexArg}]: cannot derive a stable request id; declare a shorter lowercase name`);
|
|
49
38
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
39
|
+
return requestId;
|
|
40
|
+
};
|
|
41
|
+
const deriveRequiredFeatureIds = (explicitRequestsArg) => {
|
|
42
|
+
const required = [];
|
|
43
|
+
if (explicitRequestsArg.length > 0)
|
|
44
|
+
required.push(storageFeatureIds.bindings);
|
|
45
|
+
if (explicitRequestsArg.some((requestArg) => requestArg.kind === 'filesystem')) {
|
|
46
|
+
required.push(storageFeatureIds.filesystem);
|
|
53
47
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
// App Store reads a quantity, so the same bound is applied here rather than after a request has
|
|
57
|
-
// already been assembled from it.
|
|
58
|
-
if (!Number.isSafeInteger(Number(match[1]))) {
|
|
59
|
-
throw new Error(`Invalid ${labelArg} '${quantityArg}': the quantity exceeds the safe integer range`);
|
|
48
|
+
if (explicitRequestsArg.some((requestArg) => requestArg.kind === 'objectStorage')) {
|
|
49
|
+
required.push(storageFeatureIds.objectStorage);
|
|
60
50
|
}
|
|
61
|
-
|
|
62
|
-
|
|
51
|
+
if (explicitRequestsArg.some((requestArg) => (requestArg.kind === 'objectStorage' && requestArg.delivery.type === 'file'))) {
|
|
52
|
+
required.push(storageFeatureIds.objectStorageFile);
|
|
53
|
+
}
|
|
54
|
+
return required;
|
|
55
|
+
};
|
|
63
56
|
/**
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
* call normalizeAppStoreStorageConfig with an advertised feature set.
|
|
57
|
+
* The legacy `volumes` of a version config in their object form (`{ name?, mountPath, readOnly?,
|
|
58
|
+
* backup? }`), after the config's storage passed the interfaces contract.
|
|
67
59
|
*/
|
|
68
|
-
export function
|
|
69
|
-
|
|
60
|
+
export function normalizeAppStoreVolumes(configArg, labelArg = defaultLabel) {
|
|
61
|
+
assertValidStorage(configArg, labelArg);
|
|
62
|
+
return normalizeVolumes(configArg.volumes);
|
|
70
63
|
}
|
|
71
64
|
/**
|
|
72
|
-
*
|
|
73
|
-
*
|
|
65
|
+
* The canonical pre-fulfillment storage handoff of a version config.
|
|
66
|
+
*
|
|
67
|
+
* The config's storage is judged by the interfaces contract first. Legacy `volumes` become
|
|
68
|
+
* filesystem requests of the reserved `legacyFilesystem` class, `platformRequirements.s3` becomes
|
|
69
|
+
* the `legacy-s3` object-storage request, and explicit requests fail closed unless every storage
|
|
70
|
+
* feature they need is advertised by the target runtime.
|
|
74
71
|
*/
|
|
75
|
-
export function normalizeAppStoreStorageConfig(configArg, optionsArg, labelArg =
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
80
|
-
let supportedFeatures;
|
|
81
|
-
try {
|
|
82
|
-
supportedFeatures = new Set(optionsArg.supportedFeatures);
|
|
83
|
-
}
|
|
84
|
-
catch {
|
|
85
|
-
throw new Error(`Invalid ${labelArg}: supportedFeatures must be iterable`);
|
|
86
|
-
}
|
|
87
|
-
const unsupportedFeatures = normalized.requiredFeatureIds.filter((featureIdArg) => !supportedFeatures.has(featureIdArg));
|
|
88
|
-
if (unsupportedFeatures.length > 0) {
|
|
89
|
-
throw new Error(`Unsupported ${labelArg} storage features: ${unsupportedFeatures.join(', ')}`);
|
|
90
|
-
}
|
|
91
|
-
return normalized;
|
|
92
|
-
}
|
|
93
|
-
function collectAppInputDestinations(configArg, labelArg) {
|
|
94
|
-
const declaredEnvironmentKeys = new Set();
|
|
95
|
-
const runtimeEnvironmentOwners = new Map();
|
|
96
|
-
const secretFileOwners = new Map();
|
|
97
|
-
const addDestination = (ownersArg, destinationArg, ownerArg, kindArg) => {
|
|
98
|
-
const existingOwner = ownersArg.get(destinationArg);
|
|
99
|
-
if (existingOwner) {
|
|
100
|
-
throw new Error(`Invalid ${labelArg}: ${kindArg} destination '${destinationArg}' is used by both ${existingOwner} and ${ownerArg}`);
|
|
101
|
-
}
|
|
102
|
-
ownersArg.set(destinationArg, ownerArg);
|
|
103
|
-
};
|
|
104
|
-
for (const declaration of configArg.envVars || []) {
|
|
105
|
-
declaredEnvironmentKeys.add(declaration.key);
|
|
106
|
-
const owner = `envVars.${declaration.key}`;
|
|
107
|
-
if (declaration.secret === true) {
|
|
108
|
-
if (declaration.delivery.type === 'launcher-environment') {
|
|
109
|
-
addDestination(runtimeEnvironmentOwners, declaration.delivery.variableName, owner, 'environment');
|
|
110
|
-
}
|
|
111
|
-
else {
|
|
112
|
-
addDestination(secretFileOwners, declaration.delivery.targetPath, owner, 'secret file');
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
else {
|
|
116
|
-
addDestination(runtimeEnvironmentOwners, declaration.key, owner, 'environment');
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
const platformOidc = configArg.platformOidc;
|
|
120
|
-
if (platformOidc && typeof platformOidc === 'object' && !Array.isArray(platformOidc)) {
|
|
121
|
-
const environmentVariables = platformOidc.environmentVariables;
|
|
122
|
-
if (environmentVariables && typeof environmentVariables === 'object'
|
|
123
|
-
&& !Array.isArray(environmentVariables)) {
|
|
124
|
-
for (const [field, destination] of Object.entries(environmentVariables)) {
|
|
125
|
-
if (typeof destination === 'string') {
|
|
126
|
-
addDestination(runtimeEnvironmentOwners, destination, `platformOidc.${field}`, 'environment');
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
return {
|
|
132
|
-
declaredEnvironmentKeys,
|
|
133
|
-
runtimeEnvironmentKeys: new Set(runtimeEnvironmentOwners.keys()),
|
|
134
|
-
declaredSecretPaths: new Set(secretFileOwners.keys()),
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
function validateAndNormalizeStorageConfig(configArg, labelArg) {
|
|
138
|
-
assertExactKeys(assertPlainRecord(configArg, labelArg), appStoreVersionConfigKeys, labelArg);
|
|
139
|
-
const environmentErrors = interfaces.appstore.validateAppStoreEnvironmentDeclarations(configArg.envVars);
|
|
140
|
-
if (environmentErrors.length > 0) {
|
|
141
|
-
throw new Error(`Invalid ${labelArg}: ${environmentErrors.join('; ')}`);
|
|
142
|
-
}
|
|
143
|
-
const appInputDestinations = collectAppInputDestinations(configArg, labelArg);
|
|
144
|
-
validatePlatformRequirements(configArg.platformRequirements, labelArg);
|
|
145
|
-
const explicitClassInput = configArg.storageClasses;
|
|
146
|
-
const explicitRequestInput = configArg.storageRequests;
|
|
147
|
-
const hasExplicitClasses = explicitClassInput !== undefined;
|
|
148
|
-
const hasExplicitRequests = explicitRequestInput !== undefined;
|
|
149
|
-
if (hasExplicitClasses !== hasExplicitRequests) {
|
|
150
|
-
throw new Error(`Invalid ${labelArg}: storageClasses and storageRequests must be declared together`);
|
|
151
|
-
}
|
|
152
|
-
const storageClasses = validateStorageClasses(explicitClassInput, labelArg);
|
|
153
|
-
const explicitRequests = validateExplicitStorageRequests(explicitRequestInput, storageClasses, appInputDestinations, labelArg);
|
|
154
|
-
const requiredFeatureIds = validateFeatureDeclaration(configArg, explicitRequests, labelArg);
|
|
155
|
-
if (configArg.platformRequirements?.s3 && explicitRequests.some((requestArg) => requestArg.kind === 'objectStorage')) {
|
|
156
|
-
throw new Error(`Invalid ${labelArg}: platformRequirements.s3 cannot coexist with explicit objectStorage requests`);
|
|
157
|
-
}
|
|
72
|
+
export function normalizeAppStoreStorageConfig(configArg, optionsArg, labelArg = defaultLabel) {
|
|
73
|
+
assertValidStorage(configArg, labelArg);
|
|
74
|
+
const storageClasses = structuredClone(configArg.storageClasses ?? {});
|
|
75
|
+
const explicitRequests = structuredClone(configArg.storageRequests ?? []);
|
|
158
76
|
const storageRequests = [...explicitRequests];
|
|
159
|
-
const
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
const legacyVolumes = normalizeLegacyVolumes(configArg.volumes, labelArg);
|
|
77
|
+
const requestOrigins = {};
|
|
78
|
+
for (const request of explicitRequests)
|
|
79
|
+
requestOrigins[request.id] = 'explicit';
|
|
80
|
+
const requiredFeatureIds = deriveRequiredFeatureIds(explicitRequests);
|
|
81
|
+
const legacyVolumes = normalizeVolumes(configArg.volumes);
|
|
165
82
|
if (legacyVolumes.length > 0) {
|
|
166
|
-
if (Object.hasOwn(storageClasses, legacyFilesystemClassKey)) {
|
|
167
|
-
throw new Error(`Invalid ${labelArg}: storageClasses key '${legacyFilesystemClassKey}' is reserved for legacy volume normalization`);
|
|
168
|
-
}
|
|
169
83
|
storageClasses[legacyFilesystemClassKey] = {
|
|
170
84
|
kind: 'filesystem',
|
|
171
85
|
purpose: 'runtime',
|
|
172
86
|
required: {
|
|
173
87
|
durability: 'persistent',
|
|
174
|
-
...(legacyVolumes.some((volumeArg) => volumeArg.backup !== false)
|
|
175
|
-
? { backup: true }
|
|
176
|
-
: {}),
|
|
88
|
+
...(legacyVolumes.some((volumeArg) => volumeArg.backup !== false) ? { backup: true } : {}),
|
|
177
89
|
},
|
|
178
90
|
};
|
|
179
91
|
}
|
|
180
|
-
|
|
92
|
+
legacyVolumes.forEach((volumeArg, indexArg) => {
|
|
181
93
|
const requestId = createLegacyVolumeRequestId(volumeArg, indexArg, labelArg);
|
|
182
|
-
if (requestIds.has(requestId)) {
|
|
183
|
-
throw new Error(`Invalid ${labelArg}: storage request id '${requestId}' is duplicated`);
|
|
184
|
-
}
|
|
185
|
-
assertNoPathCollision(volumeArg.mountPath, mountPaths, `${labelArg} legacy volume ${indexArg + 1}`);
|
|
186
|
-
requestIds.add(requestId);
|
|
187
|
-
mountPaths.push(volumeArg.mountPath);
|
|
188
94
|
storageRequests.push({
|
|
189
95
|
id: requestId,
|
|
190
96
|
kind: 'filesystem',
|
|
@@ -194,16 +100,10 @@ function validateAndNormalizeStorageConfig(configArg, labelArg) {
|
|
|
194
100
|
reclaimPolicy: 'retain',
|
|
195
101
|
...(volumeArg.backup === false ? {} : { protection: { backup: 'required' } }),
|
|
196
102
|
});
|
|
197
|
-
|
|
198
|
-
}
|
|
103
|
+
requestOrigins[requestId] = 'legacyVolume';
|
|
104
|
+
});
|
|
199
105
|
let legacyCompatibility;
|
|
200
106
|
if (configArg.platformRequirements?.s3) {
|
|
201
|
-
if (Object.hasOwn(storageClasses, legacyObjectStorageClassKey)) {
|
|
202
|
-
throw new Error(`Invalid ${labelArg}: storageClasses key '${legacyObjectStorageClassKey}' is reserved for legacy S3 normalization`);
|
|
203
|
-
}
|
|
204
|
-
if (requestIds.has(legacyObjectStorageRequestId)) {
|
|
205
|
-
throw new Error(`Invalid ${labelArg}: storage request id '${legacyObjectStorageRequestId}' is reserved for legacy S3 normalization`);
|
|
206
|
-
}
|
|
207
107
|
storageClasses[legacyObjectStorageClassKey] = {
|
|
208
108
|
kind: 'objectStorage',
|
|
209
109
|
purpose: 'runtime',
|
|
@@ -226,7 +126,7 @@ function validateAndNormalizeStorageConfig(configArg, labelArg) {
|
|
|
226
126
|
},
|
|
227
127
|
},
|
|
228
128
|
});
|
|
229
|
-
|
|
129
|
+
requestOrigins[legacyObjectStorageRequestId] = 'legacyS3';
|
|
230
130
|
legacyCompatibility = {
|
|
231
131
|
objectStorage: {
|
|
232
132
|
requestId: legacyObjectStorageRequestId,
|
|
@@ -235,493 +135,17 @@ function validateAndNormalizeStorageConfig(configArg, labelArg) {
|
|
|
235
135
|
},
|
|
236
136
|
};
|
|
237
137
|
}
|
|
238
|
-
|
|
138
|
+
const supportedFeatures = new Set(optionsArg.supportedFeatures);
|
|
139
|
+
const unsupportedFeatures = requiredFeatureIds.filter((featureIdArg) => !supportedFeatures.has(featureIdArg));
|
|
140
|
+
if (unsupportedFeatures.length > 0) {
|
|
141
|
+
throw new Error(`Unsupported ${labelArg} storage features: ${unsupportedFeatures.join(', ')}`);
|
|
142
|
+
}
|
|
239
143
|
return {
|
|
240
144
|
storageClasses,
|
|
241
145
|
storageRequests,
|
|
242
|
-
requestOrigins
|
|
146
|
+
requestOrigins,
|
|
243
147
|
requiredFeatureIds,
|
|
244
148
|
...(legacyCompatibility ? { legacyCompatibility } : {}),
|
|
245
149
|
};
|
|
246
150
|
}
|
|
247
|
-
|
|
248
|
-
if (classesArg === undefined)
|
|
249
|
-
return {};
|
|
250
|
-
const classesRecord = assertPlainRecord(classesArg, `${labelArg} storageClasses`);
|
|
251
|
-
const entries = Object.entries(classesRecord);
|
|
252
|
-
if (entries.length === 0 || entries.length > 64) {
|
|
253
|
-
throw new Error(`Invalid ${labelArg}: storageClasses must contain between 1 and 64 entries`);
|
|
254
|
-
}
|
|
255
|
-
const normalizedEntries = entries.map(([classKeyArg, candidateArg]) => {
|
|
256
|
-
if (!storageClassKeyPattern.test(classKeyArg)) {
|
|
257
|
-
throw new Error(`Invalid ${labelArg}: storage class key '${classKeyArg}' is not stable`);
|
|
258
|
-
}
|
|
259
|
-
const classLabel = `${labelArg} storageClasses.${classKeyArg}`;
|
|
260
|
-
const candidate = assertPlainRecord(candidateArg, classLabel);
|
|
261
|
-
assertExactKeys(candidate, ['kind', 'purpose', 'required', 'preferred'], classLabel);
|
|
262
|
-
if (!['filesystem', 'objectStorage'].includes(candidate.kind)) {
|
|
263
|
-
throw new Error(`Invalid ${classLabel}: kind must be filesystem or objectStorage`);
|
|
264
|
-
}
|
|
265
|
-
if (!['runtime', 'database', 'registry', 'backup'].includes(candidate.purpose)) {
|
|
266
|
-
throw new Error(`Invalid ${classLabel}: purpose is not supported`);
|
|
267
|
-
}
|
|
268
|
-
const required = validateClassRequirement(candidate.required, `${classLabel}.required`);
|
|
269
|
-
const preferred = validateClassRequirement(candidate.preferred, `${classLabel}.preferred`);
|
|
270
|
-
if (required && preferred) {
|
|
271
|
-
for (const requirementKey of Object.keys(required)) {
|
|
272
|
-
if (preferred[requirementKey] !== undefined
|
|
273
|
-
&& preferred[requirementKey] !== required[requirementKey]) {
|
|
274
|
-
throw new Error(`Invalid ${classLabel}: preferred.${String(requirementKey)} conflicts with required.${String(requirementKey)}`);
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
const normalized = {
|
|
279
|
-
kind: candidate.kind,
|
|
280
|
-
purpose: candidate.purpose,
|
|
281
|
-
...(required ? { required } : {}),
|
|
282
|
-
...(preferred ? { preferred } : {}),
|
|
283
|
-
};
|
|
284
|
-
return [classKeyArg, normalized];
|
|
285
|
-
});
|
|
286
|
-
return Object.fromEntries(normalizedEntries);
|
|
287
|
-
}
|
|
288
|
-
function validateClassRequirement(requirementArg, labelArg) {
|
|
289
|
-
if (requirementArg === undefined)
|
|
290
|
-
return undefined;
|
|
291
|
-
const requirement = assertPlainRecord(requirementArg, labelArg);
|
|
292
|
-
assertExactKeys(requirement, [
|
|
293
|
-
'performanceTier',
|
|
294
|
-
'durability',
|
|
295
|
-
'topology',
|
|
296
|
-
'hardQuota',
|
|
297
|
-
'snapshots',
|
|
298
|
-
'backup',
|
|
299
|
-
'encryptedInTransit',
|
|
300
|
-
], labelArg);
|
|
301
|
-
assertOptionalMember(requirement.performanceTier, ['standard', 'highIops', 'capacity'], `${labelArg}.performanceTier`);
|
|
302
|
-
assertOptionalMember(requirement.durability, ['ephemeral', 'persistent'], `${labelArg}.durability`);
|
|
303
|
-
assertOptionalMember(requirement.topology, ['singleNode', 'multiNode'], `${labelArg}.topology`);
|
|
304
|
-
assertOptionalMember(requirement.snapshots, ['portable', 'native'], `${labelArg}.snapshots`);
|
|
305
|
-
for (const booleanKey of ['hardQuota', 'backup', 'encryptedInTransit']) {
|
|
306
|
-
if (requirement[booleanKey] !== undefined && requirement[booleanKey] !== true) {
|
|
307
|
-
throw new Error(`Invalid ${labelArg}.${booleanKey}: only true may be declared`);
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
return { ...requirement };
|
|
311
|
-
}
|
|
312
|
-
function validateExplicitStorageRequests(requestsArg, classesArg, appInputDestinationsArg, labelArg) {
|
|
313
|
-
if (requestsArg === undefined)
|
|
314
|
-
return [];
|
|
315
|
-
if (!Array.isArray(requestsArg) || requestsArg.length === 0 || requestsArg.length > 64) {
|
|
316
|
-
throw new Error(`Invalid ${labelArg}: storageRequests must contain between 1 and 64 entries`);
|
|
317
|
-
}
|
|
318
|
-
const requestIds = new Set();
|
|
319
|
-
const usedClassKeys = new Set();
|
|
320
|
-
const deliveryEnvironmentKeys = new Set();
|
|
321
|
-
const { declaredEnvironmentKeys, runtimeEnvironmentKeys, declaredSecretPaths, } = appInputDestinationsArg;
|
|
322
|
-
const deliverySecretPaths = new Set();
|
|
323
|
-
const requests = requestsArg.map((candidateArg, indexArg) => {
|
|
324
|
-
const requestLabel = `${labelArg} storageRequests[${indexArg}]`;
|
|
325
|
-
const candidate = assertPlainRecord(candidateArg, requestLabel);
|
|
326
|
-
if (candidate.kind === 'filesystem') {
|
|
327
|
-
assertExactKeys(candidate, [
|
|
328
|
-
'id', 'kind', 'storageClass', 'capacity', 'reclaimPolicy',
|
|
329
|
-
'mountPath', 'accessMode', 'protection',
|
|
330
|
-
], requestLabel);
|
|
331
|
-
}
|
|
332
|
-
else if (candidate.kind === 'objectStorage') {
|
|
333
|
-
assertExactKeys(candidate, [
|
|
334
|
-
'id', 'kind', 'storageClass', 'capacity', 'reclaimPolicy',
|
|
335
|
-
'accessMode', 'delivery', 'protection',
|
|
336
|
-
], requestLabel);
|
|
337
|
-
}
|
|
338
|
-
else {
|
|
339
|
-
throw new Error(`Invalid ${requestLabel}: kind must be filesystem or objectStorage`);
|
|
340
|
-
}
|
|
341
|
-
if (typeof candidate.id !== 'string' || !storageRequestIdPattern.test(candidate.id)) {
|
|
342
|
-
throw new Error(`Invalid ${requestLabel}: id must be a stable lowercase identifier`);
|
|
343
|
-
}
|
|
344
|
-
if (requestIds.has(candidate.id)) {
|
|
345
|
-
throw new Error(`Invalid ${labelArg}: storage request id '${candidate.id}' is duplicated`);
|
|
346
|
-
}
|
|
347
|
-
requestIds.add(candidate.id);
|
|
348
|
-
if (typeof candidate.storageClass !== 'string'
|
|
349
|
-
|| !Object.hasOwn(classesArg, candidate.storageClass)) {
|
|
350
|
-
throw new Error(`Invalid ${requestLabel}: storageClass '${candidate.storageClass}' is not declared`);
|
|
351
|
-
}
|
|
352
|
-
const storageClass = classesArg[candidate.storageClass];
|
|
353
|
-
if (storageClass.kind !== candidate.kind) {
|
|
354
|
-
throw new Error(`Invalid ${requestLabel}: storageClass kind does not match request kind`);
|
|
355
|
-
}
|
|
356
|
-
usedClassKeys.add(candidate.storageClass);
|
|
357
|
-
if (!['retain', 'delete'].includes(candidate.reclaimPolicy)) {
|
|
358
|
-
throw new Error(`Invalid ${requestLabel}: reclaimPolicy must be retain or delete`);
|
|
359
|
-
}
|
|
360
|
-
const capacity = validateCapacity(candidate.capacity, `${requestLabel}.capacity`);
|
|
361
|
-
if (capacity?.limit && storageClass.required?.hardQuota !== true) {
|
|
362
|
-
throw new Error(`Invalid ${requestLabel}: capacity.limit requires storageClass.required.hardQuota`);
|
|
363
|
-
}
|
|
364
|
-
if (candidate.kind === 'filesystem') {
|
|
365
|
-
if (typeof candidate.mountPath !== 'string'
|
|
366
|
-
|| interfaces.data.normalizeServiceAbsolutePath(candidate.mountPath) !== candidate.mountPath
|
|
367
|
-
|| candidate.mountPath === '/'
|
|
368
|
-
|| pathsOverlap(candidate.mountPath, '/run/secrets')) {
|
|
369
|
-
throw new Error(`Invalid ${requestLabel}: mountPath must be a canonical non-root path outside /run/secrets`);
|
|
370
|
-
}
|
|
371
|
-
assertOptionalMember(candidate.accessMode, ['ReadWriteOnce', 'ReadOnlyMany', 'ReadWriteMany'], `${requestLabel}.accessMode`, false);
|
|
372
|
-
const protection = validateFilesystemProtection(candidate.protection, `${requestLabel}.protection`);
|
|
373
|
-
if (protection?.backup === 'required' && storageClass.required?.backup !== true) {
|
|
374
|
-
throw new Error(`Invalid ${requestLabel}: required backup must be declared by the storage class`);
|
|
375
|
-
}
|
|
376
|
-
if (protection?.snapshots && storageClass.required?.snapshots !== protection.snapshots) {
|
|
377
|
-
throw new Error(`Invalid ${requestLabel}: required snapshots must be declared by the storage class`);
|
|
378
|
-
}
|
|
379
|
-
return {
|
|
380
|
-
id: candidate.id,
|
|
381
|
-
kind: 'filesystem',
|
|
382
|
-
storageClass: candidate.storageClass,
|
|
383
|
-
...(capacity ? { capacity } : {}),
|
|
384
|
-
reclaimPolicy: candidate.reclaimPolicy,
|
|
385
|
-
mountPath: candidate.mountPath,
|
|
386
|
-
accessMode: candidate.accessMode,
|
|
387
|
-
...(protection ? { protection } : {}),
|
|
388
|
-
};
|
|
389
|
-
}
|
|
390
|
-
assertOptionalMember(candidate.accessMode, ['readOnly', 'readWrite'], `${requestLabel}.accessMode`, false);
|
|
391
|
-
const delivery = validateObjectStorageDelivery(candidate.delivery, requestLabel, declaredEnvironmentKeys, runtimeEnvironmentKeys, deliveryEnvironmentKeys, declaredSecretPaths, deliverySecretPaths);
|
|
392
|
-
const protection = validateObjectStorageProtection(candidate.protection, `${requestLabel}.protection`);
|
|
393
|
-
if (protection?.backup === 'required' && storageClass.required?.backup !== true) {
|
|
394
|
-
throw new Error(`Invalid ${requestLabel}: required backup must be declared by the storage class`);
|
|
395
|
-
}
|
|
396
|
-
return {
|
|
397
|
-
id: candidate.id,
|
|
398
|
-
kind: 'objectStorage',
|
|
399
|
-
storageClass: candidate.storageClass,
|
|
400
|
-
...(capacity ? { capacity } : {}),
|
|
401
|
-
reclaimPolicy: candidate.reclaimPolicy,
|
|
402
|
-
accessMode: candidate.accessMode,
|
|
403
|
-
delivery,
|
|
404
|
-
...(protection ? { protection } : {}),
|
|
405
|
-
};
|
|
406
|
-
});
|
|
407
|
-
for (const classKeyArg of Object.keys(classesArg)) {
|
|
408
|
-
if (!usedClassKeys.has(classKeyArg)) {
|
|
409
|
-
throw new Error(`Invalid ${labelArg}: storage class '${classKeyArg}' is not used by a request`);
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
return requests;
|
|
413
|
-
}
|
|
414
|
-
function validateCapacity(capacityArg, labelArg) {
|
|
415
|
-
if (capacityArg === undefined)
|
|
416
|
-
return undefined;
|
|
417
|
-
const capacity = assertPlainRecord(capacityArg, labelArg);
|
|
418
|
-
assertExactKeys(capacity, ['request', 'limit'], labelArg);
|
|
419
|
-
const requestedBytes = parseStorageCapacityQuantity(capacity.request, `${labelArg}.request`);
|
|
420
|
-
const limitBytes = capacity.limit === undefined
|
|
421
|
-
? undefined
|
|
422
|
-
: parseStorageCapacityQuantity(capacity.limit, `${labelArg}.limit`);
|
|
423
|
-
if (limitBytes !== undefined && limitBytes < requestedBytes) {
|
|
424
|
-
throw new Error(`Invalid ${labelArg}: limit must be greater than or equal to request`);
|
|
425
|
-
}
|
|
426
|
-
return {
|
|
427
|
-
request: capacity.request,
|
|
428
|
-
...(capacity.limit === undefined ? {} : { limit: capacity.limit }),
|
|
429
|
-
};
|
|
430
|
-
}
|
|
431
|
-
/**
|
|
432
|
-
* An absent `protection` member already states that the request asks for no protection, so an
|
|
433
|
-
* empty one states nothing a fulfillment adapter could act on. The storage contract refuses it by
|
|
434
|
-
* name (`protection must not be empty`), and this package is the producer of those requests: the
|
|
435
|
-
* manifest author is told here instead of a control plane refusing the request later. Members are
|
|
436
|
-
* copied one by one rather than spread, so a member declared as an explicit `undefined` — which
|
|
437
|
-
* the member checks treat as absent, and which the contract refuses as a non-JSON data property —
|
|
438
|
-
* can never reach the emitted request.
|
|
439
|
-
*/
|
|
440
|
-
function assertProtectionDeclaresRequirement(protectionArg, labelArg) {
|
|
441
|
-
if (Object.keys(protectionArg).length === 0) {
|
|
442
|
-
throw new Error(`Invalid ${labelArg}: declare at least one protection requirement or omit protection`);
|
|
443
|
-
}
|
|
444
|
-
return protectionArg;
|
|
445
|
-
}
|
|
446
|
-
function validateFilesystemProtection(protectionArg, labelArg) {
|
|
447
|
-
if (protectionArg === undefined)
|
|
448
|
-
return undefined;
|
|
449
|
-
const protection = assertPlainRecord(protectionArg, labelArg);
|
|
450
|
-
assertExactKeys(protection, ['backup', 'snapshots', 'consistency'], labelArg);
|
|
451
|
-
assertOptionalMember(protection.backup, ['required'], `${labelArg}.backup`);
|
|
452
|
-
assertOptionalMember(protection.snapshots, ['portable', 'native'], `${labelArg}.snapshots`);
|
|
453
|
-
assertOptionalMember(protection.consistency, ['crashConsistent', 'applicationConsistent'], `${labelArg}.consistency`);
|
|
454
|
-
return assertProtectionDeclaresRequirement({
|
|
455
|
-
...(protection.backup === undefined
|
|
456
|
-
? {}
|
|
457
|
-
: { backup: protection.backup }),
|
|
458
|
-
...(protection.snapshots === undefined
|
|
459
|
-
? {}
|
|
460
|
-
: { snapshots: protection.snapshots }),
|
|
461
|
-
...(protection.consistency === undefined
|
|
462
|
-
? {}
|
|
463
|
-
: { consistency: protection.consistency }),
|
|
464
|
-
}, labelArg);
|
|
465
|
-
}
|
|
466
|
-
function validateObjectStorageProtection(protectionArg, labelArg) {
|
|
467
|
-
if (protectionArg === undefined)
|
|
468
|
-
return undefined;
|
|
469
|
-
const protection = assertPlainRecord(protectionArg, labelArg);
|
|
470
|
-
assertExactKeys(protection, ['backup', 'versioning', 'retentionDays'], labelArg);
|
|
471
|
-
assertOptionalMember(protection.backup, ['required'], `${labelArg}.backup`);
|
|
472
|
-
assertOptionalMember(protection.versioning, ['required'], `${labelArg}.versioning`);
|
|
473
|
-
if (protection.retentionDays !== undefined
|
|
474
|
-
&& (!Number.isInteger(protection.retentionDays)
|
|
475
|
-
|| protection.retentionDays < 1
|
|
476
|
-
|| protection.retentionDays > 36500)) {
|
|
477
|
-
throw new Error(`Invalid ${labelArg}.retentionDays: expected an integer between 1 and 36500`);
|
|
478
|
-
}
|
|
479
|
-
return assertProtectionDeclaresRequirement({
|
|
480
|
-
...(protection.backup === undefined
|
|
481
|
-
? {}
|
|
482
|
-
: { backup: protection.backup }),
|
|
483
|
-
...(protection.versioning === undefined
|
|
484
|
-
? {}
|
|
485
|
-
: { versioning: protection.versioning }),
|
|
486
|
-
...(protection.retentionDays === undefined
|
|
487
|
-
? {}
|
|
488
|
-
: { retentionDays: protection.retentionDays }),
|
|
489
|
-
}, labelArg);
|
|
490
|
-
}
|
|
491
|
-
function validateObjectStorageDelivery(deliveryArg, requestLabelArg, declaredEnvironmentKeysArg, runtimeEnvironmentKeysArg, deliveryEnvironmentKeysArg, declaredSecretPathsArg, deliverySecretPathsArg) {
|
|
492
|
-
const deliveryLabel = `${requestLabelArg}.delivery`;
|
|
493
|
-
const delivery = assertPlainRecord(deliveryArg, deliveryLabel);
|
|
494
|
-
if (delivery.type === 'launcher-environment') {
|
|
495
|
-
assertExactKeys(delivery, ['type', 'keys'], deliveryLabel);
|
|
496
|
-
const keys = assertPlainRecord(delivery.keys, `${deliveryLabel}.keys`);
|
|
497
|
-
assertExactKeys(keys, [
|
|
498
|
-
'endpoint', 'bucket', 'region', 'accessKeyId', 'secretAccessKey', 'sessionToken',
|
|
499
|
-
], `${deliveryLabel}.keys`);
|
|
500
|
-
for (const requiredKey of ['endpoint', 'bucket', 'region', 'accessKeyId', 'secretAccessKey']) {
|
|
501
|
-
if (typeof keys[requiredKey] !== 'string') {
|
|
502
|
-
throw new Error(`Invalid ${deliveryLabel}.keys: '${requiredKey}' is required`);
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
const targetKeys = Object.values(keys);
|
|
506
|
-
const localKeys = new Set();
|
|
507
|
-
for (const targetKeyArg of targetKeys) {
|
|
508
|
-
if (typeof targetKeyArg !== 'string' || !environmentKeyPattern.test(targetKeyArg)) {
|
|
509
|
-
throw new Error(`Invalid ${deliveryLabel}: environment delivery keys must be canonical`);
|
|
510
|
-
}
|
|
511
|
-
if (localKeys.has(targetKeyArg)) {
|
|
512
|
-
throw new Error(`Invalid ${deliveryLabel}: environment key '${targetKeyArg}' is duplicated`);
|
|
513
|
-
}
|
|
514
|
-
if (declaredEnvironmentKeysArg.has(targetKeyArg)
|
|
515
|
-
|| runtimeEnvironmentKeysArg.has(targetKeyArg)) {
|
|
516
|
-
throw new Error(`Invalid ${deliveryLabel}: environment key '${targetKeyArg}' collides with an app runtime input`);
|
|
517
|
-
}
|
|
518
|
-
if (deliveryEnvironmentKeysArg.has(targetKeyArg)) {
|
|
519
|
-
throw new Error(`Invalid ${deliveryLabel}: environment key '${targetKeyArg}' is used by another storage request`);
|
|
520
|
-
}
|
|
521
|
-
localKeys.add(targetKeyArg);
|
|
522
|
-
deliveryEnvironmentKeysArg.add(targetKeyArg);
|
|
523
|
-
}
|
|
524
|
-
return {
|
|
525
|
-
type: 'launcher-environment',
|
|
526
|
-
keys: { ...keys },
|
|
527
|
-
};
|
|
528
|
-
}
|
|
529
|
-
if (delivery.type === 'file') {
|
|
530
|
-
assertExactKeys(delivery, ['type', 'targetPath', 'format', 'uid', 'gid', 'mode'], deliveryLabel);
|
|
531
|
-
if (delivery.format !== 'servezone-object-storage') {
|
|
532
|
-
throw new Error(`Invalid ${deliveryLabel}: secret file format is not supported`);
|
|
533
|
-
}
|
|
534
|
-
if (typeof delivery.targetPath !== 'string'
|
|
535
|
-
|| interfaces.data.normalizeServiceAbsolutePath(delivery.targetPath) !== delivery.targetPath
|
|
536
|
-
|| !/^\/run\/secrets\/[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(delivery.targetPath)) {
|
|
537
|
-
throw new Error(`Invalid ${deliveryLabel}: targetPath must be a unique canonical file below /run/secrets`);
|
|
538
|
-
}
|
|
539
|
-
if (declaredSecretPathsArg.has(delivery.targetPath)) {
|
|
540
|
-
throw new Error(`Invalid ${deliveryLabel}: targetPath collides with an app secret delivery`);
|
|
541
|
-
}
|
|
542
|
-
if (deliverySecretPathsArg.has(delivery.targetPath)) {
|
|
543
|
-
throw new Error(`Invalid ${deliveryLabel}: targetPath is used by another storage request`);
|
|
544
|
-
}
|
|
545
|
-
// `-0` survives JSON.parse and passes both the safe-integer and the range check, but the
|
|
546
|
-
// storage contract refuses it because it is a second spelling of the same identity and would
|
|
547
|
-
// give one request two canonical digests.
|
|
548
|
-
for (const identityField of ['uid', 'gid']) {
|
|
549
|
-
if (!Number.isSafeInteger(delivery[identityField])
|
|
550
|
-
|| Object.is(delivery[identityField], -0)
|
|
551
|
-
|| delivery[identityField] < 0
|
|
552
|
-
|| delivery[identityField] > 2_147_483_647) {
|
|
553
|
-
throw new Error(`Invalid ${deliveryLabel}: ${identityField} must be a bounded numeric identity`);
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
if (delivery.mode !== 0o400 && delivery.mode !== 0o440) {
|
|
557
|
-
throw new Error(`Invalid ${deliveryLabel}: mode must be 0400 or 0440`);
|
|
558
|
-
}
|
|
559
|
-
deliverySecretPathsArg.add(delivery.targetPath);
|
|
560
|
-
return {
|
|
561
|
-
type: 'file',
|
|
562
|
-
targetPath: delivery.targetPath,
|
|
563
|
-
format: 'servezone-object-storage',
|
|
564
|
-
uid: delivery.uid,
|
|
565
|
-
gid: delivery.gid,
|
|
566
|
-
mode: delivery.mode,
|
|
567
|
-
};
|
|
568
|
-
}
|
|
569
|
-
throw new Error(`Invalid ${deliveryLabel}: type must be launcher-environment or file`);
|
|
570
|
-
}
|
|
571
|
-
function validateFeatureDeclaration(configArg, explicitRequestsArg, labelArg) {
|
|
572
|
-
const requiredFeatures = new Set();
|
|
573
|
-
if (explicitRequestsArg.length > 0) {
|
|
574
|
-
requiredFeatures.add(storageFeatureIds.bindings);
|
|
575
|
-
}
|
|
576
|
-
if (explicitRequestsArg.some((requestArg) => requestArg.kind === 'filesystem')) {
|
|
577
|
-
requiredFeatures.add(storageFeatureIds.filesystem);
|
|
578
|
-
}
|
|
579
|
-
if (explicitRequestsArg.some((requestArg) => requestArg.kind === 'objectStorage')) {
|
|
580
|
-
requiredFeatures.add(storageFeatureIds.objectStorage);
|
|
581
|
-
}
|
|
582
|
-
if (explicitRequestsArg.some((requestArg) => (requestArg.kind === 'objectStorage' && requestArg.delivery.type === 'file'))) {
|
|
583
|
-
requiredFeatures.add(storageFeatureIds.objectStorageFile);
|
|
584
|
-
}
|
|
585
|
-
const declaredFeatures = configArg.requiresFeatures || [];
|
|
586
|
-
if (!Array.isArray(declaredFeatures)
|
|
587
|
-
|| declaredFeatures.some((entryArg) => typeof entryArg !== 'string')) {
|
|
588
|
-
throw new Error(`Invalid ${labelArg}: requiresFeatures must be an array of strings`);
|
|
589
|
-
}
|
|
590
|
-
if (new Set(declaredFeatures).size !== declaredFeatures.length) {
|
|
591
|
-
throw new Error(`Invalid ${labelArg}: requiresFeatures must not contain duplicates`);
|
|
592
|
-
}
|
|
593
|
-
for (const requiredFeature of requiredFeatures) {
|
|
594
|
-
if (!declaredFeatures.includes(requiredFeature)) {
|
|
595
|
-
throw new Error(`Invalid ${labelArg}: requiresFeatures is missing '${requiredFeature}'`);
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
for (const declaredFeature of declaredFeatures) {
|
|
599
|
-
if (declaredFeature.startsWith('storage.') && !knownStorageFeatureIds.has(declaredFeature)) {
|
|
600
|
-
throw new Error(`Invalid ${labelArg}: unknown storage feature '${declaredFeature}'`);
|
|
601
|
-
}
|
|
602
|
-
if (knownStorageFeatureIds.has(declaredFeature)
|
|
603
|
-
&& !requiredFeatures.has(declaredFeature)) {
|
|
604
|
-
throw new Error(`Invalid ${labelArg}: storage feature '${declaredFeature}' is not used`);
|
|
605
|
-
}
|
|
606
|
-
}
|
|
607
|
-
return Array.from(requiredFeatures);
|
|
608
|
-
}
|
|
609
|
-
function validatePlatformRequirements(requirementsArg, labelArg) {
|
|
610
|
-
if (requirementsArg === undefined)
|
|
611
|
-
return;
|
|
612
|
-
const requirements = assertPlainRecord(requirementsArg, `${labelArg} platformRequirements`);
|
|
613
|
-
assertExactKeys(requirements, ['mongodb', 's3', 'clickhouse', 'valkey', 'mariadb', 'mail'], `${labelArg} platformRequirements`);
|
|
614
|
-
for (const [keyArg, valueArg] of Object.entries(requirements)) {
|
|
615
|
-
if (typeof valueArg !== 'boolean') {
|
|
616
|
-
throw new Error(`Invalid ${labelArg} platformRequirements.${keyArg}: expected a boolean`);
|
|
617
|
-
}
|
|
618
|
-
}
|
|
619
|
-
}
|
|
620
|
-
function normalizeLegacyVolumes(volumesArg, labelArg) {
|
|
621
|
-
if (volumesArg === undefined)
|
|
622
|
-
return [];
|
|
623
|
-
if (!Array.isArray(volumesArg) || volumesArg.length > 64) {
|
|
624
|
-
throw new Error(`Invalid ${labelArg}: volumes must be an array with at most 64 entries`);
|
|
625
|
-
}
|
|
626
|
-
return volumesArg.map((volumeArg, indexArg) => {
|
|
627
|
-
const volumeLabel = `${labelArg} volumes[${indexArg}]`;
|
|
628
|
-
const normalized = typeof volumeArg === 'string'
|
|
629
|
-
? { mountPath: volumeArg }
|
|
630
|
-
: assertPlainRecord(volumeArg, volumeLabel);
|
|
631
|
-
assertExactKeys(normalized, ['name', 'source', 'mountPath', 'driver', 'readOnly', 'backup', 'options'], volumeLabel);
|
|
632
|
-
for (const forbiddenKey of ['source', 'driver', 'options']) {
|
|
633
|
-
if (normalized[forbiddenKey] !== undefined) {
|
|
634
|
-
throw new Error(`Invalid ${volumeLabel}: physical field '${forbiddenKey}' cannot be normalized portably`);
|
|
635
|
-
}
|
|
636
|
-
}
|
|
637
|
-
if (typeof normalized.mountPath !== 'string'
|
|
638
|
-
|| interfaces.data.normalizeServiceAbsolutePath(normalized.mountPath) !== normalized.mountPath
|
|
639
|
-
|| normalized.mountPath === '/'
|
|
640
|
-
|| pathsOverlap(normalized.mountPath, '/run/secrets')) {
|
|
641
|
-
throw new Error(`Invalid ${volumeLabel}: mountPath must be a canonical non-root path outside /run/secrets`);
|
|
642
|
-
}
|
|
643
|
-
if (normalized.name !== undefined
|
|
644
|
-
&& (typeof normalized.name !== 'string' || !storageRequestIdPattern.test(normalized.name))) {
|
|
645
|
-
throw new Error(`Invalid ${volumeLabel}: name must be a stable lowercase identifier`);
|
|
646
|
-
}
|
|
647
|
-
for (const booleanKey of ['readOnly', 'backup']) {
|
|
648
|
-
if (normalized[booleanKey] !== undefined && typeof normalized[booleanKey] !== 'boolean') {
|
|
649
|
-
throw new Error(`Invalid ${volumeLabel}.${booleanKey}: expected a boolean`);
|
|
650
|
-
}
|
|
651
|
-
}
|
|
652
|
-
return {
|
|
653
|
-
...(normalized.name === undefined ? {} : { name: normalized.name }),
|
|
654
|
-
mountPath: normalized.mountPath,
|
|
655
|
-
...(normalized.readOnly === undefined ? {} : { readOnly: normalized.readOnly }),
|
|
656
|
-
...(normalized.backup === undefined ? {} : { backup: normalized.backup }),
|
|
657
|
-
};
|
|
658
|
-
});
|
|
659
|
-
}
|
|
660
|
-
function createLegacyVolumeRequestId(volumeArg, indexArg, labelArg) {
|
|
661
|
-
const stablePart = volumeArg.name || volumeArg.mountPath
|
|
662
|
-
.toLowerCase()
|
|
663
|
-
.split('/')
|
|
664
|
-
.filter(Boolean)
|
|
665
|
-
.join('-')
|
|
666
|
-
.replace(/[^a-z0-9-]+/g, '-')
|
|
667
|
-
.replace(/^-+|-+$/g, '');
|
|
668
|
-
const requestId = `legacy-volume-${stablePart}`;
|
|
669
|
-
if (!stablePart || !storageRequestIdPattern.test(requestId)) {
|
|
670
|
-
throw new Error(`Invalid ${labelArg} volumes[${indexArg}]: cannot derive a stable request id; declare a shorter lowercase name`);
|
|
671
|
-
}
|
|
672
|
-
return requestId;
|
|
673
|
-
}
|
|
674
|
-
function validateAllFilesystemMountsAndSecretTargets(requestsArg, declaredSecretPathsArg, labelArg) {
|
|
675
|
-
const mountPaths = [];
|
|
676
|
-
const objectSecretPaths = [];
|
|
677
|
-
for (const requestArg of requestsArg) {
|
|
678
|
-
if (requestArg.kind === 'filesystem') {
|
|
679
|
-
assertNoPathCollision(requestArg.mountPath, mountPaths, `${labelArg} request '${requestArg.id}'`);
|
|
680
|
-
mountPaths.push(requestArg.mountPath);
|
|
681
|
-
}
|
|
682
|
-
else if (requestArg.delivery.type === 'file') {
|
|
683
|
-
objectSecretPaths.push(requestArg.delivery.targetPath);
|
|
684
|
-
}
|
|
685
|
-
}
|
|
686
|
-
for (const secretPathArg of [...declaredSecretPathsArg, ...objectSecretPaths]) {
|
|
687
|
-
if (mountPaths.some((mountPathArg) => pathsOverlap(secretPathArg, mountPathArg))) {
|
|
688
|
-
throw new Error(`Invalid ${labelArg}: secret target '${secretPathArg}' overlaps a filesystem mount`);
|
|
689
|
-
}
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
function assertNoPathCollision(pathArg, pathsArg, labelArg) {
|
|
693
|
-
const collision = pathsArg.find((existingPathArg) => pathsOverlap(pathArg, existingPathArg));
|
|
694
|
-
if (collision) {
|
|
695
|
-
throw new Error(`Invalid ${labelArg}: path '${pathArg}' overlaps '${collision}'`);
|
|
696
|
-
}
|
|
697
|
-
}
|
|
698
|
-
function pathsOverlap(leftArg, rightArg) {
|
|
699
|
-
const left = interfaces.data.normalizeServiceAbsolutePath(leftArg);
|
|
700
|
-
const right = interfaces.data.normalizeServiceAbsolutePath(rightArg);
|
|
701
|
-
if (!left || !right)
|
|
702
|
-
return false;
|
|
703
|
-
if (left === '/' || right === '/')
|
|
704
|
-
return true;
|
|
705
|
-
return left === right || left.startsWith(`${right}/`) || right.startsWith(`${left}/`);
|
|
706
|
-
}
|
|
707
|
-
function assertPlainRecord(valueArg, labelArg) {
|
|
708
|
-
if (!valueArg || typeof valueArg !== 'object' || Array.isArray(valueArg)) {
|
|
709
|
-
throw new Error(`Invalid ${labelArg}: expected an object`);
|
|
710
|
-
}
|
|
711
|
-
return valueArg;
|
|
712
|
-
}
|
|
713
|
-
function assertExactKeys(recordArg, allowedKeysArg, labelArg) {
|
|
714
|
-
const allowedKeys = new Set(allowedKeysArg);
|
|
715
|
-
const unknownKeys = Object.keys(recordArg).filter((keyArg) => !allowedKeys.has(keyArg));
|
|
716
|
-
if (unknownKeys.length > 0) {
|
|
717
|
-
throw new Error(`Invalid ${labelArg}: unknown field(s) ${unknownKeys.sort().join(', ')}`);
|
|
718
|
-
}
|
|
719
|
-
}
|
|
720
|
-
function assertOptionalMember(valueArg, allowedValuesArg, labelArg, optionalArg = true) {
|
|
721
|
-
if (valueArg === undefined && optionalArg)
|
|
722
|
-
return;
|
|
723
|
-
if (typeof valueArg !== 'string' || !allowedValuesArg.includes(valueArg)) {
|
|
724
|
-
throw new Error(`Invalid ${labelArg}: expected one of ${allowedValuesArg.join(', ')}`);
|
|
725
|
-
}
|
|
726
|
-
}
|
|
727
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RvcmFnZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzX2NsaWVudC9zdG9yYWdlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxVQUFVLE1BQU0sd0JBQXdCLENBQUM7QUFTckQsTUFBTSxpQkFBaUIsR0FBRyxVQUFVLENBQUMsUUFBUSxDQUFDLHlCQUF5QixDQUFDO0FBQ3hFLE1BQU0sc0JBQXNCLEdBQUcsSUFBSSxHQUFHLENBQVMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLENBQUM7QUFDakYsTUFBTSxzQkFBc0IsR0FBRyw4QkFBOEIsQ0FBQztBQUM5RCxNQUFNLHVCQUF1QixHQUFHLHdCQUF3QixDQUFDO0FBQ3pELE1BQU0scUJBQXFCLEdBQUcsMEJBQTBCLENBQUM7QUFDekQsTUFBTSxlQUFlLEdBQUcsa0NBQWtDLENBQUM7QUFDM0QsTUFBTSxtQkFBbUIsR0FBRztJQUMxQixHQUFHLEVBQUUsS0FBSztJQUNWLEdBQUcsRUFBRSxLQUFLLElBQUksRUFBRTtJQUNoQixHQUFHLEVBQUUsS0FBSyxJQUFJLEVBQUU7SUFDaEIsR0FBRyxFQUFFLEtBQUssSUFBSSxFQUFFO0NBQ1IsQ0FBQztBQUNYLE1BQU0sd0JBQXdCLEdBQUcsa0JBQWtCLENBQUM7QUFDcEQsTUFBTSwyQkFBMkIsR0FBRyxxQkFBcUIsQ0FBQztBQUMxRCxNQUFNLDRCQUE0QixHQUFHLFdBQVcsQ0FBQztBQUNqRCxNQUFNLHlCQUF5QixHQUFHO0lBQ2hDLE9BQU87SUFDUCxNQUFNO0lBQ04sZUFBZTtJQUNmLGFBQWE7SUFDYixTQUFTO0lBQ1Qsb0JBQW9CO0lBQ3BCLFNBQVM7SUFDVCxTQUFTO0lBQ1QsZ0JBQWdCO0lBQ2hCLGlCQUFpQjtJQUNqQixnQkFBZ0I7SUFDaEIsc0JBQXNCO0lBQ3RCLGNBQWM7SUFDZCxrQkFBa0I7SUFDbEIsbUJBQW1CO0lBQ25CLGlCQUFpQjtJQUNqQixpQkFBaUI7SUFDakIsUUFB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
|
|
151
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RvcmFnZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzX2NsaWVudC9zdG9yYWdlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBWXhDLE1BQU0saUJBQWlCLEdBQUcsT0FBTyxDQUFDLG1CQUFtQixDQUFDLFFBQVEsQ0FBQyx5QkFBeUIsQ0FBQztBQUN6RixNQUFNLHdCQUF3QixHQUFHLGtCQUFrQixDQUFDO0FBQ3BELE1BQU0sMkJBQTJCLEdBQUcscUJBQXFCLENBQUM7QUFDMUQsTUFBTSw0QkFBNEIsR0FBRyxXQUFXLENBQUM7QUFDakQsTUFBTSx1QkFBdUIsR0FBRyx3QkFBd0IsQ0FBQztBQUN6RCxNQUFNLFlBQVksR0FBRyxpQkFBaUIsQ0FBQztBQUV2Qzs7O0dBR0c7QUFDSCxNQUFNLGtCQUFrQixHQUFHLENBQUMsU0FBZ0MsRUFBRSxRQUFnQixFQUFRLEVBQUU7SUFDdEYsTUFBTSxNQUFNLEdBQUcsT0FBTyxDQUFDLG1CQUFtQixDQUFDLFFBQVEsQ0FBQyw4QkFBOEIsQ0FBQyxTQUFTLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDeEcsSUFBSSxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUM7UUFBRSxNQUFNLElBQUksS0FBSyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztBQUM1RCxDQUFDLENBQUM7QUFFRixNQUFNLGdCQUFnQixHQUFHLENBQUMsVUFBNEMsRUFBYSxFQUFFLENBQ25GLENBQUMsVUFBVSxJQUFJLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLFNBQVMsRUFBVyxFQUFFO0lBQzVDLE1BQU0sTUFBTSxHQUFHLE9BQU8sU0FBUyxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztJQUNwRixPQUFPO1FBQ0wsR0FBRyxDQUFDLE1B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
|