NIX-OS-73 — per-tenant Telegram bot integration for NIX Cafe. Admin UI to manage bot token + groups, inbound webhook for slash commands (/report, /chatid, /help), and a scheduled daily report push endpoint.
cafe.telegram_groups, cafe.telegram_send_log, plus telegram_bot_token_enc + telegram_webhook_secret columns on cafe.tenant_config.X-Telegram-Bot-Api-Secret-Token against per-tenant secret; 404 on unknown tenant, 401 on bad secret, 200 on valid.X-Cron-Secret matched against CAFE_CRON_SECRET env; 503 without env, 401 wrong, 200 with right./cafe/telegram page renders (307s unauthed — SSR clean)./api/telegram/webhook/* + /api/telegram/cron/* — those routes use their own shared-secret auth, bypass the session cookie check.Migration: migrations/20260421500000_cafe_telegram_integration.ts migrate.js (prod runner entry) Cafe app: lib/telegram/client.ts — getMe, sendMessage, setWebhook, deleteWebhook lib/db/telegram.ts — DAO: tokens, groups CRUD, send log lib/actions/telegram.ts — 6 server actions (save token, CRUD groups, test send, re-register webhook) app/(authed)/telegram/page.tsx — admin page server component app/(authed)/telegram/telegram-client.tsx — admin UI (token, groups, send log) app/api/telegram/webhook/[tenantCode]/route.ts — inbound handler app/api/telegram/cron/daily/route.ts — scheduled push endpoint middleware.ts — bypass session auth for webhook + cron lib/db/schema.ts — drizzle schema additions
Loading…
Loading…
• Cron wiring: CAFE_CRON_SECRET needs to be set on the CF Pages env + a Cloudflare Cron Trigger bound to POST /cafe/api/telegram/cron/daily. Without that binding the endpoint exists but never fires. • NIX_COMMERCE_HOST env: used to build the absolute webhook URL. Default is https://nixtech.app; set explicitly for any env where that's not right. • Telegram MarkdownV2 escaping: sendMessage attempts MarkdownV2 and falls back to plain on error. Watch the send-log for patterns of fallback use — may need to add proper escaping later. • Authenticated UI screenshot: skipped locally (Commerce SSO isn't running on localhost). Gate 2 will capture it on prod.