2 Commits

Author SHA1 Message Date
ux-frontend
f6d4e43e4c feat(frontend): wire session to real /auth/me + drop sessionStorage mock
Foundations for the sprint 1 backend wiring. No UI behavior change beyond
the loading state in AppShell, but everything below the wire is now real:

- vite.config.ts adds `server.proxy['/api']` → http://localhost:5000
  (overridable via VITE_DEV_API_TARGET). In prod Caddy routes /api → backend
  on the same origin, so the same `/api/v1/...` paths work without changes.
- src/types/api.ts hand-rolled against the backend Pydantic schemas.
  User / Engagement / EngagementCreate / Login / ApiError / ApiValidationError.
  Should be regenerated from OpenAPI once backend exposes it.
- src/lib/api.ts: thin fetch wrapper. Always credentials:'include' so the
  HttpOnly session cookie travels. 4xx/5xx normalize into ApiClientError
  with typed `body` (ApiError | ApiValidationError | null). No retry loop —
  that's TanStack Query's policy.
- src/session/sessionApi.ts: 1:1 functions for /auth/me, /auth/login,
  /auth/logout. fetchMe maps 401 → null so "unauthenticated" is data, not
  an error.
- src/session/useSession.ts: now a TanStack Query hook against
  SESSION_QUERY_KEY (`['session']`). Returns { user, isLoading, isError,
  signOut, isSigningOut }. Cookie is the source of truth, server is the
  resolver, query is the cache.
- Drop sessionStorage mock layer entirely: src/mocks/session.ts,
  src/session/SessionContext.{tsx,context.ts}, src/routing/Root.tsx all
  removed. No more provider tree — QueryClientProvider in App.tsx is the
  only global state container.
- AppShell renders a "resolving session" state during /auth/me's first
  flight so users with a valid cookie don't see a /login flash on direct
  navigation to a protected URL.
- StatusRail gains an optional `sessionState="resolving"` slot used by
  the loading shell.
- Sidebar's Sign-out wires POST /auth/logout, invalidates the session
  cache, and always navigates to /login regardless of the call outcome
  (a failed logout still expires the local cache so users aren't stuck
  on a broken cookie).
- types/roles.ts loses SessionUser (replaced by api.ts User which is the
  authoritative shape).
2026-05-23 11:12:06 +02:00
ux-frontend
80ca4641a3 feat(frontend): bootstrap Vite + React 19 + TS strict toolchain (F0.1)
- Vite 8 / React 19 / TS 6 strict (noUncheckedIndexedAccess, no baseUrl deprecation)
- Tailwind 4 via @tailwindcss/vite (no PostCSS step)
- TanStack Query 5, react-router-dom 7, Recharts, clsx
- Vitest + Testing Library + jsdom for unit tests
- Playwright skeleton + first smoke spec (login redirect)
- ESLint flat config: typescript-eslint type-checked, react-hooks, react-refresh, prettier
- Prettier config (semi, single quotes, 100-col, lf)
- IBM Plex font @font-face declarations targeting /fonts/ (self-host, no CDN — OPSEC)
2026-05-21 20:30:23 +02:00