Skip to content

feat(frontend): optional Google sign-in, my-cases library, delete-all and async render - #23

Merged
upgradedev merged 1 commit into
mainfrom
feat/multitenancy-frontend
Jul 29, 2026
Merged

feat(frontend): optional Google sign-in, my-cases library, delete-all and async render#23
upgradedev merged 1 commit into
mainfrom
feat/multitenancy-frontend

Conversation

@upgradedev

Copy link
Copy Markdown
Owner

Summary

Frontend half of multitenancy, completing the backend already on main (#21, #22):

  • Optional Google sign-in (lib/auth.ts, AuthMenu.tsx) - gated entirely on all four VITE_FIREBASE_* build vars being present. When absent (every build today, including CI), the sign-in control renders nothing and the Firebase SDK is never imported, not even as a lazy chunk - confirmed via a production build with no firebase-* chunk and zero modulepreload tags in dist/index.html.
  • My cases library (MyCases.tsx) - lists the signed-in tenant's cases with links to the case/schematic/illustration artifacts, honest empty and 401-degrade states.
  • Delete all my data - destructive action behind an accessible ConfirmDialog (focus trap, Escape, aria-modal), refreshes to the empty state on success.
  • Async render flow (RenderStep.tsx, queries.ts) - the studio wizard now submits a background job (POST /cases/render/jobs) and polls (GET /cases/render/jobs/{id}) instead of blocking one request for a multi-minute render. Guard rails: ~12 min wall-clock ceiling before an honest "taking longer than expected" state, tolerates up to 3 consecutive transient poll errors without aborting, stops polling on unmount, and handles a job that's already done on the very first poll (offline/demo path).

Auth wiring

lib/api.ts's withAuth() fetches a fresh ID token per request (never caches the raw JWT) and attaches Authorization: Bearer <token> only to the six routes whose backend dependency actually reads the tenant (render, submitRenderJob, getRenderJob, manifest, myLibrary, deleteMyData). A signed-out caller omits the headers key entirely rather than passing {}, so request()'s own default Accept header survives untouched - byte-identical to the pre-auth guest request. extract and previewSchematic never attach auth at all, even when signed in, since their backend routes don't take a tenant parameter.

Test plan

  • npm run typecheck - clean
  • npm run test:coverage - 294 tests passing, 97.81%/91.38%/91.21%/97.81% (stmts/branches/funcs/lines), above the 90/90/85/85 gate
  • npm run build - production build clean, no firebase chunk, no eager modulepreload
  • npm run e2e - 17/17 Playwright tests passing (production build), including render-step a11y and the full journey spec
  • Guest byte-identity verified: no Authorization header sent guest-side, Firebase never fetched
  • git diff --name-only --diff-filter=M -- frontend/src shows exactly the six genuinely-rewired files (App.tsx, Header.tsx, RenderStep.tsx+test, api.ts, queries.ts) - no unrelated test touched

New tests: lib/auth.test.ts (18), lib/api.auth.test.ts (15), lib/queries.auth.test.tsx (6), components/AuthMenu.test.tsx (11), components/ConfirmDialog.test.tsx (16), components/MyCases.test.tsx (15), App.library.test.tsx (2). RenderStep.test.tsx was rewritten (6 tests) because the render flow itself moved from sync to async - the one legitimate exception to "don't touch unrelated tests."

Known dev-mode-only issue (not a regression, does not block this PR)

Under npm run dev with React StrictMode enabled (the default), the render step's auto-kickoff mutation observer occasionally never surfaces its own settle to the component, even though the job succeeds server-side (confirmed via the query cache). This does not reproduce in the production build, the Playwright e2e suite, or the unit tests, and the identical pattern exists in Cinemory's GenerateReel.tsx. Filed as a standalone cross-repo investigation, not scoped to this PR.

🤖 Generated with Claude Code

@upgradedev
upgradedev merged commit 26b0031 into main Jul 29, 2026
11 checks passed
@upgradedev
upgradedev deleted the feat/multitenancy-frontend branch July 29, 2026 17:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant