@serve.zone/interfaces 32.41.0 → 32.43.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.
Files changed (36) hide show
  1. package/changelog.md +72 -0
  2. package/dist_ts/00_commitinfo_data.js +1 -1
  3. package/dist_ts/data/corestorecontroltoken.d.ts +90 -0
  4. package/dist_ts/data/corestorecontroltoken.js +106 -0
  5. package/dist_ts/data/index.d.ts +2 -0
  6. package/dist_ts/data/index.js +3 -1
  7. package/dist_ts/data/networkaddressplan.js +3 -12
  8. package/dist_ts/data/networkauthority.d.ts +16 -0
  9. package/dist_ts/data/networkauthority.js +45 -1
  10. package/dist_ts/data/networkcredential.d.ts +12 -8
  11. package/dist_ts/data/networkcredential.js +18 -13
  12. package/dist_ts/data/networkegressretirement.d.ts +129 -0
  13. package/dist_ts/data/networkegressretirement.js +142 -0
  14. package/dist_ts/data/noderetirement.d.ts +24 -4
  15. package/dist_ts/data/noderetirement.js +20 -3
  16. package/dist_ts/private/networkcontract.d.ts +2 -0
  17. package/dist_ts/private/networkcontract.js +10 -1
  18. package/dist_ts/requests/corestorecontrol.d.ts +33 -0
  19. package/dist_ts/requests/corestorecontrol.js +2 -0
  20. package/dist_ts/requests/index.d.ts +2 -1
  21. package/dist_ts/requests/index.js +3 -2
  22. package/dist_ts/requests/node.d.ts +9 -1
  23. package/package.json +4 -4
  24. package/readme.md +167 -20
  25. package/ts/00_commitinfo_data.ts +1 -1
  26. package/ts/data/corestorecontroltoken.ts +195 -0
  27. package/ts/data/index.ts +2 -0
  28. package/ts/data/networkaddressplan.ts +3 -13
  29. package/ts/data/networkauthority.ts +46 -0
  30. package/ts/data/networkcredential.ts +17 -12
  31. package/ts/data/networkegressretirement.ts +231 -0
  32. package/ts/data/noderetirement.ts +41 -5
  33. package/ts/private/networkcontract.ts +9 -0
  34. package/ts/requests/corestorecontrol.ts +43 -0
  35. package/ts/requests/index.ts +2 -0
  36. package/ts/requests/node.ts +9 -1
@@ -5,11 +5,29 @@ const nodeRuntimeRetirementStates = ['retiring', 'retired'] as const;
5
5
 
6
6
  /**
7
7
  * How far a node's retirement has come: `retiring` while the producer still stops and removes the
8
- * node's slots, the compiler quarantines its handoff and both node credentials are revoked;
9
- * `retired` once all of that has settled and nothing but the node document is left to delete.
8
+ * node's slots, the compiler quarantines its handoff and leases, both node credentials are revoked
9
+ * and the node's egress fence (`IRuntimeNetworkEgressRetirement`) is not yet recorded; `retired`
10
+ * once the protected authority no longer names the node and nothing but the node document is left
11
+ * to delete.
10
12
  */
11
13
  export type TNodeRuntimeRetirementState = typeof nodeRuntimeRetirementStates[number];
12
14
 
15
+ /** Every way a node can leave its runtime, in the order an escalation moves through them. */
16
+ export const nodeRuntimeRetirementDispositions = Object.freeze(['withdrawn', 'lost'] as const);
17
+
18
+ /**
19
+ * How the node leaves.
20
+ *
21
+ * `withdrawn`: the node still runs and takes part. Its slots are removed against its own removal
22
+ * receipts, and its Pallet withdraws its protection receipt before its credentials are revoked.
23
+ *
24
+ * `lost`: an administrator states that the node will never report again — its host is gone, wiped
25
+ * or unreachable for good. Its slots are abandoned without removal receipts, which is the one thing
26
+ * this statement authorizes. It authorizes nothing about packets: a lost node leaves the protected
27
+ * authority behind exactly the same controller-owned fence as a withdrawn one.
28
+ */
29
+ export type TNodeRuntimeRetirementDisposition = typeof nodeRuntimeRetirementDispositions[number];
30
+
13
31
  /**
14
32
  * That one node leaves its cluster's runtime, stored beside the node document rather than inside
15
33
  * it, because a node update merges caller data and no caller may retire a node with it.
@@ -24,7 +42,9 @@ export interface INodeRuntimeRetirement {
24
42
  /** The cluster the node is retiring from, copied by Cloudly; never caller-chosen. */
25
43
  clusterId: string;
26
44
  state: TNodeRuntimeRetirementState;
27
- /** The administrator who asked for the retirement. */
45
+ /** How the node leaves; a `withdrawn` retirement still `retiring` may be escalated to `lost`. */
46
+ disposition: TNodeRuntimeRetirementDisposition;
47
+ /** The administrator who asked for the retirement, or for its escalation. */
28
48
  actorId: string;
29
49
  /** Unix milliseconds on Cloudly's clock, when the row entered its current state. */
30
50
  since: number;
@@ -42,22 +62,38 @@ export const nodeRuntimeRetirementRefusals = Object.freeze([
42
62
  * `pallet`. Which of the two it is, `getClusterRuntime` says.
43
63
  */
44
64
  'cluster-runtime-not-pallet',
45
- /** The node already carries a retirement row; neither of its states is left by retiring again. */
65
+ /**
66
+ * The node already carries a retirement row that this request cannot move: anything but a
67
+ * `withdrawn` row still `retiring`, asked again as `lost`.
68
+ */
46
69
  'node-already-retired',
47
70
  /** `expectedGeneration` is not the cluster runtime's current generation, so a cutover moved underneath the caller. */
48
71
  'conflict',
72
+ /**
73
+ * A `lost` retirement of a node whose last accepted report is younger than
74
+ * `clusterNodeObservationFreshnessMs`: a node that still reports is not lost, and it leaves as
75
+ * `withdrawn`.
76
+ */
77
+ 'node-still-reporting',
49
78
  ] as const);
50
79
 
51
80
  /** One of the reasons Cloudly answers instead of a retirement row. */
52
81
  export type TNodeRuntimeRetirementRefusal = typeof nodeRuntimeRetirementRefusals[number];
53
82
 
83
+ /** One disposition, exactly as `nodeRuntimeRetirementDispositions` spells it. */
84
+ export const snapshotNodeRuntimeRetirementDisposition = (value: unknown): TNodeRuntimeRetirementDisposition => producerSafe(() => {
85
+ requireNetwork(isOneOf(nodeRuntimeRetirementDispositions, value));
86
+ return value;
87
+ });
88
+
54
89
  /**
55
90
  * Structural snapshot for exact persistence; whether the node exists and whether its cluster admits
56
91
  * the retirement is Cloudly's.
57
92
  */
58
93
  export const snapshotNodeRuntimeRetirement = (value: unknown): INodeRuntimeRetirement => producerSafe(() => {
59
- const item = networkRecord(captureNetwork(value), ['id', 'clusterId', 'state', 'actorId', 'since']);
94
+ const item = networkRecord(captureNetwork(value), ['id', 'clusterId', 'state', 'disposition', 'actorId', 'since']);
60
95
  requireNetwork(isOneOf(nodeRuntimeRetirementStates, item.state));
61
96
  return { id: networkNodeId(item.id), clusterId: networkId(item.clusterId), state: item.state,
97
+ disposition: snapshotNodeRuntimeRetirementDisposition(item.disposition),
62
98
  actorId: networkId(item.actorId), since: networkCounter(item.since) };
63
99
  });
@@ -244,3 +244,12 @@ export const networkContains = (outer: string, inner: string): boolean => {
244
244
  export const networkOverlaps = (left: string, right: string): boolean => {
245
245
  const [a, b] = networkPrefixBounds(left), [c, d] = networkPrefixBounds(right); return a <= d && c <= b;
246
246
  };
247
+ /** Whether the union of `prefixes`, which never overlap one another, covers every address of `prefix`. */
248
+ export const networkCoveredBy = (prefixes: string[], prefix: string): boolean => {
249
+ const [first, last] = networkPrefixBounds(prefix);
250
+ const covered = prefixes.reduce((sum, candidate) => {
251
+ const [low, high] = networkPrefixBounds(candidate);
252
+ return sum + Math.max(0, Math.min(last, high) - Math.max(first, low) + 1);
253
+ }, 0);
254
+ return covered === last - first + 1;
255
+ };
@@ -0,0 +1,43 @@
1
+ import * as plugins from '../plugins.js';
2
+ import type * as userInterfaces from '../data/user.js';
3
+ import type * as controlTokenInterfaces from '../data/corestorecontroltoken.js';
4
+
5
+ /**
6
+ * Stores the Corestore control token for every cluster relay to read sealed, so an administrator
7
+ * sets it without an exec into Cloudly's process.
8
+ *
9
+ * One token for both Corestore provider configs, stored in one transaction: either both hold the
10
+ * new token or neither does. `expected` is the state `getCorestoreControlTokenState` answered, and
11
+ * Cloudly stores only while the token is still exactly there; a set that committed in between is
12
+ * refused, never overwritten. Only the verified credential of a freshly authenticated
13
+ * administrator is read, and Cloudly writes the `receipt` in the transaction that stores the token.
14
+ * The token is in this request and nowhere else: never in the answer, a log, a hook or a receipt.
15
+ * Cloudly refuses with one of `data.corestoreControlTokenSetRefusals`.
16
+ */
17
+ export interface IReq_Admin_Cloudly_SetCorestoreControlToken
18
+ extends plugins.typedrequestInterfaces.implementsTR<
19
+ plugins.typedrequestInterfaces.ITypedRequest,
20
+ IReq_Admin_Cloudly_SetCorestoreControlToken
21
+ > {
22
+ method: 'setCorestoreControlToken';
23
+ request: controlTokenInterfaces.ICorestoreControlTokenSetRequest & {
24
+ identity: userInterfaces.IIdentityCredential;
25
+ };
26
+ response: controlTokenInterfaces.ICorestoreControlTokenSetResult;
27
+ }
28
+
29
+ /**
30
+ * Whether Cloudly holds the Corestore control token, at which revision, and every receipt of a set,
31
+ * oldest first. Value-free: no token, no hash. Requires an administrator.
32
+ */
33
+ export interface IReq_Admin_Cloudly_GetCorestoreControlTokenState
34
+ extends plugins.typedrequestInterfaces.implementsTR<
35
+ plugins.typedrequestInterfaces.ITypedRequest,
36
+ IReq_Admin_Cloudly_GetCorestoreControlTokenState
37
+ > {
38
+ method: 'getCorestoreControlTokenState';
39
+ request: {
40
+ identity: userInterfaces.IIdentityCredential;
41
+ };
42
+ response: controlTokenInterfaces.ICorestoreControlTokenStateRead;
43
+ }
@@ -12,6 +12,7 @@ import * as configRequests from './config.js';
12
12
  import * as coreMailRequests from './coremail.js';
13
13
  import * as coreMailAdminRequests from './coremail.admin.js';
14
14
  import * as corestoreRequests from './corestore.js';
15
+ import * as corestoreControlRequests from './corestorecontrol.js';
15
16
  import * as deploymentRequests from './deployment.js';
16
17
  import * as dnsRequests from './dns.js';
17
18
  import * as domainRequests from './domain.js';
@@ -52,6 +53,7 @@ export {
52
53
  coreMailRequests as coremail,
53
54
  coreMailAdminRequests as coremailAdmin,
54
55
  corestoreRequests as corestore,
56
+ corestoreControlRequests as corestorecontrol,
55
57
  deploymentRequests as deployment,
56
58
  dnsRequests as dns,
57
59
  domainRequests as domain,
@@ -12,7 +12,7 @@ import type {
12
12
  INodeCredentialMutationResult,
13
13
  TNodeCredentialPurpose,
14
14
  } from '../data/nodecredential.js';
15
- import type { INodeRuntimeRetirement } from '../data/noderetirement.js';
15
+ import type { INodeRuntimeRetirement, TNodeRuntimeRetirementDisposition } from '../data/noderetirement.js';
16
16
  import type { INodeRuntimeBindingRead, INodeRuntimeBindingRequest } from '../data/noderuntimebinding.js';
17
17
  import type {
18
18
  INodeEnrollmentRequest,
@@ -232,6 +232,13 @@ export interface IReq_Any_Cloudly_DeleteNodeById extends plugins.typedrequestInt
232
232
  * `expectedGeneration` is the cluster runtime generation the caller read with `getClusterRuntime`:
233
233
  * retirement is a statement about a node of a Pallet cluster, so a cutover that moved the phase
234
234
  * meanwhile refuses the write instead of retiring a node out of a runtime it no longer runs in.
235
+ *
236
+ * `disposition` states how the node leaves (`data.TNodeRuntimeRetirementDisposition`). A request
237
+ * that states none asks for `withdrawn`, the retirement this request always described: the node
238
+ * takes part, and nothing is abandoned. `lost` is taken only when stated, is refused as
239
+ * `node-still-reporting` for a node that still reports, and escalates a `withdrawn` retirement that
240
+ * is still `retiring`. Neither disposition shortens the egress fence: the node leaves the protected
241
+ * authority only behind its `data.IRuntimeNetworkEgressRetirement`.
235
242
  * Every refusal is one of `data.nodeRuntimeRetirementRefusals` and takes nothing away.
236
243
  */
237
244
  export interface IReq_Any_Cloudly_RetireClusterNode extends plugins.typedrequestInterfaces.implementsTR<
@@ -243,6 +250,7 @@ export interface IReq_Any_Cloudly_RetireClusterNode extends plugins.typedrequest
243
250
  identity: IIdentity;
244
251
  nodeId: string;
245
252
  expectedGeneration: number;
253
+ disposition?: TNodeRuntimeRetirementDisposition;
246
254
  };
247
255
  response: {
248
256
  retirement: INodeRuntimeRetirement;