From a022da19981c023f36a7f847d593b4d5064976ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Guti=C3=A9rrez?= <35082514+alezmad@users.noreply.github.com> Date: Fri, 10 Apr 2026 02:24:55 +0100 Subject: [PATCH] fix(broker): show mesh slugs in /meshes + /status, remove all-meshes fallback - /meshes and /status now show mesh slug names instead of truncated IDs - meshSlug cached on connect and loaded from DB join on boot - Remove dangerous fallback that connected to ALL meshes in email flow - BridgeRow now includes optional meshSlug field Co-Authored-By: Claude Opus 4.6 (1M context) --- apps/broker/src/index.ts | 14 ++++++-------- apps/broker/src/telegram-bridge.ts | 12 +++++++++--- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/apps/broker/src/index.ts b/apps/broker/src/index.ts index 51fcdd8..9862798 100644 --- a/apps/broker/src/index.ts +++ b/apps/broker/src/index.ts @@ -4124,14 +4124,17 @@ function main(): void { const rows = await db.select({ chatId: telegramBridge.chatId, meshId: telegramBridge.meshId, + meshSlug: mesh.slug, memberId: telegramBridge.memberId, pubkey: telegramBridge.pubkey, secretKey: telegramBridge.secretKey, displayName: telegramBridge.displayName, chatType: telegramBridge.chatType, chatTitle: telegramBridge.chatTitle, - }).from(telegramBridge).where(eq(telegramBridge.active, true)); - return rows.map(r => ({ ...r, chatId: Number(r.chatId) })); + }).from(telegramBridge) + .leftJoin(mesh, eq(telegramBridge.meshId, mesh.id)) + .where(eq(telegramBridge.active, true)); + return rows.map(r => ({ ...r, meshSlug: r.meshSlug ?? undefined, chatId: Number(r.chatId) })); }, async (row) => { await db.insert(telegramBridge).values({ @@ -4170,12 +4173,7 @@ function main(): void { const byUserId = await db.select({ meshId: meshMember.meshId }) .from(meshMember).where(and(eq(meshMember.userId, userId), isNull(meshMember.revokedAt))); for (const m of byUserId) meshIds.add(m.meshId); - // Fallback: if user has no members, check all meshes (owner bootstraps) - if (meshIds.size === 0) { - const allMeshes = await db.select({ id: mesh.id }).from(mesh); - for (const m of allMeshes) meshIds.add(m.id); - log.info("tg-email-connect: no member found, trying all meshes", { email, userId, meshCount: meshIds.size }); - } + // No fallback — user must be an explicit member of a mesh if (meshIds.size === 0) return []; const existingMembers = Array.from(meshIds).map(meshId => ({ meshId })); diff --git a/apps/broker/src/telegram-bridge.ts b/apps/broker/src/telegram-bridge.ts index 1f27a3c..cf8c438 100644 --- a/apps/broker/src/telegram-bridge.ts +++ b/apps/broker/src/telegram-bridge.ts @@ -21,6 +21,7 @@ import { validateTelegramConnectToken } from "./telegram-token"; export interface BridgeRow { chatId: number; meshId: string; + meshSlug?: string; memberId: string; pubkey: string; secretKey: string; @@ -510,6 +511,9 @@ const meshChats = new Map>(); /** meshId → shared WS connection */ const meshConnections = new Map(); +/** meshId → slug (human-readable name) */ +const meshSlugs = new Map(); + // Pending DM picker state: chatId → { message, matches, meshId } const pendingDMs = new Map< number, @@ -809,6 +813,7 @@ function setupBotCommands( ); linkChatMesh(chatId, meshId); + if (meshSlug) meshSlugs.set(meshId, meshSlug); await ctx.reply( `✅ Connected to mesh *${escapeMarkdown(meshSlug ?? meshId.slice(0, 8))}*\\!`, @@ -909,7 +914,7 @@ function setupBotCommands( const lines = meshIds.map((id) => { const conn = meshConnections.get(id); const status = conn?.isConnected() ? "🟢" : "🔴"; - return `${status} \`${id.slice(0, 16)}\``; + return `${status} \`${meshSlugs.get(id) ?? id.slice(0, 12)}\``; }); await ctx.reply(`*Connected meshes:*\n${lines.join("\n")}`, { parse_mode: "Markdown", @@ -1104,7 +1109,7 @@ function setupBotCommands( const lines = meshIds.map((id) => { const conn = meshConnections.get(id); const icon = conn?.isConnected() ? "🟢" : "🔴"; - return `${icon} \`${id.slice(0, 16)}\``; + return `${icon} \`${meshSlugs.get(id) ?? id.slice(0, 12)}\``; }); await ctx.reply( `*Claudemesh Telegram Bridge*\n${lines.join("\n")}`, @@ -1624,9 +1629,10 @@ export async function bootTelegramBridge( ); } - // Populate routing maps for all chats in this mesh + // Populate routing maps and slug cache for all chats in this mesh for (const row of meshRows) { linkChatMesh(row.chatId, meshId); + if (row.meshSlug) meshSlugs.set(meshId, row.meshSlug); } }