8.1 KiB
WebUI Phase P — P2 Data + Auth Scratchpad
Task ID: WEBUI-P2
Tracking ref: stacked on PR #1143 (feat/webui-p1-vite-skeleton); no separate issue specified in the author brief
Branch: feat/webui-p2-data-auth
Started: 2026-08-09
Role: P2 author worker (must not modify docs/TASKS.md)
Original tasking
Read
/home/jwoltje/briefs/P2-brief.mdand execute it fully in/home/jwoltje/src/stack-p1on branchfeat/webui-p2-data-auth. Run every listed verification gate, commit locally only, and do not push.
Container path mapping:
- Brief:
/home/jwoltje/distrobox-homes/mosaic-dev/briefs/P2-brief.md - Repo:
/home/jwoltje/distrobox-homes/mosaic-dev/src/stack-p1
Objective
Make the P1 Vite SPA authenticate against the Mosaic Gateway by same-origin relative paths, replace guest-route placeholders with real login/register/SSO callback pages, and enforce guest/authenticated route guards without modifying the parallel Next app tree except for unavoidable shared-library import fixes.
Scope and invariants
- All SPA HTTP and Socket.IO access remains origin-relative (
/api/...,/api/auth/...,/chat). - No
NEXT_PUBLIC_*,VITE_*origin setting, or hard-codedhttp://localhost:14242underapps/web/src/. - Verify the Gateway BetterAuth mount path from source before choosing auth-client configuration.
- Delete the legacy static SSO-provider discovery module and test; runtime
/api/sso/providersis canonical. - Preserve the Next build while adding React Router guest pages and session guards.
- Never push; stage named files only; do not touch the modified
.mosaic/orchestrator/session.lock.
Plan
- Inspect P1 SPA structure, shared libraries, legacy Next auth pages/components, Gateway auth mount, and current test setup.
- Add/adjust tests first for relative API behavior, auth-client origin configuration, relative Socket.IO singleton behavior, and all guard session states; run focused tests and capture expected RED failures.
- Implement shared-library relative networking and remove the legacy SSO-provider module/imports.
- Port login, register, and provider callback pages to React Router and wire routes.
- Implement session-aware guest/auth guards and satisfy focused tests.
- Run focused tests, all brief verification gates, invariant searches, and an independent code/security review; remediate and re-run affected gates.
- Update this scratchpad with evidence, stage named files only, and commit locally.
Testing strategy
- TDD is required because this increment changes authentication/session behavior.
- Primary situational evidence: jsdom router guard state tests plus guest-page/auth-flow contract tests already present or added as needed.
- Baseline gates: web tests, Vite build, Next build, typecheck, lint, and root format check exactly as listed in the brief.
- Browser automation is not required by the brief for P2; if used, it will be headless only.
Budget
No explicit user token cap was provided. Working soft cap: 30K tokens, derived from a multi-file auth/frontend increment with tests, dual builds, review, and remediation. Keep implementation within the brief; no unrelated refactors or dependencies.
Progress / evidence
- Loaded mission protocol, active MVP manifest/scratchpad, top-level tasks, PRD, relevant frontend/auth/testing/type/review guides, and matching skills.
- Resolved host paths to the Distrobox-mapped repo and brief.
- Confirmed branch
feat/webui-p2-data-auth, stacked at P1 commit068d0f9b. - Source and Gateway mount inspection complete.
- RED tests observed.
- Implementation complete.
- Independent review complete and findings remediated.
- Verification gates complete.
- Local implementation commit created:
46d68e1f.
Source decisions
- Gateway source mounts BetterAuth at
/api/auth/inapps/gateway/src/auth/auth.controller.ts;packages/auth/src/auth.tsconfiguresbasePath: '/api/auth'. - BetterAuth 1.5.5 defaults its browser client to
/api/authwhenbaseURLis omitted.src/lib/auth-client.tstherefore omitsbaseURL, preserving same-origin behavior without encoding any gateway origin. - The only
src/app/edit is the transitional Next provider redirect page. Deletingsrc/lib/sso-providers.tsrequired that mechanical consumer migration; it now uses the same runtime/api/sso/providersdiscovery and callback sanitizer as the SPA. - GuestGuard pending behavior intentionally follows the approved brief: if no session object exists (including pending), render
<Outlet />; only a present session redirects to/chat. AuthGuard alone renders the specified pending treatment.
TDD evidence
- Initial focused run: 9 expected failures, proving absolute API/auth/socket origins, P1 guest placeholders, and missing guard redirects/loading behavior.
- After implementation: focused contract suite 15/15 passed.
- Security remediation RED:
%2F%0A%2F%2Fevil.examplereachedsignIn.oauth2as an external-normalizing callback target before the fix. - Security remediation GREEN: shared
resolveAuthCallbackURLunit suite 9/9 plus SPA callback regression 1/1 passed; both SPA and Next consumers use the shared helper.
Independent review
- Primary Codex wrappers could not run because
jqis absent; direct Codex fallback then failed authentication with HTTP 401. No review result was claimed from those attempts. - Independent Claude Sonnet code review found no implementation-scope blocker, one pending-state UX suggestion, and one pre-existing
api.tstype-assertion suggestion. The pending-state suggestion was rejected because it contradicts the brief's explicit GuestGuard contract; the API cleanup is outside P2's preserve-contract scope. - Independent Claude Sonnet security review found a high-severity control-character open redirect in the callback prefix check shared by the newly ported SPA logic and transitional Next consumer.
- Remediation centralized WHATWG URL parsing plus exact current-origin comparison in
src/lib/auth-redirect.ts, returns only path/search/hash, and added the RED-first regression above. - Fresh code re-review:
approve, 0 blockers, 0 should-fix findings. - Fresh security re-review:
low, 0 critical/high/medium/low findings.
Documentation checklist disposition
docs/PRD.mdexists and P2 aligns to FR-8 / AC-7 authentication requirements.- No Gateway endpoint, DTO, permission, or API schema changed; existing
/api/auth/*and/api/sso/providerscontracts are consumed unchanged, so OpenAPI/API-index updates are not applicable. - Route paths were already present in the P1 route table; P2 replaces placeholders without changing site-map navigation, so
docs/SITEMAP.mdis unchanged. - User/admin auth behavior is parity with the still-live Next implementation, not a new workflow. Implementation decisions, failure behavior, testing, and migration compatibility are documented here; no publishing action is in scope.
- Documentation remains in-repo; no generated publishing output was created.
Final verification evidence
Run fresh after remediation from the locations required by the brief:
apps/web: pnpm test— PASS:Test Files 9 passed (9);Tests 27 passed (27).apps/web: pnpm build:vite— PASS:✓ 113 modules transformed;✓ built in 565ms.apps/web: pnpm build— PASS:✓ Compiled successfully in 4.6s; 10/10 static pages generated; dynamic provider/project routes retained.apps/web: pnpm typecheck— PASS:tsc --noEmitexited 0.apps/web: pnpm lint— PASS:eslint srcexited 0.- Root
pnpm format:check— PASS:All matched files use Prettier code style!. - Invariant scan — PASS: no
NEXT_PUBLIC_*,VITE_*,GATEWAY_URL,http://localhost:14242, orsso-providersreferences underapps/web/src. git diff --check— PASS.- All six required gates above were repeated successfully after implementation commit
46d68e1f, proving the exact committed source tree.
Risks / blockers
.mosaic/orchestrator/session.lockis modified by the active harness and must remain unstaged.- P2 changes shared
src/lib/modules consumed by both Vite and Next, so the Next build is a required compatibility gate.