* feat(dev): add LOCAL_DEV_MODE for one-command local dev When LOCAL_DEV_MODE=1, every protected route auto-authenticates as a seeded admin user (default dev@localhost) — no login screen, no Google OAuth config, no magic-link roundtrip. Startup logs a loud warning to make misuse obvious. Also fixes two preexisting bugs in the magic-link flow that surfaced while wiring up the dev fallback: - /auth/email/verify only accepted POST, but the URL embedded in emails is a GET link — clicking from any mail client returned 405. Added a GET variant that consumes the token, sets the auth cookie, and redirects to /dashboard. - Token expiry check compared an offset-aware datetime.now(timezone.utc) against an offset-naive value from DuckDB, raising TypeError on every valid link. Normalize the stored timestamp to UTC before subtracting. Dev-only fallback (scoped strictly to LOCAL_DEV_MODE to keep test and production behavior identical): send-link logs the magic link to stderr and returns it as dev_link in the JSON response when no SMTP is configured. Usage: ./scripts/run-local-dev.sh open http://localhost:8000 # lands on /dashboard as admin * fix(dev): URL-encode magic-link email + avoid /login redirect loop Two issues surfaced by Devin review on PR #32. 1. _build_magic_link interpolated email into the URL unescaped. For addresses with '+' (e.g. user+tag@gmail.com) Starlette's query parser decoded '+' as a space on the GET /verify side, so repo.get_by_email returned None and every click yielded 401 "Invalid link". quote(email, safe='') fixes both the email transport and the dev_link fallback. 2. /login in LOCAL_DEV_MODE unconditionally redirected to /dashboard. If dev-user seeding failed at startup (main.py wraps seed in try/except), /dashboard 401'd, the HTML redirect handler bounced to /login, and the loop repeated until the browser aborted. Now /login checks the dev user actually exists before short-circuiting; otherwise it falls through to the normal login form so the missing seed is visible.
32 lines
1.1 KiB
YAML
32 lines
1.1 KiB
YAML
# Local-dev overlay — auth bypass + no real email delivery required.
|
|
#
|
|
# Usage:
|
|
# docker compose -f docker-compose.yml -f docker-compose.local-dev.yml up
|
|
# or:
|
|
# scripts/run-local-dev.sh
|
|
#
|
|
# Effect:
|
|
# - LOCAL_DEV_MODE=1 makes every protected route auto-login as dev@localhost (role=admin).
|
|
# - Magic-link emails are logged to stderr and returned in the response (no SMTP needed).
|
|
# - Secrets (JWT, session) auto-generate into /data/state on first boot.
|
|
# - No .env file required; nothing else is mandatory.
|
|
#
|
|
# NEVER deploy this overlay to an environment reachable from the internet.
|
|
services:
|
|
app:
|
|
env_file: [] # Drop the project .env requirement — everything dev-relevant is inline below.
|
|
environment:
|
|
- DATA_DIR=/data
|
|
- LOCAL_DEV_MODE=1
|
|
- LOCAL_DEV_USER_EMAIL=dev@localhost
|
|
- SERVER_URL=http://localhost:8000
|
|
- LOG_LEVEL=info
|
|
|
|
# Scheduler also reads LOCAL_DEV flag so its auto-auth uses the same seed user.
|
|
scheduler:
|
|
env_file: []
|
|
environment:
|
|
- DATA_DIR=/data
|
|
- API_URL=http://app:8000
|
|
- LOCAL_DEV_MODE=1
|
|
- SEED_ADMIN_EMAIL=dev@localhost
|