@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
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One workload prefix a node owns inside its cluster's managed VPN, and the policy domain that
|
|
3
|
+
* names it in a grant. Both are Cloudly's words: the relay matches them, it never invents one.
|
|
4
|
+
*/
|
|
5
|
+
export interface IClusterVpnNetworkPrefix {
|
|
6
|
+
cidr: string;
|
|
7
|
+
policyDomain: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* One member of a cluster's managed VPN.
|
|
11
|
+
*
|
|
12
|
+
* Membership is presence: a node the network does not list is not a member, so there is no
|
|
13
|
+
* disabled state to carry. `publicKey` is the node's own Noise public key, the one Cloudly issued
|
|
14
|
+
* the node's credential for, and `expiresAt` is that credential's expiry in Unix milliseconds — the
|
|
15
|
+
* hub stops relaying for a member whose window ended even if nothing pushes a new network.
|
|
16
|
+
*/
|
|
17
|
+
export interface IClusterVpnNetworkNode {
|
|
18
|
+
nodeId: string;
|
|
19
|
+
publicKey: string;
|
|
20
|
+
controlAddress: string;
|
|
21
|
+
expiresAt: number;
|
|
22
|
+
workloadPrefixes: IClusterVpnNetworkPrefix[];
|
|
23
|
+
}
|
|
24
|
+
/** One directed relay permission between two workload policy domains of two different nodes. */
|
|
25
|
+
export interface IClusterVpnNetworkGrant {
|
|
26
|
+
sourceDomain: string;
|
|
27
|
+
destinationDomain: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The complete managed VPN of one cluster, as Cloudly states it to that cluster's relay.
|
|
31
|
+
*
|
|
32
|
+
* Complete, never a patch: a relay applies it as the whole authority its hub serves, so a member or
|
|
33
|
+
* a grant that is missing is withdrawn. `revision` is Cloudly's own counter for this authority and
|
|
34
|
+
* only ever rises; `authorityId` names the authority the hub is bound to, so a network compiled for
|
|
35
|
+
* another cluster is refused rather than applied.
|
|
36
|
+
*/
|
|
37
|
+
export interface IClusterVpnNetwork {
|
|
38
|
+
authorityId: string;
|
|
39
|
+
revision: number;
|
|
40
|
+
nodes: IClusterVpnNetworkNode[];
|
|
41
|
+
grants: IClusterVpnNetworkGrant[];
|
|
42
|
+
}
|
|
43
|
+
export declare const clusterVpnNetworkContract: Readonly<{
|
|
44
|
+
/** The policy domain of a node's control address; the hub relays no grant between control domains. */
|
|
45
|
+
readonly controlPolicyDomainPrefix: "control:";
|
|
46
|
+
/** The policy domain of one workload lease, named by that lease's digest. */
|
|
47
|
+
readonly workloadPolicyDomainPrefix: "workload:";
|
|
48
|
+
readonly maximumNodes: 256;
|
|
49
|
+
/** Per node; one workload lease the node's signed projection carries. */
|
|
50
|
+
readonly maximumWorkloadPrefixes: 128;
|
|
51
|
+
readonly maximumGrants: 4096;
|
|
52
|
+
readonly maximumCanonicalBytes: 917504;
|
|
53
|
+
readonly completeness: "whole-authority-never-a-patch";
|
|
54
|
+
readonly membership: "presence-only-an-absent-node-is-withdrawn";
|
|
55
|
+
}>;
|
|
56
|
+
/**
|
|
57
|
+
* Every reason a relay refuses a pushed network, in the words the refusal leads with.
|
|
58
|
+
*
|
|
59
|
+
* A push is applied to a daemon whose lifetime Cloudly cannot see, so the refusal is the only
|
|
60
|
+
* statement about whether the cluster's hub carries this authority. The relay writes
|
|
61
|
+
* `<name>: <reason>` and Cloudly matches the name, which is why the names are stated here instead
|
|
62
|
+
* of being spelled out on both sides.
|
|
63
|
+
*/
|
|
64
|
+
export declare const applyClusterVpnNetworkRefusals: readonly ["vpn-network-authority-foreign", "vpn-network-revision-stale"];
|
|
65
|
+
/** One of the reasons a relay states that its hub did not take a network over. */
|
|
66
|
+
export type TApplyClusterVpnNetworkRefusal = typeof applyClusterVpnNetworkRefusals[number];
|
|
67
|
+
/**
|
|
68
|
+
* Every reason Cloudly states that a cluster has no managed VPN to push.
|
|
69
|
+
*
|
|
70
|
+
* Both are Cloudly reading its own records: a hub it cannot select, and a grant it cannot compile
|
|
71
|
+
* because hubs are per cluster and a grant whose two ends sit in different clusters has no path
|
|
72
|
+
* through any one of them.
|
|
73
|
+
*/
|
|
74
|
+
export declare const clusterVpnNetworkSelectionRefusals: readonly ["relay-vpn-hub-absent", "grant-cross-cluster-unsupported"];
|
|
75
|
+
/** One of the reasons Cloudly states that it compiled no managed VPN for a cluster. */
|
|
76
|
+
export type TClusterVpnNetworkSelectionRefusal = typeof clusterVpnNetworkSelectionRefusals[number];
|
|
77
|
+
/** What a pushed network did to the cluster's hub, in the hub's own words. */
|
|
78
|
+
export type TClusterVpnNetworkState = 'idle' | 'applying' | 'failed';
|
|
79
|
+
export interface IApplyClusterVpnNetworkRequest {
|
|
80
|
+
network: IClusterVpnNetwork;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* What the relay answers: the revision its hub has applied, or `null` while it has applied none,
|
|
84
|
+
* and what the hub is doing. `idle` means the pushed revision is the applied one.
|
|
85
|
+
*/
|
|
86
|
+
export interface IApplyClusterVpnNetworkResponse {
|
|
87
|
+
appliedRevision: number | null;
|
|
88
|
+
state: TClusterVpnNetworkState;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* The pull carries no body. The relay's own socket names the cluster, and a hub daemon that just
|
|
92
|
+
* started holds nothing it could state about what it is missing.
|
|
93
|
+
*/
|
|
94
|
+
export type TGetClusterVpnNetworkRequest = Record<string, never>;
|
|
95
|
+
/** `null` while the cluster has no managed VPN: no address plan, or no hub selected for it yet. */
|
|
96
|
+
export interface IGetClusterVpnNetworkResponse {
|
|
97
|
+
network: IClusterVpnNetwork | null;
|
|
98
|
+
}
|
|
99
|
+
/** The policy domain of one node's control address. One rule, so both sides name it identically. */
|
|
100
|
+
export declare const clusterVpnControlPolicyDomain: (addressValue: unknown) => string;
|
|
101
|
+
/** The policy domain of one workload lease, from that lease's canonical digest. */
|
|
102
|
+
export declare const clusterVpnWorkloadPolicyDomain: (digestValue: unknown) => string;
|
|
103
|
+
/**
|
|
104
|
+
* Structural snapshot of a complete cluster network.
|
|
105
|
+
*
|
|
106
|
+
* Every node, prefix and grant is stated once and in canonical order, and every grant names a
|
|
107
|
+
* workload domain this network itself carries, on two different nodes. That last rule is what a
|
|
108
|
+
* per-cluster hub means: a grant whose other end sits on another cluster's hub cannot be expressed
|
|
109
|
+
* here at all, which is why Cloudly refuses it by name while it compiles instead of pushing it.
|
|
110
|
+
*/
|
|
111
|
+
export declare const snapshotClusterVpnNetwork: (value: unknown) => IClusterVpnNetwork;
|
|
112
|
+
export type TClusterVpnNetworkAdmission = {
|
|
113
|
+
status: 'accepted';
|
|
114
|
+
} | {
|
|
115
|
+
status: 'replay';
|
|
116
|
+
} | {
|
|
117
|
+
status: 'refused';
|
|
118
|
+
reason: TApplyClusterVpnNetworkRefusal;
|
|
119
|
+
};
|
|
120
|
+
/**
|
|
121
|
+
* The pure decision a relay makes about a pushed network against the one its hub holds, or null
|
|
122
|
+
* when the hub holds none — which is every hub that just started, because a daemon restart starts
|
|
123
|
+
* empty. A repeat of the held network is a replay the relay may apply again without effect; a lower
|
|
124
|
+
* revision, or the same revision with different content, is stale and refused by name.
|
|
125
|
+
*/
|
|
126
|
+
export declare const admitClusterVpnNetwork: (heldValue: unknown | null, nextValue: unknown) => TClusterVpnNetworkAdmission;
|
|
127
|
+
export declare const snapshotApplyClusterVpnNetworkRequest: (value: unknown) => IApplyClusterVpnNetworkRequest;
|
|
128
|
+
export declare const snapshotApplyClusterVpnNetworkResponse: (value: unknown) => IApplyClusterVpnNetworkResponse;
|
|
129
|
+
/**
|
|
130
|
+
* Compare the answer with the exact SENT network: a hub that reports itself idle has applied the
|
|
131
|
+
* revision it was sent, and no hub can report having applied a later one than exists.
|
|
132
|
+
*/
|
|
133
|
+
export declare const bindApplyClusterVpnNetworkResponse: (value: unknown, sentRequestValue: unknown) => IApplyClusterVpnNetworkResponse;
|
|
134
|
+
export declare const snapshotGetClusterVpnNetworkRequest: (value: unknown) => TGetClusterVpnNetworkRequest;
|
|
135
|
+
export declare const snapshotGetClusterVpnNetworkResponse: (value: unknown) => IGetClusterVpnNetworkResponse;
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { captureNetwork, failNetwork, networkCanonical, networkCounter, networkEqual, networkId, networkIpv4, networkList, networkNoiseKey, networkPrivatePrefix, networkRecord, networkSafe, networkSorted, requireNetwork } from '../private/networkcontract.js';
|
|
2
|
+
export const clusterVpnNetworkContract = Object.freeze({
|
|
3
|
+
/** The policy domain of a node's control address; the hub relays no grant between control domains. */
|
|
4
|
+
controlPolicyDomainPrefix: 'control:',
|
|
5
|
+
/** The policy domain of one workload lease, named by that lease's digest. */
|
|
6
|
+
workloadPolicyDomainPrefix: 'workload:',
|
|
7
|
+
maximumNodes: 256,
|
|
8
|
+
/** Per node; one workload lease the node's signed projection carries. */
|
|
9
|
+
maximumWorkloadPrefixes: 128,
|
|
10
|
+
maximumGrants: 4096,
|
|
11
|
+
maximumCanonicalBytes: 917_504,
|
|
12
|
+
completeness: 'whole-authority-never-a-patch',
|
|
13
|
+
membership: 'presence-only-an-absent-node-is-withdrawn',
|
|
14
|
+
});
|
|
15
|
+
/**
|
|
16
|
+
* Every reason a relay refuses a pushed network, in the words the refusal leads with.
|
|
17
|
+
*
|
|
18
|
+
* A push is applied to a daemon whose lifetime Cloudly cannot see, so the refusal is the only
|
|
19
|
+
* statement about whether the cluster's hub carries this authority. The relay writes
|
|
20
|
+
* `<name>: <reason>` and Cloudly matches the name, which is why the names are stated here instead
|
|
21
|
+
* of being spelled out on both sides.
|
|
22
|
+
*/
|
|
23
|
+
export const applyClusterVpnNetworkRefusals = Object.freeze([
|
|
24
|
+
/** The network names another authority than the one this cluster's hub is bound to. */
|
|
25
|
+
'vpn-network-authority-foreign',
|
|
26
|
+
/** A revision the hub has already passed, or the same revision with different content. */
|
|
27
|
+
'vpn-network-revision-stale',
|
|
28
|
+
]);
|
|
29
|
+
/**
|
|
30
|
+
* Every reason Cloudly states that a cluster has no managed VPN to push.
|
|
31
|
+
*
|
|
32
|
+
* Both are Cloudly reading its own records: a hub it cannot select, and a grant it cannot compile
|
|
33
|
+
* because hubs are per cluster and a grant whose two ends sit in different clusters has no path
|
|
34
|
+
* through any one of them.
|
|
35
|
+
*/
|
|
36
|
+
export const clusterVpnNetworkSelectionRefusals = Object.freeze([
|
|
37
|
+
/** The cluster's relay registered no hub, so no node of it may be sent to one. */
|
|
38
|
+
'relay-vpn-hub-absent',
|
|
39
|
+
/** The grant's two workloads are placed on two clusters; hub federation is a later lane. */
|
|
40
|
+
'grant-cross-cluster-unsupported',
|
|
41
|
+
]);
|
|
42
|
+
/** The policy domain of one node's control address. One rule, so both sides name it identically. */
|
|
43
|
+
export const clusterVpnControlPolicyDomain = (addressValue) => networkSafe(() => `${clusterVpnNetworkContract.controlPolicyDomainPrefix}${networkIpv4(addressValue)}`);
|
|
44
|
+
/** The policy domain of one workload lease, from that lease's canonical digest. */
|
|
45
|
+
export const clusterVpnWorkloadPolicyDomain = (digestValue) => networkSafe(() => {
|
|
46
|
+
requireNetwork(typeof digestValue === 'string' && /^sha256:[a-f0-9]{64}$/.test(digestValue));
|
|
47
|
+
return `${clusterVpnNetworkContract.workloadPolicyDomainPrefix}${digestValue.slice(7)}`;
|
|
48
|
+
});
|
|
49
|
+
const workloadPolicyDomain = (value) => {
|
|
50
|
+
requireNetwork(typeof value === 'string'
|
|
51
|
+
&& value.startsWith(clusterVpnNetworkContract.workloadPolicyDomainPrefix)
|
|
52
|
+
&& /^[a-f0-9]{64}$/.test(value.slice(clusterVpnNetworkContract.workloadPolicyDomainPrefix.length)));
|
|
53
|
+
return value;
|
|
54
|
+
};
|
|
55
|
+
const prefixOf = (value) => {
|
|
56
|
+
const item = networkRecord(value, ['cidr', 'policyDomain']);
|
|
57
|
+
return { cidr: networkPrivatePrefix(item.cidr), policyDomain: workloadPolicyDomain(item.policyDomain) };
|
|
58
|
+
};
|
|
59
|
+
const nodeOf = (value) => {
|
|
60
|
+
const item = networkRecord(value, ['nodeId', 'publicKey', 'controlAddress', 'expiresAt', 'workloadPrefixes']);
|
|
61
|
+
return { nodeId: networkId(item.nodeId), publicKey: networkNoiseKey(item.publicKey), controlAddress: networkIpv4(item.controlAddress),
|
|
62
|
+
expiresAt: networkCounter(item.expiresAt),
|
|
63
|
+
workloadPrefixes: networkSorted(networkList(item.workloadPrefixes, clusterVpnNetworkContract.maximumWorkloadPrefixes, prefixOf), prefix => prefix.cidr) };
|
|
64
|
+
};
|
|
65
|
+
const grantOf = (value) => {
|
|
66
|
+
const item = networkRecord(value, ['sourceDomain', 'destinationDomain']);
|
|
67
|
+
return { sourceDomain: workloadPolicyDomain(item.sourceDomain), destinationDomain: workloadPolicyDomain(item.destinationDomain) };
|
|
68
|
+
};
|
|
69
|
+
const grantKey = (grant) => `${grant.sourceDomain}\0${grant.destinationDomain}`;
|
|
70
|
+
/**
|
|
71
|
+
* Structural snapshot of a complete cluster network.
|
|
72
|
+
*
|
|
73
|
+
* Every node, prefix and grant is stated once and in canonical order, and every grant names a
|
|
74
|
+
* workload domain this network itself carries, on two different nodes. That last rule is what a
|
|
75
|
+
* per-cluster hub means: a grant whose other end sits on another cluster's hub cannot be expressed
|
|
76
|
+
* here at all, which is why Cloudly refuses it by name while it compiles instead of pushing it.
|
|
77
|
+
*/
|
|
78
|
+
export const snapshotClusterVpnNetwork = (value) => networkSafe(() => {
|
|
79
|
+
const captured = captureNetwork(value);
|
|
80
|
+
requireNetwork(new TextEncoder().encode(networkCanonical(captured)).length <= clusterVpnNetworkContract.maximumCanonicalBytes);
|
|
81
|
+
const item = networkRecord(captured, ['authorityId', 'revision', 'nodes', 'grants']);
|
|
82
|
+
const nodes = networkSorted(networkList(item.nodes, clusterVpnNetworkContract.maximumNodes, nodeOf), node => node.nodeId);
|
|
83
|
+
const grants = networkSorted(networkList(item.grants, clusterVpnNetworkContract.maximumGrants, grantOf), grantKey);
|
|
84
|
+
const domainOwners = new Map();
|
|
85
|
+
const addresses = new Set(), keys = new Set(), cidrs = new Set();
|
|
86
|
+
for (const node of nodes) {
|
|
87
|
+
requireNetwork(!keys.has(node.publicKey) && !addresses.has(node.controlAddress));
|
|
88
|
+
keys.add(node.publicKey);
|
|
89
|
+
addresses.add(node.controlAddress);
|
|
90
|
+
for (const prefix of node.workloadPrefixes) {
|
|
91
|
+
requireNetwork(!cidrs.has(prefix.cidr) && !domainOwners.has(prefix.policyDomain));
|
|
92
|
+
cidrs.add(prefix.cidr);
|
|
93
|
+
domainOwners.set(prefix.policyDomain, node.nodeId);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
for (const grant of grants) {
|
|
97
|
+
const source = domainOwners.get(grant.sourceDomain), destination = domainOwners.get(grant.destinationDomain);
|
|
98
|
+
requireNetwork(source && destination && source !== destination);
|
|
99
|
+
}
|
|
100
|
+
return { authorityId: networkId(item.authorityId), revision: networkCounter(item.revision), nodes, grants };
|
|
101
|
+
});
|
|
102
|
+
/**
|
|
103
|
+
* The pure decision a relay makes about a pushed network against the one its hub holds, or null
|
|
104
|
+
* when the hub holds none — which is every hub that just started, because a daemon restart starts
|
|
105
|
+
* empty. A repeat of the held network is a replay the relay may apply again without effect; a lower
|
|
106
|
+
* revision, or the same revision with different content, is stale and refused by name.
|
|
107
|
+
*/
|
|
108
|
+
export const admitClusterVpnNetwork = (heldValue, nextValue) => networkSafe(() => {
|
|
109
|
+
const next = snapshotClusterVpnNetwork(nextValue);
|
|
110
|
+
if (heldValue === null)
|
|
111
|
+
return { status: 'accepted' };
|
|
112
|
+
const held = snapshotClusterVpnNetwork(heldValue);
|
|
113
|
+
if (held.authorityId !== next.authorityId)
|
|
114
|
+
return { status: 'refused', reason: 'vpn-network-authority-foreign' };
|
|
115
|
+
if (next.revision > held.revision)
|
|
116
|
+
return { status: 'accepted' };
|
|
117
|
+
return networkEqual(held, next) ? { status: 'replay' } : { status: 'refused', reason: 'vpn-network-revision-stale' };
|
|
118
|
+
});
|
|
119
|
+
export const snapshotApplyClusterVpnNetworkRequest = (value) => networkSafe(() => {
|
|
120
|
+
const item = networkRecord(captureNetwork(value), ['network']);
|
|
121
|
+
return { network: snapshotClusterVpnNetwork(item.network) };
|
|
122
|
+
});
|
|
123
|
+
export const snapshotApplyClusterVpnNetworkResponse = (value) => networkSafe(() => {
|
|
124
|
+
const item = networkRecord(captureNetwork(value), ['appliedRevision', 'state']);
|
|
125
|
+
requireNetwork(item.state === 'idle' || item.state === 'applying' || item.state === 'failed');
|
|
126
|
+
return { appliedRevision: item.appliedRevision === null ? null : networkCounter(item.appliedRevision), state: item.state };
|
|
127
|
+
});
|
|
128
|
+
/**
|
|
129
|
+
* Compare the answer with the exact SENT network: a hub that reports itself idle has applied the
|
|
130
|
+
* revision it was sent, and no hub can report having applied a later one than exists.
|
|
131
|
+
*/
|
|
132
|
+
export const bindApplyClusterVpnNetworkResponse = (value, sentRequestValue) => networkSafe(() => {
|
|
133
|
+
const response = snapshotApplyClusterVpnNetworkResponse(value);
|
|
134
|
+
const sent = snapshotApplyClusterVpnNetworkRequest(sentRequestValue);
|
|
135
|
+
requireNetwork(response.appliedRevision === null || response.appliedRevision <= sent.network.revision);
|
|
136
|
+
requireNetwork(response.state !== 'idle' || response.appliedRevision === sent.network.revision);
|
|
137
|
+
return response;
|
|
138
|
+
});
|
|
139
|
+
export const snapshotGetClusterVpnNetworkRequest = (value) => networkSafe(() => {
|
|
140
|
+
networkRecord(captureNetwork(value), []);
|
|
141
|
+
return {};
|
|
142
|
+
});
|
|
143
|
+
export const snapshotGetClusterVpnNetworkResponse = (value) => networkSafe(() => {
|
|
144
|
+
const item = networkRecord(captureNetwork(value), ['network']);
|
|
145
|
+
return { network: item.network === null ? null : snapshotClusterVpnNetwork(item.network) };
|
|
146
|
+
});
|
|
147
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3RlcnZwbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL2RhdGEvY2x1c3RlcnZwbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsY0FBYyxFQUFFLFdBQVcsRUFBRSxnQkFBZ0IsRUFBRSxjQUFjLEVBQUUsWUFBWSxFQUFFLFNBQVMsRUFBRSxXQUFXLEVBQUUsV0FBVyxFQUN2SCxlQUFlLEVBQUUsb0JBQW9CLEVBQUUsYUFBYSxFQUFFLFdBQVcsRUFBRSxhQUFhLEVBQ2hGLGNBQWMsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBZ0R4RCxNQUFNLENBQUMsTUFBTSx5QkFBeUIsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDO0lBQ3JELHNHQUFzRztJQUN0Ryx5QkFBeUIsRUFBRSxVQUFVO0lBQ3JDLDZFQUE2RTtJQUM3RSwwQkFBMEIsRUFBRSxXQUFXO0lBQ3ZDLFlBQVksRUFBRSxHQUFHO0lBQ2pCLHlFQUF5RTtJQUN6RSx1QkFBdUIsRUFBRSxHQUFHO0lBQzVCLGFBQWEsRUFBRSxJQUFJO0lBQ25CLHFCQUFxQixFQUFFLE9BQU87SUFDOUIsWUFBWSxFQUFFLCtCQUErQjtJQUM3QyxVQUFVLEVBQUUsMkNBQTJDO0NBQy9DLENBQUMsQ0FBQztBQUVaOzs7Ozs7O0dBT0c7QUFDSCxNQUFNLENBQUMsTUFBTSw4QkFBOEIsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDO0lBQzFELHVGQUF1RjtJQUN2RiwrQkFBK0I7SUFDL0IsMEZBQTBGO0lBQzFGLDRCQUE0QjtDQUNwQixDQUFDLENBQUM7QUFLWjs7Ozs7O0dBTUc7QUFDSCxNQUFNLENBQUMsTUFBTSxrQ0FBa0MsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDO0lBQzlELGtGQUFrRjtJQUNsRixzQkFBc0I7SUFDdEIsNEZBQTRGO0lBQzVGLGlDQUFpQztDQUN6QixDQUFDLENBQUM7QUFnQ1osb0dBQW9HO0FBQ3BHLE1BQU0sQ0FBQyxNQUFNLDZCQUE2QixHQUFH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
|
package/dist_ts/data/index.d.ts
CHANGED
package/dist_ts/data/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export * from './cloudlyconfig.js';
|
|
2
2
|
export * from './cluster.js';
|
|
3
3
|
export * from './clusterruntime.js';
|
|
4
|
+
export * from './clustervpn.js';
|
|
4
5
|
export * from './clusteringress.js';
|
|
5
6
|
export * from './config.js';
|
|
6
7
|
export * from './corestore.js';
|
|
@@ -58,4 +59,4 @@ export * from './traffic.js';
|
|
|
58
59
|
export * from './user.js';
|
|
59
60
|
export * from './version.js';
|
|
60
61
|
export * from './webpush.js';
|
|
61
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
62
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9kYXRhL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGNBQWMsb0JBQW9CLENBQUM7QUFDbkMsY0FBYyxjQUFjLENBQUM7QUFDN0IsY0FBYyxxQkFBcUIsQ0FBQztBQUNwQyxjQUFjLGlCQUFpQixDQUFDO0FBQ2hDLGNBQWMscUJBQXFCLENBQUM7QUFDcEMsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxnQkFBZ0IsQ0FBQztBQUMvQixjQUFjLGVBQWUsQ0FBQztBQUM5QixjQUFjLHVCQUF1QixDQUFDO0FBQ3RDLGNBQWMsaUJBQWlCLENBQUM7QUFDaEMsY0FBYyx5QkFBeUIsQ0FBQztBQUN4QyxjQUFjLDBCQUEwQixDQUFDO0FBQ3pDLGNBQWMsMEJBQTBCLENBQUM7QUFDekMsY0FBYyxnQkFBZ0IsQ0FBQztBQUMvQixjQUFjLFVBQVUsQ0FBQztBQUN6QixjQUFjLGFBQWEsQ0FBQztBQUM1QixjQUFjLGFBQWEsQ0FBQztBQUM1QixjQUFjLFlBQVksQ0FBQztBQUMzQixjQUFjLHVCQUF1QixDQUFDO0FBQ3RDLGNBQWMsY0FBYyxDQUFDO0FBQzdCLGNBQWMsZ0JBQWdCLENBQUM7QUFDL0IsY0FBYyxZQUFZLENBQUM7QUFDM0IsY0FBYyxxQkFBcUIsQ0FBQztBQUNwQyxjQUFjLHNCQUFzQixDQUFDO0FBQ3JDLGNBQWMsNkJBQTZCLENBQUM7QUFDNUMsY0FBYyxXQUFXLENBQUM7QUFDMUIsY0FBYyxxQkFBcUIsQ0FBQztBQUNwQyxjQUFjLHFCQUFxQixDQUFDO0FBQ3BDLGNBQWMscUJBQXFCLENBQUM7QUFDcEMsY0FBYyx5QkFBeUIsQ0FBQztBQUN4QyxjQUFjLHVCQUF1QixDQUFDO0FBQ3RDLGNBQWMsd0JBQXdCLENBQUM7QUFDdkMsY0FBYyxzQkFBc0IsQ0FBQztBQUNyQyxjQUFjLG1CQUFtQixDQUFDO0FBQ2xDLGNBQWMsa0JBQWtCLENBQUM7QUFDakMsY0FBYyx3QkFBd0IsQ0FBQztBQUV2QyxjQUFjLHdCQUF3QixDQUFDO0FBQ3ZDLGNBQWMscUJBQXFCLENBQUM7QUFDcEMsY0FBYyxxQkFBcUIsQ0FBQztBQUNwQyxjQUFjLGVBQWUsQ0FBQztBQUM5QixjQUFjLHdCQUF3QixDQUFDO0FBQ3ZDLGNBQWMsb0JBQW9CLENBQUM7QUFDbkMsY0FBYyxxQkFBcUIsQ0FBQztBQUNwQyxjQUFjLDZCQUE2QixDQUFDO0FBQzVDLGNBQWMsYUFBYSxDQUFDO0FBQzVCLGNBQWMsZ0JBQWdCLENBQUM7QUFDL0IsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxrQkFBa0IsQ0FBQztBQUNqQyxjQUFjLGVBQWUsQ0FBQztBQUM5QixjQUFjLHNCQUFzQixDQUFDO0FBQ3JDLGNBQWMsY0FBYyxDQUFDO0FBQzdCLGNBQWMsd0JBQXdCLENBQUM7QUFDdkMsY0FBYyxtQkFBbUIsQ0FBQztBQUNsQyxjQUFjLHFCQUFxQixDQUFDO0FBQ3BDLGNBQWMsYUFBYSxDQUFDO0FBQzVCLGNBQWMsb0JBQW9CLENBQUM7QUFDbkMsY0FBYyxjQUFjLENBQUM7QUFDN0IsY0FBYyxXQUFXLENBQUM7QUFDMUIsY0FBYyxjQUFjLENBQUM7QUFDN0IsY0FBYyxjQUFjLENBQUMifQ==
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { IRuntimeNetworkProtectedAuthority } from './networkauthority.js';
|
|
2
|
-
import type { IGetRuntimeManagedVpnCredentialResponse } from './networkcredential.js';
|
|
3
2
|
/**
|
|
4
3
|
* The address space an administrator gives the runtime network, and the one input the protected
|
|
5
4
|
* authority is composed from. Cloudly keeps a single plan; pools and prefixes only grow, and the
|
|
@@ -13,15 +12,34 @@ export interface IRuntimeNetworkAddressPlan {
|
|
|
13
12
|
prefixes: string[];
|
|
14
13
|
pools: IRuntimeNetworkProtectedAuthority['pools'];
|
|
15
14
|
resolvers: IRuntimeNetworkProtectedAuthority['resolvers'];
|
|
16
|
-
/** Without the
|
|
15
|
+
/** Without the cluster hubs, which the composed authority adds from the hubs it is given. */
|
|
17
16
|
platformEndpoints: IRuntimeNetworkProtectedAuthority['platformEndpoints'];
|
|
18
17
|
vpn: {
|
|
19
18
|
/** The private prefix VPN control addresses are allocated from. */
|
|
20
19
|
controlPrefix: string;
|
|
21
|
-
/**
|
|
22
|
-
|
|
20
|
+
/**
|
|
21
|
+
* The protected prefix every cluster hub binds inside.
|
|
22
|
+
*
|
|
23
|
+
* The endpoints themselves are no administrator's input: a cluster's relay reports the one it
|
|
24
|
+
* bound and the composition turns it into platform endpoints, so this prefix is what an
|
|
25
|
+
* administrator reserves for them.
|
|
26
|
+
*/
|
|
27
|
+
hubPrefix: string;
|
|
23
28
|
};
|
|
24
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* One cluster's managed VPN hub, as the cluster's relay bound it.
|
|
32
|
+
*
|
|
33
|
+
* The hub is its cluster's own packet relay, so `clusterId` names both the hub and the authority
|
|
34
|
+
* that may select it, and `address` is an underlay address inside the plan's `vpn.hubPrefix`. A hub
|
|
35
|
+
* offers at least one transport; the port of a transport it did not bind is `null`.
|
|
36
|
+
*/
|
|
37
|
+
export interface IRuntimeNetworkVpnHub {
|
|
38
|
+
clusterId: string;
|
|
39
|
+
address: string;
|
|
40
|
+
quicPort: number | null;
|
|
41
|
+
websocketPort: number | null;
|
|
42
|
+
}
|
|
25
43
|
/** What an administrator writes; Cloudly supplies the id and the revision. */
|
|
26
44
|
export type TRuntimeNetworkAddressPlanWritableData = Omit<IRuntimeNetworkAddressPlan, 'id' | 'revision'>;
|
|
27
45
|
/** What a protection producer fixes around a plan: the authority's identity, revision chain and egress. */
|
|
@@ -54,20 +72,45 @@ export declare const runtimeNetworkAddressPlanContract: Readonly<{
|
|
|
54
72
|
* is stated: the private-range rule already keeps the control prefix at /8 or longer.
|
|
55
73
|
*/
|
|
56
74
|
readonly maximumControlPrefixLength: 30;
|
|
57
|
-
|
|
75
|
+
/**
|
|
76
|
+
* Every transport a hub may offer, in the order a node prefers them.
|
|
77
|
+
*
|
|
78
|
+
* One row states all three facts that belong together: the transport a credential names, the
|
|
79
|
+
* suffix its platform endpoint id carries, and the protocol the endpoint is composed with. A hub
|
|
80
|
+
* that bound both transports therefore contributes exactly two endpoints of one address.
|
|
81
|
+
*/
|
|
82
|
+
readonly hubTransports: readonly (Readonly<{
|
|
83
|
+
transport: "quic";
|
|
84
|
+
endpointSuffix: "quic";
|
|
85
|
+
protocol: "udp";
|
|
86
|
+
}> | Readonly<{
|
|
87
|
+
transport: "websocket";
|
|
88
|
+
endpointSuffix: "ws";
|
|
89
|
+
protocol: "tcp";
|
|
90
|
+
}>)[];
|
|
58
91
|
}>;
|
|
92
|
+
/** How a node reaches its cluster's hub, read off the one table that states the transports. */
|
|
93
|
+
export type TRuntimeNetworkVpnTransport = typeof runtimeNetworkAddressPlanContract.hubTransports[number]['transport'];
|
|
94
|
+
/**
|
|
95
|
+
* The platform endpoints one hub contributes to a protected authority: one per transport it bound,
|
|
96
|
+
* in id order. Every reader derives the same ids from this one function — the composition that seals
|
|
97
|
+
* the authority, and the router selection that names which of them a node may dial.
|
|
98
|
+
*/
|
|
99
|
+
export declare const runtimeNetworkVpnHubEndpoints: (hubValue: unknown) => IRuntimeNetworkProtectedAuthority["platformEndpoints"];
|
|
59
100
|
/**
|
|
60
|
-
* Structural snapshot for exact persistence and for a plan write.
|
|
61
|
-
*
|
|
62
|
-
*
|
|
101
|
+
* Structural snapshot for exact persistence and for a plan write. The plan's own sets pass the
|
|
102
|
+
* protected authority's own validator, so no plan can describe an authority that contract refuses,
|
|
103
|
+
* and both VPN prefixes are reserved inside the protected space the plan states.
|
|
63
104
|
*/
|
|
64
105
|
export declare const snapshotRuntimeNetworkAddressPlan: (value: unknown) => IRuntimeNetworkAddressPlan;
|
|
65
106
|
/**
|
|
66
107
|
* The protected authority a plan describes inside a producer's frame, digest included: the plan's
|
|
67
|
-
* sets
|
|
68
|
-
*
|
|
108
|
+
* sets plus the endpoints of every cluster hub it is given, each bound inside `vpn.hubPrefix`. One
|
|
109
|
+
* cluster contributes one hub, so `hubs` never names a cluster twice. All inputs are read before the
|
|
110
|
+
* digest is computed; an empty `hubs` composes the authority of a runtime network whose clusters
|
|
111
|
+
* have not registered a hub yet.
|
|
69
112
|
*/
|
|
70
|
-
export declare const composeRuntimeNetworkProtectedAuthority: (planValue: unknown, frameValue: unknown) => Promise<IRuntimeNetworkProtectedAuthority>;
|
|
113
|
+
export declare const composeRuntimeNetworkProtectedAuthority: (planValue: unknown, frameValue: unknown, hubsValue: unknown) => Promise<IRuntimeNetworkProtectedAuthority>;
|
|
71
114
|
/**
|
|
72
115
|
* The pure decision for replacing `previousValue`, the stored plan or null, with `nextValue` at the
|
|
73
116
|
* following revision. Leases and the managed VPN outlive a plan revision, so every pool stays exactly
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { computeRuntimeNetworkProtectedAuthorityDigest, snapshotRuntimeNetworkProtectedAuthority } from './networkauthority.js';
|
|
2
|
-
import { captureNetwork, failNetwork, networkContains, networkCounter, networkEqual, networkId, networkIpv4, networkOverlaps, networkPrefixBounds, networkPrivatePrefix, networkRecord, networkSafe, requireNetwork } from '../private/networkcontract.js';
|
|
1
|
+
import { computeRuntimeNetworkProtectedAuthorityDigest, runtimeNetworkAuthorityContract, snapshotRuntimeNetworkProtectedAuthority } from './networkauthority.js';
|
|
2
|
+
import { captureNetwork, failNetwork, networkContains, networkCounter, networkEqual, networkId, networkIpv4, networkList, networkOverlaps, networkPrefix, networkPrefixBounds, networkPrivatePrefix, networkRecord, networkSafe, requireNetwork } from '../private/networkcontract.js';
|
|
3
3
|
export const runtimeNetworkAddressPlanContract = Object.freeze({
|
|
4
4
|
id: 'address-plan',
|
|
5
5
|
/**
|
|
@@ -7,7 +7,42 @@ export const runtimeNetworkAddressPlanContract = Object.freeze({
|
|
|
7
7
|
* is stated: the private-range rule already keeps the control prefix at /8 or longer.
|
|
8
8
|
*/
|
|
9
9
|
maximumControlPrefixLength: 30,
|
|
10
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Every transport a hub may offer, in the order a node prefers them.
|
|
12
|
+
*
|
|
13
|
+
* One row states all three facts that belong together: the transport a credential names, the
|
|
14
|
+
* suffix its platform endpoint id carries, and the protocol the endpoint is composed with. A hub
|
|
15
|
+
* that bound both transports therefore contributes exactly two endpoints of one address.
|
|
16
|
+
*/
|
|
17
|
+
hubTransports: Object.freeze([
|
|
18
|
+
Object.freeze({ transport: 'quic', endpointSuffix: 'quic', protocol: 'udp' }),
|
|
19
|
+
Object.freeze({ transport: 'websocket', endpointSuffix: 'ws', protocol: 'tcp' }),
|
|
20
|
+
]),
|
|
21
|
+
});
|
|
22
|
+
/** The port a hub bound for one transport, or null when it did not bind that transport. */
|
|
23
|
+
const hubPort = (hub, transport) => transport === 'quic' ? hub.quicPort : hub.websocketPort;
|
|
24
|
+
const byEndpointId = (left, right) => left.id < right.id ? -1 : left.id > right.id ? 1 : 0;
|
|
25
|
+
const hubOf = (value) => {
|
|
26
|
+
const item = networkRecord(value, ['clusterId', 'address', 'quicPort', 'websocketPort']);
|
|
27
|
+
const port = (value) => value === null ? null : networkCounter(value, 65535);
|
|
28
|
+
const hub = { clusterId: networkId(item.clusterId), address: networkIpv4(item.address),
|
|
29
|
+
quicPort: port(item.quicPort), websocketPort: port(item.websocketPort) };
|
|
30
|
+
// A hub that bound no transport is not reachable, so it is not a hub a node could be sent to.
|
|
31
|
+
requireNetwork(runtimeNetworkAddressPlanContract.hubTransports.some(row => hubPort(hub, row.transport) !== null));
|
|
32
|
+
return hub;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* The platform endpoints one hub contributes to a protected authority: one per transport it bound,
|
|
36
|
+
* in id order. Every reader derives the same ids from this one function — the composition that seals
|
|
37
|
+
* the authority, and the router selection that names which of them a node may dial.
|
|
38
|
+
*/
|
|
39
|
+
export const runtimeNetworkVpnHubEndpoints = (hubValue) => networkSafe(() => {
|
|
40
|
+
const hub = hubOf(captureNetwork(hubValue));
|
|
41
|
+
return runtimeNetworkAddressPlanContract.hubTransports
|
|
42
|
+
.filter(row => hubPort(hub, row.transport) !== null)
|
|
43
|
+
.map(row => ({ id: `${hub.clusterId}:${row.endpointSuffix}`, address: hub.address,
|
|
44
|
+
protocol: row.protocol, port: hubPort(hub, row.transport) }))
|
|
45
|
+
.sort(byEndpointId);
|
|
11
46
|
});
|
|
12
47
|
/**
|
|
13
48
|
* The structural authority validator reads a frame's shape and nothing else, and a plan fixes none of
|
|
@@ -23,28 +58,32 @@ const unsealedDigest = `sha256:${'0'.repeat(64)}`;
|
|
|
23
58
|
const authorityOf = (sets, frame) => snapshotRuntimeNetworkProtectedAuthority({ id: frame.id,
|
|
24
59
|
generation: frame.generation, controller: frame.controller, previous: frame.previous, egressAuthorities: frame.egressAuthorities,
|
|
25
60
|
prefixes: sets.prefixes, pools: sets.pools, resolvers: sets.resolvers, platformEndpoints: sets.platformEndpoints, digest: unsealedDigest });
|
|
26
|
-
const
|
|
61
|
+
const setsWithHubs = (plan, hubs) => ({
|
|
27
62
|
prefixes: plan.prefixes, pools: plan.pools, resolvers: plan.resolvers,
|
|
28
|
-
platformEndpoints: [...plan.platformEndpoints,
|
|
29
|
-
.sort((left, right) => left.id < right.id ? -1 : left.id > right.id ? 1 : 0),
|
|
63
|
+
platformEndpoints: [...plan.platformEndpoints, ...hubs.flatMap(runtimeNetworkVpnHubEndpoints)].sort(byEndpointId),
|
|
30
64
|
});
|
|
31
65
|
const vpnOf = (value) => {
|
|
32
|
-
const item = networkRecord(value, ['controlPrefix', '
|
|
33
|
-
const relay = networkRecord(item.relay, ['id', 'address', 'port']);
|
|
66
|
+
const item = networkRecord(value, ['controlPrefix', 'hubPrefix']);
|
|
34
67
|
const controlPrefix = networkPrivatePrefix(item.controlPrefix);
|
|
35
68
|
requireNetwork(Number(controlPrefix.split('/')[1]) <= runtimeNetworkAddressPlanContract.maximumControlPrefixLength);
|
|
36
|
-
return { controlPrefix,
|
|
69
|
+
return { controlPrefix, hubPrefix: networkPrefix(item.hubPrefix) };
|
|
37
70
|
};
|
|
38
|
-
/**
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
71
|
+
/**
|
|
72
|
+
* Both VPN prefixes are protected, they hold none of the plan's own pools, resolvers or platform
|
|
73
|
+
* endpoints, and they do not overlap each other: control addresses live inside the tunnel and hub
|
|
74
|
+
* endpoints on the underlay, so one prefix can never contain the other's addresses.
|
|
75
|
+
*/
|
|
76
|
+
const requireVpnProtected = (authority, vpn) => {
|
|
77
|
+
const endpoints = [...authority.resolvers, ...authority.platformEndpoints];
|
|
78
|
+
requireNetwork([vpn.controlPrefix, vpn.hubPrefix].every(prefix => authority.prefixes.some(range => networkContains(range, prefix))
|
|
79
|
+
&& authority.pools.every(pool => !networkOverlaps(pool.prefix, prefix))
|
|
80
|
+
&& endpoints.every(endpoint => !networkContains(prefix, `${endpoint.address}/32`)))
|
|
81
|
+
&& !networkOverlaps(vpn.controlPrefix, vpn.hubPrefix));
|
|
43
82
|
};
|
|
44
83
|
/**
|
|
45
|
-
* Structural snapshot for exact persistence and for a plan write.
|
|
46
|
-
*
|
|
47
|
-
*
|
|
84
|
+
* Structural snapshot for exact persistence and for a plan write. The plan's own sets pass the
|
|
85
|
+
* protected authority's own validator, so no plan can describe an authority that contract refuses,
|
|
86
|
+
* and both VPN prefixes are reserved inside the protected space the plan states.
|
|
48
87
|
*/
|
|
49
88
|
export const snapshotRuntimeNetworkAddressPlan = (value) => networkSafe(() => {
|
|
50
89
|
const item = networkRecord(captureNetwork(value), ['id', 'revision', 'prefixes', 'pools', 'resolvers', 'platformEndpoints', 'vpn']);
|
|
@@ -53,19 +92,24 @@ export const snapshotRuntimeNetworkAddressPlan = (value) => networkSafe(() => {
|
|
|
53
92
|
platformEndpoints: item.platformEndpoints }, validationFrame);
|
|
54
93
|
const plan = { id: runtimeNetworkAddressPlanContract.id, revision: networkCounter(item.revision),
|
|
55
94
|
prefixes: own.prefixes, pools: own.pools, resolvers: own.resolvers, platformEndpoints: own.platformEndpoints, vpn: vpnOf(item.vpn) };
|
|
56
|
-
requireVpnProtected(
|
|
95
|
+
requireVpnProtected(own, plan.vpn);
|
|
57
96
|
return plan;
|
|
58
97
|
});
|
|
59
98
|
/**
|
|
60
99
|
* The protected authority a plan describes inside a producer's frame, digest included: the plan's
|
|
61
|
-
* sets
|
|
62
|
-
*
|
|
100
|
+
* sets plus the endpoints of every cluster hub it is given, each bound inside `vpn.hubPrefix`. One
|
|
101
|
+
* cluster contributes one hub, so `hubs` never names a cluster twice. All inputs are read before the
|
|
102
|
+
* digest is computed; an empty `hubs` composes the authority of a runtime network whose clusters
|
|
103
|
+
* have not registered a hub yet.
|
|
63
104
|
*/
|
|
64
|
-
export const composeRuntimeNetworkProtectedAuthority = async (planValue, frameValue) => {
|
|
105
|
+
export const composeRuntimeNetworkProtectedAuthority = async (planValue, frameValue, hubsValue) => {
|
|
65
106
|
try {
|
|
66
107
|
const plan = snapshotRuntimeNetworkAddressPlan(planValue);
|
|
67
108
|
const frame = networkRecord(captureNetwork(frameValue), ['id', 'generation', 'controller', 'previous', 'egressAuthorities']);
|
|
68
|
-
const
|
|
109
|
+
const hubs = networkList(captureNetwork(hubsValue), runtimeNetworkAuthorityContract.maximumPlatformEndpoints, hubOf);
|
|
110
|
+
requireNetwork(new Set(hubs.map(hub => hub.clusterId)).size === hubs.length
|
|
111
|
+
&& hubs.every(hub => networkContains(plan.vpn.hubPrefix, `${hub.address}/32`)));
|
|
112
|
+
const authority = authorityOf(setsWithHubs(plan, hubs), frame);
|
|
69
113
|
return { ...authority, digest: await computeRuntimeNetworkProtectedAuthorityDigest(authority) };
|
|
70
114
|
}
|
|
71
115
|
catch {
|
|
@@ -111,4 +155,4 @@ export const admitRuntimeNetworkAddressPlanChange = (previousValue, nextValue) =
|
|
|
111
155
|
return { status: 'accepted', removed: { resolverIds: idsOf(removedOrChanged(previous.resolvers, next.resolvers)),
|
|
112
156
|
platformEndpointIds: idsOf(removedOrChanged(previous.platformEndpoints, next.platformEndpoints)) } };
|
|
113
157
|
});
|
|
114
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmV0d29ya2FkZHJlc3NwbGFuLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvZGF0YS9uZXR3b3JrYWRkcmVzc3BsYW4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEsT0FBTyxFQUFFLDZDQUE2QyxFQUFFLHdDQUF3QyxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFFaEksT0FBTyxFQUFFLGNBQWMsRUFBRSxXQUFXLEVBQUUsZUFBZSxFQUFFLGNBQWMsRUFBRSxZQUFZLEVBQUUsU0FBUyxFQUFFLFdBQVcsRUFBRSxlQUFlLEVBQzFILG1CQUFtQixFQUFFLG9CQUFvQixFQUFFLGFBQWEsRUFBRSxXQUFXLEVBQUUsY0FBYyxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFnRC9ILE1BQU0sQ0FBQyxNQUFNLGlDQUFpQyxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUM7SUFDN0QsRUFBRSxFQUFFLGNBQWM7SUFDbEI7OztPQUdHO0lBQ0gsMEJBQTBCLEVBQUUsRUFBRTtJQUM5QixhQUFhLEVBQUUsS0FBSztDQUNaLENBQUMsQ0FBQztBQUVaOzs7O0dBSUc7QUFDSCxNQUFNLGVBQWUsR0FBMkM7SUFDOUQsRUFBRSxFQUFFLGNBQWMsRUFBRSxVQUFVLEVBQUUsQ0FBQyxFQUFFLFVBQVUsRUFBRSxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFFLGNBQWMsRUFBRSxLQUFLLEVBQUUsY0FBYyxFQUFFO0lBQzdHLFFBQVEsRUFBRSxJQUFJLEVBQUUsaUJBQWlCLEVBQUUsQ0FBQyxFQUFFLE1BQU0sRUFBRSxjQUFjLEVBQUUsZ0JBQWdCLEVBQUUsY0FBYyxFQUFFLENBQUM7Q0FDbEcsQ0FBQztBQUNGLE1BQU0sY0FBYyxHQUFHLFVBQVUsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsRUFBbUIsQ0FBQztBQUluRSxzRkFBc0Y7QUFDdEYsTUFBTSxXQUFXLEdBQUcsQ0FDbEIsSUFBMkMsRUFBRSxLQUFvRSxFQUM5RSxFQUFFLENB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
|
|
158
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmV0d29ya2FkZHJlc3NwbGFuLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvZGF0YS9uZXR3b3JrYWRkcmVzc3BsYW4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEsT0FBTyxFQUFFLDZDQUE2QyxFQUFFLCtCQUErQixFQUNyRix3Q0FBd0MsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQzFFLE9BQU8sRUFBRSxjQUFjLEVBQUUsV0FBVyxFQUFFLGVBQWUsRUFBRSxjQUFjLEVBQUUsWUFBWSxFQUFFLFNBQVMsRUFBRSxXQUFXLEVBQUUsV0FBVyxFQUN0SCxlQUFlLEVBQUUsYUFBYSxFQUFFLG1CQUFtQixFQUFFLG9CQUFvQixFQUFFLGFBQWEsRUFBRSxXQUFXLEVBQ3JHLGNBQWMsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBb0V4RCxNQUFNLENBQUMsTUFBTSxpQ0FBaUMsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDO0lBQzdELEVBQUUsRUFBRSxjQUFjO0lBQ2xCOzs7T0FHRztJQUNILDBCQUEwQixFQUFFLEVBQUU7SUFDOUI7Ozs7OztPQU1HO0lBQ0gsYUFBYSxFQUFFLE1BQU0sQ0FBQyxNQUFNLENBQUM7UUFDM0IsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsY0FBYyxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLENBQUM7UUFDN0UsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLFNBQVMsRUFBRSxXQUFXLEVBQUUsY0FBYyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLENBQUM7S0FDakYsQ0FBQztDQUNNLENBQUMsQ0FBQztBQUtaLDJGQUEyRjtBQUMzRixNQUFNLE9BQU8sR0FBRyxDQUFDLEdBQTBCLEVBQUUsU0FBc0MsRUFBaUIsRUFBRSxDQUNwRyxTQUFTLEtBQUssTUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsYUFBYSxDQUFDO0FBRTFELE1BQU0sWUFBWSxHQUFHLENBQTJCLElBQU8sRUFBRSxLQUFRLEVBQVUsRUFBRSxDQUMzRSxJQUFJLENBQUMsRUFBRSxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBRXZELE1BQU0sS0FBSyxHQUFHLENBQUMsS0FBYyxFQUF5QixFQUFFO0lBQ3RELE1BQU0sSUFBSSxHQUFHLGFBQWEsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxXQUFXLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxlQUFlLENBQUMsQ0FBQyxDQUFDO0lBQ3pGLE1BQU0sSUFBSSxHQUFHLENBQUMsS0FBYyxFQUFpQixFQUFFLENBQUMsS0FBSyxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxjQUFjLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ3JHLE1BQU0sR0FBRyxHQUEwQixFQUFFLFNBQVMsRUFBRSxTQUFTLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLE9BQU8sRUFBRSxXQUFXLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQztRQUMzRyxRQUFRLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsRUFBRSxhQUFhLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsRUFBRSxDQUFDO0lBQzNFLDhGQUE4RjtJQUM5RixjQUFjLENBQUMsaUNBQWlDLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLFNBQVMsQ0FBQyxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDbEgsT0FBTyxHQUFHLENBQUM7QUFDYixDQUFDLENBQUM7QUFFRjs7OztHQUlHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sNkJBQTZCLEdBQUcsQ0FBQyxRQUFpQixFQUEwRCxFQUFFLENBQ3pILFdBQVcsQ0FBQyxHQUFHLEVBQUU7SUFDZixNQUFNLEdBQUcsR0FBRyxLQUFLLENBQUMsY0FBYyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7SUFDNUMsT0FBTyxpQ0FBaUMsQ0FBQyxhQUFhO1NBQ25ELE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLFNBQVMsQ0FBQyxLQUFLLElBQUksQ0FBQztTQUNuRCxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLEdBQUcsR0FBRyxDQUFDLFNBQVMsSUFBSSxHQUFHLENBQUMsY0FBYyxFQUFFLEVBQUUsT0FBTyxFQUFFLEdBQUcsQ0FBQyxPQUFPO1FBQy9FLFFBQVEsRUFBRSxHQUFHLENBQUMsUUFBUSxFQUFFLElBQUksRUFBRSxPQUFPLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxTQUFTLENBQVcsRUFBRSxDQUFDLENBQUM7U0FDeEUsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO0FBQ3hCLENBQUMsQ0FBQyxDQUFDO0FBRUw7Ozs7R0FJRztBQUNILE1BQU0sZUFBZSxHQUEyQztJQUM5RCxFQUFFLEVBQUUsY0FBYyxFQUFFLFVBQVUsRUFBRSxDQUFDLEVBQUUsVUFBVSxFQUFFLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUUsY0FBYyxFQUFFLEtBQUssRUFBRSxjQUFjLEVBQUU7SUFDN0csUUFBUSxFQUFFLElBQUksRUFBRSxpQkFBaUIsRUFBRSxDQUFDLEVBQUUsTUFBTSxFQUFFLGNBQWMsRUFBRSxnQkFBZ0IsRUFBRSxjQUFjLEVBQUUsQ0FBQztDQUNsRyxDQUFDO0FBQ0YsTUFBTSxjQUFjLEdBQUcsVUFBVSxHQUFHLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxFQUFtQixDQUFDO0FBSW5FLHNGQUFzRjtBQUN0RixNQUFNLFdBQVcsR0FBRyxDQUNsQixJQUEyQyxFQUFFLEtBQW9FLEVBQzlFLEVBQUUsQ0FBQyx3Q0FBd0MsQ0FBQyxFQUFFLEVBQUUsRUFBRSxLQUFLLENBQUMsRUFBRTtJQUM3RixVQUFVLEVBQUUsS0FBSyxDQUFDLFVBQVUsRUFBRSxVQUFVLEVBQUUsS0FBSyxDQUFDLFVBQVUsRUFBRSxRQUFRLEVBQUUsS0FBSyxDQUFDLFFBQVEsRUFBRSxpQkFBaUIsRUFBRSxLQUFLLENBQUMsaUJBQWlCO0lBQ2hJLFFBQVEsRUFBRSxJQUFJLENBQUMsUUFBUSxFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsS0FBSyxFQUFFLFNBQVMsRUFBRSxJQUFJLENBQUMsU0FBUyxFQUFFLGlCQUFpQixFQUFFLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxNQUFNLEVBQUUsY0FBYyxFQUFFLENBQUMsQ0FBQztBQUU5SSxNQUFNLFlBQVksR0FBRyxDQUFDLElBQWdDLEVBQUUsSUFBNkIsRUFBa0IsRUFBRSxDQUFDLENBQUM7SUFDekcsUUFBUSxFQUFFLElBQUksQ0FBQyxRQUFRLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLLEVBQUUsU0FBUyxFQUFFLElBQUksQ0FBQyxTQUFTO0lBQ3JFLGlCQUFpQixFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLDZCQUE2QixDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDO0NBQ2xILENBQUMsQ0FBQztBQUVILE1BQU0sS0FBSyxHQUFHLENBQUMsS0FBYyxFQUFxQyxFQUFFO0lBQ2xFLE1BQU0sSUFBSSxHQUFHLGFBQWEsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxlQUFlLEVBQUUsV0FBVyxDQUFDLENBQUMsQ0FBQztJQUNsRSxNQUFNLGFBQWEsR0FBRyxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUM7SUFDL0QsY0FBYyxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksaUNBQWlDLENBQUMsMEJBQTBCLENBQUMsQ0FBQztJQUNwSCxPQUFPLEVBQUUsYUFBYSxFQUFFLFNBQVMsRUFBRSxhQUFhLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUM7QUFDckUsQ0FBQyxDQUFDO0FBRUY7Ozs7R0FJRztBQUNILE1BQU0sbUJBQW1CLEdBQUcsQ0FBQyxTQUE0QyxFQUFFLEdBQXNDLEVBQVEsRUFBRTtJQUN6SCxNQUFNLFNBQVMsR0FBRyxDQUFDLEdBQUcsU0FBUyxDQUFDLFNBQVMsRUFBRSxHQUFHLFNBQVMsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0lBQzNFLGNBQWMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxhQUFhLEVBQUUsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUMvRCxTQUFTLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLGVBQWUsQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUM7V0FDM0QsU0FBUyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1dBQ3BFLFNBQVMsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDLGVBQWUsQ0FBQyxNQUFNLEVBQUUsR0FBRyxRQUFRLENBQUMsT0FBTyxLQUFLLENBQUMsQ0FBQyxDQUFDO1dBQ2xGLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxhQUFhLEVBQUUsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7QUFDM0QsQ0FBQyxDQUFDO0FBRUY7Ozs7R0FJRztBQUNILE1BQU0sQ0FBQyxNQUFNLGlDQUFpQyxHQUFHLENBQUMsS0FBYyxFQUE4QixFQUFFLENBQUMsV0FBVyxDQUFDLEdBQUcsRUFBRTtJQUNoSCxNQUFNLElBQUksR0FBRyxhQUFhLENBQUMsY0FBYyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsT0FBTyxFQUFFLFdBQVcsRUFBRSxtQkFBbUIsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDO0lBQ3BJLGNBQWMsQ0FBQyxJQUFJLENBQUMsRUFBRSxLQUFLLGlDQUFpQyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ2pFLE1BQU0sR0FBRyxHQUFHLFdBQVcsQ0FBQyxFQUFFLFFBQVEsRUFBRSxJQUFJLENBQUMsUUFBUSxFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsS0FBSyxFQUFFLFNBQVMsRUFBRSxJQUFJLENBQUMsU0FBUztRQUM3RixpQkFBaUIsRUFBRSxJQUFJLENBQUMsaUJBQWlCLEVBQUUsRUFBRSxlQUFlLENBQUMsQ0FBQztJQUNoRSxNQUFNLElBQUksR0FBK0IsRUFBRSxFQUFFLEVBQUUsaUNBQWlDLENBQUMsRUFBRSxFQUFFLFFBQVEsRUFBRSxjQUFjLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQztRQUMxSCxRQUFRLEVBQUUsR0FBRyxDQUFDLFFBQVEsRUFBRSxLQUFLLEVBQUUsR0FBRyxDQUFDLEtBQUssRUFBRSxTQUFTLEVBQUUsR0FBRyxDQUFDLFNBQVMsRUFBRSxpQkFBaUIsRUFBRSxHQUFHLENBQUMsaUJBQWlCLEVBQUUsR0FBRyxFQUFFLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztJQUN2SSxtQkFBbUIsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ25DLE9BQU8sSUFBSSxDQUFDO0FBQ2QsQ0FBQyxDQUFDLENBQUM7QUFFSDs7Ozs7O0dBTUc7QUFDSCxNQUFNLENBQUMsTUFBTSx1Q0FBdUMsR0FBRyxLQUFLLEVBQzFELFNBQWtCLEVBQUUsVUFBbUIsRUFBRSxTQUFrQixFQUNmLEVBQUU7SUFDOUMsSUFBSSxDQUFDO1FBQ0gsTUFBTSxJQUFJLEdBQUcsaUNBQWlDLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDMUQsTUFBTSxLQUFLLEdBQUcsYUFBYSxDQUFDLGNBQWMsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLFVBQVUsRUFBRSxtQkFBbUIsQ0FBQyxDQUFDLENBQUM7UUFDN0gsTUFBTSxJQUFJLEdBQUcsV0FBVyxDQUFDLGNBQWMsQ0FBQyxTQUFTLENBQUMsRUFBRSwrQkFBK0IsQ0FBQyx3QkFBd0IsRUFBRSxLQUFLLENBQUMsQ0FBQztRQUNySCxjQUFjLENBQUMsSUFBSSxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxJQUFJLENBQUMsTUFBTTtlQUN0RSxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsU0FBUyxFQUFFLEdBQUcsR0FBRyxDQUFDLE9BQU8sS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2xGLE1BQU0sU0FBUyxHQUFHLFdBQVcsQ0FBQyxZQUFZLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQy9ELE9BQU8sRUFBRSxHQUFHLFNBQVMsRUFBRSxNQUFNLEVBQUUsTUFBTSw2Q0FBNkMsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO0lBQ2xHLENBQUM7SUFBQyxNQUFNLENBQUM7UUFBQyxPQUFPLFdBQVcsRUFBRSxDQUFDO0lBQUMsQ0FBQztBQUNuQyxDQUFDLENBQUM7QUFFRiwwR0FBMEc7QUFDMUcsTUFBTSxTQUFTLEdBQUcsQ0FBQyxRQUFrQixFQUFFLE1BQWMsRUFBVyxFQUFFO0lBQ2hFLE1BQU0sQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLEdBQUcsbUJBQW1CLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDbEQsTUFBTSxPQUFPLEdBQUcsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsRUFBRSxTQUFTLEVBQUUsRUFBRTtRQUNqRCxNQUFNLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxHQUFHLG1CQUFtQixDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ25ELE9BQU8sR0FBRyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFFLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQzVFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNOLE9BQU8sT0FBTyxLQUFLLElBQUksR0FBRyxLQUFLLEdBQUcsQ0FBQyxDQUFDO0FBQ3RDLENBQUMsQ0FBQztBQUVGOzs7R0FHRztBQUNILE1BQU0sZ0JBQWdCLEdBQUcsQ0FBSSxRQUFhLEVBQUUsSUFBUyxFQUFPLEVBQUUsQ0FDNUQsUUFBUSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxTQUFTLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBRWxGLE1BQU0sS0FBSyxHQUFHLENBQUMsT0FBOEIsRUFBWSxFQUFFLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUUzRjs7Ozs7O0dBTUc7QUFDSCxNQUFNLENBQUMsTUFBTSxvQ0FBb0MsR0FBRyxDQUFDLGFBQTZCLEVBQUUsU0FBa0IsRUFBb0MsRUFBRSxDQUMxSSxXQUFXLENBQUMsR0FBRyxFQUFFO0lBQ2YsTUFBTSxRQUFRLEdBQUcsYUFBYSxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxpQ0FBaUMsQ0FBQyxhQUFhLENBQUMsQ0FBQztJQUNsRyxNQUFNLElBQUksR0FBRyxpQ0FBaUMsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUMxRCxjQUFjLENBQUMsSUFBSSxDQUFDLFFBQVEsS0FBSyxDQUFDLFFBQVEsRUFBRSxRQUFRLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDaEUsSUFBSSxRQUFRLEtBQUssSUFBSTtRQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBRSxFQUFFLFdBQVcsRUFBRSxFQUFFLEVBQUUsbUJBQW1CLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztJQUM1RyxJQUFJLFlBQVksQ0FBQyxFQUFFLEdBQUcsUUFBUSxFQUFFLFFBQVEsRUFBRSxJQUFJLENBQUMsUUFBUSxFQUFFLEVBQUUsSUFBSSxDQUFDO1FBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxXQUFXLEVBQUUsQ0FBQztJQUNqRyxJQUFJLENBQUMsWUFBWSxDQUFDLFFBQVEsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQztRQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxvQkFBb0IsRUFBRSxDQUFDO0lBQ3RHLElBQUksZ0JBQWdCLENBQUMsUUFBUSxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsTUFBTSxHQUFHLENBQUM7UUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsbUJBQW1CLEVBQUUsQ0FBQztJQUN2SCxJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxNQUFNLENBQUMsQ0FBQztRQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxvQkFBb0IsRUFBRSxDQUFDO0lBQ3JJLE9BQU8sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBRSxFQUFFLFdBQVcsRUFBRSxLQUFLLENBQUMsZ0JBQWdCLENBQUMsUUFBUSxDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7WUFDOUcsbUJBQW1CLEVBQUUsS0FBSyxDQUFDLGdCQUFnQixDQUFDLFFBQVEsQ0FBQyxpQkFBaUIsRUFBRSxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQztBQUN6RyxDQUFDLENBQUMsQ0FBQyJ9
|