Commit Graph

2191 Commits

Author SHA1 Message Date
Developing-Gamer
5c7c202fb2 Revert "Add analytics table search bar routing and validation logic."
This reverts commit 78af13b5dc.
2026-07-14 11:14:28 -07:00
Developing-Gamer
32f0cfad56 Revert "Replace AI query chat hook with table filter chat hook."
This reverts commit b62fcf8297.
2026-07-14 11:14:27 -07:00
Developing-Gamer
d2f47ce03e Revert "Add unified filter-first analytics table search bar."
This reverts commit 745f122b5b.
2026-07-14 11:14:27 -07:00
Developing-Gamer
e133a6000f Revert "Wire analytics tables to filter-first search and remove AI query builder."
This reverts commit 8fd8479915.
2026-07-14 11:14:27 -07:00
Developing-Gamer
8fd8479915 Wire analytics tables to filter-first search and remove AI query builder.
Replace the AI query bar and dialog with TableSearchBar, keep columns during reloads, and move refresh into the toolbar actions slot.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-14 11:11:25 -07:00
Developing-Gamer
745f122b5b Add unified filter-first analytics table search bar.
Debounce substring search, route natural-language and zero-result queries to AI, and show active filters as removable chips.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-14 11:11:25 -07:00
Developing-Gamer
b62fcf8297 Replace AI query chat hook with table filter chat hook.
Rename useAiQueryChat to useAiTableFilterChat, scope it to a table, and surface assistant notes when no query is committed.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-14 11:11:25 -07:00
Developing-Gamer
78af13b5dc Add analytics table search bar routing and validation logic.
Route natural-language input to AI and validate committed queries stay as SELECT * row filters over the current table.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-14 11:11:25 -07:00
Developing-Gamer
42a2cddc06 Add analytics table filter chat adapter.
Use the filter-analytics-table prompt and inject the viewed table as leading context for row-filter-only AI replies.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-14 11:11:25 -07:00
Developing-Gamer
fd8f7b51e8 Fix sticky header flicker while analytics tables scroll underneath.
Restore document-level Cmd+K glow tracking and remove the dark-mode header underlay that caused compositing seams.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-14 11:11:25 -07:00
Developing-Gamer
d98ee52a94 Register analytics table filter prompts in AI query E2E tests.
Ensure build-analytics-query and filter-analytics-table are covered by the system prompt smoke suite.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-14 11:11:25 -07:00
Developing-Gamer
fbfa37c63d Add filter-analytics-table system prompt for row filters.
Constrain AI search to SELECT * FROM <table> WHERE ... so analytics table views keep the same columns.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-14 11:11:25 -07:00
Developing-Gamer
a21139958c Extract shared analytics tables schema documentation.
Deduplicate the ClickHouse schema block so analytics SQL prompts can share one source of truth.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-14 11:11:25 -07:00
Developing-Gamer
ada90e2139 Improve analytics tables layout and data grid scrolling
- Make the analytics tables page fill the shell height and scroll internally so rows never paint under the sticky translucent header
- Add horizontalScrollbarPosition option to DataGrid (top puts the horizontal scrollbar under the column headers) with header/body scroll syncing and wheel forwarding, plus tests
- Add an opaque dark-mode underlay behind the floating header to fix the bright seam when content scrolls behind it
- Scope the CmdK trigger glow to the button itself instead of a document-level mousemove listener that recomposited the header on every cursor move
2026-07-14 11:11:24 -07:00
Aman Ganapathy
32daff06f5
[Fix]: OOM Risk with Data Table (#1766)
### Context
We were seeing the txn table and the customers tab under product page
OOM.

It turns out this was because the team icon when loaded would fetch all
of the teams.

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Fixes OOM and renderer crashes in the transactions and product customers
tables by stopping per-row refetch storms and avoiding list‑all‑teams
calls. Infinite scroll is now robust, and shared avatar skeletons keep
table rendering smooth.

- **Bug Fixes**
- Data grid (`@hexclave/dashboard-ui-components` `use-data-source`):
queue `loadMore` while a fetch is in flight and replay only after a
successful settle; discard queued requests when pagination mode leaves
infinite; commit the cursor only after a result is delivered; skip
redundant refetches when inputs match a completed fetch; abort in‑flight
requests on unmount.
- Transactions table and product customers tab: wrap `User*`/`Team*`
avatar cells in `Suspense` with a shared `AvatarCellSkeleton` to prevent
per‑row fetch storms and suspend thrash.
- `serverApp.getTeam`/`useTeam` (in `@hexclave/shared` consumers): fetch
a single team by id via a cache; return null for invalid ids; keep
user‑scoped variants membership‑scoped; stabilize hook order. This
removes the “fetch all teams per row” behavior that triggered OOMs.
- Prefetching: cap `/projects/*/teams` to `useTeams({ limit: 1 })` and
remove the heavy owner‑team users prefetch.

- **Refactors**
- Add unit tests for infinite pagination in `use-data-source` (deferred
`loadMore`, aborted resets, error handling, and cursor continuity).

<sup>Written for commit 970abc0f03.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/hexclave/hexclave/pull/1766?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>

<!-- End of auto-generated description by cubic. -->

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

* **Bug Fixes**
* Added loading placeholders for customer avatar/name rendering across
payment and transaction customer tables to prevent jarring updates while
data loads.
* Improved infinite data loading to correctly queue and replay “load
more” after in-flight requests, handle abort/reset races, and avoid
stale cursor behavior; deferred requests are discarded when leaving
infinite mode.
* Improved user-scoped team lookups by validating team identifiers and
reliably returning `null` for missing/invalid teams.
* **Documentation**
* Clarified that user-level team lookups only return teams the user is a
member of.
* **Tests**
* Added/expanded coverage for infinite pagination cursor correctness,
race conditions, error handling, and mode transitions.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: aman <aman@stack-auth.com>
2026-07-14 11:06:41 -07:00
Konsti Wohlwend
21a04ac7fd
Coalesce Overview globe hover hit-testing to one per frame (#1758) 2026-07-13 18:29:14 -07:00
Konstantin Wohlwend
770f01a057 Various improvements 2026-07-13 13:40:56 -07:00
Konstantin Wohlwend
a66a8d972d Revert "Migrate backend transport from Next.js to ElysiaJS (WIP) (#1630)"
This reverts commit 5209ec83ae.
2026-07-13 12:38:53 -07:00
Konstantin Wohlwend
7525526730 Revert "refactor(backend): remove Next.js compat shims, use standard Web APIs (#1652)"
This reverts commit ae09be9c66.
2026-07-13 12:36:36 -07:00
Konstantin Wohlwend
0dacb04a19 Revert "Enhance request logging in development mode"
This reverts commit 67e3350693.
2026-07-13 12:35:14 -07:00
Konstantin Wohlwend
f6bf39cf36 Support trailing slashes 2026-07-13 12:24:02 -07:00
Konsti Wohlwend
f33cb4cbc5
Fix flaky payment e2e tests: await async Stripe webhook processing + deterministic fixtures (#1746)
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
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
2026-07-10 20:22:47 -07:00
mantrakp04
67e3350693 Enhance request logging in development mode
Added functionality to log request timings in development mode. Introduced a WeakMap to track request start times and log the elapsed time along with the request method, pathname, and response status after each request. This improves observability during development.
2026-07-10 19:02:05 -07:00
Konstantin Wohlwend
06e3a6afa9 Add --clear-screen to backend dev 2026-07-10 18:26:14 -07:00
Konstantin Wohlwend
5acfe0b465 Fix various dev server issues 2026-07-10 11:25:19 -07:00
Konstantin Wohlwend
cb6c9024fe Make Bulldozer Studio log less 2026-07-10 11:02:18 -07:00
Konstantin Wohlwend
09e5a97d77 Less Bulldozer spam 2026-07-09 21:50:13 -07:00
Mantra
ae09be9c66
refactor(backend): remove Next.js compat shims, use standard Web APIs (#1652)
## What

Removes the Next.js compatibility shim layer that the ElysiaJS backend
migration (#1630) introduced, replacing it with standard Web APIs and
de-aliased local runtime helpers. Addresses N2D4's review note on #1630:

> i think we should create a followup PR which cleans these up and uses
the elysia methods directly — so we don't need a nextjs compat layer
forever

Stacked on `migrate-backend-to-elysiajs`.

## Changes

**`next/server` → standard Web APIs (eliminated)**
- `NextRequest` → `Request`, `NextResponse.json()` → `Response.json()`,
`new NextResponse(...)` → `new Response(...)`, `req.nextUrl` → `new
URL(req.url)`
- Hot path (`smart-route-handler`) computes `const requestUrl = new
URL(req.url)` once
- Deleted `lib/next-compat/server.tsx`; rewrote
`server/next-request-shim.ts` → `server/backend-request.ts`
(`createBackendRequest`, returns a plain `Request`)

**`next/headers` + `next/navigation` → `lib/runtime/` (de-aliased)**
- `git mv`'d the real runtime helpers (`headers`, `navigation`,
`request-context`) out of `lib/next-compat/` into `lib/runtime/`,
repointing all consumers to `@/lib/runtime/*`
- The cookie/header/redirect mechanism (AsyncLocalStorage + thrown
redirect errors, driven by `app.ts`) is unchanged — it was only *named*
after Next, never actually Next

**Config + cleanup**
- Dropped the `next/*` path aliases from `tsconfig.json`,
`vitest.config.ts`, `tsdown.config.ts` (removed `nextCompatPlugin`, the
alias map, and the `next` bundling special-case)
- Deleted `fetch.d.ts` and removed the no-op `next: { revalidate }`
fetch option in `changelog/route.tsx` (caching never worked outside the
Next runtime)
- Converted the unreferenced `proxy.tsx` so it still compiles (it's dead
code superseded by `server/middleware.ts` — deletion candidate, left out
of this PR)

No `next/*` imports remain in the backend.

## Verification
- `tsc --noEmit` — passes (exit 0)
- `eslint` on all changed files — clean

## Notes / not in scope
- This removes the **`next/*` façade**. It keeps the underlying
ALS-based request-context mechanism rather than threading Elysia's
native context (`set.cookie`, `set.redirect`) into every handler —
that's a much larger change touching handler signatures across the whole
API surface.
- One internal redirect digest string is still `"NEXT_REDIRECT"`
(matched in both `navigation.tsx` and `app.ts`); renamable but cosmetic.

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Remove the `next/*` compatibility layer and switch the backend to
standard Web APIs. This simplifies handlers and config while keeping the
ALS request context and redirect behavior unchanged.

- **Refactors**
- Replaced `NextRequest`/`NextResponse` and `req.nextUrl` with
`Request`/`Response` and `new URL(req.url)` across handlers, proxies,
health/unsubscribe routes, and IDP endpoints.
- Moved runtime helpers to `@/lib/runtime/*` (`headers`, `navigation`,
`request-context`) and updated imports.
- Added `server/backend-request.ts` to build backend `Request`s with
merged headers; removed `server/next-request-shim.ts` and
`lib/next-compat/server.tsx`.
- Updated proxy rewrite to set `x-middleware-rewrite`; IDP routes now
return `Response` directly with 307/308 mapping.
- Removed the `next:{revalidate}` fetch option; deleted
`lib/next-compat/fetch.d.ts`.
- Dropped `next/*` aliases from `tsconfig`, `tsdown`, and `vitest`;
route registry/types now use `Request`.

- **Migration**
- Import from `@/lib/runtime/headers` and `@/lib/runtime/navigation`
instead of `next/headers` and `next/navigation`.
- Route handlers should accept `Request` and use `new URL(req.url)` for
URL parsing.

<sup>Written for commit b4a534ff36.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/hexclave/hexclave/pull/1652?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>

<!-- End of auto-generated description by cubic. -->

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: mantra <mantra@stack-auth.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Bilal Godil <bg2002@gmail.com>
2026-07-09 21:45:15 -07:00
Mantra
5209ec83ae
Migrate backend transport from Next.js to ElysiaJS (WIP) (#1630)
> **Draft / WIP — do not merge.** Backend Next.js → ElysiaJS transport
migration, in progress.

## Summary

Migrates the backend (`apps/backend`) HTTP transport from **Next.js (App
Router)** to **ElysiaJS** (Node adapter, `@elysiajs/node`), with the
explicit goal of keeping every API route **byte-for-byte backwards
compatible** — same URLs, methods, status codes, headers, and bodies.
Elysia becomes purely the transport layer; the existing
`createSmartRouteHandler` abstraction and all ~221 file-based route
handlers are reused unchanged.

## Approach

- **One wildcard dispatcher** reuses the existing `smart-router`
matchers + generated `routes.json`/`api-versions.json` rather than
re-registering 221 routes on Elysia's router.
- **`proxy.tsx` (Next 16 middleware) ported** to an Elysia request
pipeline: CORS, dev rate-limit, `x-hexclave-*`→`x-stack-*` header
aliasing, OPTIONS preflight, and the **API version rewrite** (`/api/v1`,
`/api/v2betaN` → `/api/latest` / `/api/migrations/*`).
- **Two-URL dispatch**: the version-rewritten path locates the handler;
the original client URL is preserved on `req.url`/`nextUrl`
(load-bearing for OIDC/neon routes that assert `/api/v1/...`).
- **`next/*` compatibility shims** (`next/headers`, `next/navigation`,
`next/server`) under `src/lib/next-compat/`, wired via aliases in
tsconfig / vitest / tsdown so route files stay untouched.
- **Observability** moved off `@sentry/nextjs` → `@sentry/node` + manual
OpenTelemetry NodeSDK preload (`src/instrument.ts`); explicit
`/monitoring` Sentry tunnel.
- **Build/deploy**: `next build/start` → tsdown bundle
(`tsdown.config.ts`) for container; Vercel default-export entry;
Dockerfile CMD → `dist/server.mjs`; `next.config.mjs` removed (security
headers etc. reimplemented).

## Status — WIP

**Green so far:** backend `typecheck`, backend `lint`, tsdown bundle,
`GET /health`, `GET /api/v1`, e2e `migration-tests` (13/13),
`analytics-query` (69/69), unit suite (~1006 tests).

**Remaining before ready for review:**
- [ ] Full backend e2e snapshot suite green (snapshots = byte-for-byte
oracle; never `-u`'d to mask drift)
- [ ] `config.test.ts` (`custom_oidc`) snapshot root-cause
- [ ] M4: source-map upload + remove remaining `@sentry/nextjs` browser
leftovers
- [ ] M5: Docker + Vercel artifact verification
- [ ] M6: confirm React-UI → slim-handler cleanup

## Notes
- Backwards-compat gate: the existing e2e snapshot files (recorded
against the Next.js backend) must pass unchanged.
- Built primarily by Codex (`gpt-5.5`); branch intentionally separate
from `dev`.

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Migrates the backend transport from Next.js to ElysiaJS with
byte‑for‑byte compatible APIs, bundled with `tsdown` for Node, Vercel,
and Docker. Reverts out‑of‑scope payments/metrics/custom OIDC changes to
keep this PR focused.

- **Refactors**
- Transport: Next.js → ElysiaJS (`elysia`, `@elysiajs/node`) via
wildcard dispatcher + generated route registry; preserve original URL;
decode params; 400 on malformed params.
- Next shims: `next/headers`, `next/navigation`, `next/server` with
request context and cookie serialization; don’t percent‑decode;
`cookies().delete()` clears pending Set‑Cookie; add `fetch` `next`
options typing.
- Observability: move to `@sentry/node`/`@sentry/browser`; preload
`@opentelemetry/sdk-node`; guard duplicate OTel registration; add
`/monitoring` tunnel; sanitize Sentry release names; replace Next.js
instrumentation with `src/instrument.ts`.
- Build/deploy: bundle `dist/server.mjs` and `dist/vercel.mjs` with
`tsdown`; Vercel function at `api/index.ts` re‑exports the handler
(`runtime: nodejs`, `maxDuration: 60`, `framework: null` rewrite);
Docker runs the Node bundle.
- Runtime: reimplement security headers; dev rate limiter uses high‑res
timers; graceful SIGTERM.
- Env/dev: expand nested env refs; load `.env.development` in dev;
TS/Vitest alias `next/*` to shims.
- Deps/tooling: re‑add `@sinclair/typebox`; regenerate `pnpm-lock.yaml`
with pnpm 11.5.0 and pin `exact-mirror@1.1.1`.

- **Bug Fixes**
  - Dispatcher: catch `NextNotFoundError` and return 404.
- Emails: deterministic localhost/loopback SMTP fallback (prefer IPv6)
and consistent HTML for snapshot parity.
- E2E parity: restore email‑conflict error; poll all‑users outbox before
asserting; extend refund/transactions timeouts; fix team invitation
revoke setup.
- Build/Docker: prevent `dist` wipes by setting `clean:false` in
db‑migrations `tsdown` config; reorder COPY so `dist/server.mjs` is
present; backend entrypoint uses `dist/server.mjs`.
- CI/tests: Vitest `minWorkers: 1`; fallback e2e starts the Elysia
bundle via `pnpm run start` with `PORT`.
- Shared: normalize `esbuild-wasm` default export under Node to avoid
runtime mismatches.

<sup>Written for commit d3c9b0ff22.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/hexclave/hexclave/pull/1630?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>

<!-- End of auto-generated description by cubic. -->

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

## Release Notes

* **Bug Fixes**
* Improved email delivery by adding localhost/loopback-aware SMTP retry
behavior and more consistent delivered email HTML.
  * Enhanced error reporting during external database synchronization.
* Refined OAuth provider type validation to better handle missing or
custom provider configurations.

* **Improvements**
* Updated backend runtime and routing/request handling for more
consistent behavior, including updated Vercel/Docker startup.
* Improved payment “dual write” reliability by scheduling Bulldozer
projection updates with per-tenant ordering.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: mantra <mantra@stack-auth.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Bilal Godil <bg2002@gmail.com>
2026-07-09 21:39:28 -07:00
Konsti Wohlwend
d5ed20863a
Enable dev tool Dashboard tab via development-environment probe instead of env var (#1749) 2026-07-09 20:23:07 -07:00
Konstantin Wohlwend
38237fe363 Decrease BulldozerJS log spam 2026-07-08 15:56:59 -07:00
Konsti Wohlwend
bf93740c7e
feat: add CLI Auth dashboard app (#1739)
## Summary

New "CLI Auth" app registered in `apps-config.ts` (alpha, parent:
authentication) and `apps-frontend.tsx` (TerminalWindowIcon, `/cli-auth`
route).

**Backend** — `GET /internal/cli-auth`:
- Queries `CliAuthAttempt` (last 50) with computed status from
`usedAt`/`refreshToken`/`expiresAt`
- Joins claimed `refreshToken` values against `ProjectUserRefreshToken`
to find active CLI sessions + user info via `ProjectUser`
- Returns `{ summary, recent_attempts, active_cli_users }`

**Dashboard** — `/cli-auth/page-client.tsx`:
- Fetches via `hexclaveAppInternalsSymbol` →
`sendRequest("/internal/cli-auth", {}, "admin")`
- Renders KPI cards (total/completed/expired/active), active sessions
list with last-active time, and recent attempts with status badges
- Expired sessions collapsed by default under `<details>`

Link to Devin session:
https://app.devin.ai/sessions/0868d1452a024b9da36b9d6a45044ff3
Requested by: @N2D4

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Adds an alpha CLI Auth dashboard to track CLI login attempts and active
refresh tokens, powered by a hidden admin-only endpoint.

- **New Features**
- Registers `cli-auth` under Authentication; adds `/cli-auth` route with
TerminalWindowIcon and docs link.
- Backend `GET /internal/cli-auth`: summary stats (incl. used_attempts),
last 50 attempts with computed status, and active CLI users by joining
CLI-issued refresh tokens (bounded).
- Dashboard fetches via admin request and shows KPIs, active sessions
(last-active/expiry), and recent attempts; expired sessions are
collapsed.

- **Bug Fixes**
- Use per-project admin app (`useAdminApp`) to avoid
ADMIN_AUTHENTICATION_REQUIRED and ensure correct tenancy scoping.
- Resolve primary emails for active sessions via `ContactChannel` join
to prevent 500s.
- Fix badges by using `DesignBadge` label prop and set expired to red;
add default cases in status switches.
- Bound token lookup to last 200 CLI-issued tokens and use a separate
COUNT(*) for accurate `active_tokens`.
  - Align loading skeleton grid with the KPI layout.
  - Docs: add `cli-auth` icon.

<sup>Written for commit 292859e921.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/hexclave/hexclave/pull/1739?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>

<!-- End of auto-generated description by cubic. -->

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

* **New Features**
* Added a **CLI Auth** dashboard page with metrics for active sessions,
an expandable expired session list, and recent login attempts.
* Added a hidden internal analytics endpoint powering the dashboard
(summary, recent attempts, and active users).
* Registered **CLI Auth** in the app catalog/navigation (alpha) and
added its icon to the docs UI.
* **Bug Fixes**
* Improved request/response validation, loading/error states, and
avoided state updates after unmount.
* **Documentation**
* Updated docs indexing settings and added a redirect for a related
guide.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-07-08 12:34:34 -07:00
Konsti Wohlwend
a14b595df3
Add browser script/esm.sh no-bundler setup to the setup prompt (#1743) 2026-07-08 12:04:34 -07:00
Konsti Wohlwend
4cb0affb64
Fix CI: stop e2e dev-env leaking into hermetic package tests + refresh stale project snapshots (#1744) 2026-07-08 12:01:46 -07:00
Konsti Wohlwend
165d9a0786
feat: center globe on viewer'S location (#1715) 2026-07-08 10:33:30 -07:00
Konsti Wohlwend
f38fde7d05
Fix CI: externalize AWS SDK from migration bundler + move Bulldozer HTTP calls out of Prisma transactions (#1716) 2026-07-08 10:22:00 -07:00
Konsti Wohlwend
7a78085a49
Preserve the caught error in the billing-degradation error boundaries (#1741) 2026-07-08 09:26:17 -07:00
github-actions[bot]
105f03fb94 chore: update package versions 2026-07-06 23:34:27 +00:00
Konsti Wohlwend
0238f0ac37
Keep the dashboard loading when bulldozer is down (internal billing degrades gracefully) (#1740) 2026-07-06 16:30:02 -07:00
github-actions[bot]
16912e7d33 chore: update package versions 2026-07-06 05:53:33 +00:00
github-actions[bot]
0344efb844 chore: update package versions 2026-07-06 05:51:13 +00:00
nams1570
e13f12a799 feat: pass env into bs tracing 2026-07-05 21:47:44 -07:00
github-actions[bot]
675e8608af chore: update package versions 2026-07-06 04:45:14 +00:00
github-actions[bot]
1fe5150740 chore: update package versions 2026-07-06 04:29:19 +00:00
Vedanta-Gawande
a5e884db91
(fix): delete dialog on click behavior; fix user page syncing issues (#1684)
<!--

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

-->

## Summary

This PR fixes the Users dashboard delete-dialog click behavior and makes
user mutations refresh the Users page without requiring a manual browser
reload.

The main user-facing changes are:

1. Opening the delete dialog from a Users table row no longer lets
dialog clicks fall through into row navigation.
2. Creating, deleting, or updating a user from the Users page now
refreshes the table, total-user count, and KPI cards automatically.
3. Users table profile links avoid expensive profile prefetching, so
refreshes no longer fan out into many unnecessary per-user profile
requests.

---

## Delete Dialog Click Behavior

The Users page has two delete-user entry points:

- the user profile action menu
- the Users table row action menu

Before this PR, the profile-page flow behaved correctly, but the
table-row flow could accidentally trigger row navigation while the
delete dialog was open. For example, clicking dialog content, footer
whitespace, the confirmation label, or the overlay could navigate to the
user's profile instead of simply interacting with or closing the dialog.

This PR fixes that by treating the row action area as non-row-click
territory and stopping click/double-click propagation from the action
surface.

Behavior after this change:

- Clicking outside the dialog closes it and returns to the page that
opened it.
- Clicking inside the dialog no longer navigates through the underlying
row.
- The confirmation label still toggles the required delete
acknowledgement.
- The explicit user identifier inside the dialog is the only navigation
target to that user's profile.
- The delete confirmation copy is shorter and uses a non-empty display
fallback:
  - display name
  - primary email
  - user ID

---

## Users Page Refresh

Previously, creating or deleting a user through the Users page changed
backend state, but the table and KPI surfaces could stay stale until the
user manually refreshed the page or clicked the reload button.

This PR adds an explicit Users-page mutation refresh path:

- `UserDialog` can notify the page after create/edit succeeds.
- `DeleteUserDialog` can notify the page after delete succeeds.
- `UserTable` exposes its existing `useDataSource().reload()` function
to the page.
- The Users page refreshes the table and the metrics/count surfaces
after successful user mutations.
- The row action menu also refreshes after removing 2FA, so the row no
longer keeps showing a stale 2FA action after the update succeeds.

---

## Refresh Performance

The existing manual reload path used the broad `_refreshUsers()` SDK
invalidation, which refreshes more than this page needs. In local
testing, that broad path could combine with profile prefetching and
trigger many per-user requests for profile details, contact channels,
and OAuth providers.

This PR narrows the automatic Users-page refresh:

- table rows reload through the table data source
- total-user counts refresh through the user-count metrics endpoint
- KPI cards refresh through the metrics endpoint
- table/profile links can opt out of dashboard `UrlPrefetcher` with
`prefetch={false}`
- dense Users table profile links use `prefetch={false}`
- the delete-dialog profile link also opts out of prefetching

This keeps the generic `DataGrid` component unchanged. The Users page
owns the fact that a user mutation happened, and the table only exposes
the reload function it already has.

---

## KPI / Navigation Consistency

The Users page now keeps a page-local metrics snapshot for the total
count and KPI cards. It refreshes that snapshot after mutations and on
page restore, so navigating into a user profile and then returning with
browser back does not leave the KPI cards showing old counts.

Passive page-load/page-restore metrics refreshes use non-alert async
handling, so a background metrics failure is reported normally instead
of showing a blocking browser alert. User-triggered refreshes and
mutation-triggered refreshes still use the dashboard's alert-backed
async handling.

---

## Screenshots of the Delete User Dialog 

Before 

<img width="524" height="302" alt="old-user-delete-dialog"
src="https://github.com/user-attachments/assets/d75f25d3-e462-4ae3-ac3b-d133f6ddbbf6"
/>

After 

<img width="520" height="281" alt="new-user-delete-dialog"
src="https://github.com/user-attachments/assets/4783f61e-76b6-45c5-8952-0f76fa48eba1"
/>



<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Fixes delete dialog click-through and makes the Users page auto-refresh
the table and metrics without flicker. KPIs and total users render
instantly from a snapshot and refresh in the background for smoother
navigation.

- **Bug Fixes**
- Block row navigation from all row-action and delete-dialog clicks; add
a non-prefetching profile link in `DeleteUserDialog` that closes the
dialog on click. Dialog now accepts `profileHref`, fires `onDeleted`,
and URL-encodes `projectId`/`user.id`; `redirectTo` still works.
- Safer links: `Link` supports `prefetch={false}` and disables internal
prefetch; applied to profile links in the table and dialogs.

- **Refactors**
- Instant metrics: preload a snapshot via
`fetchMetricsOrThrow`/`fetchMetricsUserCountsOrThrow` and pass it to
Total Users and KPI cards; auto-refresh on tab restore and after user
mutations.
- Targeted reloads: `UserTable` exposes `onReloadChange`; page, dialogs,
and 2FA removal call `onUserMutated` to reload rows and refresh metrics.
The refresh button uses the same path.
- Internals: add `sendRequest` and schema-validated metrics fetchers
with backward-compatible defaults.

<sup>Written for commit 5e5f641bbe.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/hexclave/hexclave/pull/1684?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>

<!-- End of auto-generated description by cubic. -->





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

* **New Features**
* User pages now display KPI metrics and total-user counts immediately
when available, with improved loading/skeleton behavior.
* User actions (create/update/delete/2FA changes) now automatically
refresh the table and KPI data.
  * Delete confirmation now includes a direct link to the user profile.
* **Bug Fixes**
* Improved navigation after user deletion using safer, encoded redirect
paths.
* Reduced duplicate error reporting for repeated metrics-loading
failures.
* Disabled unintended prefetching on user profile links for more
predictable navigation.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-05 21:22:05 -07:00
Armaan Jain
eba479b7cc
Fix session replay playback freezing the page (#1727)
Fixes the session replay player making the page laggy/unresponsive
during playback. Four compounding main-thread bottlenecks:

1. **Mini-tab re-seek every tick (main freeze cause).** Every 200ms TICK
emitted `sync_mini_tabs`, which calls `replayer.pause(offset)` on every
non-active tab. In rrweb v1 that's a full synchronous seek (rebuild from
last FullSnapshot + fast-forward all events), easily 100ms–1s+ of
blocking work per tab, 5×/sec. Now throttled to
`MINI_TAB_SYNC_INTERVAL_MS` (2s) in the state machine, reset on SEEK so
seeks re-sync promptly, and the executor skips tabs that aren't actually
rendered as mini thumbnails.

2. **Full-page re-render every 200ms.** Every dispatch force-rendered
the whole page component. Added `areStatesRenderEquivalent()` —
dispatches that only change playback bookkeeping fields
(`currentGlobalTimeMsForUi`, etc.) skip the React re-render; mini-tab
visibility is refreshed at the throttled sync cadence instead.

3. **Timeline re-rendered at 60fps.** The transport bar rAF loop used
`setState(currentTime)`, re-rendering the whole bar including up to 2000
marker divs every frame. Current time / progress are now written
directly to DOM refs, and the markers lane is extracted into a memoized
`TimelineMarkersLane`.

4. **Synchronous `addEvent` floods.** Background chunk processing now
yields to the event loop between chunks so feeding large batches into
live replayers doesn't block playback.

Added machine tests for the sync throttle, seek re-sync, and render
equivalence (117 passing).

Link to Devin session:
https://app.devin.ai/sessions/7d53fb70217d4ebaa77b9dbac2ba1f54
Requested by: @Developing-Gamer

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Fixes session replay playback freezing by removing main-thread
bottlenecks in the player and timeline. Playback stays smooth and
responsive; background loads finish faster in hidden tabs.

- **Bug Fixes**
- Throttled mini-tab syncing to `MINI_TAB_SYNC_INTERVAL_MS` (2s);
re-syncs on the next tick after seeks and when buffering resumes
(regardless of page age); skips non-rendered tabs to avoid `rrweb` full
seeks; refreshes mini-tab visibility on the throttled cadence.
- Skipped React re-renders for playback bookkeeping via
`areStatesRenderEquivalent`.
- Stopped 60fps timeline re-renders by writing time/progress to DOM refs
and memoizing the markers lane.
- Yield between event chunks only when the tab is visible; skip yields
in hidden tabs to avoid clamped timers and speed up background loads.
- Added tests for sync throttling, post-seek re-sync (immune to page
age), and render-equivalence.

<sup>Written for commit 4abc80c5f7.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/hexclave/hexclave/pull/1727?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>

<!-- End of auto-generated description by cubic. -->

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

* **Performance / UX**
* Session replay playback during rapid timeline changes is smoother,
with fewer unnecessary UI refreshes.
* Timeline progress/time updates are more immediate, and event markers
render more efficiently.
* **Bug Fixes**
* Mini-tab syncing is now throttled while playing and correctly re-syncs
after seeking to keep thumbnails accurate.
* Event/chunk loading now yields between batches to reduce main-thread
blocking.
* **Tests**
* Expanded session replay mini-tab sync tests to cover throttling and
post-seek resynchronization.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: armaan <armaan@stack-auth.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-07-05 21:18:16 -07:00
Armaan Jain
f2276ba39b
Onboarding auth page preview interactivity fix (#1721)
<!--

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

-->

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Restores full interactivity in the hosted auth preview across onboarding
and project settings, replaces Radix tabs with lightweight
`HostedPreviewTabs` with ARIA and keyboard support, and enables
Enter‑to‑submit in the create‑project dialog. Also keeps onboarding
progress dots centered on a fixed rail.

- **New Features**
- Replaced Radix tabs with custom `HostedPreviewTabs` (animated
indicator, ARIA roles/ids for tabs and panels, Arrow keys/Home/End
navigation).
- Hosted-style inputs and links are now interactive; typing and tab
switching work.
- Wrapped the create-project dialog in a form with a shared submit
handler; Enter in the name field submits, the primary button is
`type="submit"`, and IME composition is guarded.

- **Bug Fixes**
- Removed `pointer-events-none`, `inert`, and overlay divs that blocked
the auth preview in onboarding and the project auth-methods page.
- Centered onboarding progress dots with a fixed-width rail
(`w-[150px]`) and a left-offset back arrow; dots keep accessible labels
and `aria-current="step"`.

<sup>Written for commit 7a7f1d27e0.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/hexclave/hexclave/pull/1721?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>

<!-- End of auto-generated description by cubic. -->

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

* **New Features**
* Enhanced the “Create Project” dialog with native form submit behavior
and Enter-key handling, including safer concurrent creation and clear
post-create navigation.
* Refreshed hosted authentication previews to support fully interactive
tab switching.
* **Bug Fixes**
* Improved onboarding bottom step navigation layout for more consistent
back-button and progress positioning.
* Removed interaction-blocking styling/attributes in hosted preview
screens so users can click and type normally.
* **Tests**
* Added UI-focused assertions to verify interactive preview behavior and
form submission semantics.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: armaan <armaan@stack-auth.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-07-05 21:17:51 -07:00
Armaan Jain
d78405d7e7
Gate usage limit banners behind HEXCLAVE_DISABLE_PLAN_LIMITS (#1728)
## Summary

Threads `arePlanLimitsEnforced()` from the backend through the
plan-usage API response so the dashboard can hide all usage limit
banners when `HEXCLAVE_DISABLE_PLAN_LIMITS=true`.

Backend adds `are_plan_limits_enforced` to `planUsageResponseSchema`
(`.optional().default(true)` for backward compat with older backends) →
SDK surfaces it as `PlanUsage.arePlanLimitsEnforced` with `?? true`
runtime fallback (since `getPlanUsage()` returns raw JSON without yup
validation) → banner components early-return `null` when
`!arePlanLimitsEnforced`.

For the projects page (outside admin-app context, no project selected),
a server action reads the env var directly via
`getEnvVariable(\"STACK_DISABLE_PLAN_LIMITS\", \"false\")`.

Link to Devin session:
https://app.devin.ai/sessions/09ca53f13c294c8e98c7a7227a52217d
Requested by: @Developing-Gamer

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

* **New Features**
* Added support for a “plan limits enforced” flag to control messaging
across usage and billing-related screens.
* Projects and team invitation capacity checks now respect the same
enforcement toggle (including admin-seat invitation blocking).

* **Bug Fixes**
* Limit banners and “plan limit exceeded” alerts now only render when
enforcement is enabled (and overage/threshold conditions are met).
* Updated usage payload handling to default to enforcement enabled when
the flag is missing; added/updated tests for both enabled and disabled
scenarios.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: armaan <armaan@stack-auth.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-07-05 21:17:21 -07:00
github-actions[bot]
56dd0f357b chore: update package versions 2026-07-06 03:17:30 +00:00
BilalG1
4988312133
feat(dashboard): manual item quantity adjustments from customer payments view (#1731)
Adds a way for dashboard users to create a **manual item quantity
change** — positive or negative — for a single customer and a single
item, directly from the customer payments view.

**Base:** `dev` → **Head:** `feat/manual-item-quantity-change` · 4
files, +219/−10

## Demo

Full flow on a user detail page: open the Payments tab, hit the ± button
on an item balance row, apply **+5** with a description, then **−3** —
balance and transaction history update live.

![Manual item quantity change
flow](https://gist.githubusercontent.com/BilalG1/f55a8c9055cd0626320fb3153371fa97/raw/manual-item-quantity-change-flow.gif)

<sub>WebM version:
[trimmed.webm](https://gist.githubusercontent.com/BilalG1/f55a8c9055cd0626320fb3153371fa97/raw/trimmed.webm)</sub>

## Screenshots

| Adjust dialog (positive) | Adjust dialog (negative) |
| --- | --- |
| ![Positive change with live
preview](https://gist.githubusercontent.com/BilalG1/f55a8c9055cd0626320fb3153371fa97/raw/07-adjust-dialog-positive.png)
| ![Negative
change](https://gist.githubusercontent.com/BilalG1/f55a8c9055cd0626320fb3153371fa97/raw/09-adjust-dialog-negative.png)
|

| After applying changes | Entry point on item balance rows |
| --- | --- |
| ![Balance + transaction history
updated](https://gist.githubusercontent.com/BilalG1/f55a8c9055cd0626320fb3153371fa97/raw/10-after-negative-change.png)
| ![Item balances
card](https://gist.githubusercontent.com/BilalG1/f55a8c9055cd0626320fb3153371fa97/raw/06-user-payments-item-balances.png)
|

## What's new

- **`ItemQuantityChangeDialog`**
(`apps/dashboard/src/components/payments/item-quantity-change-dialog.tsx`)
- Signed integer quantity input (`10` adds, `-5` subtracts), validated
as a non-zero whole number, with a live `New balance: X → Y` preview.
  - Optional description, stored on the transaction.
- Submits via `adminApp.createItemQuantityChange` (which passes
`allow_negative: true`, so balances may go negative — consistent with
the existing admin API semantics).
- **Entry point** — a ± icon button on every row of the *Item balances*
card in `customer-payments-section.tsx`. Since that card is shared, the
feature works on the **user detail page**, **team detail page**, and the
payments **Customers page**, i.e. all three customer types (`user` /
`team` / `custom`).
- **SDK cache fix** (`packages/template`, SDKs regenerated) —
`createItemQuantityChange` previously left the item and transaction
caches stale, so a dashboard caller would keep seeing the old quantity.
It now refreshes the affected item cache (new protected
`_refreshItemCache` helper on the server app impl, mirroring what
`item.increaseQuantity` already did) and invalidates the transactions
cache. This is what makes the balance and transaction history update
immediately after applying a change.

## Notes for reviewers

- The dialog intentionally does not expose `expiresAt` (the API supports
it) — kept the surface minimal for the first pass.
- Transaction history already knew how to render
`manual-item-quantity-change` transactions (`api_credits (+25)` detail
rows), so no changes were needed there.
- The per-row dialog receives `currentQuantity` from the same `useItem`
hook that renders the row, so the preview can never disagree with the
displayed balance.

## Test plan

- [x] `pnpm typecheck` and `pnpm lint` green
- [x] Manual e2e against the seeded Demo Project (production builds of
dashboard + backend): created a user-scoped `api_credits` item, applied
`+25`, `−10`, `+5`, `−3` on a user — balance updated live (25 → 15 → 20
→ 17), each change produced an *Item quantity change* transaction,
success/error toasts behave, invalid input (`0`, non-integers)
disables/blocks Apply
- [x] Verified the adjust button renders for user-scoped items on the
user page (team/customers pages use the identical shared component)


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

* **New Features**
* Added an item quantity adjustment dialog for customer payments, with
live preview and “Apply change” support for manual whole-number deltas
(non-zero), plus success/error toasts.
* Payment item rows now include quick-action controls to open the
adjustment dialog directly.
* **Bug Fixes**
* Quantity updates now immediately refresh the affected item details and
keep related transaction data in sync after changes.
* Improved validation to reject invalid quantity inputs and provide
clearer inline feedback during submission.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-03 18:12:42 -07:00