@serfab/cadre-core 0.7.1 → 0.8.1
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 +9 -8
- package/dist/authority-key.d.ts +41 -0
- package/dist/authority-key.js +52 -0
- package/dist/authority-key.js.map +1 -0
- package/dist/cadre-node.d.ts +770 -11
- package/dist/cadre-node.js +1900 -88
- package/dist/cadre-node.js.map +1 -1
- package/dist/canonical-datetime.d.ts +33 -0
- package/dist/canonical-datetime.js +38 -0
- package/dist/canonical-datetime.js.map +1 -0
- package/dist/canonical-json.d.ts +12 -0
- package/dist/canonical-json.js +33 -0
- package/dist/canonical-json.js.map +1 -0
- package/dist/control-cohort.d.ts +63 -0
- package/dist/control-cohort.js +80 -0
- package/dist/control-cohort.js.map +1 -0
- package/dist/control-database.d.ts +259 -5
- package/dist/control-database.js +541 -128
- package/dist/control-database.js.map +1 -1
- package/dist/control-formation-recorder.d.ts +89 -0
- package/dist/control-formation-recorder.js +139 -0
- package/dist/control-formation-recorder.js.map +1 -0
- package/dist/control-schema.d.ts +12 -0
- package/dist/control-schema.js +199 -0
- package/dist/control-schema.js.map +1 -0
- package/dist/control-stream.d.ts +54 -0
- package/dist/control-stream.js +104 -0
- package/dist/control-stream.js.map +1 -0
- package/dist/device-token.d.ts +50 -0
- package/dist/device-token.js +66 -0
- package/dist/device-token.js.map +1 -0
- package/dist/diagnostics/connection-path.d.ts +118 -0
- package/dist/diagnostics/connection-path.js +204 -0
- package/dist/diagnostics/connection-path.js.map +1 -0
- package/dist/diagnostics/webrtc-turn-tracker.d.ts +50 -0
- package/dist/diagnostics/webrtc-turn-tracker.js +196 -0
- package/dist/diagnostics/webrtc-turn-tracker.js.map +1 -0
- package/dist/hibernation-manager.d.ts +79 -0
- package/dist/hibernation-manager.js +173 -23
- package/dist/hibernation-manager.js.map +1 -1
- package/dist/index.d.ts +25 -4
- package/dist/index.js +59 -4
- package/dist/index.js.map +1 -1
- package/dist/key-store-file.d.ts +52 -0
- package/dist/key-store-file.js +194 -0
- package/dist/key-store-file.js.map +1 -0
- package/dist/key-store.d.ts +75 -0
- package/dist/key-store.js +66 -0
- package/dist/key-store.js.map +1 -0
- package/dist/peer-authorization.d.ts +26 -0
- package/dist/peer-authorization.js +40 -0
- package/dist/peer-authorization.js.map +1 -0
- package/dist/peer-record.d.ts +89 -0
- package/dist/peer-record.js +117 -0
- package/dist/peer-record.js.map +1 -0
- package/dist/push-credentials.d.ts +34 -0
- package/dist/push-credentials.js +81 -0
- package/dist/push-credentials.js.map +1 -0
- package/dist/push-fanout.d.ts +137 -0
- package/dist/push-fanout.js +197 -0
- package/dist/push-fanout.js.map +1 -0
- package/dist/push-notifier-apns.d.ts +53 -0
- package/dist/push-notifier-apns.js +195 -0
- package/dist/push-notifier-apns.js.map +1 -0
- package/dist/push-notifier-fcm.d.ts +38 -0
- package/dist/push-notifier-fcm.js +183 -0
- package/dist/push-notifier-fcm.js.map +1 -0
- package/dist/push-notifier-shared.d.ts +18 -0
- package/dist/push-notifier-shared.js +25 -0
- package/dist/push-notifier-shared.js.map +1 -0
- package/dist/push-notifier.d.ts +71 -0
- package/dist/push-notifier.js +50 -0
- package/dist/push-notifier.js.map +1 -0
- package/dist/schema-verification.d.ts +11 -2
- package/dist/schema-verification.js +15 -4
- package/dist/schema-verification.js.map +1 -1
- package/dist/seed-bootstrap.d.ts +197 -9
- package/dist/seed-bootstrap.js +396 -137
- package/dist/seed-bootstrap.js.map +1 -1
- package/dist/seed-trust-policy.d.ts +63 -0
- package/dist/seed-trust-policy.js +56 -0
- package/dist/seed-trust-policy.js.map +1 -0
- package/dist/strand-addr-protocol.d.ts +132 -0
- package/dist/strand-addr-protocol.js +313 -0
- package/dist/strand-addr-protocol.js.map +1 -0
- package/dist/strand-cohort.d.ts +54 -0
- package/dist/strand-cohort.js +38 -0
- package/dist/strand-cohort.js.map +1 -0
- package/dist/strand-database.d.ts +54 -6
- package/dist/strand-database.js +88 -100
- package/dist/strand-database.js.map +1 -1
- package/dist/strand-formation-manager.d.ts +79 -19
- package/dist/strand-formation-manager.js +196 -104
- package/dist/strand-formation-manager.js.map +1 -1
- package/dist/strand-formation-protocol.d.ts +162 -0
- package/dist/strand-formation-protocol.js +279 -0
- package/dist/strand-formation-protocol.js.map +1 -0
- package/dist/strand-instance-manager.d.ts +73 -4
- package/dist/strand-instance-manager.js +167 -41
- package/dist/strand-instance-manager.js.map +1 -1
- package/dist/strand-member-key.d.ts +29 -0
- package/dist/strand-member-key.js +38 -0
- package/dist/strand-member-key.js.map +1 -0
- package/dist/strand-member-registry.d.ts +98 -0
- package/dist/strand-member-registry.js +129 -0
- package/dist/strand-member-registry.js.map +1 -0
- package/dist/strand-membership-writer.d.ts +361 -0
- package/dist/strand-membership-writer.js +449 -0
- package/dist/strand-membership-writer.js.map +1 -0
- package/dist/strand-solicitation.d.ts +77 -2
- package/dist/strand-solicitation.js +25 -4
- package/dist/strand-solicitation.js.map +1 -1
- package/dist/strand-wake-payload.d.ts +30 -0
- package/dist/strand-wake-payload.js +20 -0
- package/dist/strand-wake-payload.js.map +1 -0
- package/dist/strand-wake-protocol.d.ts +114 -0
- package/dist/strand-wake-protocol.js +257 -0
- package/dist/strand-wake-protocol.js.map +1 -0
- package/dist/strand-watcher.d.ts +6 -2
- package/dist/strand-watcher.js +57 -17
- package/dist/strand-watcher.js.map +1 -1
- package/dist/types.d.ts +406 -23
- package/dist/types.js +22 -5
- package/dist/types.js.map +1 -1
- package/package.json +14 -8
- package/src/authority-key.ts +68 -0
- package/src/cadre-node.ts +2937 -948
- package/src/canonical-datetime.ts +39 -0
- package/src/canonical-json.ts +30 -0
- package/src/control-cohort.ts +103 -0
- package/src/control-database.ts +931 -383
- package/src/control-formation-recorder.ts +151 -0
- package/src/control-schema.ts +198 -0
- package/src/control-stream.ts +128 -0
- package/src/device-token.ts +89 -0
- package/src/diagnostics/connection-path.ts +277 -0
- package/src/diagnostics/webrtc-turn-tracker.ts +222 -0
- package/src/hibernation-manager.ts +197 -28
- package/src/index.ts +273 -79
- package/src/key-store-file.ts +203 -0
- package/src/key-store.ts +99 -0
- package/src/peer-authorization.ts +53 -0
- package/src/peer-record.ts +146 -0
- package/src/push-credentials.ts +84 -0
- package/src/push-fanout.ts +272 -0
- package/src/push-notifier-apns.ts +243 -0
- package/src/push-notifier-fcm.ts +221 -0
- package/src/push-notifier-shared.ts +28 -0
- package/src/push-notifier.ts +93 -0
- package/src/schema-verification.ts +18 -4
- package/src/seed-bootstrap.ts +464 -188
- package/src/seed-trust-policy.ts +107 -0
- package/src/strand-addr-protocol.ts +410 -0
- package/src/strand-cohort.ts +77 -0
- package/src/strand-database.ts +113 -141
- package/src/strand-formation-manager.ts +233 -142
- package/src/strand-formation-protocol.ts +391 -0
- package/src/strand-instance-manager.ts +207 -56
- package/src/strand-member-key.ts +39 -0
- package/src/strand-member-registry.ts +177 -0
- package/src/strand-membership-writer.ts +640 -0
- package/src/strand-solicitation.ts +93 -4
- package/src/strand-wake-payload.ts +32 -0
- package/src/strand-wake-protocol.ts +331 -0
- package/src/strand-watcher.ts +61 -17
- package/src/types.ts +1012 -582
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strand-addr-protocol.js","sourceRoot":"","sources":["../src/strand-addr-protocol.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { StrandMode } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* A single CadrePeer membership row, as returned by
|
|
4
|
+
* `ControlDatabase.queryCadrePeers()`.
|
|
5
|
+
*/
|
|
6
|
+
export interface CohortPeerRow {
|
|
7
|
+
peerId: string;
|
|
8
|
+
/** Comma-joined list of multiaddr strings; `''` when no addrs were recorded. */
|
|
9
|
+
multiaddr: string | null;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Cohort-derived discovery seed for a strand's libp2p node. `bootstrapNodes`
|
|
13
|
+
* here are **strand-network** addresses resolved on demand from co-cadre
|
|
14
|
+
* siblings (see `collectStrandAddrs` / `STRAND_ADDR_PROTOCOL`), NOT the control
|
|
15
|
+
* addresses stored in `CadrePeer.Multiaddr`.
|
|
16
|
+
*/
|
|
17
|
+
export interface CohortSeed {
|
|
18
|
+
/** Dialable strand-network multiaddr strings for cohort peers other than self (deduplicated). */
|
|
19
|
+
bootstrapNodes: string[];
|
|
20
|
+
/** True when at least one CadrePeer row other than self exists (even if it has no resolvable strand addr). */
|
|
21
|
+
hasOtherPeers: boolean;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Membership-only view of a strand's cohort, derived from the control network's
|
|
25
|
+
* CadrePeer rows. The bootstrap addresses themselves are resolved separately
|
|
26
|
+
* (over the strand-addr RPC) from these peerIds, never from the rows' addr field.
|
|
27
|
+
*/
|
|
28
|
+
export interface CohortMembers {
|
|
29
|
+
/** PeerIds of cohort members other than self — the strand-addr RPC fan-out targets (deduplicated, in row order). */
|
|
30
|
+
otherPeerIds: string[];
|
|
31
|
+
/** True when at least one CadrePeer row other than self exists (even if it has no resolvable strand addr). */
|
|
32
|
+
hasOtherPeers: boolean;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Derive the membership view of a strand's cohort from the control network's
|
|
36
|
+
* CadrePeer rows: the peerIds of members other than `selfPeerId` (the strand-addr
|
|
37
|
+
* RPC fan-out targets) and whether any other member exists at all.
|
|
38
|
+
*
|
|
39
|
+
* Deliberately does NOT read `CadrePeer.Multiaddr` — that field carries each
|
|
40
|
+
* node's *control*-network address, which must not seed the *strand* mesh
|
|
41
|
+
* (dialing it reaches the remote's control instance, not its strand instance).
|
|
42
|
+
* The strand-network bootstrap addresses are resolved on demand over the control
|
|
43
|
+
* mesh from these peerIds. `hasOtherPeers` reflects membership presence, NOT
|
|
44
|
+
* dialability, so a cohort whose strand addrs are not yet resolvable still
|
|
45
|
+
* selects `networked` mode.
|
|
46
|
+
*/
|
|
47
|
+
export declare function deriveCohortMembers(peers: CohortPeerRow[], selfPeerId?: string): CohortMembers;
|
|
48
|
+
/**
|
|
49
|
+
* Choose the strand mode. An explicit mode (from `addStrand`) always wins. When
|
|
50
|
+
* omitted (the `handleStrandAdded` discovery path, or an `addStrand` caller that
|
|
51
|
+
* leaves it unset), infer: `bootstrap` for a solo/first node (no other peers),
|
|
52
|
+
* `networked` once the cohort has other members.
|
|
53
|
+
*/
|
|
54
|
+
export declare function selectStrandMode(explicitMode: StrandMode | undefined, hasOtherPeers: boolean): StrandMode;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Derive the membership view of a strand's cohort from the control network's
|
|
3
|
+
* CadrePeer rows: the peerIds of members other than `selfPeerId` (the strand-addr
|
|
4
|
+
* RPC fan-out targets) and whether any other member exists at all.
|
|
5
|
+
*
|
|
6
|
+
* Deliberately does NOT read `CadrePeer.Multiaddr` — that field carries each
|
|
7
|
+
* node's *control*-network address, which must not seed the *strand* mesh
|
|
8
|
+
* (dialing it reaches the remote's control instance, not its strand instance).
|
|
9
|
+
* The strand-network bootstrap addresses are resolved on demand over the control
|
|
10
|
+
* mesh from these peerIds. `hasOtherPeers` reflects membership presence, NOT
|
|
11
|
+
* dialability, so a cohort whose strand addrs are not yet resolvable still
|
|
12
|
+
* selects `networked` mode.
|
|
13
|
+
*/
|
|
14
|
+
export function deriveCohortMembers(peers, selfPeerId) {
|
|
15
|
+
const otherPeerIds = [];
|
|
16
|
+
const seen = new Set();
|
|
17
|
+
for (const peer of peers) {
|
|
18
|
+
if (selfPeerId !== undefined && peer.peerId === selfPeerId) {
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
if (seen.has(peer.peerId)) {
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
seen.add(peer.peerId);
|
|
25
|
+
otherPeerIds.push(peer.peerId);
|
|
26
|
+
}
|
|
27
|
+
return { otherPeerIds, hasOtherPeers: otherPeerIds.length > 0 };
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Choose the strand mode. An explicit mode (from `addStrand`) always wins. When
|
|
31
|
+
* omitted (the `handleStrandAdded` discovery path, or an `addStrand` caller that
|
|
32
|
+
* leaves it unset), infer: `bootstrap` for a solo/first node (no other peers),
|
|
33
|
+
* `networked` once the cohort has other members.
|
|
34
|
+
*/
|
|
35
|
+
export function selectStrandMode(explicitMode, hasOtherPeers) {
|
|
36
|
+
return explicitMode ?? (hasOtherPeers ? 'networked' : 'bootstrap');
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=strand-cohort.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strand-cohort.js","sourceRoot":"","sources":["../src/strand-cohort.ts"],"names":[],"mappings":"AAqCA;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAsB,EAAE,UAAmB;IAC7E,MAAM,YAAY,GAAa,EAAE,CAAC;IAClC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,UAAU,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;YAC3D,SAAS;QACX,CAAC;QACD,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YAC1B,SAAS;QACX,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACtB,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACjC,CAAC;IAED,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;AAClE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,YAAoC,EAAE,aAAsB;IAC3F,OAAO,YAAY,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;AACrE,CAAC"}
|
|
@@ -26,28 +26,76 @@ export interface StrandDatabaseConfig {
|
|
|
26
26
|
* across the two consumers.
|
|
27
27
|
*/
|
|
28
28
|
rawStorage?: IRawStorage;
|
|
29
|
+
/**
|
|
30
|
+
* Strand type (`'o'` open / `'c'` closed) from the control-network strand row.
|
|
31
|
+
* Drives the founder bootstrap: open strands get a `Header` only; closed strands
|
|
32
|
+
* also get the founding `Member`+`Authority`.
|
|
33
|
+
*/
|
|
34
|
+
strandType: 'o' | 'c';
|
|
35
|
+
/**
|
|
36
|
+
* The closed-strand `MemberPrivateKey` (base64 protobuf) from the strand row.
|
|
37
|
+
* Required when `founder` is true and `strandType` is `'c'` — it derives the
|
|
38
|
+
* founding `Member.Key`/`Authority.MemberKey`. Absent for open strands.
|
|
39
|
+
*/
|
|
40
|
+
memberPrivateKey?: string;
|
|
41
|
+
/**
|
|
42
|
+
* Whether this node founds the strand. When true, {@link initialize} runs the
|
|
43
|
+
* one-time founder membership bootstrap after the schema is applied. Joiners
|
|
44
|
+
* leave this false and write nothing (rows arrive via sync). Defaults to false.
|
|
45
|
+
*/
|
|
46
|
+
founder?: boolean;
|
|
29
47
|
}
|
|
30
48
|
/**
|
|
31
|
-
* StrandDatabase manages the sApp schema for a strand using Quereus with
|
|
32
|
-
* Each strand instance has its own isolated database with
|
|
49
|
+
* StrandDatabase manages the sApp schema for a strand using Quereus with the
|
|
50
|
+
* Optimystic backend. Each strand instance has its own isolated database with
|
|
51
|
+
* the sApp's schema applied.
|
|
52
|
+
*
|
|
53
|
+
* This class owns the `Database` lifecycle (creation, `getDatabase()`, `close()`)
|
|
54
|
+
* but delegates the actual SQL-surface composition — plugin registration, node
|
|
55
|
+
* wiring, catalog hydration, schema apply — to `connectToStrand` from
|
|
56
|
+
* `@serfab/quereus-plugin-sereus`, the single shared composition. The libp2p
|
|
57
|
+
* node is injected here, so `connectToStrand` never *creates* the node;
|
|
58
|
+
* `StrandInstanceManager` owns the node lifecycle. (The strand connection's
|
|
59
|
+
* `shutdown` still stops the injected node via the collection factory, so the
|
|
60
|
+
* manager's own `node.stop()` is an idempotent second stop — see `close()`.)
|
|
33
61
|
*/
|
|
34
62
|
export declare class StrandDatabase {
|
|
35
63
|
private db;
|
|
36
|
-
private
|
|
64
|
+
private shutdownStrand;
|
|
37
65
|
private readonly config;
|
|
38
66
|
private initialized;
|
|
39
67
|
constructor(config: StrandDatabaseConfig);
|
|
40
68
|
/**
|
|
41
|
-
* Initialize the database
|
|
69
|
+
* Initialize the database — create the `Database` and delegate the strand
|
|
70
|
+
* SQL-surface composition (plugins, node wiring, hydrate, schema apply) to
|
|
71
|
+
* `connectToStrand` with the injected libp2p node.
|
|
42
72
|
*/
|
|
43
73
|
initialize(): Promise<void>;
|
|
44
|
-
|
|
74
|
+
/**
|
|
75
|
+
* Run the founder membership bootstrap against the freshly-composed strand DB.
|
|
76
|
+
*
|
|
77
|
+
* Derives the founding keypair from the closed-strand `memberPrivateKey` (the
|
|
78
|
+
* `Member.Key`/`Authority.MemberKey` are its public key); a closed strand with no
|
|
79
|
+
* `memberPrivateKey` throws, because it could never seat a founding authority.
|
|
80
|
+
* Open strands derive no keypair (Header only). Idempotent — see
|
|
81
|
+
* {@link bootstrapFounderMembership}.
|
|
82
|
+
*/
|
|
83
|
+
private bootstrapFounder;
|
|
84
|
+
/**
|
|
85
|
+
* Derive the founding keypair for a closed strand from its `memberPrivateKey`,
|
|
86
|
+
* failing loudly when the key is absent (a closed strand with no founding
|
|
87
|
+
* Authority can never admit anyone).
|
|
88
|
+
*/
|
|
89
|
+
private deriveFounderKeyPair;
|
|
45
90
|
/**
|
|
46
91
|
* Get the underlying database for queries
|
|
47
92
|
*/
|
|
48
93
|
getDatabase(): Database;
|
|
49
94
|
/**
|
|
50
|
-
* Close the database and cleanup resources
|
|
95
|
+
* Close the database and cleanup resources. Runs the strand-connection
|
|
96
|
+
* shutdown (collection-factory teardown, which also stops the injected node),
|
|
97
|
+
* then closes the `Database`. `StrandInstanceManager.releaseRuntime` issues a
|
|
98
|
+
* further idempotent `node.stop()` after this returns.
|
|
51
99
|
*/
|
|
52
100
|
close(): Promise<void>;
|
|
53
101
|
private ensureInitialized;
|
package/dist/strand-database.js
CHANGED
|
@@ -1,122 +1,107 @@
|
|
|
1
1
|
import debug from 'debug';
|
|
2
|
-
import { Database
|
|
3
|
-
import
|
|
4
|
-
import
|
|
2
|
+
import { Database } from '@quereus/quereus';
|
|
3
|
+
import { connectToStrand } from '@serfab/quereus-plugin-sereus';
|
|
4
|
+
import { bootstrapFounderMembership } from './strand-membership-writer.js';
|
|
5
|
+
import { strandMemberKeyPair } from './strand-member-key.js';
|
|
5
6
|
const log = debug('sereus:cadre:strand-db');
|
|
6
7
|
const timing = debug('sereus:cadre:timing');
|
|
7
8
|
/**
|
|
8
|
-
* StrandDatabase manages the sApp schema for a strand using Quereus with
|
|
9
|
-
* Each strand instance has its own isolated database with
|
|
9
|
+
* StrandDatabase manages the sApp schema for a strand using Quereus with the
|
|
10
|
+
* Optimystic backend. Each strand instance has its own isolated database with
|
|
11
|
+
* the sApp's schema applied.
|
|
12
|
+
*
|
|
13
|
+
* This class owns the `Database` lifecycle (creation, `getDatabase()`, `close()`)
|
|
14
|
+
* but delegates the actual SQL-surface composition — plugin registration, node
|
|
15
|
+
* wiring, catalog hydration, schema apply — to `connectToStrand` from
|
|
16
|
+
* `@serfab/quereus-plugin-sereus`, the single shared composition. The libp2p
|
|
17
|
+
* node is injected here, so `connectToStrand` never *creates* the node;
|
|
18
|
+
* `StrandInstanceManager` owns the node lifecycle. (The strand connection's
|
|
19
|
+
* `shutdown` still stops the injected node via the collection factory, so the
|
|
20
|
+
* manager's own `node.stop()` is an idempotent second stop — see `close()`.)
|
|
10
21
|
*/
|
|
11
22
|
export class StrandDatabase {
|
|
12
23
|
constructor(config) {
|
|
13
24
|
this.db = null;
|
|
14
|
-
this.
|
|
25
|
+
this.shutdownStrand = null;
|
|
15
26
|
this.initialized = false;
|
|
16
27
|
this.config = config;
|
|
17
28
|
}
|
|
18
29
|
/**
|
|
19
|
-
* Initialize the database
|
|
30
|
+
* Initialize the database — create the `Database` and delegate the strand
|
|
31
|
+
* SQL-surface composition (plugins, node wiring, hydrate, schema apply) to
|
|
32
|
+
* `connectToStrand` with the injected libp2p node.
|
|
20
33
|
*/
|
|
21
34
|
async initialize() {
|
|
22
35
|
if (this.initialized) {
|
|
23
36
|
log('StrandDatabase for strand %s already initialized', this.config.strandId);
|
|
24
37
|
return;
|
|
25
38
|
}
|
|
26
|
-
log('Initializing StrandDatabase for strand: %s (sApp: %s v%s)', this.config.strandId, this.config.sAppConfig.id, this.config.sAppConfig.version);
|
|
27
|
-
// Create database instance
|
|
28
|
-
this.db = new Database();
|
|
29
39
|
const sid = this.config.strandId;
|
|
30
|
-
// Register crypto plugin (provides digest, sign, verify functions)
|
|
31
|
-
let t0 = performance.now();
|
|
32
|
-
await registerPlugin(this.db, cryptoPlugin);
|
|
33
|
-
timing('[strandDb:%s] cryptoPlugin: %dms', sid, Math.round(performance.now() - t0));
|
|
34
|
-
log('Registered crypto plugin');
|
|
35
|
-
// Register optimystic plugin. In `bootstrap` mode we route through the
|
|
36
|
-
// local transactor so a solo node can initialize (schema apply etc.)
|
|
37
|
-
// without network round trips. In `networked` mode the network transactor
|
|
38
|
-
// is used. Mode is fixed for the lifetime of this Database instance; the
|
|
39
|
-
// caller must restart the strand to transition modes.
|
|
40
|
-
t0 = performance.now();
|
|
41
|
-
const networkName = `strand-${sid}`;
|
|
42
40
|
const mode = this.config.mode ?? 'networked';
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
//
|
|
46
|
-
//
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
// Register vtables and functions manually since we need access to collectionFactory
|
|
63
|
-
for (const vtable of pluginResult.vtables) {
|
|
64
|
-
this.db.registerModule(vtable.name, vtable.module, vtable.auxData);
|
|
65
|
-
}
|
|
66
|
-
for (const func of pluginResult.functions) {
|
|
67
|
-
this.db.registerFunction(func.schema);
|
|
68
|
-
}
|
|
69
|
-
timing('[strandDb:%s] optimysticPlugin: %dms', sid, Math.round(performance.now() - t0));
|
|
70
|
-
this.collectionFactory = pluginResult.collectionFactory;
|
|
71
|
-
// Inject the libp2p node into the collection factory
|
|
72
|
-
t0 = performance.now();
|
|
73
|
-
this.collectionFactory.registerLibp2pNode(networkName, this.config.libp2pNode, this.config.coordinatedRepo);
|
|
74
|
-
timing('[strandDb:%s] registerLibp2pNode: %dms', sid, Math.round(performance.now() - t0));
|
|
75
|
-
log('Registered libp2p node with collection factory');
|
|
76
|
-
// Set optimystic as the default virtual table module so that
|
|
77
|
-
// `declare schema` tables (which omit USING) are backed by optimystic
|
|
78
|
-
// instead of the built-in memory module.
|
|
79
|
-
t0 = performance.now();
|
|
80
|
-
this.db.setDefaultVtabName('optimystic');
|
|
81
|
-
this.db.setDefaultVtabArgs({
|
|
82
|
-
networkName,
|
|
83
|
-
transactor: defaultTransactor,
|
|
84
|
-
keyNetwork: 'libp2p',
|
|
41
|
+
log('Initializing StrandDatabase for strand: %s (sApp: %s v%s, mode=%s)', sid, this.config.sAppConfig.id, this.config.sAppConfig.version, mode);
|
|
42
|
+
this.db = new Database();
|
|
43
|
+
// Delegate to the shared composition. The node is injected, so:
|
|
44
|
+
// - `connectToStrand` never creates a node (its `createdNode` stays null);
|
|
45
|
+
// `StrandInstanceManager` owns the node lifecycle. Its `shutdown` does
|
|
46
|
+
// still stop the injected node via the collection factory, so the
|
|
47
|
+
// manager's later `node.stop()` is an idempotent second stop;
|
|
48
|
+
// - `storage` (the strand's raw storage, same instance the node uses) is
|
|
49
|
+
// handed to the plugin's local transactor in bootstrap mode so DML lands
|
|
50
|
+
// on the host backend rather than in-memory.
|
|
51
|
+
const t0 = performance.now();
|
|
52
|
+
const result = await connectToStrand(this.db, {
|
|
53
|
+
strandId: sid,
|
|
54
|
+
schema: this.config.sAppConfig.schema,
|
|
55
|
+
mode,
|
|
56
|
+
storage: this.config.rawStorage,
|
|
57
|
+
libp2pNode: this.config.libp2pNode,
|
|
58
|
+
coordinatedRepo: this.config.coordinatedRepo,
|
|
59
|
+
enableCache: true,
|
|
85
60
|
});
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
//
|
|
89
|
-
//
|
|
90
|
-
//
|
|
91
|
-
//
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
t0 = performance.now();
|
|
96
|
-
const hydrated = await pluginResult.hydrate(this.db);
|
|
97
|
-
timing('[strandDb:%s] hydrate: %dms (tables=%d, indexes=%d)', sid, Math.round(performance.now() - t0), hydrated.tables, hydrated.indexes);
|
|
98
|
-
log('Hydrated catalog for strand %s (tables=%d, indexes=%d)', sid, hydrated.tables, hydrated.indexes);
|
|
99
|
-
// Execute the sApp schema DDL
|
|
100
|
-
t0 = performance.now();
|
|
101
|
-
await this.executeSchema();
|
|
102
|
-
timing('[strandDb:%s] executeSchema: %dms', sid, Math.round(performance.now() - t0));
|
|
61
|
+
this.shutdownStrand = result.shutdown;
|
|
62
|
+
timing('[strandDb:%s] connectToStrand: %dms (hydrated tables=%d, indexes=%d)', sid, Math.round(performance.now() - t0), result.hydrated?.tables ?? 0, result.hydrated?.indexes ?? 0);
|
|
63
|
+
// Founder-only: write the one-time membership bootstrap now that the schema is
|
|
64
|
+
// applied (connectToStrand has returned). A throw here propagates out of
|
|
65
|
+
// initialize() so buildStrandRuntime's rollback tears the half-built strand
|
|
66
|
+
// down rather than leaking a node. Joiners skip this — their rows arrive via sync.
|
|
67
|
+
if (this.config.founder === true) {
|
|
68
|
+
await this.bootstrapFounder();
|
|
69
|
+
}
|
|
103
70
|
this.initialized = true;
|
|
104
71
|
log('StrandDatabase for strand %s initialized successfully', sid);
|
|
105
72
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
73
|
+
/**
|
|
74
|
+
* Run the founder membership bootstrap against the freshly-composed strand DB.
|
|
75
|
+
*
|
|
76
|
+
* Derives the founding keypair from the closed-strand `memberPrivateKey` (the
|
|
77
|
+
* `Member.Key`/`Authority.MemberKey` are its public key); a closed strand with no
|
|
78
|
+
* `memberPrivateKey` throws, because it could never seat a founding authority.
|
|
79
|
+
* Open strands derive no keypair (Header only). Idempotent — see
|
|
80
|
+
* {@link bootstrapFounderMembership}.
|
|
81
|
+
*/
|
|
82
|
+
async bootstrapFounder() {
|
|
83
|
+
const { strandId, strandType, memberPrivateKey, sAppConfig } = this.config;
|
|
84
|
+
const founderKeyPair = strandType === 'c'
|
|
85
|
+
? this.deriveFounderKeyPair(strandId, memberPrivateKey)
|
|
86
|
+
: undefined;
|
|
87
|
+
await bootstrapFounderMembership(this.db, {
|
|
88
|
+
strandId,
|
|
89
|
+
type: strandType,
|
|
90
|
+
sApp: sAppConfig,
|
|
91
|
+
founderKeyPair,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Derive the founding keypair for a closed strand from its `memberPrivateKey`,
|
|
96
|
+
* failing loudly when the key is absent (a closed strand with no founding
|
|
97
|
+
* Authority can never admit anyone).
|
|
98
|
+
*/
|
|
99
|
+
deriveFounderKeyPair(strandId, memberPrivateKey) {
|
|
100
|
+
if (!memberPrivateKey) {
|
|
101
|
+
throw new Error(`Cannot found closed strand ${strandId}: the strand row has no MemberPrivateKey. ` +
|
|
102
|
+
'A closed strand needs a founding Member/Authority derived from that key.');
|
|
103
|
+
}
|
|
104
|
+
return strandMemberKeyPair(memberPrivateKey);
|
|
120
105
|
}
|
|
121
106
|
/**
|
|
122
107
|
* Get the underlying database for queries
|
|
@@ -126,15 +111,18 @@ export class StrandDatabase {
|
|
|
126
111
|
return this.db;
|
|
127
112
|
}
|
|
128
113
|
/**
|
|
129
|
-
* Close the database and cleanup resources
|
|
114
|
+
* Close the database and cleanup resources. Runs the strand-connection
|
|
115
|
+
* shutdown (collection-factory teardown, which also stops the injected node),
|
|
116
|
+
* then closes the `Database`. `StrandInstanceManager.releaseRuntime` issues a
|
|
117
|
+
* further idempotent `node.stop()` after this returns.
|
|
130
118
|
*/
|
|
131
119
|
async close() {
|
|
132
|
-
if (this.
|
|
133
|
-
await this.
|
|
134
|
-
this.
|
|
120
|
+
if (this.shutdownStrand) {
|
|
121
|
+
await this.shutdownStrand();
|
|
122
|
+
this.shutdownStrand = null;
|
|
135
123
|
}
|
|
136
124
|
if (this.db) {
|
|
137
|
-
this.db.close();
|
|
125
|
+
void this.db.close();
|
|
138
126
|
this.db = null;
|
|
139
127
|
}
|
|
140
128
|
this.initialized = false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"strand-database.js","sourceRoot":"","sources":["../src/strand-database.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"strand-database.js","sourceRoot":"","sources":["../src/strand-database.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Libp2p } from '@libp2p/interface';
|
|
2
2
|
import type { OpenInvitation, FormStrandResult, StrandFormationDisclosure } from './types.js';
|
|
3
|
-
import type { DisclosureValidator, FormationUsageRecorder, StrandProvisioner } from './strand-solicitation.js';
|
|
3
|
+
import type { DisclosureValidator, FormationUsageRecorder, StrandProvisioner, FormationResponseValidator } from './strand-solicitation.js';
|
|
4
4
|
/**
|
|
5
5
|
* Configuration for StrandFormationManager
|
|
6
6
|
*/
|
|
@@ -20,12 +20,14 @@ export interface StrandFormationManagerConfig {
|
|
|
20
20
|
* Options for creating a StrandFormationManager
|
|
21
21
|
*/
|
|
22
22
|
export interface StrandFormationManagerOptions {
|
|
23
|
-
/** Validates disclosures from initiators */
|
|
23
|
+
/** Validates disclosures from initiators (responder side) */
|
|
24
24
|
disclosureValidator?: DisclosureValidator;
|
|
25
|
-
/** Records and validates token usage */
|
|
25
|
+
/** Records and validates token usage (responder side) */
|
|
26
26
|
formationUsageRecorder?: FormationUsageRecorder;
|
|
27
|
-
/** Provisions strands after validation */
|
|
27
|
+
/** Provisions strands after validation (responder side) */
|
|
28
28
|
strandProvisioner?: StrandProvisioner;
|
|
29
|
+
/** Validates the responder's result (initiator side); defaults to a structural check */
|
|
30
|
+
formationResponseValidator?: FormationResponseValidator;
|
|
29
31
|
/** This party's ID for identification */
|
|
30
32
|
partyId: string;
|
|
31
33
|
/** This party's cadre peer addresses */
|
|
@@ -34,22 +36,29 @@ export interface StrandFormationManagerOptions {
|
|
|
34
36
|
config?: StrandFormationManagerConfig;
|
|
35
37
|
}
|
|
36
38
|
/**
|
|
37
|
-
* StrandFormationManager
|
|
38
|
-
*
|
|
39
|
+
* StrandFormationManager drives the native cadre-core formation transport
|
|
40
|
+
* (`strand-formation-protocol.ts`) from cadre-core's strand-solicitation interfaces.
|
|
39
41
|
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
42
|
+
* Responder side: a {@link FormationListener} wires the inbound protocol to
|
|
43
|
+
* {@link FormationUsageRecorder} (token), {@link DisclosureValidator} (identity),
|
|
44
|
+
* and {@link StrandProvisioner} (provisioning), disclosing this party's real
|
|
45
|
+
* identity + cadre only after validation.
|
|
46
|
+
*
|
|
47
|
+
* Initiator side: {@link formStrand} dials the responder carrying the real
|
|
48
|
+
* disclosure/token/cadre, then validates the responder's result via the
|
|
49
|
+
* {@link FormationResponseValidator} (or a built-in structural check).
|
|
44
50
|
*/
|
|
45
51
|
export declare class StrandFormationManager {
|
|
46
|
-
private readonly sessionManager;
|
|
47
52
|
private readonly disclosureValidator?;
|
|
48
53
|
private readonly formationUsageRecorder?;
|
|
49
54
|
private readonly strandProvisioner?;
|
|
55
|
+
private readonly formationResponseValidator?;
|
|
50
56
|
private readonly partyId;
|
|
51
57
|
private readonly cadrePeerAddrs;
|
|
52
|
-
private
|
|
58
|
+
private readonly config;
|
|
59
|
+
private readonly listener;
|
|
60
|
+
private readonly registeredNodes;
|
|
61
|
+
private dialerSessions;
|
|
53
62
|
constructor(options: StrandFormationManagerOptions);
|
|
54
63
|
/**
|
|
55
64
|
* Register this manager as a protocol handler on a libp2p node.
|
|
@@ -61,12 +70,11 @@ export declare class StrandFormationManager {
|
|
|
61
70
|
*/
|
|
62
71
|
unregisterResponder(node: Libp2p, protocolId?: string): void;
|
|
63
72
|
/**
|
|
64
|
-
* Form a strand with a responder via an open invitation.
|
|
73
|
+
* Form a strand with a responder via an open invitation (initiator side).
|
|
65
74
|
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
* 3. Returns the result as a FormStrandResult
|
|
75
|
+
* Builds a contact message carrying the real token + disclosure + this party's
|
|
76
|
+
* real cadre addresses, dials the responder over the native protocol, and
|
|
77
|
+
* validates the responder's result before returning.
|
|
70
78
|
*/
|
|
71
79
|
formStrand(invitation: OpenInvitation, disclosure: StrandFormationDisclosure, node: Libp2p): Promise<FormStrandResult>;
|
|
72
80
|
/**
|
|
@@ -76,10 +84,62 @@ export declare class StrandFormationManager {
|
|
|
76
84
|
listeners: number;
|
|
77
85
|
dialers: number;
|
|
78
86
|
};
|
|
87
|
+
private validateToken;
|
|
88
|
+
private validateDisclosure;
|
|
89
|
+
/**
|
|
90
|
+
* Responder-side provisioning. Routes on how the invite resolves
|
|
91
|
+
* ({@link ResolvedHostStrand}), and can REJECT post-validation by returning a
|
|
92
|
+
* {@link ResponderProvisionOutcome} with `approved: false` — `runSession` turns that
|
|
93
|
+
* into a clean, non-disclosing reply instead of a dropped result frame.
|
|
94
|
+
*
|
|
95
|
+
* - **bound** (host strand present): provision-then-record — write the single
|
|
96
|
+
* `FormationUsage` consent row against the pre-existing strand (record-only) and
|
|
97
|
+
* return it + its membership key (a read-gating secret disclosed only here, behind the
|
|
98
|
+
* token + disclosure validation `runSession` already enforced).
|
|
99
|
+
* - **missing** (invite names a host strand absent on this responder, e.g. unconverged):
|
|
100
|
+
* reject cleanly + retryably, writing NO usage row — recording usage here would fail the
|
|
101
|
+
* deferred `StrandExists` CHECK at commit and drop the frame.
|
|
102
|
+
* - **unbound** (no binding): the responder-provisions fallback — see {@link provisionUnbound}.
|
|
103
|
+
*
|
|
104
|
+
* Defense-in-depth: known provisioning/redeem failures (notably the concurrent
|
|
105
|
+
* `(Token, UseNumber)` PK collision when two redemptions of one unbound single-use invite
|
|
106
|
+
* race) are caught and mapped to a logged, retry-suggesting rejection rather than a thrown
|
|
107
|
+
* insert + a silently-closed stream. The LOG-before-reject keeps this a deliberate
|
|
108
|
+
* internal-error→protocol-rejection conversion (AGENTS.md: don't eat exceptions silently),
|
|
109
|
+
* not control-flow-by-exception.
|
|
110
|
+
*/
|
|
111
|
+
private provisionAsResponder;
|
|
112
|
+
/**
|
|
113
|
+
* Responder-provisions fallback (invite binds no host strand). Precedence:
|
|
114
|
+
*
|
|
115
|
+
* 1. `recorder.provisionAndRecord` present (a real DB recorder) → atomic create-strand +
|
|
116
|
+
* record-consent, so the unbound redemption is single-use just like the bound path.
|
|
117
|
+
* Returns the new strand (+ key, null for an open responder-provisioned strand).
|
|
118
|
+
* 2. else `strandProvisioner` present → the legacy/mock contract: provision a bare strand,
|
|
119
|
+
* NO inline usage write (those callers record usage explicitly via
|
|
120
|
+
* `recordFormationComplete`, or assert transport invariants only). Threads the invite's
|
|
121
|
+
* REAL `sAppId`.
|
|
122
|
+
* 3. else → a structural placeholder (no recorder + no provisioner ⇒ no single-use semantics
|
|
123
|
+
* exist to enforce).
|
|
124
|
+
*
|
|
125
|
+
* Plan tradeoff — option (a) "record usage on the fallback" over (b) "remove the fallback":
|
|
126
|
+
* (a) closes the single-use hole with a targeted atomic create+record and leaves the
|
|
127
|
+
* `StrandProvisioner` mock-transport tests untouched; (b) would delete the provisioner
|
|
128
|
+
* surface and churn ~6 unit + ~6 integration sites for ZERO production benefit (production
|
|
129
|
+
* — `cadre-web.ts` / `cadre-phone.ts` — always publishes strand-BOUND invites and treats
|
|
130
|
+
* the responder-provisions placeholder as failure). The broader "should this fallback exist
|
|
131
|
+
* at all?" question lives in backlog `formation-initiatorcreates-cover-or-remove`.
|
|
132
|
+
*/
|
|
133
|
+
private provisionUnbound;
|
|
134
|
+
/** Wrap a provision result as an approving {@link ResponderProvisionOutcome}. */
|
|
135
|
+
private approve;
|
|
79
136
|
/**
|
|
80
|
-
*
|
|
137
|
+
* The invite's authoritative `sAppId` for the responder-provisions fallback, read back
|
|
138
|
+
* from the recorder's `isTokenValid` invitation (the real `FormationInvite.sAppId`).
|
|
139
|
+
* Empty string when no recorder is wired or the invitation omits it.
|
|
81
140
|
*/
|
|
82
|
-
private
|
|
141
|
+
private resolveInviteSAppId;
|
|
142
|
+
private validateResponse;
|
|
83
143
|
}
|
|
84
144
|
/**
|
|
85
145
|
* Create a StrandFormationManager with the given options
|