@serve.zone/interfaces 31.8.0 → 32.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.smartconfig.json +1 -0
- package/changelog.md +512 -0
- package/dist_ts/00_commitinfo_data.js +3 -3
- package/dist_ts/appstore/types.d.ts +4 -6
- package/dist_ts/appstore/types.js +5 -5
- package/dist_ts/data/backup.d.ts +3 -26
- package/dist_ts/data/cluster.d.ts +36 -11
- package/dist_ts/data/cluster.js +33 -22
- package/dist_ts/data/clusteringress.d.ts +8 -0
- package/dist_ts/data/clusteringress.js +13 -8
- package/dist_ts/data/clusternode.d.ts +121 -74
- package/dist_ts/data/clusternode.js +109 -132
- package/dist_ts/data/clusterruntime.d.ts +39 -0
- package/dist_ts/data/clusterruntime.js +11 -0
- package/dist_ts/data/coremail.d.ts +3 -7
- package/dist_ts/data/coremail.js +2 -2
- package/dist_ts/data/coremail.runtime.d.ts +0 -1
- package/dist_ts/data/coremail.runtime.js +5 -22
- package/dist_ts/data/deploymentadoption.d.ts +0 -2
- package/dist_ts/data/deploymentadoption.js +40 -6
- package/dist_ts/data/deploymentoperation.js +16 -3
- package/dist_ts/data/deploymentpreflight.d.ts +0 -2
- package/dist_ts/data/deploymentpreflight.js +1 -1
- package/dist_ts/data/immutableimage.d.ts +38 -21
- package/dist_ts/data/immutableimage.js +45 -5
- package/dist_ts/data/index.d.ts +5 -1
- package/dist_ts/data/index.js +5 -1
- package/dist_ts/data/isolatedrestore.d.ts +139 -21
- package/dist_ts/data/isolatedrestore.golden.d.ts +0 -1
- package/dist_ts/data/isolatedrestore.golden.js +6 -9
- package/dist_ts/data/isolatedrestore.js +176 -40
- package/dist_ts/data/mail.d.ts +1 -1
- package/dist_ts/data/networkaddressplan.d.ts +78 -0
- package/dist_ts/data/networkaddressplan.js +114 -0
- package/dist_ts/data/networkauthority.d.ts +20 -22
- package/dist_ts/data/networkauthority.js +29 -43
- package/dist_ts/data/networkcredential.d.ts +10 -10
- package/dist_ts/data/networkcredential.js +16 -16
- package/dist_ts/data/networkdelivery.d.ts +18 -18
- package/dist_ts/data/networkdelivery.js +16 -16
- package/dist_ts/data/networklease.d.ts +18 -7
- package/dist_ts/data/networklease.js +29 -7
- package/dist_ts/data/networknode.d.ts +37 -0
- package/dist_ts/data/networknode.js +6 -0
- package/dist_ts/data/networkprojection.d.ts +59 -60
- package/dist_ts/data/networkprojection.js +53 -57
- package/dist_ts/data/networkprotection.d.ts +27 -28
- package/dist_ts/data/networkprotection.js +36 -36
- package/dist_ts/data/networkrouter.d.ts +11 -11
- package/dist_ts/data/networkrouter.js +1 -1
- package/dist_ts/data/networksigning.d.ts +16 -18
- package/dist_ts/data/networksigning.js +20 -21
- package/dist_ts/data/nodecredential.d.ts +4 -6
- package/dist_ts/data/nodeenrollment.d.ts +35 -40
- package/dist_ts/data/nodeenrollment.js +57 -72
- package/dist_ts/data/privatenetwork.d.ts +21 -24
- package/dist_ts/data/privatenetwork.js +39 -54
- package/dist_ts/data/runtimeassignment.d.ts +50 -34
- package/dist_ts/data/runtimeassignment.js +79 -45
- package/dist_ts/data/runtimeconfig.d.ts +21 -22
- package/dist_ts/data/runtimeconfig.js +37 -100
- package/dist_ts/data/runtimesession.d.ts +100 -62
- package/dist_ts/data/runtimesession.js +98 -79
- package/dist_ts/data/runtimeterminalreceipt.d.ts +28 -29
- package/dist_ts/data/runtimeterminalreceipt.js +42 -42
- package/dist_ts/data/secret.d.ts +18 -25
- package/dist_ts/data/secret.js +12 -52
- package/dist_ts/data/servicecredential.d.ts +14 -16
- package/dist_ts/data/servicecredential.js +17 -28
- package/dist_ts/data/serviceruntime.d.ts +128 -0
- package/dist_ts/data/serviceruntime.js +92 -0
- package/dist_ts/data/sparknodereport.d.ts +27 -14
- package/dist_ts/data/sparknodereport.js +35 -28
- package/dist_ts/data/webpush.d.ts +0 -1
- package/dist_ts/index.d.ts +2 -1
- package/dist_ts/index.js +3 -2
- package/dist_ts/platform/objectstorageretention.d.ts +21 -24
- package/dist_ts/platform/objectstorageretention.js +6 -18
- package/dist_ts/platform/storage.d.ts +1 -3
- package/dist_ts/platform/storagemigration.d.ts +0 -7
- package/dist_ts/platform/storagemigration.golden.d.ts +0 -1
- package/dist_ts/platform/storagemigration.golden.js +8 -12
- package/dist_ts/platform/storagemigration.js +6 -51
- package/dist_ts/platform/types.d.ts +2 -2
- package/dist_ts/private/canonicaljson.d.ts +9 -1
- package/dist_ts/private/canonicaljson.js +14 -2
- package/dist_ts/private/dataproperties.d.ts +62 -0
- package/dist_ts/private/dataproperties.js +117 -0
- package/dist_ts/private/networkcontract.d.ts +14 -10
- package/dist_ts/private/networkcontract.js +15 -1
- package/dist_ts/private/producercontract.d.ts +11 -0
- package/dist_ts/private/producercontract.js +21 -0
- package/dist_ts/private/releaseversion.d.ts +37 -0
- package/dist_ts/private/releaseversion.js +48 -0
- package/dist_ts/private/runtimepolicy.d.ts +31 -0
- package/dist_ts/private/runtimepolicy.js +90 -0
- package/dist_ts/private/tokenlist.d.ts +9 -0
- package/dist_ts/private/tokenlist.js +23 -0
- package/dist_ts/protocol.d.ts +137 -0
- package/dist_ts/protocol.js +255 -0
- package/dist_ts/requests/admin.d.ts +8 -8
- package/dist_ts/requests/backup.d.ts +102 -112
- package/dist_ts/requests/cluster.d.ts +47 -10
- package/dist_ts/requests/cluster.js +1 -1
- package/dist_ts/requests/clusteringress.d.ts +9 -0
- package/dist_ts/requests/clusteringress.js +1 -1
- package/dist_ts/requests/config.d.ts +3 -3
- package/dist_ts/requests/corestore.d.ts +0 -3
- package/dist_ts/requests/corestore.js +5 -9
- package/dist_ts/requests/network.d.ts +87 -31
- package/dist_ts/requests/node.d.ts +15 -28
- package/dist_ts/requests/pallet.d.ts +13 -13
- package/dist_ts/requests/runtimesession.d.ts +53 -41
- package/dist_ts/requests/secret.d.ts +4 -5
- package/dist_ts/requests/secret.js +1 -5
- package/dist_ts/requests/service.d.ts +60 -0
- package/dist_ts/runtime.corestore.d.ts +56 -74
- package/dist_ts/runtime.corestore.databaseexportpackage.d.ts +30 -36
- package/dist_ts/runtime.corestore.databaseexportpackage.golden.d.ts +11 -12
- package/dist_ts/runtime.corestore.databaseexportpackage.golden.js +54 -71
- package/dist_ts/runtime.corestore.databaseexportpackage.js +9 -25
- package/dist_ts/runtime.corestore.js +35 -135
- package/dist_ts/runtime.corestore.relay.js +2 -7
- package/dist_ts/runtime.d.ts +38 -48
- package/dist_ts/runtime.js +20 -77
- package/dist_ts/runtime.networkprojection.d.ts +4 -4
- package/dist_ts/runtime.networkprojection.js +18 -18
- package/dist_ts/runtime.workloadinit.d.ts +23 -24
- package/dist_ts/runtime.workloadinit.js +6 -13
- package/package.json +2 -2
- package/readme.md +540 -269
- package/ts/00_commitinfo_data.ts +3 -3
- package/ts/appstore/types.ts +4 -6
- package/ts/data/backup.ts +3 -38
- package/ts/data/cluster.ts +51 -34
- package/ts/data/clusteringress.ts +12 -12
- package/ts/data/clusternode.ts +204 -232
- package/ts/data/clusterruntime.ts +45 -0
- package/ts/data/coremail.runtime.ts +4 -21
- package/ts/data/coremail.ts +3 -7
- package/ts/data/deploymentadoption.ts +46 -4
- package/ts/data/deploymentoperation.ts +16 -1
- package/ts/data/deploymentpreflight.ts +0 -2
- package/ts/data/immutableimage.ts +71 -24
- package/ts/data/index.ts +5 -1
- package/ts/data/isolatedrestore.golden.ts +5 -9
- package/ts/data/isolatedrestore.ts +339 -54
- package/ts/data/mail.ts +1 -1
- package/ts/data/networkaddressplan.ts +175 -0
- package/ts/data/networkauthority.ts +45 -61
- package/ts/data/networkcredential.ts +24 -24
- package/ts/data/networkdelivery.ts +27 -27
- package/ts/data/networklease.ts +40 -13
- package/ts/data/networknode.ts +37 -0
- package/ts/data/networkprojection.ts +119 -124
- package/ts/data/networkprotection.ts +54 -55
- package/ts/data/networkrouter.ts +14 -14
- package/ts/data/networksigning.ts +29 -32
- package/ts/data/nodecredential.ts +4 -6
- package/ts/data/nodeenrollment.ts +96 -114
- package/ts/data/privatenetwork.ts +58 -74
- package/ts/data/runtimeassignment.ts +143 -94
- package/ts/data/runtimeconfig.ts +62 -122
- package/ts/data/runtimesession.ts +185 -138
- package/ts/data/runtimeterminalreceipt.ts +72 -73
- package/ts/data/secret.ts +28 -76
- package/ts/data/servicecredential.ts +33 -43
- package/ts/data/serviceruntime.ts +208 -0
- package/ts/data/sparknodereport.ts +48 -36
- package/ts/data/webpush.ts +0 -1
- package/ts/index.ts +2 -0
- package/ts/platform/objectstorageretention.ts +36 -55
- package/ts/platform/storage.ts +1 -3
- package/ts/platform/storagemigration.golden.ts +7 -11
- package/ts/platform/storagemigration.ts +5 -55
- package/ts/platform/types.ts +2 -2
- package/ts/private/canonicaljson.ts +13 -1
- package/ts/private/dataproperties.ts +139 -0
- package/ts/private/networkcontract.ts +23 -9
- package/ts/private/producercontract.ts +19 -0
- package/ts/private/releaseversion.ts +70 -0
- package/ts/private/runtimepolicy.ts +105 -0
- package/ts/private/tokenlist.ts +30 -0
- package/ts/protocol.ts +364 -0
- package/ts/requests/admin.ts +11 -11
- package/ts/requests/backup.ts +112 -117
- package/ts/requests/cluster.ts +58 -13
- package/ts/requests/clusteringress.ts +9 -0
- package/ts/requests/config.ts +3 -3
- package/ts/requests/corestore.ts +4 -16
- package/ts/requests/network.ts +90 -41
- package/ts/requests/node.ts +21 -38
- package/ts/requests/pallet.ts +17 -17
- package/ts/requests/runtimesession.ts +63 -51
- package/ts/requests/secret.ts +5 -10
- package/ts/requests/service.ts +81 -0
- package/ts/runtime.corestore.databaseexportpackage.golden.ts +77 -95
- package/ts/runtime.corestore.databaseexportpackage.ts +51 -73
- package/ts/runtime.corestore.relay.ts +1 -10
- package/ts/runtime.corestore.ts +118 -268
- package/ts/runtime.networkprojection.ts +30 -30
- package/ts/runtime.ts +83 -158
- package/ts/runtime.workloadinit.ts +36 -48
- package/dist_ts/runtime.cloudlylegacydeploymentsettlement.d.ts +0 -902
- package/dist_ts/runtime.cloudlylegacydeploymentsettlement.golden.d.ts +0 -35
- package/dist_ts/runtime.cloudlylegacydeploymentsettlement.golden.js +0 -315
- package/dist_ts/runtime.cloudlylegacydeploymentsettlement.js +0 -3315
- package/dist_ts/runtime.cloudlylegacydeploymentsettlement.offlineexport.d.ts +0 -291
- package/dist_ts/runtime.cloudlylegacydeploymentsettlement.offlineexport.golden.d.ts +0 -30
- package/dist_ts/runtime.cloudlylegacydeploymentsettlement.offlineexport.golden.js +0 -408
- package/dist_ts/runtime.cloudlylegacydeploymentsettlement.offlineexport.js +0 -1126
- package/ts/runtime.cloudlylegacydeploymentsettlement.golden.ts +0 -421
- package/ts/runtime.cloudlylegacydeploymentsettlement.offlineexport.golden.ts +0 -510
- package/ts/runtime.cloudlylegacydeploymentsettlement.offlineexport.ts +0 -2470
- package/ts/runtime.cloudlylegacydeploymentsettlement.ts +0 -6630
package/ts/00_commitinfo_data.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* autocreated commitinfo by @push.rocks/commitinfo
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
|
-
name:
|
|
6
|
-
version:
|
|
7
|
-
description:
|
|
5
|
+
name: "@serve.zone/interfaces",
|
|
6
|
+
version: "32.0.0",
|
|
7
|
+
description: "Shared TypeScript interfaces and TypedRequest contracts for the serve.zone ecosystem."
|
|
8
8
|
}
|
package/ts/appstore/types.ts
CHANGED
|
@@ -57,10 +57,10 @@ export type TAppStoreTrackingMode = 'tag' | 'digest';
|
|
|
57
57
|
export type TAppStoreUpgradeStrategy = 'semver' | 'branch' | 'dockerDigest';
|
|
58
58
|
|
|
59
59
|
export const appStoreStorageFeatureIds = {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
60
|
+
bindings: 'storage.bindings',
|
|
61
|
+
filesystem: 'storage.filesystem',
|
|
62
|
+
objectStorage: 'storage.object-storage',
|
|
63
|
+
objectStorageFile: 'storage.object-storage.file',
|
|
64
64
|
} as const;
|
|
65
65
|
|
|
66
66
|
export type TAppStoreStorageFeatureId =
|
|
@@ -333,7 +333,6 @@ export interface IAppStoreApp {
|
|
|
333
333
|
}
|
|
334
334
|
|
|
335
335
|
export interface IAppStoreIndex {
|
|
336
|
-
schemaVersion: number;
|
|
337
336
|
updatedAt: string;
|
|
338
337
|
resolvedAt?: string;
|
|
339
338
|
apps: IAppStoreApp[];
|
|
@@ -423,7 +422,6 @@ export interface IServezoneAppStoreVersion extends IAppStoreVersionConfig {
|
|
|
423
422
|
}
|
|
424
423
|
|
|
425
424
|
export interface IServezoneAppStoreManifest {
|
|
426
|
-
schemaVersion: number;
|
|
427
425
|
app: IServezoneAppStoreAppInfo;
|
|
428
426
|
latestVersion?: string;
|
|
429
427
|
channel?: string;
|
package/ts/data/backup.ts
CHANGED
|
@@ -56,7 +56,6 @@ export interface IBackupArchiveObject {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
export interface IBackupArchiveManifest {
|
|
59
|
-
version: 1;
|
|
60
59
|
backupId: string;
|
|
61
60
|
createdAt: number;
|
|
62
61
|
objects: IBackupArchiveObject[];
|
|
@@ -362,43 +361,6 @@ export interface IIsolatedRestoreSourceBackupHold {
|
|
|
362
361
|
releaseReason?: string;
|
|
363
362
|
}
|
|
364
363
|
|
|
365
|
-
export type TIsolatedRestoreNodeStatus =
|
|
366
|
-
| 'preparing'
|
|
367
|
-
| 'prepared'
|
|
368
|
-
| 'staging'
|
|
369
|
-
| 'restoring'
|
|
370
|
-
| 'verifying'
|
|
371
|
-
| 'ready'
|
|
372
|
-
| 'failed'
|
|
373
|
-
| 'cleaning'
|
|
374
|
-
| 'cleaned'
|
|
375
|
-
| 'cleanup-failed';
|
|
376
|
-
|
|
377
|
-
/**
|
|
378
|
-
* Data-plane state for one exact cluster/node/restore routing key. `revision`
|
|
379
|
-
* advances after every mutation and is the compare-and-swap value used by
|
|
380
|
-
* prepare, execute, and cleanup requests.
|
|
381
|
-
*/
|
|
382
|
-
export interface IIsolatedRestoreNodeState {
|
|
383
|
-
restoreId: string;
|
|
384
|
-
clusterId: string;
|
|
385
|
-
targetNodeName: string;
|
|
386
|
-
sourceBackupId: string;
|
|
387
|
-
sourceServiceId: string;
|
|
388
|
-
scratchNamespaceId: string;
|
|
389
|
-
stagingArchiveId: string;
|
|
390
|
-
revision: number;
|
|
391
|
-
status: TIsolatedRestoreNodeStatus;
|
|
392
|
-
completedResourceMappingIds: string[];
|
|
393
|
-
verification: IIsolatedRestoreVerification;
|
|
394
|
-
cleanup?: IIsolatedRestoreCleanupProgress;
|
|
395
|
-
preparedAt?: number;
|
|
396
|
-
readyAt?: number;
|
|
397
|
-
updatedAt: number;
|
|
398
|
-
lastErrorCode?: string;
|
|
399
|
-
lastErrorMessage?: string;
|
|
400
|
-
}
|
|
401
|
-
|
|
402
364
|
/**
|
|
403
365
|
* Durable control-plane record for a restore into a generated data-plane
|
|
404
366
|
* scratch namespace. The namespace is not an IService and carries no image,
|
|
@@ -423,6 +385,9 @@ export interface IIsolatedRestoreRecord {
|
|
|
423
385
|
scratchNamespaceId: string;
|
|
424
386
|
/** Server-generated archive namespace, distinct from sourceBackupId. */
|
|
425
387
|
stagingArchiveId: string;
|
|
388
|
+
/** The cluster node every control call is dispatched to, as the cluster document names it. */
|
|
389
|
+
targetNodeId: string;
|
|
390
|
+
/** The node name the signed restore grant authorizes, read from that node's cluster document. */
|
|
426
391
|
targetNodeName: string;
|
|
427
392
|
purpose: string;
|
|
428
393
|
requestedBy: IIsolatedRestoreActor;
|
package/ts/data/cluster.ts
CHANGED
|
@@ -3,6 +3,8 @@ import * as plugins from '../plugins.js';
|
|
|
3
3
|
import { type IDockerRegistryInfo } from '../data/docker.js';
|
|
4
4
|
import type { IClusterNode } from './clusternode.js';
|
|
5
5
|
import { isPlausibleUnicastIpv4 } from '../private/ipv4.js';
|
|
6
|
+
import { validateProtocolOfferOn, type IProtocolOffer } from '../protocol.js';
|
|
7
|
+
import { hasExactKeys } from '../private/dataproperties.js';
|
|
6
8
|
|
|
7
9
|
export interface ICluster {
|
|
8
10
|
id: string;
|
|
@@ -43,7 +45,7 @@ export interface ICluster {
|
|
|
43
45
|
* How cluster-side components reach this cluster's relay. Absent on a
|
|
44
46
|
* cluster whose nodes still target Cloudly directly.
|
|
45
47
|
*/
|
|
46
|
-
relay?:
|
|
48
|
+
relay?: IClusterRelay;
|
|
47
49
|
};
|
|
48
50
|
}
|
|
49
51
|
|
|
@@ -56,15 +58,14 @@ export interface ICluster {
|
|
|
56
58
|
* `new URL(origin).origin === origin`. A default `:443` is therefore written
|
|
57
59
|
* implicitly, because `URL` drops it from the origin it computes.
|
|
58
60
|
*/
|
|
59
|
-
export interface
|
|
60
|
-
schemaVersion: 1;
|
|
61
|
+
export interface IClusterRelay {
|
|
61
62
|
origin: string;
|
|
62
63
|
}
|
|
63
64
|
|
|
64
65
|
/**
|
|
65
66
|
* What a cluster relay tells Cloudly about itself once its socket is authenticated.
|
|
66
67
|
*
|
|
67
|
-
* The relay sends this after `
|
|
68
|
+
* The relay sends this after `registerCloudlyClientSession`, so the cluster it registers for
|
|
68
69
|
* is the one its verified machine identity names and is never a field here. `relay.nodeId` is
|
|
69
70
|
* the cluster node the relay process runs on, `listenAddress` and `listenPort` are the exact
|
|
70
71
|
* endpoint it bound for the Pallet nodes of its cluster, and `registrationSequence` counts up
|
|
@@ -72,8 +73,7 @@ export interface IClusterRelayV1 {
|
|
|
72
73
|
* peer, where it must strictly increase, a refused registration does not consume it, and a
|
|
73
74
|
* repeat of an accepted sequence is refused; across peers Cloudly's own acceptance time orders.
|
|
74
75
|
*/
|
|
75
|
-
export interface
|
|
76
|
-
schemaVersion: 1;
|
|
76
|
+
export interface IRegisterClusterRelayRequest {
|
|
77
77
|
relay: {
|
|
78
78
|
/** The relay build that is registering; a bounded label for operators and logs. */
|
|
79
79
|
version: string;
|
|
@@ -91,6 +91,12 @@ export interface IClusterRelayRegistrationV1 {
|
|
|
91
91
|
};
|
|
92
92
|
/** Monotonic within one relay process; it restarts at 0 when the process restarts. */
|
|
93
93
|
registrationSequence: number;
|
|
94
|
+
/**
|
|
95
|
+
* Read and negotiated before the registration is validated; see
|
|
96
|
+
* `validateRegisterClusterRelayRequest`. `relay.version` is the relay build and stays a
|
|
97
|
+
* different fact from `protocol.interfacesVersion`, which is the contract it speaks.
|
|
98
|
+
*/
|
|
99
|
+
protocol: IProtocolOffer;
|
|
94
100
|
}
|
|
95
101
|
|
|
96
102
|
/**
|
|
@@ -101,11 +107,34 @@ export interface IClusterRelayRegistrationV1 {
|
|
|
101
107
|
* registration always carries one: a cluster whose relay nobody enabled has no origin to
|
|
102
108
|
* register into, and that registration is refused by name instead of answered.
|
|
103
109
|
*/
|
|
104
|
-
export interface
|
|
110
|
+
export interface IRegisterClusterRelayResponse {
|
|
105
111
|
accepted: true;
|
|
106
112
|
origin: string;
|
|
113
|
+
/** Cloudly's own offer, so an accepted relay judges the session it just registered into. */
|
|
114
|
+
protocol: IProtocolOffer;
|
|
107
115
|
}
|
|
108
116
|
|
|
117
|
+
/**
|
|
118
|
+
* The registration refusals that end a relay's custody of its cluster.
|
|
119
|
+
*
|
|
120
|
+
* Each of them is Cloudly reading its own records and stating that this relay is not the one it
|
|
121
|
+
* dispatches to, so the answer outlives the socket it arrived on and a relay that hears one drops
|
|
122
|
+
* what it holds for its nodes instead of waiting. Cloudly's other answers — a refusal that only
|
|
123
|
+
* says it could not verify the relay, a malformed or conflicting registration, an internal error —
|
|
124
|
+
* state nothing about dispatch and are not listed here.
|
|
125
|
+
*/
|
|
126
|
+
export const clusterRelayUndispatchedRefusals = Object.freeze([
|
|
127
|
+
/** The cluster has no relay enabled, so there is no registration to accept. */
|
|
128
|
+
'relay-cluster-not-enabled',
|
|
129
|
+
/** The node the relay names belongs to another cluster than the one its identity names. */
|
|
130
|
+
'relay-node-foreign',
|
|
131
|
+
/** A registration of this relay identity at the same or a higher sequence is already recorded. */
|
|
132
|
+
'relay-sequence-not-advancing',
|
|
133
|
+
] as const);
|
|
134
|
+
|
|
135
|
+
/** One of the reasons Cloudly states that it does not dispatch to a relay. */
|
|
136
|
+
export type TClusterRelayUndispatchedRefusal = typeof clusterRelayUndispatchedRefusals[number];
|
|
137
|
+
|
|
109
138
|
const maximumClusterRelayOriginLength = 2048;
|
|
110
139
|
const maximumClusterRelayVersionLength = 64;
|
|
111
140
|
|
|
@@ -117,16 +146,6 @@ const isRecord = (valueArg: unknown): valueArg is Record<string, unknown> => (
|
|
|
117
146
|
|| Object.getPrototypeOf(valueArg) === null)
|
|
118
147
|
);
|
|
119
148
|
|
|
120
|
-
const hasExactKeys = (
|
|
121
|
-
valueArg: Record<string, unknown>,
|
|
122
|
-
keysArg: readonly string[],
|
|
123
|
-
): boolean => {
|
|
124
|
-
const actualKeys = Object.keys(valueArg).sort();
|
|
125
|
-
const expectedKeys = [...keysArg].sort();
|
|
126
|
-
return actualKeys.length === expectedKeys.length
|
|
127
|
-
&& actualKeys.every((keyArg, indexArg) => keyArg === expectedKeys[indexArg]);
|
|
128
|
-
};
|
|
129
|
-
|
|
130
149
|
const validateClusterRelayOrigin = (valueArg: unknown, pathArg: string): string[] => {
|
|
131
150
|
if (typeof valueArg !== 'string'
|
|
132
151
|
|| valueArg.length === 0
|
|
@@ -162,19 +181,14 @@ const validateClusterRelayOrigin = (valueArg: unknown, pathArg: string): string[
|
|
|
162
181
|
* identity store: it is the transport authority the node's runtime session
|
|
163
182
|
* registers over.
|
|
164
183
|
*/
|
|
165
|
-
export const
|
|
184
|
+
export const validateClusterRelay = (
|
|
166
185
|
valueArg: unknown,
|
|
167
186
|
pathArg = 'cluster relay',
|
|
168
187
|
): string[] => {
|
|
169
|
-
if (!isRecord(valueArg) || !hasExactKeys(valueArg, ['
|
|
188
|
+
if (!isRecord(valueArg) || !hasExactKeys(valueArg, ['origin'])) {
|
|
170
189
|
return [`${pathArg} must use its exact schema`];
|
|
171
190
|
}
|
|
172
|
-
|
|
173
|
-
if (valueArg.schemaVersion !== 1) {
|
|
174
|
-
errors.push(`${pathArg} schemaVersion must be 1`);
|
|
175
|
-
}
|
|
176
|
-
errors.push(...validateClusterRelayOrigin(valueArg.origin, `${pathArg} origin`));
|
|
177
|
-
return errors;
|
|
191
|
+
return validateClusterRelayOrigin(valueArg.origin, `${pathArg} origin`);
|
|
178
192
|
};
|
|
179
193
|
|
|
180
194
|
const validateClusterRelayVersion = (valueArg: unknown, pathArg: string): string[] => (
|
|
@@ -242,19 +256,22 @@ const validateClusterRelayEndpoint = (valueArg: unknown, pathArg: string): strin
|
|
|
242
256
|
* stored one is Cloudly's decision too. `registrationSequence` restarts with the relay process,
|
|
243
257
|
* so it orders registrations only within one live peer. A registration that passes here has
|
|
244
258
|
* claimed nothing.
|
|
259
|
+
*
|
|
260
|
+
* Cloudly judges the body in the one server order `protocol.readProtocolOffer` states, against its
|
|
261
|
+
* `clusterRelay` offer, and reaches this check only afterwards — so a refused relay never consumes
|
|
262
|
+
* a sequence. The `validateProtocolOfferOn` call below is therefore the self-consistency check of
|
|
263
|
+
* a body that was already negotiated, never the negotiation step; it reads the offer the same way,
|
|
264
|
+
* as data, so naming reasons never runs an accessor a peer put on the body.
|
|
245
265
|
*/
|
|
246
|
-
export const
|
|
266
|
+
export const validateRegisterClusterRelayRequest = (
|
|
247
267
|
valueArg: unknown,
|
|
248
268
|
pathArg = 'cluster relay registration',
|
|
249
269
|
): string[] => {
|
|
250
270
|
if (!isRecord(valueArg)
|
|
251
|
-
|| !hasExactKeys(valueArg, ['
|
|
271
|
+
|| !hasExactKeys(valueArg, ['relay', 'registrationSequence', 'protocol'])) {
|
|
252
272
|
return [`${pathArg} must use its exact schema`];
|
|
253
273
|
}
|
|
254
|
-
const errors: string[] =
|
|
255
|
-
if (valueArg.schemaVersion !== 1) {
|
|
256
|
-
errors.push(`${pathArg} schemaVersion must be 1`);
|
|
257
|
-
}
|
|
274
|
+
const errors: string[] = validateProtocolOfferOn(valueArg, `${pathArg} protocol`);
|
|
258
275
|
errors.push(...validateClusterRelayEndpoint(valueArg.relay, `${pathArg} relay`));
|
|
259
276
|
errors.push(...validateClusterRelayNonNegativeInteger(valueArg.registrationSequence,
|
|
260
277
|
`${pathArg} registrationSequence`));
|
|
@@ -264,7 +281,7 @@ export const validateClusterRelayRegistrationV1 = (
|
|
|
264
281
|
/**
|
|
265
282
|
* One cluster's relay as Cloudly serves it to an administrator.
|
|
266
283
|
*
|
|
267
|
-
* This is the read shape, not the registration a relay sends: `
|
|
284
|
+
* This is the read shape, not the registration a relay sends: `IRegisterClusterRelayRequest` is
|
|
268
285
|
* what the relay puts on the wire, and this is what Cloudly answers with after it accepted one.
|
|
269
286
|
* `clusterId` names the cluster the relay serves, and `acceptedAt` is Cloudly's own acceptance
|
|
270
287
|
* time, which is what orders two registrations of one cluster.
|
|
@@ -321,8 +338,8 @@ export const validateClusterRelayRegistration = (
|
|
|
321
338
|
* identically; an origin that names an address literal instead of a domain
|
|
322
339
|
* therefore has no issuable certificate.
|
|
323
340
|
*/
|
|
324
|
-
export const clusterRelayCertificateDomainName = (relayArg:
|
|
325
|
-
const errors =
|
|
341
|
+
export const clusterRelayCertificateDomainName = (relayArg: IClusterRelay): string => {
|
|
342
|
+
const errors = validateClusterRelay(relayArg);
|
|
326
343
|
if (errors.length > 0) {
|
|
327
344
|
throw new Error(errors[0]);
|
|
328
345
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { isPlausibleUnicastIpv4 } from '../private/ipv4.js';
|
|
2
2
|
import { isUtcCalendarDay } from '../private/utccalendarday.js';
|
|
3
|
+
import { validateProtocolOfferOn } from '../protocol.js';
|
|
4
|
+
import { hasExactKeys } from '../private/dataproperties.js';
|
|
3
5
|
|
|
4
6
|
/**
|
|
5
7
|
* The cluster ingress contracts.
|
|
@@ -119,16 +121,6 @@ const isRecord = (valueArg: unknown): valueArg is Record<string, unknown> => (
|
|
|
119
121
|
|| Object.getPrototypeOf(valueArg) === null)
|
|
120
122
|
);
|
|
121
123
|
|
|
122
|
-
const hasExactKeys = (
|
|
123
|
-
valueArg: Record<string, unknown>,
|
|
124
|
-
keysArg: readonly string[],
|
|
125
|
-
optionalKeysArg: readonly string[] = [],
|
|
126
|
-
): boolean => {
|
|
127
|
-
const actualKeys = Object.keys(valueArg);
|
|
128
|
-
return keysArg.every((keyArg) => actualKeys.includes(keyArg))
|
|
129
|
-
&& actualKeys.every((keyArg) => keysArg.includes(keyArg) || optionalKeysArg.includes(keyArg));
|
|
130
|
-
};
|
|
131
|
-
|
|
132
124
|
const isCounter = (valueArg: unknown): valueArg is number => (
|
|
133
125
|
Number.isSafeInteger(valueArg) && (valueArg as number) >= 0
|
|
134
126
|
);
|
|
@@ -390,16 +382,24 @@ export const validateClusterTrafficStatisticsPage = (
|
|
|
390
382
|
* which cluster is speaking comes from the identity tag on the relay's session.
|
|
391
383
|
* A registration that passes here has proven nothing — and no reason it returns
|
|
392
384
|
* ever quotes the bearer, because a reason travels into logs.
|
|
385
|
+
*
|
|
386
|
+
* Both hops judge the body in the one server order `protocol.readProtocolOffer`
|
|
387
|
+
* states, each against its own `clusterIngress` offer, so the relay refuses a peer
|
|
388
|
+
* it cannot serve without asking Cloudly and reaches this check only afterwards.
|
|
389
|
+
* The `validateProtocolOfferOn` call below is therefore the self-consistency
|
|
390
|
+
* check of a body that was already negotiated, never the negotiation step; it
|
|
391
|
+
* reads the offer the same way, as data, so naming reasons never runs an
|
|
392
|
+
* accessor a peer put on the body.
|
|
393
393
|
*/
|
|
394
394
|
export const validateClusterIngressRegistration = (
|
|
395
395
|
valueArg: unknown,
|
|
396
396
|
pathArg = 'cluster ingress registration',
|
|
397
397
|
): string[] => {
|
|
398
398
|
if (!isRecord(valueArg)
|
|
399
|
-
|| !hasExactKeys(valueArg, ['bearer', 'version', 'nodeId'], ['capabilities'])) {
|
|
399
|
+
|| !hasExactKeys(valueArg, ['bearer', 'version', 'nodeId', 'protocol'], ['capabilities'])) {
|
|
400
400
|
return [`${pathArg} must use its exact schema`];
|
|
401
401
|
}
|
|
402
|
-
const errors: string[] =
|
|
402
|
+
const errors: string[] = validateProtocolOfferOn(valueArg, `${pathArg} protocol`);
|
|
403
403
|
if (typeof valueArg.bearer !== 'string'
|
|
404
404
|
|| valueArg.bearer.length < clusterIngressLimits.minimumIngressBearerLength
|
|
405
405
|
|| valueArg.bearer.length > clusterIngressLimits.maximumIngressBearerLength) {
|