Serve dashboard SPA on shared origin with existing login

Draft
WI
2d ago
+7847-332

Routes /dashboard/* to the standalone static SPA on the existing marketing origin, with /login and authenticated /cloud/api using the existing shared-origin HttpOnly session cookie. No alternate authentication or CORS is introduced.

The optional DASHBOARD_ASSETS binding receives the path with /dashboard stripped and no cookie/authorization headers. With the binding available, the root canonicalizes to /dashboard/ and writes return 405. A missing binding returns an uncached 503. The binding remains disabled; the router README records rollout order and rollback.

The development-only Next rewrite accepts only HTTP loopback origins. Its regression test now uses the normal Vitest TypeScript runner; the former .mjs test was excluded by the CI include patterns.

Validation on 4ca656cf84918be30d9f4107662ae3671f953a95, composed with current main fad47a04537a338ec9fb9650821724b26ab33214:

  • Real root npm ci; both web/router workspace links resolve inside the T7 worktree.
  • npm test: 55 web files / 619 tests, 12 router files / 123 tests, including all 13 proxy cases.
  • npm run typecheck: both workspaces passed.
  • npm run lint: no errors; four existing warnings outside this change.
  • Negative controls: removing the dashboard rewrite makes 10 cases fail; removing origin validation makes 7 fail; enabling it outside development makes 2 fail. Source restored byte-for-byte; all 13 pass.
  • npm run build: compilation, TypeScript and 252 static pages completed, then the existing Next 16.4.0 security check exited 1. This is not a green build. Existing security PR #252 supplies the patched version; no duplicate upgrade is included here.
  • Current-head remote CI is now green: Tests42084249657 and Verify42084249702. Both job logs show actual Checkout 505e748e7f2e6d5ebe276763ee936ff5228724d9; its source parent is4ca656c and its tree exactly matches the locally validated tree. Existing CI also ran its automatic preview42084249645; no manual preview action was taken.

Keep draft until the dependency/build gate, two recorded reviews, and the real shared-origin Google/provider/dashboard journey are settled. Google configuration is available privately; live QA has not run. Local port 3100 belongs to a separate checkout and was left untouched. No manual deployment/preview, binding enablement, or production OAuth change was initiated.

Companions:


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.


Summary by cubic

Routes /dashboard/* to a standalone SPA while keeping /login as the marketing login page and /cloud/api as the Cloud backend, so the browser reuses the existing shared-origin HttpOnly session cookie without new login UI or CORS.

  • /dashboard canonicalizes to /dashboard/, non-GET/HEAD requests return 405, and the optional DASHBOARD_ASSETS binding serves asset paths with /dashboard stripped and cookie/authorization headers removed.
  • With no binding, /dashboard/* returns an uncached 503 instead of falling through to marketing.
  • A development-only Next.js rewrite proxies /dashboard and /dashboard/* to a Vite origin, restricted to HTTP loopback addresses.

Rollout

  • Publish the relay-dashboard static asset Worker, deploy Cloud's /dashboard/ OAuth return support, then enable the DASHBOARD_ASSETS binding.
  • Rollback removes the binding; existing /cloud/dashboard/* routing is unaffected.

Agent Relay sessions

  • codex session 01a18eee · opened via gh pr create · last active 2026-10-31