@serve.zone/interfaces 32.2.0 → 32.4.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 +69 -0
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/data/cluster.d.ts +30 -0
- package/dist_ts/data/cluster.js +46 -2
- package/dist_ts/data/clusternode.d.ts +21 -0
- package/dist_ts/data/clusternode.js +345 -11
- package/dist_ts/data/clustervpn.d.ts +135 -0
- package/dist_ts/data/clustervpn.js +147 -0
- package/dist_ts/data/index.d.ts +1 -0
- package/dist_ts/data/index.js +2 -1
- package/dist_ts/data/networkaddressplan.d.ts +54 -11
- package/dist_ts/data/networkaddressplan.js +67 -23
- package/dist_ts/data/networkcredential.d.ts +13 -4
- package/dist_ts/data/networkcredential.js +41 -23
- package/dist_ts/data/runtimeassignment.d.ts +23 -0
- package/dist_ts/data/runtimeassignment.js +42 -7
- package/dist_ts/platform/storage.d.ts +19 -0
- package/dist_ts/platform/storage.js +23 -3
- package/dist_ts/private/networkcontract.d.ts +6 -0
- package/dist_ts/private/networkcontract.js +12 -1
- package/dist_ts/requests/cluster.d.ts +27 -0
- package/dist_ts/requests/cluster.js +1 -1
- package/package.json +1 -1
- package/readme.md +139 -21
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/data/cluster.ts +76 -1
- package/ts/data/clusternode.ts +457 -10
- package/ts/data/clustervpn.ts +248 -0
- package/ts/data/index.ts +1 -0
- package/ts/data/networkaddressplan.ts +103 -27
- package/ts/data/networkcredential.ts +52 -24
- package/ts/data/runtimeassignment.ts +58 -5
- package/ts/platform/storage.ts +27 -5
- package/ts/private/networkcontract.ts +11 -0
- package/ts/requests/cluster.ts +35 -0
package/changelog.md
CHANGED
|
@@ -1,5 +1,74 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2026-09-19 - 32.4.0
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
- This minor removes rather than deprecates `data.IRuntimeNetworkAddressPlan.vpn.relay`,
|
|
8
|
+
`data.runtimeNetworkAddressPlanContract.relayProtocol` and
|
|
9
|
+
`data.IGetRuntimeManagedVpnCredentialResponse.relay`, which stays a minor of the one common
|
|
10
|
+
major 32 because no shipped store holds an address-plan row and a peer that still speaks the old
|
|
11
|
+
shapes is fenced by the session handshake, each server raising its own `minimumPeerVersion` for
|
|
12
|
+
`clusterRelay` and `palletRuntime` in its own commit.
|
|
13
|
+
- The managed VPN moves from one platform-wide endpoint to a hub per cluster, carried by that
|
|
14
|
+
cluster's own relay. `data.IRuntimeNetworkAddressPlan.vpn` is now
|
|
15
|
+
`{ controlPrefix, hubPrefix }`: `hubPrefix` is the protected prefix every cluster hub binds
|
|
16
|
+
inside, and the endpoints are no longer administrator input. `runtimeNetworkAddressPlanContract`
|
|
17
|
+
replaces `relayProtocol` with `hubTransports`, the one table that states each transport's endpoint
|
|
18
|
+
id suffix and protocol, and `data.runtimeNetworkVpnHubEndpoints(hub)` is the one derivation of
|
|
19
|
+
what one `data.IRuntimeNetworkVpnHub { clusterId, address, quicPort, websocketPort }` contributes:
|
|
20
|
+
`<clusterId>:quic` on `udp` and `<clusterId>:ws` on `tcp`.
|
|
21
|
+
`composeRuntimeNetworkProtectedAuthority(plan, frame, hubs)` takes those hubs as its third
|
|
22
|
+
argument and requires each address inside `vpn.hubPrefix`, with one hub per cluster; 32 clusters
|
|
23
|
+
fit one authority's 64 platform endpoints. `plan-vpn-immutable` now guards both prefixes.
|
|
24
|
+
- `data.IGetRuntimeManagedVpnCredentialResponse` names the cluster hub it sends a node to: `relay`
|
|
25
|
+
becomes `hub`, `transport` widens to `'quic' | 'websocket'`, and the new optional `serverName` is
|
|
26
|
+
present exactly when the transport is `websocket` — the TLS name that hub is dialled under, which
|
|
27
|
+
the node cross-checks against the relay origin it stores. The binder requires the selected
|
|
28
|
+
endpoint to carry the protocol of the credential's transport, so a relay still cannot name itself.
|
|
29
|
+
- `data.IRegisterClusterRelayRequest.relay.vpnHub` is the optional
|
|
30
|
+
`data.IClusterRelayVpnHub { publicKey, address, quicPort, websocketPort }` a relay reports from its
|
|
31
|
+
own bind, validated by `data.validateClusterRelayVpnHub`. A relay that serves no hub registers
|
|
32
|
+
exactly as before, and Cloudly states `relay-vpn-hub-absent` for that cluster.
|
|
33
|
+
- Add `data.IClusterVpnNetwork { authorityId, revision, nodes, grants }`, the complete managed VPN of
|
|
34
|
+
one cluster, with `snapshotClusterVpnNetwork`, `admitClusterVpnNetwork(held | null, next)`,
|
|
35
|
+
`clusterVpnControlPolicyDomain`, `clusterVpnWorkloadPolicyDomain` and `clusterVpnNetworkContract`.
|
|
36
|
+
Every grant must join two workload domains the network itself carries, on two different nodes, so a
|
|
37
|
+
cross-cluster grant cannot be expressed; Cloudly refuses it by name while it compiles.
|
|
38
|
+
- Add the two carriers on the relay's own session: `requests.cluster.applyClusterVpnNetwork`
|
|
39
|
+
(`{ network }` → `{ appliedRevision, state }`, with `bindApplyClusterVpnNetworkResponse`) and
|
|
40
|
+
`requests.cluster.getClusterVpnNetwork` (no request body → `{ network }` or `{ network: null }`),
|
|
41
|
+
plus the refusal vocabularies `data.applyClusterVpnNetworkRefusals` and
|
|
42
|
+
`data.clusterVpnNetworkSelectionRefusals`.
|
|
43
|
+
- `data.IRuntimeAssignment.workload.pullEndpoint` is the optional `host[:port]` a node fetches the
|
|
44
|
+
image from instead of the publishing `registryHost`, and
|
|
45
|
+
`data.buildRuntimeAssignmentImageReference(workload)` is the one place that choice is made. The
|
|
46
|
+
reference stays digest-pinned, so the endpoint decides reachability and never content, and
|
|
47
|
+
`registryHost` keeps its publication identity.
|
|
48
|
+
|
|
49
|
+
## 2026-09-18 - 32.3.0
|
|
50
|
+
|
|
51
|
+
### Features
|
|
52
|
+
|
|
53
|
+
- Add `platform.normalizeStorageRequest(value)`, the contract's own statement of which storage
|
|
54
|
+
requests exist: it reads a body against the exact request schema and returns the request in its
|
|
55
|
+
contract shape — canonical environment keys, no empty `protection` block, no explicitly undefined
|
|
56
|
+
member, `retentionDays` within its bound, no `-0` or unsafe integer, plain JSON data members
|
|
57
|
+
only. `canonicalizeStorageRequest` and `createStorageRequestSha256` are now derived from it, so a
|
|
58
|
+
consumer that admits requests and the control plane that digests them apply one set of acceptance
|
|
59
|
+
rules instead of each keeping an aligned copy. The input is never mutated, the returned request
|
|
60
|
+
is fresh, and a body that is not a storage request is refused with `platform.StorageContractError`
|
|
61
|
+
whose message names the failing member.
|
|
62
|
+
- Add `data.validateSparkSwarmNodeHeartbeatRequest`, `data.validateSparkMetricsSampleRequest` and
|
|
63
|
+
`data.validateSparkActionResultRequest`, so all four Spark Swarm routes are judged by the
|
|
64
|
+
contract that owns their shapes instead of by member checks a consumer keeps beside them. Each
|
|
65
|
+
reads the exact key set, the sender's `protocol` offer and the reporter's identity, then names
|
|
66
|
+
every refused member of its payload — a heartbeat's metrics and runtime description down to each
|
|
67
|
+
described serve.zone service, a sample's observations and optional network rates, and an action
|
|
68
|
+
result whose status is one a node can report, never `pending`. They answer in the same
|
|
69
|
+
`Promise<string[]>` shape as `validateSparkSwarmObservationRequest`, refuse an accessor instead
|
|
70
|
+
of running it, and neither authenticate a node nor act on the body.
|
|
71
|
+
|
|
3
72
|
## 2026-09-18 - 32.2.0
|
|
4
73
|
|
|
5
74
|
### Features
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@serve.zone/interfaces',
|
|
6
|
-
version: '32.
|
|
6
|
+
version: '32.4.0',
|
|
7
7
|
description: 'Shared TypeScript interfaces and TypedRequest contracts for the serve.zone ecosystem.'
|
|
8
8
|
};
|
|
9
9
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx3QkFBd0I7SUFDOUIsT0FBTyxFQUFFLFFBQVE7SUFDakIsV0FBVyxFQUFFLHVGQUF1RjtDQUNyRyxDQUFBIn0=
|
|
@@ -48,6 +48,24 @@ export interface ICluster {
|
|
|
48
48
|
export interface IClusterRelay {
|
|
49
49
|
origin: string;
|
|
50
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* The managed VPN hub a cluster relay bound for its own cluster.
|
|
53
|
+
*
|
|
54
|
+
* The relay is its cluster's packet relay: every node of the cluster dials this hub and no
|
|
55
|
+
* inter-node packet leaves the cluster. It reports what it bound, exactly like `listenAddress` and
|
|
56
|
+
* `listenPort`, and Cloudly composes the platform endpoints from it — a relay names no endpoint id
|
|
57
|
+
* and no TLS name of its own. `publicKey` is the hub's Noise public key in the one canonical
|
|
58
|
+
* 32-byte base64 encoding every Noise key of this contract is read with; it is public material and
|
|
59
|
+
* authenticates nothing by itself. A hub that bound only one transport reports the other port as
|
|
60
|
+
* `null`.
|
|
61
|
+
*/
|
|
62
|
+
export interface IClusterRelayVpnHub {
|
|
63
|
+
publicKey: string;
|
|
64
|
+
/** The address the hub bound, as an IPv4 literal inside the address plan's `vpn.hubPrefix`. */
|
|
65
|
+
address: string;
|
|
66
|
+
quicPort: number | null;
|
|
67
|
+
websocketPort: number | null;
|
|
68
|
+
}
|
|
51
69
|
/**
|
|
52
70
|
* What a cluster relay tells Cloudly about itself once its socket is authenticated.
|
|
53
71
|
*
|
|
@@ -74,6 +92,11 @@ export interface IRegisterClusterRelayRequest {
|
|
|
74
92
|
*/
|
|
75
93
|
listenAddress: string;
|
|
76
94
|
listenPort: number;
|
|
95
|
+
/**
|
|
96
|
+
* Absent on a relay that serves no managed VPN hub, which registers exactly as it did before.
|
|
97
|
+
* Cloudly selects no hub for such a cluster and states `relay-vpn-hub-absent` instead.
|
|
98
|
+
*/
|
|
99
|
+
vpnHub?: IClusterRelayVpnHub;
|
|
77
100
|
};
|
|
78
101
|
/** Monotonic within one relay process; it restarts at 0 when the process restarts. */
|
|
79
102
|
registrationSequence: number;
|
|
@@ -118,6 +141,13 @@ export type TClusterRelayUndispatchedRefusal = typeof clusterRelayUndispatchedRe
|
|
|
118
141
|
* registers over.
|
|
119
142
|
*/
|
|
120
143
|
export declare const validateClusterRelay: (valueArg: unknown, pathArg?: string) => string[];
|
|
144
|
+
/**
|
|
145
|
+
* Validates one hub advertisement and names every reason it is refused.
|
|
146
|
+
*
|
|
147
|
+
* Shape only: whether the address sits inside the address plan's `vpn.hubPrefix` is Cloudly's to
|
|
148
|
+
* decide against the plan it stores, and the endpoints themselves are composed there.
|
|
149
|
+
*/
|
|
150
|
+
export declare const validateClusterRelayVpnHub: (valueArg: unknown, pathArg?: string) => string[];
|
|
121
151
|
/**
|
|
122
152
|
* Validates one cluster relay registration and names every reason it is refused.
|
|
123
153
|
*
|
package/dist_ts/data/cluster.js
CHANGED
|
@@ -3,6 +3,7 @@ import {} from '../data/docker.js';
|
|
|
3
3
|
import { isPlausibleUnicastIpv4 } from '../private/ipv4.js';
|
|
4
4
|
import { validateProtocolOfferOn } from '../protocol.js';
|
|
5
5
|
import { hasExactKeys } from '../private/dataproperties.js';
|
|
6
|
+
import { networkNoiseKey } from '../private/networkcontract.js';
|
|
6
7
|
/**
|
|
7
8
|
* The registration refusals that end a relay's custody of its cluster.
|
|
8
9
|
*
|
|
@@ -96,9 +97,49 @@ const validateClusterRelayListenPort = (valueArg, pathArg) => (typeof valueArg =
|
|
|
96
97
|
const validateClusterRelayNonNegativeInteger = (valueArg, pathArg) => (typeof valueArg === 'number' && Number.isSafeInteger(valueArg) && valueArg >= 0
|
|
97
98
|
? []
|
|
98
99
|
: [`${pathArg} must be a non-negative safe integer`]);
|
|
100
|
+
/**
|
|
101
|
+
* The one canonical 32-byte base64 reading every Noise key of this contract passes, stated as a
|
|
102
|
+
* refusal this validator's callers can collect: a hub key is the same key material the managed VPN
|
|
103
|
+
* credential carries, so it is never read by a second rule that could drift from it.
|
|
104
|
+
*/
|
|
105
|
+
const validateClusterRelayVpnKey = (valueArg, pathArg) => {
|
|
106
|
+
try {
|
|
107
|
+
networkNoiseKey(valueArg);
|
|
108
|
+
return [];
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
return [`${pathArg} must be a canonical 32-byte base64 public key`];
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
/** A port the hub bound, or `null` for a transport it did not bind. */
|
|
115
|
+
const validateClusterRelayHubPort = (valueArg, pathArg) => (valueArg === null || validateClusterRelayListenPort(valueArg, pathArg).length === 0
|
|
116
|
+
? []
|
|
117
|
+
: [`${pathArg} must be null or an integer from 1 to 65535`]);
|
|
118
|
+
/**
|
|
119
|
+
* Validates one hub advertisement and names every reason it is refused.
|
|
120
|
+
*
|
|
121
|
+
* Shape only: whether the address sits inside the address plan's `vpn.hubPrefix` is Cloudly's to
|
|
122
|
+
* decide against the plan it stores, and the endpoints themselves are composed there.
|
|
123
|
+
*/
|
|
124
|
+
export const validateClusterRelayVpnHub = (valueArg, pathArg = 'cluster relay vpn hub') => {
|
|
125
|
+
if (!isRecord(valueArg)
|
|
126
|
+
|| !hasExactKeys(valueArg, ['publicKey', 'address', 'quicPort', 'websocketPort'])) {
|
|
127
|
+
return [`${pathArg} must use its exact schema`];
|
|
128
|
+
}
|
|
129
|
+
const errors = [
|
|
130
|
+
...validateClusterRelayVpnKey(valueArg.publicKey, `${pathArg} publicKey`),
|
|
131
|
+
...validateClusterRelayListenAddress(valueArg.address, `${pathArg} address`),
|
|
132
|
+
...validateClusterRelayHubPort(valueArg.quicPort, `${pathArg} quicPort`),
|
|
133
|
+
...validateClusterRelayHubPort(valueArg.websocketPort, `${pathArg} websocketPort`),
|
|
134
|
+
];
|
|
135
|
+
if (valueArg.quicPort === null && valueArg.websocketPort === null) {
|
|
136
|
+
errors.push(`${pathArg} must bind at least one of quicPort and websocketPort`);
|
|
137
|
+
}
|
|
138
|
+
return errors;
|
|
139
|
+
};
|
|
99
140
|
const validateClusterRelayEndpoint = (valueArg, pathArg) => {
|
|
100
141
|
if (!isRecord(valueArg)
|
|
101
|
-
|| !hasExactKeys(valueArg, ['version', 'nodeId', 'listenAddress', 'listenPort'])) {
|
|
142
|
+
|| !hasExactKeys(valueArg, ['version', 'nodeId', 'listenAddress', 'listenPort'], ['vpnHub'])) {
|
|
102
143
|
return [`${pathArg} must use its exact schema`];
|
|
103
144
|
}
|
|
104
145
|
return [
|
|
@@ -106,6 +147,9 @@ const validateClusterRelayEndpoint = (valueArg, pathArg) => {
|
|
|
106
147
|
...validateClusterRelayIdentifier(valueArg.nodeId, `${pathArg} nodeId`),
|
|
107
148
|
...validateClusterRelayListenAddress(valueArg.listenAddress, `${pathArg} listenAddress`),
|
|
108
149
|
...validateClusterRelayListenPort(valueArg.listenPort, `${pathArg} listenPort`),
|
|
150
|
+
...(Object.keys(valueArg).includes('vpnHub')
|
|
151
|
+
? validateClusterRelayVpnHub(valueArg.vpnHub, `${pathArg} vpnHub`)
|
|
152
|
+
: []),
|
|
109
153
|
];
|
|
110
154
|
};
|
|
111
155
|
/**
|
|
@@ -170,4 +214,4 @@ export const clusterRelayCertificateDomainName = (relayArg) => {
|
|
|
170
214
|
}
|
|
171
215
|
return new URL(relayArg.origin).hostname;
|
|
172
216
|
};
|
|
173
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
217
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL2RhdGEvY2x1c3Rlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGVBQWUsQ0FBQztBQUV6QyxPQUFPLEVBQTRCLE1BQU0sbUJBQW1CLENBQUM7QUFFN0QsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDNUQsT0FBTyxFQUFFLHVCQUF1QixFQUF1QixNQUFNLGdCQUFnQixDQUFDO0FBQzlFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUM1RCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFzSWhFOzs7Ozs7OztHQVFHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sZ0NBQWdDLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQztJQUM1RCwrRUFBK0U7SUFDL0UsMkJBQTJCO0lBQzNCLDJGQUEyRjtJQUMzRixvQkFBb0I7SUFDcEIsa0dBQWtHO0lBQ2xHLDhCQUE4QjtDQUN0QixDQUFDLENBQUM7QUFLWixNQUFNLCtCQUErQixHQUFHLElBQUksQ0FBQztBQUM3QyxNQUFNLGdDQUFnQyxHQUFHLEVBQUUsQ0FBQztBQUU1QyxNQUFNLFFBQVEsR0FBRyxDQUFDLFFBQWlCLEVBQXVDLEVBQUUsQ0FBQyxDQUMzRSxPQUFPLENBQUMsUUFBUSxDQUFDO09BQ2QsT0FBTyxRQUFRLEtBQUssUUFBUTtPQUM1QixDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDO09BQ3hCLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxRQUFRLENBQUMsS0FBSyxNQUFNLENBQUMsU0FBUztXQUNuRCxNQUFNLENBQUMsY0FBYyxDQUFDLFFBQVEsQ0FBQyxLQUFLLElBQUksQ0FBQyxDQUMvQyxDQUFDO0FBRUYsTUFBTSwwQkFBMEIsR0FBRyxDQUFDLFFBQWlCLEVBQUUsT0FBZSxFQUFZLEVB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
|
|
@@ -288,6 +288,27 @@ export declare const computeSwarmManagerSnapshotDigest: (swarmClusterIdArg: stri
|
|
|
288
288
|
export declare const validateSparkSwarmObservation: (observationArg: unknown) => Promise<string[]>;
|
|
289
289
|
export declare const validateSparkSwarmObservationRequest: (requestArg: unknown) => Promise<string[]>;
|
|
290
290
|
export declare const validateSparkSwarmObservationResponse: (responseArg: unknown, expectedRequestArg: ISparkSwarmObservationRequest) => Promise<string[]>;
|
|
291
|
+
/**
|
|
292
|
+
* Spark -> Cloudly body for `sparkSwarmNodeContracts.heartbeat.endpoint`.
|
|
293
|
+
*
|
|
294
|
+
* Stated here beside the shape it judges, so the server that reads the beat and the node that
|
|
295
|
+
* writes it apply one set of acceptance rules; a reader that kept its own member checks would
|
|
296
|
+
* decide on its own which beats exist.
|
|
297
|
+
*
|
|
298
|
+
* Every Spark route validator answers the same way — one string per refused member, empty for an
|
|
299
|
+
* admissible body, and the same `(body) => Promise<string[]>` signature, so a server can hold the
|
|
300
|
+
* four routes in one table.
|
|
301
|
+
*/
|
|
302
|
+
export declare const validateSparkSwarmNodeHeartbeatRequest: (requestArg: unknown) => Promise<string[]>;
|
|
303
|
+
/** Spark -> Cloudly body for `sparkSwarmNodeContracts.metricsSample.endpoint`. */
|
|
304
|
+
export declare const validateSparkMetricsSampleRequest: (requestArg: unknown) => Promise<string[]>;
|
|
305
|
+
/**
|
|
306
|
+
* Spark -> Cloudly body for `sparkSwarmNodeContracts.actionResult.endpoint`.
|
|
307
|
+
*
|
|
308
|
+
* `pending` is the one status a node never reports: an action it has not started has no result to
|
|
309
|
+
* post, and a server that accepted one would reopen an action it already handed out.
|
|
310
|
+
*/
|
|
311
|
+
export declare const validateSparkActionResultRequest: (requestArg: unknown) => Promise<string[]>;
|
|
291
312
|
export declare const createClusterRuntimeTargetSetDigestInput: (targetSetArg: IClusterRuntimeTargetSetReady) => string;
|
|
292
313
|
export declare const computeClusterRuntimeTargetSetDigest: (targetSetArg: IClusterRuntimeTargetSetReady) => Promise<TSha256Digest>;
|
|
293
314
|
export declare const validateClusterRuntimeTargetSet: (targetSetArg: unknown) => Promise<string[]>;
|