Hub Dashboard implementation contract

HUB documentation · CONTRACT.md

← Documentation library · Download Markdown

Production dashboard / HUB API: https://bamboubot.duckdns.org
Set HUB_URL=https://bamboubot.duckdns.org. Local-development commands and loopback bind addresses below are development/operator reference, not the production API origin. Use the existing hosted HUB; you do not need to deploy a new one.

Introduction

Backend: FastAPI + SQLite, lives in backend/. Frontend: React + TypeScript + Vite, lives in frontend/. Production backend serves frontend/dist when built. Default API port 8000. All timestamps UTC ISO 8601 strings. IDs UUID strings.

Admin API

All endpoints under /api. Bearer access token required except POST /auth/login ({password} => {access_token, token_type, expires_in}). Dashboard password supplied via HUB_ADMIN_PASSWORD (required). Tokens expire after 8 hours.

Site: {id,name,url,description,status:'healthy'|'degraded'|'offline',desired_state:'running'|'stopped',last_seen:string|null,created_at,worker_count:number,healthy_workers:number}. Offline if no heartbeat in 60 seconds. Degraded if heartbeat reports degraded or unhealthy workers. Worker: {id,name,status:'running'|'idle'|'error'|'stopped',cpu_percent:number,memory_mb:number,tasks_completed:number,last_seen:string} Error: {id,site_id,site_name,worker_id:string|null,level:'info'|'warning'|'error',message,timestamp} Config: {number_of_workers:number,ai_preset_id:string,has_ai_api_key:boolean,has_captcha_api_key:boolean,updated_at} Proxy: {id,url,username,has_password,created_at} Command: {id,action,status:'pending'|'delivered'|'completed'|'failed',created_at,completed_at:string|null,message:string|null}

Agent API

Bearer site-scoped agent token; no dashboard access. All endpoints /api/agent: - POST /heartbeat {status:'healthy'|'degraded',workers: [{id,name,status,cpu_percent?,memory_mb?,tasks_completed?}]} => {site_id,desired_state,server_time}. Replaces worker snapshot atomically. - GET /config => {number_of_workers,ai_preset_id,ai_api_key,captcha_api_key,proxies:[{id,url,username,password}]} (secrets intentionally available only to its site agent) - POST /errors {worker_id?,level:'info'|'warning'|'error',message} => {id} - GET /commands => Command[] (pending and delivered, for at-least-once delivery; agent must deduplicate by id and acknowledge) - POST /commands/{id}/ack {status:'completed'|'failed',message?} => Command

Agent poll interval 5s; heartbeat 15s; refresh config 30s. Commands are explicit local lifecycle hooks, never arbitrary shell received remotely. HTTPS required publicly. Do not log secret material. Keys encrypted at rest with persistent Fernet key in HUB_ENCRYPTION_KEY. SQLite data in HUB_DATA_DIR (default ./data).

Backup API

Backup schedules, arbitrary-file streaming uploads, cloud routing, and on-demand requests use a separate durable queue from worker lifecycle commands. See backup API contract and operator setup. Cloud credentials are configured through rclone on the hub and are never returned to the dashboard or site agents.

VPS local-file synchronization

GET /api/agent/config additionally returns revision and local_sync_initialized. The authenticated POST /api/agent/local-sync performs revision-checked, one-time import of existing local config/proxies only for a pristine hub site; afterward the hub is authoritative. Admin configuration/proxy changes increment the revision. See full synchronization contract and language starters.

Site statistics

Agent POST /api/agent/statistics accepts {links_sent_successfully:integer,average_messages_per_chat:number|null} absolute whole-site snapshots; administrator GET /api/sites/{id}/statistics returns those metrics plus site_id and updated_at (all metric/timestamp fields null before first report). Repeat submissions replace, never increment. See reporting semantics and validation contract.