Problem
After merging #58 (commit 30de716) with Better Auth + Kysely + Postgres, all /api/* routes return 401 Unauthorized from inside the Docker container — including the health endpoint that has no explicit auth guard.
Observed
$ docker exec -it sin-code-web-ui-v2-webui-1 curl -s http://localhost:3000/api/health
{"error":"Not authenticated"} # status 401
But:
pnpm tsc --noEmit returns 0 errors
.next/standalone includes the kysely adapter chunks
- Env vars are correctly set inside the container (
DATABASE_URL=postgresql://app:...@postgres:5432/sin_webui)
- Postgres is healthy and reachable from the webui container
- Middleware manifest is empty (no middleware intercepting routes)
Root cause hypotheses
- Next.js 16 + kysely-adapter — the adapter may be triggering Next.js's built-in auth interception at build time. The build output had no middleware, but there's some Next.js magic that auto-detects auth configs.
- BETTER_AUTH_URL mismatch — set to
http://localhost:3100 in docker-compose, but the container serves on http://localhost:3000. The middleware may check baseURL matches the request URL and reject otherwise.
- The kysely-adapter getDb() initialisation —
lib/db.ts uses a global memoised Kysely. On first request, the Kysely instance may be initialised in a server-component context that conflicts with Edge runtime.
Acceptance Criteria
Suggested investigation steps
- Try setting
BETTER_AUTH_URL=http://localhost:3000 (not 3100)
- Add
export const dynamic = 'force-dynamic' to the health route
- Check if
next.config.mjs has any authInterrupts or similar settings
- Try the
@better-auth/pg adapter (native, no Kysely)
- Add console.log at the top of
getAuth() to verify it's called
Related
Problem
After merging #58 (commit
30de716) with Better Auth + Kysely + Postgres, all/api/*routes return401 Unauthorizedfrom inside the Docker container — including the health endpoint that has no explicit auth guard.Observed
But:
pnpm tsc --noEmitreturns 0 errors.next/standaloneincludes the kysely adapter chunksDATABASE_URL=postgresql://app:...@postgres:5432/sin_webui)Root cause hypotheses
http://localhost:3100in docker-compose, but the container serves onhttp://localhost:3000. The middleware may checkbaseURLmatches the request URL and reject otherwise.lib/db.tsuses a global memoised Kysely. On first request, the Kysely instance may be initialised in a server-component context that conflicts with Edge runtime.Acceptance Criteria
curl http://localhost:3100/api/healthreturns{"ok":true,"db":"pg"}(not 401)Suggested investigation steps
BETTER_AUTH_URL=http://localhost:3000(not 3100)export const dynamic = 'force-dynamic'to the health routenext.config.mjshas anyauthInterruptsor similar settings@better-auth/pgadapter (native, no Kysely)getAuth()to verify it's calledRelated
30de716)lib/auth/better-auth.ts,lib/db.ts,docker-compose.yml