feat: enterprise onboarding setup wizard with subdomain auth#2920
feat: enterprise onboarding setup wizard with subdomain auth#2920adaam2 wants to merge 7 commits into
Conversation
5-step setup flow at /:orgSlug/setup — standalone layout outside app chrome. Steps: connect IdP, directory sync, instrument agents, add MCP sources, confirm traffic.
When served from the setup subdomain (setup.getgram.ai in prod, setup.localhost in dev), the dashboard shows the login page normally then redirects authenticated users to /:orgSlug/setup instead of the normal dashboard. - Add isSetupDomain() util to detect setup.* hostname - AuthProvider redirects to setup wizard on setup subdomain - Login page respects setup subdomain post-auth redirect - Add setup.localhost to Vite allowedHosts and TLS cert SANs - Add zero:hosts mise task for /etc/hosts entry
Route API calls through the Vite proxy on setup.* so session cookies (scoped to the setup origin) are included by the browser — fixes auth.info returning 401 after a successful callback. Server-side: add cookieDomainMiddleware for production (Domain=getgram.ai shares cookies across app.* and setup.*), route IDP callbacks through setup origin in local dev, and allow trusted setup-domain redirects. Client-side: render the setup wizard at "/" on the setup subdomain so the org slug never appears in the URL. AuthProvider early-returns on setup domain to avoid slug-based redirect loops.
There was a problem hiding this comment.
Claude Code Review
This repository is configured for manual code reviews. Comment @claude review to trigger a review and subscribe this PR to future pushes, or @claude review once for a one-time review.
Tip: disable this comment in your organization's Code Review settings.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
- Client: Input onChange provides string, not event — use value directly - Server: remove redundant embedded field selector (staticcheck QF1008)
🚀 Preview Environment (PR #2920)Preview URL: https://pr-2920.dev.getgram.ai
Gram Preview Bot |
The setup subdomain (e.g. setup-pr-2920.dev.getgram.ai) was blocked by the custom domains middleware because it didn't match serverURL.Host and wasn't in the custom domains table. Pass GRAM_SETUP_SITE_URL into the middleware so requests to the setup origin are allowed through.
The nonce-binding cookie was set on setup-pr-*.dev.getgram.ai during login but the callback URL pointed at pr-*.dev.getgram.ai, so the browser never sent the cookie back — causing "nonce not bound to this browser". Extend buildCallbackURL to detect the setup subdomain in all environments (not just local). Also rewrite gram_auth_nonce cookies in cookieDomainMiddleware when GRAM_COOKIE_DOMAIN is set.
isSetupDomain() only matched "setup." prefix, missing preview deploy pattern "setup-pr-*.dev.getgram.ai". Add "setup-" prefix check.
Summary
setup.getgram.ai(dev:setup.localhost)/:orgSlug/setupto/on the setup domain so the org slug never appears in the URLDetails
Setup Wizard (
client/dashboard/src/pages/setup/)/on setup domain,/:orgSlug/setupon main domainAuth Flow (
server/internal/auth/impl.go)cookieDomainMiddlewarerewritesgram_sessioncookies withDomain=attribute in production so cookies are shared acrossapp.*andsetup.*subdomainsbuildCallbackURLdetects setup-domain requests via Referer and routes IDP callbacks through setup origin (local dev only — prod uses shared cookie domain)isTrustedSetupRedirectallows absolute redirects to the setup subdomain origin after auth callbackClient Auth (
client/dashboard/src/)getServerURL()returnswindow.location.originon setup domain so API calls go through the Vite proxy (dev) or same-origin (prod), ensuring session cookies are includedAuthProviderearly-returns on setup domain at/to avoid slug-based redirect loopsLoginCheckrenders login inline on setup domain (no URL redirect)Logincomponent redirects back to setup origin after authConfig (
mise.toml,server/cmd/gram/start.go)GRAM_SETUP_SITE_URL,GRAM_COOKIE_DOMAINGRAM_COOKIE_DOMAINleft commented out for local dev (Chrome rejectsDomain=localhostper RFC 6761)Test plan
setup.localhost:5173— should show login, then setup wizard at/after authlocalhost:5173— normal app flow, unaffected/:orgSlug/setupstill works on main domainDomain=in local dev)