@agentvault/agentvault 0.19.35 → 0.19.37

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/cli.js CHANGED
@@ -47189,7 +47189,8 @@ var init_channel = __esm({
47189
47189
  this._sessions.set(convId, {
47190
47190
  ownerDeviceId: sessionData.ownerDeviceId,
47191
47191
  ratchet,
47192
- activated: sessionData.activated ?? false
47192
+ activated: sessionData.activated ?? false,
47193
+ epoch: sessionData.epoch
47193
47194
  });
47194
47195
  }
47195
47196
  }
@@ -47228,7 +47229,8 @@ var init_channel = __esm({
47228
47229
  this._sessions.set(convId, {
47229
47230
  ownerDeviceId: sd.ownerDeviceId,
47230
47231
  ratchet: DoubleRatchet.deserialize(sd.ratchetState),
47231
- activated: sd.activated ?? false
47232
+ activated: sd.activated ?? false,
47233
+ epoch: sd.epoch
47232
47234
  });
47233
47235
  }
47234
47236
  }
@@ -47568,13 +47570,15 @@ var init_channel = __esm({
47568
47570
  this._sessions.set(conv.id, {
47569
47571
  ownerDeviceId: otherDeviceId,
47570
47572
  ratchet,
47571
- activated: isInitiator
47573
+ activated: isInitiator,
47572
47574
  // initiator can send immediately
47575
+ epoch: 1
47573
47576
  });
47574
47577
  this._persisted.sessions[conv.id] = {
47575
47578
  ownerDeviceId: otherDeviceId,
47576
47579
  ratchetState: ratchet.serialize(),
47577
- activated: isInitiator
47580
+ activated: isInitiator,
47581
+ epoch: 1
47578
47582
  };
47579
47583
  conversationIds.push(conv.id);
47580
47584
  console.log(
@@ -48669,12 +48673,14 @@ var init_channel = __esm({
48669
48673
  this._sessions.set(conv.conversation_id, {
48670
48674
  ownerDeviceId: conv.owner_device_id,
48671
48675
  ratchet,
48672
- activated: false
48676
+ activated: false,
48673
48677
  // Wait for owner's first message before sending to this session
48678
+ epoch: 1
48674
48679
  });
48675
48680
  sessions[conv.conversation_id] = {
48676
48681
  ownerDeviceId: conv.owner_device_id,
48677
- ratchetState: ratchet.serialize()
48682
+ ratchetState: ratchet.serialize(),
48683
+ epoch: 1
48678
48684
  };
48679
48685
  console.log(
48680
48686
  `[SecureChannel] Session initialized for conv ${conv.conversation_id.slice(0, 8)}... (owner ${conv.owner_device_id.slice(0, 8)}..., primary=${conv.is_primary})`
@@ -49173,8 +49179,9 @@ var init_channel = __esm({
49173
49179
  ownerDeviceId: "",
49174
49180
  // A2A sessions don't have an owner device
49175
49181
  ratchetState: ratchet.serialize(),
49176
- activated: activatedRole === "initiator"
49182
+ activated: activatedRole === "initiator",
49177
49183
  // initiator can send immediately
49184
+ epoch: 1
49178
49185
  };
49179
49186
  channelEntry.role = activatedRole;
49180
49187
  if (convId) channelEntry.conversationId = convId;
@@ -49359,7 +49366,8 @@ var init_channel = __esm({
49359
49366
  conversation_id: convId,
49360
49367
  reason: "no_session",
49361
49368
  identity_public_key: this._persisted.identityKeypair.publicKey,
49362
- ephemeral_public_key: this._persisted.ephemeralKeypair.publicKey
49369
+ ephemeral_public_key: this._persisted.ephemeralKeypair.publicKey,
49370
+ epoch: this._persisted.sessions[convId]?.epoch
49363
49371
  }
49364
49372
  })
49365
49373
  );
@@ -49398,7 +49406,8 @@ var init_channel = __esm({
49398
49406
  conversation_id: convId,
49399
49407
  reason: "decrypt_failure",
49400
49408
  identity_public_key: idPubHex,
49401
- ephemeral_public_key: ephPubHex
49409
+ ephemeral_public_key: ephPubHex,
49410
+ epoch: this._persisted?.sessions[convId]?.epoch
49402
49411
  }
49403
49412
  })
49404
49413
  );
@@ -49832,13 +49841,15 @@ ${messageText}`;
49832
49841
  this._sessions.set(event.conversation_id, {
49833
49842
  ownerDeviceId: event.owner_device_id,
49834
49843
  ratchet,
49835
- activated: false
49844
+ activated: false,
49836
49845
  // Wait for owner's first message
49846
+ epoch: 1
49837
49847
  });
49838
49848
  this._persisted.sessions[event.conversation_id] = {
49839
49849
  ownerDeviceId: event.owner_device_id,
49840
49850
  ratchetState: ratchet.serialize(),
49841
- activated: false
49851
+ activated: false,
49852
+ epoch: 1
49842
49853
  };
49843
49854
  if (event.owner_hub_id) {
49844
49855
  this._persisted.ownerHubId = event.owner_hub_id;
@@ -49885,17 +49896,21 @@ ${messageText}`;
49885
49896
  keyType: "ed25519"
49886
49897
  }, hexToBytes(data.identity_public_key));
49887
49898
  const existingSession = this._sessions.get(convId);
49899
+ const existingPersisted = this._persisted.sessions[convId];
49888
49900
  const ownerDeviceId = data.sender_device_id ?? existingSession?.ownerDeviceId ?? "";
49901
+ const newEpoch = (existingPersisted?.epoch ?? existingSession?.epoch ?? 0) + 1;
49889
49902
  this._sessions.set(convId, {
49890
49903
  ownerDeviceId,
49891
49904
  ratchet,
49892
- activated: false
49905
+ activated: false,
49893
49906
  // Wait for owner's encrypted session_init
49907
+ epoch: newEpoch
49894
49908
  });
49895
49909
  this._persisted.sessions[convId] = {
49896
49910
  ownerDeviceId,
49897
49911
  ratchetState: ratchet.serialize(),
49898
- activated: false
49912
+ activated: false,
49913
+ epoch: newEpoch
49899
49914
  };
49900
49915
  await this._persistState();
49901
49916
  if (this._ws) {
@@ -49905,7 +49920,8 @@ ${messageText}`;
49905
49920
  data: {
49906
49921
  conversation_id: convId,
49907
49922
  identity_public_key: identity.publicKey,
49908
- ephemeral_public_key: ephemeral.publicKey
49923
+ ephemeral_public_key: ephemeral.publicKey,
49924
+ epoch: newEpoch
49909
49925
  }
49910
49926
  })
49911
49927
  );
@@ -49919,6 +49935,32 @@ ${messageText}`;
49919
49935
  this.emit("error", err);
49920
49936
  }
49921
49937
  }
49938
+ /**
49939
+ * Send a resync_request for a room conversation if the cooldown has elapsed.
49940
+ * Shared by all room ratchet failure paths to avoid code duplication.
49941
+ */
49942
+ _sendRoomResyncIfCooled(convId, reason, session) {
49943
+ const RESYNC_COOLDOWN_MS = 5 * 60 * 1e3;
49944
+ const lastResync = this._lastResyncRequest.get(convId) ?? 0;
49945
+ if (Date.now() - lastResync > RESYNC_COOLDOWN_MS && this._ws && this._persisted) {
49946
+ this._lastResyncRequest.set(convId, Date.now());
49947
+ this._ws.send(
49948
+ JSON.stringify({
49949
+ event: "resync_request",
49950
+ data: {
49951
+ conversation_id: convId,
49952
+ reason,
49953
+ identity_public_key: this._persisted.identityKeypair.publicKey,
49954
+ ephemeral_public_key: this._persisted.ephemeralKeypair.publicKey,
49955
+ epoch: session?.epoch
49956
+ }
49957
+ })
49958
+ );
49959
+ console.log(
49960
+ `[SecureChannel] Room resync requested for conv ${convId.slice(0, 8)} (${reason})`
49961
+ );
49962
+ }
49963
+ }
49922
49964
  /**
49923
49965
  * Handle an incoming room message. Finds the pairwise conversation
49924
49966
  * for the sender, decrypts, and emits a room_message event.
@@ -50055,12 +50097,14 @@ ${messageText}`;
50055
50097
  `[SecureChannel] Room re-init retry failed for conv ${convId.slice(0, 8)} (msgNum=${incomingMsgNum}):`,
50056
50098
  retryErr
50057
50099
  );
50100
+ this._sendRoomResyncIfCooled(convId, "room_reinit_retry_failed", session);
50058
50101
  return;
50059
50102
  }
50060
50103
  } else {
50061
50104
  console.log(
50062
50105
  `[SecureChannel] Room re-init: skipping message with msgNum=${incomingMsgNum} for conv ${convId.slice(0, 8)} (too far ahead for fresh ratchet)`
50063
50106
  );
50107
+ this._sendRoomResyncIfCooled(convId, "room_message_skip");
50064
50108
  return;
50065
50109
  }
50066
50110
  } catch (reinitErr) {
@@ -50068,6 +50112,7 @@ ${messageText}`;
50068
50112
  `[SecureChannel] Room ratchet re-init failed for conv ${convId.slice(0, 8)}...:`,
50069
50113
  reinitErr
50070
50114
  );
50115
+ this._sendRoomResyncIfCooled(convId, "room_reinit_failed");
50071
50116
  return;
50072
50117
  }
50073
50118
  }