Skip to content

[PULSE-50] Organizations rename, remove Tools page, post-login profile fetch, welcome page UX#18

Merged
uz1mani merged 11 commits intomainfrom
staging
Feb 9, 2026
Merged

[PULSE-50] Organizations rename, remove Tools page, post-login profile fetch, welcome page UX#18
uz1mani merged 11 commits intomainfrom
staging

Conversation

@uz1mani
Copy link
Copy Markdown
Member

@uz1mani uz1mani commented Feb 9, 2026

Work Item

PULSE-50

Summary

• Renamed user-facing "workspaces" to "organizations" across Pulse (header, welcome, org settings) and aligned with ciphera-ui 0.0.49 / OrganizationSwitcher.
• Removed the Tools page and its header entry.
• Fetched full profile after login so the header shows display name without refresh.
• Improved loading state and organization selection UI on the welcome page.

Changes

Organizations rename: Header dropdown section set to "Organizations"; welcome/onboarding copy updated to "Choose your organization", "Organization name", "Create a new organization"; organization settings message updated to "personal context". ciphera-ui bumped to 0.0.49; Pulse frontend updated to use OrganizationSwitcher with new props and copy.
Tools page: Removed Tools page route/component and removed Tools from the application header navigation.
Post-login profile: After login, full user profile is fetched so the header display name is correct without a page reload.
Welcome page: Enhanced loading state and organization selection UI (visual feedback and layout/UX improvements).

Test Plan

  • Header shows "Organizations" and org switcher uses new copy; welcome flow shows "Choose your organization" / "Organization name" / "Create a new organization"; org settings show "personal context".
  • Tools is not present in the header; navigating to the former Tools URL behaves as expected (e.g. 404 or redirect).
  • After login, header shows display name immediately without refreshing the page.
  • Welcome page shows clear loading state and improved organization selection UI.

@uz1mani uz1mani self-assigned this Feb 9, 2026
@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Feb 9, 2026

Greptile Overview

Greptile Summary

This PR updates Pulse’s post-login and onboarding UX while aligning terminology from “workspaces” to “organizations”. It removes the standalone Tools page/nav link, adds multiple integration guide pages, updates the header org switcher wiring to the newer ciphera-ui Header props, and fetches the full user profile after login/context switches so the display name shows correctly without a refresh.

Key correctness issues found:

  • /auth/callback retry UX is effectively broken for common failures because processedRef prevents re-running the code exchange and retry does not trigger runCodeExchange again.
  • Welcome flow still contains legacy “workspace” copy in a visible loading overlay ("Switching workspace...") despite the rename to organizations.

Confidence Score: 3/5

  • This PR is mergeable after fixing a couple user-facing flow regressions in auth callback retry and welcome copy consistency.
  • Most changes are UI/copy updates and new static integration pages, but there is a real functional regression in the auth callback retry path that will block users from recovering from transient exchange failures, plus a remaining renamed string that will be visible during onboarding org switching.
  • app/auth/callback/page.tsx, app/welcome/page.tsx

Important Files Changed

Filename Overview
app/auth/callback/page.tsx Adds full-profile fetch after login in both code exchange and direct-token flows; retry logic appears broken when initial code exchange fails after processedRef is set.
app/integrations/nextjs/page.tsx Adds new client-side Next.js integration documentation page; no functional logic changes.
app/integrations/react/page.tsx Adds new client-side React integration documentation page; static content only.
app/integrations/vue/page.tsx Adds new client-side Vue integration documentation page; static content only.
app/integrations/wordpress/page.tsx Adds new client-side WordPress integration documentation page; static content only.
app/layout-content.tsx Removes Tools nav link and wires header org switcher props to ciphera-ui Header; uses hard reload on org switch.
app/tools/page.tsx Deletes Tools page route/component; remaining UTM builder is still accessible from dashboard campaigns modal.
app/welcome/page.tsx Updates welcome flow copy and org selection UI; still shows a legacy "Switching workspace..." loading title and adds extra full-profile fetches on context switch/create.
lib/auth/context.tsx Fetches full user profile after login/init to populate display_name and clears legacy tokens; adds org auto-switch behavior and extra API call on login.

Sequence Diagram

sequenceDiagram
  autonumber
  participant U as User
  participant CB as Callback
  participant A as AuthActions
  participant API as BackendAPI
  participant C as AuthContext
  participant R as Router

  U->>CB: Open callback
  CB->>A: Exchange code
  alt ok
    A-->>CB: minimal user
    CB->>API: Fetch profile
    alt ok
      API-->>CB: full user
      CB->>C: login(merge)
    else fail
      CB->>C: login(minimal)
    end
    CB->>R: Navigate
  else error
    CB-->>U: Show error + retry
  end

  Note over U,R: Organization selection
  U->>R: Open welcome
  R->>API: Load org list
  U->>R: Pick org
  R->>API: Switch context
  API-->>R: context set
  R->>A: Update session
  A-->>R: session user
  R->>API: Fetch profile
  API-->>R: full user
  R->>C: login(merge)
  R->>R: refresh()
Loading

Copy link
Copy Markdown

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

9 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Feb 9, 2026

Additional Comments (2)

app/welcome/page.tsx
Organization rename inconsistent

Step 1/2 UI was updated to “organization”, but the blocking loading overlay still says "Switching workspace..." (shown whenever switchingOrgId is set). This will regress the user-facing rename and is visible during org switching on the welcome page.

Prompt To Fix With AI
This is a comment left during a code review.
Path: app/welcome/page.tsx
Line: 315:321

Comment:
**Organization rename inconsistent**

Step 1/2 UI was updated to “organization”, but the blocking loading overlay still says `"Switching workspace..."` (shown whenever `switchingOrgId` is set). This will regress the user-facing rename and is visible during org switching on the welcome page.

How can I resolve this? If you propose a fix, please make it concise.

app/auth/callback/page.tsx
Retry is blocked

handleRetry() only sets isRetrying=true, but runCodeExchange() is only invoked on the auth-code path after processedRef.current = true (line 101). If the first attempt fails after setting processedRef.current (e.g., network error from exchangeAuthCode), retry won’t re-run because the effect returns early when !code || !state (lines 83-86), so processedRef.current never gets reset and nothing triggers runCodeExchange() again. This makes the “Try again” button a no-op in common failure cases.

Prompt To Fix With AI
This is a comment left during a code review.
Path: app/auth/callback/page.tsx
Line: 46:49

Comment:
**Retry is blocked**

`handleRetry()` only sets `isRetrying=true`, but `runCodeExchange()` is only invoked on the auth-code path after `processedRef.current = true` (line 101). If the first attempt fails after setting `processedRef.current` (e.g., network error from `exchangeAuthCode`), retry won’t re-run because the effect returns early when `!code || !state` (lines 83-86), so `processedRef.current` never gets reset and nothing triggers `runCodeExchange()` again. This makes the “Try again” button a no-op in common failure cases.

How can I resolve this? If you propose a fix, please make it concise.

@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Feb 9, 2026

Greptile Overview

Greptile Summary

This PR updates user-facing terminology from “workspaces” to “organizations”, removes the /tools page and header nav entry, adds framework-specific integration guide pages, and improves post-login UX by fetching the full user profile so the header can show display_name without a manual refresh.

Key runtime changes are concentrated in the auth callback, auth context, and welcome/onboarding flow where session establishment is followed by a /auth/user/me fetch and a merged user object is stored in auth state/localStorage.

Confidence Score: 3/5

  • This PR is mergeable after addressing a few correctness/security issues in the auth and onboarding flows.
  • Most changes are copy/UX and new static pages, but there is a concrete open-redirect in the auth callback and a couple of inconsistent/missed rename/profile-refresh paths that will show incorrect UI state post-login/org switch in realistic scenarios.
  • app/auth/callback/page.tsx, app/welcome/page.tsx, lib/auth/context.tsx

Important Files Changed

Filename Overview
app/auth/callback/page.tsx Adds post-login full-profile fetch and retry reset; introduces an open-redirect risk via unsanitized returnTo query param.
app/integrations/nextjs/page.tsx Adds a static Next.js integration guide page; no dynamic logic.
app/integrations/react/page.tsx Adds a static React integration guide page; no dynamic logic.
app/integrations/vue/page.tsx Adds a static Vue integration guide page; no dynamic logic.
app/integrations/wordpress/page.tsx Adds a static WordPress integration guide page; no dynamic logic.
app/layout-content.tsx Removes Tools nav link and wires Header org switcher props; no new critical logic added in this PR.
app/tools/page.tsx Deletes the Tools page component.
app/welcome/page.tsx Updates onboarding UI/copy and fetches full profile after org switch/create; default org name/slug still use "workspace" terminology.
lib/auth/context.tsx Fetches full profile after login to populate display_name; auto-switch path still sets session user without fetching full profile.

Sequence Diagram

sequenceDiagram
  participant U as User
  participant CB as Auth Callback UI
  participant S as Session Update
  participant P as Profile Fetch
  participant A as Auth State
  participant H as Header UI
  participant W as Welcome UI

  U->>CB: Returns from login
  CB->>S: Update session
  S-->>CB: User summary
  CB->>P: Fetch profile
  P-->>CB: User profile
  CB->>A: Update auth state
  A-->>H: Render name
  CB-->>W: Navigate (optional)

  U->>W: Choose org
  W->>S: Update session
  S-->>W: User summary
  W->>P: Fetch profile
  P-->>W: User profile
  W->>A: Update auth state
  A-->>H: Update header
Loading

Copy link
Copy Markdown

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

9 files reviewed, 3 comments

Edit Code Review Agent Settings | Greptile

@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Feb 9, 2026

Additional Comments (3)

app/welcome/page.tsx
Rename missed in defaults
DEFAULT_ORG_NAME is set to 'My workspace' and slugFromName() falls back to 'my-workspace', which contradicts the PR’s "workspaces → organizations" rename and will surface in the default org name/slug on first load. This looks like a regression from the pre-PR defaults and should be updated to the organization terminology for consistency.

Prompt To Fix With AI
This is a comment left during a code review.
Path: app/welcome/page.tsx
Line: 49:56

Comment:
**Rename missed in defaults**
`DEFAULT_ORG_NAME` is set to `'My workspace'` and `slugFromName()` falls back to `'my-workspace'`, which contradicts the PR’s "workspaces → organizations" rename and will surface in the default org name/slug on first load. This looks like a regression from the pre-PR defaults and should be updated to the organization terminology for consistency.

How can I resolve this? If you propose a fix, please make it concise.

lib/auth/context.tsx
Stale profile after auto-switch
In the auto-switch path, setUser(result.user) writes the session user directly and calls router.refresh(), but unlike other login/switch flows in this PR it does not fetch /auth/user/me to populate display_name. If the cookie session user lacks display_name, the header can still show the email until a later refresh. Consider reusing the same "fetch full profile + merge org_id/role" approach here.

Also appears in: lib/auth/context.tsx:169-177 (same block).

Prompt To Fix With AI
This is a comment left during a code review.
Path: lib/auth/context.tsx
Line: 159:177

Comment:
**Stale profile after auto-switch**
In the auto-switch path, `setUser(result.user)` writes the session user directly and calls `router.refresh()`, but unlike other login/switch flows in this PR it does *not* fetch `/auth/user/me` to populate `display_name`. If the cookie session user lacks `display_name`, the header can still show the email until a later refresh. Consider reusing the same "fetch full profile + merge org_id/role" approach here.

Also appears in: `lib/auth/context.tsx:169-177` (same block).

How can I resolve this? If you propose a fix, please make it concise.

app/auth/callback/page.tsx
Open redirect via returnTo
returnTo is taken from the URL query string and passed directly to router.push(returnTo). If an attacker can get a user to hit /auth/callback?...&returnTo=https://evil.example, this can navigate them off-site after login. This should be restricted to same-origin relative paths (e.g., require it to start with / and reject // or http(s):).

Prompt To Fix With AI
This is a comment left during a code review.
Path: app/auth/callback/page.tsx
Line: 72:74

Comment:
**Open redirect via returnTo**
`returnTo` is taken from the URL query string and passed directly to `router.push(returnTo)`. If an attacker can get a user to hit `/auth/callback?...&returnTo=https://evil.example`, this can navigate them off-site after login. This should be restricted to same-origin relative paths (e.g., require it to start with `/` and reject `//` or `http(s):`).

How can I resolve this? If you propose a fix, please make it concise.

@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Feb 9, 2026

Greptile Overview

Greptile Summary

This PR updates user-facing terminology from “workspaces” to “organizations”, removes the Tools page/entry point, improves the welcome page loading/organization selection UX, and fetches the full user profile after login so the header can show the correct display name without a refresh.

Key integration points are the auth callback + AuthContext (session establishment and post-login profile hydration), and layout-content where the header/org-switcher wiring lives. The main items to double-check before merge are consistency between the installed @ciphera-net/ui version and the Header/Button props used, and aligning post-login navigation (returnTo) across auth flows.

Confidence Score: 3/5

  • This PR is close to mergeable but has a few functional inconsistencies that can break navigation/loading behavior depending on the UI package version in use.
  • Main risks are (1) possible mismatch between the pinned @ciphera-net/ui version and the Header/Button props used (could silently break org switching or loading indicators), and (2) inconsistent handling of returnTo between direct-token vs OAuth code-exchange paths, which will misroute users after login in OAuth scenarios.
  • app/layout-content.tsx, app/welcome/page.tsx, app/auth/callback/page.tsx

Important Files Changed

Filename Overview
app/auth/callback/page.tsx Validates returnTo for direct-token auth and resets processing state on retry; OAuth code path still redirects to / (ignores returnTo).
app/integrations/nextjs/page.tsx No functional issues found in this change; content/page copy updates only.
app/integrations/react/page.tsx No functional issues found in this change; content/page copy updates only.
app/integrations/vue/page.tsx No functional issues found in this change; content/page copy updates only.
app/integrations/wordpress/page.tsx No functional issues found in this change; content/page copy updates only.
app/layout-content.tsx Header org-switcher wiring changed; verify @ciphera-net/ui version matches new Header props (risk of silent break if version mismatch).
app/tools/page.tsx Tools page removed; ensure route handling is intentional (404/redirect) and no other references remain.
app/welcome/page.tsx Welcome/org selection UX changes and loading overlay tweaks; ensure Button props align with @ciphera-net/ui (e.g., isLoading support) and that state transitions don't block creation flow.
lib/auth/context.tsx Auth context now fetches full user profile post-login; verify it doesn’t create redundant fetch loops or regress initial auth hydration.

Sequence Diagram

sequenceDiagram
  autonumber
  participant U as User
  participant CB as AuthCallbackPage
  participant AUTH as AuthContext
  participant API as Backend
  participant H as Header
  participant W as WelcomePage

  U->>CB: Return from IdP with auth params (+ optional returnTo)
  alt Direct-token path
    CB->>AUTH: Store session
    AUTH->>API: Fetch current user profile
    API-->>AUTH: Profile (includes display name)
    AUTH-->>H: Render display name + org switcher
    CB->>CB: Validate returnTo (relative path only)
    CB-->>U: Navigate to returnTo or '/'
  else OAuth code-exchange path
    CB->>API: Exchange authorization code
    API-->>CB: Session established
    CB->>AUTH: Store session
    AUTH->>API: Fetch current user profile
    API-->>AUTH: Profile
    AUTH-->>H: Render display name + org switcher
    Note over CB: PR currently navigates to '/'
    CB-->>U: Navigate to '/'
  end

  U->>W: Visit welcome
  W->>API: Fetch organizations
  API-->>W: Org list
  W-->>U: Show org selection / create org

Loading

Copy link
Copy Markdown

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

9 files reviewed, 3 comments

Edit Code Review Agent Settings | Greptile

@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Feb 9, 2026

Additional Comments (3)

app/layout-content.tsx
UI package/prop mismatch

This file is passing org-switching props into the Header from @ciphera-net/ui. In this PR series there’s evidence of a @ciphera-net/ui version mismatch vs the prop names being used (e.g., using newer OrganizationSwitcher/org props while package.json still pins an older ui version). If the installed UI package doesn’t support these props, the org switcher will silently not render/switch. Please ensure the dependency version matches the Header API you’re using, or update the props to the version actually installed.

Prompt To Fix With AI
This is a comment left during a code review.
Path: app/layout-content.tsx
Line: 50:52

Comment:
**UI package/prop mismatch**

This file is passing org-switching props into the `Header` from `@ciphera-net/ui`. In this PR series there’s evidence of a `@ciphera-net/ui` version mismatch vs the prop names being used (e.g., using newer `OrganizationSwitcher`/org props while `package.json` still pins an older ui version). If the installed UI package doesn’t support these props, the org switcher will silently not render/switch. Please ensure the dependency version matches the Header API you’re using, or update the props to the version actually installed.

How can I resolve this? If you propose a fix, please make it concise.

app/welcome/page.tsx
Unsupported Button prop

This uses isLoading={...} on Button. If @ciphera-net/ui’s Button doesn’t support an isLoading prop in the version pinned for this PR, this will be ignored (no spinner/disabled state) or could trigger runtime warnings depending on implementation. Either switch to the supported loading pattern for your UI version (commonly disabled + local spinner) or bump the UI dependency to the version that defines isLoading.

Prompt To Fix With AI
This is a comment left during a code review.
Path: app/welcome/page.tsx
Line: 685:687

Comment:
**Unsupported Button prop**

This uses `isLoading={...}` on `Button`. If `@ciphera-net/ui`’s `Button` doesn’t support an `isLoading` prop in the version pinned for this PR, this will be ignored (no spinner/disabled state) or could trigger runtime warnings depending on implementation. Either switch to the supported loading pattern for your UI version (commonly `disabled` + local spinner) or bump the UI dependency to the version that defines `isLoading`.

How can I resolve this? If you propose a fix, please make it concise.

app/auth/callback/page.tsx
OAuth flow ignores returnTo

The returnTo parameter is validated and used in the direct-token path, but the OAuth code-exchange path always redirects to / after success. This creates inconsistent post-login navigation (users coming back via OAuth won’t land on the intended in-app destination even when returnTo is present). Thread the same validated returnTo logic through the OAuth flow as well (after exchange succeeds).

Prompt To Fix With AI
This is a comment left during a code review.
Path: app/auth/callback/page.tsx
Line: 18:22

Comment:
**OAuth flow ignores returnTo**

The `returnTo` parameter is validated and used in the direct-token path, but the OAuth code-exchange path always redirects to `/` after success. This creates inconsistent post-login navigation (users coming back via OAuth won’t land on the intended in-app destination even when `returnTo` is present). Thread the same validated `returnTo` logic through the OAuth flow as well (after exchange succeeds).

How can I resolve this? If you propose a fix, please make it concise.

@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Feb 9, 2026

Greptile Overview

Greptile Summary

This PR updates user-facing terminology from “workspace” to “organization”, removes the Tools page and header entry, improves welcome/onboarding UI, and adds logic to fetch a fuller user profile after login so the header can show the display name immediately.

Key areas touched:

  • Auth callback + AuthProvider: adds post-login /auth/user/me fetches and merges profile fields into the stored user state.
  • Layout header: removes Tools navigation item and continues to support org switching.
  • Welcome flow: improves loading visuals and org selection UI, and adjusts copy for organizations.

Issues to address before merge:

  • Welcome step-2 still uses “workspace” copy in headings/labels, which will ship inconsistent onboarding terminology.
  • Profile fetching is duplicated in multiple places (callback/welcome and login()), causing redundant requests and potentially inconsistent user state depending on response timing.
  • returnTo handling differs between direct-token vs auth-code flows in the callback; if deep-link redirects are expected in the standard code flow, they will be broken/inconsistent.

Confidence Score: 3/5

  • This PR is mergeable after addressing a few correctness issues around auth redirect behavior, duplicated profile fetching, and inconsistent onboarding terminology.
  • Most changes are copy/UI and page removal, but the auth/profile changes introduce redundant API calls and potentially inconsistent state updates. There’s also an onboarding copy regression (“workspace” remains in step 2) and callback redirect behavior is inconsistent between flows.
  • lib/auth/context.tsx, app/auth/callback/page.tsx, app/welcome/page.tsx

Important Files Changed

Filename Overview
app/auth/callback/page.tsx Adds post-login profile fetch and sanitizes returnTo for the direct-token flow; note inconsistent returnTo handling between auth-code vs direct-token branches.
app/integrations/nextjs/page.tsx Adds a new Next.js integration guide page with static instructional content and links back to /integrations.
app/integrations/react/page.tsx Adds a new React integration guide page with static instructional content and a back link.
app/integrations/vue/page.tsx Adds a new Vue integration guide page with static instructional content and a back link.
app/integrations/wordpress/page.tsx Adds a new WordPress integration guide page with static instructional content and a back link.
app/layout-content.tsx Removes Tools nav item and wires header org switcher props; current org list fetch depends only on auth.user changes.
app/tools/page.tsx Deletes Tools page component (UTM builder) as part of removing Tools section.
app/welcome/page.tsx Updates welcome UX and replaces workspace terminology with organizations in several places; step-2 copy still says workspace and profile fetch is duplicated with AuthProvider login() behavior.
lib/auth/context.tsx Adds automatic full-profile fetch after login and after org auto-switch; introduces redundant /auth/user/me fetches when callers already fetched profile.

Sequence Diagram

sequenceDiagram
  autonumber
  actor User
  participant Callback
  participant Actions
  participant Provider
  participant Header

  User->>Callback: Auth redirect
  Callback->>Actions: Establish session
  Actions-->>Callback: Session user
  Callback->>Provider: login()
  Provider-->>Header: Updated user state
  Callback-->>User: Route navigation
Loading

Copy link
Copy Markdown

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

9 files reviewed, 4 comments

Edit Code Review Agent Settings | Greptile

@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Feb 9, 2026

Additional Comments (4)

app/welcome/page.tsx
User-facing copy mismatch

This step-2 card still says “Name your workspace” even though step 1 and other updated strings say “organization”. This will ship inconsistent onboarding copy for any user creating a new org (step 2). Update the heading/labels/help text here to match the new “organization” terminology.

Prompt To Fix With AI
This is a comment left during a code review.
Path: app/welcome/page.tsx
Line: 484:490

Comment:
**User-facing copy mismatch**

This step-2 card still says “Name your workspace” even though step 1 and other updated strings say “organization”. This will ship inconsistent onboarding copy for any user creating a new org (step 2). Update the heading/labels/help text here to match the new “organization” terminology.

How can I resolve this? If you propose a fix, please make it concise.

app/auth/callback/page.tsx
Unsafe returnTo handling

returnTo is validated/sanitized in the direct-token flow (lines ~72-75), but the authorization-code flow always router.push('/') after login. If the product expects returnTo to work for the normal auth-code callback too, that behavior is now inconsistent and will break deep-linking (e.g., login redirects back to a protected page). Consider applying the same returnTo logic for the code flow as well.

Prompt To Fix With AI
This is a comment left during a code review.
Path: app/auth/callback/page.tsx
Line: 39:40

Comment:
**Unsafe returnTo handling**

`returnTo` is validated/sanitized in the direct-token flow (lines ~72-75), but the authorization-code flow always `router.push('/')` after login. If the product expects `returnTo` to work for the normal auth-code callback too, that behavior is now inconsistent and will break deep-linking (e.g., login redirects back to a protected page). Consider applying the same `returnTo` logic for the code flow as well.

How can I resolve this? If you propose a fix, please make it concise.

lib/auth/context.tsx
Duplicate profile fetches

login() now triggers an async /auth/user/me fetch (lines ~56-69), but several call sites in this PR already fetch /auth/user/me and then call login(merged) (e.g., welcome page and auth callback). That results in two back-to-back profile requests on a successful login/switch, which is wasted load and can cause user state to "flip" depending on response timing. Either remove the extra fetch from login() or ensure call sites pass a minimal user object and rely on login() to fetch once.

Prompt To Fix With AI
This is a comment left during a code review.
Path: lib/auth/context.tsx
Line: 51:70

Comment:
**Duplicate profile fetches**

`login()` now triggers an async `/auth/user/me` fetch (lines ~56-69), but several call sites in this PR already fetch `/auth/user/me` and then call `login(merged)` (e.g., welcome page and auth callback). That results in two back-to-back profile requests on a successful login/switch, which is wasted load and can cause user state to "flip" depending on response timing. Either remove the extra fetch from `login()` or ensure call sites pass a minimal user object and rely on `login()` to fetch once.

How can I resolve this? If you propose a fix, please make it concise.

app/layout-content.tsx
Stale org list after switch

The header org list is fetched only when auth.user changes (useEffect deps). handleSwitchWorkspace does a hard reload, so it will refresh, but if the UI library ever switches org without reload (or reload is removed later), orgs will be stale and activeOrgId won’t be reflected correctly. Since this PR is explicitly moving toward “no refresh needed” for profile, consider ensuring orgs refresh on org context change (e.g., when auth.user?.org_id changes) so the header stays consistent.

Prompt To Fix With AI
This is a comment left during a code review.
Path: app/layout-content.tsx
Line: 28:37

Comment:
**Stale org list after switch**

The header org list is fetched only when `auth.user` changes (useEffect deps). `handleSwitchWorkspace` does a hard reload, so it will refresh, but if the UI library ever switches org without reload (or reload is removed later), `orgs` will be stale and `activeOrgId` won’t be reflected correctly. Since this PR is explicitly moving toward “no refresh needed” for profile, consider ensuring orgs refresh on org context change (e.g., when `auth.user?.org_id` changes) so the header stays consistent.

How can I resolve this? If you propose a fix, please make it concise.

…or terminology in layout content for consistency
@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Feb 9, 2026

Greptile Overview

Greptile Summary

This PR completes a user-facing terminology shift from “workspaces” to “organizations”, updates the header org switcher wiring to match @ciphera-net/ui 0.0.49, removes the /tools route and header entry, and improves the welcome/onboarding UX (loading and org selection cards).

It also changes the post-auth flows to fetch /auth/user/me after setting the session so the in-app header can display display_name immediately (Auth callback, welcome org selection, and AuthContext login/init/auto-switch).

Confidence Score: 4/5

  • This PR is mostly safe to merge, but it has a couple of user-facing/logging inconsistencies that should be corrected first.
  • Core logic changes (safe returnTo handling, profile fetch after login) look coherent and are consistently applied across callback/welcome/auth context. The remaining issues are limited to incomplete terminology rename in the welcome flow and a stale error log message in the org switch handler.
  • app/welcome/page.tsx, app/layout-content.tsx

Important Files Changed

Filename Overview
app/auth/callback/page.tsx Adds safe returnTo handling, retry reset, and fetches full profile via /auth/user/me before calling login so display_name is available immediately.
app/integrations/nextjs/page.tsx Adds a new client-side Next.js integration documentation page with script installation snippets.
app/integrations/react/page.tsx Adds a new client-side React integration documentation page with static snippet examples.
app/integrations/vue/page.tsx Adds a new client-side Vue integration documentation page with script tag / Nuxt config examples.
app/integrations/wordpress/page.tsx Adds a new client-side WordPress integration documentation page with header script snippet instructions.
app/layout-content.tsx Renames workspace switcher wiring to org switcher props, removes Tools nav item, and keeps org list fetching; contains a stale 'workspace' error log message.
app/tools/page.tsx Deletes the Tools page route/component as part of navigation cleanup.
app/welcome/page.tsx Updates onboarding copy and UI for org selection/loading; still contains leftover 'workspace' terminology in step 2 labels/copy.
lib/auth/context.tsx Fetches full profile after login/init and on org auto-switch to populate display_name; preserves org_id/role while updating localStorage.
package.json Bumps @ciphera-net/ui dependency from 0.0.48 to 0.0.49.
package-lock.json Updates lockfile to reflect @ciphera-net/ui 0.0.49 resolution/integrity.

Sequence Diagram

sequenceDiagram
  participant U as User
  participant CB as /auth/callback (client)
  participant AS as setSessionAction/exchangeAuthCode (server action)
  participant API as API (/auth/user/me)
  participant AC as AuthContext
  participant H as Header/OrganizationSwitcher

  U->>CB: Visit callback with code (and optional returnTo)
  CB->>AS: exchangeAuthCode(code, verifier, redirectUri)
  AS-->>CB: { success, user }
  CB->>API: GET /auth/user/me (fetch full profile)
  API-->>CB: fullProfile (display_name, etc.)
  CB->>AC: login(merged user)
  AC-->>H: user updated (display_name available)
  CB->>CB: Validate returnTo (must start with '/' and not '//')
  CB->>CB: router.push(safeReturnTo)

  Note over U,CB: Welcome flow organization selection
  U->>CB: (If redirected) go to /welcome
  U->>CB: Select organization
  CB->>AS: setSessionAction(access_token)
  AS-->>CB: { success, user }
  CB->>API: GET /auth/user/me
  API-->>CB: fullProfile
  CB->>AC: login(merged user)
  AC-->>H: header reflects selected org + display_name
Loading

Copy link
Copy Markdown

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

11 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Feb 9, 2026

Additional Comments (2)

app/welcome/page.tsx
Organization rename incomplete

Step 2 still renders workspace terminology ("Name your workspace", "Workspace name", and "Used in your workspace URL."), which contradicts the PR’s org rename and the Step 1 copy. This will ship mixed terminology in the onboarding flow.

Prompt To Fix With AI
This is a comment left during a code review.
Path: app/welcome/page.tsx
Line: 483:497

Comment:
**Organization rename incomplete**

Step 2 still renders workspace terminology (`"Name your workspace"`, `"Workspace name"`, and `"Used in your workspace URL."`), which contradicts the PR’s org rename and the Step 1 copy. This will ship mixed terminology in the onboarding flow.


How can I resolve this? If you propose a fix, please make it concise.

app/layout-content.tsx
Incorrect error message label

handleSwitchOrganization logs Failed to switch workspace on error, but this handler is now org-based. This makes prod logs misleading when debugging org switching issues.

Prompt To Fix With AI
This is a comment left during a code review.
Path: app/layout-content.tsx
Line: 29:37

Comment:
**Incorrect error message label**

`handleSwitchOrganization` logs `Failed to switch workspace` on error, but this handler is now org-based. This makes prod logs misleading when debugging org switching issues.


How can I resolve this? If you propose a fix, please make it concise.

…place 'workspace' with 'organization' for consistency
@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Feb 9, 2026

Greptile Overview

Greptile Summary

This PR updates user-facing terminology from “workspace” to “organization” across the header and welcome flow, upgrades @ciphera-net/ui to 0.0.49 to use the updated OrganizationSwitcher API, and removes the /tools route and header nav entry.

It also changes the auth flow so a full /auth/user/me profile is fetched after login (and after org switching/creation) to ensure the header can show display_name without requiring a manual refresh. The welcome page gets UX improvements around loading and organization selection.

Confidence Score: 3/5

  • This PR is mergeable after addressing a couple auth/org-switch edge cases in AuthProvider.
  • Most changes are copy/UX and dependency bump, but the new post-login profile fetch is duplicated across layers and the org auto-switch merge precedence can cause repeated switching when /auth/user/me doesn’t reflect the new org immediately. Fixing those will reduce noisy failed requests and prevent loops.
  • lib/auth/context.tsx (login() post-fetch and org auto-switch merge precedence)

Important Files Changed

Filename Overview
app/auth/callback/page.tsx Adds post-login profile fetch and validates returnTo before redirect; also resets processedRef on retry.
app/integrations/nextjs/page.tsx Adds a new Next.js integrations guide page with code snippets for script inclusion.
app/integrations/react/page.tsx Adds a new React integrations guide page with static script-tag examples and optional programmatic injection.
app/integrations/vue/page.tsx Adds a new Vue integrations guide page with instructions for Vue and Nuxt script insertion.
app/integrations/wordpress/page.tsx Adds a new WordPress integrations guide page describing header script insertion options.
app/layout-content.tsx Updates header org switcher props/copy and removes Tools nav item.
app/tools/page.tsx Removes the Tools page route (deleted file).
app/welcome/page.tsx Renames workspace copy to organization and enhances step-1 org selection/loading UX; fetches full profile after org switch/create.
lib/auth/context.tsx Adds extra post-login profile fetch and changes auto-switch context logic; introduces risk of unauthenticated fetch noise and re-triggering auto-switch due to merge precedence.
package.json Bumps @ciphera-net/ui dependency to 0.0.49.
package-lock.json Updates lockfile for @ciphera-net/ui 0.0.49.

Sequence Diagram

sequenceDiagram
    autonumber
    participant U as User
    participant N as Next.js App (Pulse)
    participant A as Auth Callback Page
    participant AC as AuthContext
    participant API as Pulse API
    participant H as App Header
    participant W as Welcome Page

    U->>N: Return from IdP to /auth/callback?code&state
    N->>A: Render callback page
    A->>API: Exchange code for session/token
    API-->>A: Session established
    A->>API: Fetch full user profile (post-login)
    API-->>A: Profile (displayName, orgs, activeOrg)
    A->>AC: setAuthState(session, profile)
    AC-->>H: Header re-renders with display name
    AC-->>W: Welcome uses org list + active org
    alt No active org selected
        W->>U: Prompt: "Choose your organization"
        U->>W: Select organization
        W->>API: Set active organization
        API-->>W: Success
        W-->>H: Header org switcher updates
    else Active org exists
        W->>U: Continue into app
    end
Loading

Copy link
Copy Markdown

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

11 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Feb 9, 2026

Additional Comments (2)

lib/auth/context.tsx
Unauthenticated profile fetch
login() now calls apiRequest('/auth/user/me') immediately after setUser(userData) (lib/auth/context.tsx:51-69). In the auth callback you already fetch /auth/user/me before calling login, but login() will fetch it again, and (more importantly) any call site that invokes login(userData) before the session cookie is set will reliably trigger a failing /auth/user/me request and log an error. Consider removing the fetch from login() (or gating it behind a known-authenticated signal) and keeping the “fetch full profile” only in places where the session has definitely been established (e.g., after setSessionAction).

Prompt To Fix With AI
This is a comment left during a code review.
Path: lib/auth/context.tsx
Line: 51:69

Comment:
**Unauthenticated profile fetch**
`login()` now calls `apiRequest('/auth/user/me')` immediately after `setUser(userData)` (`lib/auth/context.tsx:51-69`). In the auth callback you already fetch `/auth/user/me` *before* calling `login`, but `login()` will fetch it again, and (more importantly) any call site that invokes `login(userData)` before the session cookie is set will reliably trigger a failing `/auth/user/me` request and log an error. Consider removing the fetch from `login()` (or gating it behind a known-authenticated signal) and keeping the “fetch full profile” only in places where the session has definitely been established (e.g., after `setSessionAction`).

How can I resolve this? If you propose a fix, please make it concise.

lib/auth/context.tsx
Repeated auto-switch loop
In the org-wall effect, when !user.org_id you switch context and then set user to a merged profile (lib/auth/context.tsx:159-163), but the merge prefers fullProfile.org_id over result.user.org_id. If /auth/user/me doesn’t reflect the newly-selected org immediately (common if it’s derived from cookie/session propagation), user.org_id can remain falsy and this effect will run again, repeatedly attempting switchContext on every render. Using org_id: result.user.org_id ?? fullProfile.org_id (and similarly for role) avoids re-triggering the auto-switch when the switch call succeeded.

Prompt To Fix With AI
This is a comment left during a code review.
Path: lib/auth/context.tsx
Line: 159:163

Comment:
**Repeated auto-switch loop**
In the org-wall effect, when `!user.org_id` you switch context and then set `user` to a `merged` profile (`lib/auth/context.tsx:159-163`), but the merge prefers `fullProfile.org_id` over `result.user.org_id`. If `/auth/user/me` doesn’t reflect the newly-selected org immediately (common if it’s derived from cookie/session propagation), `user.org_id` can remain falsy and this effect will run again, repeatedly attempting `switchContext` on every render. Using `org_id: result.user.org_id ?? fullProfile.org_id` (and similarly for `role`) avoids re-triggering the auto-switch when the switch call succeeded.

How can I resolve this? If you propose a fix, please make it concise.

@uz1mani uz1mani merged commit fe2eaa5 into main Feb 9, 2026
@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Feb 9, 2026

Greptile Overview

Greptile Summary

I couldn’t perform the requested PR review because the PR diff/content isn’t available in this environment yet. I need the actual code changes (via git diff output or by providing the file contents) to identify concrete, non-speculative issues and to produce the required line-numbered review comments, file analyses, and sequence diagram.

Confidence Score: 0/5

  • Cannot assess merge safety because PR changes were not available to review
  • A correct review requires reading the actual diffs and tracing their interactions; without access to the changed code and line numbers, any findings would be speculative.
  • All listed changed files (diffs not provided): app/auth/callback/page.tsx, app/integrations/*/page.tsx, app/layout-content.tsx, app/tools/page.tsx, app/welcome/page.tsx, lib/auth/context.tsx

Important Files Changed

Filename Overview
app/auth/callback/page.tsx Not analyzed: PR diff/content not provided in this environment.
app/integrations/nextjs/page.tsx Not analyzed: PR diff/content not provided in this environment.
app/integrations/react/page.tsx Not analyzed: PR diff/content not provided in this environment.
app/integrations/vue/page.tsx Not analyzed: PR diff/content not provided in this environment.
app/integrations/wordpress/page.tsx Not analyzed: PR diff/content not provided in this environment.
app/layout-content.tsx Not analyzed: PR diff/content not provided in this environment.
app/tools/page.tsx Not analyzed: PR diff/content not provided in this environment.
app/welcome/page.tsx Not analyzed: PR diff/content not provided in this environment.
lib/auth/context.tsx Not analyzed: PR diff/content not provided in this environment.

Sequence Diagram

sequenceDiagram
  participant Reviewer
  participant Git
  participant PR as Pull Request
  Reviewer->>PR: Request PR diff/changed file contents
  PR-->>Reviewer: Provide diffs (git diff/base..head) or file contents
  Reviewer->>Git: Trace call sites/imports
  Reviewer-->>PR: Produce line-numbered comments, file analyses, table, confidence
Loading

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