Skill: Production Readiness Review
Use this skill to evaluate whether VoxBento is ready for production deployment. Combines security, deployment, and operational readiness checks.
Security Hardening
-
SECRET_KEY≠change-me(raises no error but is insecure). -
API_KEY_ENCRYPTION_KEYis set and ≥32 chars (raisesRuntimeErrorif default). -
ADMIN_PASSWORDis set (empty = admin login disabled — decide deliberately). -
DEBUG=falsein production settings (portal/config.pydebug: bool). - TLS termination configured (Caddy via
Caddyfileor nginx). -
Strict-Transport-Securityheader set by reverse proxy. -
secure=Trueon session cookies when served over HTTPS (reverse proxy may handle this viaX-Forwarded-Proto). -
JVB_AUTH_PASSWORDandJICOFO_AUTH_PASSWORDchanged fromchangeme. - Rate limiting on
/loginand/register(see TD-08 — NOT YET IMPLEMENTED).
Infrastructure
-
DATABASE_URLis PostgreSQL (postgresql+asyncpg://...), not SQLite. - Database is backed up (automated snapshots).
-
portal-datavolume is NOT used (SQLite), or DB is external PostgreSQL. -
MEDIAMTX_WHIP_BASEis the public HTTPS URL, notlocalhost. -
DOCKER_HOST_ADDRESSis set to host's public/LAN IP (required for JVB ICE candidates). - MediaMTX UDP ICE port (8189) is open and reachable from browser clients.
- JVB UDP port (10000) is open for Jitsi media.
Observability
- Portal logs are captured and retained (Docker logging driver or external).
-
/healthzendpoint monitored (returnsmediamtx_ok: true). - Alerting on portal restart or MediaMTX unreachability.
- Transcription worker failure logging monitored (portal logs).
Functional Validation
Run the full test suite:
uv sync --python 3.13 --dev
uv run pytest tests/ -v
node --check static/js/interpreter-booth.js
node --check static/js/whep-listener.js
uv run alembic upgrade head
Manual browser check:
- Admin login + create event + room + booth + invite token.
- Open invite link → booth page → Jitsi iframe loads → mic test works → go live → WHIP connects.
- Open listener page → WHEP connects → audio plays.
- Open second interpreter tab (backup) → coordinator reassigns → first tab becomes backup.
- Transcription enabled → captions appear on listener page.
Known Production Gaps (from TECHNICAL_DEBT_REPORT.md)
| Item | Impact | Status |
|---|---|---|
| In-memory booth state lost on restart | Active sessions dropped on deploy | Not fixed — deploy in low-traffic window |
| No rate limiting on /login | Brute-force risk | Not fixed |
| No CSRF on admin forms | Low risk with lax cookies | Not fixed |
Single shared ADMIN_PASSWORD |
Weaker than per-user admin | Partially mitigated by is_admin user flag |
_created_paths cache not invalidated on MTX restart |
WHIP may fail | Mitigated by PATCH fallback |
Capacity Planning
| Component | Limitation |
|---|---|
| Transcription workers | MAX_TOTAL_WORKERS = 10 — hard limit |
| Booth state | Single-process; no horizontal scaling |
| MediaMTX streams | One per language channel; limited by server resources |
| Jitsi participants | Limited by JVB server capacity |
| DB connections | SQLAlchemy async pool (default settings) |
For events with >10 simultaneous transcribed booths: increase MAX_TOTAL_WORKERS in worker.py or add a settings override.