polygram 0.12.8 → 0.12.10

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.
@@ -190,13 +190,22 @@ function createStore(rawDb, now = () => Date.now()) {
190
190
  return { ok: false, reason: 'wrong-chat' };
191
191
  }
192
192
 
193
+ // Every pairing MUST be chat-scoped. A chat_id=NULL pairing bypasses
194
+ // requireMention in EVERY group the bot is in — the all-chats footgun that
195
+ // let a colleague (Lin) trigger shumabit in the UMI working group without a
196
+ // mention (2026-06-16). Scope to the code's chat if it was issued scoped,
197
+ // else to the chat where it's redeemed. If neither exists, refuse (and DON'T
198
+ // consume the code) rather than create a global pairing.
199
+ const pairChatId = row.chat_id || (chat_id != null ? String(chat_id) : null);
200
+ if (!pairChatId) return { ok: false, reason: 'no-chat-scope' };
201
+
193
202
  const tx = rawDb.transaction(() => {
194
203
  const upd = markCodeUsedStmt.run({ code: norm, user_id: claimer_user_id, ts: now() });
195
204
  if (upd.changes === 0) throw new Error('race: code claimed by another user');
196
205
  insertPairingStmt.run({
197
206
  bot_name: row.bot_name,
198
207
  user_id: claimer_user_id,
199
- chat_id: row.chat_id || null,
208
+ chat_id: pairChatId,
200
209
  granted_ts: now(),
201
210
  granted_by_user_id: row.issued_by_user_id,
202
211
  note: row.note,
@@ -211,7 +220,7 @@ function createStore(rawDb, now = () => Date.now()) {
211
220
  return {
212
221
  ok: true,
213
222
  bot_name: row.bot_name,
214
- chat_id: row.chat_id,
223
+ chat_id: pairChatId,
215
224
  scope: row.scope,
216
225
  note: row.note,
217
226
  };
@@ -286,7 +286,7 @@ function createSlashCommands({
286
286
  chat_id: out.chat_id, note: out.note,
287
287
  });
288
288
  const ttlLabel = args.ttl || '10m';
289
- const chatLabel = out.chat_id ? `chat ${out.chat_id}` : 'any chat';
289
+ const chatLabel = out.chat_id ? `chat ${out.chat_id}` : 'the chat where it is redeemed';
290
290
  await sendReply(
291
291
  `Code: ${out.code}\nexpires: ${ttlLabel}\nscope: ${out.scope} (${chatLabel})${out.note ? `\nnote: ${out.note}` : ''}\n\nShare with user:\n/pair ${out.code}`,
292
292
  );
@@ -341,7 +341,7 @@ function createSlashCommands({
341
341
  ok: res.ok, reason: res.reason,
342
342
  });
343
343
  if (res.ok) {
344
- const chatLabel = res.chat_id ? `chat ${res.chat_id}` : `every chat ${botName} is in`;
344
+ const chatLabel = res.chat_id ? `chat ${res.chat_id}` : 'this chat';
345
345
  await sendReply(`Paired. You can use me in ${chatLabel}.${res.note ? `\n(${res.note})` : ''}`);
346
346
  return true;
347
347
  }
@@ -807,8 +807,12 @@ class CliProcess extends Process {
807
807
  '### Sending FILES (tracks, images, docs) to the user',
808
808
  '',
809
809
  'The `mcp__polygram-bridge__reply` tool takes an optional `files` array of',
810
- 'absolute paths. This is the ONLY way to send a file. Do NOT use Bash,',
811
- 'curl, the Telegram Bot API, or polygram-ipc to send files — those fail.',
810
+ 'absolute paths. This is the ONLY correct way to send a file: reply delivers',
811
+ "it to the user's CURRENT topic/thread automatically. Do NOT use Bash, curl,",
812
+ 'the Telegram Bot API, or polygram-ipc to send files: they do NOT know your',
813
+ 'current thread, so they deliver to the WRONG topic (and skip size/safety',
814
+ 'checks). A raw Bot API call may LOOK like it worked — the upload returns 200 —',
815
+ "but it lands in the wrong topic the user isn't looking at. Always use reply(files).",
812
816
  '',
813
817
  ...(this.attachmentStagingDir ? [
814
818
  `To send a file: COPY it into the staging dir \`${this.attachmentStagingDir}\`,`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "polygram",
3
- "version": "0.12.8",
3
+ "version": "0.12.10",
4
4
  "description": "Telegram daemon for Claude Code that preserves the OpenClaw per-chat session model. Migration path for OpenClaw users moving to Claude Code.",
5
5
  "main": "lib/ipc/client.js",
6
6
  "bin": {