feat(dashboard): same-origin /api proxy for local dev against any API env#799
Conversation
… env Local dashboard dev calls a same-origin /api path; Vite proxies it to the selected backend, so the browser never makes a cross-origin (CORS-gated) request and no backend has to allow-list localhost. Replaces the prior VITE_BASE_API_URL=dev direct-call approach, which the browser blocked with CORS. - start-dashboard.mjs: API_TARGETS map (local/dev + prod placeholder), --api=<url> for any env, --yes-prod guard for prod - vite.config.mts: /api proxy target read from DASHBOARD_API_PROXY_TARGET - package.json: start:prod (replaces throwaway start:dev-proxy) - apps/CLAUDE.md: fix 'from repository root' -> apps/, document the proxy model
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughThe dashboard startup script is refactored around a centralized Dashboard API Proxy Refactor
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 56bf2c5e30
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/scripts/start-dashboard.mjs (1)
68-87:⚠️ Potential issue | 🟠 Major | ⚡ Quick winValidate required option values for
--target/--env/--apibefore consuming next argv item.
--api/--targetcurrently accept the next token blindly. If the next token is another flag (or missing), parsing becomes inconsistent (e.g.,--api --yes-prodsetsapi="--yes-prod"and skips the real flag handling). Fail fast with a clear error when the value is absent/invalid.Suggested fix
function parseArgs(argv) { let target = 'dev' let api let yesProd = false const forward = [] + const readValue = (flag, index) => { + const value = argv[index + 1] + if (!value || value.startsWith('--')) { + throw new Error(`Missing value for ${flag}`) + } + return value + } for (let i = 0; i < argv.length; i += 1) { const arg = argv[i] @@ if (arg === '--target' || arg === '--env') { - target = argv[i + 1] || target + target = readValue(arg, i) i += 1 continue } @@ if (arg === '--api') { - api = argv[i + 1] + api = readValue(arg, i) i += 1 continue } @@ } return { help: false, target, api, yesProd, forward } }Also applies to: 90-103
🤖 Prompt for 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. In `@apps/scripts/start-dashboard.mjs` around lines 68 - 87, The argument parser in start-dashboard.mjs does not validate that required option values exist before consuming them from argv. When handling flags like --target, --env, and --api that expect a value (via both --flag value and --flag=value syntax), you must check that argv[i + 1] exists and is not another flag (starting with --) before assigning it to the target or api variable. Add validation logic that checks if the next argv item is present and does not start with -- ; if the check fails, throw or log a clear error message indicating which option is missing its required value, then exit early. Apply this validation consistently across all three flag handlers (--target/--env around line 68-75 and --api around line 86-103) to prevent inconsistent parsing behavior when users accidentally omit values or provide flags out of order.
🤖 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 `@apps/scripts/start-dashboard.mjs`:
- Around line 143-156: The prod confirmation guard can be bypassed by providing
both --target=prod and --api together because the entire guard only runs when
!api is true. This means a user can skip the --yes-prod confirmation check by
supplying an API target. Restructure the condition so that the yesProd check
runs whenever selected.prod is true, regardless of whether the api parameter is
provided. Move the yesProd validation outside or separate from the !api
condition so that any prod target invocation requires --yes-prod confirmation to
be explicitly provided, closing this security gap.
---
Outside diff comments:
In `@apps/scripts/start-dashboard.mjs`:
- Around line 68-87: The argument parser in start-dashboard.mjs does not
validate that required option values exist before consuming them from argv. When
handling flags like --target, --env, and --api that expect a value (via both
--flag value and --flag=value syntax), you must check that argv[i + 1] exists
and is not another flag (starting with --) before assigning it to the target or
api variable. Add validation logic that checks if the next argv item is present
and does not start with -- ; if the check fails, throw or log a clear error
message indicating which option is missing its required value, then exit early.
Apply this validation consistently across all three flag handlers
(--target/--env around line 68-75 and --api around line 86-103) to prevent
inconsistent parsing behavior when users accidentally omit values or provide
flags out of order.
🪄 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: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 854f433d-ecdb-450c-b14f-c641815787e9
📒 Files selected for processing (4)
apps/CLAUDE.mdapps/dashboard/vite.config.mtsapps/package.jsonapps/scripts/start-dashboard.mjs
… /api Review fixes (CodeRabbit / codex): - prod guard ran only when !api, so --target=prod --api=<url> bypassed the --yes-prod confirmation. Now any prod target requires it; only the 'unconfigured' check depends on the built-in API_TARGETS map. - proxied targets clear VITE_BASE_API_URL so an inherited/exported value can't build a cross-origin apiUrl and bypass the proxy (re-introducing CORS).
What
Local dashboard dev reaches any API environment through a same-origin Vite
/apiproxy, instead of calling the API cross-origin.Why
Serving the dashboard on
localhost:3000and callinghttps://dev.boxlite.aidirectly is cross-origin. The browser requires the dev API to return a CORSAccess-Control-Allow-Originforlocalhost, which it does not — so requests failed withTypeError: Failed to fetch.Fix is the standard React/Vite approach: the dashboard calls a same-origin
/apipath, and the Vite dev server proxies it to the selected backend server-to-server (no same-origin policy between servers). No backend has to allow-listlocalhost, and no dev/prod infra changes.How
start-dashboard.mjs: singleAPI_TARGETSmap (local,dev,prodplaceholder).--api=<url>proxies to any URL;--yes-prodguards prod (real data + prod Auth0 would have to allow localhost).vite.config.mts:/apiproxy target read fromDASHBOARD_API_PROXY_TARGET(defaults to local API;nx serve dashboardunchanged).package.json:start:prod(replaces a throwawaystart:dev-proxy).apps/CLAUDE.md: corrects "from the repository root" (scripts live inapps/) and documents the proxy model.Commands
npm run start/start:devnpm run start:localnpm run start:prod--yes-prod)npm run start -- --api=<url>npm run start:mockTest
npm run start:dev→ browser fetch/api/configreturns 200 with real dev config (oidc.issuer = auth.dev.boxlite.ai), no CORS error. Logged in to the dev dashboard locally and saw real boxes + the image picker.Summary by CodeRabbit
New Features
/apiproxy routing viaDASHBOARD_API_PROXY_TARGET(with--apioverride support) and improved PROD gating for production runs.Documentation
apps/workspace root and clarified proxy/auth behavior and required local/test setup.Chores
start:prodfor production dashboard startup.