Repository navigation
fix(install): configure sandbox application URLs across SDKs - #250
Merged
Merged
Conversation
jasonbarry
changed the base branch from
nicknisi/remove-tui
to
nicknisi/installer-tui
September 24, 2026 23:40
jasonbarry
marked this pull request as ready for review
September 24, 2026 23:46
|
nicknisi
added this pull request to stack #248
September 25, 2026 00:45
nicknisi
approved these changes
Sep 25, 2026
nicknisi
force-pushed
the
nicknisi/installer-tui
branch
from
September 25, 2026 10:00
d201fd5 to
5737030
Compare
nicknisi
force-pushed
the
fix/installer-register-redirect-uris
branch
from
September 25, 2026 10:00
c8a19c5 to
10f7fe9
Compare
The installer machine only called autoConfigureWorkOSEnvironment for TanStack Start and React Router, and returned early for non-JavaScript SDKs. Each integration's run() skips its own call when the machine passes credentials, so SvelteKit, Node, PHP, Laravel, Python, Ruby, Go, .NET, Kotlin and Elixir never registered their redirect URI, CORS origin or homepage URL. Key the check on the integration's requiresApiKey flag (Next.js keeps its post-validation path), and register URLs before the non-JavaScript return. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018EgeNr2FXXVcJ5o165U5Lx
… SDKs React and vanilla JS (Vite) apps declare requiresApiKey: false, so the previous fix still skipped them, though the install usually holds an API key from the staging credentials. A client-only app needs its callback and, above all, its CORS origin registered. Register URLs for every SDK except Next.js whenever an API key is available. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018EgeNr2FXXVcJ5o165U5Lx
Only Next.js set the Sign-out URI and Initiate login URI, through the dashboard GraphQL path. The REST API has no endpoint for either, so other SDKs left both for the user to set by hand. - Run configureAuthkitApplication after the agent for every SDK. For SDKs other than Next.js, a failure leaves the settings for the dashboard instead of failing a finished install. - Save the origin as the Sign-out URI everywhere. Save an Initiate login URI only where the SDK guide fixes the route (signInPath in cli.config.ts); otherwise report it as not set. - React and vanilla JS apps get a /sign-in client route that calls signIn() on load, checked by validation before it is saved. - Pin the agent to that exact route in the prompt. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018EgeNr2FXXVcJ5o165U5Lx
Checked the saved Initiate login and callback paths against the WorkOS docs and SDK READMEs. - React and vanilla JS use /login, as the authkit-react docs do, and must pass WORKOS_REDIRECT_URI as redirectUri: the SDK defaults to the page origin, which the installer never registers. Validation checks both. - Save the documented sign-in routes for React Router (/login), TanStack Start (/api/auth/sign-in), SvelteKit (/sign-in), Node (/login, which also fixes its outro copy) and plain PHP (/login.php). - SvelteKit defaults to Vite's 5173 and /callback, per its README. - Pin the route in the custom Ruby, Go, .NET and Elixir prompts too, so the agent cannot fall back to a path the dashboard does not point at. - Drop the query-parameter pass-through: AuthKit keeps password-reset and invitation details through the redirect. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018EgeNr2FXXVcJ5o165U5Lx
- Build the default redirect URI in one resolveRedirectUri() helper. - Derive client-only SDKs from requiresApiKey instead of a second list. - Scan client source once, in parallel, for both the sign-in route and redirectUri; check only that route after the agent instead of rerunning the full validator. - Report why an initiate login URI was skipped (no fixed route vs. a missing route) and show an unusable callback URL in the checklist. - Give the Python prompt the pinned sign-in route like the other SDKs. - Read the Node outro routes from config. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018EgeNr2FXXVcJ5o165U5Lx
Address review feedback on the client-only validation: - A link to /login no longer counts as the route. Require a route declaration (router path, createFileRoute, or a pathname check) or a static page that calls signIn(). - Check that the prefixed env var the client reads as redirectUri (for example VITE_WORKOS_REDIRECT_URI) is set, and flag an unprefixed one the build tool never exposes. The installer writes only the unprefixed WORKOS_REDIRECT_URI. - Read source files in bounded batches instead of all at once. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018EgeNr2FXXVcJ5o165U5Lx
For client-only apps, the installer now writes VITE_ (or REACT_APP_ for Create React App) WORKOS_CLIENT_ID and WORKOS_REDIRECT_URI itself, instead of asking the agent to copy them and validating the copy. The validator only checks that the client reads the variable the installer wrote. Also share one route check between validation and the save step, build the route pattern from a named list, and read static pages in parallel. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018EgeNr2FXXVcJ5o165U5Lx
A Vite app may read the unprefixed WORKOS_REDIRECT_URI in server-side files such as vite.config.ts. Check Vite browser code through import.meta.env, and Create React App through process.env in src/, so those files no longer fail validation. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018EgeNr2FXXVcJ5o165U5Lx
Use one fast-glob call whose root depends on the bundler, look up the bundler prefix once per validation, and add an envReadIssue spec helper. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018EgeNr2FXXVcJ5o165U5Lx
Server code in a nested folder such as src/server/ may read the unprefixed redirect URI. Exclude server files and folders at any depth; bundler config and scripts stay root-only so browser files in src/ are still checked. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018EgeNr2FXXVcJ5o165U5Lx
…rver paths Every server-path exclusion existed to hide one read: Node code reading process.env.WORKOS_REDIRECT_URI. Exempt that read for Vite, where the same read in browser code throws at page load (no process global), and drop the server/ and scripts/ exclusions. Create React App keeps flagging it, because CRA defines process.env in the browser and the read comes back undefined without an error. The silent cases (import.meta.env with the wrong name, process.env with a browser prefix) are still flagged in any file. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018EgeNr2FXXVcJ5o165U5Lx
The route check only recognised `pathname === '/login'`. The agent followed the prompt and wrote `const path = window.location.pathname; if (path === '/login')`, which failed validation in a real Vite app. Accept a comparison against any identifier, in either order. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018EgeNr2FXXVcJ5o165U5Lx
The agent prompt and the route check had no shared contract, so the agent could write a form the validator did not know. The prompt now names the forms the validator accepts, and the route regex uses String.raw like its declarations. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018EgeNr2FXXVcJ5o165U5Lx
The API-key setup step registers a localhost redirect URI and CORS origin and sets the homepage URL. It ran for any key, and a production key can reach the installer three ways: the --api-key flag or WORKOS_API_KEY, the project's env file, or an active profile of type production (the environment picker lists every profile with a key). With this PR running the step for every SDK, a Go, Rails, or Django install with a live key would add localhost URLs to production and replace its homepage. autoConfigureWorkOSEnvironment now does nothing unless the key starts with sk_test_, and reports the redirect URI and CORS origin as skipped with the reason, so the checklist and summary show them. The check sits in the function, not a caller, because the installer machine, agent-runner, and some integrations' own run() all reach it. It is the same sk_test_ test the Next.js API-key path already uses, so every write path now agrees.
…overwritten The API-key setup step wrote the homepage URL on every sandbox. The homepage is one value per environment, and the REST API can set it but not read it (its GET answers 404), so the write replaced whatever a teammate had set on a shared sandbox. It now follows the rule #249 set for the Next.js API-key path: write it only when the user asked for it (--homepage-url) or the key belongs to the stored unclaimed environment, whose dashboard nobody has had. Otherwise the Homepage URL row says it wasn't changed. With a login, the later dashboard step reads the current homepage and fills an empty one.
The client-only checks scanned every source file in a Vite project, so they could not tell browser code from a server or script beside it. Each fix moved the gap: a /login route in server.js counted as the client route, and exempting server reads hid browser code that read process.env.WORKOS_REDIRECT_URI, which Vite leaves undefined. The route check also counted any `x === '/login'` comparison as a route. The scan now traces what the browser loads: every HTML page and its script srcs (Vite's index.html, a plain app's pages), or Create React App's src/index, then their relative, root and @/ imports. A server, a script or the bundler config is never reached from there, wherever it lives, so traced browser code that reads the unprefixed var is flagged again. A project with no entry keeps the old whole-project scan and its exemption. A comparison counts as the route only when it checks the pathname: `location.pathname === '/login'`, a variable read from it, or `case '/login':` in a switch on it. `path = '/login'` (an assignment) no longer passes as `path="/login"`. These are the forms the agent prompt names.
Revert df2d1f4. The scanner introduced false negatives for inline module imports and custom aliases without reliably proving that a route starts sign-in. Restore the previous validator and leave those review findings open. Keep the production-key guard and homepage protection unchanged.
When authenticated command smoke fails, issue a single GET /connections using the same smoke credential and configured API host through curl instead of the compiled CLI. Discard the body, do not follow redirects, and log only HTTP status, curl exit status, and the request ID. Keep the original failed check red.
Check conventional client roots without an import resolver, excluding server, API, function, script and other workspace paths. Flag Node env reads in Vite client code rather than globally exempting them. Restrict route evidence to supported router forms or actual pathname comparisons and require a sign-in call. Limit reads to 256 files, 256 KiB per file and 4 MiB total; incomplete scans cannot authorize saving a sign-in destination. Add regression cases for the review findings and previously broken inline/custom-alias layouts.
Use the established explicit-or-unclaimed homepage policy in the API-only fallback too. Authorized writes no longer require the unsupported homepage GET to succeed; unknown existing values remain untouched with an honest reason. A missing initiate-login destination leaves setup unverified even when other writes succeed. Add real GET-404 and missing-route regression coverage.
Fail required validation when bounded scans are incomplete. Replace disconnected route/signIn string matches with parsed startup or React mount-effect branches: the matching positive pathname branch must directly call signIn. Ignore comments, strings, click callbacks and unrelated routes. Standardize this conservative source-evidence form in the client prompt; no import graph or bundler resolution. Promote the already-locked Babel parser to a direct dependency and add regression coverage.
Preflight live smoke with one direct read-only API request. Missing credentials or direct HTTP401 report live checks NOT RUN with an explicit warning/summary instead of misclassifying a CLI regression. HTTP200 enables the unchanged authenticated CLI checks, whose failures still fail CI. All other HTTP or transport failures remain fatal. Localhost-only tests cover status handling, non-disclosure, no redirects, and propagation of CLI failures.
Tie JSX and object-route targets to their lexical component definitions and mount effects, including relative default/named exports from the bounded source set. A routed component does not need a redundant pathname guard. Reject unrelated, shadowed, reassigned, click-only and unresolved component bindings. Preserve the bounded scan and existing guarded startup path; no disk-expanding import traversal.
Defer non-Next.js URL writes until post-agent setup chooses the client-ID-matched dashboard application or the API-key-only fallback. Never write early through API key A then later through dashboard environment B. Include CORS in that choice: preserve existing dashboard origins with dry-run/recheck/readback, or add through REST only on the API-key path. An unregistered callback cannot be reported as successful setup. Cover mismatched credentials, late sessions, production refusal, CORS preservation and incomplete results.
This reverts commit 3052708.
This reverts commit eaae2f4.
…uest" This reverts commit 6313223.
Remove the client-route AST analyzer and its direct Babel dependency. Keep generating a public login route using app conventions, but leave the client-only Initiate login URI unchanged until browser verification. Treat scan limits as warnings while preserving callback/env checks and mandatory registration.\n\nRetain sandbox/homepage protections and single-target writes. Derive CORS from the callback origin and report read-back sign-out independently of pending login verification. CI smoke changes are split onto ci/smoke-auth-preflight.
nicknisi
force-pushed
the
fix/installer-register-redirect-uris
branch
from
September 25, 2026 10:09
10f7fe9 to
efe729e
Compare
nicknisi
removed this pull request from stack #248
September 25, 2026 10:10
This was referenced Sep 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The installer skipped callback and CORS registration for most SDKs. Expanding setup also exposed legacy paths that could write localhost settings with a production key, replace an existing homepage, mutate two different environments, or report success after callback registration failed.
Changes
--homepage-urlor a matching stored unclaimed environment./loginand configure the explicit bundler-prefixed callback, but leave Initiate login URI unchanged until browser verification. Users should open/loginwhile signed out, confirm automatic sign-in, and then set that URL in the dashboard./callback, per its README.Scope
Validation
bun install --frozen-lockfilebun run typecheckbun run test: 3,116 passed on the final full-suite run. An earlier run failed the untouched skills-repair sibling-protection test; it passed in isolation and on the full rerun without a code change.bun run lintbun run buildOriginal implementation session: https://claude.ai/code/session_018EgeNr2FXXVcJ5o165U5Lx