Commit Graph

3 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
fb9275818e fix: normalize bare postgres:// to postgresql+psycopg:// (worker crash-loop)
Root cause (confirmed on local): even with psycopg installed, SQLAlchemy
raises:
  NoSuchModuleError: Can't load plugin: sqlalchemy.dialects:postgres
when DATABASE_URL uses the bare 'postgres://' scheme, because SQLAlchemy
only resolves 'postgresql+driver://'. The deploy's DATABASE_URL was
'postgres://...', so alembic upgrade head (run by the entrypoint before
starting services) crashed and the worker crash-looped in supervisor.

Fix:
- create_database_engine now normalizes 'postgres://' and legacy
  'postgres+pq://' to 'postgresql+psycopg://' so a bare postgres scheme
  works as long as psycopg is installed.
- Dockerfile build step now verifies psycopg imports after 'uv sync'
  (fails the build loudly instead of a runtime crash-loop).
- Tests: 4 for URL normalization; backend suite now 201 passed.
2026-08-31 20:13:16 +07:00
Kunthawat Greethong
8b84378fe1 feat: SaaS foundation for CrowdSight
Elevate MiroFish/CrowdSight from single-container dev to a SaaS foundation:

- Local memory backend (Zep-compatible): memory services/models, local graph
  builder + updater, AgentActivity seam, import-boundary isolation; Zep stays
  default, local is opt-in behind MEMORY_BACKEND. Semantic parity not yet proven.
- Durable product persistence: projects/simulations/reports schema (migration
  0007) + tenant/owner-scoped ProductRepository + dual-write + scoped_project
  read-first + ArtifactStore abstraction; durable JobQueue + worker.py.
- SaaS hardening: durable RateLimiter (wired to login), UsageService (LLM
  accounting), redacted AuditService, idempotency, CORS allowlist, safe API
  errors, single-use PasswordResetService + endpoints (covers invite-pending).
- Exactly 3 roles (super_admin/admin/user) with tenant authz policy.
- Admin UI: GET/POST/PATCH /api/admin/users + GET/PUT /api/admin/settings
  (super-admin only, encrypted/masked); AdminView.vue + SettingsView.vue with
  admin/super-admin route guards, th/en i18n.
- Production deploy topology: multi-stage Dockerfile (frontend build + gunicorn
  wsgi + nginx SPA-proxy + supervisord worker), backend/wsgi.py, gunicorn dep.

Backend 197 passed; frontend 10 tests + build green. ruff unavailable (gap).
No commit of credentials; secrets handled via env/.env.example.
Deferred: Zep semantic A/B parity, object storage cutover, mobile QA, EasyPanel
container build of deploy topology.
2026-08-31 13:05:21 +07:00