@sumicom/quicksave 0.7.1 → 0.8.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/ai/claudeCliProvider.d.ts.map +1 -1
- package/dist/ai/claudeCliProvider.js +8 -11
- package/dist/ai/claudeCliProvider.js.map +1 -1
- package/dist/ai/claudeSdkProvider.d.ts.map +1 -1
- package/dist/ai/claudeSdkProvider.js +9 -14
- package/dist/ai/claudeSdkProvider.js.map +1 -1
- package/dist/ai/enrichEntry.d.ts +11 -0
- package/dist/ai/enrichEntry.d.ts.map +1 -0
- package/dist/ai/enrichEntry.js +27 -0
- package/dist/ai/enrichEntry.js.map +1 -0
- package/dist/ai/provider.d.ts +6 -0
- package/dist/ai/provider.d.ts.map +1 -1
- package/dist/ai/sandboxMcp.d.ts +41 -3
- package/dist/ai/sandboxMcp.d.ts.map +1 -1
- package/dist/ai/sandboxMcp.js +44 -3
- package/dist/ai/sandboxMcp.js.map +1 -1
- package/dist/ai/sandboxMcpStdio.js +103 -9
- package/dist/ai/sandboxMcpStdio.js.map +1 -1
- package/dist/ai/sessionManager.d.ts +14 -2
- package/dist/ai/sessionManager.d.ts.map +1 -1
- package/dist/ai/sessionManager.js +141 -19
- package/dist/ai/sessionManager.js.map +1 -1
- package/dist/ai/sessionRegistry.d.ts +57 -6
- package/dist/ai/sessionRegistry.d.ts.map +1 -1
- package/dist/ai/sessionRegistry.js +237 -31
- package/dist/ai/sessionRegistry.js.map +1 -1
- package/dist/config.d.ts +41 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +86 -0
- package/dist/config.js.map +1 -1
- package/dist/connection/connection.d.ts +61 -0
- package/dist/connection/connection.d.ts.map +1 -1
- package/dist/connection/connection.js +274 -1
- package/dist/connection/connection.js.map +1 -1
- package/dist/connection/relay.d.ts +20 -0
- package/dist/connection/relay.d.ts.map +1 -1
- package/dist/connection/relay.js +62 -1
- package/dist/connection/relay.js.map +1 -1
- package/dist/handlers/messageHandler.d.ts +10 -0
- package/dist/handlers/messageHandler.d.ts.map +1 -1
- package/dist/handlers/messageHandler.js +59 -3
- package/dist/handlers/messageHandler.js.map +1 -1
- package/dist/index.js +60 -2
- package/dist/index.js.map +1 -1
- package/dist/service/ipcClient.js +1 -1
- package/dist/service/ipcServer.d.ts.map +1 -1
- package/dist/service/ipcServer.js +10 -4
- package/dist/service/ipcServer.js.map +1 -1
- package/dist/service/run.d.ts.map +1 -1
- package/dist/service/run.js +69 -21
- package/dist/service/run.js.map +1 -1
- package/dist/service/types.d.ts +15 -0
- package/dist/service/types.d.ts.map +1 -1
- package/dist/service/types.js +6 -2
- package/dist/service/types.js.map +1 -1
- package/dist/tombstoneCheck.d.ts +43 -0
- package/dist/tombstoneCheck.d.ts.map +1 -0
- package/dist/tombstoneCheck.js +96 -0
- package/dist/tombstoneCheck.js.map +1 -0
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessionRegistry.js","sourceRoot":"","sources":["../../src/ai/sessionRegistry.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"sessionRegistry.js","sourceRoot":"","sources":["../../src/ai/sessionRegistry.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
CHANGED
|
@@ -9,6 +9,24 @@ export interface AgentConfig {
|
|
|
9
9
|
publicKey: string;
|
|
10
10
|
secretKey: string;
|
|
11
11
|
};
|
|
12
|
+
/**
|
|
13
|
+
* TOFU-pinned PWA group identity. `null` on a fresh / closed agent, which
|
|
14
|
+
* accepts the first successful V2 handshake as the trust anchor and writes
|
|
15
|
+
* both fields here. Once pinned, subsequent handshakes must prove possession
|
|
16
|
+
* of the same Ed25519 signing key before they are accepted.
|
|
17
|
+
*
|
|
18
|
+
* Cleared (set back to `null`) when a tombstone is observed on the pinned
|
|
19
|
+
* mailbox — the agent then enters the "closed" state until the user runs
|
|
20
|
+
* `quicksave pair` again.
|
|
21
|
+
*/
|
|
22
|
+
peerPWAPublicKey?: string | null;
|
|
23
|
+
peerPWASignPublicKey?: string | null;
|
|
24
|
+
/**
|
|
25
|
+
* Sticky self-destruct flag set after a verified tombstone. Persists across
|
|
26
|
+
* daemon restarts so a crash/restart window can't silently re-open TOFU.
|
|
27
|
+
* Cleared only by `unlockPairingAndRotate()` (driven by `quicksave pair`).
|
|
28
|
+
*/
|
|
29
|
+
closed?: boolean;
|
|
12
30
|
license?: License;
|
|
13
31
|
signalingServer: string;
|
|
14
32
|
anthropicApiKey?: string;
|
|
@@ -36,4 +54,27 @@ export declare function removeManagedCodingPath(path: string): void;
|
|
|
36
54
|
* This invalidates all existing PWA connections.
|
|
37
55
|
*/
|
|
38
56
|
export declare function rotateKeyPair(): AgentConfig;
|
|
57
|
+
/** True iff the agent has TOFU-pinned a PWA group identity. */
|
|
58
|
+
export declare function isPaired(config?: AgentConfig): boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Pin the given PWA group identity as this agent's trust anchor. Idempotent
|
|
61
|
+
* if the same pair is already stored; throws if a *different* pair is already
|
|
62
|
+
* pinned (caller must `clearPeerPWA` first, which is the tombstone path).
|
|
63
|
+
*/
|
|
64
|
+
export declare function pinPeerPWA(peerPWAPublicKey: string, peerPWASignPublicKey: string): AgentConfig;
|
|
65
|
+
/**
|
|
66
|
+
* Forget the pinned PWA group identity. Called when a signed tombstone is
|
|
67
|
+
* observed on the pinned mailbox. Rotates the agent's entire cryptographic
|
|
68
|
+
* identity (`agentId`, X25519 box keypair, Ed25519 signing keypair) so the
|
|
69
|
+
* old routing address and keys can no longer be used, and sets `closed: true`
|
|
70
|
+
* so the agent refuses every inbound handshake until `quicksave pair`.
|
|
71
|
+
*/
|
|
72
|
+
export declare function clearPeerPWA(): AgentConfig;
|
|
73
|
+
/**
|
|
74
|
+
* Lift the `closed` gate and produce a fresh agent identity. Called by the
|
|
75
|
+
* `quicksave pair` CLI path: even if the agent was already in a fresh state
|
|
76
|
+
* after tombstone, rotating again here means each new pairing attempt comes
|
|
77
|
+
* with an unburdened identity — no lingering state from prior pairings.
|
|
78
|
+
*/
|
|
79
|
+
export declare function unlockPairingAndRotate(): AgentConfig;
|
|
39
80
|
//# sourceMappingURL=config.d.ts.map
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,OAAO,EAA0D,KAAK,OAAO,EAAE,MAAM,2BAA2B,CAAC;AAGjH,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE;QACP,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,WAAW,EAAE;QACX,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC/B;AAID,wBAAgB,eAAe,IAAI,IAAI,CAKtC;AAED,wBAAgB,UAAU,IAAI,WAAW,GAAG,IAAI,CAU/C;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAGpD;AAED,wBAAgB,mBAAmB,CAAC,eAAe,EAAE,MAAM,GAAG,WAAW,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,OAAO,EAA0D,KAAK,OAAO,EAAE,MAAM,2BAA2B,CAAC;AAGjH,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE;QACP,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,WAAW,EAAE;QACX,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF;;;;;;;;;OASG;IACH,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC/B;AAID,wBAAgB,eAAe,IAAI,IAAI,CAKtC;AAED,wBAAgB,UAAU,IAAI,WAAW,GAAG,IAAI,CAU/C;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAGpD;AAED,wBAAgB,mBAAmB,CAAC,eAAe,EAAE,MAAM,GAAG,WAAW,CAYxE;AAED,wBAAgB,iBAAiB,CAAC,eAAe,EAAE,MAAM,GAAG,WAAW,CAmCtE;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAMjD;AAED,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAGD,wBAAgB,kBAAkB,IAAI,MAAM,GAAG,SAAS,CAEvD;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAMvD;AAED,wBAAgB,kBAAkB,IAAI,OAAO,CAE5C;AAGD,wBAAgB,eAAe,IAAI,MAAM,EAAE,CAE1C;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAQjD;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAUpD;AAGD,wBAAgB,qBAAqB,IAAI,MAAM,EAAE,CAEhD;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAQvD;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAU1D;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,WAAW,CAQ3C;AAED,+DAA+D;AAC/D,wBAAgB,QAAQ,CAAC,MAAM,GAAE,WAA2B,GAAG,OAAO,CAMrE;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CACxB,gBAAgB,EAAE,MAAM,EACxB,oBAAoB,EAAE,MAAM,GAC3B,WAAW,CAqBb;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,IAAI,WAAW,CAa1C;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,IAAI,WAAW,CAapD"}
|
package/dist/config.js
CHANGED
|
@@ -30,6 +30,9 @@ export function createDefaultConfig(signalingServer) {
|
|
|
30
30
|
agentId: generateAgentId(),
|
|
31
31
|
keyPair: generateAgentKeyPair(),
|
|
32
32
|
signKeyPair: encodeKeyPair(generateSigningKeyPair()),
|
|
33
|
+
peerPWAPublicKey: null,
|
|
34
|
+
peerPWASignPublicKey: null,
|
|
35
|
+
closed: false,
|
|
33
36
|
signalingServer,
|
|
34
37
|
};
|
|
35
38
|
saveConfig(config);
|
|
@@ -49,6 +52,19 @@ export function getOrCreateConfig(signalingServer) {
|
|
|
49
52
|
config.signKeyPair = encodeKeyPair(generateSigningKeyPair());
|
|
50
53
|
dirty = true;
|
|
51
54
|
}
|
|
55
|
+
// Pre-TOFU configs are legacy unpaired → normalize missing fields to null.
|
|
56
|
+
if (config.peerPWAPublicKey === undefined) {
|
|
57
|
+
config.peerPWAPublicKey = null;
|
|
58
|
+
dirty = true;
|
|
59
|
+
}
|
|
60
|
+
if (config.peerPWASignPublicKey === undefined) {
|
|
61
|
+
config.peerPWASignPublicKey = null;
|
|
62
|
+
dirty = true;
|
|
63
|
+
}
|
|
64
|
+
if (config.closed === undefined) {
|
|
65
|
+
config.closed = false;
|
|
66
|
+
dirty = true;
|
|
67
|
+
}
|
|
52
68
|
if (config.signalingServer !== signalingServer) {
|
|
53
69
|
config.signalingServer = signalingServer;
|
|
54
70
|
dirty = true;
|
|
@@ -145,4 +161,74 @@ export function rotateKeyPair() {
|
|
|
145
161
|
saveConfig(config);
|
|
146
162
|
return config;
|
|
147
163
|
}
|
|
164
|
+
/** True iff the agent has TOFU-pinned a PWA group identity. */
|
|
165
|
+
export function isPaired(config = loadConfig()) {
|
|
166
|
+
return (!!config &&
|
|
167
|
+
!!config.peerPWAPublicKey &&
|
|
168
|
+
!!config.peerPWASignPublicKey);
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Pin the given PWA group identity as this agent's trust anchor. Idempotent
|
|
172
|
+
* if the same pair is already stored; throws if a *different* pair is already
|
|
173
|
+
* pinned (caller must `clearPeerPWA` first, which is the tombstone path).
|
|
174
|
+
*/
|
|
175
|
+
export function pinPeerPWA(peerPWAPublicKey, peerPWASignPublicKey) {
|
|
176
|
+
const config = loadConfig();
|
|
177
|
+
if (!config) {
|
|
178
|
+
throw new Error('No config found. Run the agent first to generate a config.');
|
|
179
|
+
}
|
|
180
|
+
if (config.peerPWAPublicKey && config.peerPWASignPublicKey) {
|
|
181
|
+
if (config.peerPWAPublicKey === peerPWAPublicKey &&
|
|
182
|
+
config.peerPWASignPublicKey === peerPWASignPublicKey) {
|
|
183
|
+
return config;
|
|
184
|
+
}
|
|
185
|
+
throw new Error('Agent is already paired with a different PWA group identity. ' +
|
|
186
|
+
'Clear the pairing (rotate-keys tombstone or manual reset) first.');
|
|
187
|
+
}
|
|
188
|
+
config.peerPWAPublicKey = peerPWAPublicKey;
|
|
189
|
+
config.peerPWASignPublicKey = peerPWASignPublicKey;
|
|
190
|
+
saveConfig(config);
|
|
191
|
+
return config;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Forget the pinned PWA group identity. Called when a signed tombstone is
|
|
195
|
+
* observed on the pinned mailbox. Rotates the agent's entire cryptographic
|
|
196
|
+
* identity (`agentId`, X25519 box keypair, Ed25519 signing keypair) so the
|
|
197
|
+
* old routing address and keys can no longer be used, and sets `closed: true`
|
|
198
|
+
* so the agent refuses every inbound handshake until `quicksave pair`.
|
|
199
|
+
*/
|
|
200
|
+
export function clearPeerPWA() {
|
|
201
|
+
const config = loadConfig();
|
|
202
|
+
if (!config) {
|
|
203
|
+
throw new Error('No config found.');
|
|
204
|
+
}
|
|
205
|
+
config.peerPWAPublicKey = null;
|
|
206
|
+
config.peerPWASignPublicKey = null;
|
|
207
|
+
config.agentId = generateAgentId();
|
|
208
|
+
config.keyPair = generateAgentKeyPair();
|
|
209
|
+
config.signKeyPair = encodeKeyPair(generateSigningKeyPair());
|
|
210
|
+
config.closed = true;
|
|
211
|
+
saveConfig(config);
|
|
212
|
+
return config;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Lift the `closed` gate and produce a fresh agent identity. Called by the
|
|
216
|
+
* `quicksave pair` CLI path: even if the agent was already in a fresh state
|
|
217
|
+
* after tombstone, rotating again here means each new pairing attempt comes
|
|
218
|
+
* with an unburdened identity — no lingering state from prior pairings.
|
|
219
|
+
*/
|
|
220
|
+
export function unlockPairingAndRotate() {
|
|
221
|
+
const config = loadConfig();
|
|
222
|
+
if (!config) {
|
|
223
|
+
throw new Error('No config found.');
|
|
224
|
+
}
|
|
225
|
+
config.peerPWAPublicKey = null;
|
|
226
|
+
config.peerPWASignPublicKey = null;
|
|
227
|
+
config.agentId = generateAgentId();
|
|
228
|
+
config.keyPair = generateAgentKeyPair();
|
|
229
|
+
config.signKeyPair = encodeKeyPair(generateSigningKeyPair());
|
|
230
|
+
config.closed = false;
|
|
231
|
+
saveConfig(config);
|
|
232
|
+
return config;
|
|
233
|
+
}
|
|
148
234
|
//# sourceMappingURL=config.js.map
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AACxE,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,aAAa,EAAgB,MAAM,2BAA2B,CAAC;AACjH,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { EventEmitter } from 'events';
|
|
2
2
|
import { type Message } from '@sumicom/quicksave-shared';
|
|
3
|
+
import { type AgentConfig } from '../config.js';
|
|
4
|
+
import { type TombstoneCheckResult } from '../tombstoneCheck.js';
|
|
3
5
|
export interface ConnectionConfig {
|
|
4
6
|
signalingServer: string;
|
|
5
7
|
agentId: string;
|
|
@@ -18,7 +20,24 @@ export interface AgentConnectionEvents {
|
|
|
18
20
|
disconnected: (peerAddress: string) => void;
|
|
19
21
|
message: (message: Message, peerAddress: string) => void;
|
|
20
22
|
error: (error: Error) => void;
|
|
23
|
+
/**
|
|
24
|
+
* A verified tombstone was observed for the pinned peer PWA group. Config
|
|
25
|
+
* has already been cleared and the keypair rotated. Upper layers should
|
|
26
|
+
* typically stop the process or prompt the user to run `quicksave pair`.
|
|
27
|
+
*/
|
|
28
|
+
tombstoned: (details: {
|
|
29
|
+
oldPublicKey: string;
|
|
30
|
+
}) => void;
|
|
21
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Coarse-grained agent pairing state surfaced to the CLI + telemetry.
|
|
34
|
+
*
|
|
35
|
+
* - `unpaired`: ready to TOFU a new PWA group on the next handshake
|
|
36
|
+
* - `paired`: peerPWA identity is pinned; handshakes validated against it
|
|
37
|
+
* - `closed`: tombstone was observed; all incoming handshakes are refused
|
|
38
|
+
* until `unlockPairing()` is called (e.g. by `quicksave pair`)
|
|
39
|
+
*/
|
|
40
|
+
export type AgentPairState = 'unpaired' | 'paired' | 'closed';
|
|
22
41
|
export declare class AgentConnection extends EventEmitter {
|
|
23
42
|
private config;
|
|
24
43
|
private signaling;
|
|
@@ -27,9 +46,51 @@ export declare class AgentConnection extends EventEmitter {
|
|
|
27
46
|
private pubsub;
|
|
28
47
|
private savedPeerTopics;
|
|
29
48
|
private static readonly KEY_EXCHANGE_MAX_AGE_MS;
|
|
49
|
+
private static readonly TOMBSTONE_POLL_MS;
|
|
50
|
+
private tombstonePollTimer;
|
|
51
|
+
/** The keyHash we currently have an active relay subscription for, if any. */
|
|
52
|
+
private subscribedKeyHash;
|
|
30
53
|
constructor(config: ConnectionConfig);
|
|
31
54
|
private setupSignalingHandlers;
|
|
55
|
+
private handlePushedTombstone;
|
|
56
|
+
/**
|
|
57
|
+
* Subscribe to the pinned peer's tombstone mailbox via the relay push
|
|
58
|
+
* channel, if the agent is currently paired. Idempotent: safe to call from
|
|
59
|
+
* both `connected` and TOFU completion paths.
|
|
60
|
+
*/
|
|
61
|
+
private resubscribeIfPaired;
|
|
32
62
|
start(): Promise<void>;
|
|
63
|
+
/**
|
|
64
|
+
* Check the pinned peer's mailbox for a signed tombstone. No-op if the
|
|
65
|
+
* agent is not currently paired. Exposed so the signaling reconnect path
|
|
66
|
+
* can piggy-back on the check without re-implementing the policy.
|
|
67
|
+
*/
|
|
68
|
+
runTombstoneCheck(): Promise<TombstoneCheckResult | null>;
|
|
69
|
+
/**
|
|
70
|
+
* Invoked when a valid tombstone for the pinned peer group has been
|
|
71
|
+
* observed. Clears peer identity state on disk (which also rotates the
|
|
72
|
+
* agent's own keypair), tears down all active peer sessions, and emits
|
|
73
|
+
* `tombstoned` for upper layers. The signaling transport is left running
|
|
74
|
+
* so the agent can accept a fresh TOFU handshake from a rotated group.
|
|
75
|
+
*/
|
|
76
|
+
/**
|
|
77
|
+
* Coarse pair-state for CLI + telemetry. Reads the (possibly freshly-saved)
|
|
78
|
+
* config on each call so the answer stays accurate after tombstone cleanup.
|
|
79
|
+
* `closed` is now persisted on disk (`config.closed`), so a daemon restart
|
|
80
|
+
* preserves the self-destructed state.
|
|
81
|
+
*/
|
|
82
|
+
getState(): AgentPairState;
|
|
83
|
+
/**
|
|
84
|
+
* Lift the `closed` gate and rotate the agent's own cryptographic identity
|
|
85
|
+
* (`agentId`, X25519 keypair, Ed25519 signing keypair). Called by the
|
|
86
|
+
* `quicksave pair` CLI path. Tears down the current signaling connection
|
|
87
|
+
* and reconnects with the new `agentId` so old routing addresses stop
|
|
88
|
+
* receiving traffic. Safe to call from any state.
|
|
89
|
+
*/
|
|
90
|
+
unlockPairing(): Promise<AgentConfig>;
|
|
91
|
+
private handleVerifiedTombstone;
|
|
92
|
+
private startTombstonePolling;
|
|
93
|
+
private stopTombstonePolling;
|
|
33
94
|
private handleDataMessage;
|
|
34
95
|
/**
|
|
35
96
|
* Handle key exchange message
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/connection/connection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAGtC,OAAO,
|
|
1
|
+
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/connection/connection.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { EventEmitter } from 'events';
|
|
2
2
|
import { gzip, gunzip } from 'zlib';
|
|
3
3
|
import { promisify } from 'util';
|
|
4
|
-
import { generateKeyPair, encodeKeyPair, decodeKeyPair, encryptWithSharedSecret, decryptWithSharedSecret, decryptDEK, parseMessage, serializeMessage, } from '@sumicom/quicksave-shared';
|
|
4
|
+
import { generateKeyPair, encodeKeyPair, decodeKeyPair, decodeBase64, encryptWithSharedSecret, decryptWithSharedSecret, decryptDEK, parseMessage, serializeMessage, verifyKeyExchangeV2Signature, } from '@sumicom/quicksave-shared';
|
|
5
5
|
import { SignalingClient } from './relay.js';
|
|
6
6
|
import { PubSub, BROADCAST_TOPIC } from './pubsub.js';
|
|
7
|
+
import { clearPeerPWA, isPaired, loadConfig, pinPeerPWA, unlockPairingAndRotate, } from '../config.js';
|
|
8
|
+
import { checkTombstone, hashPublicKey, verifyTombstonePayload, } from '../tombstoneCheck.js';
|
|
7
9
|
const gzipAsync = promisify(gzip);
|
|
8
10
|
const gunzipAsync = promisify(gunzip);
|
|
9
11
|
export class AgentConnection extends EventEmitter {
|
|
@@ -17,6 +19,16 @@ export class AgentConnection extends EventEmitter {
|
|
|
17
19
|
savedPeerTopics = new Map();
|
|
18
20
|
// Key exchange replay protection
|
|
19
21
|
static KEY_EXCHANGE_MAX_AGE_MS = 60000; // 60 seconds
|
|
22
|
+
// Periodic catch-up GET fallback. Runs even when the relay-push channel is
|
|
23
|
+
// healthy — if the push path is silently broken (relay restart before we
|
|
24
|
+
// resubscribe, proxy dropping the message, etc.) this still catches the
|
|
25
|
+
// rotation within 3 minutes. 180s is the ceiling the user signed off on;
|
|
26
|
+
// tighter intervals trade latency for relay load that's not worth paying
|
|
27
|
+
// unless we see an incident.
|
|
28
|
+
static TOMBSTONE_POLL_MS = 180_000;
|
|
29
|
+
tombstonePollTimer = null;
|
|
30
|
+
/** The keyHash we currently have an active relay subscription for, if any. */
|
|
31
|
+
subscribedKeyHash = null;
|
|
20
32
|
constructor(config) {
|
|
21
33
|
super();
|
|
22
34
|
this.config = config;
|
|
@@ -25,6 +37,14 @@ export class AgentConnection extends EventEmitter {
|
|
|
25
37
|
this.setupSignalingHandlers();
|
|
26
38
|
}
|
|
27
39
|
setupSignalingHandlers() {
|
|
40
|
+
this.signaling.on('connected', () => {
|
|
41
|
+
// Each (re)connect is a chance to catch up on a missed tombstone.
|
|
42
|
+
void this.runTombstoneCheck();
|
|
43
|
+
// (Re-)subscribe the push channel if we already know the pinned peer.
|
|
44
|
+
// Unpaired agents have no mailbox to watch yet; TOFU will call this
|
|
45
|
+
// helper explicitly after pinning.
|
|
46
|
+
this.resubscribeIfPaired();
|
|
47
|
+
});
|
|
28
48
|
this.signaling.on('peer-connected', () => {
|
|
29
49
|
console.log('PWA peer connected, waiting for key exchange...');
|
|
30
50
|
});
|
|
@@ -58,6 +78,58 @@ export class AgentConnection extends EventEmitter {
|
|
|
58
78
|
this.signaling.on('error', (error) => {
|
|
59
79
|
this.emit('error', error);
|
|
60
80
|
});
|
|
81
|
+
// Relay-pushed tombstone — the emergency fast path. We still verify locally
|
|
82
|
+
// with the pinned signing pubkey because the relay is untrusted; a forged
|
|
83
|
+
// payload here will simply fail verification and be dropped.
|
|
84
|
+
this.signaling.on('tombstone-event', (keyHash, data) => {
|
|
85
|
+
this.handlePushedTombstone(keyHash, data);
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
handlePushedTombstone(keyHash, data) {
|
|
89
|
+
// Short-circuit once we're already closed: the catch-up GET and the push
|
|
90
|
+
// path can both fire for the same tombstone, and after the first handler
|
|
91
|
+
// runs `peerPWAPublicKey` is null on disk.
|
|
92
|
+
if (this.getState() === 'closed')
|
|
93
|
+
return;
|
|
94
|
+
const config = loadConfig();
|
|
95
|
+
if (!config || !isPaired(config))
|
|
96
|
+
return;
|
|
97
|
+
const expectedHash = hashPublicKey(config.peerPWAPublicKey);
|
|
98
|
+
if (keyHash !== expectedHash) {
|
|
99
|
+
// Ignore pushes for mailboxes we aren't pinned to. Shouldn't happen
|
|
100
|
+
// because we only subscribe to our pinned peer, but the relay is
|
|
101
|
+
// untrusted so we verify anyway.
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const result = verifyTombstonePayload(data, config.peerPWAPublicKey, config.peerPWASignPublicKey);
|
|
105
|
+
if (result.status === 'tombstoned') {
|
|
106
|
+
this.handleVerifiedTombstone(result.tombstone.oldPublicKey);
|
|
107
|
+
}
|
|
108
|
+
else if (result.status === 'verify-failed') {
|
|
109
|
+
console.error(`Pushed tombstone verification failed: ${result.reason}`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Subscribe to the pinned peer's tombstone mailbox via the relay push
|
|
114
|
+
* channel, if the agent is currently paired. Idempotent: safe to call from
|
|
115
|
+
* both `connected` and TOFU completion paths.
|
|
116
|
+
*/
|
|
117
|
+
resubscribeIfPaired() {
|
|
118
|
+
const config = loadConfig();
|
|
119
|
+
if (!config || !isPaired(config))
|
|
120
|
+
return;
|
|
121
|
+
const keyHash = hashPublicKey(config.peerPWAPublicKey);
|
|
122
|
+
if (this.subscribedKeyHash === keyHash) {
|
|
123
|
+
// Already subscribed to the same key — but the SignalingClient replays
|
|
124
|
+
// its own subscription set on reconnect, so we don't need to re-send.
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
// If we were subscribed to an old key (e.g. after unlockPairing), drop it.
|
|
128
|
+
if (this.subscribedKeyHash) {
|
|
129
|
+
this.signaling.unsubscribeTombstone(this.subscribedKeyHash);
|
|
130
|
+
}
|
|
131
|
+
this.signaling.subscribeTombstone(keyHash);
|
|
132
|
+
this.subscribedKeyHash = keyHash;
|
|
61
133
|
}
|
|
62
134
|
async start() {
|
|
63
135
|
console.log('Connecting to signaling server...');
|
|
@@ -65,6 +137,148 @@ export class AgentConnection extends EventEmitter {
|
|
|
65
137
|
console.log('Connected to signaling server');
|
|
66
138
|
console.log(`Agent ID: ${this.config.agentId}`);
|
|
67
139
|
console.log(`Public Key: ${this.config.keyPair.publicKey}`);
|
|
140
|
+
// Tombstone catch-up runs from the 'connected' handler registered in
|
|
141
|
+
// setupSignalingHandlers(), so every reconnect re-checks too. Also start
|
|
142
|
+
// the 180s periodic fallback in case the push channel silently breaks.
|
|
143
|
+
this.startTombstonePolling();
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Check the pinned peer's mailbox for a signed tombstone. No-op if the
|
|
147
|
+
* agent is not currently paired. Exposed so the signaling reconnect path
|
|
148
|
+
* can piggy-back on the check without re-implementing the policy.
|
|
149
|
+
*/
|
|
150
|
+
async runTombstoneCheck() {
|
|
151
|
+
const config = loadConfig();
|
|
152
|
+
if (!config || !isPaired(config))
|
|
153
|
+
return null;
|
|
154
|
+
const result = await checkTombstone({
|
|
155
|
+
signalingServer: this.config.signalingServer,
|
|
156
|
+
peerPWAPublicKey: config.peerPWAPublicKey,
|
|
157
|
+
peerPWASignPublicKey: config.peerPWASignPublicKey,
|
|
158
|
+
});
|
|
159
|
+
if (result.status === 'tombstoned') {
|
|
160
|
+
this.handleVerifiedTombstone(result.tombstone.oldPublicKey);
|
|
161
|
+
}
|
|
162
|
+
else if (result.status === 'verify-failed') {
|
|
163
|
+
console.error(`Tombstone check: verification failed (${result.reason})`);
|
|
164
|
+
}
|
|
165
|
+
else if (result.status === 'error') {
|
|
166
|
+
// Network / transient errors are non-fatal; we'll recheck next connect.
|
|
167
|
+
console.error(`Tombstone check: ${result.error}`);
|
|
168
|
+
}
|
|
169
|
+
return result;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Invoked when a valid tombstone for the pinned peer group has been
|
|
173
|
+
* observed. Clears peer identity state on disk (which also rotates the
|
|
174
|
+
* agent's own keypair), tears down all active peer sessions, and emits
|
|
175
|
+
* `tombstoned` for upper layers. The signaling transport is left running
|
|
176
|
+
* so the agent can accept a fresh TOFU handshake from a rotated group.
|
|
177
|
+
*/
|
|
178
|
+
/**
|
|
179
|
+
* Coarse pair-state for CLI + telemetry. Reads the (possibly freshly-saved)
|
|
180
|
+
* config on each call so the answer stays accurate after tombstone cleanup.
|
|
181
|
+
* `closed` is now persisted on disk (`config.closed`), so a daemon restart
|
|
182
|
+
* preserves the self-destructed state.
|
|
183
|
+
*/
|
|
184
|
+
getState() {
|
|
185
|
+
const config = loadConfig();
|
|
186
|
+
if (!config)
|
|
187
|
+
return 'unpaired';
|
|
188
|
+
if (config.closed)
|
|
189
|
+
return 'closed';
|
|
190
|
+
return isPaired(config) ? 'paired' : 'unpaired';
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Lift the `closed` gate and rotate the agent's own cryptographic identity
|
|
194
|
+
* (`agentId`, X25519 keypair, Ed25519 signing keypair). Called by the
|
|
195
|
+
* `quicksave pair` CLI path. Tears down the current signaling connection
|
|
196
|
+
* and reconnects with the new `agentId` so old routing addresses stop
|
|
197
|
+
* receiving traffic. Safe to call from any state.
|
|
198
|
+
*/
|
|
199
|
+
async unlockPairing() {
|
|
200
|
+
const newConfig = unlockPairingAndRotate();
|
|
201
|
+
this.config = {
|
|
202
|
+
...this.config,
|
|
203
|
+
agentId: newConfig.agentId,
|
|
204
|
+
keyPair: newConfig.keyPair,
|
|
205
|
+
};
|
|
206
|
+
this.keyPair = decodeKeyPair(newConfig.keyPair);
|
|
207
|
+
// Tear down every active peer session — old DEKs are irrelevant under the
|
|
208
|
+
// rotated keypair anyway.
|
|
209
|
+
for (const [address] of this.peers) {
|
|
210
|
+
this.pubsub.unsubscribeAll(address);
|
|
211
|
+
this.emit('disconnected', address);
|
|
212
|
+
}
|
|
213
|
+
this.peers.clear();
|
|
214
|
+
this.savedPeerTopics.clear();
|
|
215
|
+
// No pinned mailbox yet under the rotated identity — clear the locally
|
|
216
|
+
// tracked subscription so the next TOFU can subscribe fresh.
|
|
217
|
+
this.subscribedKeyHash = null;
|
|
218
|
+
// Reinstantiate signaling under the new agentId so the relay routes to
|
|
219
|
+
// this process under the new address only.
|
|
220
|
+
this.signaling.removeAllListeners();
|
|
221
|
+
this.signaling.disconnect();
|
|
222
|
+
this.signaling = new SignalingClient(this.config.signalingServer, newConfig.agentId);
|
|
223
|
+
this.setupSignalingHandlers();
|
|
224
|
+
try {
|
|
225
|
+
await this.signaling.connect();
|
|
226
|
+
}
|
|
227
|
+
catch (err) {
|
|
228
|
+
console.error('Signaling reconnect after unlockPairing failed:', err);
|
|
229
|
+
// Leave the SignalingClient object in place; its own reconnect loop
|
|
230
|
+
// will keep trying.
|
|
231
|
+
}
|
|
232
|
+
this.emit('identity-rotated', { agentId: newConfig.agentId });
|
|
233
|
+
return newConfig;
|
|
234
|
+
}
|
|
235
|
+
handleVerifiedTombstone(oldPublicKey) {
|
|
236
|
+
// Idempotency guard: the push-channel event and the catch-up GET can race,
|
|
237
|
+
// and both may fire before the first one has finished writing to disk. The
|
|
238
|
+
// persisted `closed` flag is the canonical answer; once set, we ignore
|
|
239
|
+
// further tombstone triggers until `unlockPairing()` clears it.
|
|
240
|
+
if (this.getState() === 'closed') {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
console.warn(`Tombstone verified for pinned peer ${oldPublicKey.slice(0, 12)}... — self-destructing pairing`);
|
|
244
|
+
// Best-effort unsubscribe from the relay push channel; the closed-state
|
|
245
|
+
// gate in handleKeyExchange is the real line of defense.
|
|
246
|
+
if (this.subscribedKeyHash) {
|
|
247
|
+
this.signaling.unsubscribeTombstone(this.subscribedKeyHash);
|
|
248
|
+
this.subscribedKeyHash = null;
|
|
249
|
+
}
|
|
250
|
+
this.stopTombstonePolling();
|
|
251
|
+
// Tear down every active peer session first so no leftover DEK answers.
|
|
252
|
+
for (const [address] of this.peers) {
|
|
253
|
+
this.pubsub.unsubscribeAll(address);
|
|
254
|
+
this.emit('disconnected', address);
|
|
255
|
+
}
|
|
256
|
+
this.peers.clear();
|
|
257
|
+
this.savedPeerTopics.clear();
|
|
258
|
+
try {
|
|
259
|
+
clearPeerPWA();
|
|
260
|
+
}
|
|
261
|
+
catch (err) {
|
|
262
|
+
console.error('clearPeerPWA failed during tombstone handling:', err);
|
|
263
|
+
}
|
|
264
|
+
this.emit('tombstoned', { oldPublicKey });
|
|
265
|
+
}
|
|
266
|
+
startTombstonePolling() {
|
|
267
|
+
if (this.tombstonePollTimer)
|
|
268
|
+
return;
|
|
269
|
+
this.tombstonePollTimer = setInterval(() => {
|
|
270
|
+
// Errors and 'absent' are silent — treated as no-op, same as the existing
|
|
271
|
+
// runTombstoneCheck behaviour. We only act on verified tombstones.
|
|
272
|
+
void this.runTombstoneCheck();
|
|
273
|
+
}, AgentConnection.TOMBSTONE_POLL_MS);
|
|
274
|
+
// Don't block process shutdown on the polling timer.
|
|
275
|
+
this.tombstonePollTimer.unref?.();
|
|
276
|
+
}
|
|
277
|
+
stopTombstonePolling() {
|
|
278
|
+
if (this.tombstonePollTimer) {
|
|
279
|
+
clearInterval(this.tombstonePollTimer);
|
|
280
|
+
this.tombstonePollTimer = null;
|
|
281
|
+
}
|
|
68
282
|
}
|
|
69
283
|
async handleDataMessage(data, from) {
|
|
70
284
|
try {
|
|
@@ -106,6 +320,14 @@ export class AgentConnection extends EventEmitter {
|
|
|
106
320
|
* Handle key exchange message
|
|
107
321
|
*/
|
|
108
322
|
async handleKeyExchange(message, from) {
|
|
323
|
+
// Closed state gate: once we've self-destructed from a tombstone, refuse
|
|
324
|
+
// any handshake until an operator runs `quicksave pair` (which calls
|
|
325
|
+
// `unlockPairing()`). Sourced from the persisted `config.closed` flag.
|
|
326
|
+
if (this.getState() === 'closed') {
|
|
327
|
+
console.error('Agent is in closed state; refusing key exchange until `quicksave pair` is run');
|
|
328
|
+
this.emit('error', new Error('Agent closed after tombstone; run `quicksave pair` to re-enable'));
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
109
331
|
// Verify timestamp for replay protection
|
|
110
332
|
const age = Date.now() - message.timestamp;
|
|
111
333
|
if (age > AgentConnection.KEY_EXCHANGE_MAX_AGE_MS) {
|
|
@@ -119,6 +341,56 @@ export class AgentConnection extends EventEmitter {
|
|
|
119
341
|
this.emit('error', new Error('Key exchange timestamp invalid'));
|
|
120
342
|
return;
|
|
121
343
|
}
|
|
344
|
+
// Proof-of-possession: the PWA must sign the canonical key-exchange body
|
|
345
|
+
// with the group's shared Ed25519 key. On the first successful handshake
|
|
346
|
+
// we TOFU-pin that key; after that, sigPubkey must match the pinned one.
|
|
347
|
+
if (!message.sigPubkey || !message.signature) {
|
|
348
|
+
console.error('Key exchange missing sigPubkey/signature — rejecting pre-TOFU legacy peer');
|
|
349
|
+
this.emit('error', new Error('Key exchange missing signature'));
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
const sigValid = verifyKeyExchangeV2Signature({
|
|
353
|
+
agentId: this.config.agentId,
|
|
354
|
+
encryptedDEK: message.encryptedDEK,
|
|
355
|
+
timestamp: message.timestamp,
|
|
356
|
+
sigPubkey: message.sigPubkey,
|
|
357
|
+
signature: message.signature,
|
|
358
|
+
decodeBase64,
|
|
359
|
+
});
|
|
360
|
+
if (!sigValid) {
|
|
361
|
+
console.error('Key exchange signature verification failed');
|
|
362
|
+
this.emit('error', new Error('Key exchange signature invalid'));
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
const config = loadConfig();
|
|
366
|
+
if (config && isPaired(config)) {
|
|
367
|
+
if (message.sigPubkey !== config.peerPWASignPublicKey) {
|
|
368
|
+
console.error('Key exchange sigPubkey does not match pinned peer — rejecting');
|
|
369
|
+
this.emit('error', new Error('Key exchange sigPubkey mismatch (peer not the pinned PWA group)'));
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
else {
|
|
374
|
+
// Unpaired: TOFU. Pin the claimed signing key (and the PWA's X25519
|
|
375
|
+
// pubkey, derived from the routed address — `pwa:{publicKey}`) for
|
|
376
|
+
// all future handshakes.
|
|
377
|
+
const peerPWAPublicKey = (from ?? '').replace(/^pwa:/, '');
|
|
378
|
+
if (peerPWAPublicKey && config) {
|
|
379
|
+
try {
|
|
380
|
+
pinPeerPWA(peerPWAPublicKey, message.sigPubkey);
|
|
381
|
+
console.log(`TOFU: pinned peer PWA pubkey ${peerPWAPublicKey.slice(0, 12)}... ` +
|
|
382
|
+
`sig ${message.sigPubkey.slice(0, 12)}...`);
|
|
383
|
+
// Now that we have a pinned mailbox, start listening for pushed
|
|
384
|
+
// tombstones on it. Idempotent.
|
|
385
|
+
this.resubscribeIfPaired();
|
|
386
|
+
}
|
|
387
|
+
catch (err) {
|
|
388
|
+
console.error('TOFU pin failed:', err);
|
|
389
|
+
this.emit('error', err instanceof Error ? err : new Error('TOFU pin failed'));
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
122
394
|
// Decrypt the session DEK
|
|
123
395
|
try {
|
|
124
396
|
const sessionDEK = decryptDEK(message.encryptedDEK, this.keyPair.secretKey);
|
|
@@ -199,6 +471,7 @@ export class AgentConnection extends EventEmitter {
|
|
|
199
471
|
console.log('Peer disconnected, waiting for new connection...');
|
|
200
472
|
}
|
|
201
473
|
disconnect() {
|
|
474
|
+
this.stopTombstonePolling();
|
|
202
475
|
this.signaling.disconnect();
|
|
203
476
|
}
|
|
204
477
|
getPublicKey() {
|