# Bot Portal Integration Design Date: 2026-03-06 ## Problem The bot service (crates/bot/) runs as a standalone Axum server at irc.bot with its own auth, templates, and web UI. This creates two problems: 1. **Route conflict**: bot-landing and bot compete for the irc.bot hostname. OCP rejects the bot route (HostAlreadyClaimed), making the bot service unreachable. 2. **Fragmented UX**: Users manage bouncers at my.irc.now but bots at irc.bot. The portal has no bot management at all. ## Walkthrough Findings Issues found walking the live product as a new user: - irc.bot "deploy a bot" CTA links to /signup (404) - irc.bot "log in" nav links to /login (404) - irc.bot footer links (/docs, /status, /marketplace, /faq, /cli) all 404 - Bot service route rejected (HostAlreadyClaimed) - my.irc.now root / returns 404 (no redirect to /dashboard) - Portal has no bot section: no nav item, no dashboard card, no pages The user journey dead-ends at registration. ## Decision Follow the irc.now pattern: irc.bot is a marketing landing page, bot management lives in the my.irc.now portal alongside bouncers, billing, and profile. Architecture: internal API. The bot service keeps its IRC runtime and Lua sandbox, exposes internal REST endpoints. web-api adds bot pages that call the bot service. Same pattern as txt/pics usage APIs. ## Bot Service Internal API The bot crate drops its web UI (templates, auth guard, session middleware, static assets) and becomes a headless service. Internal endpoints (ClusterIP only, no public Route): ``` GET /api/bots?user_id={sub} List user's bots POST /api/bots Create bot (JSON body with user_id) GET /api/bots/{id} Get bot detail PUT /api/bots/{id} Update bot config DELETE /api/bots/{id} Delete bot (stops if running, cascading delete) POST /api/bots/{id}/start Start bot POST /api/bots/{id}/stop Stop bot GET /api/bots/{id}/scripts List scripts POST /api/bots/{id}/scripts Create script GET /api/bots/{id}/scripts/{sid} Get script PUT /api/bots/{id}/scripts/{sid} Update script DELETE /api/bots/{id}/scripts/{sid} Delete script GET /api/bots/{id}/logs Recent logs (200 entries) GET /api/bots/{id}/logs/ws WebSocket live log stream GET /api/bots/{id}/kv List KV pairs PUT /api/bots/{id}/kv/{key} Set KV pair DELETE /api/bots/{id}/kv/{key} Delete KV pair GET /api/usage/{sub} Per-user usage stats (bot count, enabled, running) GET /health Health check GET /metrics Prometheus metrics ``` No auth on internal API. web-api passes user_id, bot service enforces ownership on all endpoints that reference a specific bot. All responses are JSON. Create/update endpoints accept JSON bodies. ## Portal Pages (my.irc.now) Navigation: add "bots" between "bouncers" and "billing" in the nav bar. Dashboard: new "bots" card showing bot count + status summary, linking to /bots. Routes: ``` GET /bots List user's bots GET /bots/create Create bot form POST /bots/create Submit creation GET /bots/{id} Bot detail (config, status, scripts, logs, KV) POST /bots/{id}/update Update config POST /bots/{id}/delete Delete bot POST /bots/{id}/start Start bot POST /bots/{id}/stop Stop bot GET /bots/{id}/scripts/create New script form POST /bots/{id}/scripts/create Submit script GET /bots/{id}/scripts/{sid} Edit script POST /bots/{id}/scripts/{sid}/update Update script POST /bots/{id}/scripts/{sid}/delete Delete script GET /bots/{id}/logs Log viewer (historical + WebSocket) GET /bots/{id}/kv KV browser POST /bots/{id}/kv/set Set KV pair POST /bots/{id}/kv/{key}/delete Delete KV pair ``` Templates follow existing card-based layout with portal.css styles. HTMX for status polling (same pattern as bouncer status fragment). WebSocket for live log streaming (proxied through web-api or direct to bot service). ## Landing Page Fixes (irc.bot) Fix broken links in bot-landing/index.html: - "deploy a bot" / "start free" -> https://my.irc.now/bots/create - "log in" -> https://my.irc.now/auth/login - "+ new bot" (dashboard mock) -> https://my.irc.now/bots/create - "go pro" -> https://my.irc.now/billing?plan=pro - "go team" -> https://my.irc.now/billing?plan=team - Footer docs/marketplace/faq/cli/status -> placeholder anchors or content pages ## Route Cleanup - Delete the bot OCP Route (no longer needed, bot service is internal-only) - Delete the bot WebService CR or update it to remove the host field - Add GET / -> redirect to /dashboard on web-api - Bot service keeps its ClusterIP Service (bot:8080) for internal access - web-api gets BOT_INTERNAL_URL env var (like TXT_INTERNAL_URL, PICS_INTERNAL_URL) ## Environment web-api Deployment gets: ``` BOT_INTERNAL_URL=http://bot.irc-josie-cloud.svc:8080 ``` ## Plan Limits Carried over from existing bot service: - Free: 1 bot, 1 network - Pro: 5 bots, unlimited networks Enforced by bot service on create endpoint (checks user's plan from request body).