Command audit

Every command the Discord bot allows, and the gates around it.

One control surface: a Discord bot on a VM with no inbound ports. A single auth check fronts everything — author.id != authorized_user → ignored. Past that gate, the design is "hardened edge, one powerful interior": the everyday commands are tightly constrained; two commands (!code, !page) are deliberately powerful and rest entirely on that one gate.

The full command surface

CommandAllowsRisk
!ping !help !statusLiveness, help, host uptime/disk/mem from /procnone
!run <name>A host built-in from a fixed whitelist (df, free, ps, who…)none
!job <name> · !jobs · !job killRun/list/kill background presetsnone
!cat <path>Read a file under ~/projectsmedium
!logs [id]A job log, or the bot's journalctl taillow
!new project <name>Scaffold a project dir + git commitlow
!report · !reloadBind the daily digest · hot-reload the registry (AST-validated)low
!jot !fitness !fastmail !todoist !accountability !weatherThe domain tools (read; jot/accountability also write)low
!uptime !ingestScheduled-tool control + add/query/feed/polllow
!page <slug> <request>LLM-author a page from your signals + deploy to a public Cloudflare URLHIGH
!code <project> <task>Autonomous Claude Code in a git worktreeHIGHEST

The five gates

What's genuinely strong

The two real powers (and the one gap)

!code — unsandboxed RCE, by design. Runs claude -p <task> --dangerously-skip-permissions as the host user. The git sparse-checkout scopes what's visible, not what the process can do — it can read/write anywhere in $HOME, reach the network, even push. The only boundary is "the authorized user asked for it." Correct for a personal bot; it's the headline for any security review.

!page — public egress. Publishes signal data (emails, tasks, calendar, relocation, fitness) to a guessable *.pages.dev/<slug> URL. The page is LLM-authored, not reviewed; the "no-network script" rule for interactive pages is a prompt instruction, not an enforced CSP.

!cat — name-based secret block. Blocks .env*, .pem, names containing "secret" — but misses creds in non-obvious files (credentials.json, a token literal in a .py). Low likelihood, real if any tool stores a key that way.