@serfab/cadre-core 1.6.0 → 1.7.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/dist/cadre-node.d.ts +204 -65
- package/dist/cadre-node.js +392 -95
- package/dist/cadre-node.js.map +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -1
- package/dist/joined-strand-store.d.ts +112 -0
- package/dist/joined-strand-store.js +263 -0
- package/dist/joined-strand-store.js.map +1 -0
- package/dist/key-store.d.ts +6 -0
- package/dist/key-store.js.map +1 -1
- package/dist/node-local-snapshot.d.ts +5 -4
- package/dist/node-local-snapshot.js +6 -3
- package/dist/node-local-snapshot.js.map +1 -1
- package/dist/peer-join-backfill.d.ts +33 -14
- package/dist/peer-join-backfill.js +109 -50
- package/dist/peer-join-backfill.js.map +1 -1
- package/dist/strand-instance-manager.d.ts +39 -0
- package/dist/strand-instance-manager.js +74 -1
- package/dist/strand-instance-manager.js.map +1 -1
- package/dist/strand-peer-book-file.d.ts +12 -0
- package/dist/strand-peer-book-file.js +37 -0
- package/dist/strand-peer-book-file.js.map +1 -0
- package/dist/strand-peer-book-protocol.d.ts +159 -0
- package/dist/strand-peer-book-protocol.js +360 -0
- package/dist/strand-peer-book-protocol.js.map +1 -0
- package/dist/strand-peer-book-swap.d.ts +104 -0
- package/dist/strand-peer-book-swap.js +284 -0
- package/dist/strand-peer-book-swap.js.map +1 -0
- package/dist/strand-peer-book.d.ts +159 -0
- package/dist/strand-peer-book.js +354 -0
- package/dist/strand-peer-book.js.map +1 -0
- package/dist/strand-peer-observer.d.ts +88 -0
- package/dist/strand-peer-observer.js +180 -0
- package/dist/strand-peer-observer.js.map +1 -0
- package/dist/types.d.ts +58 -0
- package/dist/types.js.map +1 -1
- package/package.json +6 -2
- package/src/cadre-node.ts +7776 -7449
- package/src/index.ts +67 -0
- package/src/joined-strand-store.ts +308 -0
- package/src/key-store.ts +6 -0
- package/src/node-local-snapshot.ts +293 -289
- package/src/peer-join-backfill.ts +112 -51
- package/src/strand-instance-manager.ts +100 -1
- package/src/strand-peer-book-file.ts +39 -0
- package/src/strand-peer-book-protocol.ts +463 -0
- package/src/strand-peer-book-swap.ts +338 -0
- package/src/strand-peer-book.ts +468 -0
- package/src/strand-peer-observer.ts +235 -0
- package/src/types.ts +60 -0
package/dist/index.d.ts
CHANGED
|
@@ -13,6 +13,11 @@ export { MemoryTrustedOwnerStore, PersistentTrustedOwnerStore, type TrustedOwner
|
|
|
13
13
|
export type { DurableSlot } from './node-local-snapshot.js';
|
|
14
14
|
export { MemoryBootstrapPeerStore, PersistentBootstrapPeerStore, type BootstrapPeerStore, type BootstrapPeerEntry } from './bootstrap-peer-store.js';
|
|
15
15
|
export { MemoryEnrolledMachineStore, PersistentEnrolledMachineStore, type EnrolledMachineStore } from './enrolled-machine-store.js';
|
|
16
|
+
export { MemoryJoinedStrandStore, KeyStoreJoinedStrandStore, type JoinedStrandStore, type JoinedStrandRecord } from './joined-strand-store.js';
|
|
17
|
+
export { MemoryStrandPeerBookStore, PersistentStrandPeerBookStore, mergeStrandPeerEntry, sanitizeStrandPeerEntry, strandPeerFreshness, MAX_STRAND_PEERS, STRAND_PEER_MAX_AGE_MS, type StrandPeerBookStore, type StrandPeerBookOptions, type StrandPeerEntry } from './strand-peer-book.js';
|
|
18
|
+
export { StrandPeerObserver, dialableAddrs, connectedIdentifiedPeers, STRAND_PEER_OBSERVE_THROTTLE_MS, type StrandPeerObservation, type StrandPeerObserverDeps, type StrandPeerObserverOptions, type ConnectedIdentifiedPeer } from './strand-peer-observer.js';
|
|
19
|
+
export { STRAND_PEER_BOOK_PROTOCOL, SIGNED_STRAND_PEER_ENTRY_VERSION, STRAND_PEER_ISSUED_AT_SKEW_MS, MAX_BOOK_FRAME_SIZE, StrandPeerBookService, exchangeStrandPeerBook, signStrandPeerEntry, signedStrandPeerEntryPayload, verifySignedStrandPeerEntry, verifyStrandPeerBookFrame, trimBookFrameToFit, assertBookFrameFits, type SignedStrandPeerEntry, type StrandPeerBookFrame, type StrandPeerEntryVerdict, type StrandPeerBookServiceDeps, type ExchangeStrandPeerBookOptions } from './strand-peer-book-protocol.js';
|
|
20
|
+
export { StrandPeerBookSwap, STRAND_PEER_BOOK_SWAP_THROTTLE_MS, OWN_ENTRY_RESIGN_DEBOUNCE_MS, type StrandPeerBookSwapDeps, type StrandPeerBookSwapOptions } from './strand-peer-book-swap.js';
|
|
16
21
|
export { controlStorageScope, isControlStorageScope, isValidStrandScopeKey, assertStrandScopeKey, InvalidStrandIdError } from './storage-scope.js';
|
|
17
22
|
export { StrandDatabase, type StrandDatabaseConfig } from './strand-database.js';
|
|
18
23
|
export { StrandWatcher, type StrandWatcherCallbacks, type StrandQueryable, type SAppIdLookup, type StrandRowWithApp } from './strand-watcher.js';
|
package/dist/index.js
CHANGED
|
@@ -49,6 +49,22 @@ export { MemoryBootstrapPeerStore, PersistentBootstrapPeerStore } from './bootst
|
|
|
49
49
|
// DIVERGES from theirs (an unreadable slot cold-starts rather than throwing) —
|
|
50
50
|
// see the module comment before unifying the three.
|
|
51
51
|
export { MemoryEnrolledMachineStore, PersistentEnrolledMachineStore } from './enrolled-machine-store.js';
|
|
52
|
+
// Node-local record of the strands this node joined from ANOTHER party, re-offered on
|
|
53
|
+
// every start as `strand:discovered`. Cross-platform: its durable form rides the
|
|
54
|
+
// KeyStore seam above (the record carries a closed strand's read secret), so there is
|
|
55
|
+
// no file-backed subpath.
|
|
56
|
+
export { MemoryJoinedStrandStore, KeyStoreJoinedStrandStore } from './joined-strand-store.js';
|
|
57
|
+
// Node-local strand peer book: per strand, the strand peers this node has met and
|
|
58
|
+
// their last-known addresses, dialed first on every launch so a restarted machine
|
|
59
|
+
// re-finds the other parties. Same cross-platform split as the bootstrap-peer store
|
|
60
|
+
// above — interface + in-memory + slot-backed stores here, Node-only file backend
|
|
61
|
+
// behind the subpath '@serfab/cadre-core/strand-peer-book-file'.
|
|
62
|
+
export { MemoryStrandPeerBookStore, PersistentStrandPeerBookStore, mergeStrandPeerEntry, sanitizeStrandPeerEntry, strandPeerFreshness, MAX_STRAND_PEERS, STRAND_PEER_MAX_AGE_MS } from './strand-peer-book.js';
|
|
63
|
+
export { StrandPeerObserver, dialableAddrs, connectedIdentifiedPeers, STRAND_PEER_OBSERVE_THROTTLE_MS } from './strand-peer-observer.js';
|
|
64
|
+
// The signed book SWAP between strand peers (`/sereus/strand-peers/1.0.0`): the wire
|
|
65
|
+
// protocol, signing and verification, and the per-strand driver that arms it.
|
|
66
|
+
export { STRAND_PEER_BOOK_PROTOCOL, SIGNED_STRAND_PEER_ENTRY_VERSION, STRAND_PEER_ISSUED_AT_SKEW_MS, MAX_BOOK_FRAME_SIZE, StrandPeerBookService, exchangeStrandPeerBook, signStrandPeerEntry, signedStrandPeerEntryPayload, verifySignedStrandPeerEntry, verifyStrandPeerBookFrame, trimBookFrameToFit, assertBookFrameFits } from './strand-peer-book-protocol.js';
|
|
67
|
+
export { StrandPeerBookSwap, STRAND_PEER_BOOK_SWAP_THROTTLE_MS, OWN_ENTRY_RESIGN_DEBOUNCE_MS } from './strand-peer-book-swap.js';
|
|
52
68
|
// Storage scope keys — what `CadreNodeConfig.storage.provider` is called with. A
|
|
53
69
|
// strand's key is its strand id; the control database's key carries the party id,
|
|
54
70
|
// so two parties on one device never share a control store. Every key stays within
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import type { KeyStore } from './key-store.js';
|
|
2
|
+
import type { StrandRow } from './types.js';
|
|
3
|
+
/** One strand this node joined from ANOTHER party — nothing in this party's control DB names it. */
|
|
4
|
+
export interface JoinedStrandRecord {
|
|
5
|
+
/** The strand id (a valid scope key, see storage-scope.ts). */
|
|
6
|
+
Id: string;
|
|
7
|
+
Type: 'o' | 'c';
|
|
8
|
+
/** The closed strand's shared read secret the formation delivered; null for an open strand. */
|
|
9
|
+
MemberPrivateKey: string | null;
|
|
10
|
+
/** Wall-clock ms this node first recorded the join. Diagnostics only. */
|
|
11
|
+
joinedAt: number;
|
|
12
|
+
}
|
|
13
|
+
export interface JoinedStrandStore {
|
|
14
|
+
/** Party this store is scoped to. */
|
|
15
|
+
readonly partyId: string;
|
|
16
|
+
/** Every remembered join. A call reflects every {@link record}/{@link forget} that resolved before it was made. */
|
|
17
|
+
list(): Promise<JoinedStrandRecord[]>;
|
|
18
|
+
/** Remember a join, REPLACING any record with the same `Id`. */
|
|
19
|
+
record(record: JoinedStrandRecord): Promise<void>;
|
|
20
|
+
/** Forget a join. A no-op when there is no record for `strandId`. */
|
|
21
|
+
forget(strandId: string): Promise<void>;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* The {@link StrandRow} a record stands for — the shape `addStrand` and `strand:discovered`
|
|
25
|
+
* carry. `FounderOwnerKey` is null because a joiner never founds; `CadreNode.launchStrand`
|
|
26
|
+
* reads null as "not mine" and joins.
|
|
27
|
+
*/
|
|
28
|
+
export declare function joinedStrandRow(record: JoinedStrandRecord): StrandRow;
|
|
29
|
+
/**
|
|
30
|
+
* Ephemeral store for a node without a `keyStore`. Warns once, at the first join it is
|
|
31
|
+
* asked to remember, because a join held only here is not re-offered after a restart —
|
|
32
|
+
* exactly the gotchoices/sereus#18 shape, and it should show in a log rather than pass
|
|
33
|
+
* silently.
|
|
34
|
+
*/
|
|
35
|
+
export declare class MemoryJoinedStrandStore implements JoinedStrandStore {
|
|
36
|
+
readonly partyId: string;
|
|
37
|
+
private readonly records;
|
|
38
|
+
private warned;
|
|
39
|
+
constructor(partyId: string);
|
|
40
|
+
list(): Promise<JoinedStrandRecord[]>;
|
|
41
|
+
record(record: JoinedStrandRecord): Promise<void>;
|
|
42
|
+
forget(strandId: string): Promise<void>;
|
|
43
|
+
private warnOnce;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Durable store over a {@link KeyStore}: one slot per join, id
|
|
47
|
+
* `cadre/joined-strand/<base64url party id>/<strand id>`, holding the record's UTF-8 JSON.
|
|
48
|
+
* The party segment is base64url for the reason `controlStorageScope` gives: a party id is
|
|
49
|
+
* arbitrary text, and base64url never contains the `/` that ends the segment.
|
|
50
|
+
*
|
|
51
|
+
* Loads every slot once, at the first {@link list}, then answers from memory and writes
|
|
52
|
+
* through, so the strand watcher's five-second poll does not read the enclave on every
|
|
53
|
+
* pass. A load that fails — `KeyStoreAccessError` from a refused unlock prompt, say —
|
|
54
|
+
* is rethrown rather than read as "no joins" and retried at the next call, exactly as
|
|
55
|
+
* `loadOrCreateIdentityKey` treats the identity slot. A slot that does not parse as a
|
|
56
|
+
* record for its own id is dropped with a log and its siblings kept: refusing to start
|
|
57
|
+
* repairs nothing, and the other joins are still good.
|
|
58
|
+
*/
|
|
59
|
+
export declare class KeyStoreJoinedStrandStore implements JoinedStrandStore {
|
|
60
|
+
private readonly keyStore;
|
|
61
|
+
readonly partyId: string;
|
|
62
|
+
private readonly slotPrefix;
|
|
63
|
+
/** The loaded records; null until a load succeeds. */
|
|
64
|
+
private records;
|
|
65
|
+
/** Runs every KeyStore access in call order, so a load never interleaves with a write. */
|
|
66
|
+
private queue;
|
|
67
|
+
constructor(keyStore: KeyStore, partyId: string);
|
|
68
|
+
list(): Promise<JoinedStrandRecord[]>;
|
|
69
|
+
/** Throws `InvalidStrandIdError` for an id that could never load back, before anything is written. */
|
|
70
|
+
record(record: JoinedStrandRecord): Promise<void>;
|
|
71
|
+
forget(strandId: string): Promise<void>;
|
|
72
|
+
private slotId;
|
|
73
|
+
private inOrder;
|
|
74
|
+
private loaded;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* What the strand watcher sees of the joined-strand store: the control rows plus one row per
|
|
78
|
+
* remembered join, which is how a join comes back as `strand:discovered` (or auto-launches)
|
|
79
|
+
* after a restart with no second offer path. One instance per node session.
|
|
80
|
+
*
|
|
81
|
+
* Holds the two pieces of state a plain union would get wrong, both of which would otherwise
|
|
82
|
+
* make the watcher detach running strands, since a joined row missing from a poll reads to it
|
|
83
|
+
* as a removal:
|
|
84
|
+
* - the last list the store answered, reused when a later list fails, so a read failure is
|
|
85
|
+
* not "every join was forgotten";
|
|
86
|
+
* - joins forgotten because this party was removed from the strand
|
|
87
|
+
* ({@link forgetAfterThisSession}): gone from the store, so the next start does not
|
|
88
|
+
* re-attach them, but still offered until this session ends, because `strand:revoked`
|
|
89
|
+
* promises that nothing is torn down for the app.
|
|
90
|
+
*/
|
|
91
|
+
export declare class JoinedStrandRows {
|
|
92
|
+
private readonly store;
|
|
93
|
+
private lastListed;
|
|
94
|
+
private readonly keptForSession;
|
|
95
|
+
constructor(store: JoinedStrandStore);
|
|
96
|
+
/**
|
|
97
|
+
* `control` plus a row for every remembered join. A control row wins an id collision: the
|
|
98
|
+
* strand is this party's own now (its founding party enrolled this machine, say), the
|
|
99
|
+
* control database remembers it, and the record is stale — so it is forgotten here.
|
|
100
|
+
*/
|
|
101
|
+
withControlRows(control: readonly StrandRow[]): Promise<StrandRow[]>;
|
|
102
|
+
/** Forget a join for good: the app is leaving the strand. */
|
|
103
|
+
forget(strandId: string): Promise<void>;
|
|
104
|
+
/**
|
|
105
|
+
* Forget a join durably, but keep offering it until this session ends. For a strand this
|
|
106
|
+
* party was removed from: it must not re-attach on every launch, and it must not be torn
|
|
107
|
+
* down underneath the app either. A no-op for a strand with no record.
|
|
108
|
+
*/
|
|
109
|
+
forgetAfterThisSession(strandId: string): Promise<void>;
|
|
110
|
+
private listed;
|
|
111
|
+
private forgetSuperseded;
|
|
112
|
+
}
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node-local record of the strands this node joined from ANOTHER party.
|
|
3
|
+
*
|
|
4
|
+
* A party's own strands come back after a restart through its control database: the
|
|
5
|
+
* `Strand` table holds their rows, the strand watcher polls it, and each row no sApp
|
|
6
|
+
* config claims is offered as `strand:discovered`. A strand joined through formation with
|
|
7
|
+
* another party (`CadreNode.formStrand`) has no row there — the other party's control
|
|
8
|
+
* database holds it — so nothing re-offered it after a restart, and every embedding app
|
|
9
|
+
* kept its own list of joins, read secret included (gotchoices/sereus#18).
|
|
10
|
+
*
|
|
11
|
+
* `CadreNode` records each such join here, hands the records to its strand watcher beside
|
|
12
|
+
* the control rows ({@link JoinedStrandRows}), and forgets one on `forgetJoinedStrand` or
|
|
13
|
+
* when this party is removed from the strand.
|
|
14
|
+
*
|
|
15
|
+
* Two implementations:
|
|
16
|
+
* - {@link MemoryJoinedStrandStore} — joins die with the process. The default only for a
|
|
17
|
+
* node configured with no `keyStore`.
|
|
18
|
+
* - {@link KeyStoreJoinedStrandStore} — one {@link KeyStore} slot per join. A record holds
|
|
19
|
+
* the closed strand's shared read secret, and the KeyStore is the one seam every
|
|
20
|
+
* platform already routes secrets through (the platform enclave on React Native, the
|
|
21
|
+
* state directory for `FileKeyStore`), so the record goes there rather than into a
|
|
22
|
+
* `DurableSlot` like the bootstrap-peer store.
|
|
23
|
+
*
|
|
24
|
+
* Party-scoped like every other node-local store, because one KeyStore can serve several
|
|
25
|
+
* parties: the React Native app keeps one per device and lets the user switch party. A
|
|
26
|
+
* join made for one party must never be offered to a node started for another.
|
|
27
|
+
*
|
|
28
|
+
* Dependency-free beyond the KeyStore seam, so safe in every entry graph.
|
|
29
|
+
*/
|
|
30
|
+
import debug from 'debug';
|
|
31
|
+
import { toString as uint8ArrayToString, fromString as uint8ArrayFromString } from 'uint8arrays';
|
|
32
|
+
import { assertStrandScopeKey, isValidStrandScopeKey } from './storage-scope.js';
|
|
33
|
+
const log = debug('sereus:cadre:joined-strand-store');
|
|
34
|
+
/**
|
|
35
|
+
* The {@link StrandRow} a record stands for — the shape `addStrand` and `strand:discovered`
|
|
36
|
+
* carry. `FounderOwnerKey` is null because a joiner never founds; `CadreNode.launchStrand`
|
|
37
|
+
* reads null as "not mine" and joins.
|
|
38
|
+
*/
|
|
39
|
+
export function joinedStrandRow(record) {
|
|
40
|
+
return { Id: record.Id, Type: record.Type, MemberPrivateKey: record.MemberPrivateKey, FounderOwnerKey: null };
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Ephemeral store for a node without a `keyStore`. Warns once, at the first join it is
|
|
44
|
+
* asked to remember, because a join held only here is not re-offered after a restart —
|
|
45
|
+
* exactly the gotchoices/sereus#18 shape, and it should show in a log rather than pass
|
|
46
|
+
* silently.
|
|
47
|
+
*/
|
|
48
|
+
export class MemoryJoinedStrandStore {
|
|
49
|
+
constructor(partyId) {
|
|
50
|
+
this.partyId = partyId;
|
|
51
|
+
this.records = new Map();
|
|
52
|
+
this.warned = false;
|
|
53
|
+
}
|
|
54
|
+
async list() {
|
|
55
|
+
return [...this.records.values()];
|
|
56
|
+
}
|
|
57
|
+
async record(record) {
|
|
58
|
+
this.warnOnce();
|
|
59
|
+
this.records.set(record.Id, { ...record });
|
|
60
|
+
}
|
|
61
|
+
async forget(strandId) {
|
|
62
|
+
this.records.delete(strandId);
|
|
63
|
+
}
|
|
64
|
+
warnOnce() {
|
|
65
|
+
if (this.warned) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
this.warned = true;
|
|
69
|
+
console.warn('CadreNode has no keyStore and no joinedStrands.store, so strands joined from another party ' +
|
|
70
|
+
'are remembered in memory only and will NOT be re-offered after a restart. Configure a keyStore, ' +
|
|
71
|
+
'or inject joinedStrands: { store: new KeyStoreJoinedStrandStore(<a durable KeyStore>, partyId) }.');
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/** Slot id prefix for every joined-strand record; the party segment and the strand id follow. */
|
|
75
|
+
const SLOT_PREFIX = 'cadre/joined-strand/';
|
|
76
|
+
/**
|
|
77
|
+
* Durable store over a {@link KeyStore}: one slot per join, id
|
|
78
|
+
* `cadre/joined-strand/<base64url party id>/<strand id>`, holding the record's UTF-8 JSON.
|
|
79
|
+
* The party segment is base64url for the reason `controlStorageScope` gives: a party id is
|
|
80
|
+
* arbitrary text, and base64url never contains the `/` that ends the segment.
|
|
81
|
+
*
|
|
82
|
+
* Loads every slot once, at the first {@link list}, then answers from memory and writes
|
|
83
|
+
* through, so the strand watcher's five-second poll does not read the enclave on every
|
|
84
|
+
* pass. A load that fails — `KeyStoreAccessError` from a refused unlock prompt, say —
|
|
85
|
+
* is rethrown rather than read as "no joins" and retried at the next call, exactly as
|
|
86
|
+
* `loadOrCreateIdentityKey` treats the identity slot. A slot that does not parse as a
|
|
87
|
+
* record for its own id is dropped with a log and its siblings kept: refusing to start
|
|
88
|
+
* repairs nothing, and the other joins are still good.
|
|
89
|
+
*/
|
|
90
|
+
export class KeyStoreJoinedStrandStore {
|
|
91
|
+
constructor(keyStore, partyId) {
|
|
92
|
+
this.keyStore = keyStore;
|
|
93
|
+
this.partyId = partyId;
|
|
94
|
+
/** The loaded records; null until a load succeeds. */
|
|
95
|
+
this.records = null;
|
|
96
|
+
/** Runs every KeyStore access in call order, so a load never interleaves with a write. */
|
|
97
|
+
this.queue = Promise.resolve();
|
|
98
|
+
this.slotPrefix = SLOT_PREFIX + uint8ArrayToString(uint8ArrayFromString(partyId, 'utf8'), 'base64url') + '/';
|
|
99
|
+
}
|
|
100
|
+
list() {
|
|
101
|
+
return this.inOrder(async () => [...(await this.loaded()).values()]);
|
|
102
|
+
}
|
|
103
|
+
/** Throws `InvalidStrandIdError` for an id that could never load back, before anything is written. */
|
|
104
|
+
record(record) {
|
|
105
|
+
assertStrandScopeKey(record.Id);
|
|
106
|
+
const stored = { ...record };
|
|
107
|
+
return this.inOrder(async () => {
|
|
108
|
+
await this.keyStore.set(this.slotId(record.Id), uint8ArrayFromString(JSON.stringify(stored), 'utf8'));
|
|
109
|
+
this.records?.set(record.Id, stored);
|
|
110
|
+
log('joined strand remembered (party=%s, strand=%s, type=%s)', this.partyId, record.Id, record.Type);
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
forget(strandId) {
|
|
114
|
+
return this.inOrder(async () => {
|
|
115
|
+
await this.keyStore.delete(this.slotId(strandId));
|
|
116
|
+
this.records?.delete(strandId);
|
|
117
|
+
log('joined strand forgotten (party=%s, strand=%s)', this.partyId, strandId);
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
slotId(strandId) {
|
|
121
|
+
return this.slotPrefix + strandId;
|
|
122
|
+
}
|
|
123
|
+
inOrder(op) {
|
|
124
|
+
const result = this.queue.then(op);
|
|
125
|
+
// The caller receives `result`, rejection included; the queue only needs to know it settled.
|
|
126
|
+
this.queue = result.catch(() => undefined);
|
|
127
|
+
return result;
|
|
128
|
+
}
|
|
129
|
+
// NOTE: a failed load is retried at the next list(), which is every strand-watcher poll;
|
|
130
|
+
// over a backend that gates reads behind an unlock prompt the user keeps declining, that
|
|
131
|
+
// is a prompt every five seconds. Every KeyStore shipped today is ungated for this reason
|
|
132
|
+
// (see `SecureStoreKeyStoreOptions.requireAuthentication`); if one is ever gated, back
|
|
133
|
+
// off the retry here.
|
|
134
|
+
async loaded() {
|
|
135
|
+
if (this.records) {
|
|
136
|
+
return this.records;
|
|
137
|
+
}
|
|
138
|
+
const records = new Map();
|
|
139
|
+
for (const slot of await this.keyStore.list()) {
|
|
140
|
+
if (!slot.startsWith(this.slotPrefix)) {
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
const strandId = slot.slice(this.slotPrefix.length);
|
|
144
|
+
const bytes = await this.keyStore.get(slot);
|
|
145
|
+
if (!bytes) {
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
const record = parseRecord(strandId, bytes);
|
|
149
|
+
if (record) {
|
|
150
|
+
records.set(strandId, record);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
this.records = records;
|
|
154
|
+
log('joined strands loaded (party=%s, count=%d)', this.partyId, records.size);
|
|
155
|
+
return records;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/** The record a slot holds, or undefined (logged) when it is not one for `strandId`. */
|
|
159
|
+
function parseRecord(strandId, bytes) {
|
|
160
|
+
let parsed;
|
|
161
|
+
try {
|
|
162
|
+
parsed = JSON.parse(uint8ArrayToString(bytes, 'utf8'));
|
|
163
|
+
}
|
|
164
|
+
catch (error) {
|
|
165
|
+
log('dropping joined-strand slot for %s: not JSON (%o)', strandId, error);
|
|
166
|
+
return undefined;
|
|
167
|
+
}
|
|
168
|
+
const { Id, Type, MemberPrivateKey, joinedAt } = (typeof parsed === 'object' && parsed !== null ? parsed : {});
|
|
169
|
+
const valid = Id === strandId
|
|
170
|
+
&& isValidStrandScopeKey(strandId)
|
|
171
|
+
&& (Type === 'o' || Type === 'c')
|
|
172
|
+
&& (MemberPrivateKey === null || typeof MemberPrivateKey === 'string')
|
|
173
|
+
&& typeof joinedAt === 'number';
|
|
174
|
+
if (!valid) {
|
|
175
|
+
log('dropping joined-strand slot for %s: not a joined-strand record for that id', strandId);
|
|
176
|
+
return undefined;
|
|
177
|
+
}
|
|
178
|
+
return { Id: strandId, Type: Type, MemberPrivateKey: MemberPrivateKey, joinedAt: joinedAt };
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* What the strand watcher sees of the joined-strand store: the control rows plus one row per
|
|
182
|
+
* remembered join, which is how a join comes back as `strand:discovered` (or auto-launches)
|
|
183
|
+
* after a restart with no second offer path. One instance per node session.
|
|
184
|
+
*
|
|
185
|
+
* Holds the two pieces of state a plain union would get wrong, both of which would otherwise
|
|
186
|
+
* make the watcher detach running strands, since a joined row missing from a poll reads to it
|
|
187
|
+
* as a removal:
|
|
188
|
+
* - the last list the store answered, reused when a later list fails, so a read failure is
|
|
189
|
+
* not "every join was forgotten";
|
|
190
|
+
* - joins forgotten because this party was removed from the strand
|
|
191
|
+
* ({@link forgetAfterThisSession}): gone from the store, so the next start does not
|
|
192
|
+
* re-attach them, but still offered until this session ends, because `strand:revoked`
|
|
193
|
+
* promises that nothing is torn down for the app.
|
|
194
|
+
*/
|
|
195
|
+
export class JoinedStrandRows {
|
|
196
|
+
constructor(store) {
|
|
197
|
+
this.store = store;
|
|
198
|
+
this.lastListed = [];
|
|
199
|
+
this.keptForSession = new Map();
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* `control` plus a row for every remembered join. A control row wins an id collision: the
|
|
203
|
+
* strand is this party's own now (its founding party enrolled this machine, say), the
|
|
204
|
+
* control database remembers it, and the record is stale — so it is forgotten here.
|
|
205
|
+
*/
|
|
206
|
+
async withControlRows(control) {
|
|
207
|
+
const controlIds = new Set(control.map((row) => row.Id));
|
|
208
|
+
const joined = new Map(this.keptForSession);
|
|
209
|
+
for (const record of await this.listed()) {
|
|
210
|
+
joined.set(record.Id, record);
|
|
211
|
+
}
|
|
212
|
+
const rows = [...control];
|
|
213
|
+
for (const record of joined.values()) {
|
|
214
|
+
if (controlIds.has(record.Id)) {
|
|
215
|
+
await this.forgetSuperseded(record.Id);
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
rows.push(joinedStrandRow(record));
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return rows;
|
|
222
|
+
}
|
|
223
|
+
/** Forget a join for good: the app is leaving the strand. */
|
|
224
|
+
async forget(strandId) {
|
|
225
|
+
this.keptForSession.delete(strandId);
|
|
226
|
+
await this.store.forget(strandId);
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Forget a join durably, but keep offering it until this session ends. For a strand this
|
|
230
|
+
* party was removed from: it must not re-attach on every launch, and it must not be torn
|
|
231
|
+
* down underneath the app either. A no-op for a strand with no record.
|
|
232
|
+
*/
|
|
233
|
+
async forgetAfterThisSession(strandId) {
|
|
234
|
+
const record = (await this.listed()).find((listed) => listed.Id === strandId);
|
|
235
|
+
if (!record) {
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
// Kept BEFORE the store forgets, so no poll can list the store without it and union
|
|
239
|
+
// without the kept copy.
|
|
240
|
+
this.keptForSession.set(strandId, record);
|
|
241
|
+
await this.store.forget(strandId);
|
|
242
|
+
}
|
|
243
|
+
async listed() {
|
|
244
|
+
try {
|
|
245
|
+
this.lastListed = await this.store.list();
|
|
246
|
+
}
|
|
247
|
+
catch (error) {
|
|
248
|
+
log('joined-strand store list failed; offering the last list it answered (%d join(s)): %o', this.lastListed.length, error);
|
|
249
|
+
}
|
|
250
|
+
return this.lastListed;
|
|
251
|
+
}
|
|
252
|
+
async forgetSuperseded(strandId) {
|
|
253
|
+
this.keptForSession.delete(strandId);
|
|
254
|
+
try {
|
|
255
|
+
await this.store.forget(strandId);
|
|
256
|
+
log('joined strand %s now has a control row — record forgotten', strandId);
|
|
257
|
+
}
|
|
258
|
+
catch (error) {
|
|
259
|
+
log('forgetting superseded joined strand %s failed; the next poll retries: %o', strandId, error);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
//# sourceMappingURL=joined-strand-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"joined-strand-store.js","sourceRoot":"","sources":["../src/joined-strand-store.ts"],"names":[],"mappings":"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"}
|
package/dist/key-store.d.ts
CHANGED
|
@@ -29,6 +29,12 @@ export declare const DEFAULT_IDENTITY_KEY_ID: KeyId;
|
|
|
29
29
|
* Key material is raw bytes (e.g. libp2p protobuf-serialized private keys).
|
|
30
30
|
* Text-only backends encode/decode (base64) internally; byte-native backends
|
|
31
31
|
* (LevelDB) store as-is.
|
|
32
|
+
*
|
|
33
|
+
* Not only keys: `KeyStoreJoinedStrandStore` keeps one small UTF-8 JSON record
|
|
34
|
+
* (about 200 bytes, a closed strand's read secret among its fields) per strand
|
|
35
|
+
* this node joined from another party, under ids beginning
|
|
36
|
+
* `cadre/joined-strand/`. {@link list} therefore returns those ids too, and a
|
|
37
|
+
* backend must accept `/` in an id and values of that size.
|
|
32
38
|
*/
|
|
33
39
|
export interface KeyStore {
|
|
34
40
|
/** Resolves to the stored material, or undefined if the slot is empty. */
|
package/dist/key-store.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"key-store.js","sourceRoot":"","sources":["../src/key-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH;;;;GAIG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAU,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"key-store.js","sourceRoot":"","sources":["../src/key-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH;;;;GAIG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAU,gBAAgB,CAAC;AAgC/D;;;;;;;;;;GAUG;AACH,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAG7C,YAAY,KAAY,EAAE,OAAe,EAAE,OAA6B;QACvE,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;QAClC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACpB,CAAC;CACD;AAED;;;;;;;;GAQG;AACH,MAAM,OAAO,gBAAgB;IAA7B;QACkB,UAAK,GAAG,IAAI,GAAG,EAAqB,CAAC;IAkBvD,CAAC;IAhBA,KAAK,CAAC,GAAG,CAAC,KAAY;QACrB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACrC,OAAO,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IAC5C,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,KAAY,EAAE,WAAuB;QAC9C,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,WAAW,CAAC,KAAK,EAAE,CAAC,CAAC;IAC5C,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAAY;QACxB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,IAAI;QACT,OAAO,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IAC/B,CAAC;CACD"}
|
|
@@ -28,15 +28,16 @@ export interface DurableSlot {
|
|
|
28
28
|
}
|
|
29
29
|
/**
|
|
30
30
|
* What one unusable entry means for its siblings — the single intentional
|
|
31
|
-
* difference between the
|
|
31
|
+
* difference between the records:
|
|
32
32
|
*
|
|
33
33
|
* - `'discard-all'` (the trusted-owner anchor): a record that cannot be read
|
|
34
34
|
* in full is not an anchor. Trusting a *subset* of the keys a file claims is
|
|
35
35
|
* a silent, security-relevant downgrade, so the whole record is discarded
|
|
36
36
|
* and the node trusts no one until re-seeded out of band.
|
|
37
|
-
* - `'drop-entry'` (the bootstrap-peer store
|
|
38
|
-
*
|
|
39
|
-
* discard a stranded node's only remaining way back
|
|
37
|
+
* - `'drop-entry'` (the bootstrap-peer store and the strand peer book): the
|
|
38
|
+
* record is a best-effort dial list and nothing in it is trust-bearing, so one
|
|
39
|
+
* junk entry must not discard a stranded node's only remaining way back to
|
|
40
|
+
* its party or its strand's peers.
|
|
40
41
|
*/
|
|
41
42
|
export type UnusableEntryPolicy = 'discard-all' | 'drop-entry';
|
|
42
43
|
/** What a particular node-local record persists, and how it validates it. */
|
|
@@ -4,15 +4,18 @@
|
|
|
4
4
|
* from shared group state:
|
|
5
5
|
*
|
|
6
6
|
* - the trusted-owner anchor (`trusted-owner-store.ts`),
|
|
7
|
-
* - the cold-start bootstrap-peer store (`bootstrap-peer-store.ts`)
|
|
7
|
+
* - the cold-start bootstrap-peer store (`bootstrap-peer-store.ts`),
|
|
8
|
+
* - the strand peer book (`strand-peer-book.ts`), whose entries are one map per
|
|
9
|
+
* strand rather than one value per key — the validation hook below is what
|
|
10
|
+
* lets it drop a single junk peer without dropping the strand.
|
|
8
11
|
*
|
|
9
|
-
*
|
|
12
|
+
* ANOTHER node-local record — the enrolled-machine count
|
|
10
13
|
* (`enrolled-machine-store.ts`) — reuses {@link DurableSlot} but deliberately
|
|
11
14
|
* NOT this module's snapshot machinery: it is one scalar rather than an entry
|
|
12
15
|
* map, and it must cold-start rather than throw on an unreadable slot. Its
|
|
13
16
|
* module comment carries the reasoning; do not fold it in here.
|
|
14
17
|
*
|
|
15
|
-
*
|
|
18
|
+
* Every record here is the same mechanism with a different payload: a
|
|
16
19
|
* `{ version, partyId, <entries> }` envelope, snapshot-written whole on every
|
|
17
20
|
* change, loaded under one fail-safe-but-not-fail-silent policy. The only part
|
|
18
21
|
* that differs per platform is WHERE the bytes are kept — Node writes a file,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node-local-snapshot.js","sourceRoot":"","sources":["../src/node-local-snapshot.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"node-local-snapshot.js","sourceRoot":"","sources":["../src/node-local-snapshot.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,6 +8,15 @@ import { BlockTransferClient, type IRawStorage } from '@optimystic/db-p2p';
|
|
|
8
8
|
* changes it or starts exporting it.
|
|
9
9
|
*/
|
|
10
10
|
export declare const MAX_BLOCK_MESSAGE_BYTES: number;
|
|
11
|
+
/**
|
|
12
|
+
* Whether an identified peer's protocol list names this network's own block-transfer
|
|
13
|
+
* protocol — the one gate that decides whether {@link PeerJoinBackfill} schedules a peer at
|
|
14
|
+
* all. A peer that lacks it (a bare circuit relay, a bootstrap node, a stranger the control
|
|
15
|
+
* network's inbound gate admitted without membership) cannot receive a push no matter how
|
|
16
|
+
* long it is dialed, since the protocol id is namespaced per network. Exported because a
|
|
17
|
+
* later strand peer-address ticket's identify-driven observation needs the identical test.
|
|
18
|
+
*/
|
|
19
|
+
export declare function speaksBlockTransfer(protocols: readonly string[], protocolPrefix: string): boolean;
|
|
11
20
|
/**
|
|
12
21
|
* Consecutive failed catch-up runs against ONE peer before the module says so on
|
|
13
22
|
* `console.warn` rather than only in its DEBUG log. At the default backoff that is reached
|
|
@@ -109,7 +118,7 @@ export interface PeerJoinBackfillResult {
|
|
|
109
118
|
* Best-effort throughout: nothing here throws into a libp2p event handler or into a
|
|
110
119
|
* runtime bring-up; a failed chunk is logged and the run continues. A peer is marked
|
|
111
120
|
* fully caught up ONLY after a run with no thrown chunk and an empty `missing` list, so
|
|
112
|
-
* the next `
|
|
121
|
+
* the next `peer:identify` from a peer whose catch-up failed retries it.
|
|
113
122
|
*/
|
|
114
123
|
export declare class PeerJoinBackfill {
|
|
115
124
|
private readonly deps;
|
|
@@ -136,30 +145,40 @@ export declare class PeerJoinBackfill {
|
|
|
136
145
|
private readonly failures;
|
|
137
146
|
/**
|
|
138
147
|
* Epoch ms before which a peer's catch-up must not be re-run, set alongside a backoff timer
|
|
139
|
-
* that will run it. Its presence is what makes `
|
|
148
|
+
* that will run it. Its presence is what makes `peer:identify` churn free: a schedule
|
|
140
149
|
* arriving inside the wait is dropped, rather than collapsing the backoff to the debounce.
|
|
141
150
|
*/
|
|
142
151
|
private readonly retryAfter;
|
|
143
152
|
/** Peers already reported on `console.warn`; reset when a run finally lands cleanly. */
|
|
144
153
|
private readonly warned;
|
|
145
|
-
private readonly
|
|
154
|
+
private readonly onPeerIdentify;
|
|
146
155
|
private loggedNoListBlockIds;
|
|
147
156
|
constructor(deps: PeerJoinBackfillDeps, config?: PeerJoinBackfillConfig);
|
|
148
|
-
/**
|
|
157
|
+
/**
|
|
158
|
+
* Subscribe to `peer:identify` AND schedule a catch-up for already-connected peers whose
|
|
159
|
+
* stored protocols already name this network's block-transfer protocol — a peer that does
|
|
160
|
+
* not speak it (a bare circuit relay, a bootstrap node) is never scheduled at all. See
|
|
161
|
+
* {@link speaksBlockTransfer} and the module comment.
|
|
162
|
+
*/
|
|
149
163
|
start(): void;
|
|
150
164
|
/** Unsubscribe, clear timers; in-flight runs observe the stopped flag and bail. */
|
|
151
165
|
stop(): void;
|
|
152
166
|
/**
|
|
153
|
-
* (Re-)schedule a debounced catch-up for every currently-connected peer
|
|
154
|
-
*
|
|
155
|
-
* peer
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
167
|
+
* (Re-)schedule a debounced catch-up for every currently-connected peer whose protocols, as
|
|
168
|
+
* already stored in the libp2p peer store, name this network's block-transfer protocol. A
|
|
169
|
+
* peer not yet in the peer store — its identify has not finished — is left to the
|
|
170
|
+
* `peer:identify` handler rather than dialed blind; one whose stored protocols are known
|
|
171
|
+
* and lack ours is skipped outright. Idempotent and cheap otherwise (caught-up peers are
|
|
172
|
+
* skipped before any timer is set, and a peer whose run is in flight is deferred to the end
|
|
173
|
+
* of that run rather than dropped). Driven by {@link start}, and — on a gated network — by
|
|
174
|
+
* the embedder whenever membership changes, so a peer whose first pass was denied (connected
|
|
175
|
+
* before it was authorized: the production join order) is retried without waiting for a
|
|
176
|
+
* reconnect. Returns how many distinct peers were considered (for the start() log) — a peer
|
|
177
|
+
* holding several connections is one peer, and is scheduled once.
|
|
161
178
|
*/
|
|
162
|
-
scheduleConnectedPeers(): number
|
|
179
|
+
scheduleConnectedPeers(): Promise<number>;
|
|
180
|
+
/** Schedules `peerId` only if the peer store already knows it speaks this network's protocol. */
|
|
181
|
+
private scheduleIfKnownToSpeak;
|
|
163
182
|
/** Debounced entry point for connection churn: one run per peer per settle window. */
|
|
164
183
|
private schedulePeer;
|
|
165
184
|
/**
|
|
@@ -173,7 +192,7 @@ export declare class PeerJoinBackfill {
|
|
|
173
192
|
/**
|
|
174
193
|
* Re-arm one peer's catch-up after a run whose push failed, on a wait that doubles
|
|
175
194
|
* per consecutive failure up to `maxRetryBackoffMs`. Sets {@link retryAfter} alongside the
|
|
176
|
-
* timer, which is what makes `
|
|
195
|
+
* timer, which is what makes `peer:identify` churn inside the wait free.
|
|
177
196
|
*/
|
|
178
197
|
private scheduleRetryWithBackoff;
|
|
179
198
|
/**
|