@serve.zone/interfaces 32.24.0 → 32.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/changelog.md +50 -0
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/data/clusternode.d.ts +16 -1
- package/dist_ts/data/clusternode.js +1 -1
- package/dist_ts/data/serviceruntime.d.ts +14 -5
- package/dist_ts/data/serviceruntime.js +3 -2
- package/dist_ts/platform/index.d.ts +3 -1
- package/dist_ts/platform/index.js +4 -2
- package/dist_ts/platform/objectstorage.d.ts +58 -0
- package/dist_ts/platform/objectstorage.js +136 -1
- package/dist_ts/platform/objectstorageenvironment.d.ts +108 -0
- package/dist_ts/platform/objectstorageenvironment.js +194 -0
- package/dist_ts/platform/objectstorageretention.d.ts +40 -0
- package/dist_ts/platform/objectstorageretention.js +121 -1
- package/dist_ts/requests/node.d.ts +29 -0
- package/package.json +2 -2
- package/readme.md +109 -9
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/data/clusternode.ts +17 -1
- package/ts/data/serviceruntime.ts +14 -4
- package/ts/platform/index.ts +3 -0
- package/ts/platform/objectstorage.ts +180 -0
- package/ts/platform/objectstorageenvironment.ts +321 -0
- package/ts/platform/objectstorageretention.ts +141 -0
- package/ts/requests/node.ts +33 -0
|
@@ -18,4 +18,139 @@ export const validatePlatformObjectStorageBucketName = (bucketNameArg, pathArg =
|
|
|
18
18
|
}
|
|
19
19
|
return [];
|
|
20
20
|
};
|
|
21
|
-
|
|
21
|
+
export const platformObjectStorageEndpointLimits = Object.freeze({
|
|
22
|
+
maximumEndpointLength: 2048,
|
|
23
|
+
maximumRegionLength: 64,
|
|
24
|
+
});
|
|
25
|
+
const platformObjectStorageRegionPattern = /^[a-z0-9](?:[a-z0-9-]{0,62}[a-z0-9])?$/;
|
|
26
|
+
const isPlainObject = (valueArg) => (Boolean(valueArg)
|
|
27
|
+
&& typeof valueArg === 'object'
|
|
28
|
+
&& !Array.isArray(valueArg)
|
|
29
|
+
&& (Object.getPrototypeOf(valueArg) === Object.prototype
|
|
30
|
+
|| Object.getPrototypeOf(valueArg) === null));
|
|
31
|
+
/** Validates an object-storage endpoint and names every reason it is refused. */
|
|
32
|
+
export const validatePlatformObjectStorageEndpoint = (valueArg, pathArg = 'objectstorage endpoint') => {
|
|
33
|
+
if (!isPlainObject(valueArg)
|
|
34
|
+
|| Object.keys(valueArg).length !== 2
|
|
35
|
+
|| !Object.hasOwn(valueArg, 'endpoint')
|
|
36
|
+
|| !Object.hasOwn(valueArg, 'region')) {
|
|
37
|
+
return [`${pathArg} must use its exact schema`];
|
|
38
|
+
}
|
|
39
|
+
const errors = [];
|
|
40
|
+
const endpoint = valueArg.endpoint;
|
|
41
|
+
if (typeof endpoint !== 'string'
|
|
42
|
+
|| endpoint.length === 0
|
|
43
|
+
|| endpoint.length > platformObjectStorageEndpointLimits.maximumEndpointLength) {
|
|
44
|
+
errors.push(`${pathArg} endpoint must be a string of 1 to `
|
|
45
|
+
+ `${platformObjectStorageEndpointLimits.maximumEndpointLength} characters`);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
let parsedEndpoint;
|
|
49
|
+
try {
|
|
50
|
+
parsedEndpoint = new URL(endpoint);
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
errors.push(`${pathArg} endpoint must be a parsable URL`);
|
|
54
|
+
}
|
|
55
|
+
if (parsedEndpoint) {
|
|
56
|
+
if (parsedEndpoint.protocol !== 'http:' && parsedEndpoint.protocol !== 'https:') {
|
|
57
|
+
errors.push(`${pathArg} endpoint must use the http or https scheme`);
|
|
58
|
+
}
|
|
59
|
+
if (parsedEndpoint.username || parsedEndpoint.password) {
|
|
60
|
+
errors.push(`${pathArg} endpoint must not carry userinfo`);
|
|
61
|
+
}
|
|
62
|
+
if (parsedEndpoint.origin !== endpoint) {
|
|
63
|
+
errors.push(`${pathArg} endpoint must be a canonical origin without a path, query, `
|
|
64
|
+
+ 'fragment, trailing slash or default port');
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (typeof valueArg.region !== 'string'
|
|
69
|
+
|| !platformObjectStorageRegionPattern.test(valueArg.region)) {
|
|
70
|
+
errors.push(`${pathArg} region must be 1 to `
|
|
71
|
+
+ `${platformObjectStorageEndpointLimits.maximumRegionLength} lowercase letters, digits `
|
|
72
|
+
+ 'and inner hyphens');
|
|
73
|
+
}
|
|
74
|
+
return errors;
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* The non-secret environment names that tell a workload where its bucket is.
|
|
78
|
+
*
|
|
79
|
+
* These are the names Corestore has always handed a workload for a bucket, so an application that
|
|
80
|
+
* read them keeps working unchanged. The six credential aliases (`S3_ACCESS_KEY`,
|
|
81
|
+
* `S3_ACCESS_KEY_ID`, `S3_SECRET_KEY`, `S3_SECRET_ACCESS_KEY`, `AWS_ACCESS_KEY_ID`,
|
|
82
|
+
* `AWS_SECRET_ACCESS_KEY`) are not among them: they are Secrets and reach the workload only through
|
|
83
|
+
* the binding's sealed Secret set.
|
|
84
|
+
*
|
|
85
|
+
* - `S3_ENDPOINT`, `AWS_ENDPOINT_URL`: the endpoint origin, identical.
|
|
86
|
+
* - `S3_ENDPOINT_HOST`: the origin's host, as the URL states it (an IPv6 literal keeps its brackets).
|
|
87
|
+
* - `S3_PORT`: the origin's port in decimal, `80` or `443` when the origin states none.
|
|
88
|
+
* - `S3_USE_SSL`: `true` for an `https:` origin, `false` for `http:`.
|
|
89
|
+
* - `S3_REGION`, `AWS_REGION`: the signing region, identical.
|
|
90
|
+
* - `S3_BUCKET`: the binding's bucket, `IPlatformBinding.objectstorageBucketName`.
|
|
91
|
+
* - `AWS_S3_FORCE_PATH_STYLE`: always `true` — a node-local origin has no wildcard DNS and a bucket
|
|
92
|
+
* name may contain dots, so path-style addressing is the only one that reaches the bucket.
|
|
93
|
+
*/
|
|
94
|
+
export const objectStorageEndpointEnvironmentKeys = Object.freeze([
|
|
95
|
+
'S3_ENDPOINT',
|
|
96
|
+
'S3_ENDPOINT_HOST',
|
|
97
|
+
'S3_PORT',
|
|
98
|
+
'S3_REGION',
|
|
99
|
+
'S3_BUCKET',
|
|
100
|
+
'S3_USE_SSL',
|
|
101
|
+
'AWS_ENDPOINT_URL',
|
|
102
|
+
'AWS_REGION',
|
|
103
|
+
'AWS_S3_FORCE_PATH_STYLE',
|
|
104
|
+
]);
|
|
105
|
+
/**
|
|
106
|
+
* The endpoint environment for one bucket.
|
|
107
|
+
*
|
|
108
|
+
* Throws the first reason the endpoint or the bucket name is refused; nothing is defaulted.
|
|
109
|
+
*/
|
|
110
|
+
export const createObjectStorageEndpointEnvironment = (endpointArg, bucketNameArg) => {
|
|
111
|
+
const errors = [
|
|
112
|
+
...validatePlatformObjectStorageEndpoint(endpointArg),
|
|
113
|
+
...validatePlatformObjectStorageBucketName(bucketNameArg),
|
|
114
|
+
];
|
|
115
|
+
if (errors.length > 0)
|
|
116
|
+
throw new Error(errors[0]);
|
|
117
|
+
const origin = new URL(endpointArg.endpoint);
|
|
118
|
+
const useSsl = origin.protocol === 'https:';
|
|
119
|
+
return {
|
|
120
|
+
S3_ENDPOINT: endpointArg.endpoint,
|
|
121
|
+
S3_ENDPOINT_HOST: origin.hostname,
|
|
122
|
+
S3_PORT: origin.port || (useSsl ? '443' : '80'),
|
|
123
|
+
S3_REGION: endpointArg.region,
|
|
124
|
+
S3_BUCKET: bucketNameArg,
|
|
125
|
+
S3_USE_SSL: useSsl ? 'true' : 'false',
|
|
126
|
+
AWS_ENDPOINT_URL: endpointArg.endpoint,
|
|
127
|
+
AWS_REGION: endpointArg.region,
|
|
128
|
+
AWS_S3_FORCE_PATH_STYLE: 'true',
|
|
129
|
+
};
|
|
130
|
+
};
|
|
131
|
+
/**
|
|
132
|
+
* Validates an endpoint environment: exactly its nine keys, each value the one
|
|
133
|
+
* `createObjectStorageEndpointEnvironment()` derives from the same endpoint and bucket.
|
|
134
|
+
*/
|
|
135
|
+
export const validateObjectStorageEndpointEnvironment = (environmentArg, pathArg = 'objectstorage endpoint environment') => {
|
|
136
|
+
if (!isPlainObject(environmentArg)
|
|
137
|
+
|| Object.keys(environmentArg).length !== objectStorageEndpointEnvironmentKeys.length
|
|
138
|
+
|| objectStorageEndpointEnvironmentKeys.some((keyArg) => (!Object.hasOwn(environmentArg, keyArg) || typeof environmentArg[keyArg] !== 'string'))) {
|
|
139
|
+
return [`${pathArg} must contain exactly its string keys`];
|
|
140
|
+
}
|
|
141
|
+
const endpoint = { endpoint: environmentArg.S3_ENDPOINT, region: environmentArg.S3_REGION };
|
|
142
|
+
const errors = [
|
|
143
|
+
...validatePlatformObjectStorageEndpoint(endpoint, pathArg),
|
|
144
|
+
...validatePlatformObjectStorageBucketName(environmentArg.S3_BUCKET, `${pathArg} S3_BUCKET`),
|
|
145
|
+
];
|
|
146
|
+
if (errors.length > 0)
|
|
147
|
+
return errors;
|
|
148
|
+
const expected = createObjectStorageEndpointEnvironment(endpoint, environmentArg.S3_BUCKET);
|
|
149
|
+
for (const key of objectStorageEndpointEnvironmentKeys) {
|
|
150
|
+
if (environmentArg[key] !== expected[key]) {
|
|
151
|
+
errors.push(`${pathArg} ${key} must equal the value derived from its endpoint`);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return errors;
|
|
155
|
+
};
|
|
156
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib2JqZWN0c3RvcmFnZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL3BsYXRmb3JtL29iamVjdHN0b3JhZ2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBT0EsTUFBTSxDQUFDLE1BQU0scUNBQXFDLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQztJQUNqRSxZQUFZLEVBQUUsQ0FBQztJQUNmLFlBQVksRUFBRSxFQUFFO0NBQ2pCLENBQUMsQ0FBQztBQUVILHNGQUFzRjtBQUN0RixNQUFNLENBQUMsTUFBTSx1Q0FBdUMsR0FBRyxDQUNyRCxhQUFzQixFQUN0QixPQUFPLEdBQUcsMEJBQTBCLEVBQzFCLEVBQUU7SUFDWixJQUFJLE9BQU8sYUFBYSxLQUFLLFFBQVEsRUFBRSxDQUFDO1FBQ3RDLE9BQU8sQ0FBQyxHQUFHLE9BQU8scUNBQXFDLENBQUMsQ0FBQztJQUMzRCxDQUFDO0lBQ0QsTUFBTSxTQUFTLEdBQUcsYUFBYSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUMzQyxNQUFNLGFBQWEsR0FBRyxTQUFTLENBQUMsTUFBTSxLQUFLLENBQUMsSUFBSSxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxDQUMzRSxVQUFVLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsSUFBSSxHQUFHLENBQ25ELENBQUMsQ0FBQztJQUNILElBQUksYUFBYSxDQUFDLE1BQU0sR0FBRyxxQ0FBcUMsQ0FBQyxZQUFZO1dBQ3hFLGFBQWEsQ0FBQyxNQUFNLEdBQUcscUNBQXFDLENBQUMsWUFBWTtXQUN6RSxDQUFDLCtCQUErQixDQUFDLElBQUksQ0FBQyxhQUFhLENBQUM7V0FDcEQsYUFBYSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUM7V0FDNUIsYUFBYSxFQUFFLENBQUM7UUFDbkIsT0FBTyxDQUFDLEdBQUcsT0FBTyxxQ0FBcUMsQ0FBQyxDQUFDO0lBQzNELENBQUM7SUFDRCxPQUFPLEVBQUUsQ0FBQztBQUNaLENBQUMsQ0FBQztBQXFCRixNQUFNLENBQUMsTUFBTSxtQ0FBbUMsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDO0lBQy9ELHFCQUFxQixFQUFFLElBQUk7SUFDM0IsbUJBQW1CLEVBQUUsRUFBRTtDQUN4QixDQUFDLENBQUM7QUFFSCxNQUFNLGtDQUFrQyxHQUFHLHdDQUF3QyxDQUFDO0FBRXBGLE1BQU0sYUFBYSxHQUFHLENBQUMsUUFBaUIsRUFBdUMsRUFBRSxDQUFDLENBQ2hGLE9BQU8sQ0FBQyxRQUFRLENBQUM7T0FDZCxPQUFPLFFBQVEsS0FBSyxRQUFRO09BQzVCLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUM7T0FDeEIsQ0FBQyxNQUFNLENBQUMsY0FBYyxDQUFDLFFBQVEsQ0FBQyxLQUFLLE1BQU0sQ0FBQyxTQUFTO1dBQ25ELE1BQU0sQ0FBQyxjQUFjLENBQUMsUUFBUSxDQUFDLEtBQUssSUFBSSxDQUFDLENBQy9DLENBQUM7QUFFRixpRkFBaUY7QUFDakYsTUFBTSxDQUFDLE1BQU0scUNBQXFDLEdBQUcsQ0FDbkQsUUFBaUIsRUFDakIsT0FBTyxHQUFHLHdCQUF3QixFQUN4QixFQUFFO0lBQ1osSUFBSSxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUM7V0FDdkIsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxNQUFNLEtBQUssQ0FBQztXQUNsQyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFLFVBQVUsQ0FBQztXQUNwQyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFLFFBQVEsQ0FBQyxFQUFFLENBQUM7UUFDeEMsT0FBTyxDQUFDLEdBQUcsT0FBTyw0QkFBNEIsQ0FBQyxDQUFDO0lBQ2xELENBQUM7SUFDRCxNQUFNLE1BQU0sR0FBYSxFQUFFLENBQUM7SUFDNUIsTUFBTSxRQUFRLEdBQUcsUUFBUSxDQUFDLFFBQVEsQ0FBQztJQUNuQyxJQUFJLE9BQU8sUUFBUSxLQUFLLFFBQVE7V0FDM0IsUUFBUSxDQUFDLE1BQU0sS0FBSyxDQUFDO1dBQ3JCLFFBQVEsQ0FBQyxNQUFNLEdBQUcsbUNBQW1DLENBQUMscUJBQXFCLEVBQUUsQ0FBQztRQUNqRixNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsT0FBTyxxQ0FBcUM7Y0FDdkQsR0FBRyxtQ0FBbUMsQ0FBQyxxQkFBcUIsYUFBYSxDQUFDLENBQUM7SUFDakYsQ0FBQztTQUFNLENBQUM7UUFDTixJQUFJLGNBQStCLENBQUM7UUFDcEMsSUFBSSxDQUFDO1lBQ0gsY0FBYyxHQUFHLElBQUksR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3JDLENBQUM7UUFBQyxNQUFNLENBQUM7WUFDUCxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsT0FBTyxrQ0FBa0MsQ0FBQyxDQUFDO1FBQzVELENBQUM7UUFDRCxJQUFJLGNBQWMsRUFBRSxDQUFDO1lBQ25CLElBQUksY0FBYyxDQUFDLFFBQVEsS0FBSyxPQUFPLElBQUksY0FBYyxDQUFDLFFBQVEsS0FBSyxRQUFRLEVBQUUsQ0FBQztnQkFDaEYsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLE9BQU8sNkNBQTZDLENBQUMsQ0FBQztZQUN2RSxDQUFDO1lBQ0QsSUFBSSxjQUFjLENBQUMsUUFBUSxJQUFJLGNBQWMsQ0FBQyxRQUFRLEVBQUUsQ0FBQztnQkFDdkQsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLE9BQU8sbUNBQW1DLENBQUMsQ0FBQztZQUM3RCxDQUFDO1lBQ0QsSUFBSSxjQUFjLENBQUMsTUFBTSxLQUFLLFFBQVEsRUFBRSxDQUFDO2dCQUN2QyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsT0FBTyw4REFBOEQ7c0JBQ2hGLDBDQUEwQyxDQUFDLENBQUM7WUFDbEQsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0lBQ0QsSUFBSSxPQUFPLFFBQVEsQ0FBQyxNQUFNLEtBQUssUUFBUTtXQUNsQyxDQUFDLGtDQUFrQyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztRQUMvRCxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsT0FBTyx1QkFBdUI7Y0FDekMsR0FBRyxtQ0FBbUMsQ0FBQyxtQkFBbUIsNkJBQTZCO2NBQ3ZGLG1CQUFtQixDQUFDLENBQUM7SUFDM0IsQ0FBQztJQUNELE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUMsQ0FBQztBQUVGOzs7Ozs7Ozs7Ozs7Ozs7OztHQWlCRztBQUNILE1BQU0sQ0FBQyxNQUFNLG9DQUFvQyxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUM7SUFDaEUsYUFBYTtJQUNiLGtCQUFrQjtJQUNsQixTQUFTO0lBQ1QsV0FBVztJQUNYLFdBQVc7SUFDWCxZQUFZO0lBQ1osa0JBQWtCO0lBQ2xCLFlBQVk7SUFDWix5QkFBeUI7Q0FDakIsQ0FBQyxDQUFDO0FBU1o7Ozs7R0FJRztBQUNILE1BQU0sQ0FBQyxNQUFNLHNDQUFzQyxHQUFHLENBQ3BELFdBQTJDLEVBQzNDLGFBQXFCLEVBQ2MsRUFBRTtJQUNyQyxNQUFNLE1BQU0sR0FBRztRQUNiLEdBQUcscUNBQXFDLENBQUMsV0FBVyxDQUFDO1FBQ3JELEdBQUcsdUNBQXVDLENBQUMsYUFBYSxDQUFDO0tBQzFELENBQUM7SUFDRixJQUFJLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQztRQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDbEQsTUFBTSxNQUFNLEdBQUcsSUFBSSxHQUFHLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQzdDLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxRQUFRLEtBQUssUUFBUSxDQUFDO0lBQzVDLE9BQU87UUFDTCxXQUFXLEVBQUUsV0FBVyxDQUFDLFFBQVE7UUFDakMsZ0JBQWdCLEVBQUUsTUFBTSxDQUFDLFFBQVE7UUFDakMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO1FBQy9DLFNBQVMsRUFBRSxXQUFXLENBQUMsTUFBTTtRQUM3QixTQUFTLEVBQUUsYUFBYTtRQUN4QixVQUFVLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLE9BQU87UUFDckMsZ0JBQWdCLEVBQUUsV0FBVyxDQUFDLFFBQVE7UUFDdEMsVUFBVSxFQUFFLFdBQVcsQ0FBQyxNQUFNO1FBQzlCLHVCQUF1QixFQUFFLE1BQU07S0FDaEMsQ0FBQztBQUNKLENBQUMsQ0FBQztBQUVGOzs7R0FHRztBQUNILE1BQU0sQ0FBQyxNQUFNLHdDQUF3QyxHQUFHLENBQ3RELGNBQXVCLEVBQ3ZCLE9BQU8sR0FBRyxvQ0FBb0MsRUFDcEMsRUFBRTtJQUNaLElBQUksQ0FBQyxhQUFhLENBQUMsY0FBYyxDQUFDO1dBQzdCLE1BQU0sQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLENBQUMsTUFBTSxLQUFLLG9DQUFvQyxDQUFDLE1BQU07V0FDbEYsb0NBQW9DLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxDQUN2RCxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsY0FBYyxFQUFFLE1BQU0sQ0FBQyxJQUFJLE9BQU8sY0FBYyxDQUFDLE1BQU0sQ0FBQyxLQUFLLFFBQVEsQ0FDckYsQ0FBQyxFQUFFLENBQUM7UUFDTCxPQUFPLENBQUMsR0FBRyxPQUFPLHVDQUF1QyxDQUFDLENBQUM7SUFDN0QsQ0FBQztJQUNELE1BQU0sUUFBUSxHQUFHLEVBQUUsUUFBUSxFQUFFLGNBQWMsQ0FBQyxXQUFXLEVBQUUsTUFBTSxFQUFFLGNBQWMsQ0FBQyxTQUFTLEVBQUUsQ0FBQztJQUM1RixNQUFNLE1BQU0sR0FBRztRQUNiLEdBQUcscUNBQXFDLENBQUMsUUFBUSxFQUFFLE9BQU8sQ0FBQztRQUMzRCxHQUFHLHVDQUF1QyxDQUFDLGNBQWMsQ0FBQyxTQUFTLEVBQUUsR0FBRyxPQUFPLFlBQVksQ0FBQztLQUM3RixDQUFDO0lBQ0YsSUFBSSxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUM7UUFBRSxPQUFPLE1BQU0sQ0FBQztJQUNyQyxNQUFNLFFBQVEsR0FBRyxzQ0FBc0MsQ0FDckQsUUFBMEMsRUFDMUMsY0FBYyxDQUFDLFNBQW1CLENBQ25DLENBQUM7SUFDRixLQUFLLE1BQU0sR0FBRyxJQUFJLG9DQUFvQyxFQUFFLENBQUM7UUFDdkQsSUFBSSxjQUFjLENBQUMsR0FBRyxDQUFDLEtBQUssUUFBUSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDMUMsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLE9BQU8sSUFBSSxHQUFHLGlEQUFpRCxDQUFDLENBQUM7UUFDbEYsQ0FBQztJQUNILENBQUM7SUFDRCxPQUFPLE1BQU0sQ0FBQztBQUNoQixDQUFDLENBQUMifQ==
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import type { IPlatformBinding } from './types.js';
|
|
2
|
+
import type { IPlatformObjectStorageEndpoint, TObjectStorageEndpointEnvironment, TObjectStorageEndpointEnvironmentKey } from './objectstorage.js';
|
|
3
|
+
import type { TServiceRuntimeRefusal, TServiceRuntimeWaitingReason } from '../data/serviceruntime.js';
|
|
4
|
+
import type { TObjectStorageRetentionEnvironment, TObjectStorageRetentionEnvironmentKey } from './objectstorageretention.js';
|
|
5
|
+
/**
|
|
6
|
+
* Every non-secret environment name an object-storage binding can give a workload: the nine
|
|
7
|
+
* endpoint names first, then the eleven retention names.
|
|
8
|
+
*/
|
|
9
|
+
export declare const objectStorageBindingEnvironmentKeys: readonly ["S3_ENDPOINT", "S3_ENDPOINT_HOST", "S3_PORT", "S3_REGION", "S3_BUCKET", "S3_USE_SSL", "AWS_ENDPOINT_URL", "AWS_REGION", "AWS_S3_FORCE_PATH_STYLE", "S3_RETENTION_MODE", "S3_RETENTION_POLICY_ID", "S3_RETENTION_DURATION_SECONDS", "S3_RETENTION_INTENT_SHA256", "S3_RETENTION_SENTINEL_KEY", "S3_RETENTION_CONFIGURED_AT", "S3_RETENTION_SENTINEL_CREATED_AT", "S3_RETENTION_SENTINEL_RETAIN_UNTIL", "S3_RETENTION_SENTINEL_PAYLOAD_SHA256", "S3_RETENTION_SENTINEL_METADATA_SHA256", "S3_RETENTION_SENTINEL_ETAG"];
|
|
10
|
+
export type TObjectStorageBindingEnvironmentKey = TObjectStorageEndpointEnvironmentKey | TObjectStorageRetentionEnvironmentKey;
|
|
11
|
+
/**
|
|
12
|
+
* The non-secret environment of one object-storage binding: always the endpoint names, and the
|
|
13
|
+
* retention names exactly when the binding declares compliance retention. Never a credential.
|
|
14
|
+
*/
|
|
15
|
+
export type TObjectStorageBindingEnvironment = TObjectStorageEndpointEnvironment | (TObjectStorageEndpointEnvironment & TObjectStorageRetentionEnvironment);
|
|
16
|
+
/**
|
|
17
|
+
* The environment Cloudly composes into a workload's runtime configuration for one binding.
|
|
18
|
+
*
|
|
19
|
+
* `bindingArg` is the Cloudly binding document and `endpointArg` the
|
|
20
|
+
* `IClusterNode.data.corestoreObjectStorage` of the node the binding is placed on. Refused by
|
|
21
|
+
* name, never guessed:
|
|
22
|
+
*
|
|
23
|
+
* - a binding that is not `objectstorage` or carries no canonical `objectstorageBucketName`;
|
|
24
|
+
* - an endpoint that `validatePlatformObjectStorageEndpoint()` refuses;
|
|
25
|
+
* - a binding that declares `objectstorageRetention` without `evidence`. Its bucket's retention is
|
|
26
|
+
* not proven yet, so the workload is not given an environment that would let it run as if its
|
|
27
|
+
* bucket were ordinary storage; the caller waits for the evidence.
|
|
28
|
+
* - evidence that does not prove the binding's own service, binding id, bucket and intent.
|
|
29
|
+
*
|
|
30
|
+
* A binding without `objectstorageRetention` gets the endpoint names alone: it promised no
|
|
31
|
+
* retention, so there is nothing to state.
|
|
32
|
+
*
|
|
33
|
+
* The evidence's reconciliation generation and binding-request digest are read from its own
|
|
34
|
+
* authority: they are what Cloudly checked when it admitted the evidence, and the binding document
|
|
35
|
+
* does not repeat them. Everything the binding does state is checked again here.
|
|
36
|
+
*
|
|
37
|
+
* `composeObjectStorageServiceEnvironment()` answers the same questions with a service runtime
|
|
38
|
+
* reason instead of an error.
|
|
39
|
+
*/
|
|
40
|
+
export declare const createObjectStorageBindingEnvironment: (bindingArg: IPlatformBinding, endpointArg: IPlatformObjectStorageEndpoint) => Promise<TObjectStorageBindingEnvironment>;
|
|
41
|
+
/**
|
|
42
|
+
* Validates one binding's environment: the nine endpoint names, the eleven retention names all or
|
|
43
|
+
* none, and nothing else — so a credential alias, or any other name, is refused.
|
|
44
|
+
*/
|
|
45
|
+
export declare const validateObjectStorageBindingEnvironment: (environmentArg: unknown, pathArg?: string) => Promise<string[]>;
|
|
46
|
+
/**
|
|
47
|
+
* A workload environment with one binding's environment added.
|
|
48
|
+
*
|
|
49
|
+
* Refuses, naming every key, when the environment already holds one of the binding's names: a
|
|
50
|
+
* service that sets `S3_ENDPOINT` itself, or a second object-storage binding on the same service,
|
|
51
|
+
* would otherwise have one value silently replace the other. The inputs are not changed.
|
|
52
|
+
*/
|
|
53
|
+
export declare const mergeObjectStorageBindingEnvironment: (environmentArg: Readonly<Record<string, string>>, bindingEnvironmentArg: TObjectStorageBindingEnvironment) => Record<string, string>;
|
|
54
|
+
/** One enabled object-storage binding of a service and the endpoint of the node it is placed on. */
|
|
55
|
+
export interface IObjectStorageBindingEnvironmentSource {
|
|
56
|
+
binding: IPlatformBinding;
|
|
57
|
+
/**
|
|
58
|
+
* The `IClusterNode.data.corestoreObjectStorage` of the node the binding is placed on, `null`
|
|
59
|
+
* when that node states none. A binding placed on no node is not a source: its service waits as
|
|
60
|
+
* `bindings-pending`.
|
|
61
|
+
*/
|
|
62
|
+
endpoint: IPlatformObjectStorageEndpoint | null;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* The service runtime waiting reason an object-storage environment reports:
|
|
66
|
+
* `objectstorage-retention-pending`, a binding that declares compliance retention whose evidence
|
|
67
|
+
* has not arrived.
|
|
68
|
+
*/
|
|
69
|
+
export type TObjectStorageEnvironmentWaitingReason = Extract<TServiceRuntimeWaitingReason, 'objectstorage-retention-pending'>;
|
|
70
|
+
/**
|
|
71
|
+
* The service runtime refusals an object-storage environment reports.
|
|
72
|
+
* `objectstorage-endpoint-missing` is a binding whose node states no valid
|
|
73
|
+
* `corestoreObjectStorage`; `objectstorage-binding-invalid` a binding
|
|
74
|
+
* `createObjectStorageBindingEnvironment()` refuses (not `objectstorage`, no canonical bucket, no
|
|
75
|
+
* canonical retention intent, or evidence that does not prove this binding);
|
|
76
|
+
* `objectstorage-environment-conflict` a name the service's own environment or another binding
|
|
77
|
+
* already sets.
|
|
78
|
+
*/
|
|
79
|
+
export type TObjectStorageEnvironmentRefusal = Extract<TServiceRuntimeRefusal, 'objectstorage-endpoint-missing' | 'objectstorage-binding-invalid' | 'objectstorage-environment-conflict'>;
|
|
80
|
+
/** A service's environment with every object-storage binding added, or the one reason it is not. */
|
|
81
|
+
export type TObjectStorageServiceEnvironmentComposition = {
|
|
82
|
+
status: 'composed';
|
|
83
|
+
environment: Record<string, string>;
|
|
84
|
+
} | {
|
|
85
|
+
status: 'waiting';
|
|
86
|
+
reason: TObjectStorageEnvironmentWaitingReason;
|
|
87
|
+
bindingId: string;
|
|
88
|
+
message: string;
|
|
89
|
+
} | {
|
|
90
|
+
status: 'refused';
|
|
91
|
+
reason: TObjectStorageEnvironmentRefusal;
|
|
92
|
+
bindingId: string;
|
|
93
|
+
message: string;
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* The service's own environment with the environment of every enabled object-storage binding
|
|
97
|
+
* added, or the service runtime reason it cannot be — so a producer reports the contract's
|
|
98
|
+
* verdict instead of classifying its errors.
|
|
99
|
+
*
|
|
100
|
+
* Each binding's names are `createObjectStorageBindingEnvironment()`'s from its node's endpoint,
|
|
101
|
+
* added as `mergeObjectStorageBindingEnvironment()` adds them. Bindings are taken in id order, so
|
|
102
|
+
* the verdict does not depend on the order of `sourcesArg`. A refusal outranks a wait, because a
|
|
103
|
+
* wait resolves on its own and a refusal never does: a binding waiting for retention evidence
|
|
104
|
+
* already claims all twenty of its names, so a collision with it is refused now, not once its
|
|
105
|
+
* evidence arrives. The first refusal is answered, otherwise the first wait, otherwise the
|
|
106
|
+
* composed environment. The inputs are not changed.
|
|
107
|
+
*/
|
|
108
|
+
export declare const composeObjectStorageServiceEnvironment: (serviceEnvironmentArg: Readonly<Record<string, string>>, sourcesArg: readonly IObjectStorageBindingEnvironmentSource[]) => Promise<TObjectStorageServiceEnvironmentComposition>;
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { createObjectStorageEndpointEnvironment, objectStorageEndpointEnvironmentKeys, validateObjectStorageEndpointEnvironment, validatePlatformObjectStorageBucketName, validatePlatformObjectStorageEndpoint, } from './objectstorage.js';
|
|
2
|
+
import { createObjectStorageRetentionEnvironment, objectStorageRetentionEnvironmentKeys, validateObjectStorageRetentionEnvironment, validateObjectStorageRetentionEvidence, validateObjectStorageRetentionIntent, } from './objectstorageretention.js';
|
|
3
|
+
import { isPlainRecord, readDataProperties } from '../private/dataproperties.js';
|
|
4
|
+
/**
|
|
5
|
+
* Every non-secret environment name an object-storage binding can give a workload: the nine
|
|
6
|
+
* endpoint names first, then the eleven retention names.
|
|
7
|
+
*/
|
|
8
|
+
export const objectStorageBindingEnvironmentKeys = Object.freeze([
|
|
9
|
+
...objectStorageEndpointEnvironmentKeys,
|
|
10
|
+
...objectStorageRetentionEnvironmentKeys,
|
|
11
|
+
]);
|
|
12
|
+
/**
|
|
13
|
+
* The one place a binding's environment is decided. `createObjectStorageBindingEnvironment()`
|
|
14
|
+
* throws its message, `composeObjectStorageServiceEnvironment()` reports its reason.
|
|
15
|
+
*/
|
|
16
|
+
const resolveBindingEnvironment = async (bindingArg, endpointArg) => {
|
|
17
|
+
const binding = readDataProperties(bindingArg);
|
|
18
|
+
if (binding === null || binding.capability !== 'objectstorage') {
|
|
19
|
+
return { status: 'refused', reason: 'objectstorage-binding-invalid',
|
|
20
|
+
message: 'objectstorage binding environment requires an objectstorage binding' };
|
|
21
|
+
}
|
|
22
|
+
const bindingName = typeof binding.id === 'string' ? binding.id : '(unnamed)';
|
|
23
|
+
if (validatePlatformObjectStorageBucketName(binding.objectstorageBucketName).length > 0) {
|
|
24
|
+
return { status: 'refused', reason: 'objectstorage-binding-invalid',
|
|
25
|
+
message: `objectstorage binding ${bindingName} carries no canonical bucket name; Cloudly owns `
|
|
26
|
+
+ 'it and no environment invents one' };
|
|
27
|
+
}
|
|
28
|
+
if (endpointArg === null) {
|
|
29
|
+
return { status: 'refused', reason: 'objectstorage-endpoint-missing',
|
|
30
|
+
message: `objectstorage binding ${bindingName} is placed on a node that states no `
|
|
31
|
+
+ 'corestoreObjectStorage endpoint' };
|
|
32
|
+
}
|
|
33
|
+
const endpointErrors = validatePlatformObjectStorageEndpoint(endpointArg);
|
|
34
|
+
if (endpointErrors.length > 0) {
|
|
35
|
+
return { status: 'refused', reason: 'objectstorage-endpoint-missing', message: endpointErrors[0] };
|
|
36
|
+
}
|
|
37
|
+
const bucketName = binding.objectstorageBucketName;
|
|
38
|
+
const endpointEnvironment = createObjectStorageEndpointEnvironment(endpointArg, bucketName);
|
|
39
|
+
const retention = binding.objectstorageRetention;
|
|
40
|
+
if (retention === undefined) {
|
|
41
|
+
return { status: 'composed', environment: endpointEnvironment };
|
|
42
|
+
}
|
|
43
|
+
const retentionBinding = readDataProperties(retention);
|
|
44
|
+
if (retentionBinding === null
|
|
45
|
+
|| validateObjectStorageRetentionIntent(retentionBinding.intent).length > 0) {
|
|
46
|
+
return { status: 'refused', reason: 'objectstorage-binding-invalid',
|
|
47
|
+
message: `objectstorage binding ${bindingName} must declare canonical compliance-retention `
|
|
48
|
+
+ 'intent' };
|
|
49
|
+
}
|
|
50
|
+
const evidence = retentionBinding.evidence;
|
|
51
|
+
if (evidence === undefined) {
|
|
52
|
+
return { status: 'waiting', reason: 'objectstorage-retention-pending',
|
|
53
|
+
message: `objectstorage binding ${bindingName} declares compliance retention without `
|
|
54
|
+
+ 'verified evidence; its workload environment waits for the evidence' };
|
|
55
|
+
}
|
|
56
|
+
const authority = isPlainRecord(evidence) ? readDataProperties(evidence.authority) : null;
|
|
57
|
+
if (authority === null) {
|
|
58
|
+
return { status: 'refused', reason: 'objectstorage-binding-invalid',
|
|
59
|
+
message: 'objectstorage retention evidence must use its exact schema' };
|
|
60
|
+
}
|
|
61
|
+
const expectation = {
|
|
62
|
+
serviceId: binding.serviceId,
|
|
63
|
+
bindingId: binding.id,
|
|
64
|
+
reconciliationGeneration: authority.reconciliationGeneration,
|
|
65
|
+
bindingRequestDigest: authority.bindingRequestDigest,
|
|
66
|
+
bucketName,
|
|
67
|
+
intent: retentionBinding.intent,
|
|
68
|
+
};
|
|
69
|
+
const evidenceErrors = await validateObjectStorageRetentionEvidence(evidence, expectation);
|
|
70
|
+
if (evidenceErrors.length > 0) {
|
|
71
|
+
return { status: 'refused', reason: 'objectstorage-binding-invalid', message: evidenceErrors[0] };
|
|
72
|
+
}
|
|
73
|
+
const retentionEnvironment = await createObjectStorageRetentionEnvironment(evidence, expectation);
|
|
74
|
+
return { status: 'composed', environment: { ...endpointEnvironment, ...retentionEnvironment } };
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* The environment Cloudly composes into a workload's runtime configuration for one binding.
|
|
78
|
+
*
|
|
79
|
+
* `bindingArg` is the Cloudly binding document and `endpointArg` the
|
|
80
|
+
* `IClusterNode.data.corestoreObjectStorage` of the node the binding is placed on. Refused by
|
|
81
|
+
* name, never guessed:
|
|
82
|
+
*
|
|
83
|
+
* - a binding that is not `objectstorage` or carries no canonical `objectstorageBucketName`;
|
|
84
|
+
* - an endpoint that `validatePlatformObjectStorageEndpoint()` refuses;
|
|
85
|
+
* - a binding that declares `objectstorageRetention` without `evidence`. Its bucket's retention is
|
|
86
|
+
* not proven yet, so the workload is not given an environment that would let it run as if its
|
|
87
|
+
* bucket were ordinary storage; the caller waits for the evidence.
|
|
88
|
+
* - evidence that does not prove the binding's own service, binding id, bucket and intent.
|
|
89
|
+
*
|
|
90
|
+
* A binding without `objectstorageRetention` gets the endpoint names alone: it promised no
|
|
91
|
+
* retention, so there is nothing to state.
|
|
92
|
+
*
|
|
93
|
+
* The evidence's reconciliation generation and binding-request digest are read from its own
|
|
94
|
+
* authority: they are what Cloudly checked when it admitted the evidence, and the binding document
|
|
95
|
+
* does not repeat them. Everything the binding does state is checked again here.
|
|
96
|
+
*
|
|
97
|
+
* `composeObjectStorageServiceEnvironment()` answers the same questions with a service runtime
|
|
98
|
+
* reason instead of an error.
|
|
99
|
+
*/
|
|
100
|
+
export const createObjectStorageBindingEnvironment = async (bindingArg, endpointArg) => {
|
|
101
|
+
const resolution = await resolveBindingEnvironment(bindingArg, endpointArg);
|
|
102
|
+
if (resolution.status !== 'composed')
|
|
103
|
+
throw new Error(resolution.message);
|
|
104
|
+
return resolution.environment;
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* Validates one binding's environment: the nine endpoint names, the eleven retention names all or
|
|
108
|
+
* none, and nothing else — so a credential alias, or any other name, is refused.
|
|
109
|
+
*/
|
|
110
|
+
export const validateObjectStorageBindingEnvironment = async (environmentArg, pathArg = 'objectstorage binding environment') => {
|
|
111
|
+
const environment = readDataProperties(environmentArg);
|
|
112
|
+
if (environment === null) {
|
|
113
|
+
return [`${pathArg} must be a plain record of data properties`];
|
|
114
|
+
}
|
|
115
|
+
const allowedKeys = objectStorageBindingEnvironmentKeys;
|
|
116
|
+
const foreignKeys = Object.keys(environment).filter((keyArg) => !allowedKeys.includes(keyArg));
|
|
117
|
+
if (foreignKeys.length > 0) {
|
|
118
|
+
return [`${pathArg} must not contain ${foreignKeys.sort().join(', ')}`];
|
|
119
|
+
}
|
|
120
|
+
const endpointEnvironment = {};
|
|
121
|
+
for (const key of objectStorageEndpointEnvironmentKeys) {
|
|
122
|
+
if (Object.hasOwn(environment, key))
|
|
123
|
+
endpointEnvironment[key] = environment[key];
|
|
124
|
+
}
|
|
125
|
+
const errors = validateObjectStorageEndpointEnvironment(endpointEnvironment, pathArg);
|
|
126
|
+
const retentionKeys = objectStorageRetentionEnvironmentKeys.filter((keyArg) => (Object.hasOwn(environment, keyArg)));
|
|
127
|
+
if (retentionKeys.length > 0) {
|
|
128
|
+
const retentionEnvironment = {};
|
|
129
|
+
for (const key of retentionKeys)
|
|
130
|
+
retentionEnvironment[key] = environment[key];
|
|
131
|
+
errors.push(...await validateObjectStorageRetentionEnvironment(retentionEnvironment, pathArg));
|
|
132
|
+
}
|
|
133
|
+
return errors;
|
|
134
|
+
};
|
|
135
|
+
const findEnvironmentCollisions = (claimedKeysArg, keysArg) => keysArg.filter((keyArg) => claimedKeysArg.has(keyArg)).sort();
|
|
136
|
+
const describeEnvironmentCollisions = (collisionsArg) => (`objectstorage binding environment collides with ${collisionsArg.join(', ')} already set on the `
|
|
137
|
+
+ 'workload');
|
|
138
|
+
/**
|
|
139
|
+
* A workload environment with one binding's environment added.
|
|
140
|
+
*
|
|
141
|
+
* Refuses, naming every key, when the environment already holds one of the binding's names: a
|
|
142
|
+
* service that sets `S3_ENDPOINT` itself, or a second object-storage binding on the same service,
|
|
143
|
+
* would otherwise have one value silently replace the other. The inputs are not changed.
|
|
144
|
+
*/
|
|
145
|
+
export const mergeObjectStorageBindingEnvironment = (environmentArg, bindingEnvironmentArg) => {
|
|
146
|
+
const collisions = findEnvironmentCollisions(new Set(Object.keys(environmentArg)), Object.keys(bindingEnvironmentArg));
|
|
147
|
+
if (collisions.length > 0)
|
|
148
|
+
throw new Error(describeEnvironmentCollisions(collisions));
|
|
149
|
+
return { ...environmentArg, ...bindingEnvironmentArg };
|
|
150
|
+
};
|
|
151
|
+
/**
|
|
152
|
+
* The service's own environment with the environment of every enabled object-storage binding
|
|
153
|
+
* added, or the service runtime reason it cannot be — so a producer reports the contract's
|
|
154
|
+
* verdict instead of classifying its errors.
|
|
155
|
+
*
|
|
156
|
+
* Each binding's names are `createObjectStorageBindingEnvironment()`'s from its node's endpoint,
|
|
157
|
+
* added as `mergeObjectStorageBindingEnvironment()` adds them. Bindings are taken in id order, so
|
|
158
|
+
* the verdict does not depend on the order of `sourcesArg`. A refusal outranks a wait, because a
|
|
159
|
+
* wait resolves on its own and a refusal never does: a binding waiting for retention evidence
|
|
160
|
+
* already claims all twenty of its names, so a collision with it is refused now, not once its
|
|
161
|
+
* evidence arrives. The first refusal is answered, otherwise the first wait, otherwise the
|
|
162
|
+
* composed environment. The inputs are not changed.
|
|
163
|
+
*/
|
|
164
|
+
export const composeObjectStorageServiceEnvironment = async (serviceEnvironmentArg, sourcesArg) => {
|
|
165
|
+
const sources = [...sourcesArg].sort((leftArg, rightArg) => (leftArg.binding.id < rightArg.binding.id ? -1 : leftArg.binding.id > rightArg.binding.id ? 1 : 0));
|
|
166
|
+
let environment = { ...serviceEnvironmentArg };
|
|
167
|
+
const claimedKeys = new Set(Object.keys(environment));
|
|
168
|
+
let wait = null;
|
|
169
|
+
for (const source of sources) {
|
|
170
|
+
const bindingId = source.binding.id;
|
|
171
|
+
const resolution = await resolveBindingEnvironment(source.binding, source.endpoint);
|
|
172
|
+
if (resolution.status === 'refused') {
|
|
173
|
+
return { status: 'refused', reason: resolution.reason, bindingId, message: resolution.message };
|
|
174
|
+
}
|
|
175
|
+
const keys = resolution.status === 'composed'
|
|
176
|
+
? Object.keys(resolution.environment)
|
|
177
|
+
: objectStorageBindingEnvironmentKeys;
|
|
178
|
+
const collisions = findEnvironmentCollisions(claimedKeys, keys);
|
|
179
|
+
if (collisions.length > 0) {
|
|
180
|
+
return { status: 'refused', reason: 'objectstorage-environment-conflict', bindingId,
|
|
181
|
+
message: describeEnvironmentCollisions(collisions) };
|
|
182
|
+
}
|
|
183
|
+
for (const key of keys)
|
|
184
|
+
claimedKeys.add(key);
|
|
185
|
+
if (resolution.status === 'composed') {
|
|
186
|
+
environment = { ...environment, ...resolution.environment };
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
wait ??= { status: 'waiting', reason: resolution.reason, bindingId, message: resolution.message };
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return wait ?? { status: 'composed', environment };
|
|
193
|
+
};
|
|
194
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib2JqZWN0c3RvcmFnZWVudmlyb25tZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvcGxhdGZvcm0vb2JqZWN0c3RvcmFnZWVudmlyb25tZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQU1BLE9BQU8sRUFDTCxzQ0FBc0MsRUFDdEMsb0NBQW9DLEVBQ3BDLHdDQUF3QyxFQUN4Qyx1Q0FBdUMsRUFDdkMscUNBQXFDLEdBQ3RDLE1BQU0sb0JBQW9CLENBQUM7QUFTNUIsT0FBTyxFQUNMLHVDQUF1QyxFQUN2QyxxQ0FBcUMsRUFDckMseUNBQXlDLEVBQ3pDLHNDQUFzQyxFQUN0QyxvQ0FBb0MsR0FDckMsTUFBTSw2QkFBNkIsQ0FBQztBQUNyQyxPQUFPLEVBQUUsYUFBYSxFQUFFLGtCQUFrQixFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFFakY7OztHQUdHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sbUNBQW1DLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQztJQUMvRCxHQUFHLG9DQUFvQztJQUN2QyxHQUFHLHFDQUFxQztDQUNoQyxDQUFDLENBQUM7QUF3Qlo7OztHQUdHO0FBQ0gsTUFBTSx5QkFBeUIsR0FBRyxLQUFLLEVBQ3JDLFVBQTRCLEVBQzVCLFdBQWtELEVBQ1YsRUFBRTtJQUMxQyxNQUFNLE9BQU8sR0FBRyxrQkFBa0IsQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUMvQyxJQUFJLE9BQU8sS0FBSyxJQUFJLElBQUksT0FBTyxDQUFDLFVBQVUsS0FBSyxlQUFlLEVBQUUsQ0FBQztRQUMvRCxPQUFPLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsK0JBQStCO1lBQ2pFLE9BQU8sRUFBRSxxRUFBcUUsRUFBRSxDQUFDO0lBQ3JGLENBQUM7SUFDRCxNQUFNLFdBQVcsR0FBRyxPQUFPLE9BQU8sQ0FBQyxFQUFFLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxXQUFX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
|
|
@@ -65,3 +65,43 @@ export declare const objectStorageRetentionIntentsEqual: (leftArg: unknown, righ
|
|
|
65
65
|
export declare const validateObjectStorageRetentionEvidence: (evidenceArg: unknown, expectedArg: IObjectStorageRetentionEvidenceExpectation) => Promise<string[]>;
|
|
66
66
|
export declare const validateObjectStorageRetentionBinding: (bindingArg: unknown, expectedArg: IObjectStorageRetentionEvidenceExpectation) => Promise<string[]>;
|
|
67
67
|
export declare const validatePlatformBindingObjectStorageRetention: (bindingArg: unknown, expectedArg: IObjectStorageRetentionEvidenceExpectation) => Promise<string[]>;
|
|
68
|
+
/**
|
|
69
|
+
* The non-secret environment names that tell a workload which retention its bucket carries.
|
|
70
|
+
*
|
|
71
|
+
* The names are the ones the cluster relay handed workloads on the Docker path, so an application
|
|
72
|
+
* that read them keeps working unchanged. Every value is a projection of verified
|
|
73
|
+
* `IObjectStorageRetentionEvidence`; none is a credential.
|
|
74
|
+
*
|
|
75
|
+
* - `S3_RETENTION_MODE`: `intent.mode`, always `compliance`.
|
|
76
|
+
* - `S3_RETENTION_POLICY_ID`: `intent.policyId`.
|
|
77
|
+
* - `S3_RETENTION_DURATION_SECONDS`: `intent.retentionDurationSeconds` in decimal.
|
|
78
|
+
* - `S3_RETENTION_INTENT_SHA256`: `intentSha256`.
|
|
79
|
+
* - `S3_RETENTION_SENTINEL_KEY`: `receipt.sentinelKey`.
|
|
80
|
+
* - `S3_RETENTION_CONFIGURED_AT`: `receipt.configuredAt`, Unix milliseconds in decimal.
|
|
81
|
+
* - `S3_RETENTION_SENTINEL_CREATED_AT`: `receipt.sentinel.createdAt`, Unix milliseconds in decimal.
|
|
82
|
+
* - `S3_RETENTION_SENTINEL_RETAIN_UNTIL`: `receipt.sentinel.retainUntil`, Unix milliseconds in
|
|
83
|
+
* decimal.
|
|
84
|
+
* - `S3_RETENTION_SENTINEL_PAYLOAD_SHA256`: `receipt.sentinel.payloadSha256`.
|
|
85
|
+
* - `S3_RETENTION_SENTINEL_METADATA_SHA256`: `receipt.sentinel.metadataSha256`.
|
|
86
|
+
* - `S3_RETENTION_SENTINEL_ETAG`: `receipt.sentinel.etag`.
|
|
87
|
+
*/
|
|
88
|
+
export declare const objectStorageRetentionEnvironmentKeys: readonly ["S3_RETENTION_MODE", "S3_RETENTION_POLICY_ID", "S3_RETENTION_DURATION_SECONDS", "S3_RETENTION_INTENT_SHA256", "S3_RETENTION_SENTINEL_KEY", "S3_RETENTION_CONFIGURED_AT", "S3_RETENTION_SENTINEL_CREATED_AT", "S3_RETENTION_SENTINEL_RETAIN_UNTIL", "S3_RETENTION_SENTINEL_PAYLOAD_SHA256", "S3_RETENTION_SENTINEL_METADATA_SHA256", "S3_RETENTION_SENTINEL_ETAG"];
|
|
89
|
+
export type TObjectStorageRetentionEnvironmentKey = typeof objectStorageRetentionEnvironmentKeys[number];
|
|
90
|
+
export type TObjectStorageRetentionEnvironment = {
|
|
91
|
+
[TKey in TObjectStorageRetentionEnvironmentKey]: string;
|
|
92
|
+
};
|
|
93
|
+
/**
|
|
94
|
+
* The retention environment of evidence that proves `expectedArg`.
|
|
95
|
+
*
|
|
96
|
+
* The evidence is validated against the expectation first, with the same validator every other
|
|
97
|
+
* consumer of retention evidence uses; the first reason it is refused is thrown. A workload is
|
|
98
|
+
* never told about a retention nobody proved.
|
|
99
|
+
*/
|
|
100
|
+
export declare const createObjectStorageRetentionEnvironment: (evidenceArg: IObjectStorageRetentionEvidence, expectedArg: IObjectStorageRetentionEvidenceExpectation) => Promise<TObjectStorageRetentionEnvironment>;
|
|
101
|
+
/**
|
|
102
|
+
* Validates a retention environment on its own: exactly its eleven keys, canonical values, an
|
|
103
|
+
* intent digest that matches the stated intent, and sentinel timestamps that agree with the
|
|
104
|
+
* duration. It cannot prove the authority or the bucket the evidence was bound to — the
|
|
105
|
+
* environment does not carry them — so it judges the shape a workload reads, not the proof.
|
|
106
|
+
*/
|
|
107
|
+
export declare const validateObjectStorageRetentionEnvironment: (environmentArg: unknown, pathArg?: string) => Promise<string[]>;
|