@cello-protocol/client 0.0.20 → 0.0.22
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/client-send-helpers.d.ts +25 -0
- package/dist/client-send-helpers.d.ts.map +1 -0
- package/dist/client-send-helpers.js +118 -0
- package/dist/client-send-helpers.js.map +1 -0
- package/dist/client-startup.d.ts +74 -0
- package/dist/client-startup.d.ts.map +1 -0
- package/dist/client-startup.js +337 -0
- package/dist/client-startup.js.map +1 -0
- package/dist/client-wiring.d.ts +120 -0
- package/dist/client-wiring.d.ts.map +1 -0
- package/dist/client-wiring.js +289 -0
- package/dist/client-wiring.js.map +1 -0
- package/dist/client.d.ts +29 -169
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +222 -5372
- package/dist/client.js.map +1 -1
- package/dist/connection-inbound-handler.d.ts +47 -0
- package/dist/connection-inbound-handler.d.ts.map +1 -0
- package/dist/connection-inbound-handler.js +325 -0
- package/dist/connection-inbound-handler.js.map +1 -0
- package/dist/connection-manager.d.ts +191 -0
- package/dist/connection-manager.d.ts.map +1 -0
- package/dist/connection-manager.js +692 -0
- package/dist/connection-manager.js.map +1 -0
- package/dist/frame-dispatch.d.ts +28 -0
- package/dist/frame-dispatch.d.ts.map +1 -0
- package/dist/frame-dispatch.js +118 -0
- package/dist/frame-dispatch.js.map +1 -0
- package/dist/registration-manager.d.ts +54 -0
- package/dist/registration-manager.d.ts.map +1 -0
- package/dist/registration-manager.js +248 -0
- package/dist/registration-manager.js.map +1 -0
- package/dist/relay-stream-manager.d.ts +136 -0
- package/dist/relay-stream-manager.d.ts.map +1 -0
- package/dist/relay-stream-manager.js +834 -0
- package/dist/relay-stream-manager.js.map +1 -0
- package/dist/seal-manager.d.ts +133 -0
- package/dist/seal-manager.d.ts.map +1 -0
- package/dist/seal-manager.js +803 -0
- package/dist/seal-manager.js.map +1 -0
- package/dist/session-assignment-parser.d.ts +33 -0
- package/dist/session-assignment-parser.d.ts.map +1 -0
- package/dist/session-assignment-parser.js +149 -0
- package/dist/session-assignment-parser.js.map +1 -0
- package/dist/session-manager.d.ts +132 -0
- package/dist/session-manager.d.ts.map +1 -0
- package/dist/session-manager.js +605 -0
- package/dist/session-manager.js.map +1 -0
- package/dist/signaling-manager.d.ts +85 -0
- package/dist/signaling-manager.d.ts.map +1 -0
- package/dist/signaling-manager.js +597 -0
- package/dist/signaling-manager.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* client-send-helpers.ts — low-level send and receive utilities for CelloClientImpl.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from client.ts to keep the facade under the 600-line AC budget.
|
|
5
|
+
*/
|
|
6
|
+
import type { CelloNode } from "@cello-protocol/transport";
|
|
7
|
+
import type { Stream } from "@libp2p/interface";
|
|
8
|
+
import type { SendResult, ReceivedEnvelope } from "./types.js";
|
|
9
|
+
export declare function isStructuredError(err: unknown, reason: string): boolean;
|
|
10
|
+
export declare function mapSendError(err: unknown): "remote_rejected" | "connection_lost" | "peer_unreachable" | "transport_not_started";
|
|
11
|
+
/**
|
|
12
|
+
* Open a CELLO_PROTOCOL_ID stream to peerId, send bytes length-prefixed,
|
|
13
|
+
* drain the read side, and return a SendResult.
|
|
14
|
+
*/
|
|
15
|
+
export declare function sendBytesViaNode(node: CelloNode, peerId: string, bytes: Uint8Array, contentHash: Uint8Array | undefined): Promise<SendResult>;
|
|
16
|
+
/**
|
|
17
|
+
* Read a single length-prefixed envelope from an inbound stream,
|
|
18
|
+
* validate it, and push it onto the receive queue.
|
|
19
|
+
* Extracted from CelloClientImpl.handleInbound.
|
|
20
|
+
*/
|
|
21
|
+
export declare function handleInboundEnvelope(stream: Stream, receiveQueues: Map<string, ReceivedEnvelope[]>, arrivalLog: Array<{
|
|
22
|
+
senderPubkeyHex: string;
|
|
23
|
+
envelope: ReceivedEnvelope;
|
|
24
|
+
}>, onMessageQueued: ((senderPubkeyHex: string) => void) | undefined): Promise<void>;
|
|
25
|
+
//# sourceMappingURL=client-send-helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-send-helpers.d.ts","sourceRoot":"","sources":["../src/client-send-helpers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAI/D,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAOvE;AAED,wBAAgB,YAAY,CAC1B,GAAG,EAAE,OAAO,GACX,iBAAiB,GAAG,iBAAiB,GAAG,kBAAkB,GAAG,uBAAuB,CAOtF;AAID;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,SAAS,EACf,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,UAAU,EACjB,WAAW,EAAE,UAAU,GAAG,SAAS,GAClC,OAAO,CAAC,UAAU,CAAC,CA6BrB;AAID;;;;GAIG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,EAAE,CAAC,EAC9C,UAAU,EAAE,KAAK,CAAC;IAAE,eAAe,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,gBAAgB,CAAA;CAAE,CAAC,EAC1E,eAAe,EAAE,CAAC,CAAC,eAAe,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,GAC/D,OAAO,CAAC,IAAI,CAAC,CAyCf"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* client-send-helpers.ts — low-level send and receive utilities for CelloClientImpl.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from client.ts to keep the facade under the 600-line AC budget.
|
|
5
|
+
*/
|
|
6
|
+
import * as lp from "it-length-prefixed";
|
|
7
|
+
import { deserializeEnvelope, validateEnvelope } from "@cello-protocol/protocol-types";
|
|
8
|
+
import { CELLO_PROTOCOL_ID } from "@cello-protocol/transport";
|
|
9
|
+
// ─── Error helpers ────────────────────────────────────────────────────────────
|
|
10
|
+
export function isStructuredError(err, reason) {
|
|
11
|
+
return (typeof err === "object" &&
|
|
12
|
+
err !== null &&
|
|
13
|
+
"reason" in err &&
|
|
14
|
+
err.reason === reason);
|
|
15
|
+
}
|
|
16
|
+
export function mapSendError(err) {
|
|
17
|
+
if (isStructuredError(err, "node_stopped"))
|
|
18
|
+
return "transport_not_started";
|
|
19
|
+
if (isStructuredError(err, "connection_lost"))
|
|
20
|
+
return "connection_lost";
|
|
21
|
+
if (isStructuredError(err, "protocol_not_supported"))
|
|
22
|
+
return "peer_unreachable";
|
|
23
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
24
|
+
if (msg.includes("reset") || msg.includes("aborted"))
|
|
25
|
+
return "remote_rejected";
|
|
26
|
+
return "connection_lost";
|
|
27
|
+
}
|
|
28
|
+
// ─── Core send path ───────────────────────────────────────────────────────────
|
|
29
|
+
/**
|
|
30
|
+
* Open a CELLO_PROTOCOL_ID stream to peerId, send bytes length-prefixed,
|
|
31
|
+
* drain the read side, and return a SendResult.
|
|
32
|
+
*/
|
|
33
|
+
export async function sendBytesViaNode(node, peerId, bytes, contentHash) {
|
|
34
|
+
let stream;
|
|
35
|
+
try {
|
|
36
|
+
stream = await node.newStream(peerId, CELLO_PROTOCOL_ID);
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
const reason = isStructuredError(err, "node_stopped")
|
|
40
|
+
? "transport_not_started"
|
|
41
|
+
: "peer_unreachable";
|
|
42
|
+
return { delivered: false, reason };
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
stream.send(lp.encode.single(bytes));
|
|
46
|
+
await stream.close();
|
|
47
|
+
try {
|
|
48
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
49
|
+
for await (const _ of lp.decode(stream)) { /* drain */ }
|
|
50
|
+
}
|
|
51
|
+
catch { /* read side error — ignore */ }
|
|
52
|
+
if (stream.status === "reset" || stream.status === "aborted") {
|
|
53
|
+
return { delivered: false, reason: "remote_rejected" };
|
|
54
|
+
}
|
|
55
|
+
const hashHex = contentHash ? Buffer.from(contentHash).toString("hex") : "";
|
|
56
|
+
return { delivered: true, contentHash: hashHex };
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
return { delivered: false, reason: mapSendError(err) };
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
// ─── Inbound envelope handler ─────────────────────────────────────────────────
|
|
63
|
+
/**
|
|
64
|
+
* Read a single length-prefixed envelope from an inbound stream,
|
|
65
|
+
* validate it, and push it onto the receive queue.
|
|
66
|
+
* Extracted from CelloClientImpl.handleInbound.
|
|
67
|
+
*/
|
|
68
|
+
export async function handleInboundEnvelope(stream, receiveQueues, arrivalLog, onMessageQueued) {
|
|
69
|
+
let payload;
|
|
70
|
+
let timeoutFired = false;
|
|
71
|
+
const readFrame = async () => {
|
|
72
|
+
for await (const chunk of lp.decode(stream)) {
|
|
73
|
+
payload = chunk.slice();
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
let timerId;
|
|
78
|
+
const timeout = new Promise((_, reject) => {
|
|
79
|
+
timerId = setTimeout(() => { timeoutFired = true; reject(new Error("truncated_frame")); }, 5_000);
|
|
80
|
+
});
|
|
81
|
+
try {
|
|
82
|
+
await Promise.race([readFrame(), timeout]);
|
|
83
|
+
clearTimeout(timerId);
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
clearTimeout(timerId);
|
|
87
|
+
stream.abort(new Error(timeoutFired ? "truncated_frame: read timeout" : "truncated_frame: stream error"));
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
if (!payload) {
|
|
91
|
+
stream.abort(new Error("truncated_frame: no frame received"));
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const deserResult = deserializeEnvelope(payload);
|
|
95
|
+
if (!deserResult.ok) {
|
|
96
|
+
stream.abort(new Error(`malformed_envelope: ${deserResult.error.reason}`));
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
const validateResult = validateEnvelope(deserResult.envelope);
|
|
100
|
+
if (!validateResult.ok) {
|
|
101
|
+
stream.abort(new Error(`validation_failed: ${validateResult.error.reason}`));
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const senderHex = Buffer.from(deserResult.envelope.sender_pubkey).toString("hex");
|
|
105
|
+
const received = {
|
|
106
|
+
content: deserResult.envelope.content,
|
|
107
|
+
senderPubkey: deserResult.envelope.sender_pubkey,
|
|
108
|
+
contentHash: deserResult.envelope.content_hash,
|
|
109
|
+
timestamp: deserResult.envelope.timestamp,
|
|
110
|
+
};
|
|
111
|
+
if (!receiveQueues.has(senderHex))
|
|
112
|
+
receiveQueues.set(senderHex, []);
|
|
113
|
+
receiveQueues.get(senderHex).push(received);
|
|
114
|
+
arrivalLog.push({ senderPubkeyHex: senderHex, envelope: received });
|
|
115
|
+
onMessageQueued?.(senderHex);
|
|
116
|
+
await stream.close().catch(() => { });
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=client-send-helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-send-helpers.js","sourceRoot":"","sources":["../src/client-send-helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* client-startup.ts — PERSIST-024: loadClientStartupState
|
|
3
|
+
*
|
|
4
|
+
* Extracted from CelloClientImpl.loadPersistedState to keep client.ts under AC-005 line budget.
|
|
5
|
+
* Loads all durable state from the SQLCipher DB and populates in-memory state via the
|
|
6
|
+
* StartupContext interface.
|
|
7
|
+
*
|
|
8
|
+
* Security invariants:
|
|
9
|
+
* SI-001: signing_share bytes never appear in any log event.
|
|
10
|
+
* SI-002: secret_key_blob bytes never appear in any log event.
|
|
11
|
+
*
|
|
12
|
+
* Crypto refs: RFC 9591 (FROST), NIST FIPS 204 (ML-DSA-44)
|
|
13
|
+
*/
|
|
14
|
+
import type { IThresholdSigner, MlDsaKeyProvider } from "@cello-protocol/crypto";
|
|
15
|
+
import type { CelloNode } from "@cello-protocol/transport";
|
|
16
|
+
import type { RegistrationState, ClientConnectionRecord } from "@cello-protocol/protocol-types";
|
|
17
|
+
import type { Logger } from "@cello-protocol/interfaces";
|
|
18
|
+
import type { ClientStatePersistence } from "./client-state-persistence.js";
|
|
19
|
+
import type { SessionRecord, PeerEntry } from "./types.js";
|
|
20
|
+
import type { SignalRequirementPolicy } from "./connection-policy.js";
|
|
21
|
+
import type { ReviewQueueItem } from "./connection-manager.js";
|
|
22
|
+
/**
|
|
23
|
+
* Narrow interface providing access to the facade's mutable state and manager callbacks
|
|
24
|
+
* needed during startup state restoration.
|
|
25
|
+
*/
|
|
26
|
+
export interface StartupContext {
|
|
27
|
+
readonly node: CelloNode;
|
|
28
|
+
readonly logger: Logger;
|
|
29
|
+
readonly persistence: ClientStatePersistence;
|
|
30
|
+
getDirectoryEndpoint(): {
|
|
31
|
+
peer_id: string;
|
|
32
|
+
multiaddrs: string[];
|
|
33
|
+
} | null;
|
|
34
|
+
getThresholdSigner(): IThresholdSigner | undefined;
|
|
35
|
+
setThresholdSigner(signer: IThresholdSigner): void;
|
|
36
|
+
getMyPubkeyHex(): string | null;
|
|
37
|
+
setMyPubkeyHex(hex: string): void;
|
|
38
|
+
setRegistrationState(state: RegistrationState): void;
|
|
39
|
+
setMlDsaProvider(provider: MlDsaKeyProvider): void;
|
|
40
|
+
addConnection(connectionId: string, record: ClientConnectionRecord): void;
|
|
41
|
+
addConnectionByPeer(counterpartyPubkey: string, connectionId: string): void;
|
|
42
|
+
addProfileUncheckedPeer(pubkey: string): void;
|
|
43
|
+
setConnectionPolicy(policy: SignalRequirementPolicy): void;
|
|
44
|
+
addPeer(peerPubkeyHex: string, entry: PeerEntry): void;
|
|
45
|
+
hasPeer(peerPubkeyHex: string): boolean;
|
|
46
|
+
setEndorsements(endorsements: Array<Record<string, unknown>>): void;
|
|
47
|
+
setAttestations(attestations: Array<Record<string, unknown>>): void;
|
|
48
|
+
setLoadedPendingHashes(hashes: Array<{
|
|
49
|
+
sessionId: string;
|
|
50
|
+
hashHex: string;
|
|
51
|
+
enqueuedAt: number;
|
|
52
|
+
}>): void;
|
|
53
|
+
getSessionById(sessionIdHex: string): SessionRecord | undefined;
|
|
54
|
+
setSession(sessionIdHex: string, record: SessionRecord): void;
|
|
55
|
+
initSessionMessageQueue(sessionIdHex: string): void;
|
|
56
|
+
getMyPrimaryPubkey(): Uint8Array | null;
|
|
57
|
+
setMyPrimaryPubkey(pubkey: Uint8Array): void;
|
|
58
|
+
restoreDecidedRequest(requestId: string): void;
|
|
59
|
+
restorePendingInboundRequest(opts: {
|
|
60
|
+
connection_request_id: string;
|
|
61
|
+
from_pubkey: string;
|
|
62
|
+
package_cbor: Uint8Array;
|
|
63
|
+
round: number;
|
|
64
|
+
}): void;
|
|
65
|
+
restoreReviewQueueItem(item: ReviewQueueItem): void;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Load all durable state from the SQLCipher DB and populate in-memory state.
|
|
69
|
+
* Called by CelloClientImpl.loadPersistedState() after SQLCipher store opens.
|
|
70
|
+
*
|
|
71
|
+
* Returns the pending hashes loaded from the DB for the composition root to enqueue.
|
|
72
|
+
*/
|
|
73
|
+
export declare function loadClientStartupState(ctx: StartupContext): Promise<void>;
|
|
74
|
+
//# sourceMappingURL=client-startup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-startup.d.ts","sourceRoot":"","sources":["../src/client-startup.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* client-startup.ts — PERSIST-024: loadClientStartupState
|
|
3
|
+
*
|
|
4
|
+
* Extracted from CelloClientImpl.loadPersistedState to keep client.ts under AC-005 line budget.
|
|
5
|
+
* Loads all durable state from the SQLCipher DB and populates in-memory state via the
|
|
6
|
+
* StartupContext interface.
|
|
7
|
+
*
|
|
8
|
+
* Security invariants:
|
|
9
|
+
* SI-001: signing_share bytes never appear in any log event.
|
|
10
|
+
* SI-002: secret_key_blob bytes never appear in any log event.
|
|
11
|
+
*
|
|
12
|
+
* Crypto refs: RFC 9591 (FROST), NIST FIPS 204 (ML-DSA-44)
|
|
13
|
+
*/
|
|
14
|
+
import { decode } from "cbor-x";
|
|
15
|
+
import { InMemoryMlDsaKeyProvider } from "@cello-protocol/crypto";
|
|
16
|
+
import { storeDkgResult } from "@cello-protocol/crypto/frost/frost-threshold-signer.js";
|
|
17
|
+
import { FrostThresholdSigner } from "@cello-protocol/crypto/frost/frost-threshold-signer.js";
|
|
18
|
+
import { NetworkDirectoryNode } from "./network-directory-node.js";
|
|
19
|
+
/**
|
|
20
|
+
* Load all durable state from the SQLCipher DB and populate in-memory state.
|
|
21
|
+
* Called by CelloClientImpl.loadPersistedState() after SQLCipher store opens.
|
|
22
|
+
*
|
|
23
|
+
* Returns the pending hashes loaded from the DB for the composition root to enqueue.
|
|
24
|
+
*/
|
|
25
|
+
export async function loadClientStartupState(ctx) {
|
|
26
|
+
const p = ctx.persistence;
|
|
27
|
+
const state = await p.loadStartupState();
|
|
28
|
+
// ── 1. FROST key share ────────────────────────────────────────────────────
|
|
29
|
+
if (state.frostShare) {
|
|
30
|
+
const row = state.frostShare;
|
|
31
|
+
const signingShareBytes = row.signing_share instanceof Buffer
|
|
32
|
+
? new Uint8Array(row.signing_share)
|
|
33
|
+
: new Uint8Array(row.signing_share);
|
|
34
|
+
const frostSecret = { identifier: row.identifier, signingShare: signingShareBytes };
|
|
35
|
+
let commitments = [];
|
|
36
|
+
let verifyingShares = {};
|
|
37
|
+
try {
|
|
38
|
+
const commitmentsCborBytes = row.commitments_cbor instanceof Buffer
|
|
39
|
+
? row.commitments_cbor
|
|
40
|
+
: Buffer.from(row.commitments_cbor);
|
|
41
|
+
const decodedCommitments = decode(commitmentsCborBytes);
|
|
42
|
+
if (Array.isArray(decodedCommitments)) {
|
|
43
|
+
commitments = decodedCommitments.map((c) => c instanceof Uint8Array ? c : Buffer.isBuffer(c) ? new Uint8Array(c) : new Uint8Array(0));
|
|
44
|
+
}
|
|
45
|
+
const verifyingSharesCborBytes = row.verifying_shares_cbor instanceof Buffer
|
|
46
|
+
? row.verifying_shares_cbor
|
|
47
|
+
: Buffer.from(row.verifying_shares_cbor);
|
|
48
|
+
const decodedVerifyingShares = decode(verifyingSharesCborBytes);
|
|
49
|
+
if (decodedVerifyingShares && typeof decodedVerifyingShares === "object" && !Array.isArray(decodedVerifyingShares)) {
|
|
50
|
+
for (const [k, v] of Object.entries(decodedVerifyingShares)) {
|
|
51
|
+
verifyingShares[k] = v instanceof Uint8Array ? v : Buffer.isBuffer(v) ? new Uint8Array(v) : new Uint8Array(0);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
ctx.logger.error("client.frost.share.load.failed", {
|
|
57
|
+
agentPubkey: row.agent_pubkey,
|
|
58
|
+
reason: "cbor_deserialize_failed",
|
|
59
|
+
});
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const frostPublic = {
|
|
63
|
+
signers: { min: row.threshold, max: row.participants + 1 },
|
|
64
|
+
commitments,
|
|
65
|
+
verifyingShares,
|
|
66
|
+
};
|
|
67
|
+
const myPubkeyHex = row.agent_pubkey;
|
|
68
|
+
try {
|
|
69
|
+
// SI-001: storeDkgResult does not log the secret
|
|
70
|
+
storeDkgResult(myPubkeyHex, frostSecret, frostPublic);
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
ctx.logger.error("client.frost.share.load.failed", {
|
|
74
|
+
agentPubkey: myPubkeyHex,
|
|
75
|
+
reason: "storeDkgResult_failed",
|
|
76
|
+
});
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
// Reconstruct FrostThresholdSigner if not already set.
|
|
80
|
+
// AC-003 (DX-001): directoryNodeStubs MUST be populated from the current directoryEndpoint.
|
|
81
|
+
if (!ctx.getThresholdSigner()) {
|
|
82
|
+
let directoryNodeStubsForSigner;
|
|
83
|
+
const directoryEndpoint = ctx.getDirectoryEndpoint();
|
|
84
|
+
if (directoryEndpoint) {
|
|
85
|
+
const stub = new NetworkDirectoryNode({
|
|
86
|
+
id: directoryEndpoint.peer_id,
|
|
87
|
+
node: ctx.node,
|
|
88
|
+
directoryPeerId: directoryEndpoint.peer_id,
|
|
89
|
+
directoryMultiaddrs: directoryEndpoint.multiaddrs,
|
|
90
|
+
});
|
|
91
|
+
stub.setBootstrapContext(myPubkeyHex, `${myPubkeyHex}:epoch:1`);
|
|
92
|
+
directoryNodeStubsForSigner = [stub];
|
|
93
|
+
}
|
|
94
|
+
ctx.setThresholdSigner(new FrostThresholdSigner({
|
|
95
|
+
threshold: row.threshold,
|
|
96
|
+
participants: row.participants,
|
|
97
|
+
directoryNodeStubs: directoryNodeStubsForSigner,
|
|
98
|
+
}, Buffer.from(myPubkeyHex, "hex")));
|
|
99
|
+
}
|
|
100
|
+
if (commitments.length > 0 && !ctx.getMyPrimaryPubkey()) {
|
|
101
|
+
ctx.setMyPrimaryPubkey(new Uint8Array(commitments[0]));
|
|
102
|
+
}
|
|
103
|
+
ctx.logger.info("client.frost.share.loaded", {
|
|
104
|
+
agentPubkey: myPubkeyHex,
|
|
105
|
+
epochId: row.epoch_id,
|
|
106
|
+
threshold: row.threshold,
|
|
107
|
+
participants: row.participants,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
// HIGH-3: emit alarm when registration exists but no FROST share found
|
|
111
|
+
if (!state.frostShare && state.registrationState) {
|
|
112
|
+
ctx.logger.error("client.frost.share.missing", {
|
|
113
|
+
agentPubkey: state.registrationState.agent_pubkey,
|
|
114
|
+
reason: "no_active_share_in_db",
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
// ── 2. ML-DSA keypair ─────────────────────────────────────────────────────
|
|
118
|
+
if (state.mlDsaKeypair) {
|
|
119
|
+
const row = state.mlDsaKeypair;
|
|
120
|
+
try {
|
|
121
|
+
const secretKeyBlob = row.secret_key_blob instanceof Buffer
|
|
122
|
+
? new Uint8Array(row.secret_key_blob)
|
|
123
|
+
: new Uint8Array(row.secret_key_blob);
|
|
124
|
+
const mlDsaPubkeyBytes = Buffer.from(row.ml_dsa_pubkey, "hex");
|
|
125
|
+
// SI-002: InMemoryMlDsaKeyProvider does not log secret key
|
|
126
|
+
ctx.setMlDsaProvider(new InMemoryMlDsaKeyProvider(mlDsaPubkeyBytes, secretKeyBlob));
|
|
127
|
+
ctx.logger.info("client.mldsa.keypair.loaded", {
|
|
128
|
+
agentPubkey: row.agent_pubkey,
|
|
129
|
+
mlDsaPubkey: row.ml_dsa_pubkey,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
catch (err) {
|
|
133
|
+
ctx.logger.error("client.mldsa.load.failed", {
|
|
134
|
+
agentPubkey: row.agent_pubkey,
|
|
135
|
+
reason: err instanceof Error ? err.message : String(err),
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// ── 3. Registration state ─────────────────────────────────────────────────
|
|
140
|
+
if (state.registrationState) {
|
|
141
|
+
const row = state.registrationState;
|
|
142
|
+
ctx.setRegistrationState({
|
|
143
|
+
agent_id: row.agent_id,
|
|
144
|
+
primary_pubkey: row.primary_pubkey,
|
|
145
|
+
ml_dsa_pubkey: row.ml_dsa_pubkey,
|
|
146
|
+
registered_at: row.registered_at,
|
|
147
|
+
status: "active",
|
|
148
|
+
});
|
|
149
|
+
ctx.logger.info("client.registration.loaded", {
|
|
150
|
+
agentPubkey: row.agent_pubkey,
|
|
151
|
+
agentId: row.agent_id,
|
|
152
|
+
status: row.status,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
// ── 4. Connections ────────────────────────────────────────────────────────
|
|
156
|
+
for (const row of state.connections) {
|
|
157
|
+
const record = {
|
|
158
|
+
connection_id: row.connection_id,
|
|
159
|
+
counterparty_primary_pubkey: row.counterparty_primary_pubkey ?? "",
|
|
160
|
+
counterparty_ml_dsa_pubkey: row.counterparty_ml_dsa_pubkey ?? "",
|
|
161
|
+
counterparty_pubkey: row.counterparty_pubkey,
|
|
162
|
+
established_at: row.established_at,
|
|
163
|
+
status: row.status,
|
|
164
|
+
};
|
|
165
|
+
ctx.addConnection(row.connection_id, record);
|
|
166
|
+
ctx.addConnectionByPeer(row.counterparty_pubkey, row.connection_id);
|
|
167
|
+
if (row.profile_unchecked) {
|
|
168
|
+
ctx.addProfileUncheckedPeer(row.counterparty_pubkey);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
// ── 5. Connection policy ──────────────────────────────────────────────────
|
|
172
|
+
if (state.connectionPolicy) {
|
|
173
|
+
ctx.setConnectionPolicy(state.connectionPolicy);
|
|
174
|
+
}
|
|
175
|
+
// ── 6. Sessions + leaves ──────────────────────────────────────────────────
|
|
176
|
+
for (const row of state.sessions) {
|
|
177
|
+
const sessionIdHex = row.session_id;
|
|
178
|
+
if (ctx.getSessionById(sessionIdHex))
|
|
179
|
+
continue;
|
|
180
|
+
const leaves = await p.loadSessionTreeLeaves(sessionIdHex);
|
|
181
|
+
const localTreeLeaves = leaves.map((l) => ({
|
|
182
|
+
kind: l.leaf_kind,
|
|
183
|
+
s2_cbor: l.s2_cbor instanceof Buffer
|
|
184
|
+
? new Uint8Array(l.s2_cbor)
|
|
185
|
+
: new Uint8Array(l.s2_cbor),
|
|
186
|
+
}));
|
|
187
|
+
const counterpartyPubkey = row.counterparty_pubkey instanceof Buffer
|
|
188
|
+
? new Uint8Array(row.counterparty_pubkey)
|
|
189
|
+
: new Uint8Array(row.counterparty_pubkey);
|
|
190
|
+
const directoryPubkey = row.directory_pubkey instanceof Buffer
|
|
191
|
+
? new Uint8Array(row.directory_pubkey)
|
|
192
|
+
: new Uint8Array(row.directory_pubkey);
|
|
193
|
+
const genesisPrevRoot = row.genesis_prev_root instanceof Buffer
|
|
194
|
+
? new Uint8Array(row.genesis_prev_root)
|
|
195
|
+
: new Uint8Array(row.genesis_prev_root);
|
|
196
|
+
let counterpartyMultiaddrs = [];
|
|
197
|
+
let relayMultiaddrs = [];
|
|
198
|
+
let directoryMultiaddrs = [];
|
|
199
|
+
try {
|
|
200
|
+
counterpartyMultiaddrs = JSON.parse(row.counterparty_multiaddrs);
|
|
201
|
+
}
|
|
202
|
+
catch { /* ignore */ }
|
|
203
|
+
try {
|
|
204
|
+
relayMultiaddrs = JSON.parse(row.relay_multiaddrs);
|
|
205
|
+
}
|
|
206
|
+
catch { /* ignore */ }
|
|
207
|
+
try {
|
|
208
|
+
directoryMultiaddrs = JSON.parse(row.directory_multiaddrs);
|
|
209
|
+
}
|
|
210
|
+
catch { /* ignore */ }
|
|
211
|
+
const record = {
|
|
212
|
+
session_id: Buffer.from(sessionIdHex, "hex"),
|
|
213
|
+
counterparty_pubkey: counterpartyPubkey,
|
|
214
|
+
counterparty_peer_id: row.counterparty_peer_id,
|
|
215
|
+
counterparty_multiaddrs: counterpartyMultiaddrs,
|
|
216
|
+
relay_endpoint: { peer_id: row.relay_peer_id, multiaddrs: relayMultiaddrs },
|
|
217
|
+
directory_endpoint: { peer_id: row.directory_peer_id, multiaddrs: directoryMultiaddrs },
|
|
218
|
+
directory_pubkey: directoryPubkey,
|
|
219
|
+
genesis_prev_root: genesisPrevRoot,
|
|
220
|
+
last_seen_seq: row.last_seen_seq,
|
|
221
|
+
last_sent_seq: row.last_sent_seq,
|
|
222
|
+
next_expected_seq: row.next_expected_seq,
|
|
223
|
+
status: row.status,
|
|
224
|
+
desynchronized: row.desynchronized !== 0,
|
|
225
|
+
local_tree_leaves: localTreeLeaves,
|
|
226
|
+
sealed_root: row.sealed_root
|
|
227
|
+
? (row.sealed_root instanceof Buffer ? new Uint8Array(row.sealed_root) : new Uint8Array(row.sealed_root))
|
|
228
|
+
: undefined,
|
|
229
|
+
seal_type: row.seal_type ?? undefined,
|
|
230
|
+
close_timestamp: row.close_timestamp ?? undefined,
|
|
231
|
+
frost_signature: row.frost_signature
|
|
232
|
+
? (row.frost_signature instanceof Buffer ? new Uint8Array(row.frost_signature) : new Uint8Array(row.frost_signature))
|
|
233
|
+
: undefined,
|
|
234
|
+
signer_pubkey: row.signer_pubkey
|
|
235
|
+
? (row.signer_pubkey instanceof Buffer ? new Uint8Array(row.signer_pubkey) : new Uint8Array(row.signer_pubkey))
|
|
236
|
+
: undefined,
|
|
237
|
+
directory_signature: row.directory_signature
|
|
238
|
+
? (row.directory_signature instanceof Buffer ? new Uint8Array(row.directory_signature) : new Uint8Array(row.directory_signature))
|
|
239
|
+
: undefined,
|
|
240
|
+
};
|
|
241
|
+
ctx.setSession(sessionIdHex, record);
|
|
242
|
+
ctx.initSessionMessageQueue(sessionIdHex);
|
|
243
|
+
// HIGH-4: emit alarm when loaded leaf count doesn't match sessions.leaf_count
|
|
244
|
+
if (leaves.length !== row.leaf_count) {
|
|
245
|
+
ctx.logger.error("client.session.leaves.mismatch", {
|
|
246
|
+
agentPubkey: row.agent_pubkey,
|
|
247
|
+
sessionId: sessionIdHex,
|
|
248
|
+
expectedLeafCount: row.leaf_count,
|
|
249
|
+
actualLeafCount: leaves.length,
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
// ── 7. Peers ──────────────────────────────────────────────────────────────
|
|
254
|
+
for (const row of state.peers) {
|
|
255
|
+
if (!ctx.hasPeer(row.peer_pubkey_hex)) {
|
|
256
|
+
let multiaddrs = [];
|
|
257
|
+
try {
|
|
258
|
+
multiaddrs = JSON.parse(row.multiaddrs);
|
|
259
|
+
}
|
|
260
|
+
catch { /* ignore */ }
|
|
261
|
+
ctx.addPeer(row.peer_pubkey_hex, { peerId: row.peer_id, multiaddrs, connected: false });
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
// ── 8. Decided requests ───────────────────────────────────────────────────
|
|
265
|
+
for (const row of state.decidedRequests) {
|
|
266
|
+
ctx.restoreDecidedRequest(row.request_id);
|
|
267
|
+
}
|
|
268
|
+
// ── 9. Pending connection requests ────────────────────────────────────────
|
|
269
|
+
for (const row of state.pendingConnectionRequests) {
|
|
270
|
+
const packageCbor = row.package_cbor instanceof Buffer
|
|
271
|
+
? new Uint8Array(row.package_cbor)
|
|
272
|
+
: new Uint8Array(row.package_cbor);
|
|
273
|
+
ctx.restorePendingInboundRequest({
|
|
274
|
+
connection_request_id: row.request_id,
|
|
275
|
+
from_pubkey: row.from_pubkey,
|
|
276
|
+
package_cbor: packageCbor,
|
|
277
|
+
round: row.round,
|
|
278
|
+
});
|
|
279
|
+
ctx.restoreReviewQueueItem({
|
|
280
|
+
connection_request_id: row.request_id,
|
|
281
|
+
from_pubkey: row.from_pubkey,
|
|
282
|
+
report: {
|
|
283
|
+
verdict: "pending_agent_review",
|
|
284
|
+
policy_summary: {
|
|
285
|
+
mode: "unknown",
|
|
286
|
+
review_mode: "inference",
|
|
287
|
+
requirements_met: [],
|
|
288
|
+
requirements_unmet: [],
|
|
289
|
+
},
|
|
290
|
+
package_summary: {
|
|
291
|
+
pseudonym_label: "",
|
|
292
|
+
endorsement_count: 0,
|
|
293
|
+
attestation_types: [],
|
|
294
|
+
pseudonym_age_days: 0,
|
|
295
|
+
registration_age_days: 0,
|
|
296
|
+
is_provisional: false,
|
|
297
|
+
},
|
|
298
|
+
is_round_2: row.round > 1,
|
|
299
|
+
},
|
|
300
|
+
package_cbor: packageCbor,
|
|
301
|
+
sender_registered_at: 0,
|
|
302
|
+
sender_is_provisional: false,
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
// ── 10. Endorsements and attestations (MED-4) ────────────────────────────
|
|
306
|
+
if (state.endorsements.length > 0) {
|
|
307
|
+
ctx.setEndorsements(state.endorsements);
|
|
308
|
+
}
|
|
309
|
+
if (state.attestations.length > 0) {
|
|
310
|
+
ctx.setAttestations(state.attestations);
|
|
311
|
+
}
|
|
312
|
+
// HIGH-3: set myPubkeyHex from registration state if sessions were loaded
|
|
313
|
+
if (!ctx.getMyPubkeyHex() && state.registrationState) {
|
|
314
|
+
ctx.setMyPubkeyHex(state.registrationState.agent_pubkey);
|
|
315
|
+
}
|
|
316
|
+
// PERSIST-024 FINDING-4: store loaded pending hashes for caller consumption
|
|
317
|
+
ctx.setLoadedPendingHashes(state.pendingHashes.map((row) => ({
|
|
318
|
+
sessionId: row.session_id,
|
|
319
|
+
hashHex: row.hash_hex,
|
|
320
|
+
enqueuedAt: row.enqueued_at,
|
|
321
|
+
})));
|
|
322
|
+
// M-5: upsertAgent at the END of startup
|
|
323
|
+
await p.upsertAgent();
|
|
324
|
+
// PERSIST-024 FINDING-3: emit client.startup.state.loaded AFTER all in-memory structures populated
|
|
325
|
+
ctx.logger.info("client.startup.state.loaded", {
|
|
326
|
+
agentPubkey: ctx.getMyPubkeyHex() ?? state.registrationState?.agent_pubkey ?? "unknown",
|
|
327
|
+
connectionCount: state.connectionCount,
|
|
328
|
+
sessionCount: state.sessionCount,
|
|
329
|
+
leafCount: state.leafCount,
|
|
330
|
+
pendingHashCount: state.pendingHashCount,
|
|
331
|
+
hasFrostShare: state.hasFrostShare,
|
|
332
|
+
hasMlDsaKeypair: state.hasMlDsaKeypair,
|
|
333
|
+
hasRegistration: state.hasRegistration,
|
|
334
|
+
hasPolicy: state.hasPolicy,
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
//# sourceMappingURL=client-startup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-startup.js","sourceRoot":"","sources":["../src/client-startup.ts"],"names":[],"mappings":"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"}
|