openmates 0.27.0-alpha.62 → 0.27.0-alpha.64

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.
@@ -205,6 +205,40 @@ function decryptWithMachineKey(encryptedB64) {
205
205
  // src/storage.ts
206
206
  var PROFILE_NAME_PATTERN = /^[a-z0-9][a-z0-9-]{0,63}$/;
207
207
  var TRUSTED_ACCOUNT_FILE = "trusted_account.json";
208
+ var DIRECT_CHAT_ACCOUNT_KEY_FILE = "direct_chat_account_key.json";
209
+ function storedSessionMatches(session, apiUrl) {
210
+ const saved = readJsonFile(join(getStateDir(), "session.json"));
211
+ return Boolean(saved && saved.apiUrl.replace(/\/$/, "") === apiUrl.replace(/\/$/, "") && session.apiUrl.replace(/\/$/, "") === apiUrl.replace(/\/$/, "") && saved.sessionId === session.sessionId && saved.hashedEmail === session.hashedEmail && saved.createdAt === session.createdAt && (typeof saved.pairedSessionExpiresAt !== "number" || saved.pairedSessionExpiresAt > Date.now()));
212
+ }
213
+ function loadCachedDirectChatAccountKey(session, apiUrl) {
214
+ const trustedAccountId = loadTrustedAccountId();
215
+ if (process.env.OPENMATES_ACCOUNT_GUARD === "required" && !trustedAccountId || !storedSessionMatches(session, apiUrl)) return null;
216
+ const cached = readJsonFile(join(getStateDir(), DIRECT_CHAT_ACCOUNT_KEY_FILE));
217
+ if (!cached || typeof cached.accountId !== "string" || !cached.accountId.trim() || cached.accountId !== cached.accountId.trim() || trustedAccountId && cached.accountId !== trustedAccountId || cached.apiUrl !== apiUrl.replace(/\/$/, "") || cached.sessionId !== session.sessionId || cached.hashedEmail !== session.hashedEmail || cached.sessionCreatedAt !== session.createdAt || !cached.record || cached.record.version !== 1 || cached.record.algorithm !== "x25519-xsalsa20poly1305" || typeof cached.record.key_id !== "string" || typeof cached.record.public_key !== "string" || typeof cached.record.encrypted_private_key !== "string") return null;
218
+ return { accountId: cached.accountId, record: cached.record };
219
+ }
220
+ function saveCachedDirectChatAccountKey(session, apiUrl, accountId, record) {
221
+ withSessionWriteLock(() => {
222
+ const trustedAccountId = loadTrustedAccountId();
223
+ if (typeof accountId !== "string" || !accountId.trim() || accountId !== accountId.trim() || process.env.OPENMATES_ACCOUNT_GUARD === "required" && !trustedAccountId || trustedAccountId && trustedAccountId !== accountId || !storedSessionMatches(session, apiUrl)) {
224
+ throw new Error("Direct chat key owner changed before local backup.");
225
+ }
226
+ writeJsonFile(join(ensureStateDir(), DIRECT_CHAT_ACCOUNT_KEY_FILE), {
227
+ accountId,
228
+ apiUrl: apiUrl.replace(/\/$/, ""),
229
+ sessionId: session.sessionId,
230
+ hashedEmail: session.hashedEmail,
231
+ sessionCreatedAt: session.createdAt,
232
+ record: {
233
+ version: record.version,
234
+ algorithm: record.algorithm,
235
+ key_id: record.key_id,
236
+ public_key: record.public_key,
237
+ encrypted_private_key: record.encrypted_private_key
238
+ }
239
+ });
240
+ });
241
+ }
208
242
  function resolveStateDir(options = {}) {
209
243
  const homeDir = options.homeDir ?? homedir2();
210
244
  const stateDir = options.stateDir ?? process.env.OPENMATES_STATE_DIR?.trim();
@@ -304,6 +338,9 @@ function saveSession(session, options = {}) {
304
338
  withSessionWriteLock(() => {
305
339
  const path = join(ensureStateDir(), "session.json");
306
340
  const current = readJsonFile(path);
341
+ if (current && options.replace && (current.sessionId !== session.sessionId || current.hashedEmail !== session.hashedEmail || current.apiUrl !== session.apiUrl || current.createdAt !== session.createdAt)) {
342
+ rmSync(join(getStateDir(), DIRECT_CHAT_ACCOUNT_KEY_FILE), { force: true });
343
+ }
307
344
  if (!current && options.expectedRefreshToken !== void 0) {
308
345
  throw new Error("Login session was removed. Retry using the current profile.");
309
346
  }
@@ -477,6 +514,7 @@ function clearSessionLocked() {
477
514
  }
478
515
  rmSync(join(getStateDir(), "tui_workspace_cache.json"), { force: true });
479
516
  rmSync(join(getStateDir(), "chat_model_preferences.json"), { force: true });
517
+ rmSync(join(getStateDir(), DIRECT_CHAT_ACCOUNT_KEY_FILE), { force: true });
480
518
  if (cleanupError) throw cleanupError;
481
519
  }
482
520
  function purgeLocalPrivateData() {
@@ -490,6 +528,7 @@ function purgeLocalPrivateData() {
490
528
  } catch (error) {
491
529
  cleanupError = error;
492
530
  }
531
+ rmSync(join(stateDir, DIRECT_CHAT_ACCOUNT_KEY_FILE), { force: true });
493
532
  try {
494
533
  purgeLocalTeamKeys(hashedEmail);
495
534
  } catch (error) {
@@ -1186,6 +1225,8 @@ async function runPrivacyDaemon() {
1186
1225
  }
1187
1226
 
1188
1227
  export {
1228
+ loadCachedDirectChatAccountKey,
1229
+ saveCachedDirectChatAccountKey,
1189
1230
  resolveStateDir,
1190
1231
  loadAnonymousId,
1191
1232
  saveAnonymousId,