Skip to content

feat: enterprise onboarding wizard#3079

Open
adaam2 wants to merge 10 commits into
mainfrom
feat/enterprise-onboarding
Open

feat: enterprise onboarding wizard#3079
adaam2 wants to merge 10 commits into
mainfrom
feat/enterprise-onboarding

Conversation

@adaam2
Copy link
Copy Markdown
Member

@adaam2 adaam2 commented May 28, 2026

Summary

  • Multi-step enterprise setup wizard at /:orgSlug/setup with stepper navigation
  • SSO connection: Provider selection grid (Okta, Azure AD, Google, etc.) with WorkOS admin portal redirect flow
  • Directory sync: User/role confirmation step (skippable)
  • Agent platform instrumentation: Per-platform setup wizards for Claude Code, OpenAI Codex, and Cursor — each with step-by-step instructions and copyable code blocks
  • MCP sources: Configure 1st and 3rd party tool sources
  • Traffic confirmation: Verify connectivity and compliance

Backend

  • GetOnboardingStatus endpoint returning SSO/DSYNC configuration state
  • GenerateWorkOSAdminPortalLink expanded with intent options (SSO provider type, domain verification, DSYNC)
  • WorkOS connection listing support in dev-idp mock

Dashboard

  • Platform logos (Claude, OpenAI, Cursor) added to public/icons/platforms/
  • Moonshine Badge components for platform setup status
  • Step gating: SSO must be configured before advancing past step 1

Test plan

  • Navigate to /:orgSlug/setup and verify wizard renders
  • Select an SSO provider and verify WorkOS portal redirect
  • Expand each agent platform card and walk through setup steps
  • Verify copy-to-clipboard works on code blocks
  • Verify step navigation (back/forward/skip) works correctly
  • Confirm completed platforms show logo + success badge

Summary by cubic

Adds a full-screen enterprise onboarding wizard at /:orgSlug/setup to guide orgs through SSO, directory sync, agent setup, and traffic verification. Adds a super‑admin Onboarding tab to email enterprise admins a setup link to the wizard.

  • New Features

    • Multi-step wizard with stepper rendered outside the main org layout; steps are skippable via ?step=<slug>.
    • SSO: Provider grid with WorkOS Admin Portal redirect; adds intentOptions (SSO providerType, domain verification), successUrl/returnUrl, and itContactEmails.
    • Directory Sync: Launch dsync from the portal and confirm users/roles (skippable).
    • Agent instrumentation: Drawer-based per‑platform setup (Claude, Codex, Cursor) with eligibility gating; auto-issues a hooks‑scoped API key and injects it into code; Shiki highlighting; platform badges/icons.
    • Traffic verification: Live tail feed polling GET /rpc/organizations.verifyOnboardingHooksSetup every 2s; React Query hooks in @gram/client. Seed demo data via mise run seed:hook-events.
    • Backend + SDK: GET /rpc/organizations.getOnboardingStatus with React Query support in @gram/client; WorkOS dev mock lists connections/directories; OpenAPI/SDK regenerated.
    • Super‑admin Onboarding tab: POST /rpc/organizations.sendEnterpriseAdminOnboardingEmail to dispatch the Loops email linking to /:orgSlug/setup; includes React Query mutation in @gram/client.
  • Bug Fixes

    • Traffic check banner uses AlertTriangle for attention states.
    • Removed unused local SSO connection state; flow advances via WorkOS success_url callback.
    • Validate return_url and success_url as URIs; avoid auth skeleton flash on /setup.

Written for commit 4de0405. Summary will update on new commits.

Review in cubic

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 28, 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 29, 2026 2:05pm

Request Review

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 28, 2026

🦋 Changeset detected

Latest commit: 4de0405

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
server Minor
dashboard Minor

Not sure what this means? Click here to learn what changesets are.

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

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

4 issues found across 63 files

Partial review: This PR has more than 50 files, so cubic reviewed the highest-priority files first. During the trial, paid plans get a higher file limit.
You can try an ultrareview to bypass the file limit, comment @cubic-dev-ai ultrareview. Learn more.

Fix all with cubic | Re-trigger cubic

Comment thread client/dashboard/src/pages/setup/components/steps/connect-idp-step.tsx Outdated
Comment thread client/dashboard/src/pages/setup/components/steps/confirm-traffic-step.tsx Outdated
Comment thread client/dashboard/src/pages/setup/components/onboarding-wizard.tsx Outdated
Comment thread server/design/organizations/design.go Outdated
adaam2 added 3 commits May 29, 2026 11:37
…m setup

Add multi-step setup wizard for enterprise organizations:
- SSO connection via WorkOS admin portal with provider selection
- Directory sync step for user/role confirmation
- Agent platform instrumentation with per-platform setup wizards (Claude, Codex, Cursor)
- MCP sources configuration step
- Traffic confirmation step

Backend: onboarding status endpoint, WorkOS admin portal link generation
with expanded intent options (SSO provider type, domain verification, DSYNC).
URL now shows ?step=connect-idp instead of ?step=1. All steps are
accessible without requiring SSO completion first — users can skip
and return later. Server callback also emits slug-based redirects.
@blacksmith-sh

This comment has been minimized.

…alidate redirect URLs

- confirm-traffic-step: render AlertTriangle on attention-required banner instead of Check
- connect-idp-step: remove unreachable isConnected state; flow advances via WorkOS success_url -> server callback redirect, not local state
- organizations design: add Format(FormatURI) to return_url and success_url
adaam2 added 5 commits May 29, 2026 12:43
…y gating, Claude managed-settings flow

- Move per-platform setup steps into a Sheet drawer with horizontal wipe animation between steps
- Add eligibility step type: yes/no gate with blocked-state when ineligible (Claude requires Teams/Enterprise plan)
- Auto-issue Gram API key (scope: hooks) on drawer open for platforms with requiresApiKey steps; substitute {{GRAM_API_KEY}} in code blocks
- Append timestamp to key name to avoid (organization_id, name) unique-index conflicts on rerun
- Add helpLink step field rendering moonshine Link with external-link icon
- Add screenshot step field with figcaption legend
- Shiki JSON syntax highlighting with wrap and 400px max-height in code blocks
- Provider search box on connect-idp step
- Remove add-sources wizard step entirely
- Rename mock-data.ts -> setup-data.ts; drop dead MOCK_DIRECTORY_USERS and unused McpSource type
GET /rpc/organizations.verifyOnboardingHooksSetup returns recent ClickHouse hook events for the active organization's projects. The onboarding wizard's confirm-traffic step polls this every 2s with a moving since_unix_nano cursor to verify Claude Code / Cursor / Codex instrumentation is delivering events to Gram.

- New OnboardingHookEvent + VerifyOnboardingHooksSetupResult types
- HookEventReader interface decouples the handler from the telemetry repo
- ListRecentHookEventsForOnboarding + CountRecentHookEventsForOnboarding ClickHouse queries against telemetry_logs
- Add ListRoles to MockOrganizationProvider to satisfy interface (rebase leftover)
- Dashboard confirm-traffic-step now consumes the real polling hook; drop MOCK_TRAFFIC_METRICS + TrafficMetric type
…g feed

- Add `mise run seed:hook-events` (calls server/cmd/seedhooks) to insert randomized bursts of synthetic hook events into local ClickHouse for demoing the confirm-traffic step. Weighted source mix, jittered cadence (rapid-fire / lull / normal), uniformly 1-3 events per burst.
- Rewrite the activity feed as a marquee-style sliding window: absolute-positioned rows translate by index * ROW_HEIGHT, AnimatePresence handles enter (from above) and exit (off the bottom). Polled events queue client-side and play back one per 400ms so the slide reads cleanly.
- Drop status dots from each row; add provider icons (Claude/Cursor/Codex) inline.
- Brighter "Live" indicator (emerald with ping ring).
- Remove now-unused MOCK_TRAFFIC_METRICS, TrafficMetric type, and "events received" banner.
- Rename continue button "Go to Dashboard" -> "Complete setup"
- Center empty-state vertically + horizontally; add spinner above the message
- "Live" -> "Live tail" on activity header
- Seed: swap to speakeasy.com user pool (adam, quinn, sagar, brian, daniel, thomas)
- Seed: 1-3 events per burst (uniform), faster default interval (800ms), wider cadence randomness
@github-actions
Copy link
Copy Markdown
Contributor

atlas migrate lint on server/migrations

Status Step Result
No migration files detected  
ERD and visual diff generated View Visualization
No issues found View Report
Read the full linting report on Atlas Cloud

@github-actions
Copy link
Copy Markdown
Contributor

atlas migrate lint on server/clickhouse/migrations

Status Step Result
No migration files detected  
ERD and visual diff generated View Visualization
No issues found View Report
Read the full linting report on Atlas Cloud

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

4 issues found across 50 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="client/dashboard/src/pages/setup/components/steps/instrument-agents-step.tsx">

<violation number="1" location="client/dashboard/src/pages/setup/components/steps/instrument-agents-step.tsx:354">
P2: When the API key is still loading or has errored, the code block displays the raw `{{GRAM_API_KEY}}` placeholder and the copy button remains active. Users can copy non-functional configuration. Consider hiding the code block or disabling copy while `isPending` is true or `error` is set for steps that require a key.</violation>
</file>

<file name="server/cmd/seedhooks/main.go">

<violation number="1" location="server/cmd/seedhooks/main.go:149">
P2: The `-burst-size` flag is advertised in usage docs and parsed, but silently ignored — the actual size is always `1 + rng.IntN(3)`. Either use the flag value (e.g., as a max for the random range) or remove the flag and update the usage comment to avoid misleading callers.</violation>
</file>

<file name="client/dashboard/src/pages/setup/setup-data.ts">

<violation number="1" location="client/dashboard/src/pages/setup/setup-data.ts:97">
P2: Codex setup copies a fake API key string because this step is not marked for API-key substitution.</violation>

<violation number="2" location="client/dashboard/src/pages/setup/setup-data.ts:125">
P2: Cursor setup also uses a hard-coded sample key without enabling API-key substitution.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Fix all with cubic | Re-trigger cubic

Comment on lines +354 to +356
step.code && needsKey && platformKey
? step.code.replaceAll(API_KEY_PLACEHOLDER, platformKey)
: step.code;
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot May 29, 2026

Choose a reason for hiding this comment

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

P2: When the API key is still loading or has errored, the code block displays the raw {{GRAM_API_KEY}} placeholder and the copy button remains active. Users can copy non-functional configuration. Consider hiding the code block or disabling copy while isPending is true or error is set for steps that require a key.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At client/dashboard/src/pages/setup/components/steps/instrument-agents-step.tsx, line 354:

<comment>When the API key is still loading or has errored, the code block displays the raw `{{GRAM_API_KEY}}` placeholder and the copy button remains active. Users can copy non-functional configuration. Consider hiding the code block or disabling copy while `isPending` is true or `error` is set for steps that require a key.</comment>

<file context>
@@ -94,11 +237,301 @@ export function InstrumentAgentsStep({
+              const error = apiKeyError[activePlatform.id];
+              const needsKey = !!step.requiresApiKey;
+              const displayCode =
+                step.code && needsKey && platformKey
+                  ? step.code.replaceAll(API_KEY_PLACEHOLDER, platformKey)
+                  : step.code;
</file context>
Suggested change
step.code && needsKey && platformKey
? step.code.replaceAll(API_KEY_PLACEHOLDER, platformKey)
: step.code;
step.code && needsKey && platformKey
? step.code.replaceAll(API_KEY_PLACEHOLDER, platformKey)
: needsKey
? null
: step.code;
Fix with Cubic


rng := rand.New(rand.NewPCG(uint64(time.Now().UnixNano()), 0xC0FFEE)) //nolint:gosec // demo seed

_ = burstSize // size is uniformly sampled in [1,3] below regardless of flag
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot May 29, 2026

Choose a reason for hiding this comment

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

P2: The -burst-size flag is advertised in usage docs and parsed, but silently ignored — the actual size is always 1 + rng.IntN(3). Either use the flag value (e.g., as a max for the random range) or remove the flag and update the usage comment to avoid misleading callers.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At server/cmd/seedhooks/main.go, line 149:

<comment>The `-burst-size` flag is advertised in usage docs and parsed, but silently ignored — the actual size is always `1 + rng.IntN(3)`. Either use the flag value (e.g., as a max for the random range) or remove the flag and update the usage comment to avoid misleading callers.</comment>

<file context>
@@ -0,0 +1,306 @@
+
+	rng := rand.New(rand.NewPCG(uint64(time.Now().UnixNano()), 0xC0FFEE)) //nolint:gosec // demo seed
+
+	_ = burstSize // size is uniformly sampled in [1,3] below regardless of flag
+	burstIdx := 0
+	for {
</file context>
Fix with Cubic

title: "Add your API key",
description:
"Set the Speakeasy API key in your environment or Cursor settings.",
code: `export SPEAKEASY_API_KEY="sk_live_speakeasy_xxxxxxxxxxxxx"`,
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot May 29, 2026

Choose a reason for hiding this comment

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

P2: Cursor setup also uses a hard-coded sample key without enabling API-key substitution.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At client/dashboard/src/pages/setup/setup-data.ts, line 125:

<comment>Cursor setup also uses a hard-coded sample key without enabling API-key substitution.</comment>

<file context>
@@ -0,0 +1,135 @@
+        title: "Add your API key",
+        description:
+          "Set the Speakeasy API key in your environment or Cursor settings.",
+        code: `export SPEAKEASY_API_KEY="sk_live_speakeasy_xxxxxxxxxxxxx"`,
+        language: "bash",
+      },
</file context>
Fix with Cubic

title: "Configure environment",
description:
"Set environment variables for Codex to route through Speakeasy.",
code: `export SPEAKEASY_API_KEY="sk_live_speakeasy_xxxxxxxxxxxxx"\nexport SPEAKEASY_CODEX_HOOK=true`,
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot May 29, 2026

Choose a reason for hiding this comment

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

P2: Codex setup copies a fake API key string because this step is not marked for API-key substitution.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At client/dashboard/src/pages/setup/setup-data.ts, line 97:

<comment>Codex setup copies a fake API key string because this step is not marked for API-key substitution.</comment>

<file context>
@@ -0,0 +1,135 @@
+        title: "Configure environment",
+        description:
+          "Set environment variables for Codex to route through Speakeasy.",
+        code: `export SPEAKEASY_API_KEY="sk_live_speakeasy_xxxxxxxxxxxxx"\nexport SPEAKEASY_CODEX_HOOK=true`,
+        language: "bash",
+      },
</file context>
Fix with Cubic

… Onboarding tab

- New POST /rpc/organizations.sendEnterpriseAdminOnboardingEmail endpoint (org:admin scope) takes a list of recipient emails and dispatches the enterprise admin onboarding email via Loops template cmpqyxnzl00hj0jwtkibhyjdz. The setup_link variable is built server-side as siteURL/<org-slug>/setup so super admins can't redirect recipients to arbitrary URLs.
- Email template registered as EnterpriseAdminOnboarding (single SetupLink field).
- Dashboard: new "Onboarding" tab on OrgAdminSettings with comma-separated email input, mutation hook, sent-count toast, and display of the embedded setup link for verification.
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 33 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="server/internal/organizations/impl.go">

<violation number="1" location="server/internal/organizations/impl.go:1152">
P2: The batch send aborts on the first delivery error, which leaves earlier recipients already emailed but returns a full failure. This creates partial side effects and duplicate emails on retry.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Fix all with cubic | Re-trigger cubic

if recipient == "" {
continue
}
if err := s.email.Send(ctx, recipient, tmpl); err != nil {
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot May 29, 2026

Choose a reason for hiding this comment

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

P2: The batch send aborts on the first delivery error, which leaves earlier recipients already emailed but returns a full failure. This creates partial side effects and duplicate emails on retry.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At server/internal/organizations/impl.go, line 1152:

<comment>The batch send aborts on the first delivery error, which leaves earlier recipients already emailed but returns a full failure. This creates partial side effects and duplicate emails on retry.</comment>

<file context>
@@ -1120,6 +1120,47 @@ func (s *Service) handleSetupCallback(w http.ResponseWriter, r *http.Request) {
+		if recipient == "" {
+			continue
+		}
+		if err := s.email.Send(ctx, recipient, tmpl); err != nil {
+			return nil, oops.E(oops.CodeUnexpected, err, "failed to send onboarding email to %s", recipient).Log(ctx, s.logger)
+		}
</file context>
Fix with Cubic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant