5 Commits
Author SHA1 Message Date
dodox 69ecc7fc67 Dockerfile: call out multi-process limitation explicitly
The reasoning for --workers 1 was already there; adding an upfront
note that this app doesn't support multi-process/multi-replica
deployment as-is, since Login Flow v2's in-flight state is in-process
memory - not just a gunicorn flag choice, a structural constraint
until that state moves somewhere shared.
2026-08-30 16:19:20 +02:00
dodoxandClaude Sonnet 5 d73c739492 Fix Login Flow v2 timing out under Docker (single gunicorn worker)
_pending_flows in app/auth.py is an in-memory dict, not shared across
processes. With --workers 2, /auth/login/start and the follow-up
/auth/login/poll calls could land on different worker processes, which
never see each other's flow_id, so login would intermittently or always
time out. Only surfaced under gunicorn (Docker); the dev server is a
single process so it never hit this.

Pin to a single worker (+ threads for request concurrency) so the shared
in-memory state is actually shared. Fine at this scale - household tool,
already SQLite-backed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011b5fAoenyLtvS54oztB7ib
2026-08-30 16:17:53 +02:00
dodox 0bab9690c6 Add Docker deployment (build- and stack-tested)
- backend/Dockerfile: gunicorn, not the dev server.
- frontend/Dockerfile: multi-stage, nginx serves the static build.
- nginx.conf proxies /api and /auth to the backend so both services
  share one origin - keeps the session cookie simple first-party,
  no SameSite=None/CORS complexity in production.
- docker-compose.yml: bind-mounts ./data/{instance,uploads} (not
  named volumes) so the sqlite db and uploaded photos are visible
  under the project dir; :Z flag for SELinux-enforcing hosts
  (Fedora/RHEL) - without it gunicorn fails with "unable to open
  database file".
- FRONTEND_PORT env var to pick the exposed port.
- .env.example: documents CORS_ORIGIN is moot in the compose setup
  (same-origin via nginx) and that SESSION_COOKIE_SECURE=true needs
  a TLS-terminating reverse proxy in front in real deployment.

Verified: both images build clean, full stack up via docker compose,
login flow starts for real against the actual NC instance through
the nginx proxy, sqlite db persists to the bind mount correctly.
2026-08-30 16:07:00 +02:00
dodox 1b38396a2c Per-user auth via Nextcloud Login Flow v2, Tailwind UI rewrite
- auth.py/auth_routes.py: Login Flow v2 (verified against real NC
  source/docs) - no OAuth2 client registration needed, backend polls
  server-side so no CORS issues. Sessions are hashed-token cookies;
  NC app passwords encrypted at rest (Fernet). Every /api/* route
  guarded by a blueprint-wide before_request, not per-route decorators,
  so future routes are protected by default.
- receipts/groups scoped per owner_nc_user_id; cross-user access 404s.
- nc_client/cospend_client take (username, app_password) per call
  instead of one shared global credential - each user's uploads/shares/
  bills now happen as themselves.
- Frontend: LoginGate component drives the login flow (open NC login
  in a new tab, poll our backend, done).
- Merged the old separate review step into the split screen, redesigned
  with Tailwind (was unstyled/broken), default-excluded-per-item
  splitting with one-click "include everyone" fixed, DD.MM.YYYY date
  field, receipt-icon branding.
- Dropped LLM bounding-box highlighting - unreliable on real receipts,
  plain photo upload instead.
- Only mention who a bill is split with in its title when there's more
  than one bill off the same receipt to disambiguate.
2026-08-30 16:02:29 +02:00
dodox d97aac0e17 Initial scaffold: Flask/SQLite backend, React/Vite PWA frontend
Backend: receipt upload -> LLM vision extraction (OpenAI-compatible,
provider-agnostic), item review/edit, per-group splitting against
Cospend projects/members, highlight+upload via WebDAV, public share
link, bill creation via Cospend's OCS API (verified against real
source, not just doc summaries).

Frontend: capture -> review -> group -> summary flow as an installable
PWA.

install.sh / run.sh (venv + npm, tmux session) instead of Docker, per
the ~/Projects/gain pattern.
2026-08-30 15:02:18 +02:00