@serve.zone/interfaces 31.3.0 → 31.5.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 +72 -0
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/data/cluster.d.ts +44 -9
- package/dist_ts/data/cluster.js +35 -12
- package/dist_ts/data/clusteringress.d.ts +137 -0
- package/dist_ts/data/clusteringress.js +302 -0
- package/dist_ts/data/coremail.runtime.js +4 -8
- package/dist_ts/data/index.d.ts +1 -0
- package/dist_ts/data/index.js +2 -1
- package/dist_ts/data/networkprotection.d.ts +18 -0
- package/dist_ts/data/networkprotection.js +24 -3
- package/dist_ts/private/networkcontract.d.ts +1 -1
- package/dist_ts/private/networkcontract.js +7 -3
- package/dist_ts/private/utccalendarday.d.ts +17 -0
- package/dist_ts/private/utccalendarday.js +27 -0
- package/dist_ts/requests/cluster.d.ts +17 -0
- package/dist_ts/requests/clusteringress.d.ts +120 -0
- package/dist_ts/requests/clusteringress.js +3 -0
- package/dist_ts/requests/index.d.ts +2 -1
- package/dist_ts/requests/index.js +3 -2
- package/package.json +1 -1
- package/readme.md +106 -6
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/data/cluster.ts +76 -17
- package/ts/data/clusteringress.ts +425 -0
- package/ts/data/coremail.runtime.ts +3 -10
- package/ts/data/index.ts +1 -0
- package/ts/data/networkprotection.ts +34 -2
- package/ts/private/networkcontract.ts +8 -2
- package/ts/private/utccalendarday.ts +30 -0
- package/ts/requests/cluster.ts +21 -0
- package/ts/requests/clusteringress.ts +140 -0
- package/ts/requests/index.ts +2 -0
|
@@ -66,10 +66,14 @@ export const captureNetwork = (value) => networkSafe(() => {
|
|
|
66
66
|
requireNetwork(encoder.encode(networkCanonical(result)).length <= 1_048_576);
|
|
67
67
|
return result;
|
|
68
68
|
});
|
|
69
|
-
export const networkRecord = (value, keys) => {
|
|
69
|
+
export const networkRecord = (value, keys, optionalKeys = []) => {
|
|
70
70
|
requireNetwork(value !== null && typeof value === 'object' && !Array.isArray(value));
|
|
71
71
|
const actual = Object.keys(value);
|
|
72
|
-
|
|
72
|
+
// Absence stays absent: a stated optional key is read, an omitted one is not
|
|
73
|
+
// defaulted, so a receiver can tell a sender that stated nothing from one that
|
|
74
|
+
// stated a value.
|
|
75
|
+
requireNetwork(keys.every(key => Object.hasOwn(value, key))
|
|
76
|
+
&& actual.every(key => keys.includes(key) || optionalKeys.includes(key)));
|
|
73
77
|
return value;
|
|
74
78
|
};
|
|
75
79
|
export const networkList = (value, maximum, read) => {
|
|
@@ -131,4 +135,4 @@ export const networkOverlaps = (left, right) => {
|
|
|
131
135
|
const [a, b] = networkPrefixBounds(left), [c, d] = networkPrefixBounds(right);
|
|
132
136
|
return a <= d && c <= b;
|
|
133
137
|
};
|
|
134
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmV0d29ya2NvbnRyYWN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvcHJpdmF0ZS9uZXR3b3JrY29udHJhY3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEsT0FBTyxFQUFFLHNCQUFzQixFQUFFLDRCQUE0QixFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFFMUYsTUFBTSxDQUFDLE1BQU0sV0FBVyxHQUFHLEdBQVUsRUFBRSxHQUFHLE1BQU0sSUFBSSxLQUFLLENBQUMsK0NBQStDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUM5RyxNQUFNLFVBQVUsY0FBYyxDQUFDLEtBQWMsSUFBbUIsSUFBSSxDQUFDLEtBQUs7SUFBRSxXQUFXLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDNUYsTUFBTSxDQUFDLE1BQU0sZ0JBQWdCLEdBQUcsQ0FBQyxLQUFjLEVBQVUsRUFBRSxDQUFDLHNCQUFzQixDQUFDLEtBQUssRUFBRSxXQUFXLENBQUMsQ0FBQztBQUN2RyxNQUFNLENBQUMsTUFBTSxZQUFZLEdBQUcsQ0FBQyxJQUFhLEVBQUUsS0FBYyxFQUFXLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsS0FBSyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUMzSCxNQUFNLENBQUMsTUFBTSxXQUFXLEdBQUcsQ0FBSSxTQUFrQixFQUFLLEVBQUUsR0FBRyxJQUFJLENBQUM7SUFBQyxPQUFPLFNBQVMsRUFBRSxDQUFDO0FBQUMsQ0FBQztBQUFDLE1BQU0sQ0FBQztJQUFDLE9BQU8sV0FBVyxFQUFFLENBQUM7QUFBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBRXpILDJGQUEyRjtBQUMzRixNQUFNLENBQUMsTUFBTSxjQUFjLEdBQUcsQ0FBQyxLQUFjLEVBQVcsRUFBRSxDQUFDLFdBQVcsQ0FBQyxHQUFHLEVBQUU7SUFDMUUsTUFBTSxPQUFPLEdBQUcsSUFBSSxXQUFXLEVBQUUsRUFBRSxTQUFTLEdBQUcsSUFBSSxHQUFHLEVB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
|
|
138
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmV0d29ya2NvbnRyYWN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvcHJpdmF0ZS9uZXR3b3JrY29udHJhY3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEsT0FBTyxFQUFFLHNCQUFzQixFQUFFLDRCQUE0QixFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFFMUYsTUFBTSxDQUFDLE1BQU0sV0FBVyxHQUFHLEdBQVUsRUFBRSxHQUFHLE1BQU0sSUFBSSxLQUFLLENBQUMsK0NBQStDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUM5RyxNQUFNLFVBQVUsY0FBYyxDQUFDLEtBQWMsSUFBbUIsSUFBSSxDQUFDLEtBQUs7SUFBRSxXQUFXLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDNUYsTUFBTSxDQUFDLE1BQU0sZ0JBQWdCLEdBQUcsQ0FBQyxLQUFjLEVBQVUsRUFBRSxDQUFDLHNCQUFzQixDQUFDLEtBQUssRUFBRSxXQUFXLENBQUMsQ0FBQztBQUN2RyxNQUFNLENBQUMsTUFBTSxZQUFZLEdBQUcsQ0FBQyxJQUFhLEVBQUUsS0FBYyxFQUFXLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsS0FBSyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUMzSCxNQUFNLENBQUMsTUFBTSxXQUFXLEdBQUcsQ0FBSSxTQUFrQixFQUFLLEVBQUUsR0FBRyxJQUFJLENBQUM7SUFBQyxPQUFPLFNBQVMsRUFBRSxDQUFDO0FBQUMsQ0FBQztBQUFDLE1BQU0sQ0FBQztJQUFDLE9BQU8sV0FBVyxFQUFFLENBQUM7QUFBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBRXpILDJGQUEyRjtBQUMzRixNQUFNLENBQUMsTUFBTSxjQUFjLEdBQUcsQ0FBQyxLQUFjLEVBQVcsRUFBRSxDQUFDLFdBQVcsQ0FBQyxHQUFHLEVBQUU7SUFDMUUsTUFBTSxPQUFPLEdBQUcsSUFBSSxXQUFXLEVBQUUsRUFBRSxTQUFTLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztJQUNqRSxJQUFJLEtBQUssR0FBRyxDQUFDLEVBQUUsS0FBSyxHQUFHLENBQUMsQ0FBQztJQUN6QixNQUFNLE9BQU8sR0FBRyxDQUFDLElBQVksRUFBRSxFQUFFO1FBQy9CLGNBQWMsQ0FBQyxJQUFJLENBQUMsTUFBTSxJQUFJLFNBQVMsQ0FBQyxDQUFDO1FBQ3pDLEtBQUssSUFBSSxPQUFPLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLE1BQU0sQ0FBQztRQUNyQyxjQUFjLENBQUMsS0FBSyxJQUFJLFNBQVMsQ0FBQyxDQUFDO0lBQ3JDLENBQUMsQ0FBQztJQUNGLE1BQU0sSUFBSSxHQUFHLENBQUMsSUFBYSxFQUFFLEtBQWEsRUFBVyxFQUFFO1FBQ3JELGNBQWMsQ0FBQyxFQUFFLEtBQUssSUFBSSxNQUFNLElBQUksS0FBSyxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQ2pELElBQUksT0FBTyxJQUFJLEtBQUssUUFBUSxFQUFFLENBQUM7WUFBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7WUFBQyxPQUFPLElBQUksQ0FBQztRQUFDLENBQUM7UUFDN0QsSUFBSSxJQUFJLEtBQUssSUFBSSxJQUFJLE9BQU8sSUFBSSxLQUFLLFNBQVM7WUFBRSxPQUFPLElBQUksQ0FBQztRQUM1RCxJQUFJLE9BQU8sSUFBSSxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQzdCLGNBQWMsQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQUMsT0FBTyxJQUFJLENBQUM7UUFDbEYsQ0FBQztRQUNELGNBQWMsQ0FBQyxJQUFJLEtBQUssSUFBSSxJQUFJLE9BQU8sSUFBSSxLQUFLLFFBQVEsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUNsRixNQUFNLEtBQUssR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFLFNBQVMsR0FBRyxNQUFNLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxFQUFFLElBQUksR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3pHLGNBQWMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLFNBQVMsS0FBSyxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxTQUFTLEtBQUssTUFBTSxDQUFDLFNBQVMsSUFBSSxTQUFTLEtBQUssSUFBSSxDQUFDLENBQUM7UUFDN0csY0FBYyxDQUFDLElBQUksQ0FBQyxNQUFNLElBQUksSUFBSSxDQUFDLENBQUM7UUFDcEMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNwQixJQUFJLENBQUM7WUFDSCxJQUFJLEtBQUssRUFBRSxDQUFDO2dCQUNWLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyx3QkFBd0IsQ0FBQyxJQUFJLEVBQUUsUUFBUSxDQUFDLEVBQUUsS0FBSyxDQUFDO2dCQUN0RSxjQUFjLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxNQUFNLENBQUMsSUFBSSxNQUFNLElBQUksQ0FBQyxJQUFJLE1BQU0sSUFBSSxJQUFJLElBQUksSUFBSSxDQUFDLE1BQU0sS0FBSyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUM7Z0JBQzVHLE1BQU0sTUFBTSxHQUFjLEVBQUUsQ0FBQztnQkFDN0IsS0FBSyxJQUFJLEtBQUssR0FBRyxDQUFDLEVBQUUsS0FBSyxHQUFHLE1BQU0sRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDO29CQUM1QyxNQUFNLFVBQVUsR0FBRyxNQUFNLENBQUMsd0JBQXdCLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO29CQUN4RSxjQUFjLENBQUMsVUFBVSxFQUFFLFVBQVUsSUFBSSxNQUFNLENBQUMsTUFBTSxDQUFDLFVBQVUsRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDO29CQUM3RSxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxFQUFFLEtBQUssR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUNqRCxDQUFDO2dCQUNELE9BQU8sTUFBTSxDQUFDO1lBQ2hCLENBQUM7WUFDRCxNQUFNLE1BQU0sR0FBNEIsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUM1RCxLQUFLLE1BQU0sR0FBRyxJQUFJLElBQUksRUFBRSxDQUFDO2dCQUN2QixjQUFjLENBQUMsT0FBTyxHQUFHLEtBQUssUUFBUSxDQUFDLENBQUM7Z0JBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUN0RCxNQUFNLFVBQVUsR0FBRyxNQUFNLENBQUMsd0JBQXdCLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFDO2dCQUM5RCxjQUFjLENBQUMsVUFBVSxFQUFFLFVBQVUsSUFBSSxNQUFNLENBQUMsTUFBTSxDQUFDLFVBQVUsRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDO2dCQUM3RSxNQUFNLENBQUMsR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLEVBQUUsS0FBSyxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQ2xELENBQUM7WUFDRCxPQUFPLE1BQU0sQ0FBQztRQUNoQixDQUFDO2dCQUFTLENBQUM7WUFBQyxTQUFTLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQUMsQ0FBQztJQUN2QyxDQUFDLENBQUM7SUFDRixNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQzlCLGNBQWMsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLGdCQUFnQixDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsTUFBTSxJQUFJLFNBQVMsQ0FBQyxDQUFDO0lBQzdFLE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUMsQ0FBQyxDQUFDO0FBRUgsTUFBTSxDQUFDLE1BQU0sYUFBYSxHQUFHLENBQzNCLEtBQWMsRUFBRSxJQUFjLEVBQUUsZUFBeUIsRUFBRSxFQUNsQyxFQUFFO0lBQzNCLGNBQWMsQ0FBQyxLQUFLLEtBQUssSUFBSSxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUNyRixNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ2xDLDZFQUE2RTtJQUM3RSwrRUFBK0U7SUFDL0Usa0JBQWtCO0lBQ2xCLGNBQWMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDLENBQUM7V0FDdEQsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLElBQUksWUFBWSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDNUUsT0FBTyxLQUFnQyxDQUFDO0FBQzFDLENBQUMsQ0FBQztBQUNGLE1BQU0sQ0FBQyxNQUFNLFdBQVcsR0FBRyxDQUFJLEtBQWMsRUFBRSxPQUFlLEVBQUUsSUFBMEIsRUFBTyxFQUFFO0lBQ2pHLGNBQWMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxJQUFJLEtBQUssQ0FBQyxNQUFNLElBQUksT0FBTyxDQUFDLENBQUM7SUFBQyxPQUFPLEtBQUssQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDMUYsQ0FBQyxDQUFDO0FBQ0YsTUFBTSxDQUFDLE1BQU0sYUFBYSxHQUFHLENBQUksTUFBVyxFQUFFLEdBQXdCLEVBQU8sRUFBRTtJQUM3RSxjQUFjLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDLEtBQUssS0FBSyxDQUFDLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQUMsT0FBTyxNQUFNLENBQUM7QUFDcEgsQ0FBQyxDQUFDO0FBQ0YsTUFBTSxDQUFDLE1BQU0sU0FBUyxHQUFHLENBQUMsS0FBYyxFQUFVLEVBQUU7SUFDbEQsY0FBYyxDQUFDLE9BQU8sS0FBSyxLQUFLLFFBQVEsSUFBSSxxQ0FBcUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUFDLE9BQU8sS0FBSyxDQUFDO0FBQy9HLENBQUMsQ0FBQztBQUNGLE1BQU0sQ0FBQyxNQUFNLGNBQWMsR0FBRyxDQUFDLEtBQWMsRUFBRSxPQUFPLEdBQUcsTUFBTSxDQUFDLGdCQUFnQixHQUFHLENBQUMsRUFBVSxFQUFFO0lBQzlGLGNBQWMsQ0FBQyxPQUFPLEtBQUssS0FBSyxRQUFRLElBQUksTUFBTSxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsSUFBSSxLQUFLLEdBQUcsQ0FBQyxJQUFJLEtBQUssSUFBSSxPQUFPLENBQUMsQ0FBQztJQUFDLE9BQU8sS0FBSyxDQUFDO0FBQzFILENBQUMsQ0FBQztBQUNGLE1BQU0sQ0FBQyxNQUFNLGFBQWEsR0FBRyxDQUFDLEtBQWMsRUFBaUIsRUFBRTtJQUM3RCxjQUFjLENBQUMsT0FBTyxLQUFLLEtBQUssUUFBUSxJQUFJLHVCQUF1QixDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO0lBQUMsT0FBTyxLQUFzQixDQUFDO0FBQ2xILENBQUMsQ0FBQztBQUNGLE1BQU0sQ0FBQyxNQUFNLGlCQUFpQixHQUFHLENBQUMsS0FBYyxFQUF3QixFQUFFO0lBQ3hFLE1BQU0sSUFBSSxHQUFHLGFBQWEsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxNQUFNLEVBQUUsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUM7SUFDM0QsY0FBYyxDQUFDLElBQUksQ0FBQyxJQUFJLEtBQUssU0FBUyxJQUFJLElBQUksQ0FBQyxJQUFJLEtBQUssUUFBUSxDQUFDLENBQUM7SUFDbEUsT0FBTyxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSSxFQUFFLEVBQUUsRUFBRSxTQUFTLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEtBQUssRUFBRSxTQUFTLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7QUFDbkYsQ0FBQyxDQUFDO0FBQ0YsTUFBTSxDQUFDLE1BQU0sZ0JBQWdCLEdBQUcsQ0FBQyxLQUFjLEVBQWdDLEVBQUU7SUFDL0UsTUFBTSxJQUFJLEdBQUcsYUFBYSxDQUFDLEtBQUssRUFBRSxDQUFDLElBQUksRUFBRSxZQUFZLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBQztJQUNsRSxPQUFPLEVBQUUsRUFBRSxFQUFFLFNBQVMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLEVBQUUsVUFBVSxFQUFFLGNBQWMsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLEVBQUUsTUFBTSxFQUFFLGFBQWEsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztBQUNySCxDQUFDLENBQUM7QUFDRixNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBRyxDQUFDLEtBQW1DLEVBQWdDLEVBQUUsQ0FDdEcsQ0FBQyxFQUFFLEVBQUUsRUFBRSxLQUFLLENBQUMsRUFBRSxFQUFFLFVBQVUsRUFBRSxLQUFLLENBQUMsVUFBVSxFQUFFLE1BQU0sRUFBRSxLQUFLLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztBQUN6RSxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQUcsQ0FBQyxJQUE2QixFQUFFLEVBQUU7SUFDL0QsTUFBTSxFQUFFLEdBQUcsU0FBUyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxVQUFVLEdBQUcsY0FBYyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUM1RSxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsUUFBUSxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDakYsY0FBYyxDQUFDLFVBQVUsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDLFFBQVEsRUFBRSxFQUFFLEtBQUssRUFBRSxJQUFJLFFBQVEsQ0FBQyxVQUFVLEtBQUssVUFBVSxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQ3JILE9BQU8sRUFBRSxFQUFFLEVBQUUsVUFBVSxFQUFFLFFBQVEsRUFBRSxDQUFDO0FBQ3RDLENBQUMsQ0FBQztBQUNGLE1BQU0sQ0FBQyxNQUFNLFdBQVcsR0FBRyxLQUFLLEVBQUUsTUFBYyxFQUFFLEtBQWdDLEVBQTBCLEVBQUU7SUFDNUcsTUFBTSxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsR0FBRyxPQUFPLEVBQUUsR0FBRyxLQUFLLENBQUM7SUFDOUMsT0FBTyxVQUFVLE1BQU0sNEJBQTRCLENBQUMsZ0JBQWdCLENBQUMsRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLENBQUMsRUFBRSxXQUFXLENBQUMsRUFBRSxDQUFDO0FBQzVHLENBQUMsQ0FBQztBQUNGLE1BQU0sQ0FBQyxNQUFNLFdBQVcsR0FBRyxDQUFDLEtBQWMsRUFBVSxFQUFFO0lBQ3BELGNBQWMsQ0FBQyxPQUFPLEtBQUssS0FBSyxRQUFRLElBQUksS0FBSyxDQUFDLE1BQU0sSUFBSSxFQUFFLENBQUMsQ0FBQztJQUNoRSxNQUFNLEtBQUssR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQy9CLGNBQWMsQ0FBQyxLQUFLLENBQUMsTUFBTSxLQUFLLENBQUMsSUFBSSxLQUFLLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMseUJBQXlCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQ3ZILE9BQU8sS0FBSyxDQUFDO0FBQ2YsQ0FBQyxDQUFDO0FBQ0YsTUFBTSxDQUFDLE1BQU0saUJBQWlCLEdBQUcsQ0FBQyxLQUFhLEVBQVUsRUFBRSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxFQUFFLElBQUksRUFBRSxFQUFFLENBQUMsR0FBRyxHQUFHLEdBQUcsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDaEksTUFBTSxDQUFDLE1BQU0sbUJBQW1CLEdBQUcsQ0FBQyxLQUFhLEVBQW9CLEVBQUU7SUFDckUsTUFBTSxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEtBQUssR0FBRyxpQkFBaUIsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUM3RSxPQUFPLENBQUMsS0FBSyxFQUFFLEtBQUssR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7QUFDdkQsQ0FBQyxDQUFDO0FBQ0YsTUFBTSxDQUFDLE1BQU0sZUFBZSxHQUFHLENBQUMsS0FBYSxFQUFFLEtBQWEsRUFBVyxFQUFFO0lBQ3ZFLE1BQU0sQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEdBQUcsbUJBQW1CLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEdBQUcsbUJBQW1CLENBQUMsS0FBSyxDQUFDLENBQUM7SUFBQyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztBQUMxRyxDQUFDLENBQUM7QUFDRixNQUFNLENBQUMsTUFBTSxlQUFlLEdBQUcsQ0FBQyxJQUFZLEVBQUUsS0FBYSxFQUFXLEVBQUU7SUFDdEUsTUFBTSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsR0FBRyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsR0FBRyxtQkFBbUIsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQ3pHLENBQUMsQ0FBQyJ9
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The UTC calendar day every consumer of this package agrees on.
|
|
3
|
+
*
|
|
4
|
+
* Two facts, deliberately separate: whether a value has the canonical shape, and whether that
|
|
5
|
+
* shape names a day that exists. `2026-13-45` passes the first and fails the second, and a
|
|
6
|
+
* caller that only checked the pattern would store a day no clock can ever produce.
|
|
7
|
+
*/
|
|
8
|
+
export declare const utcCalendarDayPattern: RegExp;
|
|
9
|
+
/**
|
|
10
|
+
* Whether a canonical `YYYY-MM-DD` string names a real day.
|
|
11
|
+
*
|
|
12
|
+
* Round-trips through `Date.UTC`, which normalises an impossible day into a neighbouring one:
|
|
13
|
+
* a value that survives the round trip unchanged is the day it claims to be.
|
|
14
|
+
*/
|
|
15
|
+
export declare const isRealUtcCalendarDay: (valueArg: string) => boolean;
|
|
16
|
+
/** Both facts at once, for a caller that reports one reason. */
|
|
17
|
+
export declare const isUtcCalendarDay: (valueArg: unknown) => valueArg is string;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The UTC calendar day every consumer of this package agrees on.
|
|
3
|
+
*
|
|
4
|
+
* Two facts, deliberately separate: whether a value has the canonical shape, and whether that
|
|
5
|
+
* shape names a day that exists. `2026-13-45` passes the first and fails the second, and a
|
|
6
|
+
* caller that only checked the pattern would store a day no clock can ever produce.
|
|
7
|
+
*/
|
|
8
|
+
export const utcCalendarDayPattern = /^[0-9]{4}-[0-9]{2}-[0-9]{2}$/;
|
|
9
|
+
/**
|
|
10
|
+
* Whether a canonical `YYYY-MM-DD` string names a real day.
|
|
11
|
+
*
|
|
12
|
+
* Round-trips through `Date.UTC`, which normalises an impossible day into a neighbouring one:
|
|
13
|
+
* a value that survives the round trip unchanged is the day it claims to be.
|
|
14
|
+
*/
|
|
15
|
+
export const isRealUtcCalendarDay = (valueArg) => {
|
|
16
|
+
if (!utcCalendarDayPattern.test(valueArg)) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
const [year, month, day] = valueArg.split('-').map(Number);
|
|
20
|
+
const parsed = new Date(Date.UTC(year, month - 1, day));
|
|
21
|
+
return parsed.getUTCFullYear() === year
|
|
22
|
+
&& parsed.getUTCMonth() + 1 === month
|
|
23
|
+
&& parsed.getUTCDate() === day;
|
|
24
|
+
};
|
|
25
|
+
/** Both facts at once, for a caller that reports one reason. */
|
|
26
|
+
export const isUtcCalendarDay = (valueArg) => (typeof valueArg === 'string' && isRealUtcCalendarDay(valueArg));
|
|
27
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRjY2FsZW5kYXJkYXkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9wcml2YXRlL3V0Y2NhbGVuZGFyZGF5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7R0FNRztBQUNILE1BQU0sQ0FBQyxNQUFNLHFCQUFxQixHQUFHLDhCQUE4QixDQUFDO0FBRXBFOzs7OztHQUtHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sb0JBQW9CLEdBQUcsQ0FBQyxRQUFnQixFQUFXLEVBQUU7SUFDaEUsSUFBSSxDQUFDLHFCQUFxQixDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO1FBQzFDLE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztJQUNELE1BQU0sQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLEdBQUcsQ0FBQyxHQUFHLFFBQVEsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzNELE1BQU0sTUFBTSxHQUFHLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLEtBQUssR0FBRyxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUN4RCxPQUFPLE1BQU0sQ0FBQyxjQUFjLEVBQUUsS0FBSyxJQUFJO1dBQ2xDLE1BQU0sQ0FBQyxXQUFXLEVBQUUsR0FBRyxDQUFDLEtBQUssS0FBSztXQUNsQyxNQUFNLENBQUMsVUFBVSxFQUFFLEtBQUssR0FBRyxDQUFDO0FBQ25DLENBQUMsQ0FBQztBQUVGLGdFQUFnRTtBQUNoRSxNQUFNLENBQUMsTUFBTSxnQkFBZ0IsR0FBRyxDQUFDLFFBQWlCLEVBQXNCLEVBQUUsQ0FBQyxDQUN6RSxPQUFPLFFBQVEsS0FBSyxRQUFRLElBQUksb0JBQW9CLENBQUMsUUFBUSxDQUFDLENBQy9ELENBQUMifQ==
|
|
@@ -83,6 +83,23 @@ export interface IReq_Any_Cloudly_DisableClusterRelayV1 extends plugins.typedreq
|
|
|
83
83
|
relay: null;
|
|
84
84
|
};
|
|
85
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* The relay registrations an administrator asks Cloudly about.
|
|
88
|
+
*
|
|
89
|
+
* Read-only: it answers with what Cloudly accepted, plus whether a verified socket carries each
|
|
90
|
+
* relay at this instant. `clusterIds` narrows the answer to the named clusters; omitting it asks
|
|
91
|
+
* for every cluster whose relay ever registered.
|
|
92
|
+
*/
|
|
93
|
+
export interface IReq_Any_Cloudly_GetClusterRelayRegistrations extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Any_Cloudly_GetClusterRelayRegistrations> {
|
|
94
|
+
method: 'getClusterRelayRegistrations';
|
|
95
|
+
request: {
|
|
96
|
+
identity: userInterfaces.IIdentity;
|
|
97
|
+
clusterIds?: string[];
|
|
98
|
+
};
|
|
99
|
+
response: {
|
|
100
|
+
registrations: clusterInterfaces.IClusterRelayRegistration[];
|
|
101
|
+
};
|
|
102
|
+
}
|
|
86
103
|
/**
|
|
87
104
|
* The cluster relay tells Cloudly where it listens, over its own authenticated socket.
|
|
88
105
|
*
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import * as clusterIngressInterfaces from '../data/clusteringress.js';
|
|
2
|
+
import * as plugins from '../plugins.js';
|
|
3
|
+
/**
|
|
4
|
+
* Cloudly hands a cluster's relay the table its ingress serves.
|
|
5
|
+
*
|
|
6
|
+
* Cloudly computes it: it is the only party that knows every service, every
|
|
7
|
+
* ready endpoint, the node address each published port answers on and the
|
|
8
|
+
* certificate each hostname needs. The relay caches it in memory and serves it
|
|
9
|
+
* to the ingress; it never authors one.
|
|
10
|
+
*
|
|
11
|
+
* The table carries private keys, so this request is secret-bearing: exclude it
|
|
12
|
+
* from hooks, logs and journals on both sides.
|
|
13
|
+
*/
|
|
14
|
+
export interface IReq_Cloudly_Relay_PushClusterRouteTable extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Cloudly_Relay_PushClusterRouteTable> {
|
|
15
|
+
method: 'pushClusterRouteTable';
|
|
16
|
+
request: {
|
|
17
|
+
table: clusterIngressInterfaces.IClusterRouteTable;
|
|
18
|
+
};
|
|
19
|
+
response: {
|
|
20
|
+
/**
|
|
21
|
+
* The revision the relay now holds. Lower than the pushed revision means
|
|
22
|
+
* the relay already held a newer table and kept it.
|
|
23
|
+
*/
|
|
24
|
+
appliedRevision: number;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The relay asks for the current table.
|
|
29
|
+
*
|
|
30
|
+
* Its own session decides which cluster it speaks for, so the request carries no
|
|
31
|
+
* cluster of its own. `null` means Cloudly has computed no table yet — a fact,
|
|
32
|
+
* not an empty table, which the relay must not serve as one.
|
|
33
|
+
*/
|
|
34
|
+
export interface IReq_Relay_Cloudly_GetClusterRouteTable extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Relay_Cloudly_GetClusterRouteTable> {
|
|
35
|
+
method: 'getClusterRouteTable';
|
|
36
|
+
request: Record<string, never>;
|
|
37
|
+
response: {
|
|
38
|
+
table: clusterIngressInterfaces.IClusterRouteTable | null;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* The cluster ingress announces itself, and Cloudly decides whether it is one.
|
|
43
|
+
*
|
|
44
|
+
* One body for both hops: the ingress sends it to its relay, and the relay
|
|
45
|
+
* forwards it to Cloudly untouched. The relay cannot decide this — anything that
|
|
46
|
+
* reaches its listener could ask — so the bearer Cloudly minted into the ingress
|
|
47
|
+
* workload's assignment environment is what authorizes the registration, and
|
|
48
|
+
* Cloudly derives which cluster is speaking from the identity tag on the relay's
|
|
49
|
+
* own session, never from a request field.
|
|
50
|
+
*
|
|
51
|
+
* A method, not a connection tag: what a relay knows about its ingress is what
|
|
52
|
+
* it registered through, which a server owns, rather than a label a client
|
|
53
|
+
* authored. Only an accepted registration binds the connection; every other
|
|
54
|
+
* ingress method is answered for that connection alone.
|
|
55
|
+
*
|
|
56
|
+
* `revision` is the table the relay holds, so an accepted ingress knows at once
|
|
57
|
+
* whether it has to fetch one. Cloudly answers `null`: the table is the relay's
|
|
58
|
+
* to state, not Cloudly's to echo.
|
|
59
|
+
*/
|
|
60
|
+
export interface IReq_Ingress_Relay_Cloudly_RegisterClusterIngress extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Ingress_Relay_Cloudly_RegisterClusterIngress> {
|
|
61
|
+
method: 'registerClusterIngress';
|
|
62
|
+
request: {
|
|
63
|
+
/**
|
|
64
|
+
* Sensitive ephemeral input: exclude the complete request from hooks, logs,
|
|
65
|
+
* diagnostics and durable journals on every hop. Cloudly mints it into the
|
|
66
|
+
* ingress workload's assignment environment and verifies it here.
|
|
67
|
+
*/
|
|
68
|
+
bearer: string;
|
|
69
|
+
/** The ingress build that registered, for operators reading a relay's log. */
|
|
70
|
+
version: string;
|
|
71
|
+
/** The node this ingress runs on, as its assignment names it. */
|
|
72
|
+
nodeId: string;
|
|
73
|
+
/** Optional capability names; an ingress that states none states nothing. */
|
|
74
|
+
capabilities?: string[];
|
|
75
|
+
};
|
|
76
|
+
response: {
|
|
77
|
+
accepted: true;
|
|
78
|
+
revision: number | null;
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* The ingress fetches the table the relay holds.
|
|
83
|
+
*
|
|
84
|
+
* `knownRevision` is what the ingress already applied: the relay answers `null`
|
|
85
|
+
* when it holds nothing newer, so a reconnect costs one round trip and not a
|
|
86
|
+
* certificate transfer.
|
|
87
|
+
*/
|
|
88
|
+
export interface IReq_Ingress_Relay_GetClusterIngressRouteTable extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Ingress_Relay_GetClusterIngressRouteTable> {
|
|
89
|
+
method: 'getClusterIngressRouteTable';
|
|
90
|
+
request: {
|
|
91
|
+
knownRevision: number | null;
|
|
92
|
+
};
|
|
93
|
+
response: {
|
|
94
|
+
table: clusterIngressInterfaces.IClusterRouteTable | null;
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* One page of the ingress's day-bucketed counters.
|
|
99
|
+
*
|
|
100
|
+
* The same body travels Cloudly → relay and relay → ingress: the relay carries
|
|
101
|
+
* the request to the ingress that answers it and the page back, adding nothing.
|
|
102
|
+
* A reader re-reads yesterday and today on every pass, because a day only stops
|
|
103
|
+
* changing once it has closed.
|
|
104
|
+
*/
|
|
105
|
+
export interface IReq_Any_Ingress_GetClusterTrafficStatistics extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Any_Ingress_GetClusterTrafficStatistics> {
|
|
106
|
+
method: 'getClusterTrafficStatistics';
|
|
107
|
+
request: {
|
|
108
|
+
/** Inclusive first UTC calendar day, `YYYY-MM-DD`. */
|
|
109
|
+
fromDayUtc: string;
|
|
110
|
+
/** Inclusive last UTC calendar day, `YYYY-MM-DD`. */
|
|
111
|
+
toDayUtc: string;
|
|
112
|
+
/** Opaque ingress-owned cursor. */
|
|
113
|
+
cursor?: string;
|
|
114
|
+
limit: number;
|
|
115
|
+
};
|
|
116
|
+
response: {
|
|
117
|
+
statistics: clusterIngressInterfaces.IClusterTrafficStatistics[];
|
|
118
|
+
nextCursor?: string;
|
|
119
|
+
};
|
|
120
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import * as clusterIngressInterfaces from '../data/clusteringress.js';
|
|
2
|
+
import * as plugins from '../plugins.js';
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3RlcmluZ3Jlc3MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9yZXF1ZXN0cy9jbHVzdGVyaW5ncmVzcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssd0JBQXdCLE1BQU0sMkJBQTJCLENBQUM7QUFDdEUsT0FBTyxLQUFLLE9BQU8sTUFBTSxlQUFlLENBQUMifQ==
|
|
@@ -5,6 +5,7 @@ import * as baseOsRequests from './baseos.js';
|
|
|
5
5
|
import * as backupRequests from './backup.js';
|
|
6
6
|
import * as certificateRequests from './certificate.js';
|
|
7
7
|
import * as clusterRequests from './cluster.js';
|
|
8
|
+
import * as clusterIngressRequests from './clusteringress.js';
|
|
8
9
|
import * as configRequests from './config.js';
|
|
9
10
|
import * as coreMailRequests from './coremail.js';
|
|
10
11
|
import * as coreMailAdminRequests from './coremail.admin.js';
|
|
@@ -34,7 +35,7 @@ import * as statusRequests from './status.js';
|
|
|
34
35
|
import * as taskRequests from './task.js';
|
|
35
36
|
import * as versionRequests from './version.js';
|
|
36
37
|
import * as webPushRequests from './webpush.js';
|
|
37
|
-
export { adminRequests as admin, appStoreRequests as appstore, baremetalRequests as baremetal, baseOsRequests as baseos, backupRequests as backup, certificateRequests as certificate, clusterRequests as cluster, configRequests as config, coreMailRequests as coremail, coreMailAdminRequests as coremailAdmin, corestoreRequests as corestore, deploymentRequests as deployment, dnsRequests as dns, domainRequests as domain, externalRegistryRequests as externalRegistry, gatewayRequests as gateway, hostedAppRequests as hostedapp, identityRequests as identity, imageRequests as image, informRequests as inform, logRequests as log, mailRequests as mail, migrationRequests as migration, networkRequests as network, nodeRequests as node, palletRequests as pallet, platformRequests as platform, routingRequests as routing, runtimeSessionRequests as runtimesession, secretRequests as secret, serviceRequests as service, settingsRequests as settings, statusRequests as status, taskRequests as task, versionRequests as version, webPushRequests as webpush, };
|
|
38
|
+
export { adminRequests as admin, appStoreRequests as appstore, baremetalRequests as baremetal, baseOsRequests as baseos, backupRequests as backup, certificateRequests as certificate, clusterRequests as cluster, clusterIngressRequests as clusteringress, configRequests as config, coreMailRequests as coremail, coreMailAdminRequests as coremailAdmin, corestoreRequests as corestore, deploymentRequests as deployment, dnsRequests as dns, domainRequests as domain, externalRegistryRequests as externalRegistry, gatewayRequests as gateway, hostedAppRequests as hostedapp, identityRequests as identity, imageRequests as image, informRequests as inform, logRequests as log, mailRequests as mail, migrationRequests as migration, networkRequests as network, nodeRequests as node, palletRequests as pallet, platformRequests as platform, routingRequests as routing, runtimeSessionRequests as runtimesession, secretRequests as secret, serviceRequests as service, settingsRequests as settings, statusRequests as status, taskRequests as task, versionRequests as version, webPushRequests as webpush, };
|
|
38
39
|
export * from './inform.js';
|
|
39
40
|
export * from './hostedapp.js';
|
|
40
41
|
export * from './mail.js';
|
|
@@ -6,6 +6,7 @@ import * as baseOsRequests from './baseos.js';
|
|
|
6
6
|
import * as backupRequests from './backup.js';
|
|
7
7
|
import * as certificateRequests from './certificate.js';
|
|
8
8
|
import * as clusterRequests from './cluster.js';
|
|
9
|
+
import * as clusterIngressRequests from './clusteringress.js';
|
|
9
10
|
import * as configRequests from './config.js';
|
|
10
11
|
import * as coreMailRequests from './coremail.js';
|
|
11
12
|
import * as coreMailAdminRequests from './coremail.admin.js';
|
|
@@ -35,9 +36,9 @@ import * as statusRequests from './status.js';
|
|
|
35
36
|
import * as taskRequests from './task.js';
|
|
36
37
|
import * as versionRequests from './version.js';
|
|
37
38
|
import * as webPushRequests from './webpush.js';
|
|
38
|
-
export { adminRequests as admin, appStoreRequests as appstore, baremetalRequests as baremetal, baseOsRequests as baseos, backupRequests as backup, certificateRequests as certificate, clusterRequests as cluster, configRequests as config, coreMailRequests as coremail, coreMailAdminRequests as coremailAdmin, corestoreRequests as corestore, deploymentRequests as deployment, dnsRequests as dns, domainRequests as domain, externalRegistryRequests as externalRegistry, gatewayRequests as gateway, hostedAppRequests as hostedapp, identityRequests as identity, imageRequests as image, informRequests as inform, logRequests as log, mailRequests as mail, migrationRequests as migration, networkRequests as network, nodeRequests as node, palletRequests as pallet, platformRequests as platform, routingRequests as routing, runtimeSessionRequests as runtimesession, secretRequests as secret, serviceRequests as service, settingsRequests as settings, statusRequests as status, taskRequests as task, versionRequests as version, webPushRequests as webpush, };
|
|
39
|
+
export { adminRequests as admin, appStoreRequests as appstore, baremetalRequests as baremetal, baseOsRequests as baseos, backupRequests as backup, certificateRequests as certificate, clusterRequests as cluster, clusterIngressRequests as clusteringress, configRequests as config, coreMailRequests as coremail, coreMailAdminRequests as coremailAdmin, corestoreRequests as corestore, deploymentRequests as deployment, dnsRequests as dns, domainRequests as domain, externalRegistryRequests as externalRegistry, gatewayRequests as gateway, hostedAppRequests as hostedapp, identityRequests as identity, imageRequests as image, informRequests as inform, logRequests as log, mailRequests as mail, migrationRequests as migration, networkRequests as network, nodeRequests as node, palletRequests as pallet, platformRequests as platform, routingRequests as routing, runtimeSessionRequests as runtimesession, secretRequests as secret, serviceRequests as service, settingsRequests as settings, statusRequests as status, taskRequests as task, versionRequests as version, webPushRequests as webpush, };
|
|
39
40
|
export * from './inform.js';
|
|
40
41
|
export * from './hostedapp.js';
|
|
41
42
|
export * from './mail.js';
|
|
42
43
|
export * from './webpush.js';
|
|
43
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
44
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9yZXF1ZXN0cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGVBQWUsQ0FBQztBQUV6QyxPQUFPLEtBQUssYUFBYSxNQUFNLFlBQVksQ0FBQztBQUM1QyxPQUFPLEtBQUssZ0JBQWdCLE1BQU0sZUFBZSxDQUFDO0FBQ2xELE9BQU8sS0FBSyxpQkFBaUIsTUFBTSxnQkFBZ0IsQ0FBQztBQUNwRCxPQUFPLEtBQUssY0FBYyxNQUFNLGFBQWEsQ0FBQztBQUM5QyxPQUFPLEtBQUssY0FBYyxNQUFNLGFBQWEsQ0FBQztBQUM5QyxPQUFPLEtBQUssbUJBQW1CLE1BQU0sa0JBQWtCLENBQUM7QUFDeEQsT0FBTyxLQUFLLGVBQWUsTUFBTSxjQUFjLENBQUM7QUFDaEQsT0FBTyxLQUFLLHNCQUFzQixNQUFNLHFCQUFxQixDQUFDO0FBQzlELE9BQU8sS0FBSyxjQUFjLE1BQU0sYUFBYSxDQUFDO0FBQzlDLE9BQU8sS0FBSyxnQkFBZ0IsTUFBTSxlQUFlLENBQUM7QUFDbEQsT0FBTyxLQUFLLHFCQUFxQixNQUFNLHFCQUFxQixDQUFDO0FBQzdELE9BQU8sS0FBSyxpQkFBaUIsTUFBTSxnQkFBZ0IsQ0FBQztBQUNwRCxPQUFPLEtBQUssa0JBQWtCLE1BQU0saUJBQWlCLENBQUM7QUFDdEQsT0FBTyxLQUFLLFdBQVcsTUFBTSxVQUFVLENBQUM7QUFDeEMsT0FBTyxLQUFLLGNBQWMsTUFBTSxhQUFhLENBQUM7QUFDOUMsT0FBTyxLQUFLLHdCQUF3QixNQUFNLHVCQUF1QixDQUFDO0FBQ2xFLE9BQU8sS0FBSyxlQUFlLE1BQU0sY0FBYyxDQUFDO0FBQ2hELE9BQU8sS0FBSyxpQkFBaUIsTUFBTSxnQkFBZ0IsQ0FBQztBQUNwRCxPQUFPLEtBQUssZ0JBQWdCLE1BQU0sZUFBZSxDQUFDO0FBQ2xELE9BQU8sS0FBSyxhQUFhLE1BQU0sWUFBWSxD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
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -1132,12 +1132,27 @@ refused by its own name, because a relay that bound one can never serve the node
|
|
|
1132
1132
|
|
|
1133
1133
|
Authority stays with Cloudly, and none of it is a request field. The cluster is the one the
|
|
1134
1134
|
verified machine identity on that socket names; whether `relay.nodeId` is a node of that cluster
|
|
1135
|
-
is decided against Cloudly's own records; and one cluster has one relay
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1135
|
+
is decided against Cloudly's own records; and one cluster has one relay. A registration for a
|
|
1136
|
+
cluster whose relay nobody enabled is refused by name, because there is no origin to register
|
|
1137
|
+
into, so an accepted registration always answers with the origin Cloudly published: that is how
|
|
1138
|
+
a relay checks that the certificate it holds and the name its nodes are told to reach are the
|
|
1139
|
+
same one.
|
|
1140
|
+
|
|
1141
|
+
`registrationSequence` restarts with the relay process, so it orders registrations only within
|
|
1142
|
+
one live peer: there it must strictly increase, a refused registration does not consume it (the
|
|
1143
|
+
same body may be re-sent once the cause is gone), and a retry that repeats a sequence Cloudly
|
|
1144
|
+
already accepted is refused. Across peers it says nothing, because a restarted relay counts from
|
|
1145
|
+
zero again; there Cloudly's own acceptance time orders the registrations, and a registration
|
|
1146
|
+
arriving on a live verified socket supersedes the stored one.
|
|
1147
|
+
|
|
1148
|
+
An administrator reads the result with `getClusterRelayRegistrations { identity, clusterIds? }`,
|
|
1149
|
+
answered with `IClusterRelayRegistration` per cluster: the cluster, the node, the listen address
|
|
1150
|
+
and port, the relay version, the sequence that relay counted, Cloudly's `acceptedAt` — and
|
|
1151
|
+
`live`, whether a verified socket carries that relay at this instant. `live` is a liveness fact
|
|
1152
|
+
and grants nothing: a registration that is perfectly current reads `live: false` while its socket
|
|
1153
|
+
is gone, and a cluster whose relay never registered is absent from the answer rather than
|
|
1154
|
+
present with an empty one. `validateClusterRelayRegistration(value, path?)` returns one named
|
|
1155
|
+
reason per violation, as every validator here does.
|
|
1141
1156
|
|
|
1142
1157
|
```typescript
|
|
1143
1158
|
const registration: data.IClusterRelayRegistrationV1 = {
|
|
@@ -1154,6 +1169,91 @@ const registration: data.IClusterRelayRegistrationV1 = {
|
|
|
1154
1169
|
const registrationReasons = data.validateClusterRelayRegistrationV1(registration); // []
|
|
1155
1170
|
```
|
|
1156
1171
|
|
|
1172
|
+
### Cluster Ingress
|
|
1173
|
+
|
|
1174
|
+
A cluster's ingress terminates TLS for the hostnames its services publish and forwards to the
|
|
1175
|
+
host ports Pallet published for the workloads behind them. Cloudly computes what it serves — it
|
|
1176
|
+
is the only party that knows every service, every ready endpoint, the node address each published
|
|
1177
|
+
port answers on and the certificate each hostname needs — and the cluster relay carries that table
|
|
1178
|
+
to the ingress and the ingress's counters back. These contracts carry no version suffix and no
|
|
1179
|
+
schema field: the protocol version is the installed `@serve.zone/interfaces` version.
|
|
1180
|
+
|
|
1181
|
+
`IClusterRouteTable { revision, issuedAt, routes, portRoutes }` is the whole table, never a delta.
|
|
1182
|
+
`revision` is its only idempotency: a relay and an ingress apply a table whose revision is greater
|
|
1183
|
+
than the one they hold and ignore anything else, so a repeated push, a replayed push and a push
|
|
1184
|
+
that crossed a newer one all settle the same way. `IClusterHttpRoute` names one hostname, its
|
|
1185
|
+
`destinations` (`{ address, port }`, unicast IPv4 and a real port), the `certificate` that
|
|
1186
|
+
terminates it and optional Basic `authentication`; `IClusterPortRoute` forwards a TCP or UDP
|
|
1187
|
+
listen port without terminating anything. `validateClusterRouteTable(value, path?)` returns one
|
|
1188
|
+
named reason per violation, refuses two routes for one hostname and two port routes for one
|
|
1189
|
+
transport and port, and — because a validation reason travels into logs — **never quotes
|
|
1190
|
+
certificate material or a password in a reason**.
|
|
1191
|
+
|
|
1192
|
+
The table is secret-bearing end to end: it carries the private key of every hostname the ingress
|
|
1193
|
+
serves. Exclude it from hooks, logs, journals and disk on every hop, exactly as a runtime session
|
|
1194
|
+
credential is excluded.
|
|
1195
|
+
|
|
1196
|
+
| Method | Direction | Body |
|
|
1197
|
+
| --- | --- | --- |
|
|
1198
|
+
| `pushClusterRouteTable` | Cloudly → relay | `{ table }` → `{ appliedRevision }` |
|
|
1199
|
+
| `getClusterRouteTable` | relay → Cloudly | `{}` → `{ table \| null }` |
|
|
1200
|
+
| `registerClusterIngress` | ingress → relay → Cloudly | `{ bearer, version, nodeId, capabilities? }` → `{ accepted: true, revision \| null }` |
|
|
1201
|
+
| `getClusterIngressRouteTable` | ingress → relay | `{ knownRevision \| null }` → `{ table \| null }` |
|
|
1202
|
+
| `getClusterTrafficStatistics` | Cloudly → relay → ingress | `{ fromDayUtc, toDayUtc, cursor?, limit }` → `{ statistics, nextCursor? }` |
|
|
1203
|
+
|
|
1204
|
+
`null` for a table means Cloudly has computed none yet — a fact, not an empty table, and an
|
|
1205
|
+
ingress must not serve it as one. An ingress announces itself with a **method**, not a connection
|
|
1206
|
+
tag: the relay learns what connected from what it registered through, which a server owns, rather
|
|
1207
|
+
than from a label a client authored.
|
|
1208
|
+
|
|
1209
|
+
**Who may be the ingress is Cloudly's decision, not the relay's.** The ingress shares the relay's
|
|
1210
|
+
node listener, so anything that reaches it could ask to register, and a relay cannot tell an
|
|
1211
|
+
ingress from anything else. `registerClusterIngress` therefore carries the `bearer` Cloudly minted
|
|
1212
|
+
into the ingress workload's assignment environment and travels both hops with one body: the
|
|
1213
|
+
ingress sends it to its relay, the relay forwards it untouched, and Cloudly verifies the bearer
|
|
1214
|
+
and derives the cluster from the identity tag on the relay's own session. The bearer is sensitive
|
|
1215
|
+
ephemeral input — excluded from hooks, logs, diagnostics and journals on every hop, and never
|
|
1216
|
+
quoted in a validation reason.
|
|
1217
|
+
|
|
1218
|
+
Isolation on that shared listener is therefore by **authorization, not by routing**: only the
|
|
1219
|
+
connection whose registration Cloudly accepted is the ingress, `getClusterIngressRouteTable` and
|
|
1220
|
+
`getClusterTrafficStatistics` are answered for that connection alone, and any other connection —
|
|
1221
|
+
including a Pallet node's — is refused by name. `validateClusterIngressRegistration(value, path?)`
|
|
1222
|
+
checks shape only: whether the bearer is the one Cloudly minted is Cloudly's to verify.
|
|
1223
|
+
|
|
1224
|
+
`IClusterTrafficStatistics` is one UTC day of one hostname's traffic on one node —
|
|
1225
|
+
`requests`, `bytesIn`, `bytesOut`, `connections` and the backend failures the proxy can observe
|
|
1226
|
+
(`connect`, `handshake`, `request`). Day buckets rather than rates: a rate answers "how busy is it
|
|
1227
|
+
now", which the live proxy already answers, while a bucket survives a restart, a poll that
|
|
1228
|
+
straddles midnight and a Cloudly outage. HTTP status classes are deliberately absent — the proxy
|
|
1229
|
+
exposes no status counters today, and a number this contract cannot source would be a guess.
|
|
1230
|
+
Readers page it exactly like CoreMail's mail statistics — the same `fromDayUtc`, `toDayUtc`,
|
|
1231
|
+
`cursor` and `limit`, answered as `{ statistics, nextCursor? }` — re-reading yesterday and today on
|
|
1232
|
+
every pass because a day only stops changing once it has closed. `dayUtc` must name a day that
|
|
1233
|
+
exists: the shared UTC calendar-day rule round-trips through `Date.UTC`, so `2026-13-45` is
|
|
1234
|
+
refused rather than stored.
|
|
1235
|
+
|
|
1236
|
+
```typescript
|
|
1237
|
+
const reasons = data.validateClusterRouteTable(table); // []
|
|
1238
|
+
const pageReasons = data.validateClusterTrafficStatisticsPage({ statistics: [] }); // []
|
|
1239
|
+
const ingressReasons = data.validateClusterIngressRegistration({
|
|
1240
|
+
bearer: ingressBearerFromAssignmentEnvironment,
|
|
1241
|
+
version: '3.0.0',
|
|
1242
|
+
nodeId: 'node-a',
|
|
1243
|
+
}); // []
|
|
1244
|
+
```
|
|
1245
|
+
|
|
1246
|
+
### Node Uplink Address
|
|
1247
|
+
|
|
1248
|
+
A route to a node's published host ports needs the address that node answers on, and only the
|
|
1249
|
+
node can prove it: it holds the uplink observation the address belongs to. It therefore states it
|
|
1250
|
+
on the network report it already sends — `IReportRuntimeNetworkProtectionRequestV1` gains the
|
|
1251
|
+
optional `uplinkAddress`, a unicast IPv4 literal that is neither loopback nor link-local
|
|
1252
|
+
(`runtimeNodeUplinkAddress`). Absence stays absent: a node that states no address is told apart
|
|
1253
|
+
from one that states a value, and nothing downstream defaults or infers one. Cloudly stores what
|
|
1254
|
+
the node stated and resolves it into the route table; the relay never substitutes an address of
|
|
1255
|
+
its own.
|
|
1256
|
+
|
|
1157
1257
|
Shared service port helpers are exported from `data` so Cloudly, App Store resolution, Coreflow, Coretraffic, Onebox, and dcrouter agree on the same normalization rules:
|
|
1158
1258
|
|
|
1159
1259
|
```typescript
|
package/ts/00_commitinfo_data.ts
CHANGED
package/ts/data/cluster.ts
CHANGED
|
@@ -68,8 +68,9 @@ export interface IClusterRelayV1 {
|
|
|
68
68
|
* is the one its verified machine identity names and is never a field here. `relay.nodeId` is
|
|
69
69
|
* the cluster node the relay process runs on, `listenAddress` and `listenPort` are the exact
|
|
70
70
|
* endpoint it bound for the Pallet nodes of its cluster, and `registrationSequence` counts up
|
|
71
|
-
* once per
|
|
72
|
-
* a
|
|
71
|
+
* once per attempt within one relay process. It orders registrations only within one live
|
|
72
|
+
* peer, where it must strictly increase, a refused registration does not consume it, and a
|
|
73
|
+
* repeat of an accepted sequence is refused; across peers Cloudly's own acceptance time orders.
|
|
73
74
|
*/
|
|
74
75
|
export interface IClusterRelayRegistrationV1 {
|
|
75
76
|
schemaVersion: 1;
|
|
@@ -96,13 +97,13 @@ export interface IClusterRelayRegistrationV1 {
|
|
|
96
97
|
* What Cloudly tells the relay back.
|
|
97
98
|
*
|
|
98
99
|
* `origin` is the origin Cloudly has published for this cluster, so a relay can check that the
|
|
99
|
-
* certificate it holds and the name its nodes are told to reach are the same one.
|
|
100
|
-
*
|
|
101
|
-
*
|
|
100
|
+
* certificate it holds and the name its nodes are told to reach are the same one. An accepted
|
|
101
|
+
* registration always carries one: a cluster whose relay nobody enabled has no origin to
|
|
102
|
+
* register into, and that registration is refused by name instead of answered.
|
|
102
103
|
*/
|
|
103
104
|
export interface IClusterRelayRegistrationResponseV1 {
|
|
104
105
|
accepted: true;
|
|
105
|
-
origin: string
|
|
106
|
+
origin: string;
|
|
106
107
|
}
|
|
107
108
|
|
|
108
109
|
const maximumClusterRelayOriginLength = 2048;
|
|
@@ -185,8 +186,8 @@ const validateClusterRelayVersion = (valueArg: unknown, pathArg: string): string
|
|
|
185
186
|
+ 'digits, dot, plus, underscore or hyphen, starting with a letter or digit']
|
|
186
187
|
);
|
|
187
188
|
|
|
188
|
-
/** The same
|
|
189
|
-
const
|
|
189
|
+
/** The same identifier rule a node's own runtime session registers under. */
|
|
190
|
+
const validateClusterRelayIdentifier = (valueArg: unknown, pathArg: string): string[] => (
|
|
190
191
|
typeof valueArg === 'string' && /^[A-Za-z0-9_-]{1,128}$/.test(valueArg)
|
|
191
192
|
? []
|
|
192
193
|
: [`${pathArg} must be 1 to 128 characters of letters, digits, underscore or hyphen`]
|
|
@@ -213,6 +214,12 @@ const validateClusterRelayListenPort = (valueArg: unknown, pathArg: string): str
|
|
|
213
214
|
: [`${pathArg} must be an integer from 1 to 65535`]
|
|
214
215
|
);
|
|
215
216
|
|
|
217
|
+
const validateClusterRelayNonNegativeInteger = (valueArg: unknown, pathArg: string): string[] => (
|
|
218
|
+
typeof valueArg === 'number' && Number.isSafeInteger(valueArg) && valueArg >= 0
|
|
219
|
+
? []
|
|
220
|
+
: [`${pathArg} must be a non-negative safe integer`]
|
|
221
|
+
);
|
|
222
|
+
|
|
216
223
|
const validateClusterRelayEndpoint = (valueArg: unknown, pathArg: string): string[] => {
|
|
217
224
|
if (!isRecord(valueArg)
|
|
218
225
|
|| !hasExactKeys(valueArg, ['version', 'nodeId', 'listenAddress', 'listenPort'])) {
|
|
@@ -220,7 +227,7 @@ const validateClusterRelayEndpoint = (valueArg: unknown, pathArg: string): strin
|
|
|
220
227
|
}
|
|
221
228
|
return [
|
|
222
229
|
...validateClusterRelayVersion(valueArg.version, `${pathArg} version`),
|
|
223
|
-
...
|
|
230
|
+
...validateClusterRelayIdentifier(valueArg.nodeId, `${pathArg} nodeId`),
|
|
224
231
|
...validateClusterRelayListenAddress(valueArg.listenAddress, `${pathArg} listenAddress`),
|
|
225
232
|
...validateClusterRelayListenPort(valueArg.listenPort, `${pathArg} listenPort`),
|
|
226
233
|
];
|
|
@@ -231,9 +238,10 @@ const validateClusterRelayEndpoint = (valueArg: unknown, pathArg: string): strin
|
|
|
231
238
|
*
|
|
232
239
|
* Shape only, exactly like every other validator here: which cluster the relay speaks for comes
|
|
233
240
|
* from the verified identity on its socket, whether `relay.nodeId` is a node of that cluster is
|
|
234
|
-
* Cloudly's to decide against its own records, and whether this registration supersedes
|
|
235
|
-
* one is Cloudly's
|
|
236
|
-
* passes here has
|
|
241
|
+
* Cloudly's to decide against its own records, and whether this registration supersedes the
|
|
242
|
+
* stored one is Cloudly's decision too. `registrationSequence` restarts with the relay process,
|
|
243
|
+
* so it orders registrations only within one live peer. A registration that passes here has
|
|
244
|
+
* claimed nothing.
|
|
237
245
|
*/
|
|
238
246
|
export const validateClusterRelayRegistrationV1 = (
|
|
239
247
|
valueArg: unknown,
|
|
@@ -248,14 +256,65 @@ export const validateClusterRelayRegistrationV1 = (
|
|
|
248
256
|
errors.push(`${pathArg} schemaVersion must be 1`);
|
|
249
257
|
}
|
|
250
258
|
errors.push(...validateClusterRelayEndpoint(valueArg.relay, `${pathArg} relay`));
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|| valueArg.registrationSequence < 0) {
|
|
254
|
-
errors.push(`${pathArg} registrationSequence must be a non-negative safe integer`);
|
|
255
|
-
}
|
|
259
|
+
errors.push(...validateClusterRelayNonNegativeInteger(valueArg.registrationSequence,
|
|
260
|
+
`${pathArg} registrationSequence`));
|
|
256
261
|
return errors;
|
|
257
262
|
};
|
|
258
263
|
|
|
264
|
+
/**
|
|
265
|
+
* One cluster's relay as Cloudly serves it to an administrator.
|
|
266
|
+
*
|
|
267
|
+
* This is the read shape, not the registration a relay sends: `IClusterRelayRegistrationV1` is
|
|
268
|
+
* what the relay puts on the wire, and this is what Cloudly answers with after it accepted one.
|
|
269
|
+
* `clusterId` names the cluster the relay serves, and `acceptedAt` is Cloudly's own acceptance
|
|
270
|
+
* time, which is what orders two registrations of one cluster.
|
|
271
|
+
*/
|
|
272
|
+
export interface IClusterRelayRegistration {
|
|
273
|
+
clusterId: string;
|
|
274
|
+
nodeId: string;
|
|
275
|
+
listenAddress: string;
|
|
276
|
+
listenPort: number;
|
|
277
|
+
version: string;
|
|
278
|
+
registrationSequence: number;
|
|
279
|
+
acceptedAt: number;
|
|
280
|
+
/**
|
|
281
|
+
* Whether a verified socket carries this relay at this instant.
|
|
282
|
+
*
|
|
283
|
+
* A liveness fact and nothing else: it grants no authority, it is not part of what was
|
|
284
|
+
* registered, and it is false for a relay whose registration is perfectly current but whose
|
|
285
|
+
* socket is gone, so a reader must not treat it as a statement about the registration.
|
|
286
|
+
*/
|
|
287
|
+
live: boolean;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Validates one served relay registration and names every reason it is refused.
|
|
292
|
+
*
|
|
293
|
+
* Shape only, like every validator here. Whether the cluster exists, whether the node still
|
|
294
|
+
* belongs to it and whether the relay is really connected are Cloudly's own records; a value
|
|
295
|
+
* that passes here has claimed nothing.
|
|
296
|
+
*/
|
|
297
|
+
export const validateClusterRelayRegistration = (
|
|
298
|
+
valueArg: unknown,
|
|
299
|
+
pathArg = 'cluster relay registration',
|
|
300
|
+
): string[] => {
|
|
301
|
+
if (!isRecord(valueArg) || !hasExactKeys(valueArg, ['clusterId', 'nodeId', 'listenAddress',
|
|
302
|
+
'listenPort', 'version', 'registrationSequence', 'acceptedAt', 'live'])) {
|
|
303
|
+
return [`${pathArg} must use its exact schema`];
|
|
304
|
+
}
|
|
305
|
+
return [
|
|
306
|
+
...validateClusterRelayIdentifier(valueArg.clusterId, `${pathArg} clusterId`),
|
|
307
|
+
...validateClusterRelayIdentifier(valueArg.nodeId, `${pathArg} nodeId`),
|
|
308
|
+
...validateClusterRelayListenAddress(valueArg.listenAddress, `${pathArg} listenAddress`),
|
|
309
|
+
...validateClusterRelayListenPort(valueArg.listenPort, `${pathArg} listenPort`),
|
|
310
|
+
...validateClusterRelayVersion(valueArg.version, `${pathArg} version`),
|
|
311
|
+
...validateClusterRelayNonNegativeInteger(valueArg.registrationSequence,
|
|
312
|
+
`${pathArg} registrationSequence`),
|
|
313
|
+
...validateClusterRelayNonNegativeInteger(valueArg.acceptedAt, `${pathArg} acceptedAt`),
|
|
314
|
+
...(typeof valueArg.live === 'boolean' ? [] : [`${pathArg} live must be a boolean`]),
|
|
315
|
+
];
|
|
316
|
+
};
|
|
317
|
+
|
|
259
318
|
/**
|
|
260
319
|
* The name the relay's certificate is issued for, and the A record Cloudly
|
|
261
320
|
* owns for it. Derived from the origin so every consumer derives it
|