Commit Graph

822 Commits

Author SHA1 Message Date
BilalG1
2f719903b1
Redesign Email Server settings + managed domain flow (#1373)
Some checks failed
all-good: Did all the other checks pass? / all-good (push) Has been cancelled
Ensure Prisma migrations are in sync with the schema / check_prisma_migrations (22.x) (push) Has been cancelled
DB migration compat / Check if migrations changed (push) Has been cancelled
Docker Server Build and Push / Docker Build and Push Server (push) Has been cancelled
Docker Server Build and Run / docker (push) Has been cancelled
Runs E2E API Tests (Local Emulator) / E2E Tests (Local Emulator, Node ${{ matrix.node-version }}) (22.x) (push) Has been cancelled
Runs E2E API Tests / E2E Tests (Node ${{ matrix.node-version }}, Freestyle ${{ matrix.freestyle-mode }}) (mock, 22.x) (push) Has been cancelled
Runs E2E API Tests / E2E Tests (Node ${{ matrix.node-version }}, Freestyle ${{ matrix.freestyle-mode }}) (prod, 22.x) (push) Has been cancelled
Runs E2E API Tests with custom port prefix / build (22.x) (push) Has been cancelled
Runs E2E Fallback Tests / E2E Fallback Tests (Node ${{ matrix.node-version }}) (22.x) (push) Has been cancelled
Lint & build / lint_and_build (24) (push) Has been cancelled
TOC Generator / TOC Generator (push) Has been cancelled
DB migration compat / Back-compat — Current branch migrations with ${{ needs.check-migrations-changed.outputs.base_branch }} branch code (push) Has been cancelled
DB migration compat / Forward-compat — Current branch code with ${{ needs.check-migrations-changed.outputs.base_branch }} branch migrations (push) Has been cancelled
DB migration compat / No migration changes (skipped) (push) Has been cancelled
## Summary

Rewrites the **Email Server** section of the project email settings page
and the managed-domain setup flow. Replaces the dropdown +
conditional-fields layout with a visual four-card picker, a clearer
unsaved-state model, a stepper dialog for managed-domain onboarding, and
a consistent tracked-domains list. Also fixes two data-correctness bugs
in the managed-domain backend.

## Walkthrough (2×, dead-frames trimmed)


![walkthrough](https://raw.githubusercontent.com/stack-auth/stack-auth/pr-assets-email-ui/pr-assets-walkthrough.gif)

## Before

The saved state was a minimal dropdown, but choosing Custom SMTP /
Resend revealed a long conditional form with a hidden gear toggle for
server config, no clear "what is saved" signal, and a separate dialog
pattern for managed domains.

| Saved (Managed) | Custom SMTP selected |
|---|---|
|
![before-managed](https://raw.githubusercontent.com/stack-auth/stack-auth/pr-assets-email-ui/pr-assets-01-before-shared.png)
|
![before-smtp](https://raw.githubusercontent.com/stack-auth/stack-auth/pr-assets-email-ui/pr-assets-02-before-smtp.png)
|

## After — Provider cards

Four visual cards (Stack Shared, Managed Domain, Resend, Custom SMTP)
with updated copy. The saved provider shows a green **Current** pill;
the card the user is previewing shows an amber dashed **Draft** pill. An
amber unsaved-changes banner appears between the picker and the form
when state diverges from saved, so it is unambiguous that a click is not
yet committed.

| Saved state | Previewing a different provider |
|---|---|
|
![after-saved](https://raw.githubusercontent.com/stack-auth/stack-auth/pr-assets-email-ui/pr-assets-03-after-saved.png)
|
![after-draft](https://raw.githubusercontent.com/stack-auth/stack-auth/pr-assets-email-ui/pr-assets-04-after-draft.png)
|

Copy changes:
- **Stack Shared** — "Only default emails — no custom templates, themes,
or sender identity." (was: "Shared (noreply@stackframe.co)")
- **Managed Domain** — "Bring your own domain. You add DNS records; we
handle signing & delivery." (was: "Managed (via managed domain setup)")
- **Resend** uses the official Resend brand mark (light/dark variants in
`apps/dashboard/public/assets/`)

## After — Managed domain list + stepper dialog

Selecting **Managed Domain** immediately shows the tracked-domain list
with an **Add domain** button. Each row reflects real status (Active /
Verified / Waiting for DNS / Verifying / Failed). Exactly one domain can
be **Active** — the one matching the saved email config; every other
verified/applied domain shows a **Use this domain** button so switching
is always possible.

Adding a domain opens a 3-stage dialog with a horizontal stepper (Verify
is right-aligned for the final step). Stage 2 replaces the old bare
NS-list with a proper **Type / Name / Content** DNS records table with
per-row copy buttons.

| Tracked domains list | DNS records table |
|---|---|
|
![after-list](https://raw.githubusercontent.com/stack-auth/stack-auth/pr-assets-email-ui/pr-assets-05-after-managed-list.png)
|
![after-dns-table](https://raw.githubusercontent.com/stack-auth/stack-auth/pr-assets-email-ui/pr-assets-06-after-dns-table.png)
|

## Bug fixes

- **Backend: applying a managed domain did not demote previously-applied
ones.** Multiple rows could end up with status `APPLIED` even though
only one could be in the saved config. New helper
`demoteOtherAppliedManagedEmailDomains({ tenancyId, keepId })` runs
inside `applyManagedEmailProvider` to demote all other applied rows in
the tenancy back to `VERIFIED` before marking the new one.
- **Frontend: "Use this domain" only appeared for `status ===
verified`.** A domain that had been applied then replaced could never be
re-applied from the UI. Button now appears for any `verified` or
`applied` row that is not currently in use; the **Active** label is
derived from config match instead of DB status.
- **Dev mock onboarding now mirrors production timing.**
`shouldUseMockManagedEmailOnboarding()` used to insert domains as
`verified` synchronously. Now the domain is created as
`pending_verification`, and a fire-and-forget `runAsynchronously(() =>
wait(1000))` updates it to `verified` — mirroring the real Resend
webhook flow so the UI states (pending → verifying → verified) are
exercised in local dev.

## Test plan
- [ ] Cards: clicking each card shows `Draft` pill + amber banner;
Discard restores; Save commits and flips `Current` to the new card
- [ ] Managed: Add domain → stage 1 input → stage 2 DNS table + copy →
Check verification flips to stage 3 → Use this domain sets it Active and
demotes the previously-active domain in the list
- [ ] Managed: clicking **Use this domain** on a non-active verified row
makes it Active and the previously-active row back to Verified
- [ ] Shared / Resend / SMTP: existing save + test-email flows still
work (logic preserved verbatim)
- [ ] `pnpm typecheck` (dashboard + backend) and `pnpm lint` pass

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Redesigned email domain setup flow with multi-step verification dialog
  * Added copy-to-clipboard for DNS records
* Enhanced provider selection interface with improved visual
presentation
* Onboarding now shows initial "pending verification" state and
completes verification asynchronously

* **Bug Fixes**
* Ensures only one managed domain becomes active when applying a domain
  * Improved error handling for email configuration saves

* **Tests**
  * Updated end-to-end tests to reflect async verification timing
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-04-24 13:35:03 -07:00
BilalG1
982b8fb2d9
Simplify sign-up rules tester dialog (#1369)
## Summary

The sign-up rules tester dialog was dense and hard to parse: a
two-column layout crammed 8 input fields against 4 stacked result panels
(Outcome, Triggered rules, Evaluation trace, Normalized context), and
used technical jargon ("Turnstile override", "Normalized context",
"Evaluation trace") without much hierarchy. This PR reworks it around
the user's actual question — *"will this sign-up be allowed?"* — and
moves the entrypoint somewhere more discoverable.

## What changed

### 1. Dialog UI — essentials-first layout
- Only **Email** and **Sign-up method** are shown upfront.
- Everything else (OAuth provider, Country, Bot / free-trial-abuse
scores, Turnstile) is hidden behind a single **Advanced options**
collapsible panel. The label previews what's inside, so users know when
they need to expand it.
- Results are outcome-first: a large green/red hero card with a check/X
icon and a plain-English decision ("Sign-up would be allowed"). Matched
rules and resolved context are tucked into `<details>` sections below.
- Removed the "Fill out the form above…" placeholder — it added clutter
without adding info.

### 2. Loading → result transition
- The outcome card now mounts **immediately** when Run test is clicked.
While the request is in flight it shows a neutral gray card with a
spinning `CircleNotchIcon` and "Running test…".
- When the result arrives, the card's border/background transitions over
500ms to green or red, the spinner fades out, and the check/X fades in.
Matched rules and resolved context slide down underneath via a
`grid-rows-[0fr→1fr]` animation.

### 3. Entry-point moved to the page header
- "Open tester" now sits **next to Add rule** in the header (secondary
variant, same size).
- Removed the dedicated "Test rules" card at the bottom of the page — it
was using real estate for something a button can do.

### 4. Code cleanup
- Dropped three exploratory variants (wizard, inspector, the original
complex card) that were temporarily in the file during design
exploration.
- Extracted `useTestRulesState()` to encapsulate state + API call, so
the card is purely presentational.

## Why

The tester is an admin-only debugging tool, so it lives or dies by how
fast someone can glance at it and answer *"would this sign-up go
through?"*. The old dialog asked readers to visually parse two columns
and seven fields just to find the outcome. The new layout answers that
question in the first card.

## Walkthrough


![walkthrough](https://gist.githubusercontent.com/BilalG1/67639d1590ac172880dc705a027560d3/raw/tester-flow.gif)

21s demo (2x speed): page → open tester → type email → Run test →
loading spinner transitions into the green decision card.
[Download
MP4](https://gist.githubusercontent.com/BilalG1/67639d1590ac172880dc705a027560d3/raw/tester-flow.mp4)
· [Gist with all
media](https://gist.github.com/BilalG1/67639d1590ac172880dc705a027560d3)

## Before / After

### Original tester

![before](https://gist.githubusercontent.com/BilalG1/67639d1590ac172880dc705a027560d3/raw/before-original.png)

### New header layout
"Open tester" next to "Add rule"; no more bottom card.
![after
header](https://gist.githubusercontent.com/BilalG1/67639d1590ac172880dc705a027560d3/raw/after-header-buttons.png)

### New tester dialog — initial
Just Email + Sign-up method. Advanced options collapsed.
![after
initial](https://gist.githubusercontent.com/BilalG1/67639d1590ac172880dc705a027560d3/raw/after-dialog-initial.png)

### New tester dialog — mid-run (loading)
Outcome card mounts with a spinner while the request is in-flight.
![after
loading](https://gist.githubusercontent.com/BilalG1/67639d1590ac172880dc705a027560d3/raw/after-dialog-loading.png)

### New tester dialog — result
Outcome hero transitions to green; matched rules + resolved context
collapsibles underneath.
![after
results](https://gist.githubusercontent.com/BilalG1/67639d1590ac172880dc705a027560d3/raw/after-dialog-results.png)

## Test plan

- [x] `pnpm typecheck` (dashboard) passes
- [x] `pnpm lint` (dashboard) passes
- [x] Manually exercised the tester against a configured rule
(`emailDomain.endsWith("tempmail.com")`) with Advanced options both open
and closed
- [x] Verified the loading → green/red transition under artificial
latency (1.2s)
- [x] Verified the "Open tester" button sits next to "Add rule" and the
bottom card is gone

## Scope notes

- No backend, schema, or API changes. Only touches
`apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/sign-up-rules/page-client.tsx`.
- The existing analytics / trigger-history / rule-editor code is
untouched.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

## Release Notes

* **New Features**
  * Advanced testing options now available in a collapsible panel
* Enhanced test results visualization with detailed rule evaluation
display

* **UI/UX Improvements**
  * Test trigger button relocated to main action area
  * Larger, repositioned "Run test" button
* Reorganized results display with collapsible sections for rules and
context details

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Bilal Godil <bilal@stack-auth.com>
2026-04-24 11:35:47 -07:00
BilalG1
94541c4a94
fix(dashboard): Restricted row styling + Replays empty state (#1366)
## Summary

Two small UI polish fixes in `apps/dashboard`:

1. **User detail page** — the **Restricted** field now visually matches
its sibling fields (`User ID`, `Display name`, `Primary email`, etc.) by
reusing the same input-box appearance (`rounded-xl` border, ring,
shadow, `h-8`). Previously it rendered as a bare button with
`rounded-md` hover styling, which looked out of place in the user
details grid.
2. **Analytics → Replays page** — the empty state previously read just
*"No session replays yet"* with no guidance. It now shows a short
description of what session replays are, and links out to the docs
(`https://docs.stack-auth.com/docs/apps/analytics`) so new users can
discover more.

## Files changed

-
[`apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/users/[userId]/page-client.tsx`](https://github.com/stack-auth/stack-auth/blob/fix/ui-bugs-users-analytics/apps/dashboard/src/app/%28main%29/%28protected%29/projects/%5BprojectId%5D/users/%5BuserId%5D/page-client.tsx)
— `RestrictedStatusRow` button now styled to mirror the read-only
`EditableInput` look.
-
[`apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/replays/page-client.tsx`](https://github.com/stack-auth/stack-auth/blob/fix/ui-bugs-users-analytics/apps/dashboard/src/app/%28main%29/%28protected%29/projects/%5BprojectId%5D/analytics/replays/page-client.tsx)
— empty state now includes a description and a `StyledLink` to the docs.

---

## Bug 1 — Restricted row no longer visually orphaned

Before, the *Restricted* row's value (`No`) was just plain text inside
the grid; every other row (User ID, Display name, Primary email,
Password, 2-factor auth, Signed up at, Risk scores, Sign-up country
code) was rendered inside a styled input box. After the fix,
*Restricted* uses the same boxed style — the row is still clickable and
still opens the existing restriction dialog.

### Before / after toggle (full page)

![user-detail
toggle](https://gist.githubusercontent.com/BilalG1/eb9ca0eeec88357728127fd4d759fa17/raw/user_detail_toggle.gif)

### Cropped view of the changed region (clearer)

![user-detail crop
toggle](https://gist.githubusercontent.com/BilalG1/eb9ca0eeec88357728127fd4d759fa17/raw/user_detail_crop_toggle.gif)

### Wipe transition

![user-detail
wipe](https://gist.githubusercontent.com/BilalG1/eb9ca0eeec88357728127fd4d759fa17/raw/user_detail_wipe.gif)

### Fade transition

![user-detail
fade](https://gist.githubusercontent.com/BilalG1/eb9ca0eeec88357728127fd4d759fa17/raw/user_detail_fade.gif)

### Pixel diff (only the Restricted cell changes)

![user-detail pixel
diff](https://gist.githubusercontent.com/BilalG1/eb9ca0eeec88357728127fd4d759fa17/raw/user_detail_pixel_diff.png)

---

## Bug 2 — Replays empty state explains itself

Before, an empty replays workspace showed only *"No session replays
yet"*. Users had no signal that there is anything they need to do, or
where to look. After the fix, the empty state explains what session
replays are, hints that replays will appear once captured, and links to
the relevant docs page.

> Session replays let you watch how users interact with your app.
Replays will appear here once your project starts capturing them.
>
> [Learn more in the
docs](https://docs.stack-auth.com/docs/apps/analytics)

### Before / after toggle (full page)

![replays
toggle](https://gist.githubusercontent.com/BilalG1/eb9ca0eeec88357728127fd4d759fa17/raw/replays_toggle.gif?v=2)

### Cropped view of the empty state

![replays crop
toggle](https://gist.githubusercontent.com/BilalG1/eb9ca0eeec88357728127fd4d759fa17/raw/replays_crop_toggle.gif?v=2)

### Wipe transition

![replays
wipe](https://gist.githubusercontent.com/BilalG1/eb9ca0eeec88357728127fd4d759fa17/raw/replays_wipe.gif?v=2)

### Fade transition

![replays
fade](https://gist.githubusercontent.com/BilalG1/eb9ca0eeec88357728127fd4d759fa17/raw/replays_fade.gif?v=2)

### Pixel diff

![replays pixel
diff](https://gist.githubusercontent.com/BilalG1/eb9ca0eeec88357728127fd4d759fa17/raw/replays_pixel_diff.png?v=2)

---

## Test plan

- [x] `pnpm --filter @stackframe/dashboard run lint` passes
- [x] `pnpm --filter @stackframe/dashboard run typecheck` passes
- [x] Manual verification on `localhost:8101`:
- [x] User detail page renders Restricted with the same input-box style
as siblings
  - [x] Clicking Restricted still opens the existing restriction dialog
  - [x] Replays empty state shows description + working docs link
- [x] Light mode visually verified (dark mode untouched, classes are
dark-mode-aware)

## Notes for reviewers

- No change to `RestrictionDialog`, `getRestrictionReasonText`, or any
restriction logic — this is purely visual.
- The replays empty-state copy keeps the existing `MonitorPlayIcon` and
centered layout; only added the description paragraph and the
`StyledLink` (which is already imported in this file).
- Comparison assets (toggles / fades / wipes / pixel diffs) are hosted
in [this
gist](https://gist.github.com/BilalG1/eb9ca0eeec88357728127fd4d759fa17)
for reference.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Style**
* Improved analytics empty state: centered, constrained layout; clearer
primary text, added muted secondary explanatory copy and an external
documentation link that opens in a new tab.
* Restyled restricted-user control: refreshed appearance and spacing,
truncation for long values, and stronger hover/focus feedback while
preserving existing behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-04-22 17:42:39 -07:00
BilalG1
0532a18c36
fix(dashboard): wrap "Block new purchases" toggle in a Card (#1364)
## Summary

The **Block new purchases** toggle on the Payments → Settings page was
visually out of place: it rendered as a bare `SettingSwitch` outside the
`max-w-3xl` settings column, while every neighboring setting (Stripe
Connection, Test Mode, Payment Methods, Platform-Managed Methods) was a
full-width `Card`.

This PR wraps it in a `Card` that matches the existing `TestModeToggle`
pattern so it inherits the same width constraint, border, padding,
title/description structure, and state-colored icon badge.

**File changed:**
[`apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/settings/page-client.tsx`](https://github.com/stack-auth/stack-auth/blob/fix/payments-block-new-purchases-card/apps/dashboard/src/app/(main)/(protected)/projects/%5BprojectId%5D/payments/settings/page-client.tsx)

## What was wrong

Two concrete mismatches with the rest of the page:

1. **Wrong container.** The `SettingSwitch` was a direct child of
`<PageLayout>` rather than the `<div className="space-y-6 max-w-3xl">`
column that wraps the other settings — so it stretched to the full page
width instead of the 3xl column and broke the vertical rhythm (no
consistent `space-y-6` gap from the card above).
2. **Wrong style primitive.** It used the bare `SettingSwitch` row
component instead of a `Card` +
`CardHeader`/`CardTitle`/`CardDescription`/`CardContent` structure — so
there was no border, no heading hierarchy, and no state-colored icon
badge, which every other setting on the page has.

## Fix

- Moved the block inside the `space-y-6 max-w-3xl` column so it's
constrained and spaced like its siblings.
- Replaced the `SettingSwitch` with a `Card` mirroring `TestModeToggle`:
- `CardHeader` with `CardTitle` (\"Block New Purchases\") and
`CardDescription` (\"Stops new checkouts while keeping existing
subscriptions active.\").
- `CardContent` with an icon badge (`ProhibitIcon`) that turns red when
blocking is active, plus a short \"Block new purchases\" label and the
`Switch`.
- Copy is intentionally minimal: one title, one sentence of description,
one label next to the switch. No two-state narration.

## Visual comparison

### Pixel diff (changed pixels tinted red over the after image)
4.7% of pixels changed, all concentrated in the bottom of the settings
column — everything else is pixel-identical, confirming the fix is
scoped.

![pixel
diff](https://gist.githubusercontent.com/BilalG1/faacb21aea28bc6acae0f527f232c38c/raw/compare_pixel_diff.png)

### Cropped before/after toggle (zoomed to the changed region)
Full-viewport comparisons are noisy when the delta is a single component
at the bottom. This one is cropped to the changed bbox so the card fix
is the whole frame — 1s before, 1s after, looped.

![crop
toggle](https://gist.githubusercontent.com/BilalG1/faacb21aea28bc6acae0f527f232c38c/raw/compare_crop_toggle.gif)

### Wipe reveal (before on the left, after swept in from the left)
A vertical red sweeps across the full page, revealing the after state
over the before state. Useful for spotting any unintended drift
elsewhere on the page (there is none).


![wipe](https://gist.githubusercontent.com/BilalG1/faacb21aea28bc6acae0f527f232c38c/raw/compare_wipe.gif)

## Test plan

- [ ] Open `/projects/<id>/payments/settings` in the dashboard.
- [ ] Verify \"Block New Purchases\" renders as a `Card` with the same
width as Stripe Connection / Test Mode / Payment Methods.
- [ ] Toggle the switch on — icon badge turns red, config write fires
(`payments.blockNewPurchases = true`, `pushable: true`).
- [ ] Toggle off — icon returns to muted gray, config write fires with
`false`.
- [ ] Reload the page and confirm the persisted state matches the
toggle.
- [ ] `pnpm lint` and `pnpm typecheck` pass.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Improvements**
* Redesigned the "Block New Purchases" toggle in payment settings with a
new card-based interface and visual prohibit indicator for improved
clarity and user experience.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-04-22 17:28:09 -07:00
BilalG1
4f198bd55b
Fix dashboard UI bugs: webhook detail crash and http domain silent https upgrade (#1362)
## Summary

Fixes two dashboard UI bugs surfaced while auditing the project area for
large user-visible issues:

1. **Webhook detail page completely broken** — the page shows a blank
screen because the SvixProvider token was being set to the string
`"[object Object]"`.
2. **Editing a trusted domain with an `http://` base URL silently
upgrades it to `https://`** — saving the edit dialog without changing
anything changes the protocol, breaking callbacks to the original host.

Both are corrected with minimal, targeted changes in the dashboard app.
No API, schema, or shared package changes are required.

---

## Bug 1 — Webhook detail page crashes because `svixToken + ''` yields
`"[object Object]"`

### Where


`apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/webhooks/[endpointId]/page-client.tsx`

### Root cause

`stackAdminApp.useSvixToken()` returns an object of shape `{ token:
string, url: string | null }` (see
`packages/template/src/lib/stack-app/apps/implementations/admin-app-impl.ts`).
The page was doing:

```ts
const svixToken = stackAdminApp.useSvixToken();
const [updateCounter, setUpdateCounter] = useState(0);

// This is a hack to make sure svix hooks update when content changes
const svixTokenUpdated = useMemo(() => {
  return svixToken + '';
}, [svixToken, updateCounter]);

// …
<SvixProvider token={svixTokenUpdated} …>
```

`svixToken + ''` coerces the object to the string `"[object Object]"`,
which is then passed to `<SvixProvider>` as the auth token. Every nested
Svix hook (`useEndpoint`, `useEndpointSecret`,
`useEndpointMessageAttempts`) authenticates with that bogus token, gets
a `401 {"code":"authentication_failed","detail":"Invalid token"}` from
Svix, and `getSvixResult`
(`apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/webhooks/utils.tsx`)
throws, crashing the page.

Additional notes while in there:
- `setUpdateCounter` was declared but never called anywhere, so the
surrounding `useMemo`/`useState` was dead weight as well as broken.
Removing it removes the dead code too.
- The neighbouring list page (`webhooks/page-client.tsx`) already uses
the correct shape (`svixToken.token`, `svixToken.url`), which is why the
list page rendered correctly while the detail page didn't.

### Fix

Pass `svixToken.token` directly to `<SvixProvider>` and drop the unused
counter/memo.

```ts
export default function PageClient(props: { endpointId: string }) {
  const stackAdminApp = useAdminApp();
  const svixToken = stackAdminApp.useSvixToken();

  return (
    <AppEnabledGuard appId="webhooks">
      <SvixProvider
        token={svixToken.token}
        appId={stackAdminApp.projectId}
        options={{ serverUrl: getPublicEnvVar('NEXT_PUBLIC_STACK_SVIX_SERVER_URL') }}
      >
        <PageInner endpointId={props.endpointId} />
      </SvixProvider>
    </AppEnabledGuard>
  );
}
```

### Reproduction (before fix)

1. Enable the Webhooks app on a project.
2. Create an endpoint with any URL.
3. Open the row's action menu and click **View Details**.
4. The page renders blank (Svix hooks throw 401 Invalid token; the error
boundary unmounts the detail tree). URL, Description, Verification
Secret, and Events History never appear.

### Before / After

| Before | After |
| --- | --- |
| ![Webhook detail blank before
fix](https://gist.githubusercontent.com/BilalG1/f31b7631cb914ea8fd0113b97d26319e/raw/bug1-webhook-detail-before.png)
| ![Webhook detail renders after
fix](https://gist.githubusercontent.com/BilalG1/f31b7631cb914ea8fd0113b97d26319e/raw/bug1-webhook-detail-after.png)
|

---

## Bug 2 — Editing an `http://` trusted domain silently upgrades it to
`https://`

### Where


`apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/domains/page-client.tsx`

### Root cause

In `EditDialog`, the form's `defaultValues` always set `insecureHttp:
false`, regardless of the protocol of the domain being edited:

```ts
defaultValues={{
  addWww: props.type === 'create',
  domain: props.type === 'update' ? props.defaultDomain.replace(/^https?:\/\//, "") : undefined,
  handlerPath: props.type === 'update' ? props.defaultHandlerPath : "/handler",
  insecureHttp: false, // ← ignores the existing protocol
}}
```

The `domain` field strips `http(s)://` for display but the protocol
itself is only tracked through the `insecureHttp` switch, which lives
inside the collapsed-by-default **Advanced** accordion. On submit:

```ts
const protocol = values.insecureHttp ? 'http://' : 'https://';
const baseUrl = protocol + values.domain;
```

So an `http://myapp.test` entry reopens with `insecureHttp: false`, the
Advanced section stays collapsed, the user sees nothing wrong, and
hitting **Save** (even with zero visible changes) writes
`https://myapp.test` back to config. Existing redirects from SSO / email
verification flows that depend on the original `http://` host stop
working.

### Fix

Derive `insecureHttp` from the existing `defaultDomain` when editing:

```ts
insecureHttp: props.type === 'update' ? props.defaultDomain.startsWith('http://') : false,
```

This makes the switch in the Advanced panel pre-check itself correctly
and the submit path emits the preserved protocol.

### Reproduction (before fix)

1. Go to **Project Settings → Trusted Domains**.
2. Add a new domain, expand **Advanced**, toggle **Use HTTP instead of
HTTPS** on, enter `myapp.test`, click **Create**. The list now shows
`http://myapp.test`.
3. Click the row's **⋯ → Edit**, then **Save** without changing
anything.
4. Observe the list now shows `https://myapp.test`.

### Before / After

**Domain list after an edit+save:**

| Before (http silently became https) | After (http preserved) |
| --- | --- |
| ![Domain list
before](https://gist.githubusercontent.com/BilalG1/f31b7631cb914ea8fd0113b97d26319e/raw/bug4-domain-list-before.png)
| ![Domain list
after](https://gist.githubusercontent.com/BilalG1/f31b7631cb914ea8fd0113b97d26319e/raw/bug4-domain-list-after.png)
|

In the "before" screenshot, `http://myapp.test` was edited with no
changes and silently became `https://myapp.test`.
`http://www.myapp.test` (not edited) stayed `http://`, confirming the
bug is triggered only through the edit-save path.

**Edit dialog (Advanced expanded):**

| Before (HTTP switch always off) | After (reflects stored protocol) |
| --- | --- |
| ![Edit dialog
before](https://gist.githubusercontent.com/BilalG1/f31b7631cb914ea8fd0113b97d26319e/raw/bug4-edit-dialog-before.png)
| ![Edit dialog
after](https://gist.githubusercontent.com/BilalG1/f31b7631cb914ea8fd0113b97d26319e/raw/bug4-edit-dialog-after.png)
|

The "after" dialog also shows the protocol prefix label flip from
`https://` to `http://` next to the input — a second visual cue that the
user is editing an HTTP domain.

---

## Scope / out of scope

In scope here:
- The two fixes above, plus a small amount of dead-code cleanup adjacent
to the first fix (the unused `updateCounter` / `useMemo` hack).

Intentionally **not** included (tracked separately from the same audit —
see internal notes):
- Cursor pagination cache wipe across Users/Teams/Transactions tables
(`data-table/common/cursor-pagination.tsx`)
- Email Outbox "Scheduled At" input being reset on every keystroke and
rendered in the wrong timezone (`email-outbox/page-client.tsx`)
- Latent empty-group handling in the sign-up rule builder (validator +
CEL emitter), which is real in code but not currently reachable through
the editor UI

These are broader and deserve their own PRs.

## Test plan

- [ ] **Bug 1 (webhook detail):** Enable Webhooks on a project, create
an endpoint, open **View Details**. Confirm URL, Description,
Verification Secret, and Events History render (no 401s in the console,
no blank page). Confirm the Copy button on the verification secret still
copies the key.
- [ ] **Bug 2 (domain edit preserves http):** Add an `http://` trusted
domain. Edit it and save with no changes — list should still show
`http://`. Edit again, flip the Advanced switch to HTTPS, save — list
should show `https://`. Repeat with the inverse direction (start https,
flip to http).
- [ ] **Regression sweep:** Webhooks list page, create/delete endpoint,
copy signing secret; Trusted Domains add/delete; auth-methods callbacks
against an `http://localhost` domain continue to work.
- [ ] `pnpm typecheck` passes locally. (`pnpm lint` was also run against
the dashboard app and is clean.)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
* Domain editing now correctly initializes and preserves the protocol
type (HTTP or HTTPS) based on the existing domain configuration.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-04-22 17:27:37 -07:00
Konstantin Wohlwend
3ea8052d35 chore: update package versions 2026-04-20 19:06:56 -07:00
BilalG1
6bc1836e66
fix(dashboard): resolve UI issues across email-* pages (#1345)
## Summary

Six UI issues found across the email-* dashboard pages, ranked by
impact, fixed here:

1. **email-sent layout** — the email log table and domain reputation
card were forced side-by-side at all widths. A fixed-width sidebar plus
a flex-1 table meant that on tablet the table got crushed, and on mobile
the row overflowed horizontally. Fix: stack vertically below `lg`, and
let the reputation card span full width on narrow viewports.
2. **Domain status enum leaks to the UI** — `<span>Status:
{domain.status}</span>` rendered raw values like `pending_dns` /
`pending_verification`. Added a `MANAGED_DOMAIN_STATUS_LABELS` map and
route through it before rendering.
3. **email-themes dialog grid cramped on mobile** — the Change Theme
dialog hardcoded `grid-cols-2`, so at 375px each theme card had ~150px
and the preview images were illegible. Changed to `grid-cols-1
sm:grid-cols-2`.
4. **Template name row overflow** — long template names pushed the Edit
Template button off the right edge of the card because the flex row had
no `min-w-0` / `truncate`. Fixed both, and made the action column
`shrink-0`.
5. **Boosted-capacity label was color-only** — during an active boost
the label used a red strikethrough for the base value and a blue number
for the boosted value with no non-color cue. Added an explicit `→` arrow
between the two numbers, `title` tooltips on each, and a visible
\"(boosted)\" marker after `/h max`.
6. **Draft progress bar overflowed at mobile width** — the 4-step
progress bar used fixed 80px connectors, giving a minimum width of
~400px that clipped off both ends at 375px. Changed connectors to `w-8
sm:w-20` (32px on mobile, 80px otherwise) so all four steps and their
labels fit below 640px.

## Before / after

Each GIF below loops \"before\" (1s) → \"after\" (1s) with a red pill in
the top-right indicating which frame is which. Full-size stills (before
+ after + extra viewports) are listed under **All screenshots** at the
bottom.

### 1. email-sent — two-column layout collapses on narrow viewports

Mobile (375px):

![email-sent
mobile](https://gist.githubusercontent.com/BilalG1/edb04740a19c3f2d048da6e602209d45/raw/gif-01-email-sent-mobile.gif)

Tablet (900px):

![email-sent
tablet](https://gist.githubusercontent.com/BilalG1/edb04740a19c3f2d048da6e602209d45/raw/gif-01-email-sent-tablet.gif)

### 2. email-settings — managed-domain status label

![domain
status](https://gist.githubusercontent.com/BilalG1/edb04740a19c3f2d048da6e602209d45/raw/gif-02-domain-status.gif)

### 3. email-themes — Change Theme dialog on mobile

![themes
mobile](https://gist.githubusercontent.com/BilalG1/edb04740a19c3f2d048da6e602209d45/raw/gif-03-themes-mobile.gif)

### 4. email-templates — long name overflow

![templates
overflow](https://gist.githubusercontent.com/BilalG1/edb04740a19c3f2d048da6e602209d45/raw/gif-04-templates-overflow.gif)

### 5. email-sent — boosted capacity label

![capacity
label](https://gist.githubusercontent.com/BilalG1/edb04740a19c3f2d048da6e602209d45/raw/gif-05-capacity-label.gif)

### 7. email-drafts — draft progress bar on mobile

![draft progress
bar](https://gist.githubusercontent.com/BilalG1/edb04740a19c3f2d048da6e602209d45/raw/gif-07-draft-progress-mobile.gif)

## Test plan

- [x] \`pnpm --filter @stackframe/dashboard lint\` — clean
- [x] \`pnpm --filter @stackframe/dashboard typecheck\` — clean
- [x] Manual verification in a browser at 375px / 900px / 1440px, light
+ dark mode, for each fixed page
- [ ] Reviewer sanity check of the remaining email-* pages
(email-outbox, email-viewer) for similar responsive regressions

## Notes

- The initial review flagged a \"white-on-white capacity boost timer\" —
on closer look the label sits on a deliberately dark `bg-zinc-900/0.82`
overlay inside the boost card, so it reads fine in light and dark mode.
Not fixing; that part of the review was a false positive.
- The initial review also flagged a missing empty state on
email-templates. Because Stack seeds built-in templates, the empty
branch is unreachable in practice — skipping that fix to avoid dead
code.

## All screenshots

Gist with all the individual before/after PNGs and the GIFs themselves:
https://gist.github.com/BilalG1/edb04740a19c3f2d048da6e602209d45

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

## Release Notes

* **New Features**
* Added human-readable status labels for managed domains in domain
settings

* **Improvements**
* Enhanced responsive layouts across dashboard pages for improved mobile
experience
* Improved email capacity display with visual indicators and tooltips
for boost status
* Refined template and theme selection layouts with better text handling
and spacing

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-04-19 22:58:07 -07:00
Konstantin Wohlwend
ac9707b89e Update metrics endpoint to no longer trigger global error boundary on failure
Some checks failed
all-good: Did all the other checks pass? / all-good (push) Has been cancelled
Ensure Prisma migrations are in sync with the schema / check_prisma_migrations (22.x) (push) Has been cancelled
Docker Server Build and Push / Docker Build and Push Server (push) Has been cancelled
Docker Server Build and Run / docker (push) Has been cancelled
Runs E2E API Tests (Local Emulator) / E2E Tests (Local Emulator, Node ${{ matrix.node-version }}) (22.x) (push) Has been cancelled
Runs E2E API Tests / E2E Tests (Node ${{ matrix.node-version }}, Freestyle ${{ matrix.freestyle-mode }}) (mock, 22.x) (push) Has been cancelled
Runs E2E API Tests / E2E Tests (Node ${{ matrix.node-version }}, Freestyle ${{ matrix.freestyle-mode }}) (prod, 22.x) (push) Has been cancelled
Runs E2E API Tests with custom port prefix / build (22.x) (push) Has been cancelled
Runs E2E Fallback Tests / E2E Fallback Tests (Node ${{ matrix.node-version }}) (22.x) (push) Has been cancelled
Lint & build / lint_and_build (24) (push) Has been cancelled
Mirror main branch to main-mirror-for-wdb / lint_and_build (push) Has been cancelled
Publish npm packages / publish (push) Has been cancelled
Publish Swift SDK to prerelease repo / publish (push) Has been cancelled
Sync Main to Dev / sync-commits (push) Has been cancelled
TOC Generator / TOC Generator (push) Has been cancelled
2026-04-18 19:08:52 -07:00
Konstantin Wohlwend
8046a7dd8f Fix dashboard sidebar hover states 2026-04-18 16:18:55 -07:00
Konstantin Wohlwend
2e247dd06d Improve dashboard sidebar styling 2026-04-18 14:54:40 -07:00
Konstantin Wohlwend
91fbf63f7f chore: update package versions 2026-04-18 14:20:39 -07:00
Konstantin Wohlwend
22ae47fe73 Replace Cmd with Ctrl on Windows computers 2026-04-17 17:04:30 -07:00
BilalG1
8af48c1e94
fix(dashboard): correct keyboard shortcut display and HTML entity rendering (#1342)
## Summary

Two small UI bugs found while auditing `apps/dashboard` for visible
defects.

### 1. Dashboards empty state hardcoded `Cmd+K`


`apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/dashboards/page-client.tsx:80`

The empty state copy referenced the command palette as `Cmd+K`. The rest
of the dashboard renders the shortcut as the `⌘ K` keycap (see
`cmdk-search.tsx:1062`), so this one string was inconsistent. Replaced
with `⌘ K` to match the convention.

**Before/after flicker:**

![bug 5
flicker](https://gist.githubusercontent.com/BilalG1/adf11369b93cf280e1af49428a5b4f89/raw/bug5-flicker.gif)

**Pixel diff** — 3,500 diff pixels (0.270%). Changed regions: the "No
dashboards yet" description line (the Cmd+K text) and the "DEV" badge in
the bottom-right.

![bug 5 pixel
diff](https://gist.githubusercontent.com/BilalG1/adf11369b93cf280e1af49428a5b4f89/raw/bug5-pixeldiff.png)

| Before | After |
|---|---|
|
![before](https://gist.githubusercontent.com/BilalG1/adf11369b93cf280e1af49428a5b4f89/raw/before-bug5-cmdk.png)
|
![after](https://gist.githubusercontent.com/BilalG1/adf11369b93cf280e1af49428a5b4f89/raw/after-bug5-cmdk.png)
|

### 2. Vercel page rendered `&apos;` as raw text


`apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/vercel/page-client.tsx:168`,
`:169`, `:414`

Three string literals contained `&apos;`:

```tsx
? "You&apos;ll receive a publishable client key and a secret server key for this project."
: "You&apos;ll receive a secret server key for this project."
…
subtitle="See Vercel&apos;s documentation on environment variables for more details."
```

These are JS strings passed into props, not JSX text nodes — React only
decodes HTML entities in JSX text, so the literal characters `&apos;`
ended up in the DOM. Verified via `document.querySelector` — actual text
content was `You&apos;ll receive a secret server key for this project.`.
Replaced with a plain ASCII apostrophe.

**Before/after flicker:**

![bug 7
flicker](https://gist.githubusercontent.com/BilalG1/adf11369b93cf280e1af49428a5b4f89/raw/bug7-flicker.gif)

**Pixel diff** — 1,252 diff pixels (0.163%). Changed region: the
`You&apos;ll` → `You'll` line.

![bug 7 pixel
diff](https://gist.githubusercontent.com/BilalG1/adf11369b93cf280e1af49428a5b4f89/raw/bug7-pixeldiff.png)

| Before | After |
|---|---|
|
![before](https://gist.githubusercontent.com/BilalG1/adf11369b93cf280e1af49428a5b4f89/raw/before-bug7-apos.png)
|
![after](https://gist.githubusercontent.com/BilalG1/adf11369b93cf280e1af49428a5b4f89/raw/after-bug7-apos.png)
|

## Test plan

- [x] Visited `/projects/<id>/dashboards` with no dashboards — empty
state now reads `(⌘ K)`
- [x] Visited `/projects/<id>/vercel` — both the "API keys generated"
subtitle and the "Need more detail?" subtitle render `'` as a real
apostrophe
- [x] `eslint` clean on both touched files
2026-04-17 14:13:49 -07:00
Konstantin Wohlwend
b5273f7326 Clicking a dashboard category now opens its first page 2026-04-17 12:15:29 -07:00
Armaan Jain
94dd22c1c5
Overview revamp (#1238) 2026-04-15 09:36:00 -07:00
Armaan Jain
654c97c56e
Onboarding redo (#1308) 2026-04-15 09:35:48 -07:00
BilalG1
c66bdfb5ae
Fix five dashboard UI issues (#1337)
## Summary

Fixes five independent UI bugs in the dashboard. Each is a narrow,
localized fix — no changes to shared table / card primitives.

### 1. Auth methods preview didn't update until save
Toggling Email/password, Magic link, or Passkey updated the switch UI
but the right-hand sign-in preview kept rendering the pre-save config
until "Save changes" was clicked. The preview was reading
`project.config` instead of the local pending state.

**Fix:** pass the computed local state (`passwordEnabled`, `otpEnabled`,
`passkeyEnabled`) into `AuthPage`'s `mockProject.config` so the preview
reflects toggles immediately.

| Before | After |
|---|---|
|
![before](b6d4f39f66/01-auth-methods-before.gif)
|
![after](b6d4f39f66/01-auth-methods-after.gif)
|

---

### 2. Email-drafts "New Draft" dropdown items stacked on two rows
Icon rendered above text in the dropdown because the icon was a child of
a non-flex inner wrapper inside `DropdownMenuItem` and phosphor icons
default to `display: block`.

**Fix:** use `DropdownMenuItem`'s built-in `icon` prop (which
absolute-positions the icon) instead of passing it as a child.

| Before | After |
|---|---|
|
![before](b6d4f39f66/02-email-drafts-before.png)
|
![after](b6d4f39f66/02-email-drafts-after.png)
|

---

### 3. Project-keys status filter: clicking options did nothing visible
`DesignDataTable` renders the toolbar outside the card when
`glassmorphic && !insideDesignCard`. The table instance was captured
once via `onTableReady`; filter clicks updated the table's internal
state (rows actually filtered to "No results") but the toolbar's parent
never re-rendered, so checkboxes, chip count, and button label stayed
frozen.

**Fix:** wrap `InternalApiKeyTable` in `DesignCard` so
`useInsideDesignCard()` returns true, `needsOwnCard` becomes false, and
the toolbar renders inside the `DataTable` where it re-renders normally.
No changes to the shared `DesignDataTable` component.

| Before | After |
|---|---|
|
![before](b6d4f39f66/03-project-keys-before.gif)
|
![after](b6d4f39f66/03-project-keys-after.gif)
|

---

### 4. Analytics "Tables" page only listed Events
`AVAILABLE_TABLES` was hardcoded to a single entry.

**Fix:** registered all 12 ClickHouse views that exist in the `default`
schema (events, users, contact_channels, teams, team_member_profiles,
team_permissions, team_invitations, email_outboxes, project_permissions,
notification_preferences, refresh_tokens, connected_accounts) with
sensible default sort columns. Widened `TableId` to `string`.

| Before | After |
|---|---|
|
![before](b6d4f39f66/04-analytics-tables-before.png)
|
![after](b6d4f39f66/04-analytics-tables-after.png)
|

---

### 5. Price input `$` prefix overlapped the number on prod
The Input composed `h-9 px-3 ... pl-7`. In production's CSS bundle order
`.px-3` declared after `.pl-7`, so `padding-left` resolved to 12px —
same as the prefix's `left-3` position — making `$` overlap the first
digit. The emulator's bundle happened to order them the other way, which
is why it only reproduced in prod. Verified with a devtools injection
that mimics the prod CSS ordering.

**Fix:** change `pl-7` → `!pl-7` in `repeating-input.tsx` so the prefix
padding wins regardless of CSS order.

| Before (prod CSS ordering) | After (same ordering) |
|---|---|
|
![before](b6d4f39f66/05-price-overlap-before.png)
|
![after](b6d4f39f66/05-price-overlap-after.png)
|

---

## Test plan

- [x] `pnpm --filter @stackframe/dashboard typecheck`
- [x] `pnpm --filter @stackframe/dashboard lint`
- [x] Manual verification of each issue against the local dev dashboard
at localhost:8101
- [ ] Reviewer: confirm no visual regressions on other `DesignDataTable`
usages (api-key-table is the only one wrapped here)
- [ ] Reviewer: confirm analytics queries on added tables work with the
signed-in user's permissions


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

## Release Notes

* **New Features**
* Added 12 new analytics tables to the dashboard for enhanced data
visibility and tracking.

* **Bug Fixes**
  * Fixed input styling issue with prefix alignment.

* **Style**
* Improved visual presentation of data tables with enhanced card
styling.
  * Refined dropdown menu icon display for better UI consistency.
* Enhanced authentication preview settings to reflect current
configuration state.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-04-14 19:38:52 -07:00
Konstantin Wohlwend
b68710e98e chore: update package versions 2026-04-14 18:06:36 -07:00
BilalG1
88d3317b22
local emulator security and features fixes (#1247)
<!--

Make sure you've read the CONTRIBUTING.md guidelines:
https://github.com/stack-auth/stack-auth/blob/dev/CONTRIBUTING.md

-->


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

## Release Notes

* **New Features**
* Added Stripe, OAuth, and Freestyle mock services to the local emulator
* Introduced `emulator run` CLI command to execute applications with
emulator credentials automatically injected
  * Enhanced credential management for local development

* **Improvements**
  * Improved ARM64 QEMU emulation with cross-architecture support
  * Better error detection and logging during emulator provisioning
  * Added example middleware configuration with authentication support
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-04-14 15:36:24 -07:00
Konstantin Wohlwend
e68015909d Fix lint 2026-04-14 13:43:33 -07:00
Konstantin Wohlwend
7f9eac40c5 Downgrade Next.js to 16.1.7 2026-04-14 12:39:55 -07:00
Konstantin Wohlwend
7caff35ba3 Fix lint 2026-04-14 09:19:18 -07:00
Konstantin Wohlwend
0dac3dba58 Upgrade to Next.js 16.2 2026-04-14 02:30:24 -07:00
Konstantin Wohlwend
f78b60bba2 chore: update package versions
Some checks failed
all-good: Did all the other checks pass? / all-good (push) Has been cancelled
Ensure Prisma migrations are in sync with the schema / check_prisma_migrations (22.x) (push) Has been cancelled
Docker Server Build and Push / Docker Build and Push Server (push) Has been cancelled
Docker Server Build and Run / docker (push) Has been cancelled
Runs E2E API Tests (Local Emulator) / E2E Tests (Local Emulator, Node ${{ matrix.node-version }}) (22.x) (push) Has been cancelled
Runs E2E API Tests / E2E Tests (Node ${{ matrix.node-version }}, Freestyle ${{ matrix.freestyle-mode }}) (mock, 22.x) (push) Has been cancelled
Runs E2E API Tests / E2E Tests (Node ${{ matrix.node-version }}, Freestyle ${{ matrix.freestyle-mode }}) (prod, 22.x) (push) Has been cancelled
Runs E2E API Tests with custom port prefix / build (22.x) (push) Has been cancelled
Runs E2E Fallback Tests / E2E Fallback Tests (Node ${{ matrix.node-version }}) (22.x) (push) Has been cancelled
Lint & build / lint_and_build (24) (push) Has been cancelled
Mirror main branch to main-mirror-for-wdb / lint_and_build (push) Has been cancelled
Publish npm packages / publish (push) Has been cancelled
Publish Swift SDK to prerelease repo / publish (push) Has been cancelled
Sync Main to Dev / sync-commits (push) Has been cancelled
TOC Generator / TOC Generator (push) Has been cancelled
2026-04-13 19:29:35 -07:00
Mantra
55b14bb409
dev tool indicator (#1272)
- Updated package versions for '@supabase/*' libraries to 2.99.2 and
'@supabase/ssr' to 0.9.0.
- Added new devDependencies for 'rimraf' and 'framer-motion' in the
pnpm-lock file.
- Modified Next.js configuration to conditionally omit 'X-Frame-Options'
in development mode for better integration with Stack Auth dev tools.
- Refactored component exports in the template package to include
tracking for dev tools.
- Introduced new dev tool components and context for improved logging
and state management.
- Added styles for the dev tool indicator and panel, ensuring a
consistent dark theme.
- Implemented fetch interception to log API calls and user
authentication events in the dev tool.

<!--

Make sure you've read the CONTRIBUTING.md guidelines:
https://github.com/stack-auth/stack-auth/blob/dev/CONTRIBUTING.md

-->


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

## Release Notes

* **New Features**
* Added comprehensive Developer Tools interface with tabs for Overview,
Components, AI Chat, Console, Dashboard, and Support.
* Integrated AI Chat assistant within Developer Tools for enhanced
debugging.
  * Added component version tracking and update notifications.
  * Implemented API request logging and event monitoring.
* Enhanced feedback system with support for bug reports and feature
requests.

* **Bug Fixes**
* Fixed Content Security Policy headers for local development
environments.

* **Dependencies**
  * Added AI SDK integration packages.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Konstantin Wohlwend <n2d4xc@gmail.com>
2026-04-13 17:43:03 -07:00
aadesh18
5573927429
Ask AI Huge Response (#1328)
This PR fixes the bug where analytics tool returns a lot of rows, which
results in huge token count. We do it by checking the number of
characters in the tool call, and if it is more than 50000 characters, we
send an error message rather than the rows and ask the ai to make more
focused queries.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* AI assistant shows friendlier, categorized error messages and captures
unexpected errors for diagnosis.
  * UI now displays classifier-derived, user-friendly AI error text.

* **Bug Fixes & Improvements**
* Enforced a hard size budget for SQL query results and gracefully
handles oversized responses.
* Centralized safer database error messaging to avoid leaking internal
details.
* Strengthened AI guidance to prefer narrower queries, safer column
selection, and pairing GROUP BY with ORDER BY + LIMIT.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-04-13 15:12:07 -07:00
aadesh18
8aa80ceb2c
AI in Stack Companion (#1297)
This PR puts the ask ai functionality into the ai stack companion, along
with persistent history.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* "Ask AI" chat sidebar with streaming assistant responses, progressive
word-by-word reveal, auto-scroll, Enter-to-send and Arrow-key
navigation, "Thinking…" and error indicators
* Chat UI primitives: inline/code blocks, smart links, copy-to-clipboard
for code/URLs, and expandable tool-result cards with copyable outputs

* **Bug Fixes**
* Prevented button/menu clicks inside list items from bubbling to parent
row handlers

* **Refactor**
* Chat rendering, streaming, parsing, and UI helpers consolidated into a
shared module and integrated into the sidebar widget
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Konsti Wohlwend <n2d4xc@gmail.com>
2026-04-13 18:40:32 +00:00
Konstantin Wohlwend
7fb660649d chore: update package versions 2026-04-13 11:31:28 -07:00
Konstantin Wohlwend
27cd8bf56b chore: update package versions 2026-04-09 13:36:23 -07:00
Konstantin Wohlwend
5f4233ec8a Add a dialog with sign-up rule trigger history 2026-04-09 11:55:26 -07:00
Konstantin Wohlwend
1b3e7f5ba2 Fix Vercel integration when publishable client keys are missing 2026-04-08 17:26:50 -07:00
aadesh18
a0710f8807
fixed delete bug and removed console statements (#1313) 2026-04-08 17:14:30 -07:00
BilalG1
4f99c469fe
stack auth preview mode (#1307)
<!--

Make sure you've read the CONTRIBUTING.md guidelines:
https://github.com/stack-auth/stack-auth/blob/dev/CONTRIBUTING.md

-->


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Preview mode: sandboxed experience with mock projects, placeholder
data, and disabled external integrations (payments, webhooks, email
rendering, session replays).
* One-click preview project creation and automatic preview sign-in for
quick access.

* **New Features — Walkthrough**
* Interactive guided walkthroughs with spotlight, animated cursor,
step-driven navigation, and targeted element hooks.

* **Style**
* UI/UX adjustments for preview: theme behavior, conditional
banners/alerts, informational alerts, and walkthrough attributes added
across pages.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-04-08 16:57:42 -07:00
BilalG1
8857dbaa48
clickhouse new syncs and verify-data (#1304)
<!--

Make sure you've read the CONTRIBUTING.md guidelines:
https://github.com/stack-auth/stack-auth/blob/dev/CONTRIBUTING.md

-->


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* External DB sync now covers teams, team members, permissions,
invitations, email outbox, session replays, refresh tokens, and
connected accounts.
* New sequence ID fields and automatic change-flagging added to many
record types to enable incremental sync.

* **Improvements**
* Added concurrent indexes, faster/parallelized sync pipelines,
verification tooling, and richer observability.
* Dashboard sequencer stats expanded and end-to-end sync tests
significantly extended.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-04-08 14:43:22 -07:00
Konstantin Wohlwend
b7f5687d88 Add Mintlify docs to pnpm run dev 2026-04-06 13:47:53 -07:00
Konstantin Wohlwend
add0d56be0 More CMD+K actions 2026-04-06 09:12:14 -07:00
Konstantin Wohlwend
9b1284dc9e Fraud Protection sub-app 2026-04-05 21:35:01 -07:00
Mantra
ce49eae155
emu with a q stuff (#1266)
Some checks failed
all-good: Did all the other checks pass? / all-good (push) Has been cancelled
Ensure Prisma migrations are in sync with the schema / check_prisma_migrations (22.x) (push) Has been cancelled
DB migration compat / Check if migrations changed (push) Has been cancelled
Docker Server Build and Push / Docker Build and Push Server (push) Has been cancelled
Docker Server Build and Run / docker (push) Has been cancelled
Runs E2E API Tests (Local Emulator) / E2E Tests (Local Emulator, Node ${{ matrix.node-version }}) (22.x) (push) Has been cancelled
Runs E2E API Tests / E2E Tests (Node ${{ matrix.node-version }}, Freestyle ${{ matrix.freestyle-mode }}) (mock, 22.x) (push) Has been cancelled
Runs E2E API Tests / E2E Tests (Node ${{ matrix.node-version }}, Freestyle ${{ matrix.freestyle-mode }}) (prod, 22.x) (push) Has been cancelled
Runs E2E API Tests with custom port prefix / build (22.x) (push) Has been cancelled
Lint & build / lint_and_build (latest) (push) Has been cancelled
Dev Environment Test With Custom Base Port / restart-dev-and-test-with-custom-base-port (push) Has been cancelled
Dev Environment Test / restart-dev-and-test (push) Has been cancelled
Run setup tests with custom base port / setup-tests-with-custom-base-port (push) Has been cancelled
Run setup tests / setup-tests (push) Has been cancelled
TOC Generator / TOC Generator (push) Has been cancelled
DB migration compat / Back-compat — Current branch migrations with ${{ needs.check-migrations-changed.outputs.base_branch }} branch code (push) Has been cancelled
DB migration compat / Forward-compat — Current branch code with ${{ needs.check-migrations-changed.outputs.base_branch }} branch migrations (push) Has been cancelled
DB migration compat / No migration changes (skipped) (push) Has been cancelled
commit 5d43722575b826a8ed8dbb6b828f48eae4bca02c
Author: mantrakp04 <mantrakp@gmail.com>
Date:   Wed Mar 18 12:27:01 2026 -0700

    Add QEMU emulator snapshot functionality and reset command

- Introduced a new `emulator-qemu:reset` command in package.json to
clear snapshots and force a fresh boot of the emulator.
- Enhanced the `run-emulator.sh` script to support saving and restoring
snapshots, significantly reducing restart time from ~62s to ~4s.
- Implemented logic to check for existing snapshots and restore them
during startup, improving the emulator's efficiency.
- Updated documentation in CLAUDE-KNOWLEDGE.md to explain the new
snapshot restore process and its benefits.

These changes enhance the QEMU emulator's performance and usability for
developers, providing a more efficient workflow during development.

commit 3877445bdd83cb8690da18c8520bf260d2795172
Author: mantrakp04 <mantrakp@gmail.com>
Date:   Wed Mar 18 11:55:18 2026 -0700

    Enhance QEMU emulator performance and configuration management

- Added optimizations to the QEMU emulator's app container startup
process, reducing startup time from ~92s to ~62s by using qcow2 backing
files and setting the working directory to /app.
- Updated the build-image.sh script to conditionally wait for background
processes, improving robustness.
- Modified the run-emulator.sh script to create the disk image using
qcow2 format instead of copying, enhancing efficiency.
- Adjusted the cloud-init user-data to set STACK_RUNTIME_WORK_DIR to
/app, streamlining file operations during container initialization.
- Improved the entrypoint script to avoid unnecessary file copying when
the working directory is set to /app.

These changes significantly enhance the performance and usability of the
QEMU emulator for developers.

commit e0b86d3f1d5c08e46d0d343bc632e2a8c5777845
Author: mantrakp04 <mantrakp@gmail.com>
Date:   Wed Mar 18 11:07:55 2026 -0700

Refactor local emulator configuration management and enhance Docker
setup

- Removed redundant comments and improved code clarity in the local
emulator's route handling.
- Streamlined the Dockerfile and docker-compose.yaml for better
readability and maintenance.
- Updated entrypoint and initialization scripts to enhance service
startup processes.
- Introduced a new common script for QEMU emulator to centralize
architecture detection and firmware handling.
- Enhanced error handling in the host file bridge for improved
robustness.
    - Removed obsolete country code utilities to clean up the codebase.

These changes significantly improve the local emulator's configuration
management and overall setup experience for developers.

commit 4fb0f93c6cc4f749a14acf0228c261e180875609
Author: mantrakp04 <mantrakp@gmail.com>
Date:   Wed Mar 18 10:24:53 2026 -0700

Implement local emulator file bridge for enhanced configuration
management

- Introduced a new host file bridge to facilitate reading and writing
configuration files between the local emulator and the host system.
- Refactored the local-emulator module to utilize the file bridge for
file operations, improving error handling and response validation.
- Added tests to ensure the file bridge functionality works as expected,
including handling of non-existent files and writing configurations.
- Updated the run-emulator script to start the file bridge
automatically, ensuring seamless integration during emulator startup.
- Enhanced documentation to reflect the new file bridge capabilities and
usage instructions.

These changes significantly improve the local emulator's ability to
manage configuration files, enhancing the development experience.

commit 3d18a7ce5bbf00a62a40a3f48f27856e79ecc62f
Author: mantrakp04 <mantrakp@gmail.com>
Date:   Tue Mar 17 22:36:46 2026 -0700

    Refactor QEMU local emulator setup and enhance app bundle handling

- Introduced a new script for packaging Docker images into a compressed
app bundle, improving the emulator's deployment process.
- Updated build-image.sh to create a runtime configuration ISO, ensuring
better management of environment settings.
- Enhanced cloud-init user-data scripts for both dev-server and deps
guests, streamlining service setup and configuration.
- Improved the run-emulator.sh script to facilitate better handling of
runtime configurations and dependencies.
- Adjusted the .gitignore to include .DS_Store and removed obsolete
entries, cleaning up the repository.

These changes significantly enhance the local emulator's functionality
and reliability for developers.

commit 8a35fb1ce79898d73e2259e256c11b6fd9b0a584
Author: mantrakp04 <mantrakp@gmail.com>
Date:   Tue Mar 17 21:52:24 2026 -0700

    Enhance local emulator functionality and configuration

- Updated package.json to improve the start-emulator command, providing
clearer dashboard and backend URLs.
- Added a new wait-until-emulator-is-ready command to ensure the
emulator is fully operational before proceeding.
- Refactored the local-emulator project route to streamline file
existence checks and default config creation.
- Enhanced user guidance in the dashboard for local Stack config file
handling.
- Updated tests to reflect changes in config file handling, ensuring
non-existent files are created with default settings.
- Improved Docker configurations for the local emulator, including new
environment variables and service dependencies.

These changes significantly enhance the local development experience and
emulator reliability.

commit 3910ed4bc40bbb37340c1c316c24c2826ba372bd
Author: mantrakp04 <mantrakp@gmail.com>
Date:   Tue Mar 17 19:59:36 2026 -0700

    Remove unused stash-0.patch file to clean up the repository.

commit 74146d974458037a7a9590120a524629a1a6a162
Author: mantrakp04 <mantrakp@gmail.com>
Date:   Tue Mar 17 19:58:46 2026 -0700

Enhance QEMU local emulator with app bundle support and runtime
configuration

- Introduced a new script to package the backend and dashboard assets
into a standalone app bundle for the QEMU emulator.
- Updated the build-image.sh script to create an ISO containing the app
bundle, ensuring the guest image includes the full runtime.
- Modified cloud-init user-data to handle the new app bundle and runtime
configuration, improving the setup process for local development.
- Enhanced the run-emulator.sh script to prepare and mount the runtime
configuration ISO, facilitating better environment management for the
emulator.
- Updated the user-data to include necessary environment variables for
the stack application, ensuring seamless integration during startup.

These changes significantly improve the local emulator's functionality
and ease of use for developers.

commit 9e865a1cf524398bc58f00e0836278775c4ae936
Author: mantrakp04 <mantrakp@gmail.com>
Date:   Tue Mar 17 16:50:45 2026 -0700

    Enhance local emulator setup with new services and configurations

- Added Docker support for a local emulator, integrating PostgreSQL,
Redis, Inbucket, Svix, ClickHouse, MinIO, and QStash.
- Introduced new scripts for managing the emulator lifecycle, including
build and run commands.
- Implemented cloud-init provisioning for automatic service setup on
first boot.
- Updated package.json with new commands for emulator management and
added dotenv-cli for environment variable management.
    - Added tests for OAuth authorization flow to return JSON responses.
    - Included configuration files for ClickHouse and user management.

This commit significantly improves the local development experience by
providing a comprehensive emulator environment.

<!--

Make sure you've read the CONTRIBUTING.md guidelines:
https://github.com/stack-auth/stack-auth/blob/dev/CONTRIBUTING.md

-->


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

## Release Notes

* **New Features**
* Introduced a local QEMU-based emulator for development with bundled
services (PostgreSQL, Redis, ClickHouse, MinIO, Inbucket, Svix, QStash).
* Added CLI commands to manage the emulator (start, stop, reset, status,
pull images).
  * Added emulator status dashboard to monitor service health.
  * Introduced new configuration system via `stack.config.ts`.

* **Tests**
  * Added configuration read/write tests for the emulator.
  * Added emulator CLI validation tests.

* **Documentation**
  * Added emulator setup and usage guide.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-04-04 00:33:52 +00:00
Konstantin Wohlwend
d3ea2b9001 Add server-side flags for anonymous users 2026-04-03 10:43:34 -07:00
Konstantin Wohlwend
ae3ad74e66 Improve sidebar font weights 2026-04-03 10:22:44 -07:00
Konstantin Wohlwend
87705fbeae Separate Users and Trusted Domains from Authentication app 2026-04-03 10:14:52 -07:00
Konstantin Wohlwend
73f68c831f "Only anonymous" users filter
Some checks failed
all-good: Did all the other checks pass? / all-good (push) Has been cancelled
Ensure Prisma migrations are in sync with the schema / check_prisma_migrations (22.x) (push) Has been cancelled
Docker Server Build and Push / Docker Build and Push Server (push) Has been cancelled
Docker Server Build and Run / docker (push) Has been cancelled
Runs E2E API Tests (Local Emulator) / E2E Tests (Local Emulator, Node ${{ matrix.node-version }}) (22.x) (push) Has been cancelled
Runs E2E API Tests / E2E Tests (Node ${{ matrix.node-version }}, Freestyle ${{ matrix.freestyle-mode }}) (mock, 22.x) (push) Has been cancelled
Runs E2E API Tests / E2E Tests (Node ${{ matrix.node-version }}, Freestyle ${{ matrix.freestyle-mode }}) (prod, 22.x) (push) Has been cancelled
Runs E2E API Tests with custom port prefix / build (22.x) (push) Has been cancelled
Lint & build / lint_and_build (latest) (push) Has been cancelled
Mirror main branch to main-mirror-for-wdb / lint_and_build (push) Has been cancelled
Publish npm packages / publish (push) Has been cancelled
Dev Environment Test With Custom Base Port / restart-dev-and-test-with-custom-base-port (push) Has been cancelled
Dev Environment Test / restart-dev-and-test (push) Has been cancelled
Run setup tests with custom base port / setup-tests-with-custom-base-port (push) Has been cancelled
Run setup tests / setup-tests (push) Has been cancelled
Sync Main to Dev / sync-commits (push) Has been cancelled
TOC Generator / TOC Generator (push) Has been cancelled
2026-04-03 09:54:29 -07:00
Mantra
998b3662a5
Enhance error handling and logging in Emailable response validation (#1292)
- Updated `validateVerifyResponse` to capture errors for invalid or
unexpected responses.
- Improved handling of malformed responses in `checkEmailWithEmailable`,
ensuring a consistent return structure.
- Refactored `getDerivedSignUpCountryCode` to log errors for non-ISO
country codes.
- Simplified country code determination logic in
`createOrUpgradeAnonymousUserWithRules`.

<!--

Make sure you've read the CONTRIBUTING.md guidelines:
https://github.com/stack-auth/stack-auth/blob/dev/CONTRIBUTING.md

-->


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Replaced country code dropdown selection with a direct text input
field for simpler data entry.
* Updated country code validation to accept any 2-letter code format,
improving flexibility.

* **Bug Fixes**
* Refined country code normalization logic across sign-up rules and user
profile pages for consistency.

* **Documentation**
* Clarified country code field messaging from "ISO code" to "2-letter
country code" terminology for better user guidance.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-04-01 09:21:43 -07:00
Konstantin Wohlwend
300970c924 chore: update package versions 2026-03-31 10:54:12 -07:00
Konstantin Wohlwend
5616b0054b chore: update package versions 2026-03-30 12:26:13 -07:00
Konstantin Wohlwend
b40e05f3f2 Inline tooltip 2026-03-30 12:26:03 -07:00
Konstantin Wohlwend
dab5a609e9 Info tooltip for anonymous users 2026-03-30 11:22:32 -07:00
Konsti Wohlwend
5bfe1a79ce
New { type: "hosted" } for page URLs (#1261)
Other minor redirect URL changes:

- app.urls.* is now deprecated
- redirectToSignOut now sets and preserves after_auth_return_to
- OAuth sign-in after_auth_return_to now carries callback-return context

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **High Risk**
> High risk because it changes OAuth authorization/token issuance,
redirect URL validation, and introduces a new cross-domain handoff
endpoint plus a DB migration linking authorization codes to refresh
tokens, which can affect login/session security and reliability.
> 
> **Overview**
> Adds **hosted URL targets** for SDK `urls` resolution (new `{ type:
"hosted" }`/`{ type: "handler-component" }`/`{ type: "custom" }`
options), including env-driven hosted handler domain/template support
and fallback routing for unknown `/handler/*` paths.
> 
> Implements a **cross-domain OAuth PKCE handoff**: a new
`/auth/oauth/cross-domain/authorize` endpoint issues one-time
authorization-code redirects bound to the caller’s session refresh
token; authorization codes now persist `grantedRefreshTokenId` and token
issuance reuses/validates ownership of that refresh token. Redirect
planning for `redirectTo*` (and OAuth callback handling) is refactored
into `redirect-page-urls.ts` to preserve `after_auth_return_to` and
cross-domain handoff params.
> 
> Tightens redirect safety (e.g., `after_callback_redirect_url` is
validated/whitelisted), centralizes SDK env var reads via `envVars` with
lint enforcement, hardens `EventTracker` startup for partial DOM test
environments, and adds unit/E2E coverage plus a demo page for manual
cross-domain verification.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
9197d4f32b. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Cross-domain OAuth PKCE handoff flow (client + server) for hosted
sign-in.
* Hosted handler URL templating with local development domain suffix
support.
* Demo UI page to exercise hosted cross-domain sign-in/out and OAuth
flows.
* Authorization codes now preserve an associated refresh-token id to
support cross-domain exchanges.

* **Bug Fixes**
* Stricter redirect-URL validation and stronger refresh-token ownership
checks.
* More robust event-tracker startup guards in partial DOM environments.

* **Tests**
* New E2E and unit tests covering cross-domain authorize, callback
validation, and handoff flows.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-03-27 14:48:01 -07:00
Konstantin Wohlwend
a993ec0780 chore: update package versions 2026-03-25 16:44:42 -07:00
Mantra
cfa6204c2d
Replace Web3Forms with internal feedback emails (#1244)
## Summary
- replace the dashboard feedback form's Web3Forms submission with an
authenticated internal backend endpoint
- send support and feature-request notifications through Stack Auth's
native internal email pipeline
- share internal project auth headers in the dashboard and add backend
E2E coverage for support feedback

## Testing
- pnpm typecheck
- pnpm lint -- "src/components/feedback-form.tsx"
"src/components/stack-companion/feature-request-board.tsx"

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Internal feedback submission endpoint with automated internal email
notifications
* New internal email builder and sending utility; recipient list
configurable via env

* **Enhancements**
* Feedback form requires sign-in, disables submit when unauthenticated,
and tightens validation
  * Centralized header helper for authenticated internal requests
* Feature request board gates actions for signed-out users and improves
upvote/submit reliability
* Runtime retrieval/validation of the feature-tracking API key and
streamlined user handling

* **Tests**
* End-to-end tests covering internal feedback flows, validation, and
email delivery
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-03-23 17:07:37 -07:00