diff --git a/CHANGELOG.md b/CHANGELOG.md index 167826d..d580db8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Fixed +- Fixed `UndefinedTableError` on first boot: the lifespan startup event now calls `Base.metadata.create_all()` via the async engine before attempting to seed default settings, so all tables are created automatically when the database is empty (e.g., fresh PostgreSQL container with no Alembic migrations run yet). - Fixed frontend API calls being hardcoded to `http://localhost:8000` in production: `NEXT_PUBLIC_API_URL` is baked into the JavaScript bundle at Next.js build time, so it can never be overridden at container runtime. Replaced the `NEXT_PUBLIC_API_URL` mechanism with a Next.js Route Handler proxy at `/api/v1/[...path]` that reads `process.env.BACKEND_URL` at server startup and proxies all `/api/v1/*` requests to the real backend. The frontend Axios client now uses a relative base URL (`/api/v1`), which also eliminates the CORS issue since the browser only ever talks to the same-origin Next.js server. Update `BACKEND_URL=http://backend:8000` in `docker-compose.new.yml` (or your deployment env) to point the proxy at your backend. - Fixed infinite spinning wheel on the home page: `authStore` no longer initialises `isLoading` as `true` unconditionally — it is now `false` when no access token exists in `localStorage`, so unauthenticated users see the landing page immediately instead of an endless spinner - Home page now performs an auth check when a token is present in `localStorage`, redirecting authenticated users to the dashboard and clearing stale tokens on failure diff --git a/backend/app/main.py b/backend/app/main.py index 882a400..cd53368 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -29,6 +29,21 @@ async def lifespan(app: FastAPI) -> AsyncIterator[None]: logger.info(f"Debug mode: {settings.DEBUG}") logger.info("API documentation: /api/docs") + # Ensure all database tables exist (idempotent; safe to run on every startup) + try: + from app.core.database import engine, Base + import app.models.database_models # noqa: F401 - register all ORM models + + async with engine.begin() as conn: + await conn.run_sync(Base.metadata.create_all) + logger.info("Database tables verified/created") + except Exception as exc: + logger.error( + "Could not create database tables: %s — API requests requiring DB will fail", + exc, + exc_info=True, + ) + # Seed default database-backed settings (no-op if they already exist) try: from app.core.database import async_session_maker diff --git a/docs/TODO.md b/docs/TODO.md index bd6decb..d0d3797 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -100,6 +100,7 @@ Comprehensive task breakdown for repository improvements and production readines - [x] Fix Docker build failure: wrap `useSearchParams()` in Suspense boundary in `/auth/callback` page - [x] Fix frontend API URL hardcoded to `localhost:8000` in production: replaced build-time `NEXT_PUBLIC_API_URL` with a runtime Next.js Route Handler proxy (`/api/v1/[...path]`) reading `BACKEND_URL` at server startup - [x] Log `BACKEND_URL` at frontend server startup and include target URL in per-request proxy error messages +- [x] Fix `UndefinedTableError` on first boot: lifespan event now runs `Base.metadata.create_all()` so tables are created automatically when no migrations have been applied ### In Progress 🔨 - [ ] Configure branch protection rules