@sumicom/quicksave 0.7.0 → 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.
Files changed (64) hide show
  1. package/README.md +110 -0
  2. package/dist/ai/cardBuilder.d.ts.map +1 -1
  3. package/dist/ai/cardBuilder.js +14 -2
  4. package/dist/ai/cardBuilder.js.map +1 -1
  5. package/dist/ai/claudeCliProvider.d.ts.map +1 -1
  6. package/dist/ai/claudeCliProvider.js +8 -11
  7. package/dist/ai/claudeCliProvider.js.map +1 -1
  8. package/dist/ai/claudeSdkProvider.d.ts.map +1 -1
  9. package/dist/ai/claudeSdkProvider.js +9 -14
  10. package/dist/ai/claudeSdkProvider.js.map +1 -1
  11. package/dist/ai/enrichEntry.d.ts +11 -0
  12. package/dist/ai/enrichEntry.d.ts.map +1 -0
  13. package/dist/ai/enrichEntry.js +27 -0
  14. package/dist/ai/enrichEntry.js.map +1 -0
  15. package/dist/ai/provider.d.ts +6 -0
  16. package/dist/ai/provider.d.ts.map +1 -1
  17. package/dist/ai/sandboxMcp.d.ts +41 -3
  18. package/dist/ai/sandboxMcp.d.ts.map +1 -1
  19. package/dist/ai/sandboxMcp.js +44 -3
  20. package/dist/ai/sandboxMcp.js.map +1 -1
  21. package/dist/ai/sandboxMcpStdio.js +103 -9
  22. package/dist/ai/sandboxMcpStdio.js.map +1 -1
  23. package/dist/ai/sessionManager.d.ts +23 -5
  24. package/dist/ai/sessionManager.d.ts.map +1 -1
  25. package/dist/ai/sessionManager.js +160 -22
  26. package/dist/ai/sessionManager.js.map +1 -1
  27. package/dist/ai/sessionRegistry.d.ts +57 -6
  28. package/dist/ai/sessionRegistry.d.ts.map +1 -1
  29. package/dist/ai/sessionRegistry.js +237 -31
  30. package/dist/ai/sessionRegistry.js.map +1 -1
  31. package/dist/config.d.ts +41 -0
  32. package/dist/config.d.ts.map +1 -1
  33. package/dist/config.js +86 -0
  34. package/dist/config.js.map +1 -1
  35. package/dist/connection/connection.d.ts +61 -0
  36. package/dist/connection/connection.d.ts.map +1 -1
  37. package/dist/connection/connection.js +274 -1
  38. package/dist/connection/connection.js.map +1 -1
  39. package/dist/connection/relay.d.ts +20 -0
  40. package/dist/connection/relay.d.ts.map +1 -1
  41. package/dist/connection/relay.js +62 -1
  42. package/dist/connection/relay.js.map +1 -1
  43. package/dist/handlers/messageHandler.d.ts +10 -6
  44. package/dist/handlers/messageHandler.d.ts.map +1 -1
  45. package/dist/handlers/messageHandler.js +59 -62
  46. package/dist/handlers/messageHandler.js.map +1 -1
  47. package/dist/index.js +74 -5
  48. package/dist/index.js.map +1 -1
  49. package/dist/service/ipcClient.js +1 -1
  50. package/dist/service/ipcServer.d.ts.map +1 -1
  51. package/dist/service/ipcServer.js +10 -4
  52. package/dist/service/ipcServer.js.map +1 -1
  53. package/dist/service/run.d.ts.map +1 -1
  54. package/dist/service/run.js +69 -27
  55. package/dist/service/run.js.map +1 -1
  56. package/dist/service/types.d.ts +15 -0
  57. package/dist/service/types.d.ts.map +1 -1
  58. package/dist/service/types.js +6 -2
  59. package/dist/service/types.js.map +1 -1
  60. package/dist/tombstoneCheck.d.ts +43 -0
  61. package/dist/tombstoneCheck.d.ts.map +1 -0
  62. package/dist/tombstoneCheck.js +96 -0
  63. package/dist/tombstoneCheck.js.map +1 -0
  64. package/package.json +3 -3
@@ -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,EASL,KAAK,OAAO,EAGb,MAAM,2BAA2B,CAAC;AAOnC,MAAM,WAAW,gBAAgB;IAC/B,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;CACnD;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,UAAU,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,YAAY,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAC/B;AAED,qBAAa,eAAgB,SAAQ,YAAY;IAC/C,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,KAAK,CAAuC;IACpD,OAAO,CAAC,MAAM,CAAgB;IAI9B,OAAO,CAAC,eAAe,CAAuC;IAG9D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,uBAAuB,CAAS;gBAE5C,MAAM,EAAE,gBAAgB;IAQpC,OAAO,CAAC,sBAAsB;IAyCxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YAQd,iBAAiB;IAsC/B;;OAEG;YACW,iBAAiB;IAqE/B,OAAO,CAAC,UAAU,CAAyC;IAE3D,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI;IAsBnD,OAAO,CAAC,sBAAsB;IAa9B,UAAU,IAAI,IAAI;IAIlB,YAAY,IAAI,MAAM;IAItB,UAAU,IAAI,MAAM;IAIpB,YAAY,IAAI,MAAM;IAItB,QAAQ,IAAI,OAAO;IAInB,gDAAgD;IAChD,aAAa,IAAI;QAAE,KAAK,EAAE,KAAK,CAAC;YAAE,OAAO,EAAE,MAAM,CAAC;YAAC,WAAW,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,EAAE,CAAA;SAAE,CAAC,CAAC;QAAC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;KAAE;IActI,iEAAiE;IACjE,SAAS,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;CAgBlC;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAE/E"}
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() {
@@ -1 +1 @@
1
- {"version":3,"file":"connection.js","sourceRoot":"","sources":["../../src/connection/connection.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"connection.js","sourceRoot":"","sources":["../../src/connection/connection.ts"],"names":[],"mappings":"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"}
@@ -6,6 +6,7 @@ export interface SignalingEvents {
6
6
  connected: () => void;
7
7
  disconnected: () => void;
8
8
  error: (error: Error) => void;
9
+ 'tombstone-event': (keyHash: string, data: string) => void;
9
10
  }
10
11
  export declare class SignalingClient extends EventEmitter {
11
12
  private ws;
@@ -15,6 +16,8 @@ export declare class SignalingClient extends EventEmitter {
15
16
  private reconnectDelay;
16
17
  private maxReconnectDelay;
17
18
  private isConnected;
19
+ /** Active tombstone subscriptions keyed by `keyHash`. Replayed on reconnect. */
20
+ private tombstoneSubscriptions;
18
21
  constructor(signalingServer: string, agentId: string);
19
22
  connect(): Promise<void>;
20
23
  private handleMessage;
@@ -23,6 +26,23 @@ export declare class SignalingClient extends EventEmitter {
23
26
  private compress;
24
27
  private decompress;
25
28
  private send;
29
+ /**
30
+ * Send a plain-JSON signaling message without gzip wrapping. The relay's
31
+ * `onMessage` hook parses the envelope directly, so control messages like
32
+ * `tombstone-subscribe` must skip the `{z:...}` compression envelope.
33
+ */
34
+ private sendRaw;
35
+ /**
36
+ * Ask the relay to push `tombstone-event` for `keyHash`. Idempotent: the
37
+ * relay de-dupes per socket, and we track subscriptions locally so reconnects
38
+ * replay them automatically.
39
+ */
40
+ subscribeTombstone(keyHash: string): void;
41
+ /**
42
+ * Stop receiving push for `keyHash`. Best-effort — if the socket is down the
43
+ * relay will drop the subscription on disconnect anyway.
44
+ */
45
+ unsubscribeTombstone(keyHash: string): void;
26
46
  private attemptReconnect;
27
47
  private intentionalDisconnect;
28
48
  private heartbeatInterval;
@@ -1 +1 @@
1
- {"version":3,"file":"relay.d.ts","sourceRoot":"","sources":["../../src/connection/relay.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAQtC,MAAM,WAAW,eAAe;IAC9B,gBAAgB,EAAE,MAAM,IAAI,CAAC;IAC7B,mBAAmB,EAAE,MAAM,IAAI,CAAC;IAChC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAClD,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAC/B;AAED,qBAAa,eAAgB,SAAQ,YAAY;IAC/C,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,cAAc,CAAQ;IAC9B,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,WAAW,CAAS;gBAEhB,eAAe,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;IAMpD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IA4DxB,OAAO,CAAC,aAAa;IA0BrB,OAAO,IAAI,IAAI;IAIf,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;YAkB5C,QAAQ;YAKR,UAAU;IAMxB,OAAO,CAAC,IAAI;IAWZ,OAAO,CAAC,gBAAgB;IAkBxB,OAAO,CAAC,qBAAqB,CAAS;IACtC,OAAO,CAAC,iBAAiB,CAA+C;IACxE,OAAO,CAAC,WAAW,CAA8C;IAEjE,OAAO,CAAC,cAAc;IAiBtB,OAAO,CAAC,cAAc;IAWtB,UAAU,IAAI,IAAI;IAUlB,UAAU,IAAI,MAAM;IAIpB,gBAAgB,IAAI,MAAM;CAG3B"}
1
+ {"version":3,"file":"relay.d.ts","sourceRoot":"","sources":["../../src/connection/relay.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAQtC,MAAM,WAAW,eAAe;IAC9B,gBAAgB,EAAE,MAAM,IAAI,CAAC;IAC7B,mBAAmB,EAAE,MAAM,IAAI,CAAC;IAChC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAClD,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAC9B,iBAAiB,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC5D;AAED,qBAAa,eAAgB,SAAQ,YAAY;IAC/C,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,cAAc,CAAQ;IAC9B,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,WAAW,CAAS;IAC5B,gFAAgF;IAChF,OAAO,CAAC,sBAAsB,CAAqB;gBAEvC,eAAe,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;IAMpD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IA6ExB,OAAO,CAAC,aAAa;IAuCrB,OAAO,IAAI,IAAI;IAIf,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;YAkB5C,QAAQ;YAKR,UAAU;IAMxB,OAAO,CAAC,IAAI;IAWZ;;;;OAIG;IACH,OAAO,CAAC,OAAO;IAMf;;;;OAIG;IACH,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAQzC;;;OAGG;IACH,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAQ3C,OAAO,CAAC,gBAAgB;IAkBxB,OAAO,CAAC,qBAAqB,CAAS;IACtC,OAAO,CAAC,iBAAiB,CAA+C;IACxE,OAAO,CAAC,WAAW,CAA8C;IAEjE,OAAO,CAAC,cAAc;IAiBtB,OAAO,CAAC,cAAc;IAWtB,UAAU,IAAI,IAAI;IAUlB,UAAU,IAAI,MAAM;IAIpB,gBAAgB,IAAI,MAAM;CAG3B"}
@@ -12,6 +12,8 @@ export class SignalingClient extends EventEmitter {
12
12
  reconnectDelay = 1000;
13
13
  maxReconnectDelay = 90000;
14
14
  isConnected = false;
15
+ /** Active tombstone subscriptions keyed by `keyHash`. Replayed on reconnect. */
16
+ tombstoneSubscriptions = new Set();
15
17
  constructor(signalingServer, agentId) {
16
18
  super();
17
19
  this.url = `${signalingServer}/agent/${agentId}`;
@@ -25,6 +27,14 @@ export class SignalingClient extends EventEmitter {
25
27
  this.isConnected = true;
26
28
  this.reconnectAttempts = 0;
27
29
  this.startHeartbeat();
30
+ // Replay active tombstone subscriptions so reconnects don't leave the
31
+ // agent silently unsubscribed after a relay restart or network blip.
32
+ for (const keyHash of this.tombstoneSubscriptions) {
33
+ this.sendRaw({
34
+ type: 'tombstone-subscribe',
35
+ payload: { keyHash },
36
+ });
37
+ }
28
38
  this.emit('connected');
29
39
  resolve();
30
40
  });
@@ -38,7 +48,16 @@ export class SignalingClient extends EventEmitter {
38
48
  return;
39
49
  }
40
50
  // Handle signaling messages (only specific types from signaling server)
41
- const signalingTypes = ['peer-connected', 'peer-offline', 'data', 'bye', 'error', 'pwa-bye'];
51
+ const signalingTypes = [
52
+ 'peer-connected',
53
+ 'peer-offline',
54
+ 'data',
55
+ 'bye',
56
+ 'error',
57
+ 'pwa-bye',
58
+ 'sync-updated',
59
+ 'tombstone-event',
60
+ ];
42
61
  if (parsed.type && signalingTypes.includes(parsed.type)) {
43
62
  this.handleMessage(parsed);
44
63
  return;
@@ -97,6 +116,15 @@ export class SignalingClient extends EventEmitter {
97
116
  }
98
117
  break;
99
118
  }
119
+ case 'tombstone-event': {
120
+ const payload = message.payload;
121
+ if (payload &&
122
+ typeof payload.keyHash === 'string' &&
123
+ typeof payload.data === 'string') {
124
+ this.emit('tombstone-event', payload.keyHash, payload.data);
125
+ }
126
+ break;
127
+ }
100
128
  }
101
129
  }
102
130
  sendBye() {
@@ -139,6 +167,39 @@ export class SignalingClient extends EventEmitter {
139
167
  });
140
168
  }
141
169
  }
170
+ /**
171
+ * Send a plain-JSON signaling message without gzip wrapping. The relay's
172
+ * `onMessage` hook parses the envelope directly, so control messages like
173
+ * `tombstone-subscribe` must skip the `{z:...}` compression envelope.
174
+ */
175
+ sendRaw(message) {
176
+ if (this.ws && this.ws.readyState === WebSocket.OPEN) {
177
+ this.ws.send(JSON.stringify(message));
178
+ }
179
+ }
180
+ /**
181
+ * Ask the relay to push `tombstone-event` for `keyHash`. Idempotent: the
182
+ * relay de-dupes per socket, and we track subscriptions locally so reconnects
183
+ * replay them automatically.
184
+ */
185
+ subscribeTombstone(keyHash) {
186
+ this.tombstoneSubscriptions.add(keyHash);
187
+ this.sendRaw({
188
+ type: 'tombstone-subscribe',
189
+ payload: { keyHash },
190
+ });
191
+ }
192
+ /**
193
+ * Stop receiving push for `keyHash`. Best-effort — if the socket is down the
194
+ * relay will drop the subscription on disconnect anyway.
195
+ */
196
+ unsubscribeTombstone(keyHash) {
197
+ this.tombstoneSubscriptions.delete(keyHash);
198
+ this.sendRaw({
199
+ type: 'tombstone-unsubscribe',
200
+ payload: { keyHash },
201
+ });
202
+ }
142
203
  attemptReconnect() {
143
204
  if (this.intentionalDisconnect)
144
205
  return;