# Work Summary — 2026-08-03 23:42 ## Task Add a dev-only auth bypass so local testing doesn't require a real Auth0 login round-trip, per the dev-iteration plan from the previous session (see `work-summary-Claude-2026-08-03-2009.md`). ## Context The only way to get an authenticated session locally was to log into the real Auth0 tenant in a browser and copy the resulting `access_token` JWT cookie into `curl` commands by hand — evidenced by several one-off curl-with-pasted-cookie entries in `.claude/settings.local.json`. Auth is driven entirely by DB state: `Identify` middleware (`server/auth/auth.go`) looks up `access_token` in `oauth_tokens`, joined to `oauth_users` and `accounts` — there's no in-process session logic to fake, just rows to write. Also discovered along the way: the `database_migrations/` `.sql` files are stale relative to the live schema — migration `000016` (still on disk) references a `claims JSONB NOT NULL` column and a `TEXT`-typed `id_token_custom_claims_updated_at`, but the live `oauth_tokens` table has no `claims` column at all and that column is actually `timestamptz`. Something changed the schema by hand at some point without updating the migration files. Didn't touch this — just noted it and built against the real live schema (confirmed via `psql \d oauth_tokens`). ## Changes - `config/config.go`: added optional `DevAuthEnabled bool`, parsed from `DEV_AUTH_ENABLED` (`strconv.ParseBool`; unset = false; invalid value = fail fast). - `domains/authentication/dev.go` (new): `Authenticator.DevLogin(ctx, userID, name)` generates a random `dev_`-prefixed token and writes real `oauth_users`/`oauth_tokens` rows (expiry set 1 year out, specifically to stay clear of the near-expiry auto-refresh path in `server/auth`, since a dev token has no real Auth0 refresh token behind it). Reuses the exact same tables real login writes to, so every downstream code path (identity lookup, account linking/creation, cookie handling) treats it identically to a real session — no special-cased "is this dev" branches anywhere else in the app. - `server/api/auth/router.go`: `Routes` takes a new `devAuthEnabled bool`. When true, logs a loud startup warning and registers `GET /api/auth/dev-login?user_id=...&name=...&target=...` (all params optional; different `user_id` values let you test multiple accounts side by side). - Threaded `devAuthEnabled` through `server/api/apis.go` → `server/server.go` (`NewRouter`) → `main.go` (`runServer`), sourced from `cfg.DevAuthEnabled`. - `.env` / `.env.example`: added `DEV_AUTH_ENABLED` (true in local `.env`, documented in `.env.example`). ## Verification - `go build ./...` clean. - Full manual end-to-end run against the real local Postgres: hit `/api/auth/dev-login?user_id=dev-smoke-test&target=/ui`, confirmed `Set-Cookie` on the response, followed up with `/ui` using that cookie and got a 200 with account-appropriate content (the "no account yet" state, matching what a real first-time login produces). Verified `oauth_users`/`oauth_tokens` rows landed correctly via `psql`, then deleted the test rows. - `go vet ./...` shows only two pre-existing unreachable-code warnings unrelated to this change (`domains/accounts/accounts.go:1472`, `server/sse/publisher.go:141`). ## Follow-ups / not done here - `database_migrations/*.sql` are out of sync with the live DB schema (see Context above) — worth reconciling at some point (either a migration that documents the drift, or regenerating migrations from the live schema) so `go:generate`'d diagrams and any fresh-DB setup aren't misleading. - Next planned step per the dev-iteration plan: a dev script/Makefile to bring up Postgres, run migrations, build Tailwind, and start the server in one command.