@serfab/cadre-core 0.0.2

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 (54) hide show
  1. package/README.md +252 -0
  2. package/dist/arachnode-stub.d.ts +60 -0
  3. package/dist/arachnode-stub.js +120 -0
  4. package/dist/arachnode-stub.js.map +1 -0
  5. package/dist/cadre-node.d.ts +252 -0
  6. package/dist/cadre-node.js +753 -0
  7. package/dist/cadre-node.js.map +1 -0
  8. package/dist/control-database.d.ts +62 -0
  9. package/dist/control-database.js +295 -0
  10. package/dist/control-database.js.map +1 -0
  11. package/dist/enrollment.d.ts +76 -0
  12. package/dist/enrollment.js +126 -0
  13. package/dist/enrollment.js.map +1 -0
  14. package/dist/hibernation-manager.d.ts +68 -0
  15. package/dist/hibernation-manager.js +212 -0
  16. package/dist/hibernation-manager.js.map +1 -0
  17. package/dist/index.d.ts +12 -0
  18. package/dist/index.js +24 -0
  19. package/dist/index.js.map +1 -0
  20. package/dist/seed-bootstrap.d.ts +164 -0
  21. package/dist/seed-bootstrap.js +554 -0
  22. package/dist/seed-bootstrap.js.map +1 -0
  23. package/dist/strand-database.d.ts +39 -0
  24. package/dist/strand-database.js +108 -0
  25. package/dist/strand-database.js.map +1 -0
  26. package/dist/strand-formation-manager.d.ts +87 -0
  27. package/dist/strand-formation-manager.js +168 -0
  28. package/dist/strand-formation-manager.js.map +1 -0
  29. package/dist/strand-instance-manager.d.ts +60 -0
  30. package/dist/strand-instance-manager.js +209 -0
  31. package/dist/strand-instance-manager.js.map +1 -0
  32. package/dist/strand-solicitation.d.ts +145 -0
  33. package/dist/strand-solicitation.js +180 -0
  34. package/dist/strand-solicitation.js.map +1 -0
  35. package/dist/strand-watcher.d.ts +70 -0
  36. package/dist/strand-watcher.js +136 -0
  37. package/dist/strand-watcher.js.map +1 -0
  38. package/dist/types.d.ts +484 -0
  39. package/dist/types.js +26 -0
  40. package/dist/types.js.map +1 -0
  41. package/package.json +67 -0
  42. package/src/arachnode-stub.ts +160 -0
  43. package/src/cadre-node.ts +923 -0
  44. package/src/control-database.ts +376 -0
  45. package/src/enrollment.ts +199 -0
  46. package/src/hibernation-manager.ts +268 -0
  47. package/src/index.ts +71 -0
  48. package/src/seed-bootstrap.ts +753 -0
  49. package/src/strand-database.ts +168 -0
  50. package/src/strand-formation-manager.ts +277 -0
  51. package/src/strand-instance-manager.ts +281 -0
  52. package/src/strand-solicitation.ts +318 -0
  53. package/src/strand-watcher.ts +197 -0
  54. package/src/types.ts +553 -0
@@ -0,0 +1,68 @@
1
+ import type { StrandInstance, HibernationConfig } from './types.js';
2
+ /**
3
+ * Callbacks for hibernation state changes
4
+ */
5
+ export interface HibernationCallbacks {
6
+ onIdle: (strandId: string) => Promise<void>;
7
+ onHibernate: (strandId: string) => Promise<void>;
8
+ onWake: (strandId: string) => Promise<void>;
9
+ }
10
+ /**
11
+ * Manages strand hibernation state transitions based on activity.
12
+ *
13
+ * State machine:
14
+ * active → idle (after idleTimeout with no activity)
15
+ * idle → hibernating (after hibernateTimeout with no activity)
16
+ * idle → active (on activity)
17
+ * hibernating → active (on wake signal or check-in with pending activity)
18
+ */
19
+ export declare class HibernationManager {
20
+ private readonly config;
21
+ private readonly callbacks;
22
+ private readonly timers;
23
+ private readonly checkInTimers;
24
+ private running;
25
+ constructor(config: HibernationConfig, callbacks: HibernationCallbacks);
26
+ /**
27
+ * Get effective timeouts for a latency hint
28
+ */
29
+ private getTimeouts;
30
+ /**
31
+ * Start managing hibernation for all strands
32
+ */
33
+ start(): void;
34
+ /**
35
+ * Stop managing hibernation
36
+ */
37
+ stop(): void;
38
+ /**
39
+ * Register a strand for hibernation management
40
+ */
41
+ trackStrand(instance: StrandInstance): void;
42
+ /**
43
+ * Untrack a strand from hibernation management
44
+ */
45
+ untrackStrand(strandId: string): void;
46
+ /**
47
+ * Record activity on a strand - resets idle timer
48
+ */
49
+ recordActivity(instance: StrandInstance): void;
50
+ /**
51
+ * Force wake a hibernating strand
52
+ */
53
+ wakeStrand(strandId: string): Promise<void>;
54
+ private scheduleIdleTransition;
55
+ private handleIdleTimeout;
56
+ private scheduleHibernateTransition;
57
+ private handleHibernateTimeout;
58
+ private scheduleCheckIn;
59
+ private clearTimer;
60
+ private clearTimers;
61
+ /**
62
+ * Get the current status of hibernation tracking
63
+ */
64
+ getStatus(): {
65
+ enabled: boolean;
66
+ trackedStrands: number;
67
+ };
68
+ }
@@ -0,0 +1,212 @@
1
+ import debug from 'debug';
2
+ import { HIBERNATION_TIMEOUTS } from './types.js';
3
+ const log = debug('sereus:cadre:hibernation');
4
+ /**
5
+ * Manages strand hibernation state transitions based on activity.
6
+ *
7
+ * State machine:
8
+ * active → idle (after idleTimeout with no activity)
9
+ * idle → hibernating (after hibernateTimeout with no activity)
10
+ * idle → active (on activity)
11
+ * hibernating → active (on wake signal or check-in with pending activity)
12
+ */
13
+ export class HibernationManager {
14
+ constructor(config, callbacks) {
15
+ this.timers = new Map();
16
+ this.checkInTimers = new Map();
17
+ this.running = false;
18
+ this.config = config;
19
+ this.callbacks = callbacks;
20
+ log('HibernationManager created, enabled=%s', config.enabled);
21
+ }
22
+ /**
23
+ * Get effective timeouts for a latency hint
24
+ */
25
+ getTimeouts(hint) {
26
+ const defaults = HIBERNATION_TIMEOUTS[hint];
27
+ const custom = this.config.customTimeouts?.[hint];
28
+ if (!custom)
29
+ return defaults;
30
+ return {
31
+ idleTimeout: custom.idleTimeout ?? defaults.idleTimeout,
32
+ hibernateTimeout: custom.hibernateTimeout ?? defaults.hibernateTimeout,
33
+ checkInInterval: custom.checkInInterval ?? defaults.checkInInterval
34
+ };
35
+ }
36
+ /**
37
+ * Start managing hibernation for all strands
38
+ */
39
+ start() {
40
+ if (this.running)
41
+ return;
42
+ this.running = true;
43
+ log('HibernationManager started');
44
+ }
45
+ /**
46
+ * Stop managing hibernation
47
+ */
48
+ stop() {
49
+ if (!this.running)
50
+ return;
51
+ this.running = false;
52
+ // Clear all timers
53
+ for (const timer of this.timers.values()) {
54
+ clearTimeout(timer);
55
+ }
56
+ this.timers.clear();
57
+ for (const timer of this.checkInTimers.values()) {
58
+ clearInterval(timer);
59
+ }
60
+ this.checkInTimers.clear();
61
+ log('HibernationManager stopped');
62
+ }
63
+ /**
64
+ * Register a strand for hibernation management
65
+ */
66
+ trackStrand(instance) {
67
+ if (!this.config.enabled || !this.running)
68
+ return;
69
+ const { strandId, latencyHint } = instance;
70
+ const timeouts = this.getTimeouts(latencyHint);
71
+ // Don't track strands that never hibernate
72
+ if (timeouts.idleTimeout === Infinity) {
73
+ log('Strand %s has realtime latency hint - no hibernation', strandId);
74
+ return;
75
+ }
76
+ log('Tracking strand %s for hibernation (hint=%s)', strandId, latencyHint);
77
+ this.scheduleIdleTransition(instance);
78
+ }
79
+ /**
80
+ * Untrack a strand from hibernation management
81
+ */
82
+ untrackStrand(strandId) {
83
+ this.clearTimers(strandId);
84
+ log('Untracked strand %s from hibernation', strandId);
85
+ }
86
+ /**
87
+ * Record activity on a strand - resets idle timer
88
+ */
89
+ recordActivity(instance) {
90
+ if (!this.config.enabled || !this.running)
91
+ return;
92
+ const { strandId, status, latencyHint } = instance;
93
+ instance.lastActivity = new Date();
94
+ // If idle or hibernating, wake up
95
+ if (status === 'idle' || status === 'hibernating') {
96
+ log('Activity on %s strand %s - waking', status, strandId);
97
+ this.clearTimers(strandId);
98
+ void this.callbacks.onWake(strandId);
99
+ }
100
+ // Reschedule idle transition if active
101
+ if (status === 'active') {
102
+ const timeouts = this.getTimeouts(latencyHint);
103
+ if (timeouts.idleTimeout !== Infinity) {
104
+ this.scheduleIdleTransition(instance);
105
+ }
106
+ }
107
+ }
108
+ /**
109
+ * Force wake a hibernating strand
110
+ */
111
+ async wakeStrand(strandId) {
112
+ this.clearTimers(strandId);
113
+ await this.callbacks.onWake(strandId);
114
+ }
115
+ scheduleIdleTransition(instance) {
116
+ const { strandId, latencyHint } = instance;
117
+ const timeouts = this.getTimeouts(latencyHint);
118
+ // Clear existing timer
119
+ this.clearTimer(strandId);
120
+ // Schedule idle transition
121
+ const timer = setTimeout(() => {
122
+ this.handleIdleTimeout(instance);
123
+ }, timeouts.idleTimeout);
124
+ this.timers.set(strandId, timer);
125
+ }
126
+ handleIdleTimeout(instance) {
127
+ const { strandId, latencyHint } = instance;
128
+ if (!this.running)
129
+ return;
130
+ log('Idle timeout for strand %s', strandId);
131
+ // Transition to idle
132
+ void this.callbacks.onIdle(strandId).then(() => {
133
+ // Schedule hibernate transition
134
+ const timeouts = this.getTimeouts(latencyHint);
135
+ if (timeouts.hibernateTimeout !== Infinity) {
136
+ this.scheduleHibernateTransition(instance);
137
+ }
138
+ });
139
+ }
140
+ scheduleHibernateTransition(instance) {
141
+ const { strandId, latencyHint } = instance;
142
+ const timeouts = this.getTimeouts(latencyHint);
143
+ // Clear existing timer
144
+ this.clearTimer(strandId);
145
+ // Schedule hibernate transition
146
+ const timer = setTimeout(() => {
147
+ this.handleHibernateTimeout(instance);
148
+ }, timeouts.hibernateTimeout);
149
+ this.timers.set(strandId, timer);
150
+ }
151
+ handleHibernateTimeout(instance) {
152
+ const { strandId, latencyHint } = instance;
153
+ if (!this.running)
154
+ return;
155
+ log('Hibernate timeout for strand %s', strandId);
156
+ // Transition to hibernating
157
+ void this.callbacks.onHibernate(strandId).then(() => {
158
+ // Schedule periodic check-ins
159
+ const timeouts = this.getTimeouts(latencyHint);
160
+ if (timeouts.checkInInterval !== Infinity) {
161
+ this.scheduleCheckIn(instance);
162
+ }
163
+ });
164
+ }
165
+ scheduleCheckIn(instance) {
166
+ const { strandId, latencyHint } = instance;
167
+ const timeouts = this.getTimeouts(latencyHint);
168
+ // Clear existing check-in timer
169
+ const existing = this.checkInTimers.get(strandId);
170
+ if (existing) {
171
+ clearInterval(existing);
172
+ }
173
+ // Schedule periodic check-ins
174
+ const timer = setInterval(() => {
175
+ if (!this.running) {
176
+ clearInterval(timer);
177
+ return;
178
+ }
179
+ log('Check-in for hibernating strand %s', strandId);
180
+ instance.nextCheckIn = new Date(Date.now() + timeouts.checkInInterval);
181
+ // In a real implementation, this would query the cohort for pending activity
182
+ // For now, we just update the nextCheckIn timestamp
183
+ }, timeouts.checkInInterval);
184
+ this.checkInTimers.set(strandId, timer);
185
+ instance.nextCheckIn = new Date(Date.now() + timeouts.checkInInterval);
186
+ }
187
+ clearTimer(strandId) {
188
+ const timer = this.timers.get(strandId);
189
+ if (timer) {
190
+ clearTimeout(timer);
191
+ this.timers.delete(strandId);
192
+ }
193
+ }
194
+ clearTimers(strandId) {
195
+ this.clearTimer(strandId);
196
+ const checkInTimer = this.checkInTimers.get(strandId);
197
+ if (checkInTimer) {
198
+ clearInterval(checkInTimer);
199
+ this.checkInTimers.delete(strandId);
200
+ }
201
+ }
202
+ /**
203
+ * Get the current status of hibernation tracking
204
+ */
205
+ getStatus() {
206
+ return {
207
+ enabled: this.config.enabled && this.running,
208
+ trackedStrands: this.timers.size + this.checkInTimers.size
209
+ };
210
+ }
211
+ }
212
+ //# sourceMappingURL=hibernation-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hibernation-manager.js","sourceRoot":"","sources":["../src/hibernation-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export * from './types.js';
2
+ export { CadreNode } from './cadre-node.js';
3
+ export { ControlDatabase, type ControlDatabaseConfig } from './control-database.js';
4
+ export { StrandDatabase, type StrandDatabaseConfig } from './strand-database.js';
5
+ export { StrandWatcher, type StrandWatcherCallbacks, type StrandQueryable, type SAppIdLookup, type StrandRowWithApp } from './strand-watcher.js';
6
+ export { StrandInstanceManager, type StartStrandConfig, getStrandStoragePath } from './strand-instance-manager.js';
7
+ export { HibernationManager, type HibernationCallbacks } from './hibernation-manager.js';
8
+ export { ArachnodeStub, createArachnodeStub, type RingConfig } from './arachnode-stub.js';
9
+ export { EnrollmentService, type MemberVerifier, type MemberRegistry } from './enrollment.js';
10
+ export { StrandSolicitationService, type DisclosureValidator, type FormationUsageRecorder, type StrandProvisioner, type FormationSigner, type StrandSolicitationServiceOptions } from './strand-solicitation.js';
11
+ export { SeedBootstrapService, SEED_PROTOCOL, type SeedBootstrapConfig, type SeedEventCallbacks } from './seed-bootstrap.js';
12
+ export { StrandFormationManager, createStrandFormationManager, type StrandFormationManagerConfig, type StrandFormationManagerOptions } from './strand-formation-manager.js';
package/dist/index.js ADDED
@@ -0,0 +1,24 @@
1
+ // Core types
2
+ export * from './types.js';
3
+ // Main CadreNode class
4
+ export { CadreNode } from './cadre-node.js';
5
+ // Control database
6
+ export { ControlDatabase } from './control-database.js';
7
+ // Strand database
8
+ export { StrandDatabase } from './strand-database.js';
9
+ // Strand management
10
+ export { StrandWatcher } from './strand-watcher.js';
11
+ export { StrandInstanceManager, getStrandStoragePath } from './strand-instance-manager.js';
12
+ // Hibernation
13
+ export { HibernationManager } from './hibernation-manager.js';
14
+ // Arachnode (stub)
15
+ export { ArachnodeStub, createArachnodeStub } from './arachnode-stub.js';
16
+ // Enrollment
17
+ export { EnrollmentService } from './enrollment.js';
18
+ // Strand Solicitation
19
+ export { StrandSolicitationService } from './strand-solicitation.js';
20
+ // Seed Bootstrap
21
+ export { SeedBootstrapService, SEED_PROTOCOL } from './seed-bootstrap.js';
22
+ // Strand Formation (strand-proto integration)
23
+ export { StrandFormationManager, createStrandFormationManager } from './strand-formation-manager.js';
24
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,aAAa;AACb,cAAc,YAAY,CAAC;AAE3B,uBAAuB;AACvB,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,mBAAmB;AACnB,OAAO,EAAE,eAAe,EAA8B,MAAM,uBAAuB,CAAC;AAEpF,kBAAkB;AAClB,OAAO,EAAE,cAAc,EAA6B,MAAM,sBAAsB,CAAC;AAEjF,oBAAoB;AACpB,OAAO,EACL,aAAa,EAKd,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,qBAAqB,EAErB,oBAAoB,EACrB,MAAM,8BAA8B,CAAC;AAEtC,cAAc;AACd,OAAO,EACL,kBAAkB,EAEnB,MAAM,0BAA0B,CAAC;AAElC,mBAAmB;AACnB,OAAO,EACL,aAAa,EACb,mBAAmB,EAEpB,MAAM,qBAAqB,CAAC;AAE7B,aAAa;AACb,OAAO,EACL,iBAAiB,EAGlB,MAAM,iBAAiB,CAAC;AAEzB,sBAAsB;AACtB,OAAO,EACL,yBAAyB,EAM1B,MAAM,0BAA0B,CAAC;AAElC,iBAAiB;AACjB,OAAO,EACL,oBAAoB,EACpB,aAAa,EAGd,MAAM,qBAAqB,CAAC;AAE7B,8CAA8C;AAC9C,OAAO,EACL,sBAAsB,EACtB,4BAA4B,EAG7B,MAAM,+BAA+B,CAAC"}
@@ -0,0 +1,164 @@
1
+ import type { Libp2p } from '@libp2p/interface';
2
+ import type { ControlNetworkSeed, SeedAckMessage, AuthorizePeerOptions, ApplySeedResult, AddDroneOptions, AddPhoneOptions, DroneInitResult, InviteResult, CadreInvite } from './types.js';
3
+ import type { ControlDatabase } from './control-database.js';
4
+ /** Protocol ID for seed delivery */
5
+ export declare const SEED_PROTOCOL = "/sereus/seed/1.0.0";
6
+ /**
7
+ * Configuration for the SeedBootstrapService
8
+ */
9
+ export interface SeedBootstrapConfig {
10
+ /** Party ID for this cadre */
11
+ partyId: string;
12
+ /** Authority private key for signing seeds and peer authorizations (base64url) */
13
+ authorityPrivateKey?: string;
14
+ /** Authority public key (base64url) - derived from private key if not provided */
15
+ authorityPublicKey?: string;
16
+ }
17
+ /**
18
+ * Event callbacks for seed-related events
19
+ */
20
+ export interface SeedEventCallbacks {
21
+ /** Called when a seed is received via the protocol */
22
+ onSeedReceived?: (partyId: string, peerId: string) => void;
23
+ /** Called when a seed is successfully applied */
24
+ onSeedApplied?: (partyId: string, peersAdded: number) => void;
25
+ /** Called when seed application fails */
26
+ onSeedError?: (partyId: string, error: string) => void;
27
+ }
28
+ /**
29
+ * SeedBootstrapService handles control network seed generation and delivery.
30
+ *
31
+ * Seeds solve the cold-start problem: new nodes need control data to validate
32
+ * connections, but can't get data without connecting first. Seeds pre-populate
33
+ * the new node's cache with peer information and optionally transactions.
34
+ */
35
+ export declare class SeedBootstrapService {
36
+ private readonly config;
37
+ private libp2pNode;
38
+ private controlDatabase;
39
+ private readonly authorityPublicKey;
40
+ private eventCallbacks;
41
+ constructor(config: SeedBootstrapConfig);
42
+ /**
43
+ * Set event callbacks for seed-related events.
44
+ * Used by CadreNode to emit events.
45
+ */
46
+ setEventCallbacks(callbacks: SeedEventCallbacks): void;
47
+ /**
48
+ * Initialize the service with libp2p node and control database
49
+ */
50
+ initialize(libp2pNode: Libp2p, controlDatabase: ControlDatabase): void;
51
+ /**
52
+ * Authorize a new peer to join the cadre.
53
+ * Signs the peer ID with the authority key and inserts into CadrePeer table.
54
+ */
55
+ authorizePeer(options: AuthorizePeerOptions): Promise<void>;
56
+ /**
57
+ * Create a seed from the current control network state.
58
+ * The seed contains peer information and is signed by an authority.
59
+ */
60
+ createSeed(): Promise<ControlNetworkSeed>;
61
+ /**
62
+ * Apply a seed to populate the peer cache and enable connections.
63
+ * Validates the seed signature before applying.
64
+ */
65
+ applySeed(seed: ControlNetworkSeed): Promise<ApplySeedResult>;
66
+ /**
67
+ * Encode a seed for out-of-band delivery (e.g., QR code, copy/paste).
68
+ */
69
+ encodeSeed(seed: ControlNetworkSeed): string;
70
+ /**
71
+ * Decode a seed from base64url encoding.
72
+ */
73
+ decodeSeed(encoded: string): ControlNetworkSeed;
74
+ /**
75
+ * Deliver a seed directly to a peer via the /sereus/seed/1.0.0 protocol.
76
+ */
77
+ deliverSeed(targetMultiaddr: string, seed: ControlNetworkSeed): Promise<SeedAckMessage>;
78
+ /**
79
+ * Get this node's circuit relay address for inclusion in seeds.
80
+ * Returns null if no relay address is available.
81
+ */
82
+ getRelayAddress(): Promise<string | null>;
83
+ /**
84
+ * Validate a seed's signature.
85
+ */
86
+ validateSeedSignature(seed: ControlNetworkSeed): boolean;
87
+ /**
88
+ * Query peers from the control database.
89
+ */
90
+ private queryPeers;
91
+ /**
92
+ * Register the seed protocol handler.
93
+ */
94
+ private registerProtocolHandler;
95
+ /**
96
+ * Shutdown the service.
97
+ */
98
+ shutdown(): Promise<void>;
99
+ /**
100
+ * Add a drone to the cadre (phone/server adds provider-hosted node).
101
+ *
102
+ * Use this when you've spawned a drone via provider API and received its
103
+ * peer ID and multiaddrs. This method:
104
+ * 1. Authorizes the drone peer
105
+ * 2. Creates a seed including all current peers
106
+ * 3. Returns the seed for sending to provider API
107
+ *
108
+ * @param options - Drone peer info from provider API
109
+ * @returns Seed and encoded seed for drone initialization
110
+ */
111
+ addDrone(options: AddDroneOptions): Promise<DroneInitResult>;
112
+ /**
113
+ * Create an invite for a phone to join the cadre.
114
+ *
115
+ * Use this when a server (public IP) wants to invite a phone (NAT'd).
116
+ * The invite is shared out-of-band (QR code, link, etc.) and contains
117
+ * the server's address so the phone can dial in.
118
+ *
119
+ * @param token - Optional invite token for validation
120
+ * @param expiresIn - Optional expiration time in milliseconds
121
+ * @returns Invite and encoded invite for sharing
122
+ */
123
+ createInvite(token?: string, expiresIn?: number): Promise<InviteResult>;
124
+ /**
125
+ * Accept a phone connection using an invite.
126
+ *
127
+ * Use this when a phone dials in with an invite token. This method:
128
+ * 1. Validates the token if provided
129
+ * 2. Authorizes the phone peer
130
+ *
131
+ * After this, the phone can sync the control database normally.
132
+ *
133
+ * @param options - Phone peer info and invite token
134
+ * @param issuedInvite - The original invite for validation
135
+ */
136
+ acceptPhone(options: AddPhoneOptions, issuedInvite?: CadreInvite): Promise<void>;
137
+ /**
138
+ * Add a phone to the cadre with relay support.
139
+ *
140
+ * Use this when both nodes are NAT'd (phone-to-phone). This method:
141
+ * 1. Authorizes the new phone peer
142
+ * 2. Creates a seed with relay addresses for dialing
143
+ *
144
+ * @param phonePeerId - Peer ID of the new phone
145
+ * @returns Seed with relay addresses for out-of-band delivery
146
+ */
147
+ addPhoneWithRelay(phonePeerId: string): Promise<DroneInitResult>;
148
+ /**
149
+ * Encode an invite for out-of-band delivery.
150
+ */
151
+ encodeInvite(invite: CadreInvite): string;
152
+ /**
153
+ * Decode an invite from base64url encoding.
154
+ */
155
+ decodeInvite(encoded: string): CadreInvite;
156
+ /**
157
+ * Dial an authority from an invite.
158
+ * Use this on a phone after receiving an invite to connect to the authority.
159
+ *
160
+ * @param invite - The invite received out-of-band
161
+ * @returns Connection to the authority
162
+ */
163
+ dialInvite(invite: CadreInvite): Promise<void>;
164
+ }