feat: Plan 9 PR A — dashboard shell + CP static serve - #26
feat: Plan 9 PR A — dashboard shell + CP static serve#26messagesgoel-blip wants to merge 3 commits into
Conversation
Add Vite/React dashboard with API-key and OIDC PKCE auth scaffolding, X-Tenant-Id client wiring, provider/agent-builder/admin shells, and control-plane SPA static hosting behind /v1 and /healthz. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 46 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (13)
WalkthroughAdded a React/Vite dashboard with API-key and OIDC authentication, protected routes, tenant selection, API helpers, control-plane SPA serving, integration tests, documentation, and CI validation. ChangesDashboard foundation
Authentication and API client
Routes and dashboard pages
Control-plane SPA serving
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Browser
participant LoginPage
participant AuthProvider
participant sessionStorage
participant OIDCProvider
Browser->>LoginPage: submit API key or start OIDC sign-in
LoginPage->>AuthProvider: setToken(token)
AuthProvider->>sessionStorage: store token and tenant ID
LoginPage->>OIDCProvider: redirect with PKCE authorization URL
OIDCProvider-->>LoginPage: return authorization callback
LoginPage->>AuthProvider: navigate authenticated session to /provider
sequenceDiagram
participant Browser
participant ExpressApp
participant mountDashboardSpa
participant DashboardDist
Browser->>ExpressApp: request dashboard path
ExpressApp->>mountDashboardSpa: evaluate route and method
mountDashboardSpa->>DashboardDist: read static asset or index.html
DashboardDist-->>ExpressApp: return dashboard content
ExpressApp-->>Browser: send asset or SPA fallback
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Comment |
PR Summary by QodoScaffold Dashboard SPA and serve built assets from control-plane
AI Description
Diagram
High-Level Assessment
Files changed (31)
|
Code Review by Qodo
Context used✅ Compliance rules (platform):
18 rules 1.
|
There was a problem hiding this comment.
Actionable comments posted: 11
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@control-plane/src/dashboard/spaServe.ts`:
- Around line 18-20: Update isSpaBypassPath in
control-plane/src/dashboard/spaServe.ts (lines 18-20) to match exact /v1 and
/webhooks paths in addition to their slash-prefixed namespaces. Add regression
tests in control-plane/src/dashboard/spaServe.test.ts (lines 69-74) confirming
GET requests to both exact paths bypass the SPA fallback and return JSON API 404
responses.
- Around line 9-13: Update resolveDashboardDistPath to remove the
process.cwd()-based fallback; require the configured
DASHBOARD_DIST_PATH/config.dashboard.distPath and use a repository-stable
dashboard distribution location instead. In the dashboard request routing, treat
exact /v1 and /webhooks paths as bypasses so they do not reach the SPA
index.html fallback, while preserving SPA handling for other paths.
In `@dashboard/package.json`:
- Line 13: The test:e2e script currently falls back to playwright without
declaring that executable. Add `@playwright/test` to dashboard/package.json
devDependencies and update the lockfile so clean installs provide the fallback
runner, or remove the fallback and enforce the documented pw-test prerequisite.
In `@dashboard/README.md`:
- Around line 8-12: Update the development commands in the README to begin from
the canonical repository path /srv/storage/repo/VeriLink/ before entering
control-plane or dashboard. Apply the same absolute-path change to both terminal
instructions so they no longer depend on the caller’s current directory.
In `@dashboard/src/api/client.ts`:
- Around line 20-24: Update the request header construction around the headers
initialization so a body alone never assigns application/json; set Content-Type
only when an explicit JSON option requests it or the caller already supplies a
header, preserving FormData multipart boundaries and URLSearchParams form
encoding. Add regression coverage for both FormData and URLSearchParams
requests.
In `@dashboard/src/auth/oidc.ts`:
- Around line 26-35: Update the authorization URL builder around the OIDC
endpoint construction to use a validated discovery metadata
authorization_endpoint, or a separately validated authorizationEndpoint
configuration, instead of appending /oauth/authorize to opts.issuerUrl. Ensure
the endpoint is resolved before setting the existing OAuth query parameters and
preserve the current PKCE and state values.
In `@dashboard/src/auth/session.ts`:
- Around line 8-10: Replace the token persistence in setStoredToken with a
server-managed HttpOnly, Secure, SameSite session-cookie flow through a
same-origin session or BFF endpoint; remove bearer/API credential storage from
sessionStorage and retain sessionStorage only for non-sensitive UI state.
In `@dashboard/src/pages/AuthCallbackPage.tsx`:
- Around line 16-40: Complete the AuthCallbackPage callback flow after state
validation by reading the authorization code and stored PKCE verifier,
exchanging them through the configured token or control-plane session endpoint,
and passing the resulting bearer token to auth.setToken before navigating to
/provider. Handle missing parameters and exchange failures with terminal
user-facing messages, and remove the stored OIDC state and verifier after any
terminal callback result. Add a test covering a successful OIDC callback.
In `@dashboard/src/styles/index.css`:
- Line 10: Update the stylesheet declarations around the root font-family and
the Fraunces font-family declarations to satisfy the configured Stylelint rules:
move the declaration at line 10 to the permitted position and remove unnecessary
quotes from the Fraunces family names at the referenced declarations, preserving
the existing font stacks and styling behavior.
- Around line 145-171: Update the `.login__form` min-width to use the available
container width rather than a viewport-based `90vw` minimum, ensuring the form
does not exceed `.login`’s padded width on narrow viewports.
In `@dashboard/vite.config.ts`:
- Around line 1-23: Update the Vite config’s defineConfig callback to call
loadEnv before resolving VITE_DEV_PROXY_TARGET, ensuring `.env.local` values are
available during evaluation. Store the loaded proxy target once and reuse it for
both the `/v1` and `/healthz` proxy entries, preserving the existing localhost
fallback.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: e08912c0-dd6f-4852-8888-27f98d2d84c0
⛔ Files ignored due to path filters (1)
dashboard/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (30)
.github/workflows/ci.yml.gitignorecontrol-plane/src/app.tscontrol-plane/src/config.tscontrol-plane/src/dashboard/spaServe.test.tscontrol-plane/src/dashboard/spaServe.tsdashboard/README.mddashboard/index.htmldashboard/package.jsondashboard/src/api/client.test.tsdashboard/src/api/client.tsdashboard/src/auth/AuthProvider.tsxdashboard/src/auth/oidc.tsdashboard/src/auth/session.tsdashboard/src/config.tsdashboard/src/layouts/AppShell.tsxdashboard/src/main.tsxdashboard/src/pages/AdminHomePage.tsxdashboard/src/pages/AgentBuilderHomePage.tsxdashboard/src/pages/AuthCallbackPage.tsxdashboard/src/pages/LoginPage.tsxdashboard/src/pages/ProviderHomePage.tsxdashboard/src/router.tsxdashboard/src/styles/index.cssdashboard/src/test/setup.tsdashboard/src/vite-env.d.tsdashboard/tsconfig.app.jsondashboard/tsconfig.jsondashboard/vite.config.tsdocs/superpowers/plans/HANDOVER.md
Bypass SPA for /v1 and /webhooks roots, validate 68-char API keys, allow disabling SPA via DASHBOARD_DIST_PATH sentinels, and set Content-Type only for string request bodies. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Addressed open Qodo findings:
Re: hardcoded |
Stabilize SPA dist resolution, OIDC discovery + token exchange, in-memory bearer storage, Vite loadEnv proxy, README paths, and narrow-viewport CSS. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Addressed CodeRabbit
@coderabbitai review |
|
✅ Action performedReview finished.
|
Summary
dashboard/(Vite + React + TanStack Query/Router)VITE_AUTH_MODE=apikey|oidc, session token + tenant selector →Authorization+X-Tenant-Iddashboard/dist(orDASHBOARD_DIST_PATH) after API routes without shadowing/v1,/webhooks,/healthzTest plan
cd dashboard && npm run typecheck && npm test && npm run buildcd control-plane && node --test --import tsx src/dashboard/spaServe.test.tsDASHBOARD_DIST_PATH, hit/via CP@coderabbitai review
Summary by CodeRabbit