mirror of
https://github.com/Significant-Gravitas/AutoModerate.git
synced 2026-11-09 04:59:33 -10:00
Security / correctness - Privilege escalation: rule/api-key/project-update routes now gate on can_manage_members instead of is_member; plain members could previously rewrite or disable moderation rules and delete API keys. - Project.is_owner() AttributeError on non-admin API-user deletion (route + template) replaced with user_id comparison. - Flask-Limiter on /auth/login, /auth/register, /auth/change-password, and /api/moderate (per API key id). - Remove silent SECRET_KEY fallback: docker-compose fails hard if unset; production config validator refuses to boot without SECRET_KEY and OPENAI_API_KEY. - Require verified email in Google OAuth auto-link flow. - User-supplied regex now evaluated via the regex package with a 1s timeout, closing the ReDoS vector. - Cap batched AI chunk count (max 40) and concurrent workers (200 -> 10). - openai>=2.32 (from 1.55.3 so reasoning_effort kwarg works); add regex, Flask-Limiter, gunicorn, eventlet, psycogreen; drop the stdlib-shadowing pypi asyncio package. Production runtime - New wsgi.py: eventlet.monkey_patch + psycogreen.patch_psycopg so DB queries cooperate with the event loop; sets SOCKETIO_ASYNC_MODE=eventlet for app startup. - Dockerfiles run as non-root app user and CMD gunicorn with --worker-class eventlet. run.py refuses FLASK_CONFIG=production so a misconfigured deploy fails loudly. - cloudbuild.yaml stops managing env vars/secrets on deploy — it was about to clobber secret-backed env vars with plain ones. Runtime config is now owned by the Cloud Run service. SocketIO async-mode fix (was causing full site lockup during API calls) - async_mode picked via SOCKETIO_ASYNC_MODE env var, default "threading". The previous sys.modules auto-detect false-positived because flask_socketio / python-engineio import eventlet on load whenever it is installed, pinning a non-monkey-patched eventlet server in front of blocking stdlib I/O. Real-time dashboard updates - New content_received WebSocket event fires when the API accepts a submission; UI renders a "Processing…" row immediately and updates it in place when moderation_update arrives. - Fix stale updated_at timestamp in moderation_update payloads. Batched AI rule evaluation - Replace the per-rule parallel fan-out (N OpenAI calls) with a single batched call evaluating all AI-prompt rules at once. On a 6-rule default project this drops safe-content cost from 5-12s to ~1-4s. - response_format=json_object + max_completion_tokens=4000 so the model emits strict JSON and stops at the close-brace. - OPENAI_REASONING_EFFORT config: minimal/low/medium/high for gpt-5 / o-series; accepts "none" on gpt-5.4. Works around the gpt-5-nano case where reasoning tokens ate the full output budget and returned empty responses. Client errors - Malformed / non-UTF-8 JSON bodies now return 400 with a clear message about UTF-8 encoding instead of a generic 500. Logging - Single INFO line per moderation: the existing "Content <id>: decision in Zs" summary. - Per-stage timing, websocket scheduling, and batched-AI call details moved to DEBUG so they are available when diagnosing latency without cluttering steady-state logs.
37 lines
1.2 KiB
YAML
37 lines
1.2 KiB
YAML
version: '3.8'
|
|
|
|
services:
|
|
automoderate:
|
|
build:
|
|
context: ..
|
|
dockerfile: docker/Dockerfile
|
|
ports:
|
|
- "6217:6217"
|
|
environment:
|
|
- FLASK_CONFIG=production
|
|
- DATABASE_URL=postgresql://automod_user:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD must be set in .env}@postgres:5432/automoderate
|
|
- SECRET_KEY=${SECRET_KEY:?SECRET_KEY must be set in .env; generate with: python -c 'import secrets; print(secrets.token_urlsafe(64))'}
|
|
- OPENAI_API_KEY=${OPENAI_API_KEY:?OPENAI_API_KEY must be set in .env}
|
|
- ADMIN_EMAIL=${ADMIN_EMAIL:?ADMIN_EMAIL must be set in .env}
|
|
- ADMIN_PASSWORD=${ADMIN_PASSWORD:?ADMIN_PASSWORD must be set in .env}
|
|
depends_on:
|
|
- postgres
|
|
volumes:
|
|
- app_data:/app/instance
|
|
restart: unless-stopped
|
|
|
|
postgres:
|
|
image: postgres:15-alpine
|
|
environment:
|
|
- POSTGRES_DB=automoderate
|
|
- POSTGRES_USER=automod_user
|
|
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD:?POSTGRES_PASSWORD must be set in .env}
|
|
volumes:
|
|
- postgres_data:/var/lib/postgresql/data
|
|
# Postgres is only reachable from the automoderate container on the internal
|
|
# network; do not publish 5432 to the host.
|
|
restart: unless-stopped
|
|
|
|
volumes:
|
|
postgres_data:
|
|
app_data: |