@serfab/cadre-core 1.15.0 → 1.17.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 +1 -1
- 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 +55 -138
- package/dist/cadre-invite-protocol.js +94 -449
- 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 +530 -247
- package/dist/cadre-node.js +1046 -525
- 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 +22 -23
- package/dist/control-cohort.js +24 -24
- package/dist/control-cohort.js.map +1 -1
- package/dist/control-database.d.ts +416 -136
- package/dist/control-database.js +757 -378
- package/dist/control-database.js.map +1 -1
- package/dist/control-protocol-guard.d.ts +5 -4
- package/dist/control-protocol-guard.js +6 -3
- package/dist/control-protocol-guard.js.map +1 -1
- package/dist/control-schema-version.d.ts +80 -0
- package/dist/control-schema-version.js +203 -0
- package/dist/control-schema-version.js.map +1 -0
- package/dist/control-schema.d.ts +45 -5
- package/dist/control-schema.js +254 -70
- package/dist/control-schema.js.map +1 -1
- package/dist/control-write-retry.d.ts +5 -5
- package/dist/control-write-retry.js +10 -8
- 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/index.d.ts +16 -7
- package/dist/index.js +26 -7
- package/dist/index.js.map +1 -1
- package/dist/joined-strand-store.d.ts +3 -3
- package/dist/joined-strand-store.js +3 -3
- 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/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 +250 -0
- package/dist/member-redemption.js +485 -0
- package/dist/member-redemption.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 +247 -0
- package/dist/owner-grant-protocol.js +330 -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-authorization.d.ts +83 -18
- package/dist/peer-authorization.js +123 -53
- package/dist/peer-authorization.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 +131 -109
- package/dist/seed-bootstrap.js +260 -248
- 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 +1 -0
- package/dist/strand-database.js +3 -0
- package/dist/strand-database.js.map +1 -1
- package/dist/strand-first-sync-gate.d.ts +4 -3
- package/dist/strand-first-sync-gate.js +4 -3
- package/dist/strand-first-sync-gate.js.map +1 -1
- package/dist/strand-instance-manager.d.ts +1 -1
- package/dist/strand-membership-writer.d.ts +13 -2
- package/dist/strand-membership-writer.js +52 -16
- package/dist/strand-membership-writer.js.map +1 -1
- package/dist/strand-move.d.ts +6 -5
- package/dist/strand-move.js +31 -30
- 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/types.d.ts +286 -103
- package/dist/types.js.map +1 -1
- package/package.json +16 -7
- package/src/bootstrap-peer-store-file.ts +44 -44
- package/src/bootstrap-peer-store.ts +214 -214
- package/src/cadre-invite-protocol.ts +131 -531
- package/src/cadre-join-request.ts +188 -167
- package/src/cadre-node.ts +1166 -541
- package/src/control-authorization.ts +47 -14
- package/src/control-cohort.ts +127 -128
- package/src/control-database.ts +940 -456
- package/src/control-protocol-guard.ts +7 -4
- package/src/control-schema-version.ts +251 -0
- package/src/control-schema.ts +265 -70
- package/src/control-write-retry.ts +569 -567
- package/src/delegate-admission.ts +37 -0
- 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/index.ts +102 -5
- package/src/joined-strand-store.ts +4 -4
- package/src/key-store.ts +10 -4
- package/src/machine-removal.ts +26 -111
- package/src/member-redemption.ts +642 -0
- package/src/owner-anchor-sync.ts +19 -18
- package/src/owner-grant-protocol.ts +532 -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-authorization.ts +558 -488
- package/src/provider/rent-node.ts +1 -1
- package/src/seed-bootstrap.ts +301 -312
- 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 +3 -0
- package/src/strand-first-sync-gate.ts +4 -3
- package/src/strand-instance-manager.ts +1 -1
- package/src/strand-membership-writer.ts +61 -16
- package/src/strand-move.ts +45 -36
- package/src/strand-peer-redial.ts +2 -3
- package/src/types.ts +304 -103
package/dist/seed-bootstrap.d.ts
CHANGED
|
@@ -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
|
|
3
|
+
import type { ControlNetworkSeed, SeedPeer, SeedAckMessage, SeedDeliveryTarget, AuthorizePeerOptions, ApplySeedResult, AddDroneOptions, DroneInitResult, CadreInviteRow, OwnerGrantRow, PeerAddressRecord, DeviceTokenRecord, RevocationRow, RevocationLedgerOpenResult, MachineRemovalResult } from './types.js';
|
|
4
|
+
import type { 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
|
/**
|
|
@@ -47,10 +48,12 @@ export declare function mergeSeedPeers(node: Libp2p, peers: readonly SeedPeer[])
|
|
|
47
48
|
export interface SeedBootstrapConfig {
|
|
48
49
|
/** Party ID for this cadre */
|
|
49
50
|
partyId: string;
|
|
50
|
-
/**
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
/**
|
|
52
|
+
* The owner signer every seed and owner-signed write of this service goes through
|
|
53
|
+
* (`owner-signer.ts`). Unset for a listener-only service, which receives and applies seeds
|
|
54
|
+
* but refuses every owner write.
|
|
55
|
+
*/
|
|
56
|
+
ownerSigner?: OwnerSigner;
|
|
54
57
|
/**
|
|
55
58
|
* Trust anchor for incoming seeds. Decides whether a signature-verified
|
|
56
59
|
* `signerKey` should be trusted, against the receiver's anchored owner
|
|
@@ -107,7 +110,7 @@ export interface SeedBootstrapConfig {
|
|
|
107
110
|
* sized for the forms that dial inside it. Delivery does not set `runOnLimitedConnection`,
|
|
108
111
|
* so it does not use a limited relayed connection today; the relayed-dial count is the upper
|
|
109
112
|
* 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
|
|
113
|
+
* address. It holds only link work because the receiver acks before it dials the seed's peers.
|
|
111
114
|
*
|
|
112
115
|
* NOTE: no transfer allowance — a seed is a peer list of a few KB, and `MAX_SEED_SIZE` (1 MiB)
|
|
113
116
|
* is a defensive cap. If seeds ever grow toward that cap, add an allowance the way
|
|
@@ -116,7 +119,7 @@ export interface SeedBootstrapConfig {
|
|
|
116
119
|
seedDeliverTimeoutMs?: number;
|
|
117
120
|
/**
|
|
118
121
|
* Time limits for each peer this service dials from a list of addresses —
|
|
119
|
-
* {@link SeedBootstrapService.applySeed}'s
|
|
122
|
+
* {@link SeedBootstrapService.applySeed}'s dials of the seed's preferred peers and
|
|
120
123
|
* {@link SeedBootstrapService.deliverSeed}'s dial of a peer id with addresses — per
|
|
121
124
|
* address and per peer (see `peer-dial.ts`). Defaults to {@link DEFAULT_PEER_DIAL_BUDGET}; a `CadreNode`
|
|
122
125
|
* passes its `network.controlCohort` limits.
|
|
@@ -135,7 +138,7 @@ export interface SeedEventCallbacks {
|
|
|
135
138
|
* `seed` is the applied seed itself: the inbound protocol handler applies it
|
|
136
139
|
* INSIDE the service, so this callback is the only seam through which a
|
|
137
140
|
* `CadreNode` sees a wire-delivered seed's contents — which it needs to
|
|
138
|
-
* retain the
|
|
141
|
+
* retain the preferred peers as cold-start bootstrap dial targets.
|
|
139
142
|
*/
|
|
140
143
|
onSeedApplied?: (partyId: string, peersAdded: number, seed: ControlNetworkSeed) => void;
|
|
141
144
|
/** Called when seed application fails */
|
|
@@ -152,7 +155,6 @@ export declare class SeedBootstrapService {
|
|
|
152
155
|
private readonly config;
|
|
153
156
|
private libp2pNode;
|
|
154
157
|
private controlDatabase;
|
|
155
|
-
private readonly ownerPublicKey;
|
|
156
158
|
private readonly trustPolicy;
|
|
157
159
|
private readonly seedReadTimeoutMs;
|
|
158
160
|
private readonly maxConcurrentSeeds;
|
|
@@ -168,20 +170,21 @@ export declare class SeedBootstrapService {
|
|
|
168
170
|
*/
|
|
169
171
|
setEventCallbacks(callbacks: SeedEventCallbacks): void;
|
|
170
172
|
/**
|
|
171
|
-
* Whether this service holds an owner
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
-
* drain to skip owner work on a non-owner node.
|
|
173
|
+
* Whether this service holds an owner signer, i.e. can produce the owner signatures that
|
|
174
|
+
* gate `CadrePeer` / `DeviceToken` inserts, deletes, and re-authorizations. A
|
|
175
|
+
* seed-listener-only service (`enableSeedListener`, no signer) returns false: it can
|
|
176
|
+
* receive/apply seeds but cannot author or re-issue owner writes. Used by the
|
|
177
|
+
* write-while-alone re-replication drain to skip owner work on a non-owner node.
|
|
177
178
|
*/
|
|
178
179
|
canAuthorize(): boolean;
|
|
180
|
+
/** The owner signer this service was built with, or null for a listener-only service. */
|
|
181
|
+
get ownerSigner(): OwnerSigner | null;
|
|
179
182
|
/**
|
|
180
183
|
* Initialize the service with libp2p node and control database.
|
|
181
184
|
*
|
|
182
185
|
* `registerHandler` (default true) gates registration of the shared inbound
|
|
183
186
|
* `/sereus/seed/1.0.0` handler on `libp2pNode`. Persistent services
|
|
184
|
-
* (`
|
|
187
|
+
* (`CadreNode.useOwnerSigner`, `enableSeedListener`) own that handler and leave
|
|
185
188
|
* it on. The throwaway temp service CadreNode builds in `applySeed` passes
|
|
186
189
|
* `false`: it only needs the stored `libp2pNode` / `controlDatabase` for
|
|
187
190
|
* dialing and known-key lookup, and must NOT bind a discarded closure to the
|
|
@@ -207,8 +210,11 @@ export declare class SeedBootstrapService {
|
|
|
207
210
|
* `UpdatedAt` but no self-signature (`Sig` null) — the owner cannot produce
|
|
208
211
|
* the peer's self-signature, so the peer must self-publish (see
|
|
209
212
|
* {@link CadreNode.registerSelf}) before the row resolves.
|
|
213
|
+
*
|
|
214
|
+
* @param sign - The signature function of an owner approval the caller already holds, so a
|
|
215
|
+
* multi-step action asks once; omitted, this write asks for its own approval.
|
|
210
216
|
*/
|
|
211
|
-
authorizePeer(options: AuthorizePeerOptions): Promise<void>;
|
|
217
|
+
authorizePeer(options: AuthorizePeerOptions, sign?: OwnerSign): Promise<void>;
|
|
212
218
|
/**
|
|
213
219
|
* Owner-signed INSERT of this node's OWN self-signed address record.
|
|
214
220
|
*
|
|
@@ -222,17 +228,16 @@ export declare class SeedBootstrapService {
|
|
|
222
228
|
* in which case the row in the database is NOT this record and carries whatever
|
|
223
229
|
* `Sig` that writer had, so the caller must self-update to publish its signature.
|
|
224
230
|
*/
|
|
225
|
-
insertSelfPeerRecord(record: PeerAddressRecord): Promise<boolean>;
|
|
231
|
+
insertSelfPeerRecord(record: PeerAddressRecord, sign?: OwnerSign): Promise<boolean>;
|
|
226
232
|
/**
|
|
227
|
-
* Shared owner-signed `CadrePeer` INSERT — the row fields and the owner-
|
|
233
|
+
* Shared owner-signed `CadrePeer` INSERT — the row fields and the owner-signer
|
|
228
234
|
* precondition; the stamp mint, voucher signature, write lock, existence check and
|
|
229
235
|
* membership notify are all {@link ControlDatabase.insertCadrePeer}'s (see there for
|
|
230
236
|
* the anti-replay and insert-race rationale). No `CadrePeer` write may bypass that
|
|
231
237
|
* method: the write is what admits the peer's traffic.
|
|
232
238
|
*
|
|
233
|
-
* The DB check precedes the owner-
|
|
234
|
-
* always surfaced them
|
|
235
|
-
* DB check).
|
|
239
|
+
* The DB check precedes the owner-signer check here, matching the order this method has
|
|
240
|
+
* always surfaced them.
|
|
236
241
|
*
|
|
237
242
|
* @returns `true` when this call performed the INSERT, `false` when the row was
|
|
238
243
|
* already seated by a concurrent writer. The loser needs to know: an authorize seats
|
|
@@ -257,7 +262,7 @@ export declare class SeedBootstrapService {
|
|
|
257
262
|
* fresh signature — unaffected by the cleared row's retired stamp
|
|
258
263
|
* (`DeviceToken.NotRevoked`).
|
|
259
264
|
*/
|
|
260
|
-
insertSelfDeviceToken(record: DeviceTokenRecord): Promise<void>;
|
|
265
|
+
insertSelfDeviceToken(record: DeviceTokenRecord, sign?: OwnerSign): Promise<void>;
|
|
261
266
|
/**
|
|
262
267
|
* Owner-signed DELETE of a peer's `DeviceToken` row (logout / token
|
|
263
268
|
* invalidation). The `DeviceToken.AuthorizedDelete` constraint validates an owner
|
|
@@ -276,44 +281,27 @@ export declare class SeedBootstrapService {
|
|
|
276
281
|
* Both digests, the stamp read, and the transaction come from
|
|
277
282
|
* {@link ControlDatabase.deleteDeviceToken} — one shared implementation across
|
|
278
283
|
* `CadrePeer` / `DeviceToken` / `Strand` / `ValidationKey`. What stays here is the
|
|
279
|
-
* owner-
|
|
284
|
+
* owner-signer precondition; a no-op on an already-absent row is the shared body's
|
|
280
285
|
* behavior, and unlike {@link removePeer} nothing here rides on it.
|
|
281
286
|
*/
|
|
282
|
-
deleteDeviceToken(peerId: string): Promise<void>;
|
|
287
|
+
deleteDeviceToken(peerId: string, sign?: OwnerSign): Promise<void>;
|
|
283
288
|
/**
|
|
284
|
-
* Return the configured owner
|
|
285
|
-
*
|
|
286
|
-
*
|
|
287
|
-
*
|
|
288
|
-
*
|
|
289
|
-
*
|
|
290
|
-
*/
|
|
291
|
-
private requireOwnerPrivateKey;
|
|
292
|
-
/**
|
|
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.
|
|
289
|
+
* Return the configured owner signer, or throw if none is set. The single precondition
|
|
290
|
+
* gate for every owner-signed write. {@link removePeer} / {@link reauthorizePeer} read the
|
|
291
|
+
* row's `StampId` from the DB BEFORE they sign, so they call this up front — otherwise a
|
|
292
|
+
* signerless service would either surface the wrong "Control database not initialized"
|
|
293
|
+
* error or, worse, silently no-op when the target row is absent (the early
|
|
294
|
+
* `stampId === null` return) instead of rejecting.
|
|
300
295
|
*/
|
|
301
|
-
private
|
|
296
|
+
private requireOwnerSigner;
|
|
297
|
+
/** The control database {@link initialize} attached, or a throw. */
|
|
298
|
+
private requireControlDatabase;
|
|
302
299
|
/**
|
|
303
|
-
*
|
|
304
|
-
*
|
|
305
|
-
*
|
|
306
|
-
* {@link signMessageBytes}. Throws if no owner key is set.
|
|
300
|
+
* Run `body` with an owner signature function: the caller's `sign` when it passes one (a
|
|
301
|
+
* `CadreNode` action already inside its approval), otherwise one approval of this service's
|
|
302
|
+
* signer for `action`, the plain-words description a prompting signer shows.
|
|
307
303
|
*/
|
|
308
|
-
private
|
|
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".
|
|
315
|
-
*/
|
|
316
|
-
private signMessageBytes;
|
|
304
|
+
private withOwnerSign;
|
|
317
305
|
/**
|
|
318
306
|
* Remove a peer from the cadre by owner signature.
|
|
319
307
|
*
|
|
@@ -336,45 +324,46 @@ export declare class SeedBootstrapService {
|
|
|
336
324
|
* Both digests, the stamp read, the transaction, and the post-commit membership notify
|
|
337
325
|
* come from {@link ControlDatabase.deleteCadrePeer} — one shared implementation across
|
|
338
326
|
* `CadrePeer` / `DeviceToken` / `Strand` / `ValidationKey`. What stays here is the
|
|
339
|
-
* owner-
|
|
327
|
+
* owner-signer precondition and the absent-row gate the notify depends on (below).
|
|
340
328
|
*/
|
|
341
|
-
removePeer(peerId: string): Promise<void>;
|
|
329
|
+
removePeer(peerId: string, sign?: OwnerSign): Promise<void>;
|
|
342
330
|
/**
|
|
343
|
-
* Seat `ownerPublicKey` as a further owner, signed by this service's owner
|
|
331
|
+
* Seat `ownerPublicKey` as a further owner, signed by this service's owner signer. The
|
|
344
332
|
* liveness check, the stamp, the signature and the membership notify are
|
|
345
|
-
* {@link ControlDatabase.insertOwnerKeyVouched}'s; what stays here is the owner-
|
|
333
|
+
* {@link ControlDatabase.insertOwnerKeyVouched}'s; what stays here is the owner-signer
|
|
346
334
|
* precondition, checked before any read (see {@link removePeer}).
|
|
347
335
|
*
|
|
336
|
+
* @param label - the user's name for the key, bound into the signature
|
|
337
|
+
* ({@link ControlDatabase.insertOwnerKey} has the rule).
|
|
348
338
|
* @returns `true` when the row was seated, `false` when the key is already a live owner.
|
|
349
339
|
*/
|
|
350
|
-
addOwner(ownerPublicKey: string): Promise<boolean>;
|
|
340
|
+
addOwner(ownerPublicKey: string, label?: string, sign?: OwnerSign): Promise<boolean>;
|
|
351
341
|
/**
|
|
352
|
-
* Remove `ownerPublicKey` from the owners, signed by this service's owner
|
|
342
|
+
* Remove `ownerPublicKey` from the owners, signed by this service's owner signer: the delete
|
|
353
343
|
* and its `Revocation` tombstone in one transaction. The by-name refusals (self-removal,
|
|
354
344
|
* the last owner), the digests and the membership notify are
|
|
355
|
-
* {@link ControlDatabase.deleteOwnerKey}'s; what stays here is the owner-
|
|
345
|
+
* {@link ControlDatabase.deleteOwnerKey}'s; what stays here is the owner-signer precondition,
|
|
356
346
|
* checked before any read (see {@link removePeer}).
|
|
357
347
|
*
|
|
358
348
|
* @returns `true` when the row was removed, `false` when the key is not a live owner here.
|
|
359
349
|
*/
|
|
360
|
-
removeOwner(ownerPublicKey: string): Promise<boolean>;
|
|
350
|
+
removeOwner(ownerPublicKey: string, sign?: OwnerSign): Promise<boolean>;
|
|
361
351
|
/**
|
|
362
|
-
* Re-vouch another owner's row under this service's owner
|
|
352
|
+
* Re-vouch another owner's row under this service's owner signer, so it stands on a remaining
|
|
363
353
|
* owner's signature before the owner that added it is removed
|
|
364
|
-
* ({@link ControlDatabase.revouchOwnerKey}; for `CadreNode.
|
|
365
|
-
* here is the owner-
|
|
354
|
+
* ({@link ControlDatabase.revouchOwnerKey}; for `CadreNode.removeOwner` only). What stays
|
|
355
|
+
* here is the owner-signer precondition, checked before any read (see {@link removePeer}).
|
|
366
356
|
*
|
|
367
357
|
* @returns `true` when the row was re-vouched, `false` when the key is not a live owner here.
|
|
368
358
|
*/
|
|
369
|
-
revouchOwner(ownerPublicKey: string): Promise<boolean>;
|
|
359
|
+
revouchOwner(ownerPublicKey: string, sign?: OwnerSign): Promise<boolean>;
|
|
370
360
|
/**
|
|
371
|
-
* Remove a machine completely, signed by this service's owner
|
|
372
|
-
* `
|
|
373
|
-
*
|
|
374
|
-
* ({@link
|
|
375
|
-
* checked before any read (see {@link removePeer}).
|
|
361
|
+
* Remove a machine completely, signed by this service's owner signer: its `CadrePeer` row, its
|
|
362
|
+
* `DeviceToken` row, and the withdrawal of every invitation in `target.inviteKeys`, all in one
|
|
363
|
+
* transaction ({@link ControlDatabase.removeMachine}). What stays here is the owner-signer
|
|
364
|
+
* precondition, checked before any read (see {@link removePeer}).
|
|
376
365
|
*/
|
|
377
|
-
removeMachine(target: Parameters<ControlDatabase['removeMachine']>[0]): Promise<
|
|
366
|
+
removeMachine(target: Parameters<ControlDatabase['removeMachine']>[0], sign?: OwnerSign): Promise<MachineRemovalResult>;
|
|
378
367
|
/**
|
|
379
368
|
* Owner "re-touch" of an existing `CadrePeer` membership row: bump `UpdatedAt` and
|
|
380
369
|
* re-vouch the row so it is re-emitted as a fresh, broadcasting transaction. This is
|
|
@@ -384,16 +373,16 @@ export declare class SeedBootstrapService {
|
|
|
384
373
|
*
|
|
385
374
|
* The stamp read, the voucher signature, the write lock and the membership notify are
|
|
386
375
|
* {@link ControlDatabase.reauthorizeCadrePeer}'s — including the caveat that it rebinds
|
|
387
|
-
* `VouchOwner` to this node's owner key. What stays here is the owner-
|
|
376
|
+
* `VouchOwner` to this node's owner key. What stays here is the owner-signer precondition.
|
|
388
377
|
*
|
|
389
378
|
* A no-op (no throw, no notify) when the row does not exist.
|
|
390
379
|
*
|
|
391
380
|
* @param peerId - the membership row to re-touch.
|
|
392
381
|
* @param updatedAt - the strictly-increasing freshness stamp to write.
|
|
393
|
-
* @throws if no owner
|
|
382
|
+
* @throws if no owner signer is configured (a non-owner cannot
|
|
394
383
|
* re-sign another peer's row) or the control database is not initialized.
|
|
395
384
|
*/
|
|
396
|
-
reauthorizePeer(peerId: string, updatedAt: number): Promise<void>;
|
|
385
|
+
reauthorizePeer(peerId: string, updatedAt: number, sign?: OwnerSign): Promise<void>;
|
|
397
386
|
/**
|
|
398
387
|
* Owner re-issue of a batch of `Revocation` tombstones: bump each row's
|
|
399
388
|
* `ReissuedAt` so the storage layer re-broadcasts a tombstone that committed
|
|
@@ -404,51 +393,80 @@ export declare class SeedBootstrapService {
|
|
|
404
393
|
*
|
|
405
394
|
* The signatures, the single transaction, and the strictly-monotonic
|
|
406
395
|
* `reissuedAt` contract are {@link ControlDatabase.reissueRevocations}'s. What
|
|
407
|
-
* stays here is the owner-
|
|
396
|
+
* stays here is the owner-signer precondition.
|
|
408
397
|
*
|
|
409
398
|
* @returns how many tombstones were re-issued (`rows.length` on success).
|
|
410
|
-
* @throws if no owner
|
|
399
|
+
* @throws if no owner signer is configured or the control database is not
|
|
411
400
|
* initialized.
|
|
412
401
|
*/
|
|
413
|
-
reissueRevocations(rows: readonly RevocationRow[], reissuedAt: number): Promise<number>;
|
|
402
|
+
reissueRevocations(rows: readonly RevocationRow[], reissuedAt: number, sign?: OwnerSign): Promise<number>;
|
|
414
403
|
/**
|
|
415
404
|
* Owner filing of the singleton `Revocation` ledger marker, so the table is never a
|
|
416
405
|
* never-written block that the storage layer re-consults on every read.
|
|
417
406
|
*
|
|
418
407
|
* The signature, the insert-if-absent guard and the `'already-open'` mapping are
|
|
419
|
-
* {@link ControlDatabase.openRevocationLedger}'s. What stays here is the owner-
|
|
408
|
+
* {@link ControlDatabase.openRevocationLedger}'s. What stays here is the owner-signer
|
|
420
409
|
* precondition.
|
|
421
410
|
*
|
|
422
|
-
* @throws if no owner
|
|
411
|
+
* @throws if no owner signer is configured or the control database is not
|
|
423
412
|
* initialized.
|
|
424
413
|
*/
|
|
425
|
-
openRevocationLedger(): Promise<RevocationLedgerOpenResult>;
|
|
414
|
+
openRevocationLedger(sign?: OwnerSign): Promise<RevocationLedgerOpenResult>;
|
|
426
415
|
/**
|
|
427
416
|
* Owner-signed INSERT of a `CadreInvite` row — an invitation any member machine can redeem
|
|
428
417
|
* on this owner's behalf ({@link ControlDatabase.insertCadreInvite}). The keypair mint, the
|
|
429
418
|
* expiry and use-count defaults, and the bundle the holder receives are
|
|
430
|
-
* `CadreNode.createCadreInvitation`'s; what stays here is the owner-
|
|
431
|
-
* the
|
|
419
|
+
* `CadreNode.createCadreInvitation`'s; what stays here is the owner-signer precondition and
|
|
420
|
+
* the approval, as {@link insertSelfDeviceToken} keeps them for device tokens.
|
|
432
421
|
*
|
|
433
422
|
* @returns the row as stored, which the invitation bundle carries verbatim.
|
|
434
|
-
* @throws if no owner
|
|
423
|
+
* @throws if no owner signer is configured or the control database is not initialized.
|
|
435
424
|
*/
|
|
436
|
-
insertCadreInvite(invite: Parameters<ControlDatabase['insertCadreInvite']>[0]): Promise<CadreInviteRow>;
|
|
425
|
+
insertCadreInvite(invite: Parameters<ControlDatabase['insertCadreInvite']>[0], sign?: OwnerSign): Promise<CadreInviteRow>;
|
|
437
426
|
/**
|
|
438
427
|
* Owner-signed WITHDRAWAL of a `CadreInvite`: the `Revocation` tombstone over its stamp, with
|
|
439
428
|
* the row kept ({@link ControlDatabase.withdrawCadreInvite}). What stays here is the
|
|
440
|
-
* owner-
|
|
429
|
+
* owner-signer precondition.
|
|
430
|
+
*
|
|
431
|
+
* @returns `true` when this call filed the tombstone, `false` when the row is absent here or
|
|
432
|
+
* already withdrawn.
|
|
433
|
+
* @throws if no owner signer is configured or the control database is not initialized.
|
|
434
|
+
*/
|
|
435
|
+
withdrawCadreInvite(key: string, sign?: OwnerSign): Promise<boolean>;
|
|
436
|
+
/**
|
|
437
|
+
* Owner-signed INSERT of an `OwnerGrant` row — a grant of ownership any member machine can
|
|
438
|
+
* redeem on this owner's behalf ({@link ControlDatabase.insertOwnerGrant}). The keypair mint,
|
|
439
|
+
* the lifetime default and the bundle the holder receives are `CadreNode.createOwnerGrant`'s;
|
|
440
|
+
* what stays here is the owner-signer precondition and the approval, as for
|
|
441
|
+
* {@link insertCadreInvite}. The label is checked before the approval opens, so one the row
|
|
442
|
+
* would refuse never prompts the user.
|
|
443
|
+
*
|
|
444
|
+
* @returns the row as stored, which the grant bundle carries verbatim.
|
|
445
|
+
* @throws if no owner signer is configured, the control database is not initialized, or the label is too long.
|
|
446
|
+
*/
|
|
447
|
+
insertOwnerGrant(grant: Parameters<ControlDatabase['insertOwnerGrant']>[0], sign?: OwnerSign): Promise<OwnerGrantRow>;
|
|
448
|
+
/**
|
|
449
|
+
* Owner-signed WITHDRAWAL of an `OwnerGrant`: the `Revocation` tombstone over its stamp, with
|
|
450
|
+
* the row kept ({@link ControlDatabase.withdrawOwnerGrant}). What stays here is the
|
|
451
|
+
* owner-signer precondition.
|
|
441
452
|
*
|
|
442
453
|
* @returns `true` when this call filed the tombstone, `false` when the row is absent here or
|
|
443
454
|
* already withdrawn.
|
|
444
|
-
* @throws if no owner
|
|
455
|
+
* @throws if no owner signer is configured or the control database is not initialized.
|
|
445
456
|
*/
|
|
446
|
-
|
|
457
|
+
withdrawOwnerGrant(key: string, sign?: OwnerSign): Promise<boolean>;
|
|
447
458
|
/**
|
|
448
459
|
* Create a seed from the current control network state.
|
|
449
|
-
* The seed contains peer information and is signed by an owner
|
|
460
|
+
* The seed contains peer information and is signed by an owner; its `signerKey` is the
|
|
461
|
+
* owner signer's key.
|
|
462
|
+
*/
|
|
463
|
+
createSeed(sign?: OwnerSign): Promise<ControlNetworkSeed>;
|
|
464
|
+
/**
|
|
465
|
+
* {@link createSeed}, with `selfRelayAddr` added to this node's own peer entry before the
|
|
466
|
+
* seed is signed: the signature covers every address ({@link seedDigest}), so nothing may
|
|
467
|
+
* be added after it.
|
|
450
468
|
*/
|
|
451
|
-
|
|
469
|
+
private mintSeed;
|
|
452
470
|
/**
|
|
453
471
|
* Apply a seed to populate the peer cache and enable connections.
|
|
454
472
|
*
|
|
@@ -456,9 +474,8 @@ export declare class SeedBootstrapService {
|
|
|
456
474
|
* `signerKey` that does NOT come from the seed body: the receiver's
|
|
457
475
|
* node-local {@link SeedBootstrapConfig.trustedOwners} anchor, optionally
|
|
458
476
|
* augmented by pinned keys or TOFU via the configured/overriding
|
|
459
|
-
* `SeedTrustPolicy`. A forged self-
|
|
460
|
-
*
|
|
461
|
-
* by a key a stranger genesis-inserted into the replicated `OwnerKey` table.
|
|
477
|
+
* `SeedTrustPolicy`. A forged self-signed seed does not pass, and neither does
|
|
478
|
+
* one signed by a key a stranger genesis-inserted into the replicated `OwnerKey` table.
|
|
462
479
|
*
|
|
463
480
|
* A key accepted via a pin/TOFU is persisted into the anchor (the policy says
|
|
464
481
|
* so via `SeedTrustDecision.anchorAs`), so the next seed from that owner is
|
|
@@ -475,22 +492,23 @@ export declare class SeedBootstrapService {
|
|
|
475
492
|
/**
|
|
476
493
|
* The first half of {@link applySeed}: check the signature and the signer's trust, then merge
|
|
477
494
|
* 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
|
|
495
|
+
* what the inbound handler acks with; the dials that follow cannot change it.
|
|
479
496
|
*/
|
|
480
497
|
private verifyAndMergeSeed;
|
|
481
498
|
/**
|
|
482
|
-
* The second half of {@link applySeed}: dial the seed's
|
|
499
|
+
* The second half of {@link applySeed}: dial the seed's preferred peers (`SeedPeer.preferred`:
|
|
500
|
+
* the machine that minted it and every always-on machine) to establish connections.
|
|
483
501
|
*
|
|
484
|
-
* Best-effort and COUNTED:
|
|
502
|
+
* Best-effort and COUNTED: a peer that is momentarily down leaves this node seeded but
|
|
485
503
|
* unconnected, which the caller can only see if the outcome is reported (see
|
|
486
|
-
* `ApplySeedResult.
|
|
504
|
+
* `ApplySeedResult.preferredDialsFailed`). Recovery is not this loop's job —
|
|
487
505
|
* `CadreNode.dialColdStartBootstrap` retries these same addresses on every control-cohort
|
|
488
506
|
* reconcile pass until the control database has siblings.
|
|
489
507
|
*
|
|
490
508
|
* The inbound handler runs this AFTER it has acked and closed the stream
|
|
491
|
-
* ({@link handleSeedStream}), because an unreachable
|
|
509
|
+
* ({@link handleSeedStream}), because an unreachable peer can take `dialBudget.totalMs`.
|
|
492
510
|
*/
|
|
493
|
-
private
|
|
511
|
+
private dialPreferredPeers;
|
|
494
512
|
/**
|
|
495
513
|
* Persist a signer that a pin/TOFU accepted into the node-local anchor, so a
|
|
496
514
|
* later seed from the same owner is anchored without re-supplying the pin
|
|
@@ -603,10 +621,10 @@ export declare class SeedBootstrapService {
|
|
|
603
621
|
*/
|
|
604
622
|
validateSeedSignature(seed: ControlNetworkSeed, digestB64?: string): boolean;
|
|
605
623
|
/**
|
|
606
|
-
* The peers a seed carries: the control database's own projection
|
|
624
|
+
* The peers a seed `minterPeerId` mints carries: the control database's own projection
|
|
607
625
|
* ({@link ControlDatabase.querySeedPeers}, shared with the cadre invitation redemption
|
|
608
|
-
* reply), which reads through the revocation filter and
|
|
609
|
-
*
|
|
626
|
+
* reply), which reads through the revocation filter and marks the minter and every
|
|
627
|
+
* always-on machine preferred — a dial hint, not a trust decision.
|
|
610
628
|
*/
|
|
611
629
|
private queryPeers;
|
|
612
630
|
/**
|
|
@@ -617,14 +635,14 @@ export declare class SeedBootstrapService {
|
|
|
617
635
|
private registerProtocolHandler;
|
|
618
636
|
/**
|
|
619
637
|
* Read one inbound seed frame, verify and merge it, write the ack and close the
|
|
620
|
-
* stream, then dial the seed's
|
|
638
|
+
* stream, then dial the seed's preferred peers.
|
|
621
639
|
*
|
|
622
|
-
* The ack and the close come BEFORE
|
|
640
|
+
* The ack and the close come BEFORE those dials: an unreachable peer can hold
|
|
623
641
|
* a dial for `dialBudget.totalMs` (86 s at the default declared link), which is not
|
|
624
642
|
* link time and does not belong inside the sender's delivery deadline. The close is
|
|
625
643
|
* what releases the sender, which reads the ack to end-of-stream. The stream stays
|
|
626
644
|
* counted in {@link activeStreams} through the dials, so {@link maxConcurrentSeeds}
|
|
627
|
-
* still bounds concurrent
|
|
645
|
+
* still bounds concurrent dial phases.
|
|
628
646
|
*
|
|
629
647
|
* Hardened against a buggy/compromised own-cadre node: a concurrency cap (over
|
|
630
648
|
* {@link maxConcurrentSeeds}, reply without applying), a read timeout (a peer
|
|
@@ -664,10 +682,12 @@ export declare class SeedBootstrapService {
|
|
|
664
682
|
* does not listen. Call `CadreNode.reconcileControlCohort()` after delivering
|
|
665
683
|
* the seed to dial at once.
|
|
666
684
|
*
|
|
685
|
+
* The vouch and the seed are one owner approval.
|
|
686
|
+
*
|
|
667
687
|
* @param options - Drone peer info from provider API
|
|
668
688
|
* @returns Seed and encoded seed for drone initialization
|
|
669
689
|
*/
|
|
670
|
-
addDrone(options: AddDroneOptions): Promise<DroneInitResult>;
|
|
690
|
+
addDrone(options: AddDroneOptions, sign?: OwnerSign): Promise<DroneInitResult>;
|
|
671
691
|
/**
|
|
672
692
|
* Add a phone to the cadre with relay support.
|
|
673
693
|
*
|
|
@@ -675,8 +695,10 @@ export declare class SeedBootstrapService {
|
|
|
675
695
|
* 1. Authorizes the new phone peer
|
|
676
696
|
* 2. Creates a seed with relay addresses for dialing
|
|
677
697
|
*
|
|
698
|
+
* The vouch and the seed are one owner approval.
|
|
699
|
+
*
|
|
678
700
|
* @param phonePeerId - Peer ID of the new phone
|
|
679
701
|
* @returns Seed with relay addresses for out-of-band delivery
|
|
680
702
|
*/
|
|
681
|
-
addPhoneWithRelay(phonePeerId: string): Promise<DroneInitResult>;
|
|
703
|
+
addPhoneWithRelay(phonePeerId: string, sign?: OwnerSign): Promise<DroneInitResult>;
|
|
682
704
|
}
|