AttendiBotAttendiBot

Architecture

System design, data flow, and monorepo layout.

Technical overview of AttendiBot for developers and contributors.

System diagram

Loading diagram…

Monorepo layout

AttendiBot/
├── backend/                 # Rust Discord bot + HTTP API
│   ├── crates/
│   │   ├── bot/             # Main binary (attendibot-bot)
│   │   └── shared/          # Shared types: signing, voice, subscription
│   └── migrations/          # SQL migrations (001–006)
├── web/                     # Next.js marketing + dashboard
│   └── src/
│       ├── app/             # App Router pages
│       ├── components/      # UI components
│       └── lib/             # API client, auth, DAL
└── docs/                    # Documentation

Backend process

Single Rust binary (attendibot-bot) runs concurrently:

TaskDescription
Discord clientSerenity + Poise — slash commands + GUILD_VOICE_STATES events
HTTP serverAxum on port 8080 — health, public verify, authenticated /api/v1
Period reset schedulerArchives signed period snapshots on schedule
Log destination schedulerPosts embeds to Discord text channels

Entry point: backend/crates/bot/src/main.rs

Crate responsibilities

attendibot-bot

  • Discord event handlers and slash commands (commands/)
  • Voice tracking logic (voice/tracker.rs, voice/fairness.rs)
  • HTTP API handlers (http/handlers/, http/router.rs)
  • Service layer (services/)
  • Database repositories (voice/repository.rs)

attendibot-shared

  • Ed25519 signing (signing.rs)
  • Voice types and payloads (voice.rs)
  • Subscription tiers (subscription.rs)
  • Log types (logs.rs)

Voice tracking pipeline

  1. Discord sends voice_state_update event
  2. voice/tracker.rs processes join / leave / move
  3. Fairness rules evaluated (voice/fairness.rs)
  4. On leave: build session payload → sign with Ed25519 → persist to voice_sessions
  5. Update active session and period leaderboard counters

If signing is locked, completed sessions are dropped.

BFF authentication pattern

The web app acts as a Backend-for-Frontend (BFF):

  1. Admin signs in via Auth.js (Discord OAuth, identify guilds scope)
  2. Server-side DAL mints a short-lived HS256 JWT (60s TTL) with user_id and guild_id
  3. JWT sent to Rust API as Authorization: Bearer <token>
  4. Backend validates JWT and verifies Manage Server via Discord REST API

Implementation:

  • Web: web/src/lib/attendibot-api.ts
  • Backend auth: backend/crates/bot/src/http/auth.rs

Public routes (/health, /verify/*) require no authentication.

Database schema

PostgreSQL via SQLx migrations. Key tables:

TablePurpose
guild_signing_keysEncrypted Ed25519 private keys + public keys
guild_voice_settingsTracking mode, reset schedule, fairness, subscription tier
tracked_channelsAllowlist/denylist channel IDs
leaderboard_periodsPeriod metadata and signed snapshots
voice_sessionsCompleted signed voice sessions
active_voice_sessionsIn-progress sessions
log_destinationsDiscord text channel log configs
verified_role_rulesAuto-role attendance thresholds (Pro)
guild_webhooksOutbound webhook settings (Pro)

Subscription enforcement

Tier limits checked in service layer (shared/subscription.rs):

  • Free: 5 archived periods, no export/webhooks/verified roles
  • Pro/Enterprise: unlimited history + premium features

HTTP API layers

LayerRoutesAuth
Public/health, /verify/session/{id}, /verify/period/{guild_id}/{index}None
Authenticated/api/v1/guilds/{guild_id}/*BFF JWT + Manage Server
Webhook/webhooks/attendancex-webhook-secret header (501 not implemented)

See API Reference for full endpoint list.

Web app structure

AreaPathPurpose
Marketingapp/(marketing)/Landing, docs, FAQ, pricing
Dashboardapp/dashboard/Admin UI (server components + client panels)
Authauth.tsAuth.js Discord provider
API clientlib/attendibot-api.tsServer-side Rust API calls

Dashboard pages fetch data server-side via the DAL, which mints internal JWTs per request.

CI pipeline

GitHub Actions (.github/workflows/ci.yml):

  • Backend: cargo fmt, clippy, test (with Postgres service)
  • Web: npm ci, npm run build
  • Docker: build verification
Edit on GitHub

On this page