@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.
Files changed (268) hide show
  1. package/README.md +4 -3
  2. package/dist/bootstrap-peer-store-file.js +1 -1
  3. package/dist/bootstrap-peer-store.d.ts +1 -1
  4. package/dist/bootstrap-peer-store.js +4 -4
  5. package/dist/cadre-invite-protocol.d.ts +81 -142
  6. package/dist/cadre-invite-protocol.js +168 -458
  7. package/dist/cadre-invite-protocol.js.map +1 -1
  8. package/dist/cadre-join-request.d.ts +15 -2
  9. package/dist/cadre-join-request.js +22 -3
  10. package/dist/cadre-join-request.js.map +1 -1
  11. package/dist/cadre-node.d.ts +1089 -475
  12. package/dist/cadre-node.js +2170 -1037
  13. package/dist/cadre-node.js.map +1 -1
  14. package/dist/control-authorization.d.ts +36 -14
  15. package/dist/control-authorization.js +20 -3
  16. package/dist/control-authorization.js.map +1 -1
  17. package/dist/control-cohort.d.ts +88 -32
  18. package/dist/control-cohort.js +91 -33
  19. package/dist/control-cohort.js.map +1 -1
  20. package/dist/control-database.d.ts +856 -318
  21. package/dist/control-database.js +1422 -701
  22. package/dist/control-database.js.map +1 -1
  23. package/dist/control-formation-recorder.d.ts +46 -43
  24. package/dist/control-formation-recorder.js +77 -78
  25. package/dist/control-formation-recorder.js.map +1 -1
  26. package/dist/control-protocol-guard.d.ts +11 -4
  27. package/dist/control-protocol-guard.js +20 -5
  28. package/dist/control-protocol-guard.js.map +1 -1
  29. package/dist/control-schema-version.d.ts +97 -0
  30. package/dist/control-schema-version.js +225 -0
  31. package/dist/control-schema-version.js.map +1 -0
  32. package/dist/control-schema.d.ts +45 -5
  33. package/dist/control-schema.js +262 -78
  34. package/dist/control-schema.js.map +1 -1
  35. package/dist/control-write-retry.d.ts +45 -10
  36. package/dist/control-write-retry.js +92 -22
  37. package/dist/control-write-retry.js.map +1 -1
  38. package/dist/delegate-admission.d.ts +13 -0
  39. package/dist/delegate-admission.js +27 -0
  40. package/dist/delegate-admission.js.map +1 -1
  41. package/dist/ed25519-key.d.ts +10 -7
  42. package/dist/ed25519-key.js +23 -20
  43. package/dist/ed25519-key.js.map +1 -1
  44. package/dist/edge-node/config.d.ts +122 -0
  45. package/dist/edge-node/config.js +199 -0
  46. package/dist/edge-node/config.js.map +1 -0
  47. package/dist/edge-node/dissolve.d.ts +95 -0
  48. package/dist/edge-node/dissolve.js +184 -0
  49. package/dist/edge-node/dissolve.js.map +1 -0
  50. package/dist/edge-node/edge-join.d.ts +44 -0
  51. package/dist/edge-node/edge-join.js +227 -0
  52. package/dist/edge-node/edge-join.js.map +1 -0
  53. package/dist/edge-node/edge-node.d.ts +295 -0
  54. package/dist/edge-node/edge-node.js +704 -0
  55. package/dist/edge-node/edge-node.js.map +1 -0
  56. package/dist/edge-node/index.d.ts +18 -0
  57. package/dist/edge-node/index.js +18 -0
  58. package/dist/edge-node/index.js.map +1 -0
  59. package/dist/edge-node/join-credential.d.ts +11 -0
  60. package/dist/edge-node/join-credential.js +11 -0
  61. package/dist/edge-node/join-credential.js.map +1 -0
  62. package/dist/edge-node/lazy-raw-storage.d.ts +40 -0
  63. package/dist/edge-node/lazy-raw-storage.js +134 -0
  64. package/dist/edge-node/lazy-raw-storage.js.map +1 -0
  65. package/dist/edge-node/node-local.d.ts +60 -0
  66. package/dist/edge-node/node-local.js +58 -0
  67. package/dist/edge-node/node-local.js.map +1 -0
  68. package/dist/edge-node/options.d.ts +83 -0
  69. package/dist/edge-node/options.js +110 -0
  70. package/dist/edge-node/options.js.map +1 -0
  71. package/dist/edge-node/owner-grant.d.ts +41 -0
  72. package/dist/edge-node/owner-grant.js +38 -0
  73. package/dist/edge-node/owner-grant.js.map +1 -0
  74. package/dist/edge-node/platform.d.ts +140 -0
  75. package/dist/edge-node/platform.js +12 -0
  76. package/dist/edge-node/platform.js.map +1 -0
  77. package/dist/edge-node/strand-move.d.ts +115 -0
  78. package/dist/edge-node/strand-move.js +223 -0
  79. package/dist/edge-node/strand-move.js.map +1 -0
  80. package/dist/edge-node/strands.d.ts +28 -0
  81. package/dist/edge-node/strands.js +60 -0
  82. package/dist/edge-node/strands.js.map +1 -0
  83. package/dist/enrolled-machine-store.d.ts +3 -3
  84. package/dist/enrolled-machine-store.js +3 -3
  85. package/dist/formation-token.d.ts +48 -0
  86. package/dist/formation-token.js +26 -0
  87. package/dist/formation-token.js.map +1 -0
  88. package/dist/index.d.ts +27 -17
  89. package/dist/index.js +39 -17
  90. package/dist/index.js.map +1 -1
  91. package/dist/joined-strand-store.d.ts +29 -12
  92. package/dist/joined-strand-store.js +66 -27
  93. package/dist/joined-strand-store.js.map +1 -1
  94. package/dist/key-store.d.ts +9 -4
  95. package/dist/key-store.js +9 -4
  96. package/dist/key-store.js.map +1 -1
  97. package/dist/link-budget.d.ts +9 -7
  98. package/dist/link-budget.js +9 -7
  99. package/dist/link-budget.js.map +1 -1
  100. package/dist/machine-removal.d.ts +19 -39
  101. package/dist/machine-removal.js +24 -98
  102. package/dist/machine-removal.js.map +1 -1
  103. package/dist/member-redemption.d.ts +256 -0
  104. package/dist/member-redemption.js +490 -0
  105. package/dist/member-redemption.js.map +1 -0
  106. package/dist/membership-view.d.ts +91 -0
  107. package/dist/membership-view.js +110 -0
  108. package/dist/membership-view.js.map +1 -0
  109. package/dist/owner-anchor-sync.d.ts +4 -4
  110. package/dist/owner-anchor-sync.js +16 -15
  111. package/dist/owner-anchor-sync.js.map +1 -1
  112. package/dist/owner-grant-protocol.d.ts +251 -0
  113. package/dist/owner-grant-protocol.js +344 -0
  114. package/dist/owner-grant-protocol.js.map +1 -0
  115. package/dist/owner-key-export.d.ts +70 -0
  116. package/dist/owner-key-export.js +279 -0
  117. package/dist/owner-key-export.js.map +1 -0
  118. package/dist/owner-key-flows.d.ts +55 -0
  119. package/dist/owner-key-flows.js +60 -0
  120. package/dist/owner-key-flows.js.map +1 -0
  121. package/dist/owner-key-store.d.ts +31 -0
  122. package/dist/owner-key-store.js +81 -0
  123. package/dist/owner-key-store.js.map +1 -0
  124. package/dist/owner-keys.d.ts +78 -0
  125. package/dist/owner-keys.js +133 -0
  126. package/dist/owner-keys.js.map +1 -0
  127. package/dist/owner-signer.d.ts +54 -0
  128. package/dist/owner-signer.js +51 -0
  129. package/dist/owner-signer.js.map +1 -0
  130. package/dist/peer-addr-book.d.ts +10 -1
  131. package/dist/peer-addr-book.js +4 -3
  132. package/dist/peer-addr-book.js.map +1 -1
  133. package/dist/peer-authorization.d.ts +83 -18
  134. package/dist/peer-authorization.js +123 -53
  135. package/dist/peer-authorization.js.map +1 -1
  136. package/dist/peer-join-backfill.d.ts +89 -20
  137. package/dist/peer-join-backfill.js +265 -108
  138. package/dist/peer-join-backfill.js.map +1 -1
  139. package/dist/pending-join-runner.d.ts +48 -18
  140. package/dist/pending-join-runner.js +74 -56
  141. package/dist/pending-join-runner.js.map +1 -1
  142. package/dist/provider/rent-node.js +1 -1
  143. package/dist/provider/rent-node.js.map +1 -1
  144. package/dist/seed-bootstrap.d.ts +162 -133
  145. package/dist/seed-bootstrap.js +300 -283
  146. package/dist/seed-bootstrap.js.map +1 -1
  147. package/dist/seed-trust-policy.js +4 -4
  148. package/dist/strand-addr-protocol.d.ts +4 -1
  149. package/dist/strand-addr-protocol.js +8 -2
  150. package/dist/strand-addr-protocol.js.map +1 -1
  151. package/dist/strand-cohort.d.ts +3 -0
  152. package/dist/strand-cohort.js.map +1 -1
  153. package/dist/strand-database.d.ts +24 -2
  154. package/dist/strand-database.js +29 -6
  155. package/dist/strand-database.js.map +1 -1
  156. package/dist/strand-first-sync-gate.d.ts +176 -88
  157. package/dist/strand-first-sync-gate.js +288 -121
  158. package/dist/strand-first-sync-gate.js.map +1 -1
  159. package/dist/strand-formation-deadlines.d.ts +9 -9
  160. package/dist/strand-formation-deadlines.js +9 -9
  161. package/dist/strand-formation-manager.d.ts +23 -17
  162. package/dist/strand-formation-manager.js +46 -44
  163. package/dist/strand-formation-manager.js.map +1 -1
  164. package/dist/strand-formation-protocol.d.ts +5 -8
  165. package/dist/strand-formation-protocol.js +101 -16
  166. package/dist/strand-formation-protocol.js.map +1 -1
  167. package/dist/strand-instance-manager.d.ts +27 -18
  168. package/dist/strand-instance-manager.js +119 -50
  169. package/dist/strand-instance-manager.js.map +1 -1
  170. package/dist/strand-membership-reconciler.d.ts +16 -13
  171. package/dist/strand-membership-reconciler.js +30 -22
  172. package/dist/strand-membership-reconciler.js.map +1 -1
  173. package/dist/strand-membership-writer.d.ts +45 -22
  174. package/dist/strand-membership-writer.js +226 -131
  175. package/dist/strand-membership-writer.js.map +1 -1
  176. package/dist/strand-move.d.ts +6 -5
  177. package/dist/strand-move.js +36 -32
  178. package/dist/strand-move.js.map +1 -1
  179. package/dist/strand-peer-redial.js +2 -3
  180. package/dist/strand-peer-redial.js.map +1 -1
  181. package/dist/strand-revocation-enforcer.d.ts +134 -60
  182. package/dist/strand-revocation-enforcer.js +144 -71
  183. package/dist/strand-revocation-enforcer.js.map +1 -1
  184. package/dist/strand-solicitation.d.ts +50 -39
  185. package/dist/strand-solicitation.js +10 -3
  186. package/dist/strand-solicitation.js.map +1 -1
  187. package/dist/strand-watcher.d.ts +80 -13
  188. package/dist/strand-watcher.js +152 -48
  189. package/dist/strand-watcher.js.map +1 -1
  190. package/dist/table-change-watch.d.ts +63 -0
  191. package/dist/table-change-watch.js +209 -0
  192. package/dist/table-change-watch.js.map +1 -0
  193. package/dist/timeout-scheduler.d.ts +4 -3
  194. package/dist/timeout-scheduler.js +4 -3
  195. package/dist/timeout-scheduler.js.map +1 -1
  196. package/dist/types.d.ts +374 -150
  197. package/dist/types.js +4 -4
  198. package/dist/types.js.map +1 -1
  199. package/package.json +17 -8
  200. package/src/bootstrap-peer-store-file.ts +44 -44
  201. package/src/bootstrap-peer-store.ts +214 -214
  202. package/src/cadre-invite-protocol.ts +740 -1052
  203. package/src/cadre-join-request.ts +24 -3
  204. package/src/cadre-node.ts +2402 -1079
  205. package/src/control-authorization.ts +47 -14
  206. package/src/control-cohort.ts +204 -128
  207. package/src/control-database.ts +1749 -820
  208. package/src/control-formation-recorder.ts +359 -353
  209. package/src/control-protocol-guard.ts +23 -6
  210. package/src/control-schema-version.ts +301 -0
  211. package/src/control-schema.ts +273 -78
  212. package/src/control-write-retry.ts +641 -567
  213. package/src/delegate-admission.ts +351 -314
  214. package/src/ed25519-key.ts +174 -171
  215. package/src/edge-node/config.ts +277 -0
  216. package/src/edge-node/dissolve.ts +251 -0
  217. package/src/edge-node/edge-join.ts +319 -0
  218. package/src/edge-node/edge-node.ts +1045 -0
  219. package/src/edge-node/index.ts +59 -0
  220. package/src/edge-node/join-credential.ts +16 -0
  221. package/src/edge-node/lazy-raw-storage.ts +178 -0
  222. package/src/edge-node/node-local.ts +84 -0
  223. package/src/edge-node/options.ts +179 -0
  224. package/src/edge-node/owner-grant.ts +63 -0
  225. package/src/edge-node/platform.ts +151 -0
  226. package/src/edge-node/strand-move.ts +270 -0
  227. package/src/edge-node/strands.ts +72 -0
  228. package/src/enrolled-machine-store.ts +3 -3
  229. package/src/formation-token.ts +63 -0
  230. package/src/index.ts +899 -789
  231. package/src/joined-strand-store.ts +73 -28
  232. package/src/key-store.ts +10 -4
  233. package/src/link-budget.ts +9 -7
  234. package/src/machine-removal.ts +26 -111
  235. package/src/member-redemption.ts +649 -0
  236. package/src/membership-view.ts +144 -0
  237. package/src/owner-anchor-sync.ts +19 -18
  238. package/src/owner-grant-protocol.ts +547 -0
  239. package/src/owner-key-export.ts +348 -0
  240. package/src/owner-key-flows.ts +109 -0
  241. package/src/owner-key-store.ts +85 -0
  242. package/src/owner-keys.ts +178 -0
  243. package/src/owner-signer.ts +94 -0
  244. package/src/peer-addr-book.ts +4 -3
  245. package/src/peer-authorization.ts +558 -488
  246. package/src/peer-join-backfill.ts +971 -761
  247. package/src/pending-join-runner.ts +76 -53
  248. package/src/provider/rent-node.ts +1 -1
  249. package/src/seed-bootstrap.ts +343 -349
  250. package/src/seed-trust-policy.ts +4 -4
  251. package/src/strand-addr-protocol.ts +547 -538
  252. package/src/strand-cohort.ts +4 -0
  253. package/src/strand-database.ts +352 -319
  254. package/src/strand-first-sync-gate.ts +334 -133
  255. package/src/strand-formation-deadlines.ts +227 -227
  256. package/src/strand-formation-manager.ts +731 -725
  257. package/src/strand-formation-protocol.ts +122 -24
  258. package/src/strand-instance-manager.ts +2092 -2026
  259. package/src/strand-membership-reconciler.ts +33 -25
  260. package/src/strand-membership-writer.ts +2093 -1974
  261. package/src/strand-move.ts +50 -38
  262. package/src/strand-peer-redial.ts +2 -3
  263. package/src/strand-revocation-enforcer.ts +740 -654
  264. package/src/strand-solicitation.ts +61 -34
  265. package/src/strand-watcher.ts +175 -56
  266. package/src/table-change-watch.ts +285 -0
  267. package/src/timeout-scheduler.ts +29 -28
  268. package/src/types.ts +391 -152
@@ -1,9 +1,10 @@
1
1
  import type { Libp2p } from '@libp2p/interface';
2
2
  import { type PeerDialBudget } from './peer-dial.js';
3
- import type { ControlNetworkSeed, SeedPeer, SeedAckMessage, SeedDeliveryTarget, AuthorizePeerOptions, ApplySeedResult, AddDroneOptions, DroneInitResult, CadreInviteRow, PeerAddressRecord, DeviceTokenRecord, RevocationRow, RevocationLedgerOpenResult } from './types.js';
4
- import type { ControlDatabase, MachineRemovalWrites } from './control-database.js';
3
+ import type { ControlNetworkSeed, SeedPeer, SeedDialTarget, SeedAckMessage, SeedDeliveryTarget, AuthorizePeerOptions, ApplySeedResult, AddDroneOptions, DroneInitResult, CadreInviteRow, OwnerGrantRow, PeerAddressRecord, DeviceTokenRecord, RevocationRow, MachineRemovalResult } from './types.js';
4
+ import type { CadrePeerRetouchMode, CadrePeerRetouchOutcome, ControlDatabase } from './control-database.js';
5
5
  import { type SeedTrustPolicy } from './seed-trust-policy.js';
6
6
  import type { TrustedOwnerStore } from './trusted-owner-store.js';
7
+ import { type OwnerSign, type OwnerSigner } from './owner-signer.js';
7
8
  /** Protocol ID for seed delivery */
8
9
  export declare const SEED_PROTOCOL = "/sereus/seed/1.0.0";
9
10
  /**
@@ -32,6 +33,15 @@ export declare function canonicalSeedPayload(seed: Pick<ControlNetworkSeed, 'par
32
33
  * proof to one seed through this value) all name the same bytes.
33
34
  */
34
35
  export declare function seedDigest(seed: Pick<ControlNetworkSeed, 'partyId' | 'peers'>): string;
36
+ /**
37
+ * The peers `seed` nominates for dialing: its preferred peers (`SeedPeer.preferred`: the machine
38
+ * that minted it and every always-on machine) that have an address and are not `selfPeerId`.
39
+ *
40
+ * Self is dropped because `createSeed` projects every non-revoked CadrePeer row, so a preferred
41
+ * machine applying a seed minted after it joined finds itself in the list, and a dial of self
42
+ * always throws. An undefined `selfPeerId` matches nothing.
43
+ */
44
+ export declare function seedDialTargets(seed: ControlNetworkSeed, selfPeerId: string | undefined): SeedDialTarget[];
35
45
  /**
36
46
  * Merge a peer list's addresses into `node`'s peer store, so the node can dial them: the
37
47
  * seed's peers after its signature and trust checks, the dial hints a member returns on
@@ -47,10 +57,12 @@ export declare function mergeSeedPeers(node: Libp2p, peers: readonly SeedPeer[])
47
57
  export interface SeedBootstrapConfig {
48
58
  /** Party ID for this cadre */
49
59
  partyId: string;
50
- /** Owner private key for signing seeds and peer authorizations (base64url) */
51
- ownerPrivateKey?: string;
52
- /** Owner public key (base64url) - derived from private key if not provided */
53
- ownerPublicKey?: string;
60
+ /**
61
+ * The owner signer every seed and owner-signed write of this service goes through
62
+ * (`owner-signer.ts`). Unset for a listener-only service, which receives and applies seeds
63
+ * but refuses every owner write.
64
+ */
65
+ ownerSigner?: OwnerSigner;
54
66
  /**
55
67
  * Trust anchor for incoming seeds. Decides whether a signature-verified
56
68
  * `signerKey` should be trusted, against the receiver's anchored owner
@@ -107,7 +119,7 @@ export interface SeedBootstrapConfig {
107
119
  * sized for the forms that dial inside it. Delivery does not set `runOnLimitedConnection`,
108
120
  * so it does not use a limited relayed connection today; the relayed-dial count is the upper
109
121
  * bound on the dial it can use, the same choice `CadreNode.controlDialBudget` makes for every
110
- * address. It holds only link work because the receiver acks before its owner dials.
122
+ * address. It holds only link work because the receiver acks before it dials the seed's peers.
111
123
  *
112
124
  * NOTE: no transfer allowance — a seed is a peer list of a few KB, and `MAX_SEED_SIZE` (1 MiB)
113
125
  * is a defensive cap. If seeds ever grow toward that cap, add an allowance the way
@@ -116,7 +128,7 @@ export interface SeedBootstrapConfig {
116
128
  seedDeliverTimeoutMs?: number;
117
129
  /**
118
130
  * Time limits for each peer this service dials from a list of addresses —
119
- * {@link SeedBootstrapService.applySeed}'s owner dials and
131
+ * {@link SeedBootstrapService.applySeed}'s dials of the seed's preferred peers and
120
132
  * {@link SeedBootstrapService.deliverSeed}'s dial of a peer id with addresses — per
121
133
  * address and per peer (see `peer-dial.ts`). Defaults to {@link DEFAULT_PEER_DIAL_BUDGET}; a `CadreNode`
122
134
  * passes its `network.controlCohort` limits.
@@ -130,12 +142,13 @@ export interface SeedEventCallbacks {
130
142
  /** Called when a seed is received via the protocol */
131
143
  onSeedReceived?: (partyId: string, peerId: string) => void;
132
144
  /**
133
- * Called when a seed is successfully applied.
145
+ * Called when a seed delivered over the protocol has been verified, merged and
146
+ * acknowledged; the dials of its preferred peers follow, so this waits on no connection.
134
147
  *
135
148
  * `seed` is the applied seed itself: the inbound protocol handler applies it
136
149
  * INSIDE the service, so this callback is the only seam through which a
137
150
  * `CadreNode` sees a wire-delivered seed's contents — which it needs to
138
- * retain the owner-flagged peers as cold-start bootstrap dial targets.
151
+ * retain the preferred peers as cold-start bootstrap dial targets.
139
152
  */
140
153
  onSeedApplied?: (partyId: string, peersAdded: number, seed: ControlNetworkSeed) => void;
141
154
  /** Called when seed application fails */
@@ -152,7 +165,6 @@ export declare class SeedBootstrapService {
152
165
  private readonly config;
153
166
  private libp2pNode;
154
167
  private controlDatabase;
155
- private readonly ownerPublicKey;
156
168
  private readonly trustPolicy;
157
169
  private readonly seedReadTimeoutMs;
158
170
  private readonly maxConcurrentSeeds;
@@ -168,20 +180,21 @@ export declare class SeedBootstrapService {
168
180
  */
169
181
  setEventCallbacks(callbacks: SeedEventCallbacks): void;
170
182
  /**
171
- * Whether this service holds an owner private key, i.e. can produce the
172
- * owner signatures that gate `CadrePeer` / `DeviceToken` inserts, deletes,
173
- * and re-authorizations. A seed-listener-only service (`enableSeedListener`,
174
- * no owner key) returns false: it can receive/apply seeds but cannot author
175
- * or re-issue owner writes. Used by the write-while-alone re-replication
176
- * drain to skip owner work on a non-owner node.
183
+ * Whether this service holds an owner signer, i.e. can produce the owner signatures that
184
+ * gate `CadrePeer` / `DeviceToken` inserts, deletes, and re-authorizations. A
185
+ * seed-listener-only service (`enableSeedListener`, no signer) returns false: it can
186
+ * receive/apply seeds but cannot author or re-issue owner writes. Used by the
187
+ * write-while-alone re-replication drain to skip owner work on a non-owner node.
177
188
  */
178
189
  canAuthorize(): boolean;
190
+ /** The owner signer this service was built with, or null for a listener-only service. */
191
+ get ownerSigner(): OwnerSigner | null;
179
192
  /**
180
193
  * Initialize the service with libp2p node and control database.
181
194
  *
182
195
  * `registerHandler` (default true) gates registration of the shared inbound
183
196
  * `/sereus/seed/1.0.0` handler on `libp2pNode`. Persistent services
184
- * (`initializeSeedBootstrap`, `enableSeedListener`) own that handler and leave
197
+ * (`CadreNode.useOwnerSigner`, `enableSeedListener`) own that handler and leave
185
198
  * it on. The throwaway temp service CadreNode builds in `applySeed` passes
186
199
  * `false`: it only needs the stored `libp2pNode` / `controlDatabase` for
187
200
  * dialing and known-key lookup, and must NOT bind a discarded closure to the
@@ -207,8 +220,11 @@ export declare class SeedBootstrapService {
207
220
  * `UpdatedAt` but no self-signature (`Sig` null) — the owner cannot produce
208
221
  * the peer's self-signature, so the peer must self-publish (see
209
222
  * {@link CadreNode.registerSelf}) before the row resolves.
223
+ *
224
+ * @param sign - The signature function of an owner approval the caller already holds, so a
225
+ * multi-step action asks once; omitted, this write asks for its own approval.
210
226
  */
211
- authorizePeer(options: AuthorizePeerOptions): Promise<void>;
227
+ authorizePeer(options: AuthorizePeerOptions, sign?: OwnerSign): Promise<void>;
212
228
  /**
213
229
  * Owner-signed INSERT of this node's OWN self-signed address record.
214
230
  *
@@ -222,17 +238,16 @@ export declare class SeedBootstrapService {
222
238
  * in which case the row in the database is NOT this record and carries whatever
223
239
  * `Sig` that writer had, so the caller must self-update to publish its signature.
224
240
  */
225
- insertSelfPeerRecord(record: PeerAddressRecord): Promise<boolean>;
241
+ insertSelfPeerRecord(record: PeerAddressRecord, sign?: OwnerSign): Promise<boolean>;
226
242
  /**
227
- * Shared owner-signed `CadrePeer` INSERT — the row fields and the owner-key
243
+ * Shared owner-signed `CadrePeer` INSERT — the row fields and the owner-signer
228
244
  * precondition; the stamp mint, voucher signature, write lock, existence check and
229
245
  * membership notify are all {@link ControlDatabase.insertCadrePeer}'s (see there for
230
246
  * the anti-replay and insert-race rationale). No `CadrePeer` write may bypass that
231
247
  * method: the write is what admits the peer's traffic.
232
248
  *
233
- * The DB check precedes the owner-key check here, matching the order this method has
234
- * always surfaced them (the owner-key error used to come out of the signer, after the
235
- * DB check).
249
+ * The DB check precedes the owner-signer check here, matching the order this method has
250
+ * always surfaced them.
236
251
  *
237
252
  * @returns `true` when this call performed the INSERT, `false` when the row was
238
253
  * already seated by a concurrent writer. The loser needs to know: an authorize seats
@@ -257,7 +272,7 @@ export declare class SeedBootstrapService {
257
272
  * fresh signature — unaffected by the cleared row's retired stamp
258
273
  * (`DeviceToken.NotRevoked`).
259
274
  */
260
- insertSelfDeviceToken(record: DeviceTokenRecord): Promise<void>;
275
+ insertSelfDeviceToken(record: DeviceTokenRecord, sign?: OwnerSign): Promise<void>;
261
276
  /**
262
277
  * Owner-signed DELETE of a peer's `DeviceToken` row (logout / token
263
278
  * invalidation). The `DeviceToken.AuthorizedDelete` constraint validates an owner
@@ -276,44 +291,27 @@ export declare class SeedBootstrapService {
276
291
  * Both digests, the stamp read, and the transaction come from
277
292
  * {@link ControlDatabase.deleteDeviceToken} — one shared implementation across
278
293
  * `CadrePeer` / `DeviceToken` / `Strand` / `ValidationKey`. What stays here is the
279
- * owner-key precondition; a no-op on an already-absent row is the shared body's
294
+ * owner-signer precondition; a no-op on an already-absent row is the shared body's
280
295
  * behavior, and unlike {@link removePeer} nothing here rides on it.
281
296
  */
282
- deleteDeviceToken(peerId: string): Promise<void>;
283
- /**
284
- * Return the configured owner private key, or throw if none is set. The single
285
- * precondition gate for every owner-signed write. {@link removePeer} /
286
- * {@link reauthorizePeer} read the row's `StampId` from the DB BEFORE they sign, so
287
- * they call this up front — otherwise a keyless service would either surface the
288
- * wrong "Control database not initialized" error or, worse, silently no-op when the
289
- * target row is absent (the early `stampId === null` return) instead of rejecting.
290
- */
291
- private requireOwnerPrivateKey;
297
+ deleteDeviceToken(peerId: string, sign?: OwnerSign): Promise<void>;
292
298
  /**
293
- * The owner PUBLIC key that rides in every owner-signed write's context, non-null.
294
- *
295
- * The field is nullable because a read-only service carries no owner key at all, but the
296
- * constructor derives the public key whenever `ownerPrivateKey` is set — so gating on
297
- * {@link requireOwnerPrivateKey} first makes the pair inseparable and the second throw
298
- * unreachable. Callers that must reject a keyless service BEFORE any DB read use this as
299
- * their first line and get the owner-key precondition for free.
300
- */
301
- private requireOwnerPublicKey;
302
- /**
303
- * Sign a base64url digest with the owner key (ed25519). The single place the
304
- * owner private key is applied; callers pass the canonical domain-tagged digest for
305
- * the specific action ({@link deviceTokenAddDigest}), or the raw-bytes form via
306
- * {@link signMessageBytes}. Throws if no owner key is set.
299
+ * Return the configured owner signer, or throw if none is set. The single precondition
300
+ * gate for every owner-signed write. {@link removePeer} / {@link reauthorizePeer} read the
301
+ * row from the DB BEFORE they sign, so they call this up front — otherwise a signerless
302
+ * service would either surface the wrong "Control database not initialized" error or,
303
+ * worse, silently no-op when the target row is absent (their early absent return) instead
304
+ * of rejecting.
307
305
  */
308
- private signDigest;
306
+ private requireOwnerSigner;
307
+ /** The control database {@link initialize} attached, or a throw. */
308
+ private requireControlDatabase;
309
309
  /**
310
- * Adapt the control database's raw-bytes `signMessage` callback (every guarded delete
311
- * takes one) to {@link signDigest}'s base64url-string form. Both encodings hash to the
312
- * same signed bytes (`sign` decodes its base64url input), so a signature minted here
313
- * satisfies the same schema CHECK as one from the callers that sign the bytes directly — see
314
- * `control-revocation-replay.spec.ts`'s "raw-bytes and digest-string signers agree".
310
+ * Run `body` with an owner signature function: the caller's `sign` when it passes one (a
311
+ * `CadreNode` action already inside its approval), otherwise one approval of this service's
312
+ * signer for `action`, the plain-words description a prompting signer shows.
315
313
  */
316
- private signMessageBytes;
314
+ private withOwnerSign;
317
315
  /**
318
316
  * Remove a peer from the cadre by owner signature.
319
317
  *
@@ -336,64 +334,69 @@ export declare class SeedBootstrapService {
336
334
  * Both digests, the stamp read, the transaction, and the post-commit membership notify
337
335
  * come from {@link ControlDatabase.deleteCadrePeer} — one shared implementation across
338
336
  * `CadrePeer` / `DeviceToken` / `Strand` / `ValidationKey`. What stays here is the
339
- * owner-key precondition and the absent-row gate the notify depends on (below).
337
+ * owner-signer precondition and the absent-row gate the notify depends on (below).
340
338
  */
341
- removePeer(peerId: string): Promise<void>;
339
+ removePeer(peerId: string, sign?: OwnerSign): Promise<void>;
342
340
  /**
343
- * Seat `ownerPublicKey` as a further owner, signed by this service's owner key. The
341
+ * Seat `ownerPublicKey` as a further owner, signed by this service's owner signer. The
344
342
  * liveness check, the stamp, the signature and the membership notify are
345
- * {@link ControlDatabase.insertOwnerKeyVouched}'s; what stays here is the owner-key
343
+ * {@link ControlDatabase.insertOwnerKeyVouched}'s; what stays here is the owner-signer
346
344
  * precondition, checked before any read (see {@link removePeer}).
347
345
  *
346
+ * @param label - the user's name for the key, bound into the signature
347
+ * ({@link ControlDatabase.insertOwnerKey} has the rule).
348
348
  * @returns `true` when the row was seated, `false` when the key is already a live owner.
349
349
  */
350
- addOwner(ownerPublicKey: string): Promise<boolean>;
350
+ addOwner(ownerPublicKey: string, label?: string, sign?: OwnerSign): Promise<boolean>;
351
351
  /**
352
- * Remove `ownerPublicKey` from the owners, signed by this service's owner key: the delete
352
+ * Remove `ownerPublicKey` from the owners, signed by this service's owner signer: the delete
353
353
  * and its `Revocation` tombstone in one transaction. The by-name refusals (self-removal,
354
354
  * the last owner), the digests and the membership notify are
355
- * {@link ControlDatabase.deleteOwnerKey}'s; what stays here is the owner-key precondition,
355
+ * {@link ControlDatabase.deleteOwnerKey}'s; what stays here is the owner-signer precondition,
356
356
  * checked before any read (see {@link removePeer}).
357
357
  *
358
358
  * @returns `true` when the row was removed, `false` when the key is not a live owner here.
359
359
  */
360
- removeOwner(ownerPublicKey: string): Promise<boolean>;
360
+ removeOwner(ownerPublicKey: string, sign?: OwnerSign): Promise<boolean>;
361
361
  /**
362
- * Re-vouch another owner's row under this service's owner key, so it stands on a remaining
362
+ * Re-vouch another owner's row under this service's owner signer, so it stands on a remaining
363
363
  * owner's signature before the owner that added it is removed
364
- * ({@link ControlDatabase.revouchOwnerKey}; for `CadreNode.removeMachine` only). What stays
365
- * here is the owner-key precondition, checked before any read (see {@link removePeer}).
364
+ * ({@link ControlDatabase.revouchOwnerKey}; for `CadreNode.removeOwner` only). What stays
365
+ * here is the owner-signer precondition, checked before any read (see {@link removePeer}).
366
366
  *
367
367
  * @returns `true` when the row was re-vouched, `false` when the key is not a live owner here.
368
368
  */
369
- revouchOwner(ownerPublicKey: string): Promise<boolean>;
369
+ revouchOwner(ownerPublicKey: string, sign?: OwnerSign): Promise<boolean>;
370
370
  /**
371
- * Remove a machine completely, signed by this service's owner key: its `CadrePeer` row, its
372
- * `OwnerKey` row when `target.ownerKey` names one, its `DeviceToken` row, and the
373
- * withdrawal of every invitation in `target.inviteKeys`, all in one transaction
374
- * ({@link ControlDatabase.removeMachine}). What stays here is the owner-key precondition,
375
- * checked before any read (see {@link removePeer}).
371
+ * Remove a machine completely, signed by this service's owner signer: its `CadrePeer` row, its
372
+ * `DeviceToken` row, and the withdrawal of every invitation in `target.inviteKeys`, all in one
373
+ * transaction ({@link ControlDatabase.removeMachine}). What stays here is the owner-signer
374
+ * precondition, checked before any read (see {@link removePeer}).
376
375
  */
377
- removeMachine(target: Parameters<ControlDatabase['removeMachine']>[0]): Promise<MachineRemovalWrites>;
376
+ removeMachine(target: Parameters<ControlDatabase['removeMachine']>[0], sign?: OwnerSign): Promise<MachineRemovalResult>;
378
377
  /**
379
- * Owner "re-touch" of an existing `CadrePeer` membership row: bump `UpdatedAt` and
380
- * re-vouch the row so it is re-emitted as a fresh, broadcasting transaction. This is
381
- * the write-while-alone re-replication primitive (`control-write-ensure-replicated`):
382
- * a membership row that committed local-only (its block's cluster ≤1 at insert) is
383
- * pushed to the cohort once it grows.
378
+ * Owner "re-touch" of an existing `CadrePeer` membership row, in one of two modes
379
+ * ({@link CadrePeerRetouchMode}): `'rebroadcast'` bumps `UpdatedAt` and re-vouches the row so
380
+ * it is re-emitted as a fresh, broadcasting transaction — the write-while-alone re-replication
381
+ * primitive (`control-write-ensure-replicated`): a membership row that committed local-only
382
+ * (its block's cluster ≤1 at insert) is pushed to the cohort once it grows — and writes only
383
+ * while the machine has not self-published; `'revouch'` rebinds the voucher to this node's
384
+ * owner key, leaving `UpdatedAt` alone, whether or not the machine has self-published
385
+ * (`CadreNode.removeOwner`).
384
386
  *
385
- * The stamp read, the voucher signature, the write lock and the membership notify are
387
+ * The row read, the mode's decision, the stamp bump, the voucher signature, the write lock,
388
+ * the lost-update retry and the membership notify are
386
389
  * {@link ControlDatabase.reauthorizeCadrePeer}'s — including the caveat that it rebinds
387
- * `VouchOwner` to this node's owner key. What stays here is the owner-key precondition.
388
- *
389
- * A no-op (no throw, no notify) when the row does not exist.
390
+ * `VouchOwner` to this node's owner key. What stays here is the owner-signer precondition.
390
391
  *
391
392
  * @param peerId - the membership row to re-touch.
392
- * @param updatedAt - the strictly-increasing freshness stamp to write.
393
- * @throws if no owner private key is configured (a non-owner cannot
393
+ * @param mode - re-broadcast or re-vouch.
394
+ * @returns what was found and done ({@link CadrePeerRetouchOutcome}); an absent row, or a
395
+ * self-published one in `'rebroadcast'` mode, writes nothing and does not throw.
396
+ * @throws if no owner signer is configured (a non-owner cannot
394
397
  * re-sign another peer's row) or the control database is not initialized.
395
398
  */
396
- reauthorizePeer(peerId: string, updatedAt: number): Promise<void>;
399
+ reauthorizePeer(peerId: string, mode: CadrePeerRetouchMode, sign?: OwnerSign): Promise<CadrePeerRetouchOutcome>;
397
400
  /**
398
401
  * Owner re-issue of a batch of `Revocation` tombstones: bump each row's
399
402
  * `ReissuedAt` so the storage layer re-broadcasts a tombstone that committed
@@ -404,51 +407,68 @@ export declare class SeedBootstrapService {
404
407
  *
405
408
  * The signatures, the single transaction, and the strictly-monotonic
406
409
  * `reissuedAt` contract are {@link ControlDatabase.reissueRevocations}'s. What
407
- * stays here is the owner-key precondition.
410
+ * stays here is the owner-signer precondition.
408
411
  *
409
412
  * @returns how many tombstones were re-issued (`rows.length` on success).
410
- * @throws if no owner private key is configured or the control database is not
413
+ * @throws if no owner signer is configured or the control database is not
411
414
  * initialized.
412
415
  */
413
- reissueRevocations(rows: readonly RevocationRow[], reissuedAt: number): Promise<number>;
414
- /**
415
- * Owner filing of the singleton `Revocation` ledger marker, so the table is never a
416
- * never-written block that the storage layer re-consults on every read.
417
- *
418
- * The signature, the insert-if-absent guard and the `'already-open'` mapping are
419
- * {@link ControlDatabase.openRevocationLedger}'s. What stays here is the owner-key
420
- * precondition.
421
- *
422
- * @throws if no owner private key is configured or the control database is not
423
- * initialized.
424
- */
425
- openRevocationLedger(): Promise<RevocationLedgerOpenResult>;
416
+ reissueRevocations(rows: readonly RevocationRow[], reissuedAt: number, sign?: OwnerSign): Promise<number>;
426
417
  /**
427
418
  * Owner-signed INSERT of a `CadreInvite` row — an invitation any member machine can redeem
428
419
  * on this owner's behalf ({@link ControlDatabase.insertCadreInvite}). The keypair mint, the
429
420
  * expiry and use-count defaults, and the bundle the holder receives are
430
- * `CadreNode.createCadreInvitation`'s; what stays here is the owner-key precondition and
431
- * the signature, as {@link insertSelfDeviceToken} keeps them for device tokens.
421
+ * `CadreNode.createCadreInvitation`'s; what stays here is the owner-signer precondition and
422
+ * the approval, as {@link insertSelfDeviceToken} keeps them for device tokens.
432
423
  *
433
424
  * @returns the row as stored, which the invitation bundle carries verbatim.
434
- * @throws if no owner private key is configured or the control database is not initialized.
425
+ * @throws if no owner signer is configured or the control database is not initialized.
435
426
  */
436
- insertCadreInvite(invite: Parameters<ControlDatabase['insertCadreInvite']>[0]): Promise<CadreInviteRow>;
427
+ insertCadreInvite(invite: Parameters<ControlDatabase['insertCadreInvite']>[0], sign?: OwnerSign): Promise<CadreInviteRow>;
437
428
  /**
438
429
  * Owner-signed WITHDRAWAL of a `CadreInvite`: the `Revocation` tombstone over its stamp, with
439
430
  * the row kept ({@link ControlDatabase.withdrawCadreInvite}). What stays here is the
440
- * owner-key precondition.
431
+ * owner-signer precondition.
441
432
  *
442
433
  * @returns `true` when this call filed the tombstone, `false` when the row is absent here or
443
434
  * already withdrawn.
444
- * @throws if no owner private key is configured or the control database is not initialized.
435
+ * @throws if no owner signer is configured or the control database is not initialized.
436
+ */
437
+ withdrawCadreInvite(key: string, sign?: OwnerSign): Promise<boolean>;
438
+ /**
439
+ * Owner-signed INSERT of an `OwnerGrant` row — a grant of ownership any member machine can
440
+ * redeem on this owner's behalf ({@link ControlDatabase.insertOwnerGrant}). The keypair mint,
441
+ * the lifetime default and the bundle the holder receives are `CadreNode.createOwnerGrant`'s;
442
+ * what stays here is the owner-signer precondition and the approval, as for
443
+ * {@link insertCadreInvite}. The label is checked before the approval opens, so one the row
444
+ * would refuse never prompts the user.
445
+ *
446
+ * @returns the row as stored, which the grant bundle carries verbatim.
447
+ * @throws if no owner signer is configured, the control database is not initialized, or the label is too long.
445
448
  */
446
- withdrawCadreInvite(key: string): Promise<boolean>;
449
+ insertOwnerGrant(grant: Parameters<ControlDatabase['insertOwnerGrant']>[0], sign?: OwnerSign): Promise<OwnerGrantRow>;
450
+ /**
451
+ * Owner-signed WITHDRAWAL of an `OwnerGrant`: the `Revocation` tombstone over its stamp, with
452
+ * the row kept ({@link ControlDatabase.withdrawOwnerGrant}). What stays here is the
453
+ * owner-signer precondition.
454
+ *
455
+ * @returns `true` when this call filed the tombstone, `false` when the row is absent here or
456
+ * already withdrawn.
457
+ * @throws if no owner signer is configured or the control database is not initialized.
458
+ */
459
+ withdrawOwnerGrant(key: string, sign?: OwnerSign): Promise<boolean>;
447
460
  /**
448
461
  * Create a seed from the current control network state.
449
- * The seed contains peer information and is signed by an owner.
462
+ * The seed contains peer information and is signed by an owner; its `signerKey` is the
463
+ * owner signer's key.
450
464
  */
451
- createSeed(): Promise<ControlNetworkSeed>;
465
+ createSeed(sign?: OwnerSign): Promise<ControlNetworkSeed>;
466
+ /**
467
+ * {@link createSeed}, with `selfRelayAddr` added to this node's own peer entry before the
468
+ * seed is signed: the signature covers every address ({@link seedDigest}), so nothing may
469
+ * be added after it.
470
+ */
471
+ private mintSeed;
452
472
  /**
453
473
  * Apply a seed to populate the peer cache and enable connections.
454
474
  *
@@ -456,9 +476,8 @@ export declare class SeedBootstrapService {
456
476
  * `signerKey` that does NOT come from the seed body: the receiver's
457
477
  * node-local {@link SeedBootstrapConfig.trustedOwners} anchor, optionally
458
478
  * augmented by pinned keys or TOFU via the configured/overriding
459
- * `SeedTrustPolicy`. A forged self-asserting seed — one that merely lists its
460
- * own signer as an owner peer — no longer passes, and neither does one signed
461
- * by a key a stranger genesis-inserted into the replicated `OwnerKey` table.
479
+ * `SeedTrustPolicy`. A forged self-signed seed does not pass, and neither does
480
+ * one signed by a key a stranger genesis-inserted into the replicated `OwnerKey` table.
462
481
  *
463
482
  * A key accepted via a pin/TOFU is persisted into the anchor (the policy says
464
483
  * so via `SeedTrustDecision.anchorAs`), so the next seed from that owner is
@@ -475,22 +494,26 @@ export declare class SeedBootstrapService {
475
494
  /**
476
495
  * The first half of {@link applySeed}: check the signature and the signer's trust, then merge
477
496
  * the seed's peer addresses into the peer store. Every rejection happens here, so this result is
478
- * what the inbound handler acks with; the owner dials that follow cannot change it.
497
+ * what the inbound handler acks with; the dials that follow cannot change it.
479
498
  */
480
499
  private verifyAndMergeSeed;
481
500
  /**
482
- * The second half of {@link applySeed}: dial the seed's owner peers to establish connections.
501
+ * The second half of {@link applySeed}: dial the seed's preferred peers (`SeedPeer.preferred`:
502
+ * the machine that minted it and every always-on machine) to establish connections.
483
503
  *
484
- * Best-effort and COUNTED: an owner that is momentarily down leaves this node seeded but
504
+ * Best-effort and COUNTED: a peer that is momentarily down leaves this node seeded but
485
505
  * unconnected, which the caller can only see if the outcome is reported (see
486
- * `ApplySeedResult.ownerDialsFailed`). Recovery is not this loop's job —
506
+ * `ApplySeedResult.preferredDialsFailed`). Recovery is not this loop's job —
487
507
  * `CadreNode.dialColdStartBootstrap` retries these same addresses on every control-cohort
488
508
  * reconcile pass until the control database has siblings.
489
509
  *
490
- * The inbound handler runs this AFTER it has acked and closed the stream
491
- * ({@link handleSeedStream}), because an unreachable owner can take `dialBudget.totalMs`.
510
+ * The inbound handler runs this AFTER it has acked, closed the stream and reported the seed
511
+ * applied ({@link handleSeedStream}), because an unreachable peer can take `dialBudget.totalMs`.
512
+ * The node may stop while these dials are in flight (cadre-cli restarts a claimed node on
513
+ * `seed:applied`): the node's stop aborts the dial in flight and every later one is refused
514
+ * at once (`dialAddr`), and each is counted as failed here.
492
515
  */
493
- private dialSeedOwners;
516
+ private dialPreferredPeers;
494
517
  /**
495
518
  * Persist a signer that a pin/TOFU accepted into the node-local anchor, so a
496
519
  * later seed from the same owner is anchored without re-supplying the pin
@@ -603,10 +626,10 @@ export declare class SeedBootstrapService {
603
626
  */
604
627
  validateSeedSignature(seed: ControlNetworkSeed, digestB64?: string): boolean;
605
628
  /**
606
- * The peers a seed carries: the control database's own projection
629
+ * The peers a seed `minterPeerId` mints carries: the control database's own projection
607
630
  * ({@link ControlDatabase.querySeedPeers}, shared with the cadre invitation redemption
608
- * reply), which reads through the revocation filter and flags owners from the replicated
609
- * `OwnerKey` table — a dial hint, not a trust decision (the NOTE at `projectSeedPeers`).
631
+ * reply), which reads through the revocation filter and marks the minter and every
632
+ * always-on machine preferred — a dial hint, not a trust decision.
610
633
  */
611
634
  private queryPeers;
612
635
  /**
@@ -617,14 +640,16 @@ export declare class SeedBootstrapService {
617
640
  private registerProtocolHandler;
618
641
  /**
619
642
  * Read one inbound seed frame, verify and merge it, write the ack and close the
620
- * stream, then dial the seed's owners.
643
+ * stream, report the seed applied, then dial the seed's preferred peers.
621
644
  *
622
- * The ack and the close come BEFORE the owner dials: an unreachable owner can hold
623
- * a dial for `dialBudget.totalMs` (86 s at the default declared link), which is not
624
- * link time and does not belong inside the sender's delivery deadline. The close is
625
- * what releases the sender, which reads the ack to end-of-stream. The stream stays
626
- * counted in {@link activeStreams} through the dials, so {@link maxConcurrentSeeds}
627
- * still bounds concurrent owner-dial phases.
645
+ * The ack, the close and `onSeedApplied` come BEFORE those dials: an unreachable peer
646
+ * can hold a dial for `dialBudget.totalMs` (86 s at the default declared link), which is
647
+ * not link time and does not belong inside the sender's delivery deadline, nor ahead of
648
+ * a claimed node's restart (which stops this node, so its dials would be wasted). The
649
+ * close is what releases the sender, which reads the ack to end-of-stream, and it is
650
+ * awaited before `onSeedApplied`, so the ack is flushed before anything the callback
651
+ * starts. The stream stays counted in {@link activeStreams} through the dials, so
652
+ * {@link maxConcurrentSeeds} still bounds concurrent dial phases.
628
653
  *
629
654
  * Hardened against a buggy/compromised own-cadre node: a concurrency cap (over
630
655
  * {@link maxConcurrentSeeds}, reply without applying), a read timeout (a peer
@@ -664,10 +689,12 @@ export declare class SeedBootstrapService {
664
689
  * does not listen. Call `CadreNode.reconcileControlCohort()` after delivering
665
690
  * the seed to dial at once.
666
691
  *
692
+ * The vouch and the seed are one owner approval.
693
+ *
667
694
  * @param options - Drone peer info from provider API
668
695
  * @returns Seed and encoded seed for drone initialization
669
696
  */
670
- addDrone(options: AddDroneOptions): Promise<DroneInitResult>;
697
+ addDrone(options: AddDroneOptions, sign?: OwnerSign): Promise<DroneInitResult>;
671
698
  /**
672
699
  * Add a phone to the cadre with relay support.
673
700
  *
@@ -675,8 +702,10 @@ export declare class SeedBootstrapService {
675
702
  * 1. Authorizes the new phone peer
676
703
  * 2. Creates a seed with relay addresses for dialing
677
704
  *
705
+ * The vouch and the seed are one owner approval.
706
+ *
678
707
  * @param phonePeerId - Peer ID of the new phone
679
708
  * @returns Seed with relay addresses for out-of-band delivery
680
709
  */
681
- addPhoneWithRelay(phonePeerId: string): Promise<DroneInitResult>;
710
+ addPhoneWithRelay(phonePeerId: string, sign?: OwnerSign): Promise<DroneInitResult>;
682
711
  }