Discord

ContextBay ships an in-process Discord bot for slash commands, embed-rich responses, and threaded follow-ups against the master. It is off by default and gated by config — no token, no init. Discord is the only chat integration; CB does not support Telegram or Slack.

What CB does with Discord

  • Slash commands for ops actions — list nodes, ack alerts, run an AI prompt, trigger a backup, deploy a stack.
  • Embed-rich responses with consistent colour/footer styling for status, logs, and metric snapshots.
  • Threads for AI conversations — every /ai prompt:... response opens a thread on the reply so back-and-forth stays contained.
  • Auto-poster: optional recurring posts (status dashboard, daily digest) into configured channels.
  • Outbound sanitization: Discord is a public channel. CB scrubs IPs, secrets, and internal URLs before sending — see below.

Enabling the bot

Two steps: turn the module on, and provide a bot token. The module is OFF by default — without a token the Discord package never initialises.

[modules]
discord = true

[discord]
enabled  = true
token    = "<bot-token-from-discord-developer-portal>"
guild_id = "<your-server-id>"

# Optional but strongly recommended:
alerts_channel    = "<channel-id-for-bot-routed-alerts>"
status_channel    = "<channel-id-for-the-status-dashboard>"
admin_role_id     = "<role-id-required-for-destructive-cmds>"
allowed_roles     = ["<role-id-1>","<role-id-2>"]
allowed_users     = ["<user-id-1>"]
sanitize_outbound = true   # Default. Don't turn off in shared servers.
allowed_ip_ranges = ["10.0.0.0/8"]
rate_limit_per_min = 10

Restart the master after editing — the bot registers slash commands on connect. Token rotation: replace [discord].token and restart; the old session disconnects cleanly.

Discord Developer Portal setup

Create a bot at discord.com/developers/applications, then under Bot:

  • Copy the Token into [discord].token.
  • Enable Message Content Intent (CB reads command arguments and message context for some flows).
  • Disable Public Bot unless you actually want anyone to invite the bot.

Under OAuth2 → URL Generator:

  • Scopes: bot + applications.commands.
  • Bot permissions: Send Messages, Embed Links, Attach Files, Read Message History, Use Slash Commands, Create Public Threads, Send Messages in Threads, Manage Threads (for the auto-poster).

Visit the generated URL and authorise the bot into your server — copy the server's id (Developer Mode → right-click server → Copy ID) into [discord].guild_id.

Channels + roles

SettingPurpose
alerts_channelChannel id for bot-routed alert posts (alerts that opt-in to Discord delivery).
status_channelChannel id for the auto-updating status dashboard (one persistent message that the bot edits in place).
allowed_rolesRole ids whitelisted to invoke any slash command. Empty = all roles allowed.
allowed_usersSpecific user ids whitelisted in addition to the role list.
admin_role_idRole required for destructive commands (deploy, exec, container actions).
rate_limit_per_minPer-user slash-command rate limit. Default 10/min — protects against runaway scripts and abuse.

Sanitisation + opsec

Discord is a public channel. Even in a private server, message logs leak via screenshots, third-party Discord clients, audit logs, and Discord itself. CB's position is conservative:

  • sanitize_outbound = true (default) runs every outbound message through a scrubber that redacts IP addresses, common secret patterns (API keys, tokens, passwords), and internal URLs before send. Resulting embeds reference resources by id, not content.
  • allowed_ip_ranges is a CIDR allowlist of IPs that are not redacted. Use this for documenting subnets you're happy to expose (e.g. a public VPN range).
  • CB never sends file contents, secrets, raw config dumps, or full log lines that match the secret patterns. When the bot wants to share data, it sends a link to a CB UI page (which requires auth) instead.

Disable sanitisation only on truly private, single-tenant servers. Even then, prefer reference-not-content responses for anything sensitive.

Slash commands

The bot registers a set of top-level commands at startup. Sub-commands and arguments are documented in-line via Discord's autocomplete — type / in the channel to explore.

CommandWhat it does
/statusMaster + sub-container fleet health snapshot.
/nodesList enrolled nodes with state + last heartbeat.
/alertsList firing alerts (top 20 by severity).
/alert-rulesSub-commands to list and create alert rules.
/alert-manageack / resolve a specific alert by id.
/containersList containers across all endpoints with state + health.
/workflowsList n8n workflows + recent executions.
/tasksList background AI tasks with status + cost.
/logsTail recent logs for a container or service.
/knowledgeWraps /query for the Brain RAG search.
/metricsRun a quick PromQL query and return a snapshot.
/censusShow the latest deep-system census for a node.
/ai prompt:<text>Run a prompt through the tiered AI router; opens a thread for follow-ups.
/brainSub-commands: search, read, update KB pages.
/backlogFilter the planner backlog by project + priority + source.
/issueCRUD on planner issues from Discord.
/planProject planner roll-up for a project.
/sprintSprint operations: list, view, start, complete.
/backup action:<list|run>List backup jobs or trigger one.
/deployTrigger a stack deploy / redeploy (admin role).
/execRun an exec command on a container (admin role).
/securitySub-commands: overview, alerts, events.
/claudeManage Claude sessions from Discord.
/workflowManage n8n workflows: activate, deactivate, run.

Simulating events for development

POST /api/discord/simulate (admin role) injects a synthetic event into the bot's handler. Useful for testing embed formatting, the auto-poster, and rate-limit behaviour without producing real ops alerts. The response includes the rendered Discord payload so you can eyeball it before it goes live.

Pair with POST /api/discord/test (sends an actual test message to a channel) when you need to validate token + permissions end-to-end.

Related