@profullstack/qryptchat 0.4.2 → 0.4.3

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.
@@ -992,6 +992,20 @@ class QcClient {
992
992
  throw new QcError(data.error_description || data.error || `HTTP ${res.status}`, res.status);
993
993
  return data;
994
994
  }
995
+ async keyCheck() {
996
+ try {
997
+ const me = this.me?.id;
998
+ const mine = this.session.keys?.keys1024?.publicKey;
999
+ if (!me || !mine)
1000
+ return "unknown";
1001
+ const { public_keys: keys = {} } = await this.request("/api/crypto/public-keys", { method: "POST", body: { user_ids: [me] } });
1002
+ if (!keys[me])
1003
+ return "unknown";
1004
+ return keys[me] === mine ? "ok" : "mismatch";
1005
+ } catch {
1006
+ return "unknown";
1007
+ }
1008
+ }
995
1009
  async conversations() {
996
1010
  const { conversations = [] } = await this.request("/api/conversations/load", { method: "POST", body: {} });
997
1011
  return conversations.map((c) => ({ ...c, title: conversationTitle(c, this.me) }));
@@ -1440,7 +1454,11 @@ async function main2(argv, { version = "0.0.0" } = {}) {
1440
1454
  }
1441
1455
  case "login": {
1442
1456
  const { session } = await login({ oob: !!flags.oob });
1443
- return out(`Signed in as @${session.user?.username ?? "unknown"} on ${session.base}. Keys sealed (ChaCha20-Poly1305) in ${sessionPath()}.`);
1457
+ out(`Signed in as @${session.user?.username ?? "unknown"} on ${session.base}. Keys sealed (ChaCha20-Poly1305) in ${sessionPath()}.`);
1458
+ if (await new QcClient(session).keyCheck() === "mismatch") {
1459
+ out("Warning: the browser handed over keys that are not your account's current keys, so messages will not decrypt here. Restore your keys in that browser (Settings > Keys) or approve from the device you chat on, then run qc login again.");
1460
+ }
1461
+ return;
1444
1462
  }
1445
1463
  case "logout":
1446
1464
  clearSession();
package/dist/commands.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  parseArgs2,
4
4
  findChat2,
5
5
  main2
6
- } from "./chunk-7mn96363.js";
6
+ } from "./chunk-8m3j5hfk.js";
7
7
  import"./chunk-vfahhydf.js";
8
8
  export {
9
9
  HELP2 as HELP,
package/dist/mcp.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import"./chunk-vfahhydf.js";
2
2
  import {
3
3
  findChat2
4
- } from "./chunk-7mn96363.js";
4
+ } from "./chunk-8m3j5hfk.js";
5
5
 
6
6
  // src/cli/mcp.js
7
7
  import { createInterface } from "node:readline";
package/dist/tui.js CHANGED
@@ -203,16 +203,17 @@ function saveRecent(list) {
203
203
  writeFileSync(recentFile(), JSON.stringify(list), { mode: 384 });
204
204
  } catch {}
205
205
  }
206
+ var KEY_MISMATCH = "Keys don't match your account, so messages can't decrypt. Run qc login and approve from a browser that can read your chats.";
206
207
  async function runTui(client, { initialChat } = {}) {
207
208
  const state = initialState(client.me);
208
209
  state.recent = loadRecent();
209
210
  const abort = new AbortController;
210
211
  const app = await createApp({ quitKeys: ["ctrl+c"], focusNavigation: false });
211
212
  const redraw = () => app.invalidate();
212
- const note = (msg) => {
213
+ const note = (msg, { sticky = false } = {}) => {
213
214
  state.notice = msg;
214
215
  redraw();
215
- if (msg)
216
+ if (msg && !sticky)
216
217
  setTimeout(() => {
217
218
  if (state.notice === msg) {
218
219
  state.notice = "";
@@ -231,6 +232,7 @@ async function runTui(client, { initialChat } = {}) {
231
232
  note(`Could not load messages: ${err.message}`);
232
233
  }
233
234
  }
235
+ let keysChecked = false;
234
236
  async function loadConversations() {
235
237
  try {
236
238
  const before = state.activeId;
@@ -243,6 +245,11 @@ async function runTui(client, { initialChat } = {}) {
243
245
  state.selected = Math.max(0, state.conversations.findIndex((c) => c.id === before));
244
246
  }
245
247
  redraw();
248
+ if (!keysChecked) {
249
+ keysChecked = true;
250
+ if (await client.keyCheck() === "mismatch")
251
+ note(KEY_MISMATCH, { sticky: true });
252
+ }
246
253
  } catch (err) {
247
254
  state.loading = false;
248
255
  note(err.status === 401 ? "Session ended: run qc login" : `Could not load chats: ${err.message}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@profullstack/qryptchat",
3
- "version": "0.4.2",
3
+ "version": "0.4.3",
4
4
  "description": "qc: qrypt.chat in your terminal. A full-screen end-to-end encrypted chat client (ML-KEM-1024), plus a scriptable CLI and an MCP server.",
5
5
  "type": "module",
6
6
  "bin": {