Commit Graph

4 Commits

Author SHA1 Message Date
Kunthawat Greethong
91beb8c2dc fix: fail fast on missing/short SECRET_KEY; hide ADMIN_PASSWORD from argv
Production correct-credential login returned auth_unavailable 503 because
Flask's SECRET_KEY was unset: wrong-password probes stopped at 401 before
CSRF token issuance, while valid credentials reached _csrf_serializer()
and crashed. App factory now rejects absent/short (<32 char) SECRET_KEY at
startup, and docker_entrypoint.sh fails fast before migration/services.
Bootstrap no longer passes ADMIN_PASSWORD in process arguments; env-only.

Tests: app-factory + entrypoint regression (5 focused passed), full
backend suite 204 passed. Independent review PASS.
2026-09-01 16:28:04 +07:00
Kunthawat Greethong
9b0c0da9cb deploy: auto-bootstrap first super_admin on startup (ADMIN_* env)
With this, a fresh deploy provisions its own first super_admin automatically:
after alembic migrations the entrypoint runs scripts/bootstrap_super_admin.py
when ADMIN_EMAIL + ADMIN_PASSWORD are set (idempotent, never overwrites an
existing password; org name/slug optional). This removes the chicken-egg where
login needs a user but no UI/seed could create the very first one.

Optionally runs only when both env vars are present, so an existing deployment
is unaffected. Verified: bash syntax ok; fresh DB produced org+password+
super_admin; re-run left the existing password unchanged.
2026-09-01 14:31:31 +07:00
Kunthawat Greethong
8953b8f066 fix: ensure Postgres driver installs in image & stop uv re-sync at runtime
Worker crash-loop root cause (from container log):
  sqlalchemy.exc.NoSuchModuleError: Can't load plugin: sqlalchemy.dialects:postgres

Two compounding issues:
1. Dockerfile copied pyproject.toml/uv.lock, ran 'uv sync --frozen',
   then 'COPY backend ./backend' which OVERWROTE those dep files with the
   shipped versions. The two could differ, so every entrypoint 'uv run'
   detected drift and REBUILT/re-synced the project at container runtime
   (seen as repeated 'Building crowdsight-backend...' + 'Uninstalled N /
   Installed 1'), never installing the psycopg Postgres driver that the
   image's own lock actually lists.
2. Result: alembic upgrade head over a postgres DATABASE_URL crashed with
   NoSuchModuleError -> worker crash-loop.

Fix:
- Dockerfile: COPY backend (full source) BEFORE 'uv sync --frozen --no-dev',
  so the installed deps match the shipped pyproject.toml/uv.lock exactly.
- Use 'uv run --frozen' for alembic/gunicorn/worker so nothing re-syncs at
  runtime.
- entrypoint: fail fast with a clear message if DATABASE_URL is postgres
  but psycopg is missing (instead of a confusing alembic traceback).
Verified: entrypoint bash syntax ok; 'uv run --frozen ... import psycopg'
passes; psycopg present in git-tracked uv.lock + pyproject.
2026-08-31 18:56:18 +07:00
Kunthawat Greethong
42208c4f5a fix: run alembic migrations before starting services
Production image had no DB migration step, so a fresh container had an
empty database: the durable worker queried the 'jobs' table before it
existed and crash-looped with sqlalchemy OperationalError 'no such table:
jobs' (supervisor restart loop).

- Add backend/docker_entrypoint.sh: fail-fast if DATABASE_URL is unset,
  run 'alembic upgrade head' (idempotent), then exec supervisord.
- Dockerfile CMD now runs the entrypoint.
- supervisor: fix nodaemon typo, stream stdout/stderr to /dev/stdout +
  /dev/stderr so worker errors are visible in container logs, and give
  worker startsecs/startretries.

Verified locally: entrypoint bash syntax ok, alembic upgrade head
idempotent, jobs + 19 tables created, worker --once exits 0 after migrate
(previously exit 1 with no-such-table). Worker/schema tests 11 passed.
2026-08-31 15:16:59 +07:00