Skip to content

feat: enterprise onboarding setup wizard with subdomain auth#2920

Open
adaam2 wants to merge 7 commits into
mainfrom
adaam2/enterprise-onboarding-setup
Open

feat: enterprise onboarding setup wizard with subdomain auth#2920
adaam2 wants to merge 7 commits into
mainfrom
adaam2/enterprise-onboarding-setup

Conversation

@adaam2
Copy link
Copy Markdown
Member

@adaam2 adaam2 commented May 19, 2026

Summary

  • Adds enterprise onboarding setup wizard served from setup.getgram.ai (dev: setup.localhost)
  • Implements full auth flow for the setup subdomain — session cookies, IDP callbacks, and trusted redirects all scoped correctly
  • Opaquely rewrites /:orgSlug/setup to / on the setup domain so the org slug never appears in the URL

Details

Setup Wizard (client/dashboard/src/pages/setup/)

  • Multi-step onboarding wizard: Connect IDP → Directory Sync → Add Sources → Instrument Agents → Confirm Traffic
  • Self-contained with mock data for initial UI development
  • Rendered at / on setup domain, /:orgSlug/setup on main domain

Auth Flow (server/internal/auth/impl.go)

  • cookieDomainMiddleware rewrites gram_session cookies with Domain= attribute in production so cookies are shared across app.* and setup.* subdomains
  • buildCallbackURL detects setup-domain requests via Referer and routes IDP callbacks through setup origin (local dev only — prod uses shared cookie domain)
  • isTrustedSetupRedirect allows absolute redirects to the setup subdomain origin after auth callback

Client Auth (client/dashboard/src/)

  • getServerURL() returns window.location.origin on setup domain so API calls go through the Vite proxy (dev) or same-origin (prod), ensuring session cookies are included
  • AuthProvider early-returns on setup domain at / to avoid slug-based redirect loops
  • LoginCheck renders login inline on setup domain (no URL redirect)
  • Login component redirects back to setup origin after auth

Config (mise.toml, server/cmd/gram/start.go)

  • New env vars: GRAM_SETUP_SITE_URL, GRAM_COOKIE_DOMAIN
  • GRAM_COOKIE_DOMAIN left commented out for local dev (Chrome rejects Domain=localhost per RFC 6761)

Test plan

  • Navigate to setup.localhost:5173 — should show login, then setup wizard at / after auth
  • Navigate to localhost:5173 — normal app flow, unaffected
  • Verify /:orgSlug/setup still works on main domain
  • Check no redirect loops on setup domain
  • Verify session cookie is set correctly (no Domain= in local dev)

adaam2 added 3 commits May 19, 2026 14:25
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.
@adaam2 adaam2 requested review from a team as code owners May 19, 2026 13:26
Copy link
Copy Markdown

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@vercel
Copy link
Copy Markdown

vercel Bot commented May 19, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
gram-docs-redirect Ready Ready Preview, Comment May 20, 2026 8:34am

Request Review

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 19, 2026

⚠️ No Changeset found

Latest commit: 051e123

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

- Client: Input onChange provides string, not event — use value directly
- Server: remove redundant embedded field selector (staticcheck QF1008)
@github-actions github-actions Bot added the preview Spawn a preview environment label May 19, 2026
@speakeasybot
Copy link
Copy Markdown
Collaborator

speakeasybot commented May 19, 2026

🚀 Preview Environment (PR #2920)

Preview URL: https://pr-2920.dev.getgram.ai

Component Status Details Updated (UTC)
✅ Database Ready Existing database reused 2026-05-20 12:02:09.
✅ Images Available Container images ready 2026-05-20 12:01:49.

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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

preview Spawn a preview environment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants