BuilderIO / BuilderIO/agent-native
Auth guard: root handoff (rootAuth) serves the sign-in document in the dev gateway but the React marketing route on a Vercel unified deploy
- Dominant language
- TypeScript
- Stars
- 4.8k
- Forks
- 449
- Avg merge
- 10h 24m
- Merged PRs (30d)
- 883
Description
# Auth guard: root handoff (`rootAuth`) serves the sign-in document in the dev gateway but the React marketing route on a Vercel unified deploy
**Version:** `@agent-native/core` 0.176.4, workspace of four apps, `deploy --preset vercel`.
**What happens.** In the dev gateway, `GET //` with `sec-fetch-dest: document` returns the sign-in document titled " — Sign in" carrying `data-agent-native-auth-redirect`, so a signed-in visitor is redirected to `//home`. On the Vercel deployment of the same code, the same request returns the React `_index.tsx` `MarketingHome` page for every app (Chat, Content, Assets templates), CDN cached with `cache-control: public, max-age=600, stale-while-revalidate=604800`, and signed-in users land on the marketing page from every workspace link (org switcher, Dispatch cards, sibling sidebar links all target the app root).
**What we verified.** The guard runs in production: `//sign-in` returns the sign-in document. No static `index.html` intercepts the root (`.vercel/output/static//` has none; routes are `{ src: "/", dest: "/-server" }`). `APP_BASE_PATH` and `VITE_APP_BASE_PATH` are injected per function by `workspace-deploy`. So `p === "/"` should hold and `config.rootAuth` must be resolving false in the function.
**Why (probable).** `rootAuth` is derived from `options.marketing` in `getOnboardingLoginHtmlConfig` and in the "guard already installed" branch of `mountAuthFallbackRoutes`, but from `options.loginHtml` only in the fresh-install branch (`rootAuth: options.rootAuth ?? Boolean(options.loginHtml)`). Plugin mount order differs between the dev server and the bundled function (the code comments note that in production `bootstrapDefaultPlugins` mounts defaults first), so the branch that ignores `marketing` may win there.
**Expected.** `rootAuth` defaults to true whenever `marketing` is provided, in every initialisation path, and the behaviour matches between dev and hosted deploys.
**Workaround used.** `rootAuth: true` passed explicitly in every app's `createAuthPlugin` options (via a shared plugin factory); did not change the Vercel behaviour (see the retest below). Chat's sidebar links to sibling apps now target `//home` directly; the org switcher and Dispatch cards still land on the marketing route.
**Retest with the explicit flag (2026-09-09).** Every app now passes `rootAuth: true` explicitly through a shared `createAuthPlugin` wrapper. On a fresh Vercel preview the result is unchanged: `GET /documents` (signed into Vercel SSO, no app session) returns the React `MarketingHome` route titled "Content - Open Source, agent-friendly Obsidian alternative", while `GET /documents/sign-in` on the same deployment returns the framework sign-in document with the wrapper's branding. So the guard runs and the login document is configured, but the `p === "/"` root branch is never reached for the app root on the unified deploy. Remaining suspects: how the deploy entry rewrites the request path for the `{ src: "/", dest: "/-server" }` route before the guard computes `p`, or an early return ahead of the root branch that only triggers in the bundled function.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with getOnboardingLoginHtmlConfig, mountAuthFallbackRoutes, and bootstrapDefaultPlugins, comparing how rootAuth is derived across initialization paths and plugin mount order. Trace the Vercel route from the / rewrite into the bundled function and inspect the request path before the root branch. Done means the unified deploy serves the sign-in document at each app root for unauthenticated document requests and matches the dev gateway behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- react, typescript
- Domain
- authentication, backend, cloud
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100