@serfab/cadre-core 1.16.0 → 1.18.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/README.md +4 -3
- package/dist/bootstrap-peer-store-file.js +1 -1
- package/dist/bootstrap-peer-store.d.ts +1 -1
- package/dist/bootstrap-peer-store.js +4 -4
- package/dist/cadre-invite-protocol.d.ts +81 -142
- package/dist/cadre-invite-protocol.js +168 -458
- package/dist/cadre-invite-protocol.js.map +1 -1
- package/dist/cadre-join-request.d.ts +15 -2
- package/dist/cadre-join-request.js +22 -3
- package/dist/cadre-join-request.js.map +1 -1
- package/dist/cadre-node.d.ts +1089 -475
- package/dist/cadre-node.js +2170 -1037
- package/dist/cadre-node.js.map +1 -1
- package/dist/control-authorization.d.ts +36 -14
- package/dist/control-authorization.js +20 -3
- package/dist/control-authorization.js.map +1 -1
- package/dist/control-cohort.d.ts +88 -32
- package/dist/control-cohort.js +91 -33
- package/dist/control-cohort.js.map +1 -1
- package/dist/control-database.d.ts +856 -318
- package/dist/control-database.js +1422 -701
- package/dist/control-database.js.map +1 -1
- package/dist/control-formation-recorder.d.ts +46 -43
- package/dist/control-formation-recorder.js +77 -78
- package/dist/control-formation-recorder.js.map +1 -1
- package/dist/control-protocol-guard.d.ts +11 -4
- package/dist/control-protocol-guard.js +20 -5
- package/dist/control-protocol-guard.js.map +1 -1
- package/dist/control-schema-version.d.ts +97 -0
- package/dist/control-schema-version.js +225 -0
- package/dist/control-schema-version.js.map +1 -0
- package/dist/control-schema.d.ts +45 -5
- package/dist/control-schema.js +262 -78
- package/dist/control-schema.js.map +1 -1
- package/dist/control-write-retry.d.ts +45 -10
- package/dist/control-write-retry.js +92 -22
- package/dist/control-write-retry.js.map +1 -1
- package/dist/delegate-admission.d.ts +13 -0
- package/dist/delegate-admission.js +27 -0
- package/dist/delegate-admission.js.map +1 -1
- package/dist/ed25519-key.d.ts +10 -7
- package/dist/ed25519-key.js +23 -20
- package/dist/ed25519-key.js.map +1 -1
- package/dist/edge-node/config.d.ts +122 -0
- package/dist/edge-node/config.js +199 -0
- package/dist/edge-node/config.js.map +1 -0
- package/dist/edge-node/dissolve.d.ts +95 -0
- package/dist/edge-node/dissolve.js +184 -0
- package/dist/edge-node/dissolve.js.map +1 -0
- package/dist/edge-node/edge-join.d.ts +44 -0
- package/dist/edge-node/edge-join.js +227 -0
- package/dist/edge-node/edge-join.js.map +1 -0
- package/dist/edge-node/edge-node.d.ts +295 -0
- package/dist/edge-node/edge-node.js +704 -0
- package/dist/edge-node/edge-node.js.map +1 -0
- package/dist/edge-node/index.d.ts +18 -0
- package/dist/edge-node/index.js +18 -0
- package/dist/edge-node/index.js.map +1 -0
- package/dist/edge-node/join-credential.d.ts +11 -0
- package/dist/edge-node/join-credential.js +11 -0
- package/dist/edge-node/join-credential.js.map +1 -0
- package/dist/edge-node/lazy-raw-storage.d.ts +40 -0
- package/dist/edge-node/lazy-raw-storage.js +134 -0
- package/dist/edge-node/lazy-raw-storage.js.map +1 -0
- package/dist/edge-node/node-local.d.ts +60 -0
- package/dist/edge-node/node-local.js +58 -0
- package/dist/edge-node/node-local.js.map +1 -0
- package/dist/edge-node/options.d.ts +83 -0
- package/dist/edge-node/options.js +110 -0
- package/dist/edge-node/options.js.map +1 -0
- package/dist/edge-node/owner-grant.d.ts +41 -0
- package/dist/edge-node/owner-grant.js +38 -0
- package/dist/edge-node/owner-grant.js.map +1 -0
- package/dist/edge-node/platform.d.ts +140 -0
- package/dist/edge-node/platform.js +12 -0
- package/dist/edge-node/platform.js.map +1 -0
- package/dist/edge-node/strand-move.d.ts +115 -0
- package/dist/edge-node/strand-move.js +223 -0
- package/dist/edge-node/strand-move.js.map +1 -0
- package/dist/edge-node/strands.d.ts +28 -0
- package/dist/edge-node/strands.js +60 -0
- package/dist/edge-node/strands.js.map +1 -0
- package/dist/enrolled-machine-store.d.ts +3 -3
- package/dist/enrolled-machine-store.js +3 -3
- package/dist/formation-token.d.ts +48 -0
- package/dist/formation-token.js +26 -0
- package/dist/formation-token.js.map +1 -0
- package/dist/index.d.ts +27 -17
- package/dist/index.js +39 -17
- package/dist/index.js.map +1 -1
- package/dist/joined-strand-store.d.ts +29 -12
- package/dist/joined-strand-store.js +66 -27
- package/dist/joined-strand-store.js.map +1 -1
- package/dist/key-store.d.ts +9 -4
- package/dist/key-store.js +9 -4
- package/dist/key-store.js.map +1 -1
- package/dist/link-budget.d.ts +9 -7
- package/dist/link-budget.js +9 -7
- package/dist/link-budget.js.map +1 -1
- package/dist/machine-removal.d.ts +19 -39
- package/dist/machine-removal.js +24 -98
- package/dist/machine-removal.js.map +1 -1
- package/dist/member-redemption.d.ts +256 -0
- package/dist/member-redemption.js +490 -0
- package/dist/member-redemption.js.map +1 -0
- package/dist/membership-view.d.ts +91 -0
- package/dist/membership-view.js +110 -0
- package/dist/membership-view.js.map +1 -0
- package/dist/owner-anchor-sync.d.ts +4 -4
- package/dist/owner-anchor-sync.js +16 -15
- package/dist/owner-anchor-sync.js.map +1 -1
- package/dist/owner-grant-protocol.d.ts +251 -0
- package/dist/owner-grant-protocol.js +344 -0
- package/dist/owner-grant-protocol.js.map +1 -0
- package/dist/owner-key-export.d.ts +70 -0
- package/dist/owner-key-export.js +279 -0
- package/dist/owner-key-export.js.map +1 -0
- package/dist/owner-key-flows.d.ts +55 -0
- package/dist/owner-key-flows.js +60 -0
- package/dist/owner-key-flows.js.map +1 -0
- package/dist/owner-key-store.d.ts +31 -0
- package/dist/owner-key-store.js +81 -0
- package/dist/owner-key-store.js.map +1 -0
- package/dist/owner-keys.d.ts +78 -0
- package/dist/owner-keys.js +133 -0
- package/dist/owner-keys.js.map +1 -0
- package/dist/owner-signer.d.ts +54 -0
- package/dist/owner-signer.js +51 -0
- package/dist/owner-signer.js.map +1 -0
- package/dist/peer-addr-book.d.ts +10 -1
- package/dist/peer-addr-book.js +4 -3
- package/dist/peer-addr-book.js.map +1 -1
- package/dist/peer-authorization.d.ts +83 -18
- package/dist/peer-authorization.js +123 -53
- package/dist/peer-authorization.js.map +1 -1
- package/dist/peer-join-backfill.d.ts +89 -20
- package/dist/peer-join-backfill.js +265 -108
- package/dist/peer-join-backfill.js.map +1 -1
- package/dist/pending-join-runner.d.ts +48 -18
- package/dist/pending-join-runner.js +74 -56
- package/dist/pending-join-runner.js.map +1 -1
- package/dist/provider/rent-node.js +1 -1
- package/dist/provider/rent-node.js.map +1 -1
- package/dist/seed-bootstrap.d.ts +162 -133
- package/dist/seed-bootstrap.js +300 -283
- package/dist/seed-bootstrap.js.map +1 -1
- package/dist/seed-trust-policy.js +4 -4
- package/dist/strand-addr-protocol.d.ts +4 -1
- package/dist/strand-addr-protocol.js +8 -2
- package/dist/strand-addr-protocol.js.map +1 -1
- package/dist/strand-cohort.d.ts +3 -0
- package/dist/strand-cohort.js.map +1 -1
- package/dist/strand-database.d.ts +24 -2
- package/dist/strand-database.js +29 -6
- package/dist/strand-database.js.map +1 -1
- package/dist/strand-first-sync-gate.d.ts +176 -88
- package/dist/strand-first-sync-gate.js +288 -121
- package/dist/strand-first-sync-gate.js.map +1 -1
- package/dist/strand-formation-deadlines.d.ts +9 -9
- package/dist/strand-formation-deadlines.js +9 -9
- package/dist/strand-formation-manager.d.ts +23 -17
- package/dist/strand-formation-manager.js +46 -44
- package/dist/strand-formation-manager.js.map +1 -1
- package/dist/strand-formation-protocol.d.ts +5 -8
- package/dist/strand-formation-protocol.js +101 -16
- package/dist/strand-formation-protocol.js.map +1 -1
- package/dist/strand-instance-manager.d.ts +27 -18
- package/dist/strand-instance-manager.js +119 -50
- package/dist/strand-instance-manager.js.map +1 -1
- package/dist/strand-membership-reconciler.d.ts +16 -13
- package/dist/strand-membership-reconciler.js +30 -22
- package/dist/strand-membership-reconciler.js.map +1 -1
- package/dist/strand-membership-writer.d.ts +45 -22
- package/dist/strand-membership-writer.js +226 -131
- package/dist/strand-membership-writer.js.map +1 -1
- package/dist/strand-move.d.ts +6 -5
- package/dist/strand-move.js +36 -32
- package/dist/strand-move.js.map +1 -1
- package/dist/strand-peer-redial.js +2 -3
- package/dist/strand-peer-redial.js.map +1 -1
- package/dist/strand-revocation-enforcer.d.ts +134 -60
- package/dist/strand-revocation-enforcer.js +144 -71
- package/dist/strand-revocation-enforcer.js.map +1 -1
- package/dist/strand-solicitation.d.ts +50 -39
- package/dist/strand-solicitation.js +10 -3
- package/dist/strand-solicitation.js.map +1 -1
- package/dist/strand-watcher.d.ts +80 -13
- package/dist/strand-watcher.js +152 -48
- package/dist/strand-watcher.js.map +1 -1
- package/dist/table-change-watch.d.ts +63 -0
- package/dist/table-change-watch.js +209 -0
- package/dist/table-change-watch.js.map +1 -0
- package/dist/timeout-scheduler.d.ts +4 -3
- package/dist/timeout-scheduler.js +4 -3
- package/dist/timeout-scheduler.js.map +1 -1
- package/dist/types.d.ts +374 -150
- package/dist/types.js +4 -4
- package/dist/types.js.map +1 -1
- package/package.json +17 -8
- package/src/bootstrap-peer-store-file.ts +44 -44
- package/src/bootstrap-peer-store.ts +214 -214
- package/src/cadre-invite-protocol.ts +740 -1052
- package/src/cadre-join-request.ts +24 -3
- package/src/cadre-node.ts +2402 -1079
- package/src/control-authorization.ts +47 -14
- package/src/control-cohort.ts +204 -128
- package/src/control-database.ts +1749 -820
- package/src/control-formation-recorder.ts +359 -353
- package/src/control-protocol-guard.ts +23 -6
- package/src/control-schema-version.ts +301 -0
- package/src/control-schema.ts +273 -78
- package/src/control-write-retry.ts +641 -567
- package/src/delegate-admission.ts +351 -314
- package/src/ed25519-key.ts +174 -171
- package/src/edge-node/config.ts +277 -0
- package/src/edge-node/dissolve.ts +251 -0
- package/src/edge-node/edge-join.ts +319 -0
- package/src/edge-node/edge-node.ts +1045 -0
- package/src/edge-node/index.ts +59 -0
- package/src/edge-node/join-credential.ts +16 -0
- package/src/edge-node/lazy-raw-storage.ts +178 -0
- package/src/edge-node/node-local.ts +84 -0
- package/src/edge-node/options.ts +179 -0
- package/src/edge-node/owner-grant.ts +63 -0
- package/src/edge-node/platform.ts +151 -0
- package/src/edge-node/strand-move.ts +270 -0
- package/src/edge-node/strands.ts +72 -0
- package/src/enrolled-machine-store.ts +3 -3
- package/src/formation-token.ts +63 -0
- package/src/index.ts +899 -789
- package/src/joined-strand-store.ts +73 -28
- package/src/key-store.ts +10 -4
- package/src/link-budget.ts +9 -7
- package/src/machine-removal.ts +26 -111
- package/src/member-redemption.ts +649 -0
- package/src/membership-view.ts +144 -0
- package/src/owner-anchor-sync.ts +19 -18
- package/src/owner-grant-protocol.ts +547 -0
- package/src/owner-key-export.ts +348 -0
- package/src/owner-key-flows.ts +109 -0
- package/src/owner-key-store.ts +85 -0
- package/src/owner-keys.ts +178 -0
- package/src/owner-signer.ts +94 -0
- package/src/peer-addr-book.ts +4 -3
- package/src/peer-authorization.ts +558 -488
- package/src/peer-join-backfill.ts +971 -761
- package/src/pending-join-runner.ts +76 -53
- package/src/provider/rent-node.ts +1 -1
- package/src/seed-bootstrap.ts +343 -349
- package/src/seed-trust-policy.ts +4 -4
- package/src/strand-addr-protocol.ts +547 -538
- package/src/strand-cohort.ts +4 -0
- package/src/strand-database.ts +352 -319
- package/src/strand-first-sync-gate.ts +334 -133
- package/src/strand-formation-deadlines.ts +227 -227
- package/src/strand-formation-manager.ts +731 -725
- package/src/strand-formation-protocol.ts +122 -24
- package/src/strand-instance-manager.ts +2092 -2026
- package/src/strand-membership-reconciler.ts +33 -25
- package/src/strand-membership-writer.ts +2093 -1974
- package/src/strand-move.ts +50 -38
- package/src/strand-peer-redial.ts +2 -3
- package/src/strand-revocation-enforcer.ts +740 -654
- package/src/strand-solicitation.ts +61 -34
- package/src/strand-watcher.ts +175 -56
- package/src/table-change-watch.ts +285 -0
- package/src/timeout-scheduler.ts +29 -28
- package/src/types.ts +391 -152
package/dist/types.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ConnectionGater, Libp2p, PeerId, PrivateKey } from '@libp2p/interface';
|
|
2
2
|
import type { CircuitRelayServerInit } from '@libp2p/circuit-relay-v2';
|
|
3
3
|
import type { IRawStorage, Libp2pConnectionMonitorInit, Libp2pTransports, NoiseCryptoInterface } from '@optimystic/db-p2p';
|
|
4
|
-
import type { IPeerNetwork, IRepo } from '@optimystic/db-core';
|
|
4
|
+
import type { CollectionChangeListener, IPeerNetwork, IRepo } from '@optimystic/db-core';
|
|
5
5
|
import type { PeerJoinBackfillConfig } from './peer-join-backfill.js';
|
|
6
6
|
import type { StrandReactivityConfig } from './strand-reactivity.js';
|
|
7
7
|
import type { StrandRevocationEnforcementConfig } from './strand-revocation-enforcer.js';
|
|
@@ -17,8 +17,11 @@ import type { StrandNetworkStateStore } from './strand-network-state.js';
|
|
|
17
17
|
import type { EnrolledMachineStore } from './enrolled-machine-store.js';
|
|
18
18
|
import type { JoinedStrandStore } from './joined-strand-store.js';
|
|
19
19
|
import type { PushNotifier } from './push-notifier.js';
|
|
20
|
-
import type { CadreInviteSignedFields, RevocableTable } from './control-authorization.js';
|
|
21
|
-
import type {
|
|
20
|
+
import type { CadreInviteSignedFields, OwnerGrantSignedFields, RevocableTable } from './control-authorization.js';
|
|
21
|
+
import type { FoundingInvite } from './control-database.js';
|
|
22
|
+
import type { CadreInvitation } from './cadre-invite-protocol.js';
|
|
23
|
+
import type { OwnerGrantBundle } from './owner-grant-protocol.js';
|
|
24
|
+
import type { RedemptionAddressOutcome } from './member-redemption.js';
|
|
22
25
|
import type { ControlRetryAbandonment } from './control-retry.js';
|
|
23
26
|
import type { FormationRejectionCode } from './strand-formation-rejection.js';
|
|
24
27
|
import type { ListenTransportOptions } from './relay-addrs.js';
|
|
@@ -36,6 +39,23 @@ export interface Libp2pNodeWithRepo extends Libp2p {
|
|
|
36
39
|
* backfill (`peer-join-backfill.ts`) logs once and stays inert when it is absent.
|
|
37
40
|
*/
|
|
38
41
|
keyNetwork?: IPeerNetwork;
|
|
42
|
+
/**
|
|
43
|
+
* The node's block store, attached by the same factory (Optimystic's
|
|
44
|
+
* `OptimysticNodeAttachments.storageRepo`), narrowed to the storage-wide change feed: it
|
|
45
|
+
* fires for every block that lands in this node's store, a push or a commit. Optional for
|
|
46
|
+
* the same reason as `keyNetwork`; the first-sync gate (`strand-first-sync-gate.ts`) wakes
|
|
47
|
+
* on it, and logs once and probes on its backstop alone when it is absent.
|
|
48
|
+
*/
|
|
49
|
+
storageRepo?: {
|
|
50
|
+
onAnyCollectionChange(listener: CollectionChangeListener): () => void;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Tells the node a peer holds a block at a revision or later (Optimystic's
|
|
54
|
+
* `OptimysticNodeAttachments.reportBlockHeld`), so its under-replication drain and rebalance
|
|
55
|
+
* monitor do not push that peer the same block again. Optional for the same reason as
|
|
56
|
+
* `keyNetwork`; the join catch-up (`peer-join-backfill.ts`) reports each block a peer accepted.
|
|
57
|
+
*/
|
|
58
|
+
reportBlockHeld?: (blockId: string, rev: number, peerId: string) => Promise<void>;
|
|
39
59
|
}
|
|
40
60
|
/**
|
|
41
61
|
* Node profile determines storage participation
|
|
@@ -544,8 +564,13 @@ export interface NetworkConfig {
|
|
|
544
564
|
*/
|
|
545
565
|
targetDegree?: number;
|
|
546
566
|
/**
|
|
547
|
-
*
|
|
548
|
-
*
|
|
567
|
+
* The reconcile pass's backstop in ms: a pass runs this long after the last one
|
|
568
|
+
* settled when nothing has started one sooner (a membership table change, a sibling
|
|
569
|
+
* connecting or disconnecting, an address change, a redial or strand-address wake).
|
|
570
|
+
* It also caps the redial ladder. Defaults to
|
|
571
|
+
* {@link DEFAULT_CONTROL_COHORT_RECONCILE_MS} (2 minutes). The membership rows view's
|
|
572
|
+
* maximum age (`MEMBERSHIP_VIEW_MAX_AGE_MS`, 15 s) does not follow this field: a backstop
|
|
573
|
+
* longer than it reads storage on every backstop pass, a shorter one every 15 s at most.
|
|
549
574
|
*/
|
|
550
575
|
reconcileMs?: number;
|
|
551
576
|
/**
|
|
@@ -613,10 +638,10 @@ export interface NetworkConfig {
|
|
|
613
638
|
* pinging node's monitor sees the reset and aborts the connection exactly as it would on its
|
|
614
639
|
* own timeout. So this deadline is only real up to the handler timeout of the node being
|
|
615
640
|
* pinged, which has to stay above it. The deployed relay sets its handler to 60 s for that
|
|
616
|
-
* reason (`ops/docker/libp2p-infra/src/main.ts`). Every cadre node's handler is Optimystic's
|
|
617
|
-
*
|
|
618
|
-
* (`
|
|
619
|
-
*
|
|
641
|
+
* reason (`ops/docker/libp2p-infra/src/main.ts`). Every cadre node's handler is Optimystic's,
|
|
642
|
+
* which derives it from this object: twice `pingTimeout.maxTimeout`, so 60 s
|
|
643
|
+
* (`NodeOptions.pingHandlerTimeoutMs`, unset here, since Optimystic 1.16.0). An app that
|
|
644
|
+
* replaces this object without a `pingTimeout` gets `@libp2p/ping`'s 10 s handler back.
|
|
620
645
|
*
|
|
621
646
|
* WHAT THE LINK NEEDS OF IT. One ping opens a fresh stream and echoes over it: a protocol
|
|
622
647
|
* negotiation plus the echo, two link round trips by `link-budget.ts`'s counts (a `newStream`
|
|
@@ -723,11 +748,10 @@ export interface CadreNodeConfig {
|
|
|
723
748
|
* form). Mutually exclusive with {@link privateKey}. Absent ⇒ use `privateKey`
|
|
724
749
|
* when set, else libp2p generates an ephemeral key.
|
|
725
750
|
*
|
|
726
|
-
*
|
|
727
|
-
*
|
|
728
|
-
*
|
|
729
|
-
*
|
|
730
|
-
* built here.
|
|
751
|
+
* The node signs owner writes through whatever owner signer the embedder wires
|
|
752
|
+
* (`CadreNode.useOwnerSigner`). An owner key has its own slot
|
|
753
|
+
* (`owner-key-store.ts`), which may be in this same store; this identity is never
|
|
754
|
+
* an owner key.
|
|
731
755
|
*/
|
|
732
756
|
keyStore?: KeyStore;
|
|
733
757
|
/** Slot id for the node identity in {@link keyStore}. Default: `'cadre/identity'`. */
|
|
@@ -782,10 +806,11 @@ export interface CadreNodeConfig {
|
|
|
782
806
|
strandClusterSize?: number;
|
|
783
807
|
/**
|
|
784
808
|
* Tuning for the strand peer-join block catch-up (see `peer-join-backfill.ts`):
|
|
785
|
-
* when a strand's libp2p node connects to a peer
|
|
786
|
-
*
|
|
787
|
-
*
|
|
788
|
-
*
|
|
809
|
+
* when a strand's libp2p node connects (or reconnects) to a peer, every
|
|
810
|
+
* block in the strand's own raw store that the peer is not
|
|
811
|
+
* known to hold is pushed to it, each block once per peer, so a machine that
|
|
812
|
+
* joined the strand after blocks were committed still ends up physically
|
|
813
|
+
* holding them. Applies to every strand this node starts.
|
|
789
814
|
* Omit for the defaults (`DEFAULT_PEER_JOIN_BACKFILL`); `{ enabled: false }`
|
|
790
815
|
* restores the no-backfill behaviour. The control network runs its own,
|
|
791
816
|
* separately tuned catch-up — see {@link controlBackfill}.
|
|
@@ -812,13 +837,14 @@ export interface CadreNodeConfig {
|
|
|
812
837
|
/**
|
|
813
838
|
* Tuning for the CONTROL network's peer-join block catch-up (same module,
|
|
814
839
|
* `peer-join-backfill.ts`, wired in `CadreNode.start`): when the control
|
|
815
|
-
* libp2p node connects to an AUTHORIZED party member
|
|
816
|
-
*
|
|
817
|
-
* it. This is what makes a control
|
|
818
|
-
*
|
|
819
|
-
* that joined later — without it,
|
|
820
|
-
* the affected tables as empty.
|
|
821
|
-
*
|
|
840
|
+
* libp2p node connects (or reconnects) to an AUTHORIZED party member, every
|
|
841
|
+
* block in the control database's own raw store that the
|
|
842
|
+
* member is not known to hold is pushed to it. This is what makes a control
|
|
843
|
+
* block committed while the writer was alone (collection headers written at
|
|
844
|
+
* genesis above all) physically reach members that joined later — without it,
|
|
845
|
+
* such a member that restarts offline reads the affected tables as empty.
|
|
846
|
+
* Pushes are gated on the node's authorized-member snapshot (the rule
|
|
847
|
+
* `CadreNode.isAuthorizedMember` reads), checked at push time, because the control
|
|
822
848
|
* network's inbound gate deliberately admits non-members in several states
|
|
823
849
|
* (seed delivery, enrollment, bootstrap/relay peers). Omit for the defaults
|
|
824
850
|
* (`DEFAULT_PEER_JOIN_BACKFILL`); `{ enabled: false }` disables it.
|
|
@@ -830,9 +856,10 @@ export interface CadreNodeConfig {
|
|
|
830
856
|
* starts: each strand node materializes the peer ids bound to REMOVED members
|
|
831
857
|
* (orphaned `Strand.MemberPeer` rows) and refuses them at the stream and
|
|
832
858
|
* connection layers, so removing a party cuts the network to its machines
|
|
833
|
-
* rather than only deleting its row. Open strands never arm it.
|
|
834
|
-
*
|
|
835
|
-
*
|
|
859
|
+
* rather than only deleting its row. Open strands never arm it. Each strand
|
|
860
|
+
* re-reads its membership when `Strand.Member` or `Strand.MemberPeer` changes,
|
|
861
|
+
* and at the latest every `DEFAULT_REVOCATION_BACKSTOP_MS`. Omit for the
|
|
862
|
+
* defaults; `{ enabled: false }` restores the pre-existing behaviour.
|
|
836
863
|
*/
|
|
837
864
|
strandRevocationEnforcement?: StrandRevocationEnforcementConfig;
|
|
838
865
|
/**
|
|
@@ -844,9 +871,8 @@ export interface CadreNodeConfig {
|
|
|
844
871
|
* background without blocking bring-up. `pollIntervalMs` is the IDLE cadence
|
|
845
872
|
* (how often a machine nobody has admitted re-checks) and the cap of the
|
|
846
873
|
* unfinished-join retry ladder, NOT the retry cadence itself — an unfinished
|
|
847
|
-
* join retries from 1 s, doubling. Omit for the defaults
|
|
848
|
-
* {
|
|
849
|
-
* `{ enabled: false }` disarms the loop — for test fixtures that hand-drive
|
|
874
|
+
* join retries from 1 s, doubling. Omit for the defaults
|
|
875
|
+
* (`DEFAULT_MEMBERSHIP_RECONCILE_INTERVAL_MS`); `{ enabled: false }` disarms the loop — for test fixtures that hand-drive
|
|
850
876
|
* the membership writers and assert exact row sets.
|
|
851
877
|
*/
|
|
852
878
|
strandMembershipReconciliation?: StrandMembershipReconciliationConfig;
|
|
@@ -855,21 +881,27 @@ export interface CadreNodeConfig {
|
|
|
855
881
|
* (`strand-first-sync-gate.ts`), applied to every strand this node launches as a
|
|
856
882
|
* non-founder: the strand's database is withheld from the app (`StrandInstance.database`
|
|
857
883
|
* unset, status `'syncing'`) until the strand's `Strand.Header` has been received from
|
|
858
|
-
* another member and every `App` table has been read once, because a
|
|
859
|
-
* to a table it has never fetched creates a private copy of it that
|
|
884
|
+
* another member and every `Strand` and `App` table has been read once, because a
|
|
885
|
+
* machine that writes to a table it has never fetched creates a private copy of it that
|
|
886
|
+
* never merges.
|
|
860
887
|
* `timeoutMs` bounds how long {@link CadreNode.addStrand} waits before rejecting with
|
|
861
|
-
* `StrandAwaitingFirstSyncError` (retryable — the launch stays up and keeps probing)
|
|
862
|
-
*
|
|
888
|
+
* `StrandAwaitingFirstSyncError` (retryable — the launch stays up and keeps probing).
|
|
889
|
+
* While gated the machine probes whenever data lands in the strand's store, and
|
|
890
|
+
* `backstopMs` after its last probe when none has. Omit for the defaults (`DEFAULT_STRAND_FIRST_SYNC_TIMEOUT_MS`,
|
|
863
891
|
* sized for a machine re-attaching through a relay on a slow link, the slowest attach
|
|
864
892
|
* measured; that constant's doc comment carries the number, the measurement behind it and
|
|
865
|
-
* what the budget costs, and is the only copy of them; `
|
|
866
|
-
*
|
|
893
|
+
* what the budget costs, and is the only copy of them; `DEFAULT_STRAND_FIRST_SYNC_BACKSTOP_MS`,
|
|
894
|
+
* 2 s). There is deliberately no way to disable the gate: a machine whose store already
|
|
867
895
|
* holds the Header is never gated, so nothing that works today is blocked by it.
|
|
868
896
|
*/
|
|
869
897
|
strandFirstSync?: StrandFirstSyncConfig;
|
|
870
898
|
/** Hibernation configuration */
|
|
871
899
|
hibernation?: HibernationConfig;
|
|
872
|
-
/**
|
|
900
|
+
/**
|
|
901
|
+
* The strand watcher's backstop in ms (default 300000): the longest it goes without
|
|
902
|
+
* re-reading `Strand` and `JoinedStrand` when no change to them is heard. It otherwise runs
|
|
903
|
+
* on a change. Also caps the first step of its retry ladders, which is 5 s otherwise.
|
|
904
|
+
*/
|
|
873
905
|
strandWatchInterval?: number;
|
|
874
906
|
/**
|
|
875
907
|
* Require a valid author signature on every sApp schema before a strand is
|
|
@@ -900,7 +932,7 @@ export interface CadreNodeConfig {
|
|
|
900
932
|
*
|
|
901
933
|
* A node has exactly one cold-start trust source, so `claim` beside a non-empty
|
|
902
934
|
* `trustedOwners.pinnedKeys` or a `seedTrustPolicy` fails `start()` closed, and
|
|
903
|
-
* `
|
|
935
|
+
* `useOwnerSigner` (an owner key) refuses on such a node: a hosted node never
|
|
904
936
|
* holds an owner key. A claimed node restarted with this still set ignores it (its
|
|
905
937
|
* anchor is non-empty), so the operator need not remove it.
|
|
906
938
|
*
|
|
@@ -952,7 +984,7 @@ export interface CadreNodeConfig {
|
|
|
952
984
|
/**
|
|
953
985
|
* Provenance recorded for {@link pinnedKeys}. Default: 'operator'.
|
|
954
986
|
* ('genesis' is reserved for the node's own founding key, seeded
|
|
955
|
-
* internally by `
|
|
987
|
+
* internally by `useOwnerSigner`; 'chain' is written only by the
|
|
956
988
|
* anchor sync, `CadreNode.syncOwnerAnchor`.)
|
|
957
989
|
*/
|
|
958
990
|
pinnedSource?: Exclude<TrustSource, 'genesis' | 'chain'>;
|
|
@@ -1175,16 +1207,21 @@ export interface StrandRow {
|
|
|
1175
1207
|
MemberPrivateKey: string | null;
|
|
1176
1208
|
Type: 'o' | 'c';
|
|
1177
1209
|
/**
|
|
1178
|
-
* ed25519 (base64url) owner key
|
|
1179
|
-
*
|
|
1180
|
-
* the
|
|
1181
|
-
*
|
|
1182
|
-
*
|
|
1183
|
-
* `null` on a consent-seated strand (the unsigned `FormationUsage` branch
|
|
1184
|
-
* records no trustworthy signer). Provenance, not content —
|
|
1185
|
-
* `strandRowMismatches` excludes it from the identical-content comparison.
|
|
1210
|
+
* ed25519 (base64url) owner key that signed the owner-signed `Strand` insert
|
|
1211
|
+
* (`== context.OwnerKey`, pinned by the schema's `AuthorizedInsert`). `null` on a
|
|
1212
|
+
* consent-seated strand (the unsigned `FormationUsage` branch records no
|
|
1213
|
+
* signer). Provenance, not content — `strandRowMismatches` excludes it from the
|
|
1214
|
+
* identical-content comparison.
|
|
1186
1215
|
*/
|
|
1187
1216
|
FounderOwnerKey: string | null;
|
|
1217
|
+
/**
|
|
1218
|
+
* Peer id of the machine that runs the founder bootstrap, named by the owner
|
|
1219
|
+
* signature on the insert (`CadreNode.publishStrand` writes its own). A launch
|
|
1220
|
+
* with no explicit `founder` flag founds iff this is its own peer id (see
|
|
1221
|
+
* `CadreNode.launchStrand`), so two machines holding one owner key never both
|
|
1222
|
+
* found. `null` on a consent-seated strand. Provenance, as {@link FounderOwnerKey}.
|
|
1223
|
+
*/
|
|
1224
|
+
FounderPeerId: string | null;
|
|
1188
1225
|
}
|
|
1189
1226
|
/**
|
|
1190
1227
|
* A `CadreControl.JoinRequest` row: a join this party asked for through another party's
|
|
@@ -1305,7 +1342,7 @@ export interface StrandConfig {
|
|
|
1305
1342
|
* unset and writes nothing — it receives those rows via Optimystic sync.
|
|
1306
1343
|
*
|
|
1307
1344
|
* When unset, founder-ness is DERIVED from the row: this node founds iff
|
|
1308
|
-
* {@link StrandRow.
|
|
1345
|
+
* {@link StrandRow.FounderPeerId} is its own peer id. An explicit
|
|
1309
1346
|
* `true`/`false` wins over the derivation — the formation/responder flows pass
|
|
1310
1347
|
* it deliberately, since a consent-seated row carries a null column.
|
|
1311
1348
|
*/
|
|
@@ -1357,6 +1394,14 @@ export interface FoundStrandConfig {
|
|
|
1357
1394
|
memberPrivateKey?: string;
|
|
1358
1395
|
/** sApp configuration the hosting application provides, as for {@link StrandConfig}. */
|
|
1359
1396
|
sAppConfig: SAppConfig;
|
|
1397
|
+
/**
|
|
1398
|
+
* A formation invitation to publish bound to this strand, for the app `sAppConfig.id`, in the
|
|
1399
|
+
* same control transaction and owner approval as the strand row. Mint it first with
|
|
1400
|
+
* `createOpenInvitation` (its `expiration` is `expiresAtMs`). When the strand is already
|
|
1401
|
+
* published the invitation is published on its own, under its own approval, as
|
|
1402
|
+
* `publishFormationInvite` would; one already stored under `token` for this strand is kept.
|
|
1403
|
+
*/
|
|
1404
|
+
formationInvite?: Omit<FoundingInvite, 'sAppId'>;
|
|
1360
1405
|
/**
|
|
1361
1406
|
* Forwarded to the attach ({@link StrandConfig.awaitFirstSync}). Matters only when the
|
|
1362
1407
|
* call ATTACHES rather than founds — the stored row was published by a sibling machine
|
|
@@ -1390,6 +1435,35 @@ export interface FoundStrandResult {
|
|
|
1390
1435
|
*/
|
|
1391
1436
|
founded: boolean;
|
|
1392
1437
|
}
|
|
1438
|
+
/**
|
|
1439
|
+
* Options for {@link CadreNode.foundStrand}. Passing them selects the form that returns once
|
|
1440
|
+
* the row is published ({@link FoundStrandBackgroundResult}), for a caller that needs only the
|
|
1441
|
+
* row: minting an invitation reads just its id and membership key.
|
|
1442
|
+
*
|
|
1443
|
+
* An invitation redeemed before the start finishes is refused, retryably: a closed host
|
|
1444
|
+
* strand answers `host-strand-unavailable` and leaves the token unspent. For an open host
|
|
1445
|
+
* strand the approval is sent, but carries no strand addresses, because the strand node does
|
|
1446
|
+
* not exist yet.
|
|
1447
|
+
*/
|
|
1448
|
+
export interface FoundStrandOptions {
|
|
1449
|
+
/** Return once the row is published; the start continues in {@link FoundStrandBackgroundResult.ready}. */
|
|
1450
|
+
background: true;
|
|
1451
|
+
}
|
|
1452
|
+
/** What {@link CadreNode.foundStrand} returns with `{ background: true }`: the row is published; the local start continues. */
|
|
1453
|
+
export interface FoundStrandBackgroundResult {
|
|
1454
|
+
/** The live control-plane row: freshly published, or the one already there. Same as {@link FoundStrandResult.strandRow}. */
|
|
1455
|
+
strandRow: StrandRow;
|
|
1456
|
+
/** Same as {@link FoundStrandResult.founded}. */
|
|
1457
|
+
founded: boolean;
|
|
1458
|
+
/**
|
|
1459
|
+
* Settles when the local start does. Resolves with the instance `addStrand` returns.
|
|
1460
|
+
* Rejects with the start's own error. After a launch failure the strand stays published
|
|
1461
|
+
* and the strand watcher keeps retrying it. After a first-sync timeout (only an adopted,
|
|
1462
|
+
* not-founded row waits for one) the instance stays up and still syncing, so wait with
|
|
1463
|
+
* {@link CadreNode.whenStrandWritable}.
|
|
1464
|
+
*/
|
|
1465
|
+
ready: Promise<StrandInstance>;
|
|
1466
|
+
}
|
|
1393
1467
|
/**
|
|
1394
1468
|
* Result of creating a new cadre peer
|
|
1395
1469
|
*/
|
|
@@ -1643,14 +1717,14 @@ export interface CadreNodeEvents {
|
|
|
1643
1717
|
* Also emitted for a strand this node joined from ANOTHER party, which no control
|
|
1644
1718
|
* row names: the node remembers every such join (see
|
|
1645
1719
|
* {@link CadreNodeConfig.joinedStrands}) and offers it here on each start, as a row
|
|
1646
|
-
* with
|
|
1720
|
+
* with null founder columns carrying the closed strand's `MemberPrivateKey`. That
|
|
1647
1721
|
* row is the product of the formation's consent, so claiming it needs no second one.
|
|
1648
1722
|
*
|
|
1649
1723
|
* **Fired once per strand per session, and it can fire before your listener is
|
|
1650
|
-
* attached.** The strand watcher's first
|
|
1724
|
+
* attached.** The strand watcher's first run is inside `CadreNode.start()`
|
|
1651
1725
|
* (100 ms after the watcher starts), so every strand already stored for this
|
|
1652
1726
|
* party is normally offered while the embedding app is still inside its own
|
|
1653
|
-
* `start()` await. The watcher then records the strand as seen and no later
|
|
1727
|
+
* `start()` await. The watcher then records the strand as seen and no later run
|
|
1654
1728
|
* re-offers it, so a listener attached a moment late misses those strands for the
|
|
1655
1729
|
* life of the process.
|
|
1656
1730
|
*
|
|
@@ -1711,10 +1785,17 @@ export interface CadreNodeEvents {
|
|
|
1711
1785
|
partyId: string;
|
|
1712
1786
|
peerId: string;
|
|
1713
1787
|
};
|
|
1714
|
-
/**
|
|
1788
|
+
/**
|
|
1789
|
+
* Emitted when a seed delivered over the seed protocol has been verified, merged and
|
|
1790
|
+
* acknowledged to its sender. The dials of its preferred peers follow this event, so it
|
|
1791
|
+
* waits on no connection. `dialTargets` are those peers (`seedDialTargets`): an embedder
|
|
1792
|
+
* that restarts into another party's stores carries them there, since this node retained
|
|
1793
|
+
* them in its own.
|
|
1794
|
+
*/
|
|
1715
1795
|
'seed:applied': {
|
|
1716
1796
|
partyId: string;
|
|
1717
1797
|
peersAdded: number;
|
|
1798
|
+
dialTargets: SeedDialTarget[];
|
|
1718
1799
|
};
|
|
1719
1800
|
/** Emitted when seed application fails */
|
|
1720
1801
|
'seed:error': {
|
|
@@ -1726,10 +1807,10 @@ export interface CadreNodeEvents {
|
|
|
1726
1807
|
* valid claim proof has been recorded (`claim.record`) and has durably anchored its
|
|
1727
1808
|
* signer as this node's owner. Carries the claim's party beside the owner key: the
|
|
1728
1809
|
* party this node should serve from now on, which its own config did not know. Fires
|
|
1729
|
-
* BEFORE the seed is acknowledged to the claimant
|
|
1730
|
-
*
|
|
1731
|
-
*
|
|
1732
|
-
*
|
|
1810
|
+
* BEFORE the seed is acknowledged to the claimant and its peers merged, so it precedes
|
|
1811
|
+
* that seed's `seed:applied`; an embedder that restarts into the claimed party on this
|
|
1812
|
+
* event should wait for that `seed:applied` (or `seed:error`) so the acknowledgement is
|
|
1813
|
+
* not lost with the node. `CadreNode.isAwaitingClaim` is the
|
|
1733
1814
|
* matching predicate for a reader that subscribed too late to see the event.
|
|
1734
1815
|
*/
|
|
1735
1816
|
'claim:accepted': NodeClaimRecord;
|
|
@@ -1820,25 +1901,27 @@ export interface CadrePeerRow {
|
|
|
1820
1901
|
export type CadrePeerVoucherFields = Pick<CadrePeerRow, 'peerId' | 'stampId' | 'vouchOwner' | 'vouchSig' | 'vouchUsage'>;
|
|
1821
1902
|
/**
|
|
1822
1903
|
* One live `CadreControl.OwnerKey` row as `ControlDatabase.queryOwnerKeyRows` reads it: the
|
|
1823
|
-
* key and the persisted proof of how it was seated. The three proof shapes are the
|
|
1824
|
-
* (`OwnerKey.Authorized`): the founding row (all three null), an owner-signed add
|
|
1825
|
-
* and `vouchSig`, the signer's signature over `ownerKeyAddDigest(key, stampId)`), or an
|
|
1826
|
-
* owner
|
|
1827
|
-
* `
|
|
1828
|
-
* the stampless row the schema permits but no writer produces,
|
|
1829
|
-
* `stampId` is non-null here. The anchor sync (`deriveOwnerAnchor`)
|
|
1830
|
-
* the proof against the keys it already trusts, never against the table itself.
|
|
1904
|
+
* key, its label and the persisted proof of how it was seated. The three proof shapes are the
|
|
1905
|
+
* schema's (`OwnerKey.Authorized`): the founding row (all three null), an owner-signed add
|
|
1906
|
+
* (`vouchOwner` and `vouchSig`, the signer's signature over `ownerKeyAddDigest(key, label, stampId)`), or an
|
|
1907
|
+
* owner grant redeemed by consent (`vouchOwner` the issuer, `vouchSig` null, `vouchUsage` the
|
|
1908
|
+
* `OwnerGrantUsage` row). Rows whose stamp is
|
|
1909
|
+
* retired in `Revocation`, and the stampless row the schema permits but no writer produces,
|
|
1910
|
+
* never reach a reader, so `stampId` is non-null here. The anchor sync (`deriveOwnerAnchor`)
|
|
1911
|
+
* judges the proof against the keys it already trusts, never against the table itself.
|
|
1831
1912
|
*/
|
|
1832
1913
|
export interface OwnerKeyRow {
|
|
1833
1914
|
/** ed25519 public key (base64url) — the row key. */
|
|
1834
1915
|
key: string;
|
|
1916
|
+
/** The user's name for the key, bound into an owner-signed add or into the grant that seated it; null when none was given. */
|
|
1917
|
+
label: string | null;
|
|
1835
1918
|
/** Single-use anti-replay nonce the voucher signature, or the usage row, is bound to. */
|
|
1836
1919
|
stampId: string;
|
|
1837
|
-
/** The owner that signed the add, or that issued the
|
|
1920
|
+
/** The owner that signed the add, or that issued the grant that seated it; null on the founding row. */
|
|
1838
1921
|
vouchOwner: string | null;
|
|
1839
|
-
/** That owner's signature over the row's `'add'` digest, base64url; null on the founding row and on
|
|
1922
|
+
/** That owner's signature over the row's `'add'` digest, base64url; null on the founding row and on a consent-seated row. */
|
|
1840
1923
|
vouchSig: string | null;
|
|
1841
|
-
/** The `
|
|
1924
|
+
/** The `OwnerGrantUsage.UsageStampId` that seated this row; null otherwise. */
|
|
1842
1925
|
vouchUsage: string | null;
|
|
1843
1926
|
}
|
|
1844
1927
|
/**
|
|
@@ -1870,30 +1953,70 @@ export interface CadreInviteUsageRow {
|
|
|
1870
1953
|
peerId: string;
|
|
1871
1954
|
/** The admitted device's ed25519 public key (base64url). */
|
|
1872
1955
|
peerKey: string;
|
|
1873
|
-
/** The `CadrePeer.StampId` this redemption seated
|
|
1956
|
+
/** The `CadrePeer.StampId` this redemption seated. */
|
|
1874
1957
|
peerStampId: string;
|
|
1875
|
-
/** The `OwnerKey.StampId` this redemption seated, when the invitation grants ownership; else null. */
|
|
1876
|
-
ownerStampId: string | null;
|
|
1877
1958
|
/** The invitation private key's signature over the `'redeem'` digest, base64url. */
|
|
1878
1959
|
inviteSig: string;
|
|
1879
1960
|
/** The device's signature over the `'consent'` digest, base64url. */
|
|
1880
1961
|
peerSig: string;
|
|
1881
1962
|
}
|
|
1882
1963
|
/**
|
|
1883
|
-
* The usage and invitation rows an invitation-admitted row is verified through
|
|
1884
|
-
* `
|
|
1885
|
-
*
|
|
1886
|
-
* `verifyInvitationOwnerAdmission` (`deriveOwnerAnchor`). Loaded once per membership refresh
|
|
1887
|
-
* (`CadreNode.loadInvitationChain`) and shared by both readers.
|
|
1964
|
+
* The usage and invitation rows an invitation-admitted `CadrePeer` row is verified through
|
|
1965
|
+
* (`verifyInvitationAdmission`, `CadreNode.listAuthorizedMembers`), keyed by `UsageStampId`
|
|
1966
|
+
* and `CadreInvite.Key`. Loaded once per membership refresh (`CadreNode.loadInvitationChain`).
|
|
1888
1967
|
*/
|
|
1889
1968
|
export interface InvitationChain {
|
|
1890
1969
|
usages: Map<string, CadreInviteUsageRow>;
|
|
1891
1970
|
invites: Map<string, CadreInviteRow>;
|
|
1892
1971
|
}
|
|
1893
1972
|
/**
|
|
1894
|
-
* One
|
|
1895
|
-
*
|
|
1896
|
-
*
|
|
1973
|
+
* One `CadreControl.OwnerGrant` row: an owner-signed grant of ownership to whoever holds its
|
|
1974
|
+
* private half, as `ControlDatabase.insertOwnerGrant` returns it and `queryOwnerGrant` reads
|
|
1975
|
+
* it. Every column is here because the row travels, as a {@link CadreInviteRow} does: the
|
|
1976
|
+
* holder carries it inside the grant bundle and a member re-seats it verbatim
|
|
1977
|
+
* (`seatOwnerGrant`), so `expiresAt` is the engine-canonical `datetime` string the row
|
|
1978
|
+
* stores. The signed subset is `OwnerGrantSignedFields` (`control-authorization.ts`); the
|
|
1979
|
+
* grant names no machine and no peer id.
|
|
1980
|
+
*/
|
|
1981
|
+
export interface OwnerGrantRow extends OwnerGrantSignedFields {
|
|
1982
|
+
/** The owner that signed the row (`IssuerKey`, base64url ed25519); a reader checks it against its anchor. */
|
|
1983
|
+
issuerKey: string;
|
|
1984
|
+
/** That owner's `'add'` signature over the row (`IssuerSig`, base64url). */
|
|
1985
|
+
issuerSig: string;
|
|
1986
|
+
}
|
|
1987
|
+
/**
|
|
1988
|
+
* One `CadreControl.OwnerGrantUsage` row: a redemption of an {@link OwnerGrantRow}, as
|
|
1989
|
+
* `ControlDatabase.queryOwnerGrantUsages` reads it. Both signatures are stored so any reader
|
|
1990
|
+
* can re-verify the chain grant → usage → `OwnerKey` row (`verifyOwnerGrantAdmission`).
|
|
1991
|
+
*/
|
|
1992
|
+
export interface OwnerGrantUsageRow {
|
|
1993
|
+
/** The redemption's single-use nonce (the row key), signed into both signatures. */
|
|
1994
|
+
usageStampId: string;
|
|
1995
|
+
/** The `OwnerGrant.Key` redeemed. */
|
|
1996
|
+
grantKey: string;
|
|
1997
|
+
/** The owner key seated (base64url ed25519): the holder's, fresh or already held. */
|
|
1998
|
+
seatedKey: string;
|
|
1999
|
+
/** The `OwnerKey.StampId` this redemption seated. */
|
|
2000
|
+
seatedStampId: string;
|
|
2001
|
+
/** The grant private key's signature over the `'redeem'` digest, base64url. */
|
|
2002
|
+
grantSig: string;
|
|
2003
|
+
/** The seated key's signature over the `'consent'` digest, base64url. */
|
|
2004
|
+
ownerSig: string;
|
|
2005
|
+
}
|
|
2006
|
+
/**
|
|
2007
|
+
* The usage and grant rows a grant-seated `OwnerKey` row is verified through, keyed by
|
|
2008
|
+
* `UsageStampId` and `OwnerGrant.Key` (`verifyOwnerGrantAdmission`, from `deriveOwnerAnchor`).
|
|
2009
|
+
* The grant twin of {@link InvitationChain}, loaded beside it by `CadreNode.syncOwnerAnchor`
|
|
2010
|
+
* when some owner row is consent-seated; a row's `vouchUsage` is looked up in this chain
|
|
2011
|
+
* first and in the invitation chain otherwise.
|
|
2012
|
+
*/
|
|
2013
|
+
export interface OwnerGrantChain {
|
|
2014
|
+
usages: Map<string, OwnerGrantUsageRow>;
|
|
2015
|
+
grants: Map<string, OwnerGrantRow>;
|
|
2016
|
+
}
|
|
2017
|
+
/**
|
|
2018
|
+
* One machine of the cadre as `CadreNode.listMachines` reports it: a live `CadrePeer` row. An
|
|
2019
|
+
* owner key is not a machine; `CadreNode.listOwnerKeys` lists those.
|
|
1897
2020
|
*
|
|
1898
2021
|
* `profile` and `lastPublishedAt` are the machine's own claim only when the row's
|
|
1899
2022
|
* self-signature verifies; both are null otherwise, so an owner re-vouch that bumped
|
|
@@ -1902,74 +2025,112 @@ export interface InvitationChain {
|
|
|
1902
2025
|
*/
|
|
1903
2026
|
export interface CadreMachine {
|
|
1904
2027
|
peerId: string;
|
|
1905
|
-
/** ed25519
|
|
2028
|
+
/** The machine's ed25519 identity key (base64url) behind `peerId`; null when the id is not ed25519. Never an owner key (`listOwnerKeys` lists those). */
|
|
1906
2029
|
publicKey: string | null;
|
|
1907
2030
|
/** This node itself. */
|
|
1908
2031
|
isSelf: boolean;
|
|
1909
|
-
/** `publicKey` is a live `OwnerKey` here. */
|
|
1910
|
-
isOwner: boolean;
|
|
1911
|
-
/** Has a live `CadrePeer` row; false for an owner key with no machine row. */
|
|
1912
|
-
isMember: boolean;
|
|
1913
2032
|
/** Passes this node's authorized-membership predicate now (`CadreNode.listAuthorizedMembers`; always false for self, which that set excludes). */
|
|
1914
2033
|
trusted: boolean;
|
|
1915
2034
|
/** The machine's self-published node profile; null until it publishes, or when its signature does not verify. */
|
|
1916
2035
|
profile: NodeProfile | null;
|
|
1917
2036
|
/** `UpdatedAt` of its self-signed record, re-stamped while it runs; null on the same terms as `profile`. */
|
|
1918
2037
|
lastPublishedAt: number | null;
|
|
1919
|
-
/** `CadrePeer.VouchOwner
|
|
2038
|
+
/** `CadrePeer.VouchOwner`: the owner key that vouched it, or the issuer of the invitation that admitted it. */
|
|
1920
2039
|
vouchedBy: string | null;
|
|
1921
2040
|
}
|
|
2041
|
+
/** One live owner key as `CadreNode.listOwnerKeys` lists it, for an app's owner-key screen. */
|
|
2042
|
+
export interface CadreOwnerKey {
|
|
2043
|
+
/** ed25519 public key (base64url). */
|
|
2044
|
+
key: string;
|
|
2045
|
+
/** The user's name for the key ("phone", "paper backup"); null when none was given. */
|
|
2046
|
+
label: string | null;
|
|
2047
|
+
/** `OwnerKey.VouchOwner`: the owner that signed its add, or that issued the owner grant that seated it; null on the founding key. */
|
|
2048
|
+
vouchedBy: string | null;
|
|
2049
|
+
/** This node's owner signer holds it. */
|
|
2050
|
+
heldHere: boolean;
|
|
2051
|
+
/** In this node's trusted-owner anchor, so this node accepts what it signs. */
|
|
2052
|
+
trusted: boolean;
|
|
2053
|
+
}
|
|
2054
|
+
/** Why `CadreNode.addOwner` refuses by name (`OwnerKeyAddRefusedError.code`). */
|
|
2055
|
+
export type OwnerKeyAddRefusal =
|
|
2056
|
+
/** No sibling reachable (`CadreNode.hasReachableControlSibling`) while the party has other members: the row would stay on this node, and nothing re-issues an `OwnerKey` add. */
|
|
2057
|
+
'alone';
|
|
1922
2058
|
/** Why `CadreNode.removeMachine` refuses by name (`MachineRemovalRefusedError.code`). */
|
|
1923
2059
|
export type MachineRemovalRefusal =
|
|
1924
2060
|
/** This node holds no enrolled owner key, so it cannot sign the removal. */
|
|
1925
2061
|
'not-an-owner'
|
|
1926
|
-
/** The machine is this node:
|
|
1927
|
-
| 'self'
|
|
1928
|
-
/** The machine holds the only live owner key here (`MinOneOwner`). */
|
|
1929
|
-
| 'last-owner';
|
|
2062
|
+
/** The machine is this node: leaving a cadre is the embedder's flow (stop the node, delete its data), not a removal. */
|
|
2063
|
+
| 'self';
|
|
1930
2064
|
/**
|
|
1931
2065
|
* What `CadreNode.removeMachine` would do for one machine, read without writing
|
|
1932
|
-
* (`CadreNode.planMachineRemoval`), for an app's confirmation step.
|
|
2066
|
+
* (`CadreNode.planMachineRemoval`), for an app's confirmation step. A machine vouches nothing
|
|
2067
|
+
* (a `VouchOwner` is an owner key), so removing one strands no other row.
|
|
1933
2068
|
*/
|
|
1934
2069
|
export interface MachineRemovalPlan {
|
|
1935
2070
|
/** The machine as listed, or null when no live row names it here (already removed). */
|
|
1936
2071
|
machine: CadreMachine | null;
|
|
1937
2072
|
refusal: MachineRemovalRefusal | null;
|
|
1938
|
-
/** The machine's key is a live owner key, so the removal also retires it. */
|
|
1939
|
-
removesOwnerKey: boolean;
|
|
1940
|
-
/** Rows the machine's owner key vouched, which stop passing the membership predicate everywhere once it is removed unless re-vouched first. Empty unless `removesOwnerKey`. */
|
|
1941
|
-
dependents: {
|
|
1942
|
-
/** Live `OwnerKey` rows whose `VouchOwner` is the machine's key, this node's own excluded. */
|
|
1943
|
-
owners: string[];
|
|
1944
|
-
/** Live `CadrePeer` rows whose `VouchOwner` is the machine's key, the machine itself and this node excluded. */
|
|
1945
|
-
peers: string[];
|
|
1946
|
-
};
|
|
1947
2073
|
/** Live `CadreInvite` keys the machine could redeem to come back: targeted at it, or already redeemed by it with uses left. */
|
|
1948
2074
|
invitations: string[];
|
|
1949
|
-
/** This node's own `OwnerKey` or `CadrePeer` row was vouched by the machine. It cannot re-vouch its own rows; another owner has to re-add it afterwards. */
|
|
1950
|
-
ownDependency: boolean;
|
|
1951
|
-
}
|
|
1952
|
-
/** Options for `CadreNode.removeMachine`. */
|
|
1953
|
-
export interface RemoveMachineOptions {
|
|
1954
|
-
/** Dependents to re-vouch under this node's key before the removal; each must appear in the plan's `dependents`. */
|
|
1955
|
-
revouch?: {
|
|
1956
|
-
owners?: readonly string[];
|
|
1957
|
-
peers?: readonly string[];
|
|
1958
|
-
};
|
|
1959
2075
|
}
|
|
1960
2076
|
/** What `CadreNode.removeMachine` wrote. All false and empty when no live row named the machine here. */
|
|
1961
2077
|
export interface MachineRemovalResult {
|
|
1962
2078
|
removedPeer: boolean;
|
|
1963
|
-
removedOwnerKey: boolean;
|
|
1964
2079
|
removedDeviceToken: boolean;
|
|
1965
2080
|
/** `CadreInvite` keys whose withdrawal tombstone this call filed. */
|
|
1966
2081
|
withdrawnInvitations: string[];
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
2082
|
+
}
|
|
2083
|
+
/** Why `CadreNode.removeOwner` refuses by name (`OwnerKeyRemovalRefusedError.code`). */
|
|
2084
|
+
export type OwnerKeyRemovalRefusal =
|
|
2085
|
+
/** This node holds no enrolled owner key, so it cannot sign the removal. */
|
|
2086
|
+
'not-an-owner'
|
|
2087
|
+
/** No live `OwnerKey` row names the key here (never an owner, or already removed). */
|
|
2088
|
+
| 'unknown'
|
|
2089
|
+
/** The key is the only live owner key (`MinOneOwner`); no owner can remove it. */
|
|
2090
|
+
| 'last-owner'
|
|
2091
|
+
/** The key is this node's own owner key: an owner cannot sign its own row's removal (`A.Key <> old.Key`), so ask another owner key. */
|
|
2092
|
+
| 'self'
|
|
2093
|
+
/** A re-vouch of an `OwnerKey` row was asked for while this node reaches no sibling and the party has other members: the re-added row has no re-issue path. Decided at call time, so never planned. */
|
|
2094
|
+
| 'alone';
|
|
2095
|
+
/** The rows sharing the owner keys' voucher column that a removed owner key strands unless re-vouched first. */
|
|
2096
|
+
export interface OwnerKeyDependents {
|
|
2097
|
+
/** Live `OwnerKey` rows whose `VouchOwner` is the key, this node's own excluded. */
|
|
2098
|
+
owners: string[];
|
|
2099
|
+
/** Live `CadrePeer` rows (peer ids) whose `VouchOwner` is the key, this node's own excluded. */
|
|
2100
|
+
peers: string[];
|
|
2101
|
+
}
|
|
2102
|
+
/**
|
|
2103
|
+
* What `CadreNode.removeOwner` would do for one owner key, read without writing
|
|
2104
|
+
* (`CadreNode.planOwnerKeyRemoval`), for an app's confirmation step.
|
|
2105
|
+
*/
|
|
2106
|
+
export interface OwnerKeyRemovalPlan {
|
|
2107
|
+
/** The key as `CadreNode.listOwnerKeys` lists it, or null when no live row names it here. */
|
|
2108
|
+
ownerKey: CadreOwnerKey | null;
|
|
2109
|
+
refusal: Exclude<OwnerKeyRemovalRefusal, 'alone'> | null;
|
|
2110
|
+
/** Rows the key vouched, which stop passing the membership predicate on every machine once it is removed unless re-vouched first. */
|
|
2111
|
+
dependents: OwnerKeyDependents;
|
|
2112
|
+
/** This node's own `CadrePeer` row was vouched by the key, so `removeOwner` re-vouches it under this node's key first, unasked: left on the removed key, every other machine would drop this node. */
|
|
2113
|
+
revouchesOwnRow: boolean;
|
|
2114
|
+
/** This node's own `OwnerKey` row was vouched by the key. It cannot re-vouch that row (the re-add's delete would be its own removal); it keeps its place in every anchor that already derived it, and another owner can re-vouch it afterwards. */
|
|
2115
|
+
ownDependency: boolean;
|
|
2116
|
+
/** Live owner grants the key issued, which stop being redeemable once it is removed (`OwnerGrantUsage.Authorized` wants a live issuer): an app says "the backup made with this key stops working". Withdrawn, expired and spent grants are not listed. */
|
|
2117
|
+
grants: OwnerGrantRow[];
|
|
2118
|
+
}
|
|
2119
|
+
/** Options for `CadreNode.removeOwner`. */
|
|
2120
|
+
export interface RemoveOwnerOptions {
|
|
2121
|
+
/** Dependents to re-vouch under this node's key before the removal; each must appear in the plan's `dependents`. */
|
|
2122
|
+
revouch?: {
|
|
2123
|
+
owners?: readonly string[];
|
|
2124
|
+
peers?: readonly string[];
|
|
1971
2125
|
};
|
|
1972
2126
|
}
|
|
2127
|
+
/** What `CadreNode.removeOwner` wrote. */
|
|
2128
|
+
export interface OwnerKeyRemovalResult {
|
|
2129
|
+
/** The `OwnerKey` row and its tombstone were written; false only when another owner's removal reached this node between the plan and the write. */
|
|
2130
|
+
removed: boolean;
|
|
2131
|
+
/** Rows re-vouched under this node's key before the removal: the dependents asked for, and this node's own row when the plan's `revouchesOwnRow`. */
|
|
2132
|
+
revouched: OwnerKeyDependents;
|
|
2133
|
+
}
|
|
1973
2134
|
/**
|
|
1974
2135
|
* This node's own removal from its cadre, as it learned it: the `CadrePeer` tombstone naming
|
|
1975
2136
|
* its peer id, read after it had seen its own live row (`CadreNode.removedFromCadre`, the
|
|
@@ -1999,22 +2160,42 @@ export interface CadreInviteStatus {
|
|
|
1999
2160
|
}
|
|
2000
2161
|
/**
|
|
2001
2162
|
* What `ControlDatabase.redeemCadreInvite` did. `alreadyMember` is the idempotent
|
|
2002
|
-
* retry after a dropped reply: the device's row
|
|
2003
|
-
*
|
|
2004
|
-
* no seat was spent. The stamps are the live rows' either way.
|
|
2163
|
+
* retry after a dropped reply: the device's row was already present, so nothing was
|
|
2164
|
+
* written and no seat was spent. The stamp is the live row's either way.
|
|
2005
2165
|
*/
|
|
2006
2166
|
export interface CadreInviteRedemptionResult {
|
|
2007
2167
|
alreadyMember: boolean;
|
|
2008
2168
|
peerStampId: string;
|
|
2009
|
-
|
|
2169
|
+
}
|
|
2170
|
+
/**
|
|
2171
|
+
* One {@link OwnerGrantRow} with its standing, as `ControlDatabase.listOwnerGrantStatuses`
|
|
2172
|
+
* reports it. `live` is the redemption's own test: not withdrawn, unexpired, uses left,
|
|
2173
|
+
* issuer still an owner here.
|
|
2174
|
+
*/
|
|
2175
|
+
export interface OwnerGrantStatus {
|
|
2176
|
+
grant: OwnerGrantRow;
|
|
2177
|
+
live: boolean;
|
|
2178
|
+
withdrawn: boolean;
|
|
2179
|
+
/** Redemptions this node holds for it (`OwnerGrantUsage` rows). */
|
|
2180
|
+
usesRecorded: number;
|
|
2181
|
+
}
|
|
2182
|
+
/**
|
|
2183
|
+
* What `ControlDatabase.redeemOwnerGrant` did. `alreadyOwner` is the idempotent retry after
|
|
2184
|
+
* a dropped reply, and the case of a holder seating a key that is already an owner: the
|
|
2185
|
+
* key's live `OwnerKey` row was already present, so nothing was written and no use was
|
|
2186
|
+
* spent. `seatedStampId` is the live row's either way.
|
|
2187
|
+
*/
|
|
2188
|
+
export interface OwnerGrantRedemptionResult {
|
|
2189
|
+
alreadyOwner: boolean;
|
|
2190
|
+
seatedStampId: string;
|
|
2010
2191
|
}
|
|
2011
2192
|
/**
|
|
2012
2193
|
* One `CadreControl.Revocation` tombstone as read by
|
|
2013
2194
|
* `ControlDatabase.queryRevocations`: the identity triple plus the `ReissuedAt`
|
|
2014
2195
|
* counter an owner bumps (`ControlDatabase.reissueRevocations`) to re-write — and
|
|
2015
2196
|
* therefore re-broadcast — a tombstone that committed while the node was alone.
|
|
2016
|
-
* Never the ledger marker: that row names no guarded table, and
|
|
2017
|
-
* skips it, which is what keeps `tableName` a {@link RevocableTable}.
|
|
2197
|
+
* Never the ledger marker an older party may hold: that row names no guarded table, and
|
|
2198
|
+
* `queryRevocations` skips it, which is what keeps `tableName` a {@link RevocableTable}.
|
|
2018
2199
|
*/
|
|
2019
2200
|
export interface RevocationRow {
|
|
2020
2201
|
/** Which guarded table's stamp was retired. */
|
|
@@ -2030,13 +2211,6 @@ export interface RevocationRow {
|
|
|
2030
2211
|
/** That owner's signature over the tombstone's `'remove'` digest (`Revocation.SignerSig`). */
|
|
2031
2212
|
signerSig: string;
|
|
2032
2213
|
}
|
|
2033
|
-
/**
|
|
2034
|
-
* Outcome of `ControlDatabase.openRevocationLedger`: `'opened'` when this call filed the
|
|
2035
|
-
* singleton `Revocation` ledger marker, `'already-open'` when it was already filed (seen
|
|
2036
|
-
* by the in-lock guard, or filed first by another owner and refused on the primary key).
|
|
2037
|
-
* Either way the marker exists afterwards.
|
|
2038
|
-
*/
|
|
2039
|
-
export type RevocationLedgerOpenResult = 'opened' | 'already-open';
|
|
2040
2214
|
/**
|
|
2041
2215
|
* Outcome of {@link CadreNode.registerSelf}, surfaced so callers (e.g. the CLI
|
|
2042
2216
|
* `--owner` branch) can log what happened:
|
|
@@ -2197,7 +2371,7 @@ export interface ApnsCredentials {
|
|
|
2197
2371
|
production?: boolean;
|
|
2198
2372
|
}
|
|
2199
2373
|
/**
|
|
2200
|
-
* A peer entry in a control network seed.
|
|
2374
|
+
* A peer entry in a control network seed, or in a cadre invitation redemption reply.
|
|
2201
2375
|
* Contains connection information for a cadre peer.
|
|
2202
2376
|
*/
|
|
2203
2377
|
export interface SeedPeer {
|
|
@@ -2205,11 +2379,15 @@ export interface SeedPeer {
|
|
|
2205
2379
|
peerId: string;
|
|
2206
2380
|
/** Multiaddrs for connecting to this peer */
|
|
2207
2381
|
multiaddrs: string[];
|
|
2208
|
-
/**
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2382
|
+
/**
|
|
2383
|
+
* Dial this peer first: the machine that minted the seed (or answered the redemption) and
|
|
2384
|
+
* every always-on machine (`CadrePeer.Profile = 'storage'`). A dial hint only — it grants
|
|
2385
|
+
* nothing, and says nothing about owner keys (`projectSeedPeers`).
|
|
2386
|
+
*/
|
|
2387
|
+
preferred: boolean;
|
|
2212
2388
|
}
|
|
2389
|
+
/** A peer a seed nominates for dialing, and the addresses to dial it at (`seedDialTargets`). */
|
|
2390
|
+
export type SeedDialTarget = Pick<SeedPeer, 'peerId' | 'multiaddrs'>;
|
|
2213
2391
|
/**
|
|
2214
2392
|
* Control network seed for bootstrapping new nodes.
|
|
2215
2393
|
* Pre-populates a new node's cache to solve the cold-start problem:
|
|
@@ -2399,15 +2577,15 @@ export interface ApplySeedResult {
|
|
|
2399
2577
|
/** Machine-readable refusal cause, when the refusing trust policy supplied one. */
|
|
2400
2578
|
code?: SeedRefusalCode;
|
|
2401
2579
|
/**
|
|
2402
|
-
*
|
|
2403
|
-
* carried no
|
|
2580
|
+
* Preferred seed peers (`SeedPeer.preferred`) this apply attempted to dial. Zero when the
|
|
2581
|
+
* seed carried no preferred peer with an address, or when the seed was rejected before
|
|
2404
2582
|
* the dial loop ran.
|
|
2405
2583
|
*/
|
|
2406
|
-
|
|
2584
|
+
preferredDialsAttempted: number;
|
|
2407
2585
|
/**
|
|
2408
|
-
* How many of those dials threw. `
|
|
2409
|
-
* ===
|
|
2410
|
-
* accepted (`success: true`) but no
|
|
2586
|
+
* How many of those dials threw. `preferredDialsAttempted > 0 && preferredDialsFailed
|
|
2587
|
+
* === preferredDialsAttempted` means "seeded but stranded": the seed itself was
|
|
2588
|
+
* accepted (`success: true`) but no preferred peer could be reached, so this node has
|
|
2411
2589
|
* no connection to bootstrap its control database from. The node retries those
|
|
2412
2590
|
* addresses on every control-cohort reconcile pass (see
|
|
2413
2591
|
* `CadreNode.dialColdStartBootstrap`), so this is a signal, not a fatal error.
|
|
@@ -2419,7 +2597,7 @@ export interface ApplySeedResult {
|
|
|
2419
2597
|
* down. Treat a non-zero value as certain failure and zero as "no failure
|
|
2420
2598
|
* observed".
|
|
2421
2599
|
*/
|
|
2422
|
-
|
|
2600
|
+
preferredDialsFailed: number;
|
|
2423
2601
|
}
|
|
2424
2602
|
/**
|
|
2425
2603
|
* Node network topology type for seed helper scenarios.
|
|
@@ -2427,18 +2605,13 @@ export interface ApplySeedResult {
|
|
|
2427
2605
|
export type NodeTopology = 'public' | 'nat';
|
|
2428
2606
|
/**
|
|
2429
2607
|
* What an owner asks `CadreNode.createCadreInvitation` for. The invitation is a keypair the
|
|
2430
|
-
* node mints; whoever holds the returned bundle can redeem it at any member machine.
|
|
2608
|
+
* node mints; whoever holds the returned bundle can redeem it at any member machine. It admits
|
|
2609
|
+
* a machine and grants nothing else; ownership is an owner grant (`CreateOwnerGrantOptions`).
|
|
2431
2610
|
*/
|
|
2432
2611
|
export interface CreateCadreInvitationOptions {
|
|
2433
2612
|
/** The one device that may redeem it; omit for whoever redeems first. */
|
|
2434
2613
|
peerId?: string;
|
|
2435
|
-
/**
|
|
2436
|
-
grantsOwner: boolean;
|
|
2437
|
-
/**
|
|
2438
|
-
* Lifetime from now, in ms. Defaults to 15 minutes for an untargeted owner-granting
|
|
2439
|
-
* invitation — a bearer credential for admin rights — and 24 hours otherwise. A negative
|
|
2440
|
-
* value mints an already-expired invitation (tests).
|
|
2441
|
-
*/
|
|
2614
|
+
/** Lifetime from now, in ms; default 24 hours. A negative value mints an already-expired invitation (tests). */
|
|
2442
2615
|
expiresInMs?: number;
|
|
2443
2616
|
/** How many redemptions it allows; default 1. */
|
|
2444
2617
|
uses?: number;
|
|
@@ -2490,17 +2663,68 @@ export type CadreJoinProgress = {
|
|
|
2490
2663
|
* least one member answered with a retryable refusal (issuer-unknown, busy, conflict, internal).
|
|
2491
2664
|
*/
|
|
2492
2665
|
reason: 'no-member-answered' | 'member-not-ready';
|
|
2493
|
-
outcomes: readonly
|
|
2666
|
+
outcomes: readonly RedemptionAddressOutcome[];
|
|
2494
2667
|
};
|
|
2495
2668
|
/** What `CadreNode.redeemCadreInvitation` returns once a member accepted. */
|
|
2496
2669
|
export interface RedeemCadreInvitationResult {
|
|
2497
2670
|
/** The member machine that admitted this device, when its address named one. */
|
|
2498
2671
|
peerId: string | null;
|
|
2499
|
-
/** Whether the invitation also seated this device's key as an owner. */
|
|
2500
|
-
grantsOwner: boolean;
|
|
2501
2672
|
/** When the member accepted, ISO 8601. */
|
|
2502
2673
|
redeemedAt: string;
|
|
2503
2674
|
}
|
|
2675
|
+
/**
|
|
2676
|
+
* What an owner asks `CadreNode.createOwnerGrant` for. The grant is a keypair the node mints;
|
|
2677
|
+
* whoever holds the returned bundle can become an owner of this cadre through any member
|
|
2678
|
+
* machine, so it is a bearer credential for admin rights.
|
|
2679
|
+
*/
|
|
2680
|
+
export interface CreateOwnerGrantOptions {
|
|
2681
|
+
/** The label every key the grant seats will carry; trimmed, at most 64 characters, blank meaning none. */
|
|
2682
|
+
label?: string;
|
|
2683
|
+
/**
|
|
2684
|
+
* Lifetime from now, in ms; default 15 minutes. `null` means NO expiry and must be passed
|
|
2685
|
+
* explicitly: a backup grant, kept as carefully as an owner key. A negative value mints an
|
|
2686
|
+
* already-expired grant (tests).
|
|
2687
|
+
*/
|
|
2688
|
+
expiresInMs?: number | null;
|
|
2689
|
+
/** How many redemptions it allows; default 1. */
|
|
2690
|
+
uses?: number;
|
|
2691
|
+
}
|
|
2692
|
+
/** What `CadreNode.createOwnerGrant` returns: the bundle, the same encoded for sharing, and how far it reaches. */
|
|
2693
|
+
export interface CreateOwnerGrantResult {
|
|
2694
|
+
grant: OwnerGrantBundle;
|
|
2695
|
+
/** `encodeOwnerGrant(grant)`: `sereus-owner-grant:1.` and base64url JSON, for a QR code, a paste or a file. */
|
|
2696
|
+
encoded: string;
|
|
2697
|
+
/** Whether a holder could redeem it once the minting machine is gone; see {@link CadreInvitationReach}. */
|
|
2698
|
+
reach: CadreInvitationReach;
|
|
2699
|
+
}
|
|
2700
|
+
/** How `CadreNode.redeemOwnerGrant` and `joinWithOwnerGrant` dial the grant's members: the invitation's options, with the same meanings. */
|
|
2701
|
+
export type RedeemOwnerGrantOptions = RedeemCadreInvitationOptions;
|
|
2702
|
+
/** What `CadreNode.redeemOwnerGrant` returns once the key is seated. */
|
|
2703
|
+
export interface RedeemOwnerGrantResult {
|
|
2704
|
+
/** The key seated as an owner: the signer's public key. */
|
|
2705
|
+
ownerKey: string;
|
|
2706
|
+
/** The key was already a live owner, so nothing was written and no use of the grant was spent. */
|
|
2707
|
+
alreadyOwner: boolean;
|
|
2708
|
+
/** The member machine that wrote the row, when the redemption went over the protocol and its address named one; null on the local path. */
|
|
2709
|
+
memberPeerId: string | null;
|
|
2710
|
+
}
|
|
2711
|
+
/** What `CadreNode.joinWithOwnerGrant` returns once this node is a member and its key an owner. */
|
|
2712
|
+
export interface JoinWithOwnerGrantResult {
|
|
2713
|
+
/** The member machine that admitted this node, when its address named one. */
|
|
2714
|
+
peerId: string | null;
|
|
2715
|
+
/** When the member admitted this node, ISO 8601. */
|
|
2716
|
+
redeemedAt: string;
|
|
2717
|
+
/** The key seated as an owner: the signer's public key. */
|
|
2718
|
+
ownerKey: string;
|
|
2719
|
+
/** The key was already a live owner of the party, so the grant spent no use. */
|
|
2720
|
+
alreadyOwner: boolean;
|
|
2721
|
+
/**
|
|
2722
|
+
* The signer was wired as this node's owner signer, because its `OwnerKey` row reached this
|
|
2723
|
+
* node within the bound. False when the row had not synced in time: the node is a member and
|
|
2724
|
+
* the key an owner all the same, and `CadreNode.wireOwnKeyIfOwner(signer)` wires it later.
|
|
2725
|
+
*/
|
|
2726
|
+
ownerWired: boolean;
|
|
2727
|
+
}
|
|
2504
2728
|
/**
|
|
2505
2729
|
* Options for adding a drone via provider API.
|
|
2506
2730
|
*/
|