mirror of
https://github.com/stack-auth/stack.git
synced 2026-06-13 21:01:21 +08:00
docs/apps_updates
1644 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
2f3e5d0d5a | Update LLM documentation | ||
|
|
c5a49d6721 | Fix legacy cookie mixing | ||
|
|
bef9452c95 | chore: update package versions | ||
|
|
c8954ad172
|
Fix bundled dashboard symlinks in stack-cli (#1485) | ||
|
|
ed54832671 | chore: update package versions | ||
|
|
d30962bf66 | Fix GH tokens refresh & devtool tabs | ||
|
|
f7e389809e
|
feat(hexclave): PR 1 — wire compatibility layer (invisible) (#1475)
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
**Stacked on #1468** (`docs/hexclave-rename-plan` — the plan doc). Diff
vs that base = the actual PR 1 code.
This is **PR 1 of the Hexclave rebrand: the invisible compatibility
layer**. Everything is additive. Old SDKs, old wire identifiers, and old
env var names keep working unchanged. The backend dual-accepts and
dual-emits; new SDK code emits `x-hexclave-*` headers and the
`hexclave_` Bearer prefix; cookies dual-write; env vars dual-read across
every category. **No user-visible rebranding lands here** — that's PR 2.
See [`RENAME-TO-HEXCLAVE.md`](./RENAME-TO-HEXCLAVE.md) → *"PR 1
implementation guide"* for the full per-work-area spec, file pointers,
and chosen approach.
## What's implemented (all 14 PR-1 work-areas)
- **SDK export aliases** — `Hexclave*` aliases for the user-facing
`Stack*` exports added in `packages/template`; codegen propagates them
to `@stackframe/{js,stack,react,tanstack-start}`. React-only aliases
correctly excluded from `@stackframe/js`. (`e60550a2`)
- **JWT issuer dual-accept** — `decodeAccessToken` accepts both
`api.stack-auth.com` and `api.hexclave.com` issuers. Signing unchanged.
(`fc781def`)
- **Request-header dual-accept** — backend + dashboard proxies normalize
`x-hexclave-*` → `x-stack-*` at the existing empty proxy hook (so
`smart-request.tsx` and every route schema keep working unchanged); CORS
allowlists extended via a derive-once helper. (`2a056eac`)
- **MCP `ask_hexclave`** — registered alongside `ask_stack_auth` via a
shared helper; `ask_stack_auth` behavior byte-identical. (`30ffd604`)
- **Dev-tool** — DOM ids + header emit switched.
`window.HexclaveDevTool` exposed alongside `window.StackDevTool`.
(`32131ea7`)
- **The big consolidated commit** (`7fed864a`):
- **Env vars** — central `getEnvVariable` prefix-transform (HEXCLAVE
first, STACK fallback); dashboard + template client env files dual-read;
`turbo.json` globalEnv; `NEXT_PUBLIC_STACK_PORT_PREFIX` renamed outright
across ~82 files including docker.
- **Cookies** — dual-write/dual-read auth (`stack-access`/`-refresh-*`
and custom-domain variants), OAuth-state
(`stack-oauth-{inner,outer}-*`), and low-risk cookies (`stack-is-https`,
`stack-last-seen-changelog-version`). Bypass sites patched (backend
OAuth callback, dashboard remote-dev auth route, impersonation snippets,
snapshot serializer).
- **Bearer prefix** — SDK token parser accepts both `stackauth_` and
`hexclave_`; emits `hexclave_`. Discovery correction: this is purely
SDK-internal — the backend never parses it.
- **Response headers** — backend dual-emits
`x-hexclave-{request-id,actual-status,known-error}`; SDKs dual-read (new
first, stack fallback).
- **SDK request-header emit switch** —
`client/server/admin-interface.ts` + dashboard `api-headers.ts` +
`internal-project-headers.ts` + `feedback-form.tsx` switched to
`x-hexclave-*`. Plus `stack_response_mode` query param.
- **Storage keys** — dev-tool / cli-auth / oauth-button / docs keys
renamed (straight); `stack:session-replay:v1` dual-read so in-progress
recordings survive SDK upgrades; `stack_mfa_attempt_code` dual-read.
- **Query params** — cross-domain params dual-emit/dual-accept via
shared helpers; backend `oauth/authorize` accepts
`hexclave_response_mode` and `stack_response_mode`; `stack-init-id`
renamed.
- **`Symbol.for`** — app-internals symbol gets a parallel
`Symbol.for("Hexclave--app-internals")` getter on each attach site (no
read-site churn — old symbol still attached). 3 file-private symbols
renamed outright.
- **Config discovery** — prefer `hexclave.config.ts`, fall back to
`stack.config.ts` at every discovery site (CLI / dashboard / backend /
local-emulator); `init` writes the new filename; CLI credentials path
migrates.
- **Internal renames** — `StackAssertionError`,
`StackClient/Server/AdminInterface` renamed outright (no alias, per the
"internal-only → rename" rule). ~264 files touched.
- **Review-pass fixes** (`21217fbe`) — three real bugs found by parallel
review agents and fixed:
- `snapshot-serializer.ts` was interpolating the whole
`keyedCookieNamePrefixes` array (`${arr}`) — adding a second prefix
would have corrupted **every** OAuth-cookie snapshot, not just new ones.
- **Docker port-prefix producer/consumer mismatch** —
`entrypoint.sh`/`run-emulator.sh`/cloud-init `user-data` were still
producing `NEXT_PUBLIC_STACK_PORT_PREFIX` while the dashboard sentinel +
consumers had been renamed; silent self-host regression (custom port
prefix would be ignored).
- **Missing `hexclave-oauth-inner-*` dual-write** in the OAuth authorize
route — callback's fallback masked it but the dual-write was specified
by the plan.
- Plus: `mcp.test.ts` tool-list assertions updated to include
`ask_hexclave`; two dashboard header-emit sites switched to
`x-hexclave-*` for consistency.
- **E2E snapshot serializer follow-up** (`4b16cc5d`) —
`x-hexclave-request-id` added to the hidden-headers list (mirroring
`x-stack-request-id` treatment), and 2 sample inline snapshots
regenerated in `projects.test.ts` to include the new dual-emitted
headers.
## Verification
- **`pnpm typecheck`** — clean (the fresh-worktree `@/.source` / Prisma
codegen gap in `stack-docs` is pre-existing and unrelated).
- **`pnpm lint`** — 29/29 packages green.
- **`pnpm exec turbo run build --filter=./packages/*`** — 13/13 packages
build (including `@stackframe/stack-cli` once the dashboard standalone
is present).
- **Live E2E** against a running backend on `cl/hexclave-pr1`:
- `pnpm test run
apps/e2e/tests/backend/endpoints/api/v1/internal/mcp.test.ts` — **6/6
pass** (verifies the new `ask_hexclave` tool — the hand-written inline
snapshot matched actual MCP server output).
- `pnpm test run
apps/e2e/tests/backend/endpoints/api/v1/internal/projects.test.ts` —
**11/11 pass** (verifies wire dual-accept + dual-emit end-to-end; the
snapshot serializer fix was found and applied during this check).
A four-agent parallel **review pass** also audited the full diff for
logic/runtime bugs across the work-areas (wire headers + JWT, cookies +
bearer + symbols, env vars, query params + config + MCP + aliases). All
in-slice review verdicts were ✓ except the three bugs listed above,
which are now fixed.
## Known follow-ups (out of scope for this PR)
- **E2E snapshots across the rest of the suite** — backend now
dual-emits `x-hexclave-{known-error,actual-status}` alongside
`x-stack-*`, which legitimately appears in inline snapshots throughout
`apps/e2e`. Two were regenerated here as a sample; the rest should regen
with `vitest -u` in CI.
- **Docker shell env vars beyond `PORT_PREFIX`** — `entrypoint.sh` still
reads `STACK_*` env vars directly (the JS-side `getEnvVariable`
transform doesn't help the shell). JS consumers dual-read so it works in
practice; full shell-level dual-read is a deeper self-host follow-up.
- **`@stackframe/stack-cli` build ordering** — pre-existing; needs
`build:rde-standalone` first. Not affected by this PR.
## Test plan
- [ ] CI runs full e2e suite (with `vitest -u` to absorb dual-emit
snapshot deltas, then committed back)
- [ ] Spot-check: an old SDK build (emitting only `x-stack-*`) still
authenticates against the new backend
- [ ] Spot-check: a new SDK (emitting `x-hexclave-*` / `Bearer
hexclave_*`) still authenticates against an old backend during deploy
ordering
- [ ] Manual: `npx @stackframe/stack-cli@latest init` (new onboarding
entrypoint) generates `hexclave.config.ts`
- [ ] Manual: existing `stack.config.ts`-only project still resolves (no
migration required)
---------
Co-authored-by: bilal <bilal@stack-auth.com>
|
||
|
|
957a33a651 | chore: update package versions | ||
|
|
6a0ded1340 | chore: update package versions | ||
|
|
9b1851dd54
|
Managed email domain deletion and Cloudflare DNS import UX (#1442)
## Summary - Add an admin-only delete endpoint and SDK method to remove managed email domains, with Resend/DNSimple cleanup and a guard against deleting domains currently in use for sending. - Add dashboard UI to remove unused managed domains (with confirmation) and improve the DNS setup step with Cloudflare detection, zone file download, and import instructions. - Add E2E coverage for delete auth, success, in-use rejection, post-switch deletion, and 404 cases. ## Test plan - [ ] Run `pnpm test run managed-email-onboarding` - [ ] In dashboard email settings, add a managed domain and verify Cloudflare hint appears when NS records point to Cloudflare - [ ] Remove an unused managed domain and confirm it disappears from the list - [ ] Verify active (in-use) managed domains cannot be deleted until email provider is switched away Made with [Cursor](https://cursor.com) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Delete managed email domains from the dashboard with a confirmation flow and success notification * Cloudflare-aware domain setup: detection banner, quick links to Cloudflare DNS, downloadable zone file, and import instructions * Admin API and admin-app method to perform managed-domain deletion * **Bug Fixes** * Deletion blocked with a clear error when a domain is actively used for sending * **Tests** * Added end-to-end coverage for managed-domain delete scenarios (success, in-use conflict, auth rejection, and 404) * **Style** * Data grid layout adjusted to prevent unintended full-height stretching across various tables <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/hexclave/stack-auth/pull/1442?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
f6ef49a3dc | Remove source-of-truth logic | ||
|
|
01948e2313 | chore: update package versions | ||
|
|
62aa8616d5 | chore: update package versions | ||
|
|
ca2fa8cd10 | Remove MCP setup prompt | ||
|
|
70999df64e | chore: update package versions | ||
|
|
9355c8665c | chore: update package versions | ||
|
|
cd29811456 | chore: update package versions | ||
|
|
a443ec4a68 | Small Overview page docs fixes | ||
|
|
05e22e10a3
|
Use redirectToHandler in StackHandler and disallow string default URL target (#1472) | ||
|
|
1effedbc42 | Fix various cross-domain auth bugs | ||
|
|
0c6e135c30 |
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
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
|
||
|
|
99f07e9516 |
Trust hosted domains
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
Publish npm packages / publish (push) Has been cancelled
Publish Swift SDK to prerelease repo / publish (push) Has been cancelled
TOC Generator / TOC Generator (push) Has been cancelled
|
||
|
|
d12968eb3d | chore: update package versions | ||
|
|
c6d59d0288
|
Cross domain handoffs (#1458) | ||
|
|
03e7b61308 | chore: update package versions | ||
|
|
bf8d0ece28 | chore: update package versions | ||
|
|
4ff24dea9b | chore: update package versions | ||
|
|
e42ec65c88
|
Payments app design fixes (#1375)
<!-- Make sure you've read the CONTRIBUTING.md guidelines: https://github.com/stack-auth/stack-auth/blob/dev/CONTRIBUTING.md --> ## Summary This PR brings the Payments dashboard surfaces in line with the shared design system: product creation, product-line / included-item dialogs, auth-method toggles, payments empty states, and related layout polish. Dialogs migrate from raw shadcn `Dialog` to `DesignDialog` with consistent headers, footers, inputs, and selector dropdowns. **Base:** `dev` → **Head:** `Payments-app-design-fixes` **Scope:** 31 files, ~+1.4k / −1.3k lines **Captured on:** local dev server (`internal` project), signed in as `admin@example.com` ## Screenshots Captured from `http://localhost:8101` (viewport: **1920×1200** standard, **2560×1440** widescreen). Assets hosted in [this gist](https://gist.github.com/mantrakp04/ca3483d2b66b8e28f0872488df573ccf). > Red outlines on the **after** shots mark the new or changed UI introduced by this PR. ### Create Product — payments form redesign | | Before | After | | --- | --- | --- | | Light |  |  | | Dark |  |  | Widescreen: | | Before | After | | --- | --- | --- | | Light |  |  | | Dark |  |  | ### Product Lines onboarding — vertical centering fix | | Before | After | | --- | --- | --- | | Light |  |  | | Dark |  |  | ### Create Product Line dialog — `DesignDialog` migration | | Before | After | | --- | --- | --- | | Light | *(legacy shadcn dialog on `dev` — open via Product Line → Create new)* |  | | Dark | |  | ### Auth Methods — toggle row accessibility | | Before | After | | --- | --- | --- | | Light |  |  | | Dark |  |  | ### Other migrated surfaces (after only) | Page | Light | Dark | | --- | --- | --- | | Payments settings |  |  | | Sign-up rules |  |  | | Projects list (Create Project button) |  |  | | Playground / DesignDialog |  |  | | Included Item dialog |  |  | ### Scroll behaviour — Sign-up Rules | | Light | Dark | | --- | --- | --- | | Scroll |  |  | ## What's new - **`DesignDialog`** extended with `customHeader`, `noBodyPadding`, and section `className` hooks; Playground updated to showcase them. - **Payments dialogs** (`CreateProductLineDialog`, `IncludedItemDialog`, price edit, item dialog) migrated to design-system components. - **Create Product** page uses `DesignButton`, `DesignInput`, `DesignSelectorDropdown`, and refreshed header actions. - **Auth Methods** toggle rows use semantic `<Label htmlFor>` instead of click-capture divs. - **Payments layout** empty-state card centers correctly; product-lines onboarding slideshow vertically centers. - **Backend** seed invariant for Growth product price; removed unused import in product switch route. ## Notes for reviewers - Dialog migrations preserve validation + async error handling (`runAsynchronouslyWithAlert` where applicable). - Included-item dialog uses a sentinel value for “Create new item” to avoid colliding with real item IDs. - `packages/stack` / `packages/js` are untouched; template + dashboard-ui-components carry SDK-facing dialog changes. ## Test plan - [x] Visual capture on `internal` project (`admin@example.com`) — light/dark, standard + widescreen - [ ] Create product flow: customer type → product line dropdown → create line dialog - [ ] Add included item dialog from create/edit product - [ ] Auth Methods toggles (label click + switch) - [ ] Payments product-lines onboarding slideshow at varied viewport heights - [ ] `pnpm typecheck` / `pnpm lint` / targeted E2E if API surface changed --------- Co-authored-by: nams1570 <amanganapathy@gmail.com> Co-authored-by: mantrakp04 <mantrakp@gmail.com> Co-authored-by: Mantra <87142457+mantrakp04@users.noreply.github.com> |
||
|
|
b8fc04bdbd
|
feat: link Stack Auth projects to GitHub and push config from the dashboard (#1450)
End-to-end flow for managing Stack Auth config via GitHub: link a repo
during onboarding, edit settings in the dashboard, and have the change
committed to your repo + synced back via a GitHub Actions workflow.

## What this adds
- **CLI** — `stack config push --source github --source-repo
--source-path --source-workflow-path`. Records the source on the config
row so the dashboard knows where the file lives. Reads `GITHUB_SHA` /
`GITHUB_REF_NAME` for commit + branch.
- **Onboarding "Link existing project"** — searchable repo/branch
comboboxes, auto-detects candidate `stack.config.{ts,js}` paths, writes
`STACK_AUTH_PROJECT_ID` + `STACK_AUTH_SECRET_SERVER_KEY` secrets, and
commits a generated workflow YAML that re-runs `stack config push` on
every change to the config file.
- **Dashboard "Push to GitHub" dialog** — replaces the prior TODO
buttons. Pre-flights `repo`+`workflow` scopes on the user's GitHub
connection; if missing, the button flips to "Reconnect with GitHub". On
push, commits the dashboard's edit straight to the linked repo/branch
via the Contents API (with `cache: "no-store"` to dodge GitHub's 60s GET
cache so consecutive pushes don't 409). Suspense boundary scoped to the
dialog body so opening it doesn't blank the dashboard.
- **Project settings** — surface the linked workflow file as a clickable
GitHub link when the source carries `workflow_path`.
## Test plan
- `pnpm lint` (29/29) ✓
- `pnpm typecheck` (29/29) ✓
- `pnpm --filter @stackframe/stack-cli test` (111/111) ✓
- Dashboard vitest on the three relevant files
(`link-existing-onboarding-workflow`, `github-api`,
`github-config-push`) — 37/37 ✓
- Live end-to-end: `BilalG1/lex-lookup` linked to a local dev project;
passkey toggled, push committed `0bb958bd`
([commit](
|
||
|
|
0e85b05c3d
|
[Fix]: Payments App Sundry Fixes (#1455)
### Summary of Changes
You can now edit items on a product view.
The "Make free" button is less obtuse, and it clearly tells you what
it's going to do.
Additionally, we found out while working on this PR that you cannot
create a `paymentIntent` on stripe that is < 0.5$. So, you can't create
an OTP for a "free" product. We add safeguards to protect against that.
Also, 0 dollar subscriptions don't create a subscription invoice.
Additionally, the old code relied on being able to fetch the stripe
client secret, which would be null for a 0 dollar subscription so we
create a carve out.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Better free-product checkout handling: $0 subscriptions return an
empty success response without a payment client secret; non-free
subscriptions include client secret when needed.
* UI: “Make free” flow, “Free · {amount}” with price ID, per-price
checkout error indicators/tooltips, and an alert for products with
invalid prices.
* Client- and server-side Stripe one-time minimum checks.
* **Bug Fixes**
* Included-item dialog now resets form state when opened to avoid stale
values.
* **Documentation**
* OpenAPI: clarified client_secret may be omitted when no customer
confirmation is required.
* **Tests**
* Added end-to-end tests covering $0 purchase-session flows.
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/hexclave/stack-auth/pull/1455?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)
<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
|
||
|
|
01aacd2dd4
|
fix(dashboard): repair and polish the GitHub link-existing project flow (#1441)
Rework of the **new-project → Link Existing Config** flow on the dashboard, plus the published `stack-cli` it depends on. The starting point on `dev` had the link-existing flow effectively broken end-to-end (the generated GitHub workflow could never authenticate, and the GitHub-account selection UI dead-ended in several states). This PR fixes the blockers, polishes the local-CLI path, and adds a searchable repo/branch picker. --- ## What was broken | Severity | Issue | Fixed in | |---|---|---| | 🔴 | Generated workflow omitted the required `--cloud-project-id` flag → every run failed at Commander before the action ran. | `d0e6ad15f`, `55ff7e319` | | 🔴 | Workflow exported `STACK_PROJECT_ID` env var the CLI never read. | `55ff7e319` (CLI now reads it; workflow drops the explicit flag) | | 🔴 | `pnpx` isn't on `ubuntu-latest` → step failed with `command not found`. | `65789a1ac` | | 🔴 | "No connected GitHub account found" alert with **no Connect button**. | `d0e6ad15f` | | 🟠 | "Connect new" used `getOrLinkConnectedAccount` (get-or-link) → silently returned the existing account instead of starting a fresh OAuth flow. | `d0e6ad15f` | | 🟠 | `workflow_dispatch` 404s on non-default branches; threw before advancing to the logs step even though the push-triggered run worked. | `d0e6ad15f` | | 🟠 | Config-path suggestions prepended `./`, which breaks GitHub's `on.push.paths` filter — ongoing config edits never re-triggered the workflow. | `d0e6ad15f` | | 🟡 | Account selector briefly showed the numeric `providerAccountId` before the GitHub `/user` fetch populated the username. | `de9ec1923` | | 🟡 | Repository / branch dropdowns capped at 100 entries with no search. | `7550eaacb` | ## What changed ### Dashboard — Link Existing Config flow - **Local CLI step rebuild** (`ed25eabf9`, `ebb090e5b`): split into separate "Sign in" and "Push config" code blocks using the shared `CodeBlock` component (copy button built-in), added a `npx / pnpx / bunx` runner pill toggle (default `npx`), moved `--config-file <path>` to the end of the push command so users can copy everything up to the placeholder, trimmed redundant helper text. - **GitHub OAuth states** (`d0e6ad15f`, `de9ec1923`): empty-state "Connect GitHub account" button; "Connect new" now uses `linkConnectedAccount` so it actually starts OAuth; loading row instead of `providerAccountId` flash. - **Searchable repo + branch combobox** (`7550eaacb`, `5ce1b6bd9`): new `RemoteSearchCombobox` (Popover + cmdk, same pattern as `data-table/faceted-filter`), debounced GitHub `/search/repositories` and `/git/matching-refs/heads/{prefix}` calls so users with > 100 repos/branches can find any of them. Branch "Refresh" button removed — branches auto-load on repo select. - **Workflow generator** (`d0e6ad15f`, `65789a1ac`): config paths normalised (strip leading `./`); workflow uses `actions/setup-node@v4` + `npx --yes`; `workflow_dispatch` failure is now best-effort (the workflow-file commit's push event triggers the run on any branch). ### Stack CLI - `STACK_PROJECT_ID` env-var fallback for `--cloud-project-id` (`55ff7e319`). Both `config push` and `config pull` are affected; explicit flag still wins. New `resolveProjectId` helper in `lib/auth.ts` with 5 unit tests (`auth.test.ts`). ### Misc - `2faffb662` drops an unused `useTransition` wrapper around a `setProjectStatuses` Map insert in the new-project flow. --- ## Release ordering note The generated workflow's `run:` line **no longer passes `--cloud-project-id`** — the CLI reads `STACK_PROJECT_ID` from env instead. This means a workflow generated by this branch only works against a `@stackframe/stack-cli` published with the env-var fallback from `55ff7e319`. The CLI and dashboard ship from the same monorepo so this should be a non-issue in the normal release cadence, but worth confirming the CLI publishes alongside the dashboard deploy. Existing workflows already committed in user repos still have the explicit flag and continue to work unchanged. ## Validation - `pnpm --filter @stackframe/dashboard run typecheck` ✅ - `pnpm --filter @stackframe/dashboard run lint` ✅ - `pnpm --filter @stackframe/stack-cli run typecheck` ✅ - `pnpm --filter @stackframe/stack-cli run lint` ✅ - `pnpm --filter @stackframe/stack-cli test` ✅ (14 tests; 5 new for `resolveProjectId`) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Searchable repository and branch selection UI for GitHub onboarding * New remote search combobox component for selecting repos/branches * Selectable CLI package runner and dynamic command display during onboarding * **Improvements** * CLI accepts STACK_PROJECT_ID env var; cloud project flag is optional * Workflow generation normalizes/validates config paths, sets up Node.js v20, and uses npx; onboarding dispatch is non-fatal * Hardened repository loading to avoid stale async updates * **Tests** * Added tests covering project ID resolution logic <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/hexclave/stack-auth/pull/1441?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
055304d3fd
|
Onboarding app redesign (#1370)
# Onboarding app redesign Rolls out a unified dashboard visual language centered on `DesignCard` groupings, a new canonical `DesignDialog`, and an inline live-preview pattern. Touches the project listing, project overview, auth methods, design language, onboarding, and sign-up rules surfaces. Reusable primitives (`DesignCard`, `DesignDialog`, `MethodToggleRow`) replace one-off layouts, and the project card now leads with **total users + 30-day signups** instead of a weekly-users tile. **Base:** `dev` → **Head:** `onboarding-app-redesign` > Red outlines on the "after" shots highlight the UI that changed in this PR. Empty outlines = layout/chrome change with no data delta. --- ## Flagship: Project listing (`/projects`) Project cards swap the weekly-users widget for a `ProjectUsersMetric` (total user count + 30-day signups sparkline). Hover lifts the card; the metrics row is now part of the card body instead of a footer strip. | | Light | Dark | |--------|-------|------| | Before |  |  | | After |  |  | ## Flagship: Auth methods (`/projects/[id]/auth-methods`) Full restructure: the horizontal `SettingCard` strips are replaced by stacked `DesignCard` sections (Sign-in methods · Sign-up policies · User deletion), with a sticky **live sign-in preview** column on the right. Provider rows become `MethodToggleRow`s with inline configure actions. | | Light | Dark | |--------|-------|------| | Before |  |  | | After |  |  | ## Flagship: Project overview (`/projects/[id]`) Line + donut charts migrate to the shared `AnalyticsChart` component. Referrers list gains a max-height + scroll affordance so it no longer pushes neighbouring tiles off-screen. | | Light | Dark | |--------|-------|------| | Before |  |  | | After |  |  | ## Other migrated surfaces | Surface | Before (dark) | After (dark) | What changed | |---------|---------------|--------------|--------------| | `/projects/[id]/onboarding` |  |  | Email-verification toggle adopts the new `MethodToggleRow` + confirmation `DesignDialog` variant | | `/projects/[id]/sign-up-rules` |  |  | Rule builder rewrapped in `DesignCard`/`DesignAlert`/`DesignButton` primitives | | `/projects/[id]/design-language` |  |  | Adds a `DesignDialog` showcase section so consumers can see the canonical modal styling | | `/playground` |  |  | New `dialog` playground entry exercising the size/variant/icon-chip permutations | Light-mode counterparts for the long-tail surfaces are in the [companion gist](https://gist.github.com/mantrakp04/ff6b32969cb08510860e94be7d67dbf7). --- ## What's new - **`DesignDialog`** (`packages/dashboard-ui-components/src/components/dialog.tsx`) — canonical modal with configurable size/variant, optional icon chip, and split header/body/footer regions. Replaces ad-hoc `Dialog` + `DialogContent` usage across the dashboard. - **`MethodToggleRow`** — shared row primitive used by auth-methods and onboarding for "thing with a toggle and an inline configure CTA". - **`ProjectUsersMetric`** — total users + 30-day signups sparkline; powers the new project card metric and reuses the `projects-weekly-users` backend route renamed to `projects-metrics`. - **`action-dialog`** gains `keepOpenOnOutsideInteraction` and `contentClassName` props so variant chrome can ride along through the existing helper. - Backend: new internal `projects-metrics` route + test; `seed-dummy-data.ts` updated to populate the new metric. ## Notes for reviewers - Reusable primitives (`DesignCard`, `DesignDialog`, `MethodToggleRow`) live in `packages/dashboard-ui-components` — please flag any inline duplications you spot. - The auth-methods live-preview only renders at `lg+`. Below that breakpoint the page falls back to the stacked card layout. - The OAuth provider config dialogs adopt the new pill toggle for **Shared keys / Custom OAuth credentials**; the underlying form fields are unchanged. ## Test plan - [ ] `/projects` — verify the metric tile renders both empty-state and populated (Demo Project has 584 users seeded) - [ ] `/projects/[id]/auth-methods` — toggle each method on/off, confirm live preview updates in real time - [ ] `/projects/[id]/auth-methods` — open a provider dialog, switch between Shared / Custom keys, verify form state preserved - [ ] `/projects/[id]/onboarding` — toggle email verification, confirm the confirmation dialog variant - [ ] `/projects/[id]/sign-up-rules` — verify rule builder still saves correctly under the new chrome - [ ] Mobile/`md` breakpoint — auth-methods falls back to stacked layout, no overflow - [ ] Dark mode parity on every flagship surface <sub>Visuals captured via local dev server (`localhost:8101`) on `admin@example.com` seeded account. Red outlines mark new/changed UI on the "after" pass.</sub> --------- Co-authored-by: mantrakp04 <mantrakp@gmail.com> Co-authored-by: Mantra <87142457+mantrakp04@users.noreply.github.com> |
||
|
|
90421431ee | chore: update package versions | ||
|
|
5dbfb1ebab
|
Auth app redesign (#1367)
<!-- 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** * Added a reusable DesignDialog modal system (sizes, variants, header/footer/headerContent, trigger/close controls). * Added a documented "roids" skill and pinned it in the skills registry. * **Documentation** * Expanded design guide with comprehensive dialog usage patterns, examples, and props. * **Improvements** * Playground now previews and generates dialog code interactively. * Auth methods and sign-up rules UIs migrated to the new design system. * Action dialogs can opt to ignore outside interactions and accept custom content classes. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --- ## Summary Two things bundled together: 1. **New `DesignDialog` primitive** in `@stackframe/dashboard-ui-components` — the canonical glassmorphic dashboard modal shell. Exposes configurable sizes (`sm`→`7xl`/`full`), `glassmorphic` vs `plain` variant, optional icon / title / description / footer / custom header slots, and a `DesignDialogClose` companion. Replaces the ad-hoc dialog wrappers scattered across the dashboard. 2. **Auth-app pages migrated onto the design-components system** — `auth-methods` and `sign-up-rules` are rebuilt on `DesignCard` / `DesignAlert` / `DesignButton` / `DesignBadge` / `DesignInput` / `DesignMenu` / `DesignSelectorDropdown` / `DesignDialog`. Live OAuth-page preview frame, glassmorphic confirmation dialogs, and a redesigned rule-builder all live behind these new shells. The design-language catalog page and the `/playground` component explorer were both extended with full dialog showcases so the new primitive has a single discoverable home. **Base:** `dev` → **Head:** `auth-app-redesign` **Scope:** 11 files changed · +2553 / −1151 lines --- ## Screenshots — before and after > Captured locally against `http://localhost:8101` at 1440×900 with a fresh project (`Demo Project`) created via the sign-up + new-project flow. Dev-only overlays (outdated-version banner, console toasts) are hidden via injected CSS for clarity. ### Auth methods — `/projects/<id>/auth-methods` The big page-client rewrite. Before was a flat list of toggleable rows with a live preview pinned to the right. After is a sectioned layout — `SIGN-IN METHODS` and `SSO PROVIDERS` get uppercase subheaders, each method gets a `DesignBadge` icon + description ("Classic email + password credentials.", "One-time codes delivered by email.", "Phishing-resistant device-bound credentials."), and empty states (e.g. SSO with no providers configured) become real call-outs instead of plain rows. | Before (`dev`) | After (this PR) | | --- | --- | |  |  | |  |  | ### Sign-up rules — `/projects/<id>/sign-up-rules` Full rule-builder rewrite (CEL ↔ visual tree round-trip kept intact, just dressed in the new design system). Before's empty state was a flat alert + plain "Default action" row. After uses `DesignCard` variants — `NO RULES YET` with an inline "Add your first rule" CTA, an "If no rules match → Allow sign-up" surface, and a dedicated `TEST RULES` card linking the simulator. | Before (`dev`) | After (this PR) | | --- | --- | |  |  | |  |  | ### Component playground — `/playground` A new **Dialog** entry was added to the component selector. The before shots show `dev` — the selector only listed Button (and a handful of other primitives) and had no Dialog playground at all. The after shots show the new entry: a props panel for `shape` / `size` / `variant` / `title` / `description` / `headerIcon` / `footer` / `topRightClose`, plus an "Open confirmation" button that mounts the live `DesignDialog`. #### Closed (props panel + code preview) | Before (`dev` — no Dialog entry) | After (this PR) | | --- | --- | |  |  | |  |  | > The "before" shots default to the Button playground because the Dialog entry doesn't exist on `dev` — that's the change. #### Open (glassmorphic surface in action) The dialog itself — only available after this PR, so no `dev` equivalent. | Light | Dark | | --- | --- | |  |  | ## What changed - **New** `packages/dashboard-ui-components/src/components/dialog.tsx` — the `DesignDialog` primitive. Props shape: `size` × `variant` × optional `icon` / `title` / `description` / `headerContent` / `customHeader` / `footer` slots, plus `trigger`, `noBodyPadding`, `hideTopCloseButton`, and per-section `*ClassName` escape hatches. Exports `DesignDialog`, `DesignDialogClose`, plus the `DesignDialogSize` / `DesignDialogVariant` / `DesignDialogProps` types. - **Exports** wired through `packages/dashboard-ui-components/src/index.ts` so consumers import from `@stackframe/dashboard-ui-components` or, by extension, the dashboard's local `@/components/design-components` barrel. - **Auth methods page** (`apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/auth-methods/page-client.tsx`) — full migration. Sign-in methods, OAuth provider list, dot-menu actions, "Add disabled providers" search dialog, two confirmation dialogs, sign-up policy block, user-deletion block. Old `Card` / `Input` / `Button` / `SettingCard` imports replaced with their design-component counterparts. `providers.tsx` follows the same migration for the per-provider config dialogs. - **Sign-up rules page** (`apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/sign-up-rules/page-client.tsx`) — the big 1830-line rewrite. Rule builder, empty state, conditional-group editor, and tester sheet all rebuilt on the new primitives. CEL ↔ visual-tree conversion (`parseCelToVisualTree` / `visualTreeToCel`) is unchanged. - **Design-language catalog** (`apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/design-language/page-client.tsx`) — adds the Dialog section so the catalog reflects the new primitive. - **Playground** (`apps/dashboard/src/app/(main)/(outside-dashboard)/playground/page-client.tsx`) — adds the Dialog entry with `Shape` / `Size` / `Variant` / `Title` / `Description` / `Header Icon` / `Footer` / `Top-right close` controls and live JSX generation. - **Design guide** (`apps/dashboard/DESIGN-GUIDE.md`) — new "Dialogs" section documenting when to reach for `DesignDialog` (default), `DesignDrawer`, `ActionDialog`, or the raw `<Dialog>` primitives, plus the canonical usage snippet. - **Action dialog shim** (`apps/dashboard/src/components/ui/action-dialog.tsx`) — small follow-on edits so existing `ActionDialog` callers stay consistent with the new look. ## Notes for reviewers - **Start with** `packages/dashboard-ui-components/src/components/dialog.tsx` — it's the load-bearing piece. The two state machines worth eyeballing are the `dialogSurfaceClasses` map (glassmorphic vs plain shells, including the dark-mode ring/backdrop tweaks) and the header/body/footer composition inside the main `DesignDialog` function. - **Then** `sign-up-rules/page-client.tsx`. 1830 lines, but the diff is mostly mechanical (Card→DesignCard, Button→DesignButton, etc.). The interesting bits are the rule-row layout, the conditional-group editor, and the simulator drawer — those received structural tweaks, not just visual ones. The CEL serialization (`parseCelToVisualTree` / `visualTreeToCel`) was deliberately left alone. - **OAuth provider migration to non-pushable config** — a `// OAuth client ID/secret are environment-level (not pushable)` comment was removed from a couple of call-sites. Behaviour-equivalent (the call already passes `pushable: false`), just trimmed because the new code is cleaner. Flag if you want it kept. - **Catalog routes are dashboard-internal** (`/projects/<id>/design-language`, `/playground`) — exposed only in dev/staging, not customer-facing. They exist so design changes have a discoverable demo surface. - **Live-preview frame on `auth-methods`** uses a real `<AuthPage>` inside `BrowserFrame`, fed by the in-progress config. Verify your changes still render correctly there if you touch `<AuthPage>` props. ## Test plan - [ ] `/projects/<id>/auth-methods` — toggle each sign-in method; live preview reflects the change; "Save changes" inline action works; "Add SSO providers" dialog filters via the search input - [ ] OAuth provider dot-menu — open the provider config dialog (now `DesignDialog` glassmorphic), confirm the per-provider switches/inputs save through the `useUpdateConfig` hook - [ ] Sign-up confirmation dialogs — toggling "Allow new user sign-ups" off and back on shows the new warning `DesignAlert`s inside the dialog - [ ] `/projects/<id>/sign-up-rules` — add a rule, add a condition group, run the tester sheet; CEL output unchanged vs `dev` - [ ] `/projects/<id>/design-language` — Dialog showcase renders all sizes/variants without overflow - [ ] `/playground` → select **Dialog** — all prop combinations render; generated code snippet matches the rendered component; "Open confirmation" launches the glassmorphic shell - [ ] Light + dark mode visual sanity across all four pages (screenshots above are the canonical reference) --------- Co-authored-by: Aadesh Kheria <kheriaaadesh@gmail.com> |
||
|
|
954ebffc31
|
fix/kim john ung prompt (#1446)
- **Update generated prompts** - **Fix React error** - **Don't show alpha apps during onboarding** - **[Docs] First-class TanStack Start in AI setup prompts + clearer env-var guidance (#1438)** - **update docs** <!-- Make sure you've read the CONTRIBUTING.md guidelines: https://github.com/hexclave/stack-auth/blob/dev/CONTRIBUTING.md --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Simplified setup and environment-variable guidance across docs, onboarding prompts, and setup snippets, replacing long explanatory blocks with concise inline notes. * Condensed frontend/backend examples into shorter combined examples and streamlined cloud-project instructions. * Shortened custom auth page prompts by removing verbose redirect/URL override explanations and relying on shared reminder text. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/hexclave/stack-auth/pull/1446?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
2aa4affa54
|
Fix build and lint failures on dev (#1445) | ||
|
|
07af46944b
|
[Docs] First-class TanStack Start in AI setup prompts + clearer env-var guidance (#1438)
## Summary
Two related improvements to Stack Auth's AI setup story, both driven by
`packages/stack-shared/src/ai/prompts.ts`:
### 1. Clearer env-var guidance in the cloud-project flow (existing
commit)
The previous wording suggested `STACK_PROJECT_ID` should be prefixed via
a generic _"if available, prefix with your framework's convention"_
comment, and the backend section additionally listed
`NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY` — which the SDK does not
actually read in the cloud-project setup. Agents would dutifully
fabricate that third variable.
This is now spelled out:
- The exact prefix per framework (Next.js →
`NEXT_PUBLIC_STACK_PROJECT_ID`, Vite → `VITE_STACK_PROJECT_ID`, etc.) is
given inline.
- A note clarifies that on the client, **only** the project ID is read —
there is no separate publishable / client key.
- A note clarifies that the backend setup reads exactly two variables
(`STACK_PROJECT_ID` + `STACK_SECRET_SERVER_KEY`); a third slot in
`.env.local` is wrong.
### 2. First-class TanStack Start support (new commit)
Until now `mainType: "tanstack-start"` was silently routed through
`@stackframe/react` and inherited the React-only setup steps. Agents had
to guess at the TanStack-specific bits (where to mount `StackProvider`,
what to do with `routeTree.gen.ts`, how `useUser()` behaves under SSR,
where the handler route lives).
`prompts.ts` now:
- Recognizes TanStack Start as its own `mainType` and routes the install
to `@stackframe/tanstack-start`.
- Lists TanStack Start alongside Next.js / React in the
supported-frameworks list and the package table.
- Adds three TanStack-specific steps that don't apply to vanilla React:
1. Mount `StackProvider` / `StackTheme` inside the root route's
`component` (the inner React tree), keeping `shellComponent` as the
document shell.
2. Wrap `<Outlet />` in `Suspense` inside `RootComponent`.
3. Register the Stack handler splat at `src/routes/handler/\$.tsx` with
`ssr: false`.
- Surfaces the two notes that aren't obvious from the React docs:
`routeTree.gen.ts` is generated and shouldn't be hand-edited, and
`useUser()` resolves the SSR user from TanStack Start's request cookies
for free as long as `tokenStore: \"cookie\"` is set.
The auto-generated outputs
(`docs-mintlify/guides/getting-started/setup.mdx`,
`docs-mintlify/snippets/home-prompt-island.jsx`) are regenerated from
the prompt.
### 3. tanstack-start-demo SSR-vs-client examples
Two paired routes (`/ssr` and `/client`) render the same `AuthDemoCard`
so the SSR-vs-\`ssr: false\` tradeoff is observable side-by-side. The
new \`AuthDemoCard\` shows the resolved Stack Auth user (or sign-in/up
buttons) plus the snippet that produced it. The
\`ClientMountedUserButton\` workaround in the header is dropped now that
SSR cookie reading just works, and the empty \`Suspense
fallback={null}\` in \`__root.tsx\` is replaced with a
\`RouteLoadingState\` skeleton.
## Test plan
- [ ] \`pnpm typecheck\` and \`pnpm lint\` both pass on the touched
packages (\`stack-shared\`, \`tanstack-start-demo\`).
- [ ] \`docs-mintlify/guides/getting-started/setup.mdx\` and
\`docs-mintlify/snippets/home-prompt-island.jsx\` are byte-identical to
a fresh \`scripts/generate-setup-prompt-docs.ts\` run.
- [ ] In \`tanstack-start-demo\`, \`/ssr\` renders the user card during
the server response (no flash from signed-out → signed-in), and
\`/client\` renders the empty card on first paint, then resolves to the
user after hydration.
- [ ] \`/handler/sign-in\`, \`/handler/sign-up\`, OAuth callbacks, and
password reset all render correctly through the new splat route.
- [ ] Following the new TanStack Start prompt steps from scratch in an
empty \`npm create @tanstack/start@latest\` project produces a working
sign-in flow without any extra changes.
Made with [Cursor](https://cursor.com)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added TanStack Start support, provider/theme wiring, SSR and
client-only demo pages, plus an Auth demo card component.
* **Documentation**
* Updated setup guides and snippets across frameworks; clarified env-var
guidance (client reads only project ID; secret is server-only) and
removed misleading publishable-key example.
* Clarified OAuth callback and hosted-domain behavior.
* **Improvements**
* Added loading skeleton UI, refined demo navigation, and tightened
setup wording.
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/hexclave/stack-auth/pull/1438?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)
<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
|
||
|
|
48acb8c640 | chore: update package versions | ||
|
|
29cea48beb
|
Remote dev envs (#1435) | ||
|
|
d68631ea4f | Update GitHub URL | ||
|
|
d0202eeef9
|
payments: rework refund flow to three-knob API (#1429)
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
- Replaces per-entry refund schema with a flat `{ amount_usd,
revoke_product, end_subscription? }` shape; refund state is now derived
from bulldozer ledger rows (`refund:<sourceTxnId>:<uuid>`) instead of
the legacy `refundedAt` column, enabling multiple partial refunds up to
the remaining cap.
- Adds `invoice_id` for refunding any subscription invoice (start or
renewal), Stripe idempotency keys derived from `(tenancyId, sourceTxnId,
amount, prior_refunded)` so retries dedupe but intentional partials
don't collide, and a legacy backstop that rejects pre-rework
`refundedAt` purchases.
- Dashboard refund dialog rebuilt around the three toggles (revoke→end
coupling cascades into the UI); refund rows surface in the listing as
`type: "refund"` with `adjusted_by` linkage handling both new and legacy
formats.
## Implements
[STA2-52 — Build in refund logic for
payments](https://linear.app/stack-auth/issue/STA2-52/build-in-refund-logic-for-payments)
## Documented limitations (planned follow-up work)
These are called out in code comments and intentionally deferred to a
follow-up PR:
- **Cap-check race under concurrent refunds.** Bulldozer's embedded
`BEGIN/COMMIT` prevents an outer Prisma tx from scoping the writes, so
two concurrent refunds can both pass the cap check. Needs a
bulldozer-aware mutex or pending-refund-intent pattern. In practice
refunds are admin-only and rare, so the race window is small.
- **Stripe + DB non-atomicity on the DB-success → response-loss path.**
The Stripe idempotency key is keyed on `(tenancyId, sourceTxnId, amount,
priorRefunded)`, so a retry after Stripe-success → DB-fail self-heals
(Stripe dedupes; the next attempt writes the bulldozer row). The hole is
the reverse direction: if the bulldozer row commits but the response is
lost, a retry sees a higher `priorRefunded` and generates a fresh key —
Stripe would issue a second real refund. No out-of-band reconciliation
today.
- **Dashboard can't reach the `invoice_id` path.** Refund actions are
only enabled on `purchase` rows and the submit call never passes
`invoice_id`, so admins refunding a renewal must use the API directly.
Follow-up: enable the action on `subscription-renewal` rows and thread
`invoice_id` through.
## Architectural note
`active-subscription-end` and `item-quantity-expire` entries are **not**
emitted on the refund row itself. They're produced by the derived
sub-end transaction (`transactions.ts:158-228`) once Prisma
`subscription.endedAt` is updated, keeping the `expiresWhen` /
`when-repeated` semantics in one place. This is the main structural
divergence from the ticket's literal entry recipe.
## Review follow-ups addressed in this PR
**First-pass review:**
- **KnownError back-compat preserved**: `SubscriptionAlreadyRefunded` /
`OneTimePurchaseAlreadyRefunded` are once again thrown by the
legacy-`refundedAt` backstop, and `TestModePurchaseNonRefundable` is
thrown when an admin sends `amount_usd > 0` against a test-mode
purchase. Callers catching by error code keep working through the
rework.
- **Idempotency-key comment corrected**: now accurately describes the
`(tenancyId, sourceTxnId, amount, priorRefunded)` key and its
self-healing behaviour on the Stripe-success → DB-fail retry path (see
Documented limitations above for the remaining hole).
- **Renewal-invoice e2e coverage added**: new test sets up a live-mode
subscription via Stripe webhooks (`subscription_create` +
`subscription_cycle` invoices), refunds the renewal invoice via
`invoice_id`, and asserts the resulting `refund_transaction_id` starts
with `refund:sub-renewal:` and is linked back via `adjusted_by` on the
*renewal* row (not the start row). Plus negative cases:
cross-subscription `invoice_id` → 404, `invoice_id` on a one-time
purchase → SchemaError.
**Second-pass review:**
- **Idempotent sub-cancel error-code string fix**: the Stripe code for
re-cancelling an already-canceled sub is
`subscription_already_canceled`, not `subscription_canceled` — the
previous catch would have re-thrown.
- **End-only sub refund replay rejected**: when `amount=0, revoke=false,
end=true` and the sub is already `cancelAtPeriodEnd` or `endedAt`, throw
SchemaError. Otherwise `readPriorRefundSummary` doesn't see end-only
events and the call would be a forever-no-op accumulating empty refund
rows.
- **`revoke_product=true` with renewal `invoice_id` rejected**: the
product grant lives on the sub-start txn, not on renewal txns — a
renewal-scoped revocation would write a back-reference to a non-existent
entry. Forces admin to revoke against the start invoice (or the default
no-`invoice_id` call).
- **Refund row `id` matches the linkage**: the listing route now returns
the full refund txnId as `id` for `type: "refund"` rows so it matches
`adjusted_by.transaction_id` — the dashboard can join source rows to
their refund rows.
- **+2 e2e tests** for the above (end-only replay rejection,
revoke+renewal rejection).
**Third-pass review:**
- **Dashboard refund dialog seeds state on open**: previously the reset
block lived in `ActionDialog`'s `onOpenChange`, which doesn't fire on
the open transition for a controlled dialog. As a result the dialog
opened with the initial `useState` defaults (`amountUsd = '0'`), and an
admin submitting unchanged on a paid purchase would revoke/end at $0
instead of refunding the charged amount. The seed now runs in the menu
`onClick` before `setIsDialogOpen(true)`.
- **`SUBSCRIPTION_START_PRODUCT_GRANT_ENTRY_INDEX` corrected from 1 →
0**: the constant is persisted as `adjustedEntryIndex` on
product-revocation entries and copied through verbatim by
`mapLedgerEntry`. That mapper drops the hidden
`active-subscription-start` entry, so the public-API layout puts the
product grant at index 0. The prior value of `1` pointed at the
money-transfer entry (or out of range on test-mode subs) through the
public listing.
- **`amountTotal` cap gated behind a USD pre-flight**:
`SubscriptionInvoice` doesn't persist invoice currency, and the previous
code took `invoice.amountTotal` as USD cents directly. Now
`getTotalUsdStripeUnits` (which throws on non-USD pricing) is always
called first; `amountTotal` is only preferred as the actual cap after
that pre-flight succeeds.
## Test plan
- [x] `pnpm typecheck` — 28/28 pass
- [x] `pnpm lint` — 28/28 pass
- [x] `pnpm test run
apps/e2e/tests/backend/endpoints/api/v1/internal/transactions-refund.test.ts`
— **19/19 pass** (was 14/14 on the original PR; +3 for `invoice_id`
path: renewal refund happy path, unrelated `invoice_id` rejection,
`invoice_id` on OTP rejection; +2 for second-pass: end-only replay
rejection, revoke+renewal rejection)
- [x] curl smoke against
`/api/latest/internal/payments/transactions/refund` — unknown purchase →
404, no-op → 400, negative → 400, sub-revoke-without-end → 400
- [x] **Dashboard UI end-to-end re-run pending** — the original
agent-browser pass ran before the third-pass dialog-seed fix, so any
"money + revoke" submissions may have actually sent `amount_usd = "0"`.
Re-test before un-drafting: open the refund dialog from the menu,
confirm the amount field pre-fills with the charged amount, exercise
validation (negative / exceeds-cap / no-op), and submit both an
end-subscription-only sub refund and a money+revoke OTP refund; verify
bulldozer rows and Prisma `cancelAtPeriodEnd` updates.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Ledger-driven refund flow with stable refund IDs, invoice-aware
refunds, OTP/product-revocation support, tri-state end_action (now /
at-period-end / none), and API responses that include
refund_transaction_id.
* **Bug Fixes / Improvements**
* Deterministic Stripe idempotency, stronger replay protection,
refundable-amount caps, test-mode constraints, and transactions listing
updated to surface refunds.
* **Tests**
* Expanded unit and E2E coverage for new request shape, invoice paths,
money-unit conversion, and edge cases.
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/hexclave/stack-auth/pull/1429)
<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
|
||
|
|
049c557a06 | --config-file is now a file, not a folder | ||
|
|
9102b3db75
|
[Feat] Hexclave AI integration: skill, MCP SKILL.md route, docs (#1434)
## Summary - Adds a `hexclave` SKILL.md pointer skill that fetches the live skill body on every invocation - Adds an `/SKILL.md` route on the MCP app that renders the full skill (CLI usage + docs sidebar generated from `docs.json`) - Expands `docs-mintlify/guides/getting-started/ai-integration.mdx` with three install paths (CLI, Skill, MCP) and per-agent config snippets - Updates `packages/stack-shared/src/helpers/init-prompt.ts` to install both the MCP server and skill file, with per-project vs global scope detection ## Test plan - [ ] `pnpm typecheck` - [ ] `pnpm lint` - [ ] Hit the MCP app's `/SKILL.md` endpoint locally and verify it returns valid markdown with the full docs sidebar - [ ] Render the updated `ai-integration.mdx` in Mintlify preview and confirm tabs/cards render <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Rewrote the AI integration guide with complete, user-facing instructions for connecting Stack Auth to coding agents; removed the separate MCP setup page and updated site navigation. * Added the canonical Stack Auth skill content and guidance that clients should fetch the latest skill at runtime. * **New Features** * MCP now serves the canonical Stack Auth skill dynamically and provides interactive skill responses. * Init prompts now include full MCP + skill install workflows and scope guidance. * Added a health-check endpoint. * **Chores** * Added scaffold and configs for a new skills app (build, dev, lint, and type settings). <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/hexclave/stack-auth/pull/1434?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
5cb9240bc3
|
refactor(dashboard): unify AI chat surfaces on assistant-ui Thread (#1427)
## Summary - Replace the bespoke `ai-chat-shared` chat UI (used by ask-ai, the stack companion widget, vibe coding chat, and the create-dashboard preview) with the shared `assistant-ui` `Thread` component. - Extract streaming request/format helpers into a new `components/assistant-ui/chat-stream.ts` module so each surface only owns its `ChatModelAdapter`. - Add a reusable `ToolFallback` for tool-call rendering and delete the now-unused `ai-chat-shared.tsx` (-1386 / +747 lines net). Stacked on top of `refactor/data-grid-and-dashboard-surfaces`. Base: `refactor/data-grid-and-dashboard-surfaces` → Head: `refactor/assistant-ui-chat-surfaces` · 18 files changed > Red outlines on the **after** shots mark the unified `assistant-ui` `Thread` surface in each location. ## Screenshots ### Analytics → Tables — AI Query dialog | | Before | After | |---|---|---| | **Light** | <img src="https://gist.githubusercontent.com/mantrakp04/323851437f41145aab12a27fb6c392b4/raw/analytics-tables-ai-before-light.png" width="480" /> | <img src="https://gist.githubusercontent.com/mantrakp04/323851437f41145aab12a27fb6c392b4/raw/analytics-tables-ai-after-light.png" width="480" /> | | **Dark** | <img src="https://gist.githubusercontent.com/mantrakp04/323851437f41145aab12a27fb6c392b4/raw/analytics-tables-ai-before-dark.png" width="480" /> | <img src="https://gist.githubusercontent.com/mantrakp04/323851437f41145aab12a27fb6c392b4/raw/analytics-tables-ai-after-dark.png" width="480" /> | ### Stack Companion — chat widget | | Before | After | |---|---|---| | **Light** | <img src="https://gist.githubusercontent.com/mantrakp04/323851437f41145aab12a27fb6c392b4/raw/stack-companion-before-light.png" width="480" /> | <img src="https://gist.githubusercontent.com/mantrakp04/323851437f41145aab12a27fb6c392b4/raw/stack-companion-after-light.png" width="480" /> | | **Dark** | <img src="https://gist.githubusercontent.com/mantrakp04/323851437f41145aab12a27fb6c392b4/raw/stack-companion-before-dark.png" width="480" /> | <img src="https://gist.githubusercontent.com/mantrakp04/323851437f41145aab12a27fb6c392b4/raw/stack-companion-after-dark.png" width="480" /> | ### Ask-AI command palette (⌘K → Ask AI) | | Before | After | |---|---|---| | **Light** | <img src="https://gist.githubusercontent.com/mantrakp04/323851437f41145aab12a27fb6c392b4/raw/ask-ai-cmdk-before-light.png" width="480" /> | <img src="https://gist.githubusercontent.com/mantrakp04/323851437f41145aab12a27fb6c392b4/raw/ask-ai-cmdk-after-light.png" width="480" /> | | **Dark** | <img src="https://gist.githubusercontent.com/mantrakp04/323851437f41145aab12a27fb6c392b4/raw/ask-ai-cmdk-before-dark.png" width="480" /> | <img src="https://gist.githubusercontent.com/mantrakp04/323851437f41145aab12a27fb6c392b4/raw/ask-ai-cmdk-after-dark.png" width="480" /> | ### Email editor — embedded chat panel | | Before | After | |---|---|---| | **Light** | <img src="https://gist.githubusercontent.com/mantrakp04/323851437f41145aab12a27fb6c392b4/raw/email-editor-chat-before-light.png" width="480" /> | <img src="https://gist.githubusercontent.com/mantrakp04/323851437f41145aab12a27fb6c392b4/raw/email-editor-chat-after-light.png" width="480" /> | | **Dark** | <img src="https://gist.githubusercontent.com/mantrakp04/323851437f41145aab12a27fb6c392b4/raw/email-editor-chat-before-dark.png" width="480" /> | <img src="https://gist.githubusercontent.com/mantrakp04/323851437f41145aab12a27fb6c392b4/raw/email-editor-chat-after-dark.png" width="480" /> | ## Notes for reviewers The four surfaces above all previously shared `components/commands/ai-chat-shared.tsx` (516 lines, deleted). After this PR they each own a thin `ChatModelAdapter` and render through `components/assistant-ui/thread.tsx` + the new `chat-stream.ts` helpers. Visual differences between **before** and **after** are intentional — the `assistant-ui` `Thread` brings its own message bubbles, scroll-to-bottom behaviour, composer, and `ToolFallback` rendering. The email editor's chat panel is the surface where the behaviour change is most visible (tool-call rendering now consistent with the rest of the app). Heaviest changes (lines): - `components/stack-companion/ai-chat-widget.tsx` (571) - `components/commands/ai-chat-shared.tsx` (516, deleted) - `analytics/tables/ai-query-dialog.tsx` (429) - `components/vibe-coding/chat-adapters.ts` (400) - `components/assistant-ui/chat-stream.ts` (284, new) - `components/commands/ask-ai.tsx` (274) - `components/assistant-ui/thread.tsx` (115) - `components/assistant-ui/tool-fallback.tsx` (113) ## Test plan - [ ] `pnpm lint` - [ ] `pnpm typecheck` - [ ] Manually exercise each affected surface: command-center Ask AI, stack-companion widget, vibe-coding chat, analytics tables AI query, create-dashboard preview, email editor chat. - [ ] Verify tool-call chips render consistently across all four surfaces (uses the new `ToolFallback`). - [ ] Verify streaming + cancel works on each adapter (`chat-stream.ts` is shared). |
||
|
|
c808e23b7d
|
Data-grid overhaul + session-replays / team-payments dashboard surfaces (#1424)
## Summary Refactors the dashboard data-grid into a smaller, URL-state-aware primitive and lands several new dashboard surfaces around it: per-user session replays, team-level analytics and payments, and pagination for permission definitions. Also moves session replays out from under `/analytics` to a top-level surface and adds a `project_user.last_active_at` index that the new weekly-active metrics depend on. **Base:** `dev` → **Head:** `refactor/data-grid-and-dashboard-surfaces` **Scope:** 91 files, +5,644 / −1,858. Assets in [this gist](https://gist.github.com/mantrakp04/01bf8db4c71ec7a119b73d6ee60717a7). ## Screenshots Captured from a local dev server (dashboard at `:8101`, dummy project seeded with 26 users). Standard viewport **1920×1200**, widescreen **2560×1440**. ### Users list — data-grid overhaul in context | Light | Dark | | --- | --- | |  |  | Widescreen: | Light | Dark | | --- | --- | |  |  | ### User detail — new session-replays card + weekly metrics | Light | Dark | | --- | --- | |  |  | Widescreen: | Light | Dark | | --- | --- | |  |  | ### Session replays — moved out of `/analytics` | Light | Dark | | --- | --- | |  |  | Widescreen: | Light | Dark | | --- | --- | |  |  | ### Project permissions — new pagination | Light | Dark | | --- | --- | |  |  | Widescreen: | Light | Dark | | --- | --- | |  |  | ### Other migrated surfaces | Page | Light | Dark | | --- | --- | --- | | Project picker |  |  | | Overview / setup |  |  | | Teams list |  |  | | Team permissions |  |  | | API keys |  |  | ### Scroll behaviour — new data-grid on the users list | Light | Dark | | --- | --- | |  |  | ## What's new - **`packages/dashboard-ui-components/src/components/data-grid`** — rewritten. Trimmed `data-grid.tsx` from ~1.7k LOC, split sizing logic into `data-grid-sizing.ts`, added `use-url-state.ts` for URL-synced state, and added `data-grid.test.tsx`. - **Session replays** moved from `…/analytics/replays` to `…/session-replays` (top-level surface). New `user-session-replays.tsx` card on the user detail page; new internal `route.tsx` to feed it. - **Teams** detail page gains `team-analytics.tsx` and `team-payments.tsx`. - **Permissions** — new shared `permission-definitions-pagination.ts` consumed by both project and team permission CRUD routes. - **Backend** — Prisma migration `add_project_user_last_active_at_idx` + a `lastActiveAt` index that backs the new weekly-active metrics. - **Polish** — `editable-input`, `inline-save-discard`, `settings.tsx`, walkthrough steps, and several data-table components touched in line with the data-grid rewrite. ## Notes for reviewers - The data-grid rewrite changes the *shape* of state (now URL-synced), not just internals. Consumers in `apps/dashboard/src/components/data-table/*` were updated to match — please scan those for any missed knobs. - The `analytics/replays` → `session-replays` rename is git-tracked as renames; diffs should be small in those files. - New SDK surface in `packages/template/src/lib/stack-app/session-replays/index.ts` and additions in `admin-app-impl.ts` / `server-app-impl.ts` mean OpenAPI specs (`docs-mintlify/openapi/{admin,client}.json`) regenerate; the diff is mostly mechanical. ## Test plan - [ ] `pnpm typecheck` clean - [ ] `pnpm lint` clean - [ ] Data-grid unit tests pass (`packages/dashboard-ui-components`) - [ ] Manual: users list — column resize, sort, filter, paginate; URL state reflects each change and survives reload - [ ] Manual: user detail — session-replays card lists replays; weekly-metrics card renders without `lastActiveAt` index migration applied (i.e. on a fresh DB) and after applying it - [ ] Manual: project + team permissions — pagination cursor advances and stays consistent under search - [ ] Manual: session-replays top-level page loads; old `/analytics/replays/...` URL path is no longer expected to be linked anywhere <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Session Replays app (embedded mode, search, sorting, share links) * Tabbed Team pages with Team Analytics and Team Payments dashboards * Server-backed cursor pagination, debounced search, and infinite-scroll for teams/users/permissions * **UX** * Permission and member tables refresh after edits; permission creation triggers table refresh * Users list supports sorting by last-active * **Performance** * Index added to speed ProjectUser last-active queries * **Documentation** * API/SDK docs updated for pagination and new query params * Contributor guidance: explicit git-safety rules added (no destructive git ops without consent) * **Tests** * Added e2e tests for pagination and filtering on list endpoints <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
a9623d976a
|
[Refactor] [Fix] Remove default prod creation (#1350)
With the new bulldozer rework we dont support default products anymore. Users are encouraged to currently manually handle granting products to their end users. We block api requests and new product creations that attempt to set no price, and we remove any options to set include-by-default. We also migrate users' existing product snapshots in `Subscriptions`, `OneTimePurchases`, and `ProductVersions` to have no price set if it's an include-by-default product. This will make it so that next time a user goes onto their products page, they will be informed that the pricing is invalid and it is no longer delivered by default. Note, however, that these products will still be providing items and the like to the users who have them. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Migrated legacy product snapshots so missing included-items no longer break readers. * Removed deprecated "include-by-default" pricing sentinel; pricing now requires explicit price entries and write validation rejects the old sentinel. * **Chores** * Simplified dashboard pricing flows: create/edit/save now use explicit prices and surface an alert when a formerly implicit free plan needs an explicit $0 price. * Config overrides and stored data are auto-normalized to explicit price objects. * **Tests** * Updated and added tests covering migration, validation, and switching behavior for explicit prices. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: mantrakp04 <mantrakp@gmail.com> Co-authored-by: Mantra <87142457+mantrakp04@users.noreply.github.com> |
||
|
|
15faf709f3
|
stack-cli: explicit --cloud-project-id / --config-file across exec, config, project (#1422)
## Summary Reworks the `stack` CLI surface so the cloud-vs-local choice is **explicit at every invocation**, removing the global `--project-id` / `STACK_PROJECT_ID` env var and the local-default `exec` behavior introduced earlier in this branch. ### `stack exec` - Removes `--cloud`, `STACK_EXEC_DEFAULT_TARGET`, and the implicit local default. The CLI now requires **exactly one** of: - `--cloud-project-id <id>` — run against the Stack Auth cloud API - `--config-file <path>` — run against the local emulator project mapped to that absolute config-file path - The `--config-file` branch resolves the project id by calling the existing `GET /api/latest/internal/local-emulator/project` endpoint and matching `absolute_file_path` client-side. No new backend endpoint introduced. ### `stack config pull` / `stack config push` - Both now take `--cloud-project-id <id>` per-command instead of the global flag / `STACK_PROJECT_ID` env. - `config pull --config-file` is **optional**: when omitted, the CLI uses `./stack.config.ts` from the current directory. If neither flag nor cwd file is present, it exits with a clear hint to pass `--config-file` or `cd` into a directory containing `stack.config.ts`. ### `stack project list` - Default (no flags) lists both **cloud and local emulator** projects. Each entry carries a `target: "cloud" | "dev"` field (text format: `<id>\t<displayName>\t[<target>]`). - `--cloud` / `--dev` filter to a single source (mutually exclusive — passing both errors). - On the default code path, an unreachable local emulator emits a single stderr warning (`warning: skipping dev projects — local emulator not reachable …`) and the command still succeeds with cloud results. With `--dev` explicit, the unreachable case hard-errors. ### `stack project create` - Now requires `--cloud` to make the cloud-vs-local choice explicit. There is no local alternative today; the flag exists to surface the decision so a future local-project create doesn't silently change behavior. ### Backend - Bumps the `LIMIT` on `GET /api/latest/internal/local-emulator/project` from 20 → 100 so `project list --dev` doesn't silently truncate. ### Refactors (from earlier in this branch, unchanged here) - Local-emulator paths/ports/PCK polling live in `packages/stack-cli/src/lib/emulator-paths.ts`. - Shared local-emulator admin credentials live in `packages/stack-shared/src/local-emulator.ts`. - `resolveAuth` / `resolveLocalEmulatorAuth` take an explicit `projectId: string` (no more `Flags` parameter). - New `packages/stack-cli/src/lib/local-emulator-client.ts` encapsulates the GET-and-match flow used by both `exec --config-file` and `project list --dev`. ## Breaking changes **Scripts that relied on any of the following must be updated:** | Removed | Replacement | | --- | --- | | Global `--project-id <id>` flag | Per-command `--cloud-project-id <id>` | | `STACK_PROJECT_ID` env var | Per-command `--cloud-project-id <id>` | | `stack exec --cloud` | `stack exec --cloud-project-id <id>` | | `STACK_EXEC_DEFAULT_TARGET=cloud\|local` | `--cloud-project-id <id>` or `--config-file <path>` | | `stack exec` defaulting to local emulator | Explicit `--config-file <path>` required | | `stack project create` without a flag | `stack project create --cloud …` required | ## Test plan - [x] `pnpm lint` (stack-cli, backend, e2e) — clean - [x] `pnpm --filter @stackframe/stack-cli typecheck` — clean - [x] `pnpm --filter @stackframe/stack-cli exec vitest run` — **72/72 passing** (new unit tests: `parseExecTarget`, `resolveConfigFilePathForPull`, `resolveProjectListSources`, `formatProjectList`) - [x] `pnpm test run apps/e2e/tests/general/cli.test.ts` — **73 passing, 4 skipped, 0 failing**. New e2e cases cover: - `exec` with neither flag → errors with "Specify a target" - `exec` with both flags → errors with "not both" - `exec --config-file` with missing file / missing PCK / unreachable API - `exec --config-file` happy path against a real local-emulator backend (gated on `NEXT_PUBLIC_STACK_IS_LOCAL_EMULATOR=true`) - `config pull` cwd fallback to `./stack.config.ts` - `config pull` with no `--config-file` and no cwd `stack.config.ts` → errors with `Pass --config-file …` - `project list --cloud --dev` together → errors - `project list` default with unreachable emulator → cloud results + single stderr warning - `project create` without `--cloud` → errors - All previously-`--cloud` exec cases ported to `--cloud-project-id` - [x] Manual smoke: `stack exec --help`, `stack project list --cloud --dev`, `stack project create` all emit the expected friendly errors / help text. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **New Features** * CLI `exec`, `config`, and `project` commands now require explicit targeting via `--cloud-project-id` (cloud) or `--config-file` (local emulator). * `project list` now supports `--cloud` and `--dev` flags to display projects from both sources with target indicators. * Enhanced environment variable validation for emulator service ports with proper fallback handling. * **Bug Fixes** * `project list` now gracefully handles unreachable emulator with warning fallback instead of failure. * **Tests** * Expanded test coverage for project targeting, config file resolution, and emulator connectivity scenarios. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
748d708d53
|
[Docs Mintlify] - Updates and new additions (#1401)
## Summary Refreshes the docs around Stack Auth setup, CLI workflows, local development, the local emulator, known SDK errors, self-hosting, and the public showcase. This also wires the new docs into Mintlify navigation and normalizes `sharp` dependency resolution for docs/image tooling. Base: `dev` -> Head: `docs-mintlify/updates` Scope: 17 files, +1154 / -435 ## What's New - Adds a dedicated **Stack CLI** guide covering install, auth, init modes, project commands, config pull/push, `stack exec`, and emulator commands. - Adds a full **Local Emulator** guide for QEMU requirements, ports, default credentials, config-file backed projects, image pulls, state, and troubleshooting. - Reworks **Local Development** around two supported workflows: cloud-backed local dev and emulator-backed local dev, including app env vars, local config files, CI usage, and common failure modes. - Rewrites **Self-host** around the supported `stackauth/server` Docker deployment path, including Postgres, ClickHouse, cron scheduling, seeded admin access, reverse proxy setup, SDK env vars, email, webhooks, S3 storage, upgrades, and common issues. - Adds a **Known Errors** reference for public SDK-exposed known errors, runtime `errorCode` values, and REST API handling. - Clarifies **CLI App Authentication** so users can distinguish authenticating their own CLI app from using the official `stack` command. - Updates the JWT guide to remove the missing inline viewer reference and recommend an external JWT viewer. - Adds showcase cards for Browser Use and Overworld with supporting images and styles. - Pins `sharp` to `0.34.5` through pnpm overrides and lockfile cleanup. ## Review Notes - The self-host guide was audited against the current Docker entrypoint, server env templates, seed script, ClickHouse migration behavior, cron endpoints, and SDK API URL env resolution. - The Docker image starts the backend and dashboard, but not production schedulers, so the new cron section is called out explicitly. - Managed Domain email setup is documented as operator-managed because it depends on server-side Resend/DNSimple credentials; self-hosters are directed toward Custom SMTP or their own Resend API key. - `self-host-old.mdx` is kept as a legacy reference file and is not added to navigation. - `emulator run` documentation now matches CLI behavior: it stops the emulator only when it started that emulator instance. ## Test Plan - [x] Reviewed all files changed by `origin/dev...HEAD`. - [x] Ran `git diff --check origin/dev...HEAD`. - [x] Checked IDE diagnostics for the changed docs/CLI files. - [ ] Preview Mintlify docs locally and click through new navigation entries. - [ ] Verify showcase cards and images in light and dark themes. - [ ] Smoke-test the copied self-host commands in a non-production Docker environment. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Added comprehensive Stack CLI, Local Emulator, Known Errors, and Local Development guides * Restructured Self-Hosting guide for production deployments and expanded authentication docs * Updated site navigation to include new guide pages * **New Features** * Added visual showcase section with responsive cards and hover/zoom interactions (and supporting styles) <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
2cf0f6f981
|
[Apps] Adding support app alpha and dogfooding (#1368)
<!-- 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** * Support app: inbox UI to create, view, reply, and manage conversations (status, priority, assignee, tags, internal notes). * Dashboard pages: Conversations and Support Settings; feedback can create managed conversations. * Public/internal APIs for listing, creating, updating, and fetching conversation details; client-side helpers. * **SLA** * Configurable first/next response targets, urgency classification, and timing logic. * **Data** * New conversation persistence (conversations, entry points, messages) and migration tests; preserves conversations on user/team deletion and anonymizes sender data. * **Tests** * Unit, migration, and end-to-end tests added. * **Documentation** * Updated docs describing conversation model and workflow rules. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
e0c1cc5376
|
Fix null-unsafe payments config validation for partial overrides (#1363)
## Summary - Make the `branchPaymentsSchema` custom validator tolerant of partial override objects - Avoid crashing when `payments.products` or `payments.productLines` are absent during validation - Add regression tests for partial configs plus the existing missing-line and customer-type mismatch cases ## Testing - Added Vitest coverage for partial payments configs and validation failures - Lint passed for the touched schema files - Typecheck passed for `packages/stack-shared` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved validation robustness with stricter type-safety checks for payment-related data configurations. * Enhanced error messages for clearer feedback on validation failures. * **Tests** * Added comprehensive test coverage for edge cases including missing configurations and type mismatches. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
e880df121d
|
Dev tool redesign (#1409) | ||
|
|
80a26ca15d | chore: update package versions | ||
|
|
68ae6d1f1c
|
[codex] Add TanStack Start SDK integration (#1399)
## Summary - Adds the generated `@stackframe/tanstack-start` workspace package registration. - Adds TanStack Start platform macros/dependencies to the SDK template and generator. - Adds TanStack Start cookie/token-store support plus the handler SSR guard needed by Start. ## Scope This intentionally excludes Dashboard V2 routes, hooks, components, app shell logic, and dashboard API type additions. Those stay in the existing dashboard PR/branch. ## Validation - `pnpm install --lockfile-only --ignore-scripts` - `pnpm install --ignore-scripts` - `pnpm -C packages/template lint src/components-page/stack-handler-client.tsx src/lib/cookie.ts src/lib/stack-app/apps/implementations/client-app-impl.ts` Package typecheck was attempted with `pnpm -C packages/template typecheck`, but the clean worktree lacks generated package declaration outputs for workspace dependencies such as `@stackframe/stack-shared` and `@stackframe/stack-ui`. Per repo instructions, package builds/codegen are not run by agents. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * TanStack Start integration: published SDK package, example demo app, dashboard onboarding flow, framework-aware CTAs/docs, and a TanStack-specific provider for client-only auth routes. * Improved client/server auth: safer runtime guards and consistent cookie/token-store behavior across SSR and client. * **Documentation** * New Integrations guide and expanded getting-started/setup docs with TanStack Start examples and env/key guidance. * **Chores** * Template, build, tooling, and demo config updates to support the new platform. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
acc646cb0b
|
stack-cli: cloud/local init flow, auto-create on empty projects, post-setup next-steps (#1383)
### Summary Reworks `stack init` UX, adds Sentry error reporting to the CLI, polishes the emulator start flow, and overhauls the local-emulator dashboard's "Open config file" dialog. #### `stack init` flow - **New top-level flow.** Drops the old "link existing vs. create new local" fork. `init` now asks *where* to create the project — "Stack Auth Cloud" or "Local". Adds a new `create-cloud` mode that logs the user in, creates a cloud project, mints keys, and writes `.env` — no round-trip through the dashboard. - **Conditional emulator-install warning.** The "Local" choice label only shows "(requires local emulator installation, ~1.3gb storage required)" when the QEMU image isn't already on disk; otherwise it shows "(emulator already installed)". Driven by a new `isEmulatorImageInstalled()` helper in `commands/emulator.ts`. - **Auto-create on zero-projects.** When the link-from-cloud path hits an empty project list, the CLI now prompts *"You don't have any Stack Auth projects yet. Would you like to create one?"* and, on yes, runs the same flow as `stack project create`. Skips the pointless "select a project" prompt when we just created one. - **MCP-server notice.** Before invoking the coding agent, the CLI announces that it's also registering the Stack Auth MCP server (`mcp.stack-auth.com`) so the agent can answer Stack-specific questions going forward. - **Local-emulator env header.** When `writeProjectKeysToEnv` runs in `local` mode it writes a 3-line comment header above the keys explaining they're emulator-only and only valid while the emulator is running. - **"What's next" footer.** After setup finishes, prints a short orientation block: where the sign-up/sign-in routes live (`/handler/sign-up`, `/handler/sign-in`), how to start the local emulator (for `create` mode), a dashboard deep link for cloud projects (respects `STACK_DASHBOARD_URL`), and a docs link. #### Sentry error reporting (`lib/sentry.ts`, `index.ts`, `tsdown.config.ts`) - New `lib/sentry.ts` initializes `@sentry/node` with PII scrubbing (Stack key prefixes, JWTs, home-dir paths, sensitive field names like `token`/`secret`/`password`/`dsn`). - DSN is baked at build time via a tsdown `define` sentinel (`__STACK_CLI_SENTRY_DSN__`) — no DSN in source, no runtime env-var dependency for installed users. CI sets `STACK_CLI_SENTRY_DSN_BUILD` before `pnpm build`. - Disabled when `NODE_ENV=development` or `CI`. No user opt-out. - Wired into `main()`'s catch (only for unexpected errors — `CliError`/`AuthError` still print and exit cleanly) plus `uncaughtException` and `unhandledRejection` handlers via a `handleFatal` helper. #### `stack emulator start` welcome - After a fresh start (not when reusing a running VM, not when `--config-file` keeps stdout JSON-only), prints a short "Emulator is up" block with service URLs (dashboard / backend / inbucket) and common commands (`status`, `stop`, `reset`, `run`). #### Local-emulator dashboard "Open config file" dialog The dialog at `http://localhost:26700` (when no project is loaded) used to be a single text input asking for an absolute path, with no explanation of where that path comes from. **Backend** (`apps/backend/src/app/api/latest/internal/local-emulator/project/route.tsx`): - POST is now tolerant of directory paths or paths that don't end in `.ts`/`.js`/`.mjs` — it appends `stack.config.ts` and creates the file if missing (`writeConfigToFile` mkdir's parents). Lets users paste a project folder instead of hunting for the config file. - New GET endpoint returns up to 20 most-recent `LocalEmulatorProject` rows joined with their display names, sorted by `updatedAt` desc. Same `isLocalEmulatorEnabled()` + client-auth gating as POST. **Dashboard** (`apps/dashboard/src/app/(main)/(protected)/(outside-dashboard)/projects/page-client.tsx`): - Title changed to "Open your Stack Auth project". Description now explicitly ties the file to `stack init`: *"Point the local dashboard at the `stack.config.ts` in your project. If you just ran `stack init`, it was created at the root of that project."* - Added: *"Don't have one yet? Paste your project folder path instead and we'll create stack.config.ts for you."* - Recent-projects list (clickable rows that prefill the input) fetched from the new GET endpoint when the dialog opens. - OS-specific copy-path tip below the input (macOS ⌥-Copy as Pathname, Windows Shift+RC Copy as path, Linux `realpath`). - "Open project" button is disabled when the input is empty. - All error paths (empty input, non-absolute path, server errors, exceptions) surface via destructive toasts instead of throwing. Why no native file picker: browsers do not expose absolute filesystem paths from `<input type="file">`, drag-and-drop, or the File System Access API. The backend requires an absolute path, so a Finder-style picker isn't possible from a web page. The recent list + OS tips are the workaround. ### Goal The previous `init` flow dead-ended new users: if you had no project you got an error telling you to go create one in the dashboard and come back. The happy path also forced a choice between "link existing" and "create local emulator" — not the question most users are trying to answer. The emulator dashboard's open-project dialog had similar friction: an unexplained path field with no recall of previously-opened projects. And the CLI silently swallowed unexpected errors with no telemetry. This branch makes the first-run path work end-to-end from the terminal, gives the emulator dashboard a usable open-project surface, and turns CLI crashes into actionable bug reports. ### How to review - Start with `packages/stack-cli/src/commands/init.ts` — the whole user-facing flow lives in `runInit`. Mode dispatch at the top, `handleCreateCloud` is the new cloud branch, `printNextSteps` is the footer, the MCP notice prints right before `runClaudeAgent`. - `packages/stack-cli/src/lib/sentry.ts` is small and self-contained; the sentinel-replacement contract is in `tsdown.config.ts`'s `define` block. Confirm `dist/index.js` contains zero `__STACK_CLI_SENTRY_DSN__` occurrences after a build with the env var unset, and the actual DSN host after a build with it set. - `packages/stack-cli/src/commands/emulator.ts` — `printEmulatorWelcome()` is the welcome block; `isEmulatorImageInstalled()` is the new exported helper used by `init.ts`. - `apps/backend/src/app/api/latest/internal/local-emulator/project/route.tsx` — the directory-tolerance branch is in the POST handler around the `looksLikeConfigFile` check; the GET handler is appended at the bottom. - `apps/dashboard/src/app/(main)/(protected)/(outside-dashboard)/projects/page-client.tsx` — dialog markup, recent-list fetch effect, `pathCopyTip` memo, and the toast-based error handling in `handleOpenConfigFile`. - Non-interactive (CI) paths stay strict: empty-project list still errors with a pointer to `stack project create --display-name`. No surprise project creation in CI. - No tests. The CLI has no harness for the interactive flow; verification is manual. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Recent local emulator projects listed in the config dialog for quick selection. * New CLI create-cloud mode and --display-name flag; interactive cloud project creation and clearer next steps. * Emulator start shows a welcome banner with service URLs when a new instance starts. * **Improvements** * Config dialog UX, validation, error-toasting, and platform-aware copy refined; “Open project” disabled for empty/invalid paths. * CLI: centralized interactive project creation and improved fatal error handling. * **Chores** * Sentry added and initialized for CLI error reporting. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Bilal Godil <bg2002@gmail.com> |
||
|
|
6eaf49237f
|
Add fix command registration and update agent UI label handling (#1387)
Adds a fix command to the stack cli <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added a CLI "fix" command to submit Stack Auth errors (flag, stdin, or interactive), confirm before applying changes, show a customizable progress label, and produce a final markdown report with Error, Files changed, and Solution. * Added a CLI "doctor" command to analyze projects (framework override, output directory, JSON output), run framework-specific checks, validate env and config, and exit non-zero on failures. * **Tests** * Added comprehensive end-to-end tests for the doctor command. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
647883c7ac
|
Move MCP server into a standalone apps/mcp app (#1405)
## Summary Splits the Stack Auth MCP server out of `apps/backend` and into a dedicated Next.js app at `apps/mcp/`, served on port `:42` (suffixed via `NEXT_PUBLIC_STACK_PORT_PREFIX`) and exposed in production at `https://mcp.stack-auth.com/mcp`. The backend no longer carries the MCP transport route; clients now point at the new host. Base: `dev` → Head: `chore/move-mcp-to-a-sep-app` Scope: 34 files, +1425 / −353 ## What changed - **New app** `apps/mcp/` — standalone Next.js + `@vercel/mcp-adapter`, with: - `src/app/api/internal/[transport]/route.ts` — MCP transport handler (moved from backend) - `src/app/mcp/route.ts`, `src/app/route.ts` — public landing + setup page - `src/app/health/route.ts` — health check - `src/mcp-handler.ts`, `src/setup-page.ts`, `src/analytics.ts` - **Backend** drops `apps/backend/src/app/api/internal/[transport]/route.ts` (−105) — MCP code is gone from the backend image. - **Dashboard** install hint updated to point at `https://mcp.stack-auth.com/mcp` (was `/`). - **Dev launchpad** gets an MCP tile so the new service shows up alongside the rest of the local stack. - **CI** workflows (`db-migration-backwards-compatibility`, `e2e-api-tests*`) start the MCP service in the background before running tests. - **Docs** (`docs-mintlify`, `docs/`) and `init-stack` / `init-prompt` updated to reference the new URL. - **E2E** `apps/e2e/tests/backend/endpoints/api/v1/internal/mcp.test.ts` reworked to hit the new host; `helpers.ts` and env files gain an MCP base-URL var. ## Visuals ### New `apps/mcp` setup page (`https://mcp.stack-auth.com/`) The standalone app's root now serves a self-contained MCP setup guide with per-client instructions (Cursor, VS Code, Codex, Claude Code, Claude Desktop, Windsurf, ChatGPT, Gemini CLI):  ### Dev launchpad now lists the MCP service New tile at port suffix `:42`, importance 2, alongside Backend / Dashboard / Demo app:  ## Notes for reviewers - The MCP transport endpoint moved path: it was mounted under `/api/internal/[transport]` in the backend; in the new app it's at the same path but on the dedicated host. The public-facing URL is `https://mcp.stack-auth.com/mcp`. - `apps/mcp` ships its own PostHog analytics client (`src/analytics.ts`) so the backend doesn't have to proxy events for it anymore. - Port allocation: `${PORT_PREFIX}42` (default `8142` in dev). Picked to fit the existing dev-launchpad importance-2 row. - No DB migrations. ## Test plan - [x] `apps/mcp` builds and `pnpm dev` serves on `:8142` - [x] Dev launchpad renders the new MCP tile (screenshot above) - [x] MCP setup page renders client tabs (screenshot above) - [x] E2E `mcp.test.ts` updated to hit the new host - [ ] CI green on `e2e-api-tests*` and `db-migration-backwards-compatibility` workflows (they were touched to start the MCP service) - [ ] `init-stack` / `mcp.ts` install flow lands users on the new URL <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Standalone MCP app added with a public /mcp endpoint and health check. * MCP appears in the dev-launchpad apps list. * **Documentation** * MCP endpoint updated to https://mcp.stack-auth.com/mcp in all setup guides and installer snippets. * Setup page enhanced with detailed client install tabs and instructions. * **Chores** * MCP service integrated into CI/e2e workflows and local env configs. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
7acbd8d56d | Improved StackAssertionError error logging | ||
|
|
d69773c9df | Retry OAuth refreshes | ||
|
|
5ccd8dfd38 | Update GitHub URL | ||
|
|
602cf4be82 | Fix CI/CD | ||
|
|
bd8c4489ed | Fix dev server on clean repo | ||
|
|
765b0f4e29
|
New setup (#1413) | ||
|
|
440c18c894 | chore: update package versions | ||
|
|
2e41fde9c2 | _useSession now refreshes tokens more aggressively | ||
|
|
775a3be8cc
|
small component ui fix (#1414)
<!-- 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 * **Refactor** * Enhanced CLI authentication confirmation tracking to improve session persistence and state management during sign-in flows. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
b0812c8808
|
feat(analytics): gzip event batch body to bypass adblockers (#1407)
## Summary
The `POST /api/latest/analytics/events/batch` endpoint was being dropped
by content-blocking browser extensions (adblockers) because the JSON
request body literally contains the substring `$click`. Many filter
lists pattern-match on tokens like that and silently kill the request —
analytics events from anyone with an adblocker enabled never reached our
backend.
This PR encodes the request body so keyword-matching filters can't see
those tokens, while keeping the URL path unchanged (only the body was
being matched here) and keeping older SDK clients working.
## Approach
- **Client**: gzip the JSON payload via the browser-native
`CompressionStream("gzip")` API and POST it as
`application/octet-stream`. Falls back to plain JSON if
`CompressionStream` isn't available (very old browsers / non-browser
runtimes).
- **Server**: a yup `.transform()` on the body schema detects an
`ArrayBuffer`/`Uint8Array` input, gunzips it, and `JSON.parse`s before
normal schema validation runs. The existing JSON path is untouched, so
requests from older SDK versions in the wild continue to work without
changes — and all existing schema-error snapshot tests still pass
verbatim.
- **Safety**: hard caps on compressed (1 MB) and decompressed (8 MB)
sizes guard against zip-bomb shaped abuse. `node:zlib`'s
`maxOutputLength` enforces the latter at the C++ layer.
Bonus: gzip also gives a meaningful bandwidth win — click/page-view
events compress very well — and keepalive bodies (which have a 64 KB cap
in browsers) get more headroom.
## Files
- `apps/backend/src/app/api/latest/analytics/events/batch/route.tsx` —
body schema gains `.transform()` that gunzips binary inputs; size limits
added; everything else unchanged.
- `packages/stack-shared/src/interface/client-interface.ts` —
`sendAnalyticsEventBatch` now routes through a new module-level
`encodeAnalyticsBody` helper that gzips and switches Content-Type. Same
outer signature; encoding is internal.
- `apps/e2e/tests/backend/backend-helpers.ts` — `niceBackendFetch` gains
optional `rawBody`/`rawContentType` params so tests can send non-JSON
payloads. Existing JSON callers unaffected.
-
`apps/e2e/tests/backend/endpoints/api/v1/analytics-events-batch.test.ts`
— adds two tests:
- happy path: gzipped binary body returns `inserted: 1`
- sad path: garbage bytes return 400
## Out of scope (intentional)
- **URL path renaming**: not all adblockers match on `/analytics/`, but
some do. We're shipping the body fix first and will revisit if requests
still get blocked after deployment.
- **Encryption**: gzip is enough to defeat keyword filters. Encryption
adds key-management cost with no real adversary.
- **SDK regen**: only `client-interface.ts` (in `stack-shared`) was
touched; `event-tracker.ts` (the caller) is unchanged because it already
passes a JSON string. No `pnpm -w run generate-sdks` needed.
## Test plan
- [x] `pnpm typecheck` — green
- [x] `pnpm lint` — green
- [ ] Manually verify in dev: enable adblocker, click around with
analytics enabled, confirm batch requests now go through
- [ ] Spot-check ClickHouse `analytics_internal.events` shows the
expected rows
- [ ] Run the new e2e tests (`pnpm test run
apps/e2e/tests/backend/endpoints/api/v1/analytics-events-batch.test.ts`)
and confirm both new cases plus all preexisting snapshots pass
- [ ] Confirm the JSON back-compat path still works by hitting the route
with the existing JSON-body curl/test payloads
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Analytics batch uploads now accept gzipped binary payloads; clients
can send compressed bytes and the server will detect and decompress.
* Client sender can gzip event batches (falls back to JSON) and uses
keepalive to choose JSON vs compressed bytes.
* **Bug Fixes**
* Malformed, non-gzip, or overly-large compressed payloads now return a
clear 400 response.
* **Tests**
* Added E2E and unit tests plus test-helper support for raw/gzipped
request bodies and encoding behaviors.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
|
||
|
|
185bddec9e
|
[Dashboard] Redefine the user page with tabs and updated UI (#1351)
<!-- 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** * Tabbed user profile with Activity (30-day analytics, KPIs, daily chart, top lists, recent events), Payments (transactions, subscriptions, product/item balances) and an activity heatmap sidebar. * New internal user-activity API and admin-facing activity hook; admin API client can fetch per-user activity. * **UI/UX Improvements** * Unified menus, cards and tables; inline editable user details with accept/revert; metadata editor validates JSON; country-code input has draft editing; tabs support optional icons. * **API** * Transactions endpoint and admin transaction queries now support optional customer-scoped filtering. * **Tests** * End-to-end coverage for the user-activity endpoint. <!-- end of auto-generated comment: release notes by coderabbit.ai --> <img width="1326" height="752" alt="image" src="https://github.com/user-attachments/assets/97c04dca-db59-4357-98b1-8eae5a7a3673" /> <img width="1142" height="251" alt="image" src="https://github.com/user-attachments/assets/e1aa44fc-0d7e-436d-90a5-c7cb15155e24" /> <img width="1170" height="1125" alt="image" src="https://github.com/user-attachments/assets/bf6659fd-a9b5-4ae6-a13d-dab9956ad650" /> |
||
|
|
c01c052ac9
|
[Refactor][Feat] Implement Plan Limits for Hard-and-Soft Item Caps (#1215)
### Suggested Review Areas Please see `plans.ts` and `seed.ts` to verify whether the item caps are where they should be. Outside of that, each commit should be atomic so stepping through the commits should give you an idea of how I implemented each limit. ### Discussion Something to discuss: when a user cancels team/growth we regrant free fine, but any extra-seats they had just keeps billing. So they end up paying ~$29/mo per extra-seat on top of free's 1 seat, which is strictly worse than just staying on team. This surfaced while manually testing this PR, we only enforce the add-on base requirement at purchase time, nothing cascades on cancel. Should we cascade cancel add ons? ### Context Now that we have a stable suite of products for stack-auth, we want to limit the items under each product a customer has access to based on their plan. So for example, a free plan user has a certain amount of emails they can send out each month, and so on. We try to implement limits in this PR. ### Summary of Changes Implemented hard limits for dashboard admins, analytics per-query timeouts, sent email monthly capacity, events, and session replays. Implemented a soft cap for auth users (where if there's a signup beyond the limit, we log it to sentry so we can manually choose to email that user/team). For auth users, we do not block new user sign ups once plan limit has been hit. We also don't degrade or impact the customer experience. It logs to sentry and it is up to us to take manual action to email the user to upgrade the plan. Also, implementation wise, we count all the users across all the projects for this team and compare it to their plan item limit, rather than debiting items like we do for other approaches. As a soft cap, this should be fine plus this is a better source of truth. For email capacity, we operate a monthly limit of emails. Once this is hit, no more emails can be sent until the next month/ a plan upgrade. These emails will be treated as a send error, so they can be manually resent once the capacity is reset. With respect to the `email-queue` state engine, they go from `SENDING`->`SERVER_ERROR`, hooking into the existing state engine flow, with an external error that shows it's because of the rate limit. This is cleaner than inventing a new state that is identical for all intents and purposes to `SERVER_ERROR`. We check in processSingleEmail since that maps to the sending state. For analytics query timeouts, the backend route accepts a timeout parameter with the request. The way we implement the timeout for each query is by taking the `min(request_timeout,plan_timeout)` and using that. This determines how long a query can run for. For analytics events, there are server-side events (like refresh token refreshes or sign up rule triggers) and client side events (like page views or clicks). When these events occur, they are written to the events table in clickhouse. We choose to implement a hard cap for the total events, not just server side or client side. Once the cap is hit, we stop storing the events and display a banner on the analytics page. A different banner renders when we are at >=80% of total plan capacity. For session replays, we stop creating new session replays when the limit is hit. Old replays can still have chunks appended to them. The source of truth here is the session replay table- a new replay corresponds to a new row in the table. We have similar banners as to the events. Dashboard admins should be 4 for both team and unlimited. #### Implementation Caveats For debiting items across these limits, we now use `tryDecreaseQuantity` at the beginning. This means we debit first if possible before conducting the action (like writing events to clickhouse). In practice, this means that if clickhouse fails, then the user is debited for something that doesn't happen. However trying to build a refund workaround would be very clunky, and also, clickhouse is reliable. For debits that are very small in the order of things (say, 200 items on a 100k plan), it doesn't mean much. For emails, we don't debit items if it's a retry. This prevents the user for being charged multiple times for effectively one email. ### UI Changes The only UI changes in this PR are having certain banners render in analytics when a customer is approaching/ is at their monthly limit of session replays or events. ### Out of Scope for this PR We do not have metered pricing yet, so events/session replays/ email use beyond the limits cannot be charged yet. This is why for this implementation, we rely on hard and soft caps. We do not implement payment per-transaction pricing yet. That is deferred to a followup PR. The UI for the onboarding call will be set up as part of the overall onboarding flow which doesn't exist yet, so it has been deferred. Since the UI for the dashboard home page and project/account settings is currently being reworked, finding a better spot for plan upgrades is not handled in this PR. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Session replays added as a monthly included entitlement; onboarding calls added to Team/Growth plans. Dashboard banners warn about analytics-event and session-replay limits. Projects page adds extra-seat flow and improved invitation error handling. * **Behavior Changes** * Monthly renewal semantics for emails-per-month and analytics-events; analytics query timeouts now respect plan limits and are clamped. Email sends, analytics events, and new session creation are blocked when quotas are exhausted. Growth plan seats set to 4. * **Tests** * E2E and unit tests added to verify quota enforcement and free-plan regranting. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Mantra <87142457+mantrakp04@users.noreply.github.com> |
||
|
|
c69a27017b
|
fix team invitation email check + verification code TOCTOU (#1365)
## Summary Two authorization fixes in the backend. Both are pre-existing in `dev` and were found during a security audit of `apps/backend/src`. ### 1. Team invitation accept — email not validated [`team-invitations/accept/verification-code-handler.tsx`](https://github.com/stack-auth/stack-auth/blob/dev/apps/backend/src/app/api/latest/team-invitations/accept/verification-code-handler.tsx) destructured the invited email as `{}` and only used `data.team_id` + the accepting `user`. Any signed-in user in the tenancy who possessed the 45-char code could join the team as themselves — the invitation was not actually bound to the email it was addressed to. **Attack scenarios that work without this fix** - Forwarded invitation email (shared inbox, assistant inbox, auto-forward rules). - Screenshot of the invitation link pasted into Slack / Notion. - Insider with server-access reading the email outbox (`GET /api/latest/emails/outbox` returns rendered `html` + `variables.teamInvitationLink`). - Stale invite still sitting in spam after the invitee forwarded it elsewhere. **Fix.** The accept handler now requires that the accepting user owns the invited email as a *verified* contact channel on their account. Matches the invariant already used by the "list invitations for me" endpoint ([`team-invitations/crud.tsx:41-66`](https://github.com/stack-auth/stack-auth/blob/dev/apps/backend/src/app/api/latest/team-invitations/crud.tsx#L41-L66)). Rejections return a new `TEAM_INVITATION_EMAIL_MISMATCH` (403) error. ### 2. Verification-code handler TOCTOU [`route-handlers/verification-code-handler.tsx`](https://github.com/stack-auth/stack-auth/blob/dev/apps/backend/src/route-handlers/verification-code-handler.tsx) had a classic read-then-write TOCTOU: ```ts const verificationCode = await prisma.verificationCode.findUnique(...); if (verificationCode.usedAt) throw new KnownErrors.VerificationCodeAlreadyUsed(); // ... validation ... await prisma.verificationCode.update({ data: { usedAt: new Date() } }); // unconditional return await options.handler(...); ``` Five concurrent requests with the same code all pass the `if (usedAt)` gate, all mark the code used, all run the post-handler. For OTP sign-in the handler calls `createAuthTokens` which writes a fresh `projectUserRefreshToken` row per call — so **one OTP → N refresh tokens**. `auth/sessions/current` only revokes by `id: refreshTokenId` and there is no bulk-revoke for passwordless users (only password change in [`users/crud.tsx:1210`](https://github.com/stack-auth/stack-auth/blob/dev/apps/backend/src/app/api/latest/users/crud.tsx#L1210) does `deleteMany`). A phished OTP therefore becomes a session-persistence primitive. **Fix.** Replace the unconditional `update` with a conditional `updateMany({ where: { …, usedAt: null } })` executed before `options.handler`; if `count === 0` the race was already lost and we throw `VERIFICATION_CODE_ALREADY_USED` (409). This also benefits MFA sign-in and passkey sign-in, which share the same handler. ## Changes | File | Change | |---|---| | `team-invitations/accept/verification-code-handler.tsx` | Require verified contact channel matching `method.email` | | `route-handlers/verification-code-handler.tsx` | Atomic `updateMany` claim gated on `usedAt: null` | | `stack-shared/src/known-errors.tsx` | New `TeamInvitationEmailMismatch` (403) | | `e2e/.../team-invitations.test.ts` | Two new tests (mismatch + happy path) | | `e2e/.../auth/otp/sign-in.test.ts` | One new test: 5 parallel redemptions of one OTP → 1× 200 + 4× 409 | ## Test plan - [x] `pnpm test run apps/e2e/tests/backend/endpoints/api/v1/team-invitations.test.ts` — 27/27 pass - [x] `pnpm test run apps/e2e/tests/backend/endpoints/api/v1/auth/otp/sign-in.test.ts` — 12/12 (+ 4 pre-existing `it.todo`) - [x] `pnpm test run apps/e2e/tests/backend/endpoints/api/v1/auth/password` — 33/33 (+ 7 pre-existing todos) - [x] `pnpm test run apps/e2e/tests/backend/endpoints/api/v1/contact-channels` — 24/24 - [x] `pnpm test run apps/e2e/tests/backend/endpoints/api/v1/auth/passkey apps/e2e/tests/backend/endpoints/api/v1/auth/mfa` — 16/16 - [x] `pnpm --filter @stackframe/backend typecheck` — clean - [x] `pnpm --filter @stackframe/backend lint` + `pnpm --filter @stackframe/stack-shared lint` — clean ## Notes - The broader "plaintext credentials in DB + Sentry logs every header" finding from the same audit is **not** in this PR — a scrubber for `Sentry.setContext` request headers + unit tests is prepared on a local stash and will go out as a separate PR. - The team-invitation fix does not require any config change; fresh signups via the OTP / password flows that set `primary_email_verified: true` during creation already land the user with a verified channel matching the invited email, so the happy path is unaffected. ### Follow-up review (Codex) Addressed in follow-up commit `954cddb`: - **Finding 1 (High)**: mismatched invite acceptance was consuming the invitation before rejecting. Moved the email-ownership check into the pre-claim `options.validate` hook so a wrong-email attempt leaves `usedAt` untouched and the real recipient can still redeem. New test asserts this end-to-end. - **Finding 3 (Medium)**: invitation stored `body.email` raw but contact channels are stored via `normalizeEmail`, so case-varied invites (e.g. `Alice@Example.com`) wouldn't match a `alice@example.com` channel. `send-code` now normalizes on storage and `accept` normalizes on compare for back-compat with already-issued invites. New test covers the mixed-case path. - **Finding 2 (partial)**: added `expiresAt > now` to the atomic claim predicate for the boundary case where a code expires between the read and the claim. The reviewer's broader point about the `attemptCount` rate-limit check being non-atomic with its own increment **pre-dates this PR** (it reads the in-memory `verificationCode.attemptCount` from line 150, not a fresh read) and exists independently of the `usedAt` TOCTOU I'm fixing here. Tracking that as a separate follow-up so this PR stays scoped to the two originally-flagged issues. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Invite acceptance now requires the invitee’s verified, normalized (case‑insensitive) email; mismatches return HTTP 403 (TEAM_INVITATION_EMAIL_MISMATCH). * Client APIs now surface the new email-mismatch error alongside verification errors. * **Bug Fixes** * OTP verification codes are now guarded against parallel double‑redeem so only one request succeeds. * **Tests** * Added E2E tests for invitation email validation, non‑consuming rejection, case‑insensitive matching, and OTP concurrency. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
0ab2654051 | chore: update package versions | ||
|
|
e2dc5f5ee0
|
[codex] fix OAuth redirect contract (#1393)
## Summary - Route browser OAuth redirects through the configured `redirectMethod` instead of hardcoded `window.location` calls. - Keep OAuth redirect APIs pending after navigation starts, including custom redirect methods. - Add `cliAuthConfirm` handler URL metadata and custom-page prompt coverage. - Update SDK spec text for browser OAuth callback and `returnTo` behavior. ## Root Cause OAuth helpers previously combined URL construction with direct browser navigation. That bypassed configured redirect methods and made it too easy for public redirect APIs to resolve after navigation started. ## Impact Browser SDK consumers get consistent redirect behavior across built-in and custom navigation methods. `returnTo` is handled as the post-callback destination while the OAuth callback URL remains fixed to the configured handler route. ## Validation - `pnpm test run packages/template/src/lib/auth.test.ts` - `pnpm test run apps/e2e/tests/js/oauth.test.ts` - `pnpm -C packages/template lint` - `pnpm -C apps/e2e lint` - `pnpm -C packages/template typecheck` - `pnpm -C apps/e2e typecheck` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added CLI authorization confirmation page/flow for terminal-based auth. * Added optional returnTo parameter for OAuth to control post-auth redirects. * Exposed configurable redirect behavior so apps follow the chosen redirect method. * **Bug Fixes** * OAuth callback now uses app navigation/queued redirects and shows a fallback link instead of forcing location.assign. * **Tests** * Added unit and e2e tests covering OAuth URL generation, scope handling, and CLI auth confirmation. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
5e5cfdec4f
|
[Dashboard][Backend][SDK] - Adds sharable session replay ids. (#1294)
# Shareable Session Replay Links Adds the ability to share individual session replays via unique, direct URLs. https://www.loom.com/share/1e3298a19b114fc38af4bc43dcd5ec48 ## What changed - New admin endpoint — GET /api/v1/internal/session-replays/:id - Fetches a single session replay by ID with user metadata (display name, primary email) and chunk/event counts - Returns 404 if the replay doesn't exist - Admin-only access, consistent with the existing list endpoint ## New standalone replay page — /projects/:projectId/analytics/replays/:replayId - Thin server page wrapper that passes the replay ID to the existing PageClient - PageClient detects standalone mode via initialReplayId prop and fetches replay metadata directly instead of loading the full session list - Sidebar is hidden; the replay viewer takes the full width - "Back to all replays" link shown under the page title ## Copy link button - Moved from per-session sidebar items to the replay viewer header (next to the settings gear) - Copies a direct URL to the currently selected replay ## SDK plumbing - AdminGetSessionReplayResponse type in stack-shared - getSessionReplay() on StackAdminInterface, StackAdminApp interface, and _StackAdminAppImplIncomplete ## Tests - Happy path: fetch single replay by ID with inline snapshot - 404 for nonexistent replay ID - 401 for non-admin access (client and server) ## Test plan - [ ] Open /analytics/replays, select a replay, click the link icon in the header — verify URL is copied to clipboard - [ ] Paste that URL in a new tab — verify the standalone replay page loads and plays the correct replay - [ ] Verify "Back to all replays" link navigates back to the list page - [ ] Verify the original /analytics/replays list page still works as before (selecting, filtering, pagination) - [ ] Run pnpm test run session-replays <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Backend: internal endpoint to fetch a single session replay with user info, millisecond timestamps, and chunk/event counts. * Admin SDK/App: added response type and admin method to retrieve a single session replay; admin app maps response into the app model. * Dashboard: standalone session-replay page, UI adjustments for standalone mode, and a “copy replay link” button. * **Tests** * Added end-to-end tests for retrieval, not-found, and access-control scenarios. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
9d1eee8ab8
|
Add useCliAuthConfirmation hook and customizable cliAuthConfirm URL target (#1388)
## Summary - Extract CLI auth confirmation into a `useCliAuthConfirmation()` hook (status / error / isLoading / authorize / retry) so custom pages don't have to reimplement the protocol; `CliAuthConfirmation` now consumes the hook. - Make `cliAuthConfirm` a first-class handler URL target — resolved via `resolveHandlerUrls`, customizable per project, and used by `promptCliLogin` through a new `buildCliAuthConfirmUrl()` helper. - Move `StackContext` to its own module so the hook can be unit-tested with a test double without tripping the client-version sentinel; register `cliAuthConfirm` in custom-page prompts and the dev-tool components tab; export the hook + types from `@stackframe/stack`. ## Test plan - [ ] `pnpm typecheck` - [ ] `pnpm lint` - [ ] `pnpm --filter @stackframe/stack test cli-auth-confirm url-targets` - [ ] Manually verify default `/handler/cli-auth-confirm` flow + a project with a custom `cliAuthConfirm` URL <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Adds a CLI authentication confirmation page with clear states (invalid, authorizing, redirecting, success, error), retry action, and flows for signed-in and anonymous users. * CLI login URL generation now derives from the configured handler target and app base, improving reliability. * CLI confirmation page exposed in the components/dev UI for previewing. * **Tests** * End-to-end and unit tests covering confirmation behaviors and URL generation. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
b3d0ab66cc
|
fix(stack-shared): make process.env access browser-safe (#1391)
## Summary - Bare `process.env.X` accesses in `stack-shared` throw `ReferenceError: process is not defined` when the package is bundled into a browser app without a `process` shim (e.g. a plain Vite app). The most reachable offenders are in `StackAssertionError`'s constructor and `schema-fields.ts`'s Neon Basic-auth validator, both of which can run on the client during normal sign-in flows with `@stackframe/react`. - Extracted a zero-dependency `getProcessEnv` helper at `packages/stack-shared/src/utils/process-env.tsx` and routed the bare references through it. Returns `undefined` when `process` is not defined; otherwise behaves like a normal `process.env[name]` read, so Next.js/webpack inlining is unchanged on the server. - Touched: `schema-fields.ts:884` (`STACK_INTEGRATION_CLIENTS_CONFIG`), `utils/errors.tsx:81` (`NEXT_PUBLIC_STACK_DEBUGGER_ON_ASSERTION_ERROR`), `utils/promises.tsx` (`NODE_ENV` in `runAsynchronouslyWithAlert`), `utils/esbuild.tsx:16` (`NODE_ENV`, also reordered the `typeof process` guard so the env access is unreachable in browsers). ## Why a separate helper module `utils/env.tsx` already exists but its `getEnvVariable` explicitly throws in the browser, so it can't be reused here. The new module has zero imports so it can be safely consumed from low-level utilities like `errors.tsx` without creating a cycle (env.tsx ↔ errors.tsx). ## Test plan - [x] `pnpm lint` passes - [x] `pnpm typecheck` passes - [ ] Reproduced the original failure in a Vite + `@stackframe/react` app: sign-in flow logged `ReferenceError: process is not defined` from `StackAssertionError`, plus `clientSecret must not be empty` cascading from the same path - [ ] Verify the same flow in a Vite app no longer throws once `@stackframe/react` is rebuilt against this `stack-shared` change - [ ] Confirm Next.js consumer behavior is unchanged (env vars still inlined at build time for `NEXT_PUBLIC_*`) 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **Refactor** * Improved environment variable handling across shared utilities for enhanced browser compatibility and safety. Introduced a new utility for dynamic, browser-safe environment variable access that prevents errors in non-Node.js environments. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
65d87a4836
|
Dashboard: DataGrid refactor + layout (stacked on overview-revamp) (#1338)
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 Stacked on `overview-revamp` (now rebased against `dev`). Introduces a first-class `DataGrid` component in `@stackframe/dashboard-ui-components`, migrates every dashboard table off the legacy `DesignDataTable` / hand-rolled `<Table>` pattern to it, and ships a matching dashboard design guide. Since the last writeup the `DataGrid` runtime has been substantially rewritten: the virtualizer now supports `rowHeight="auto"` with `estimatedRowHeight`, every column can opt into `cellOverflow: "wrap"`, the toolbar + header stick under a configurable `stickyTop`, and the seeded dummy data has been fleshed out so the migrated surfaces render with realistic density. The AI-analytics prompt was also extended with full schema docs for the auth / team / email / payments tables so natural-language queries produce better SQL. **Base:** `dev` → **Head:** `ui-fixes-minor` **Scope:** 39 files, ~+6.5k / -2.4k ## Screenshots Captured against the seeded Demo Project on the local dashboard (`admin@example.com` via mock GitHub OAuth). Viewport: **1920×1200** (standard) and **2560×1440** (widescreen). Assets hosted in [this gist](https://gist.github.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9). ### Overview — revamped metrics + line chart | Light | Dark | | --- | --- | |  |  | Widescreen: | Light | Dark | | --- | --- | |  |  | ### Users — DataGrid with seeded rows | Light | Dark | | --- | --- | |  |  | Widescreen: | Light | Dark | | --- | --- | |  |  | ### Transactions — new DataGridToolbar + sticky chrome | Light | Dark | | --- | --- | |  |  | Widescreen: | Light | Dark | | --- | --- | |  |  | ### Teams | Light | Dark | | --- | --- | |  |  | Widescreen: | Light | Dark | | --- | --- | |  |  | ### Email Outbox | Light | Dark | | --- | --- | |  |  | Widescreen: | Light | Dark | | --- | --- | |  |  | ### Payments — Customers | Light | Dark | | --- | --- | |  |  | Widescreen: | Light | Dark | | --- | --- | |  |  | ### Sticky behaviour — scrolled views Grids scrolled down ~600px. The page header is still pinned, and the `DataGrid` toolbar + column header row stay put under it (backdrop-blur + `stickyTop` offset) while the virtualized body rows scroll past. Compare the scrolled view against the top-of-page view above. | Page | Light | Dark | | --- | --- | --- | | Users |  |  | | Teams |  |  | | Transactions |  |  | | Payments Customers |  |  | | Email Outbox |  |  | | Analytics Tables |  |  | ### Other migrated surfaces | Page | Light | Dark | | --- | --- | --- | | Analytics Tables |  |  | | Emails |  |  | | Email Sent |  |  | | Domains |  |  | | Webhooks |  |  | | External DB Sync |  |  | ## What's new ### `DataGrid` in `@stackframe/dashboard-ui-components` A new, fully-typed, fully-controlled grid component under `packages/dashboard-ui-components/src/components/data-grid/`. Single source of truth for tabular UI across the dashboard. Package files: - `data-grid.tsx` — main grid renderer (virtualized rows, sticky toolbar + header) - `data-grid-toolbar.tsx` — built-in toolbar (search, columns, density, export) - `data-grid-sizing.ts` — column width / flex / min-width resolution - `state.ts` — state helpers (`createDefaultDataGridState`, sort / select / paginate utilities, `exportToCsv`, date formatters) - `strings.ts` — i18n string table + `resolveDataGridStrings` - `types.ts` — public types (`DataGridColumnDef`, `DataGridProps`, `DataGridState`, `DataGridDataSource`, etc.) - `use-data-source.ts` — `useDataSource` hook with `client` / `server` / `infinite` modes - `index.ts` — package entrypoint Features: - Controlled state (`state` + `onChange`) covering sorting, pagination, column visibility, column widths, column pinning, selection, date-display mode, and quick search. - Column definitions with `string` / `number` / `date` / `dateTime` / `boolean` / `singleSelect` / `custom` types, custom `renderCell`, custom sort comparators, per-column `parseValue` / `dateFormat`, pinning, align, flex / min / max width. - **Cell overflow control** — new `cellOverflow: "truncate" | "wrap"` per column. `"wrap"` + `rowHeight="auto"` lets rows grow to fit multi-line content. - **Dynamic row heights** — `rowHeight` now accepts `"auto"` with an `estimatedRowHeight` hint for the virtualizer, eliminating scroll-position jank while rows are still being measured. - **Sticky chrome with `stickyTop`** — the toolbar and header stick under a caller-provided offset (matching the page header height) with a proper blur backdrop. See the _Sticky behaviour — scrolled views_ section above for the visual. - Client-side sort + quick-search + pagination via `useDataSource` — consumer never pre-sorts / paginates. - Server-side and async-generator data sources for streaming / cursor pagination. - Paginated and infinite-scroll UI modes. - CSV export + clipboard copy. - Row single / multi selection with shift-range anchor. - Row + cell click / double-click callbacks. - Pluggable toolbar / footer / empty / loading states and i18n strings. ### Dashboard design guide New `apps/dashboard/DESIGN-GUIDE.md`: prescriptive, AI-readable source of truth for dashboard UI. Documents when to use each `design-components` primitive, the `DataGrid` canonical pattern, color / typography / spacing / motion rules, route-specific guidance, and the migration priority. Now also documents the new `cellOverflow` and dynamic-`rowHeight` patterns, and marks `DesignDataTable` as deprecated in favor of `DataGrid` + `useDataSource` + `createDefaultDataGridState`. ### Overview page revamp `apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/(overview)/line-chart.tsx` — line chart rewritten on top of the shared `AnalyticsChart` / `DonutChartDisplay` primitives, feeding the revamped Overview. ### Data-table migrations Every shared table under `apps/dashboard/src/components/data-table/` has been rewritten on top of `DataGrid`: - `api-key-table.tsx` - `payment-product-table.tsx` - `permission-table.tsx` - `team-member-search-table.tsx` - `team-member-table.tsx` - `team-search-table.tsx` - `team-table.tsx` - `transaction-table.tsx` — now also wires in `DataGridToolbar` with search / column visibility - `user-search-picker.tsx` - `user-table.tsx` — extracted `USER_TABLE_COLUMNS` for readability / reuse ### Page adoption Page-level tables migrated to `DataGrid` (or the new `useDataSource` + `createDefaultDataGridState` pattern): - `(overview)/line-chart.tsx` - `analytics/tables/query-data-grid.tsx` (now with sticky header) - `domains/page-client.tsx` - `email-drafts/[draftId]/page-client.tsx` - `email-outbox/page-client.tsx` (with `DataGridToolbar`) - `email-sent/page-client.tsx`, `grouped-email-table.tsx`, `sent-emails-view.tsx` - `emails/page-client.tsx` - `external-db-sync/page-client.tsx` - `payments/layout.tsx`, `payments/customers/page-client.tsx`, `payments/products/[productId]/page-client.tsx` - `users/[userId]/page-client.tsx` - `webhooks/page-client.tsx`, `webhooks/[endpointId]/page-client.tsx` - `design-language/page-client.tsx`, `design-language/realistic-demo/page-client.tsx` - `playground/page-client.tsx` ### Backend & supporting changes - `apps/backend/src/lib/ai/prompts.ts` — extends the AI-analytics prompt with detailed schema docs for `contact_channels`, `teams`, `team_member_profiles`, `team_permissions`, `team_invitations`, `email_outboxes`, `project_permissions`, `notification_preferences`, `refresh_tokens`, and `connected_accounts`, so natural-language queries have richer context to compile against. - `apps/backend/src/lib/seed-dummy-data.ts` — additional OAuth providers on seed users, improving dummy-data coverage for the migrated tables (visible on the Users grid). - `apps/dashboard/src/app/globals.css` — adds `--data-grid-sticky-top` token used to derive the grid's sticky offset under the page header. - `packages/template/src/dev-tool/dev-tool-core.ts` — persist the "closed" state when the user closes the dev-tool panel so it doesn't reopen on next load. ## Notes for reviewers - Rebased onto latest `dev`; conflict in `api-key-table.tsx` resolved by keeping the `DataGrid` implementation (consistent with the other migrated tables). - `DesignDataTable` is still in the codebase but marked deprecated in the design guide — new code must use `DataGrid`. - `DataGrid` is fully controlled: consumers must pass state + onChange, must feed `rows` from `useDataSource` (never raw arrays), and must define columns outside the component or via `useMemo`. The guide's §4.12 spells this out. - `rowHeight="auto"` is opt-in; the default fixed-height virtualization path is unchanged and remains the fast path for dense, single-line grids (users, transactions, etc.). - Screenshots are JPEG this round — the local capture tooling's PNG path was producing blank frames, so the new set is `.jpg` end-to-end. Same viewports, same seeded project. ## Test plan - [ ] `pnpm lint` passes - [ ] `pnpm typecheck` passes - [ ] Load the dashboard and verify every migrated surface renders, sorts, searches, paginates, and handles row-click navigation: - [ ] Overview (line chart + donut metrics) - [ ] Users list + user detail (teams, sessions, permissions, API keys) - [ ] Teams list + team detail (members, permissions) - [ ] Domains - [ ] Emails, email-sent, email-outbox, email-drafts - [ ] Webhooks list + endpoint detail - [ ] Payments customers, product detail, transactions (new toolbar) - [ ] External DB sync - [ ] Analytics query table (sticky header) - [ ] Verify infinite-scroll surfaces (domains, etc.) load additional rows on scroll - [ ] Verify sticky header stays below the page header in light and dark themes - [ ] Verify CSV export produces correct output on a representative table - [ ] Verify column resize, visibility toggle, and sort work across themes - [ ] Verify `cellOverflow: "wrap"` rows grow to fit when `rowHeight="auto"` and clip when `rowHeight` is numeric - [ ] Spot-check AI analytics queries against the new schema context (contact_channels, teams, email_outboxes, …) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **New Features** * Unified table components across dashboard with improved infinite pagination and quick search. * **Improvements** * Enhanced table performance with sticky headers and better row height handling. * Improved sorting, filtering, and data loading with consistent state management. * Better visual consistency across all data grids and table layouts. * **UI/Styling** * Refined table styling for better text truncation and content wrapping. * Optimized layout spacing and alignment across dashboard tables. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Developing-Gamer <maxcodes11110@gmail.com> Co-authored-by: Armaan Jain <84474476+Developing-Gamer@users.noreply.github.com> Co-authored-by: Konstantin Wohlwend <n2d4xc@gmail.com> |
||
|
|
5423d774a2
|
feat(stack-cli): auto-install emulator deps on pull (#1384)
## Summary - `stack emulator pull` now preflights VM dependencies (QEMU binaries, socat/curl/nc/lsof/openssl/zstd, and aarch64 UEFI firmware on arm64) before downloading. - Missing deps are listed, then installed with user confirmation via `brew` on macOS (bootstrapping Homebrew itself if absent) or `sudo apt-get` on Linux. - Skipped when `--skip-snapshot` is passed, since that path never boots the VM. - `gh` / `GITHUB_TOKEN` are intentionally excluded from the auto-install set. ## Test plan - [ ] `node packages/stack-cli/dist/index.js emulator pull` on a machine with all deps present → no prompt, proceeds as before. - [ ] Unlink a dep (e.g. `brew unlink zstd`) and rerun → missing dep listed, decline prompt → exits with a clear error; accept prompt → brew install runs and pull continues. - [ ] `emulator pull --skip-snapshot` still bypasses the dep check. - [ ] Linux path: missing binaries trigger `sudo apt-get update && sudo apt-get install -y …`. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Emulator pull now detects missing host dependencies and, on macOS/Linux with an interactive terminal and supported package tools, shows a proposed install plan, prompts for confirmation, and can auto-install required packages (including optional ARM64 firmware). Homebrew will be bootstrapped if absent. * Use --skip-snapshot to bypass the interactive dependency check and installation. * **Behavior** * In non-interactive or unsupported environments, the tool falls back to the prior preflight behavior instead of attempting installation. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
3b8667d5f8
|
cli add back init options (#1379)
<!-- 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** * Added a "create-cloud" mode to the CLI init flow. * New interactive project creation flow that can prompt for display name and select/create a team-backed project. * **Behavior Changes** * Init now resolves mode from flags, config, or interactive prompts; prompts to choose linking vs creating when inputs are missing. * Non-interactive runs now error when required inputs are absent; cloud linking offers auto-create in interactive mode. * **Refactor** * Centralized auth, project-creation, and env key writing for clearer, safer linking and creation flows. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: aadesh18 <110230993+aadesh18@users.noreply.github.com> |
||
|
|
04d57d91ed
|
fix(emulator): move mock OAuth off 8114 to avoid pnpm dev conflict (#1385)
## Summary
- The emulator's mock OAuth server bound to `${PORT_PREFIX}14` (8114)
inside the VM and the host forwarded the same port, colliding with `pnpm
dev`'s mock-oauth-server on 8114.
- Moves the emulator's mock OAuth to `EMULATOR_MOCK_OAUTH_PORT` (default
`26704`, joining the existing `267xx` host port block) and binds the
VM-internal mock to the same port. Same port on both sides keeps the
OIDC issuer URL (`http://localhost:26704`) resolvable identically from
the browser and from the backend inside the VM.
- Plumbed via `runtime-config.iso` as
`STACK_EMULATOR_MOCK_OAUTH_HOST_PORT`, read by cloud-init into
`STACK_OAUTH_MOCK_URL` + new `STACK_OAUTH_MOCK_PORT`;
`mock-oauth-server` now prefers `STACK_OAUTH_MOCK_PORT` so `pnpm dev`
(which doesn't set it) stays on 8114.
## Files
- `docker/local-emulator/qemu/run-emulator.sh` — new
`EMULATOR_MOCK_OAUTH_PORT`, hostfwd/ensure_ports_free/runtime.env
updates
- `docker/local-emulator/qemu/cloud-init/emulator/user-data` — reads the
host port, sets `STACK_OAUTH_MOCK_URL` + `STACK_OAUTH_MOCK_PORT`
- `apps/mock-oauth-server/src/index.ts` — honors `STACK_OAUTH_MOCK_PORT`
- `packages/stack-cli/src/commands/emulator.ts` — default + runtime.env
entry
## Test plan
- [ ] `pnpm emulator:build` succeeds and new snapshot boots
- [ ] `stack emulator start` with `pnpm dev` running on 8114 — no port
collision
- [ ] OAuth sign-in via mock provider completes end-to-end in the
emulator
- [ ] `pnpm dev` mock OAuth unchanged (still 8114)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
## Release Notes
* **New Features**
* The mock OAuth server port is now configurable in the local emulator
with a sensible default, allowing custom port assignments via
environment variable.
* **Improvements**
* Updated port forwarding and environment variable handling to ensure
consistent mock OAuth endpoint configuration across host and guest
systems in the emulator.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
|
||
|
|
d1751a7634
|
fix(init-prompt): require StackProvider for all frameworks (#1374)
## Summary - The init prompt marked the `StackProvider` step as *React only* and placed it after the `StackHandler` step. Following it on a Next.js project produced a layout with no provider, so `StackHandler` crashed at runtime with `useStackApp must be used within a StackProvider`. - Make the provider step unconditional and move it ahead of the handler step so the dependency order matches the instruction order. Also quote the exact error message so the model won't skip it. ## Test plan - [ ] Run `npx @stackframe/stack-cli init` (or the web flow) against a fresh Next.js app and confirm `/handler/[...stack]` renders without the `useStackApp` error. - [ ] Re-run against a Vite/React app to confirm the reordered instructions still produce a working setup. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Added explicit global MCP config file path guidance for several coding agents. * Documented required provider configuration across supported frameworks. * Clarified where to place provider wrappers in root app layouts (including Next.js app/layout). * Reordered setup steps to surface the required "Wrap your app in a Stack provider" step and updated step numbering. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
cbd945e3a6
|
[codex] Fix Neon malformed Basic auth validation (#1381)
## What changed This fixes Sentry issue [STACK-BACKEND-1A3](https://stackframe-pw.sentry.io/issues/7436639623/?project=4507442898272256&query=is%3Aunresolved&referrer=issue-stream&seerDrawer=true). A request with this malformed header: ```http Authorization: Basic ``` used to crash the Neon auth validator with a `StackAssertionError`, which turned a bad client request into a 500. The fix makes `neonAuthorizationHeaderSchema` only validate Neon client credentials after the Basic auth header successfully decodes. If decoding fails, the Neon-specific validator returns `true` and lets `basicAuthorizationHeaderSchema` produce the intended 400 schema error: `Authorization header must be in the format "Basic <base64>"`. ## Reviewer walkthrough There are two checks chained together: 1. `basicAuthorizationHeaderSchema` checks that the header is structurally valid Basic auth. 2. `neonAuthorizationHeaderSchema` checks that the decoded `client_id:client_secret` matches a configured Neon client. Yup may still run the second check after the first one has failed, because route validation collects errors with `abortEarly: false`. The old code assumed the first check had already passed and called `throwErr(...)` when decoding returned `null`. This PR changes that path to return `true`, because the format error is already owned by the first check. ## Tests - `pnpm -C packages/stack-shared exec vitest run --maxWorkers=1 --minWorkers=1 src/schema-fields.ts` - `pnpm -C apps/e2e exec vitest run --maxWorkers=1 --minWorkers=1 tests/backend/endpoints/api/v1/integrations/neon/projects/transfer.test.ts -t "malformed"` - `pnpm -C packages/stack-shared lint` - `pnpm -C packages/stack-shared typecheck` - `pnpm -C apps/e2e lint` - `pnpm -C apps/e2e typecheck` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Enhanced authorization header validation in API endpoints with improved error handling, ensuring malformed credentials return clear, specific validation error messages. * **Tests** * Added comprehensive end-to-end test coverage for API request validation, including edge cases for authorization headers. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
37e70ca1ae | rotate stack cli publishable client key | ||
|
|
3ea8052d35 | chore: update package versions | ||
|
|
37ee5ec320
|
Fast-start local emulator via RAM snapshot + live secret rotation (#1340)
## Summary
`stack emulator start` now resumes a fully-warm VM snapshot instead of
cold-booting, bringing startup from 30–120s down to ~5–8s with
per-install secret rotation, or ~2.5s with rotation opt-out. The
snapshot is captured **locally on first `stack emulator pull`**, not
shipped from CI — QEMU migration state isn't portable across
accelerators (KVM/HVF/TCG) or `-cpu max` feature sets, so a CI-captured
snapshot couldn't resume reliably on arbitrary user hardware.
Also bundles a pile of CLI QoL fixes (progress bars, PR/run artifact
pulls, PR-build download, native-TS ISO writer replacing
`hdiutil`/`mkisofs`/`genisoimage` host dep, unit tests).
| Scenario | Before | After |
|---|---|---|
| Cold boot (no snapshot) | 30–120s | same, works as fallback |
| `stack emulator pull` (one-time, includes local snapshot capture) |
~30s download | ~30s download + ~1–3 min cold-boot capture |
| Snapshot resume, normal start | — | **~5–8s** |
| Snapshot resume, `EMULATOR_NO_ROTATION=1` | — | **~2.5s** |
Backend (`/health?db=1`) and dashboard (`/handler/sign-in`) return 200
on all paths. Two successive snapshot resumes produce different rotated
PCK/SSK/SAK/CRON_SECRET values per install.
## How it works
**Build (CI)** — `docker/local-emulator/qemu/build-image.sh`:
1. Cloud-init provisioning runs to completion (migrations, seed,
slim-image) producing `stack-emulator-<arch>.qcow2`.
2. Image is built with a topology compatible with later snapshot capture
(pinned SMP=4, phantom seed/bundle ISOs, STACKCFG runtime ISO mounted at
build time, qemu-guest-agent running, placeholder hex secrets baked in
under `STACK_EMULATOR_BUILD_SNAPSHOT=1`).
3. CI publishes **only the qcow2** — no `.savevm.zst` ships.
**Pull (user's machine)** —
`packages/stack-cli/src/commands/emulator.ts` + `run-emulator.sh
capture`:
1. `stack emulator pull` downloads the qcow2 with a progress bar (or
from a PR / workflow run via `--pr` / `--run`).
2. CLI invokes `run-emulator.sh capture`: cold-boots the qcow2 with a
matching device layout (phantom ISOs, fsdev, pcie-root-port, virtfs
detached — migration-incompatible), waits for backend+dashboard health,
then drives QMP: `stop` → set `mapped-ram` + `multifd` caps → `migrate
file:state.raw` → poll `query-migrate` → `quit`. Raw mapped-ram file is
zstd-compressed to `stack-emulator-<arch>.savevm.zst` in the images dir.
3. `--skip-snapshot` opts out (first `start` will then cold-boot).
**Runtime** — `run-emulator.sh start`:
1. Launch QEMU with `-incoming defer` when a `.savevm.zst` is present;
decompress on first use, keep the `.raw` cached for subsequent starts.
2. QMP: same `mapped-ram` + `multifd` caps → `migrate-incoming
file:<.raw>` → poll for `paused` → `cont`.
3. Generate fresh per-install secrets on the host; pipe them
base64-encoded through QGA `guest-exec input-data` →
`trigger-fast-rotate` in the guest → `docker exec -e … rotate-secrets`.
4. `rotate-secrets` in the container: validate keys (hex-only), targeted
`sed` on the placeholder PCK across built JS, `UPDATE ApiKeySet`,
`supervisorctl restart stack-app cron-jobs` (with
`stopasgroup`/`killasgroup` so the Node children actually die and
release their ports).
5. Poll backend+dashboard health; if anything fails, clean up and fall
back to cold boot transparently.
**Security model**: placeholder hex values are baked into the snapshot
(`00…ff` PCK, `00…ee` SSK, `00…dd` SAK, `00…cc` CRON_SECRET). They are
non-secret by construction. Real per-install secrets are generated at
each `emulator start` and never leave the host.
## CLI changes (`packages/stack-cli`)
- **`src/lib/iso.ts`** (new): native TypeScript ISO 9660 + Joliet
writer, replacing the host-side `hdiutil`/`mkisofs`/`genisoimage`
dependency for generating the STACKCFG runtime config disk. Unit tests
in `src/lib/iso.test.ts`.
- **`src/commands/emulator.ts`**:
- `pull`: streamed downloads with progress bar + ETA; `--pr <number>`
and `--run <id>` to pull from a PR build's CI artifacts (uses
`extract-zip` for the nested zip); `--skip-snapshot` to opt out of the
one-time local capture.
- `start` (existing, extended): auto-pulls AND auto-captures when no
image exists, so first-ever `start` is self-bootstrapping; emits
`STACK_EMULATOR_CLI_WROTE_ISO=1` so the shell helper skips its own ISO
regen (avoids the genisoimage host dep).
- `capture` (new, invoked by `pull` and the auto-pull path of `start`):
drives the local snapshot capture via `run-emulator.sh`.
- `status`, `stop`, `reset`, `list-releases`: preflight +
path-resolution tightening (`STACK_EMULATOR_HOME` → images/run dirs).
- Unit tests in `src/commands/emulator.test.ts`.
- **`EMULATOR_NO_ROTATION=1`** env var skips the post-resume rotation
(intended for tests/CI where the placeholder secrets are fine — comes
with a loud warning).
## CI (`.github/workflows/qemu-emulator-build.yaml`)
- Builds **QEMU 10.2.2 from source** (cached), because
`mapped-ram`/`multifd` migration capabilities aren't available in the
distro's QEMU. Enables KVM on ubicloud runners so amd64 boots at
hardware speed.
- amd64 + arm64 both build on the same amd64 matrix
(`ubicloud-standard-8`); arm64 runs under cross-arch TCG (provisioning
only — boot/verify smoke test is amd64-only).
- Verification now runs through the CLI: `emulator start` → `emulator
status` → `emulator stop` against the freshly-built qcow2 (via
`STACK_EMULATOR_HOME` pointing at the workspace, so the CLI doesn't
silently auto-pull a prior release).
- Packages **only** the qcow2. No `.savevm.zst` upload / publish.
- Release notes updated.
## Key files
**Shell / guest:**
- `docker/local-emulator/qemu/build-image.sh` — snapshot-compatible
device topology + STACKCFG runtime ISO at build time
- `docker/local-emulator/qemu/run-emulator.sh` — `start`, `capture`,
`stop`, `reset`, `status`; `-incoming defer`, `.raw` cache, QGA-driven
rotation, cold-boot fallback
- `docker/local-emulator/qemu/common.sh` (new) — shared `qmp_session` +
`capture_vm_state` (factored out so build-image.sh and run-emulator.sh
share the capture path)
- `docker/local-emulator/qemu/cloud-init/emulator/user-data` —
placeholder secrets in snapshot mode, `wait-for-stack-ready`,
`trigger-fast-rotate`, qemu-guest-agent enabled
- `docker/local-emulator/rotate-secrets.sh` (new) — in-container
rotation (sed + UPDATE + supervisorctl)
- `docker/local-emulator/supervisord.conf` — `stopasgroup`/`killasgroup`
on `stack-app` and `cron-jobs`
- `docker/local-emulator/entrypoint.sh` — only mint CRON_SECRET if unset
(placeholder supplied in snapshot mode via --env-file)
- `docker/local-emulator/Dockerfile` — ships `rotate-secrets` to
`/usr/local/bin`
- `docker/server/entrypoint.sh` — source
`/run/stack-auth/rotated-secrets.env`; skip full-tree sentinel scan on
warm restarts via marker
**CLI:**
- `packages/stack-cli/src/lib/iso.ts` (new) + `iso.test.ts` (new)
- `packages/stack-cli/src/commands/emulator.ts` + `emulator.test.ts`
(new)
- `packages/stack-cli/vitest.config.ts` (new)
**CI:**
- `.github/workflows/qemu-emulator-build.yaml`
## Test plan
- [x] `docker/local-emulator/qemu/build-image.sh {amd64,arm64}` produces
`stack-emulator-<arch>.qcow2` with snapshot-compatible topology
- [x] `stack emulator pull` downloads qcow2 with progress, then captures
locally (~1–3 min) and writes `stack-emulator-<arch>.savevm.zst` in the
images dir
- [x] `stack emulator pull --skip-snapshot` stops after download
- [x] `stack emulator pull --pr <n>` / `--run <id>` pull from PR /
workflow run artifacts
- [x] `stack emulator start` on a fresh dir auto-pulls **and**
auto-captures, then starts; subsequent starts fast-resume in ~5–8s;
backend + dashboard return 200
- [x] `EMULATOR_NO_ROTATION=1 stack emulator start` completes in ~2.5s;
backend + dashboard return 200 with warning printed
- [x] Two consecutive `emulator start` invocations produce different PCK
values in the internal `ApiKeySet` row
- [x] `stack emulator status` / `stop` / `reset` resolve paths from
`STACK_EMULATOR_HOME`
- [x] Verified end-to-end on arm64 macOS under HVF (capture ~50s,
fast-resume ~6.5s)
- [x] `pnpm lint` and `pnpm typecheck` pass; stack-cli unit tests (iso +
emulator) pass
- [ ] CI green on this PR (qemu-emulator-build matrix, smoke test)
- [ ] `gh release download emulator-<branch>-latest` contains only
`stack-emulator-<arch>.qcow2` once this PR merges and publish runs
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Snapshot fast-start/resume with optional warm-snapshot assets, runtime
ISO generation, and a cached QEMU build to speed emulator setup.
* CLI: streamed artifact downloads with progress, improved release/asset
handling, stronger preflight checks, and start/status/stop emulator
commands.
* Automated secret rotation and ability to apply rotated secrets at
container startup; supervisor control socket enabled.
* **Bug Fixes**
* More robust start/stop/resume flows with automatic fallback to cold
boot and improved process-group shutdown behavior.
* **Tests**
* New tests for CLI utilities and ISO image generation.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
|
||
|
|
0621ad2032
|
ai proxy fix (#1343)
<!-- 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 * **Refactor** * Request sanitization now includes an extra proxy-specific preprocessing step for safer AI proxying. * **New Features** * Initialization prompts centralized into a shared helper, with a web-specific prompt variant. * Authenticated requests can optionally route via a provided external API key to access alternate models. * **Chores** * Added and exposed a preprocessing hook with a default no-op implementation. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
91fbf63f7f | chore: update package versions | ||
|
|
f4ca6cb4c7 | More tracing for replication-related functions | ||
|
|
1de8a17183
|
Payments bulldozer txn rework (#1315)
### Object of this PR This PR is NOT a monolithic series of fixes for the payments suite + a complete rework. Its aims were a) introducing and robustly testing the bulldozer db system b) reworking the payments underlying architecture to use bulldozer for correctness and scalability c) Achieving parity with the old payments system excepting a few changes like ensuring correctness of the ledger algo There may still be some work to do with handling refunds, decoupling the concepts of purchases from that of products, and some other things. ### Ledger Algorithm This has been tuned and fixed. Item removals i.e negative item quantity changes will apply to the soonest expiring item grant i.e positive item quantity change. This is what is best for the user. Item grants can also expire, and when they expire we obviate whatever is left of their original capacity (meaning after all the removals that were applied to it). Our ledger algo is applied via Bulldozer, so automatic re-computation is handled when a new grant/ removal is inserted in the middle of the existing ones. ### Things we got rid of * No more automatic support for default products. You can use $0 plan provisions to accomplish the same effect but it's manual * Negative item quantity changes (i.e item removals) no longer can have expiries <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Enhanced payment processing pipeline with improved data consistency and state management. * Advanced refund handling with comprehensive transaction tracking. * Better tracking and management of customer item quantities and owned products. * Improved subscription lifecycle management including period-end handling. * **Bug Fixes** * Fixed payment data integrity verification. * Improved handling of edge cases in refund scenarios. * **Chores** * Updated cSpell configuration with additional words. * Expanded developer documentation for linting workflows. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Konstantin Wohlwend <n2d4xc@gmail.com> Co-authored-by: Aadesh Kheria <kheriaaadesh@gmail.com> Co-authored-by: Mantra <87142457+mantrakp04@users.noreply.github.com> |
||
|
|
94dd22c1c5
|
Overview revamp (#1238) | ||
|
|
654c97c56e
|
Onboarding redo (#1308) | ||
|
|
d21bdb0ea8 | Skip diagnostics for analytics requests | ||
|
|
b68710e98e | chore: update package versions | ||
|
|
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 --> |
||
|
|
2af2a591b4
|
Skip analytics init on apps without persistent token store (#1336)
Owned admin apps are constructed with `tokenStore: null`, which caused EventTracker/SessionRecorder flushes to throw from _ensurePersistentTokenStore() after #1331 removed the silencing. <!-- 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 * **Bug Fixes** * Improved analytics stability and privacy by restricting session recording and event tracking to environments with required persistent storage. * **Tests** * Adjusted a few end-to-end tests to skip when running against a local emulator to reduce spurious failures. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
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
|
||
|
|
7f8e3df852
|
feat: add anonRefreshToken to CLI auth flow and enhance session management (#1303)
- Extended `CliAuthAttempt` with `anonRefreshToken` and a migration. - CLI `POST /auth/cli` accepts optional `anon_refresh_token` (must be an anonymous user's refresh token for the current project). - `POST /auth/cli/complete` supports `mode` `check` (anonymous vs none), `claim-anon-session` (issue tokens for the linked anonymous session), and `complete` (bind the browser session's refresh token to the attempt). Completing clears `anonRefreshToken` on the row. We do **not** merge anonymous account data into the signed-in user (that behavior was removed as a security risk; the anonymous user remains unchanged). - Template CLI confirmation page, stack-cli optional `STACK_CLI_ANON_REFRESH_TOKEN`, SDK/spec updates, and e2e coverage. <!-- 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** * CLI login supports attaching anonymous sessions and a multi-mode confirm/claim/check flow; CLI tools now surface login codes and remove anon token after use. * Added interactive CLI auth demo page and a CLI simulator script. * Client libraries: prompt flow accepts an optional anon token and a promptLink(url, loginCode) callback. * **Tests** * Expanded end-to-end coverage for anonymous CLI sessions, claim/complete/poll flows, upgrades, and error cases. * **Documentation** * Updated prompt CLI docs/spec to describe new options and callback signature. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
b3ed56ee0c
|
Fix session recorder and even tracker access token fetch (#1331)
The gate delayed flushes until an access token resolved, but sendBatch already resolves the session itself via _getSession() at send time, so _lastKnownAccessToken was a redundant readiness check that caused head-of-session events to be silently dropped on slow auth init and suppressed uploads entirely when token fetch failed. <!-- 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 * **Refactor** * Simplified analytics, session-replay, and event-tracking to stop periodic background access-token refreshes; flushing now occurs based on buffered data and lifecycle triggers. * **Bug Fixes** * Anonymous-user fallback tightened: anonymous identity is only applied when explicitly requested as "anonymous-if-exists," preventing unintended anonymous attribution. * **Tests** * Updated timing helper and removed token callback from test setups to align with the new flush behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
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> |
||
|
|
7fb660649d | chore: update package versions | ||
|
|
c324ef4a12 | Better error message when user info fetching fails | ||
|
|
310278781a
|
Fix EventTracker silently dormant in real browsers (#1327)
`window.screen` and `window.history` are accessor properties on `Window.prototype`, so `Object.getOwnPropertyDescriptor(window, X)?.value` returned undefined in real browsers, causing `start()` to short-circuit and never capture or send any $page-view / $click events. Read the globals directly instead; the jsdom-based regression test pins the accessor-descriptor shape so this can't silently come back. <!-- 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 * **Tests** * Added a new test suite verifying event batching, timing, page-view and click event capture, and client-side navigation behavior using simulated timers and DOM environment. * **Bug Fixes** * Improved event tracker reliability by changing how browser screen and history are read, yielding more consistent detection of screen dimensions and navigation for analytics capture. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
bb277d33c9
|
Backend fallback (cloud run) (#1306)
- Added support for `@opentelemetry/sdk-node` in the backend. - Updated various dependencies including AWS SDK and OpenTelemetry packages. - Implemented graceful shutdown handling for non-Vercel runtimes in `prisma-client.tsx`. - Enhanced AWS credentials retrieval to support GCP Workload Identity Federation. - Introduced a Dockerfile for Cloud Run deployment, optimizing the backend build process. - Updated `.gitignore` to include Terraform runtime files and secrets. This commit improves the backend's observability and deployment flexibility, particularly for Cloud Run environments. <!-- 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** * OpenTelemetry observability with dynamic provider selection per deployment. * Cloud Run trusted-proxy support for accurate client IP handling. * Graceful shutdown that waits for in-flight background work. * New background-task handling to improve async webhook/email delivery reliability. * AWS credential providers added (Vercel OIDC & GCP Workload Identity Federation). * Dockerized backend image for Cloud Run / self-host deployments. * **Chores** * Updated dependencies for OpenTelemetry and AWS SDK support. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Konstantin Wohlwend <n2d4xc@gmail.com> |
||
|
|
27cd8bf56b | chore: update package versions | ||
|
|
06760d1170 | Update sign-in page to redirect to onboarding when needed | ||
|
|
d6c067972d
|
Replace npx with pnpm exec (#1300) | ||
|
|
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 --> |
||
|
|
a6e9ff6a88 | Disable blast effect with reduced motion | ||
|
|
37a69b0f0a
|
make config typesafe (#1254)
## Summary - add a public `defineStackConfig` helper and `StackConfig` type for nested config authoring - emit helper-based nested config files from the CLI and local emulator - update type coverage and e2e expectations for the new `stack.config` format ## Testing - pnpm --filter ./packages/stack-shared typecheck - pnpm --filter ./packages/stack-cli typecheck - pnpm --filter ./apps/backend typecheck - pnpm --filter ./apps/e2e typecheck <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Type-safe configuration API with compile-time validation * New config rendering utility for producing typed config files * Public local-emulator settings and a public helper to detect emulator mode * Added --overwrite flag for config pull * **Improvements** * Stronger validation and clearer errors for invalid or conflicting config shapes * Config output now includes explicit TypeScript typing * **Tests** * Added and strengthened tests for config authoring, rendering, CLI behavior, and emulator flows <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
9b1284dc9e | Fraud Protection sub-app | ||
|
|
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 -->
|
||
|
|
e2fbe2ca09
|
Fix cross-subdomain cookie deletion and prefetch trusted parent domain (#1302)
Cross-subdomain refresh cookies were not being deleted correctly because the domain option was not passed to deleteCookie/deleteCookieClient. This caused stale cookies to accumulate and auth state to persist across subdomains after sign-out. Also eagerly warms the trusted parent domain cache on app construction to avoid a race condition where navigation after sign-in could prevent the cross-subdomain cookie from being written. <!-- 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** * Automatically recreates a missing cross-subdomain refresh cookie on app startup in browser sessions when applicable. * **Bug Fixes** * Cookie deletions now correctly scope removals to the encoded parent domain when applicable for both browser and server token-store flows. * **Performance** * Pre-warms a domain-resolution cache in browser token-store scenarios to reduce authentication latency. * **Tests** * Added end-to-end tests validating custom refresh-cookie name encoding/decoding, non-custom cookie handling, and eager cookie recreation. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
d3ea2b9001 | Add server-side flags for anonymous users | ||
|
|
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 --> |
||
|
|
df5c5884ae
|
Fix default redirectMethod for Node.js environments (#1301)
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
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
## Summary - Fixes the default `redirectMethod` to check `typeof window !== "undefined"` before defaulting to `"window"` - In Node.js/CLI environments (where `window` is undefined), defaults to `"none"` instead, preventing runtime errors ## Context PR #1253 changed the default `redirectMethod` from `"none"` to `"window"`, but this breaks non-browser environments (Node.js scripts, CLI tools, backend services) that don't have a `window` object. ## Test plan - [ ] Verify existing e2e tests pass (they explicitly set `redirectMethod: "none"`) - [ ] Verify browser usage still defaults to `"window"` - [ ] Verify Node.js usage (e.g. `stack-cli`) defaults to `"none"` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Fixed redirect behavior so client-side redirects continue in browser environments, while non-browser or server-side executions now default to no automatic redirect, avoiding unexpected navigation. Existing platform-specific redirect handling remains unchanged. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
48295825eb
|
fix default redirect method (#1253)
<!-- 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 * **Refactor** * Adjusted internal default selection for redirect handling to improve consistency; no change to user-facing behavior or settings. * **Tests** * Updated end-to-end tests and helpers to explicitly set redirect behavior so test runs remain deterministic. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
300970c924 | chore: update package versions | ||
|
|
cf53313ff4 | rename signed_up_at_millis JWT claim to signed_up_at | ||
|
|
9cbbafeb65 | signed_up_at_millis JWT claim | ||
|
|
5616b0054b | chore: update package versions | ||
|
|
ea62e70f44 | Fix dashboard loading bug | ||
|
|
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
|
||
|
|
a993ec0780 | chore: update package versions | ||
|
|
3efb226c59
|
make publishable client keys truly optional ig (i hope) (#1274)
<!-- 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 ## Documentation * Updated setup instructions across all documentation to clarify that the publishable client key is only required when your project configuration enforces it, removing confusion about unconditional requirements. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
d22593d535
|
private files n sm build shit (#1276)
- Introduced a fallback mechanism for the private sign-up risk engine, allowing for zero-score assessments when the primary engine is unavailable. - Updated Next.js configuration to support dynamic resolution of the private risk engine, including aliasing for both Turbopack and Webpack. - Added a new fallback implementation in `private-sign-up-risk-engine-fallback.ts` to ensure consistent behavior during builds. - Adjusted `risk-scores.tsx` to utilize the new compiled engine, improving error handling and logging for risk assessment failures. This update improves the robustness of the sign-up risk scoring system and enhances the development experience by streamlining engine resolution. <!-- 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 * **Improvements** * Sign-up risk engine is initialized and validated at startup for more predictable performance. * If the risk engine is unavailable or invalid, the system immediately returns safe zero-risk scores to avoid runtime failures. * **Tests** * End-to-end tests updated to match the new engine initialization and detection behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Konstantin Wohlwend <n2d4xc@gmail.com> |
||
|
|
0886586aa7
|
risk score calculation debug logs (#1275)
- Updated pnpm-lock.yaml to include 'rolldown' as a new optional dependency and upgraded 'minimatch' to version 10.2.4. - Added a debug log statement in risk-scores.tsx to indicate when the sign-up risk engine is disabled in the public build. <!-- 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 * **Bug Fixes** * Signup risk scoring now returns a neutral (zero) score when the scoring engine is unavailable; scoring errors are logged and surfaced consistently instead of being silently swallowed. * Invalid engine shapes now fail loudly rather than falling back silently. * **Chores** * Updated private engine reference and adjusted tests to reflect the new loading/resolution behavior. * Expanded Next.js output tracing to include private package files used by API routes. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
e59a70783e
|
Turnstile integration for fraud protection (#1239)
Enhances sign-up process with Turnstile integration for fraud protection. Builds on top of fraud-protection-temp-emails. Made with [Cursor](https://cursor.com) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Cloudflare Turnstile bot-protection across signup/sign-in flows (including SDK JSON mode). * Email deliverability checks via Emailable. * Sign-up risk scoring with persisted risk metrics and country code tracking. * UI: country-code selector, risk-score editing in user details, users list refresh button, and Turnstile signup demo pages. * **Bug Fixes** * Use actual sign-up timestamp for reporting/metrics. * **Documentation** * Expanded knowledge base on Turnstile, risk scoring, and env configuration. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Konstantin Wohlwend <n2d4xc@gmail.com> Co-authored-by: BilalG1 <bg2002@gmail.com> Co-authored-by: Armaan Jain <84474476+Developing-Gamer@users.noreply.github.com> Co-authored-by: nams1570 <amanganapathy@gmail.com> |
||
|
|
0993f151b1 |
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
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
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
|
||
|
|
e6131ca776 | chore: update package versions | ||
|
|
8267ebce35
|
Custom dashboards and unified ai no playground (#1243)
This PR implements unified AI endpoint and custom dashboards. **Unified AI Endpoint** We now use a single endpoint throughout the codebase that makes the call to openrouter. Specifically, email drafts, email templates, email themes, wysiwyg, cmd centre ai search and docs ai, all use this unified ai endpoint. All the tools are defined in the backend, all the prompts exist in the backend. How to review this PR for unified ai endpoint: This PR will be easier to review if we look at the different folders that were affected. under packages - We added streaming functionality, and made renaming changes under docs - there are three files that have changed package.json - we updated the package (we were previously using a very old version of the package) route.ts - we changed the call from a direct call to openrouter to the unified ai endpoint ai-chat.tsx - because of updating the package, we had to make changes to adapt to the latest versions of the package under backend route.ts - the main unified ai endpoint. this endpoint uses various support files forward.ts - this is the forward to production functionality models.ts - consists of the models, and the rules for selecting those models prompts.ts - consists of the base prompt + specific system prompts depending upon the usage schema.ts every single file under ai/tools folder - which as the name suggests, consists of the implementations of the different tools that can be provided to the llm route-handlers - added support for streaming to SmartRoute and response under dashboard ai-search/route.ts - refactored the file to use unified ai endpoint chat-adapters.ts - refactored the file to use unified ai endpoint and created extra checks for the ai generated code **Custom Dashboards** We let the user write their query in english. We then use AI to create dashboards that are interactive, live and savable. This PR includes a new package called dashboard-ui-components. This package has components that are used in the dashboard and more importantly, these components are being imported from esm in the ai generated code for custom dashboards. We also change the bar at the top for the products pages. How to review this PR: Review the new package (package/dashboard-ui-components), the setup and the files inside it. Review the schema changes in stack-shared/src Review the changes in dashboard. The following changes have been made Updated the design-components folder since we moved the dashboard components to the new package Updated imports for these components accordingly Updated the title bar of the product pages Created the files for custom dashboards under the dashboards folder and components under commands/create-dashboard Created a script under dashboard/scripts that generates the file with type definitions that would go to the llm Review the backend Started using unified ai endpoint <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added custom dashboards feature allowing users to create and manage personalized dashboards with AI assistance. * Integrated AI-assisted dashboard code generation with visual preview and editing capabilities. * Introduced new AI query endpoints supporting stream and generate modes with configurable model quality/speed settings. * **Improvements** * Reorganized UI components into a dedicated component library package for better code reuse. * Enhanced chat architecture with improved message handling and tool integration. * Updated AI provider integration with improved configuration management. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Konsti Wohlwend <n2d4xc@gmail.com> Co-authored-by: Bilal Godil <bg2002@gmail.com> Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> |
||
|
|
35b7e72ff2 | prompt fix | ||
|
|
3c6372a971
|
stack cli fixes (#1252)
<!-- 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 * **Bug Fixes** * Fixed authentication errors in the Claude agent. * **Refactor** * Simplified the CLI initialization process to default to cloud project linking, removing interactive prompts. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
b5d5e5cea6
|
Add onboarding status to Project model and implement related database… (#1246) | ||
|
|
fc9999a347 | chore: update package versions | ||
|
|
59a65bb863
|
[Docs] [Feat] Enabling client side events for non internal projects, updating docs for payments and analytics (#1250) | ||
|
|
f016cd8993
|
CLI init (#1242)
<!-- 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** * Interactive init workflow (create, link-config, link-cloud) with safe non-interactive behavior; writes/updates project config and .env, and prints STACK AUTH setup instructions. * CLI assistant/agent with a progress UI for long-running tasks. * Backend AI proxy endpoint that validates and forwards AI requests to an external provider. * **Tests** * End-to-end tests covering all init modes, outputs, env linking, and error cases. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
8e03677aad
|
change cli init across docs (#1245)
<!-- 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 * **Documentation** * Updated installation and setup instructions across all documentation, README files, and getting started guides to use the new Stack CLI command format for project initialization. Users will now see the updated command throughout documentation and framework-specific setup guides. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
8f0be2d94c | chore: update package versions | ||
|
|
612cb71a28 | chore: update package versions | ||
|
|
a2e2de07fb | Move Analytics to beta | ||
|
|
485fa9d623
|
[Refactor][Feat][Fix] Rework Email Section With New Sent Page, Better Drafts Page, and Settings Page (#1221)
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
### Context We didn't have an easy place for a user to see their domain statistics and track their sent emails, either overall or by draft. Additionally, there was scope creep with the sidebar, where we were supporting more pages. Our emails landing page was also rather confusing, especially toggling/ working with different email server types. So, we decide to add a "sent" page, to track email logs and email statistics, as well as let users temporarily override their sending limits if need be. Additionally, a user may want to see a particular email in more detail: what stage is it in? How did it proceed through time? How can I pause the sending of this email or change the scheduled time or edit the code? We allow for that to happen. ### Summary of Changes #### New Pages 1. **Sent Page:** A Domain Reputation card lets you track how many of your sent emails were bounced or marked as spam as well as how much capacity you have left. We also provide a temporary override, where you can use up to 4 times your capacity for a limited period of time. Additionally, we provide an email log that lets you see the recently sent emails. You can also toggle this view from a "list all emails" to "group by template/draft" which shows stats for each template/draft id (i.e a bar showing how many emails were sent, are pending, were marked as spam, were bounced etc, and the total number of emails sent with that template or draft). Clicking on an email in the list all view takes you to the "email-viewer" endpoint for that email (see below). Clicking on a template/draft in the group by view takes you to a page where you can see the statistics for that template/draft in more detail (the "send" stage view for that template/draft, as referenced below). 2. **Settings Page:** This is a new page we created because the old "emails" landing page wasn't doing its job. This page is to track all the email settings. Currently, we put in 2 sections. A "theme settings" card where users can see their active theme and click on a button to be navigated to the themes page. This is necessary as we remove themes from the sidebar. The other section is a card for email server and domain configuration - you can change your server type and adjust the settings or send a test email. It's cleaner and less noisy. 3. **Drafts Page**: There are a lot of changes here. On the landing page, we actually separate out the drafts into "active drafts" and "draft history" because drafts are meant to be fire-and-forget, not reusable. We also add the functionality to create a draft from a template. This was tricky to manage because templates rely on template variables which sent to the backend along with the code and injected during render time. We deal with this by having AI rewrite the template source code to remove any references to template variables and to make the draft standalone. The drafts page has been separated into a stepper-controlled multi stage process: draft->recipients->schedule->sent. Sent is a read only view that shows you the statistics of the emails sent using that draft, as mentioned earlier. You can also see the sent view of a historical draft. You can also bulk pause/cancel any unsent emails from the sent view of the drafts. 4. **Sidebar Updates**: The email sidebar now doesn't show "themes" or "emails" (the old landing page), but it does show "settings" and "sent", and the default landing page for emails is "sent". 5. **Email Viewer**: When you click on an individual email, you get navigated here. This has a timeline showing the progress of the email on the right, and some optional info for the user that's toggleable on the right bottom, while having either a preview of the email if it's sent or a way to edit it. You can also change the scheduledAt date of an email if it hasn't already been sent. #### Bug Fixes 1. **Search in `TeamMemberSearchTable`**: This was broken. Every time you tried to enter or remove a character, it would trigger skeleton loading that overlapped the search bar too, preventing you from adding/removing more. This was caused because the `useUser` hook eventually ended up calling a `use` hook, which throws a promise that triggers a suspense. This, coupled with the fact that the implementation of `TeamMemberSearchTable` involved a prop-drilling/ dependency inversion approach to passing down its toolbar to a base table component, meant the suspense would cover the toolbar too and couldn't be scoped to just the table. A refactor has gotten rid of the need for those base components while fixing tables in `payments/customers`, `teams/team_id`, and `payments/transactions` on top of the existing use in email drafts recipients stage. We also dedupped some code. 2. **Stale draft fetches on draft landing page**: `useEmailDrafts` uses an asyncCache to cache the fetched drafts. It is used on the drafts landing page to render the drafts. When a draft is sent, its `sentAt` is marked versus when it is still active, it is marked as null. The cache was stale and so navigating to the landing page after firing off a draft would errorneously represent that draft as still active and indeed, even allow you to edit it and fire it again. This violated the principle of drafts being fire and forget. This has been dealt with by adding functionality to refresh the draft cache upon firing off a draft. #### Other Changes 1. We bumped up the base time for the exponential send attempt retry backoff in `email-queue-step` to 20 seconds. The previous base was two seconds, and this effectively just made it wait until the next iteration of the `email-queue-step` cron job or at most an iteration that wasn't too far away. When an outage with our provider happens, it may take a while for it to be resolved, so a longer backoff is justified 2. We transitioned the themes page and the templates page to using the new components, though deeper UI refactors for them were out of scope for this ticket. 3. We implement a "temporarily increase capacity" button, that bumps up the throughput/ capacity limit fourfold for a user for a given period of time. It works like this: > Clicking the button sets a boost expiredat time. > When this time is set and still valid, the capacity rate is multiplied by 4. > When the button is clicked, trigger a loading spinner until the route finishes processing. > When the timer runs out, we reset the button back to its original state. > We dont need to wrap the onclick with runAsyncWithAlert because the component does that already. 4. We add a new default theme: a colorful theme with a lavender base. This was mainly done so we could have three times in a theme showcase in the settings page. ### UI Demos **Sent Page Demo:** https://github.com/user-attachments/assets/19294a90-bb65-4f00-9a97-111f6c08287f **Drafts Page Demo** https://github.com/user-attachments/assets/847609ef-d699-470c-a699-297bb9e17f04 **Settings Page Demo** https://github.com/user-attachments/assets/190a3829-036a-4f57-89c0-a873bef5a7ce **Email Viewer Page Demo** https://github.com/user-attachments/assets/3bc50159-4acb-4865-a4dd-830c84ee4235 --------- Co-authored-by: Konstantin Wohlwend <n2d4xc@gmail.com> |
||
|
|
66adb4e50f
|
Local emulator base (#1233)
<!-- 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** * Provision local-emulator projects from a local config file and return emulator credentials via a new internal endpoint. * Dashboard: "Open config file" flow to open local projects and refresh owned projects. * **Changes** * Branch config can prefer/read/write local files for emulator projects. * Environment config updates/resets are blocked for local-emulator projects. * Dashboard UI shows read-only notices and disables project creation in emulator mode. * Added DB mapping and a standard env flag to identify local-emulator projects. * **Tests** * New E2E tests covering provisioning and config restrictions. * **Chores** * Removed legacy emulator docs and compose; added CI workflow for local-emulator E2E runs. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Konstantin Wohlwend <n2d4xc@gmail.com> |
||
|
|
a64055cfca
|
Hosted components (#1229)
<!-- 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** * Added a new "Hosted Components" app with its own app shell, routing, auth-aware UI, a handler route, and a welcome page showing the signed-in user. * **Chores** * Added dev tooling and configuration for the new app (build, lint, typecheck, Vite/TS, package manifest) and updated dev env API URL. * **Tests** * Excluded the new app from the test workspace. * **Bug Fixes** * Suppressed noisy console errors for a specific internal sentinel and clarified related error messaging. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Konstantin Wohlwend <n2d4xc@gmail.com> |
||
|
|
85ea5d25c8 |
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 / 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
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
|
||
|
|
b701fdfb0a
|
Managed email provider (#1222)
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 / 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
<!-- 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** * Managed email domain onboarding: setup, DNS provisioning, verification, status checks, and apply flow (Resend-backed). * **UI** * Project email settings: managed-provider setup dialog, managed sender fields, status display, and test-send mapping. * **Integrations** * DNS provider automation and Resend webhook handling for domain status updates; scoped keys for sending. * **API** * Admin endpoints / client APIs to setup, check, list, and apply managed email domains. * **Tests** * End-to-end tests covering the full onboarding flow. * **Chores** * Added environment variables and config schema support for Resend and DNS integrations. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
57149bd84b
|
Stack CLI (#1227)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **New Features** * Added Stack CLI with authentication (login/logout) commands. * Added project management commands to list and create projects. * Added configuration management to pull and push project settings. * Added code execution capability to run JavaScript expressions. * Added initialization command for Stack Auth setup. * **Tests** * Added comprehensive end-to-end test suite for CLI functionality. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
d0879acd26 |
Fix lint
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 / 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
|
||
|
|
00fd0eb4c8 | Revert Docker build fix | ||
|
|
c8b516833e |
Add requires_totp_mfa to JWT
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 / 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
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
|
||
|
|
5b150acfa8 | Fix pnpm-lock | ||
|
|
2e6091571e | Update rimraf | ||
|
|
0c130b5d67 | Fix package |