Commit Graph

1738 Commits

Author SHA1 Message Date
github-actions[bot]
484850e8d2 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
Publish RDE dashboard release / publish-dashboard (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
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
2026-07-02 16:45:16 +00:00
aadesh18
d5d2f27a96
Move queryAnalytics to server app (#1687)
Moves `queryAnalytics` from the admin app to the server app so backend
code can call it without needing an over-privileged admin key. All
existing dashboard pages that ran queries internally are updated to use
`useServerApp()` instead of `useAdminApp()`.

## What changed

- **Backend**: New `POST /api/v1/analytics/query` and `POST
/api/v1/analytics/query/timing` endpoints on the **server** app
(previously admin-only)
- **Dashboard**: `queryAnalytics` calls in Queries, Query Analytics,
Session Replays, and Sign-up Rules pages switched from `adminApp` →
`serverApp`
- **Docs**: Added SDK + REST API usage example under the Queries section
of the Analytics guide
- **REST API reference**: New `Run analytics query` and `Get analytics
query timing` endpoints visible under Server API > Analytics

## Docs — Analytics › Queries section

New paragraph + code snippet showing
`hexclaveServerApp.queryAnalytics()` from backend code.

| | Light | Dark |
|---|---|---|
| **Before** |
![](https://gist.githubusercontent.com/aadesh18/e7950872b14557cfac823a99cb90ea9f/raw/analytics-before-light-queries.png)
|
![](https://gist.githubusercontent.com/aadesh18/e7950872b14557cfac823a99cb90ea9f/raw/analytics-before-dark-queries.png)
|
| **After** |
![](https://gist.githubusercontent.com/aadesh18/e7950872b14557cfac823a99cb90ea9f/raw/analytics-after-light-queries.png)
|
![](https://gist.githubusercontent.com/aadesh18/e7950872b14557cfac823a99cb90ea9f/raw/analytics-after-dark-queries.png)
|

<details>
<summary>Full-page overview (both themes)</summary>

| Light | Dark |
|---|---|
|
![](https://gist.githubusercontent.com/aadesh18/e7950872b14557cfac823a99cb90ea9f/raw/analytics-after-light.png)
|
![](https://gist.githubusercontent.com/aadesh18/e7950872b14557cfac823a99cb90ea9f/raw/analytics-after-dark.png)
|

</details>

## REST API reference — new Server API endpoints

`POST /analytics/query` and `POST /analytics/query/timing` now appear
under **Server API > Analytics** in the Mintlify reference.

| Light | Dark |
|---|---|
|
![](https://gist.githubusercontent.com/aadesh18/e7950872b14557cfac823a99cb90ea9f/raw/mintlify-run-analytics-query-light.png)
|
![](https://gist.githubusercontent.com/aadesh18/e7950872b14557cfac823a99cb90ea9f/raw/mintlify-run-analytics-query-dark.png)
|


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

* **New Features**
* Added public server-access analytics query support, including a query
timing endpoint for performance details.
  * Enriched API documentation for analytics queries and results.
* **Bug Fixes**
* Switched analytics querying across the dashboard and E2E tests to use
the correct public route and server access flow.
* Increased the long-request warning threshold for the analytics query
endpoint.
* **Documentation**
* Updated OpenAPI specs and the analytics guide with REST endpoint
details and examples.
* **Breaking Changes**
* Removed analytics query support from the admin client-side flow; use
the server-access method instead.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-02 09:42:10 -07:00
Konstantin Wohlwend
c5c853ccff Cleaner SMTP connections 2026-07-01 17:09:18 -07:00
Konstantin Wohlwend
82517ee69d Move dbSync to environment config 2026-07-01 12:44:33 -07:00
Konstantin Wohlwend
91d7362617 Add comment explaining how to use queryAnalytics 2026-07-01 11:57:28 -07:00
github-actions[bot]
e883f112fb chore: update package versions 2026-07-01 18:33:02 +00:00
Armaan Jain
db94ec2d94
More consistent dashboard (#1613)
<!--

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

-->

## Summary

This PR tightens dashboard consistency across the project list, team
invite flow, hosted auth previews, and shared overlay surfaces. It also
includes smaller visual fixes for charts/tooltips, globe sizing, sticky
data-grid surfaces, and dashboard/hosted component light-mode parity.

**Base:** `dev@2c5b2d02c` -> **Head:**
`more-consistent-dashboard@b1eae206`
**Capture notes:** screenshots were captured locally at `1440x1000`
after signing in through GitHub -> `admin@example.com` on the mock OAuth
server. Each page/state was allowed to settle for 5 seconds immediately
before capture. Dark mode is used by default; light mode is included
only for the light-specific overlay/dialog surfaces changed in this PR.

## Visual Comparison

### Hosted Auth Preview - Dark Mode

| Before | After |
| --- | --- |
| ![Before hosted auth preview
dark](https://gist.githubusercontent.com/Developing-Gamer/7f29365532f54161bc5b4531f7a71b1b/raw/before-auth-methods-preview-dark.png)
| ![After hosted auth preview
dark](https://gist.githubusercontent.com/Developing-Gamer/7f29365532f54161bc5b4531f7a71b1b/raw/after-auth-methods-preview-dark.png)
|

### Team Invite Dialog - Light-Specific Surface

| Before | After |
| --- | --- |
| ![Before team invite dialog
light](https://gist.githubusercontent.com/Developing-Gamer/7f29365532f54161bc5b4531f7a71b1b/raw/before-projects-invite-dialog-light.png)
| ![After team invite dialog
light](https://gist.githubusercontent.com/Developing-Gamer/7f29365532f54161bc5b4531f7a71b1b/raw/after-projects-invite-dialog-light.png)
|

## What's Changed

- Reworks the team invite dialog with clearer loading/retry states, seat
information, capacity warnings, pending invites, revoke actions, and
refresh behavior.
- Adds a dashboard-local hosted auth preview used by Auth Methods and
onboarding-style flows, showing sign-in/sign-up methods with project
display names and disabled sign-up behavior.
- Standardizes overlay and popover surfaces across dashboard, hosted
components, and shared UI primitives for better light/dark consistency.
- Adjusts chart, tooltip, globe, sidebar drawer, data-grid, and
email-log presentation details to reduce clipping, bleed, and stacking
issues.

## Notes For Reviewers

- The visual comparison focuses on places where this PR has visible UI
differences: project cards/actions, the team invite modal, overlay menu
styling, and the hosted auth preview.
- Lower-level primitive background/ring changes are represented through
the menu/dialog screenshots rather than separate screenshots for every
consuming component.

## Test Plan

- Captured the before screenshots on `dev@2c5b2d02c` and the after
screenshots on `more-consistent-dashboard@b1eae206`.
- Waited 5 seconds on each page/state before capturing screenshots.
- Uploaded exactly 10 screenshots to a fresh gist and embedded them
above.
- Not run in this pass: code tests, because this pass only updates the
PR description/screenshots.


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

## Summary by CodeRabbit

* **New Features**
* Added a live hosted authentication preview for project setup and auth
methods, including sign-in/sign-up states and multiple login options.

* **Bug Fixes**
* Improved invite dialog behavior so seat limits, plan upgrades, loading
states, retries, and invitation refreshes stay in sync.
* Fixed chart tooltip and globe display behavior so overlays, sizing,
and labels render more reliably.

* **Style**
* Refreshed dialogs, menus, tooltips, charts, and sidebars with improved
light/dark theme styling and spacing.

<!-- 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-01 09:24:08 -07:00
github-actions[bot]
c9612539c7 chore: update package versions 2026-06-30 23:15:23 +00:00
BilalG1
526ce69ab9
feat(cli): fetch RDE dashboard from GitHub Releases instead of bundling (#1682)
## Summary

The RDE dashboard was bundled into the `@hexclave/cli` npm tarball
(~165MB). That made the `npx @latest` auto-update re-exec pull a huge
tarball, which tripped download firewalls (Socket Firewall
false-positives on Replit → `Lock compromised`).

This decouples the dashboard from the CLI: it's published as a **GitHub
Release artifact** (a zip + `manifest.json` on a floating
`dashboard-latest` release) and fetched at runtime, cached on disk. The
dashboard now rolls forward **independently of the CLI version**
(assuming newest dashboards stay compatible with older CLIs — no compat
gate yet, by design for now).

## How it works

- **Runtime** (`packages/cli/src/lib/dashboard-release.ts`): on
`hexclave dev`, fetch `manifest.json` (`{version, sha256, url}`) from a
stable, no-API GitHub URL → cache under
`<dirname(devEnvStatePath())>/dashboards/<version>/` → streamed
download, **sha256 verify**, extract via the existing `extract-zip` dep,
atomic publish. Offline → fall back to the newest cached build.
- **Wiring** (`dev.ts`): `startDashboardIfNeeded` resolves/launches the
cached release; the restart decision now compares the **dashboard
release** version (not the CLI version). `HEXCLAVE_DASHBOARD_DIR` runs a
local build with zero network; a custom dev dashboard command bypasses
releases entirely.
- **No more npx self-update**: the `npx @latest` re-exec in `hexclave
dev` is removed entirely (along with `self-update.ts`, the
`--no-auto-update` flag, and the binName plumbing that only built the
npx call). It existed to keep the bundled dashboard fresh; now the
dashboard self-updates from GitHub, so the re-exec only added an npx
download on every run — the firewall surface. Users update the CLI via
npm/npx themselves.
- **Publishing** (`scripts/package-dashboard-release.mjs` +
`.github/workflows/dashboard-release.yaml`): build standalone → zip →
write manifest → publish immutable `dashboard-v<version>` release +
clobber the `dashboard-latest` manifest. **Fails loudly** if an existing
tag's asset sha differs from a fresh build (dashboard changed without a
version bump → would otherwise advertise a hash the served zip doesn't
match).
- **Build**: CLI build is now `tsdown`-only (no bundled dashboard);
`turbo.json` drops the dashboard standalone build from the CLI build
graph.

## Testing

- **Unit**: 135 CLI tests pass (manifest parsing incl. path-safe version
validation, URL resolution, version picking, dir override).
- **End-to-end (no GitHub)**: a localhost HTTP server + fixture zip
exercised the full fetch path — download, sha256 verify, cache-hit,
roll-forward, **corrupt-sha rejection**, offline→cache fallback (9/9).
- **Real dashboard, no GitHub**: built the standalone, served the real
76MB zip over `python -m http.server`, and confirmed `hexclave dev`
downloads → verifies → extracts → **boots** the dashboard and registers
an RDE session against the hosted backend. Also validated
`HEXCLAVE_DASHBOARD_DIR` boot.

## Review

Three review agents (runtime correctness, packaging/workflow, code
quality) ran; valid findings fixed: path-traversal hardening on
`version`, a concurrent cache rm/rename race, the workflow
sha-mismatch/atomicity gap, plus `errorMessage` dedup and added tests.

## Notes / follow-ups

- No CLI↔dashboard compatibility gate yet (assumes always-compatible);
easy to add later via a min-CLI field in the manifest. This matters more
now that the CLI no longer auto-updates.
- The publish workflow has not run yet, so the first push to `main` will
create the `dashboard-latest` release.

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

* **New Features**
* Added automated, immutable versioned releases for the standalone
dashboard plus a continuously updated “latest” manifest.
* CLI now fetches, verifies, caches, and supports offline fallback for
the dashboard runtime.
* **Bug Fixes**
* Improved dashboard restart behavior to update only when a strictly
newer published version is available.
* **Chores**
* Removed the CLI’s automatic update/re-launch behavior for more
predictable startup.
* **Tests**
* Added unit tests for dashboard manifest validation and latest-version
selection.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-30 16:12:13 -07:00
Konsti Wohlwend
6a979e8b3e
chore: remove unused dependencies from package.json files (#1698) 2026-06-30 15:45:25 -07:00
Konsti Wohlwend
d472283283
Use tsdown -W --watch (workspace mode) for dev builds (#1689) 2026-06-30 15:40:08 -07:00
github-actions[bot]
31b32735bf chore: update package versions 2026-06-30 20:44:13 +00:00
BilalG1
2f0d9bc6cb
fix(session-replay): gzip replay batches so large rrweb snapshots aren't dropped (#1675)
## Problem

Session replay batches are uploaded as **raw, uncompressed JSON**. A
single large rrweb full snapshot (>900 KB) is dropped client-side in
`SessionRecorder._flush`, and any batch near the server's 1 MB body
limit is rejected. Meanwhile the **analytics events** path right next
door already gzips on the wire (`encodeAnalyticsBody` + a server-side
gunzip with zip-bomb guards) — replays just never got the same
treatment.

Notably, `dev` was already **red** on the SDK test `sends a single
oversized event alone without dropping it` (the code dropped at 900 KB
while the test expected the event to be sent). This change makes that
test pass.

## What this does

Ports the proven analytics compression pattern to session replays:

- **`packages/shared` (client transport):** generalize
`encodeAnalyticsBody` → `encodeGzipJsonBody` and wire it into
`sendSessionReplayBatch`. Replays now gzip via native
`CompressionStream` (`application/octet-stream`), with the same
fallbacks: keepalive flushes send plain JSON (so the request survives
page teardown), and a missing/throwing `CompressionStream` (Safari <
16.4) degrades to plain JSON.
- **`packages/template` (SDK recorder):** replace the 900 KB hard-drop
with `MAX_SINGLE_EVENT_BYTES = 8 MB`, kept in sync with the server's
decompressed cap. The wire is gzipped downstream, so an oversized single
event is now sent compressed instead of discarded; only an event that
could never fit *decompressed* is dropped.
- **`apps/backend` (route):** add `maybeDecodeBinaryBody` (gunzip with a
1 MB compressed cap + 8 MB `maxOutputLength` zip-bomb guard) via a
`.transform` on the batch route body schema. Plain-JSON bodies pass
through untouched.

## Why gzip / CompressionStream

Benchmarked on a real rrweb capture (Puppeteer, rrweb 1.1.3): a **1.09
MiB full snapshot → 134 KiB gzip (~8×) in ~6.6 ms**. Native
`CompressionStream` adds **0 bundle bytes** and was faster than fflate.
This mirrors what PostHog (gzip, native `CompressionStream` + fflate
fallback) and Sentry (fflate deflate in a worker) both ship — both rely
on compression, not splitting, as the primary mechanism for large
events.

## Tests

- **Client SDK** (`client-interface.test.ts`): gzip+octet-stream on
non-keepalive (round-trip + size assert), plain JSON on keepalive, and
both `CompressionStream`-unavailable fallbacks.
- **SDK recorder** (`session-replay.test.ts`): existing oversized-event
test now passes; new test that a >8 MB event is dropped while a
following normal event still sends.
- **Backend e2e** (`session-replays.test.ts`): gzipped happy path
(`compressed < 1MB < raw`), invalid gzip → 400, oversized compressed →
413, zip-bomb → 400. Verified passing against a live local backend.

## Verification notes

- `@hexclave/shared` + `@hexclave/template` typecheck pass; touched
files lint clean; SDK unit tests pass.
- Two **pre-existing, unrelated** local failures (each confirmed by
stashing this change and re-running on clean `dev`): a backend typecheck
error in `oauth/ssrf-protection.test.ts` (`NODE_ENV` read-only), and 3
session-replay **quota** e2e tests failing in the payments
`setSessionReplayItemQuantity` setup helper.

## Follow-up (out of scope)

The keepalive/unload path still sends uncompressed (64 KB browser
keepalive cap), so a very large final batch on page exit can still be
lost — not addressed here.

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Gzip session replay batches so large rrweb snapshots are sent instead of
dropped. Keepalive flushes cap single-event size to avoid 413s on page
unload, and limits now include a 1 KiB envelope margin to match server
caps.

- **Bug Fixes**
- Client (`@hexclave/shared`): generalized `encodeAnalyticsBody` →
`encodeGzipJsonBody`; gzip via native `CompressionStream` for
`/session-replays/batch`; keepalive and missing/throwing
`CompressionStream` fall back to JSON.
- SDK recorder (`@hexclave/template`): normal flushes allow a single
event up to `MAX_SINGLE_EVENT_BYTES = 8 MiB - 1 KiB`; keepalive flushes
cap single-event size at `MAX_BATCH_UNCOMPRESSED_BYTES = 900 KB`; send
oversized events alone and rely on gzip; drop only above those
thresholds; log a distinct 413 warning with the count of buffered events
dropped and stop the loop.
- Backend: gunzip `application/octet-stream` bodies with caps (`1 MB`
compressed, `8 MiB` decompressed); invalid gzip → 400; oversized
compressed → 413; plain JSON passes through.
- Tests: added client encoding tests for session replays; SDK tests for
>8 MiB drop, keepalive drop, and 413 warning; backend e2e for gzip,
invalid gzip, oversized compressed, and zip-bomb. The oversized-event
SDK test now passes.

- **Refactors**
  - Hoisted shared test helpers and trimmed comments.

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

<a
href="https://cubic.dev/pr/hexclave/hexclave/pull/1675?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**
* Session replay batch uploads can now be automatically gzipped (when
supported) to reduce request size; analytics batch uploads use the same
behavior.
* **Bug Fixes**
* Improved handling of gzipped upload bodies, with stricter validation
and safer size/decompression limits to reject invalid payloads and “zip
bomb” scenarios.
* Updated session replay buffering so oversized events are dropped only
when they exceed decompression constraints, while allowing later events
to upload.
* **Tests**
* Added client, server, and end-to-end coverage for gzip/keepalive
behavior and limit enforcement.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-30 13:13:11 -07:00
Konstantin Wohlwend
7588445efa Update AI setup prompt 2026-06-30 11:36:13 -07:00
github-actions[bot]
9b52f76520 chore: update package versions 2026-06-30 18:27:55 +00:00
BilalG1
81433e5181
feat(emails): arbitrary-recipient send + Emailable on managed domains (#1681)
## Summary

Two related email changes:

### 1. Send to arbitrary email addresses
The `sendEmail` SDK function and `POST /api/v1/emails/send-email` now
accept a third recipient selector, **`emails: string[]`**, mutually
exclusive (XOR) with `user_ids` and `all_users`. These recipients don't
have to belong to a user — they're mapped to the existing internal
`custom-emails` recipient type (no associated user object, can't
unsubscribe, so intended for transactional mail).

- Response `results` items are now `{ user_id?, email? }`; the `emails`
path returns `{ email }`.
- Validation message updated to `Exactly one of user_ids, all_users, or
emails must be provided`.
- Recipient addresses are validated with the shared `emailSchema`.

### 2. Run Emailable on managed custom domains
`LowLevelEmailConfig.type` is widened `'shared' | 'standard'` →
`'shared' | 'managed' | 'standard'`, and `getEmailConfig` returns
`'managed'` for the managed-Resend branch. The Emailable deliverability
check now runs for **shared** and **managed**, and is skipped for
**`standard`** (a customer's own SMTP server or Resend API key).

**Why:** managed domains send through our single Resend *account*
(per-domain scoped keys, but shared account → account-level bounce
penalties are collateral across managed customers), so we own that
reputation. With a custom SMTP server or the customer's own Resend key,
the customer owns their deliverability, so we don't second-guess their
recipients or spend Emailable checks on their volume. The shared
dev-email wrapper remains `shared`-only.

## Tests
- `send-email.test.ts`: added arbitrary-recipient send
(single/multiple), empty-array, and validation cases (both-selectors,
no-selector, invalid email); updated the exactly-one-of snapshot.
**24/24 pass.**
- New `emails/deliverability-gating.test.ts`: shared & managed skip an
undeliverable address (`LIKELY_NOT_DELIVERABLE`), custom SMTP still
sends. **3/3 pass.**

> Note: `email-queue.test.ts` has 2 pre-existing snapshot failures (a
`margin:0rem`→`margin:0` CSS normalization in rendered email HTML) that
are unrelated to this change — confirmed by reproducing them on `dev`
with these changes stashed.

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Adds support for sending emails to arbitrary addresses and enables
Emailable checks for managed domains to protect shared sending
reputation. The API/SDK now accept `emails: string[]` as a recipient
selector, and deliverability checks run on shared and managed sending.

- New Features
- API/SDK: `emails: string[]` recipient selector (XOR with
`user_ids`/`all_users`) in `sendEmail` and POST
/api/v1/emails/send-email. Results return `{ email }` for this path;
addresses validated via `emailSchema`. Recipients map to
transactional-only “custom-emails” (no user, no unsubscribe).
- Deliverability: email config adds `'managed'`; `getEmailConfig`
returns it for managed Resend domains. Emailable check runs for `shared`
and `managed`; skipped for `standard` (custom SMTP or customer Resend
key).

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

<a
href="https://cubic.dev/pr/hexclave/hexclave/pull/1681?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**
* Emails can now be sent to arbitrary email addresses, not just existing
users.
* Email sending APIs and client options now accept an email list as a
recipient choice.

* **Bug Fixes**
* Improved recipient validation so exactly one target type must be
chosen.
* Fixed response results to consistently show either a user ID or an
email address.
* Corrected deliverability checks for managed email setups and updated
skip behavior for undeliverable addresses.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-30 11:16:25 -07:00
github-actions[bot]
ea2915faa8 chore: update package versions 2026-06-30 18:04:45 +00:00
Konsti Wohlwend
d6d9d0d934
Remove local emulator support (#1692) 2026-06-30 10:27:01 -07:00
github-actions[bot]
d962e9843a chore: update package versions 2026-06-30 17:18:40 +00:00
Konstantin Wohlwend
b049306b6e Make hexclave exec support local dashboard
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
2026-06-29 18:45:11 -07:00
github-actions[bot]
2c5b2d02cd chore: update package versions 2026-06-30 01:19:04 +00:00
Mantra
6bbc792fb3
refactor: migrate config parsing from Babel AST to jiti (#1661)
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
## Summary

Replace `parseHexclaveConfigFileContent` /
`evaluateStaticConfigExpression` (Babel AST walker) with
`evalConfigFileContent` using `jiti.evalModule()`. Move
`renderConfigFileContent` from `hexclave-config-file.ts` →
`config-rendering.ts`.

Added `jiti` dep to `@hexclave/shared` (already used in shared-backend,
dashboard, backend, cli).

Link to Devin session:
https://app.devin.ai/sessions/cb098b1fb62b4dfeaf3324bc2e1377f1
Requested by: @mantrakp04

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Migrates trusted config evaluation to `jiti` and moves GitHub config
edits to a server‑side repo agent running in a Vercel Sandbox with an
apply → review → commit flow. Adds run tracking, safer defaults, and a
dashboard diff review with clear, user‑facing errors.

- **New Features**
- Two‑phase flow and endpoints: POST `/internal/config/github/apply`,
`.../commit`, `.../cancel`, plus GET `.../run`; each run tracked by
`run_id` in `ConfigAgentRun` (status, stage, progress, diff, base
commit, sandbox id). Run ids validated as UUIDs.
- Repo agent runs in a fresh sandboxed clone; warm‑boot via base
snapshot (`apps/backend/scripts/config-agent/build-image.ts`,
`HEXCLAVE_CONFIG_AGENT_BASE_SNAPSHOT_ID`). Captures a unified diff and
base commit, stops the sandbox at review, then rebuilds files from the
stored diff on commit. Returns `commitSha`, uses a safe conflict error,
and strips OAuth tokens from git remotes.
- Dashboard: non‑dismissible progress and diff preview using
`@pierre/diffs` with a cross‑tab run watcher; blocks conflicting edits
and supports cancel/commit review flow. Adds an RDE “apply” path with
progress UI.
- AI proxy defaults to `/api/latest/integrations/ai-proxy` (production
passthrough via `PRODUCTION_AI_PROXY_BASE_URL`); adds
`anthropic/claude-haiku-4.5`.

- **Refactors and Fixes**
- Trusted eval via `@hexclave/shared` `config-eval` using `jiti`;
browser‑safe parsing for untrusted GitHub content; rendering remains in
`config-rendering`. Clear separation of Node‑only code into
`config-eval`.
- Shared agent/updater logic moved to `@hexclave/shared-backend`;
removed deterministic fast path so all writes go through the agent to
preserve authoring. CLI and emulator updated to use `config-eval`.
- Defaults/renames: config file `hexclave.config.ts` (CLI `config pull`
defaults to this path), workflow `hexclave-config-sync.yml`; env
prefixes standardized to `HEXCLAVE_*`.
- Integrity and UX: commit advancement gated to the current linked
repo/branch; cancel clears any captured diff; elapsed timer handles late
starts and the not‑started sentinel; loader vs invalid config export
errors separated for accurate messaging.
- Onboarding and seeds: wizard now uses environment‑based OAuth provider
setup with updated tests; corrected GitHub owner in dummy project
seeding.

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

<a
href="https://cubic.dev/pr/hexclave/hexclave/pull/1661?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

* **Refactor**
* Improved configuration file parsing/validation by evaluating config
modules, supporting both string and object-based `config` exports and
ensuring the expected `config` export is present.
* Updated config rendering and import-package detection to consistently
generate the `config` export and handle legacy package entrypoints.
* Tightened handling of non-statically-resolvable forms during update
flows.
* **Tests**
* Updated and extended config parsing/validation tests to reflect the
new evaluation behavior and edge cases.
* **Chores**
  * Added a Jiti-based dependency to support runtime evaluation.
<!-- 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>
2026-06-29 10:25:11 -07:00
devin-ai-integration[bot]
4a0f2b1778
Default user export to filtered scope; note Anonymous in all-users label (#1679)
## Summary
Two changes to the user data export dialog on the project Users page:

1. The export scope now defaults to **"Export only filtered/searched
users"** instead of "all users".
2. The all-users option label is now **"Export all users in the project
(includes Anonymous)"**.

To keep this scoped to the Users table (the shared export dialog is
reused by other tables), the dialog's default scope is made configurable
rather than changed globally:

- `DataGridExportOptions` gains `defaultScope?: DataGridExportScope`
(defaults to `"all"`).
- The dialog initializes `useState(exportOptions?.defaultScope ??
"all")`.
- `user-table.tsx` passes `defaultScope: "filtered"` and the updated
`allScopeLabel`.

Other tables (teams, transactions, emails) are unaffected — they keep
the `"all"` default.

Link to Devin session:
https://app.devin.ai/sessions/4996678b2b944090b6eef2f64f0a62a1

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Default the Users export dialog to filtered scope and clarify that the
"all users" option includes Anonymous; scope resets to the per-table
default only when the dialog reopens, and other tables keep "all".

- **New Features**
- Added `defaultScope` to export options and initialized scope from it;
Users table sets `defaultScope: "filtered"` and updates the all-users
label.
- Reset scope to `defaultScope` only on a closed→open transition to
avoid changing it while the dialog is open.

- **Bug Fixes**
- Stubbed `NODE_ENV` via `vi.stubEnv` in
`apps/backend/src/oauth/ssrf-protection.test.ts` to fix lint and prevent
env mutation.

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

<a
href="https://cubic.dev/pr/hexclave/hexclave/pull/1679?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: vedanta.gawande <vedanta.gawande@gmail.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-06-29 09:31:06 -07:00
github-actions[bot]
092c27dd0e chore: update package versions 2026-06-27 22:00:12 +00:00
github-actions[bot]
e70e95a3af chore: update package versions 2026-06-27 00:28:49 +00:00
Konstantin Wohlwend
cf17fff37d stack dev -> hexclave dev 2026-06-26 16:05:34 -07:00
Konstantin Wohlwend
32e5a1ccbc Log config update agent stdout & stderr if needed 2026-06-26 16:05:34 -07:00
github-actions[bot]
c868ec31bc chore: update package versions 2026-06-26 21:28:46 +00:00
Konstantin Wohlwend
a19f686c92 Update reminder with instructions on ask timeouts 2026-06-26 14:22:56 -07:00
github-actions[bot]
788e7cc87c chore: update package versions 2026-06-26 21:18:23 +00:00
Konstantin Wohlwend
73b8a0c27f Fix redirect URL on devtool indicator 2026-06-26 14:12:47 -07:00
Konstantin Wohlwend
912eea4f7f Improve local agent update logging 2026-06-26 14:08:03 -07:00
Konstantin Wohlwend
dff454f47f Document init script less 2026-06-26 13:50:48 -07:00
github-actions[bot]
ee48755ef3 chore: update package versions 2026-06-26 20:38:10 +00:00
Konstantin Wohlwend
ee93732e8e Silence HEXCLAVE_BOT_CHALLENGE_SITE_KEY warning 2026-06-26 13:30:54 -07:00
Konstantin Wohlwend
932a676596 Improve setup instructions 2026-06-26 13:27:45 -07:00
Vedanta-Gawande
164374f6c8
User page email filtering (#1668) 2026-06-26 12:27:24 -07:00
github-actions[bot]
53b0cae480 chore: update package versions 2026-06-26 19:10:16 +00:00
github-actions[bot]
fc6d111e6b chore: update package versions 2026-06-26 18:50:39 +00:00
Konsti Wohlwend
325fb791f6
fix: prevent OAuth callback race condition between startup handler and OAuthCallback component (#1671) 2026-06-26 11:44:28 -07:00
BilalG1
d2a84f5a28
fix: reduce recurring production Sentry errors (Stripe webhooks, email, session replay) (#1667)
## Summary

A cleanup pass over recurring production errors triaged from Sentry
(`stackframe-pw` org). The common thread: expected/edge-case conditions
thrown as `HexclaveAssertionError` / `captureError`, so Sentry filed
them as errors (and, for the Stripe ones, Stripe redelivered
indefinitely). Each is handled at the source or logged at the correct
severity.

| Sentry issue | Fix | Risk |
|---|---|---|
|
[STACK-BACKEND-1F5](https://stackframe-pw.sentry.io/issues/STACK-BACKEND-1F5)
— `Unknown stripe webhook type` (`invoice_payment.paid`, `payout.paid`)
| Add both to `ignoredEvents`. They fell through to the throwing `else`
and Stripe redelivered them. (`payout.failed`/`canceled`/`updated`
intentionally left unhandled for now.) | Trivial |
|
[STACK-SERVER-1ZV](https://stackframe-pw.sentry.io/issues/STACK-SERVER-1ZV)
— session-replay `413 Request body too large` | Measure event size in
UTF-8 bytes (was UTF-16 `.length`, which undercounts multibyte content);
drop a single oversized event with a warning instead of shipping a
doomed request | Low |
|
[STACK-BACKEND-140](https://stackframe-pw.sentry.io/issues/STACK-BACKEND-140)
+
[STACK-BACKEND-1F1](https://stackframe-pw.sentry.io/issues/STACK-BACKEND-1F1)
— `Unknown error while sending (test) email` | Classify refused SMTP
connections (`ECONNREFUSED`, surfaced by nodemailer as `code:
'ESOCKET'`) as a typed `CONNECTION_REFUSED` error with a real
user-facing message, instead of falling through to the `UNKNOWN`
catch-all in both the low-level sender and the send-test-email route.
Marked `canRetry` so the queued-email path reschedules with backoff. |
Low |

## Notes

- **Session replay (1ZV):** edited the `packages/template`
source-of-truth; the generated SDK copies are gitignored and regenerated
by CI (`pnpm -w run generate-sdks`). The `TextEncoder` is hoisted out of
the rrweb emit hot path to avoid per-event allocation.
- **Email classification (140/1F1):** the new `CONNECTION_REFUSED`
errorType is additive — other consumers only read `errorType` for
logging, and the send-test-email route only special-cases `UNKNOWN`, so
the new type cleanly bypasses both assertion captures. `canRetry: true`
is safe because the connection is refused before any SMTP exchange (no
message handed off → no duplicate-delivery risk); transient refusals
recover, and a persistent misconfig still fails after
`MAX_SEND_ATTEMPTS`. The one-shot send-test-email path ignores
`canRetry`, so its immediate feedback is unchanged.

## Investigated but intentionally NOT changed here

These were initially included, then reverted so we keep getting Sentry
signal while the root causes are still under investigation:

-
**[STACK-BACKEND-1GM](https://stackframe-pw.sentry.io/issues/STACK-BACKEND-1GM)**
— `Stripe webhook bad customer id`. A subscription-changed event with no
customer (the observed case was a Stripe-CLI test
`payment_intent.succeeded` against a dev-connected account). Skipping is
likely the right long-term fix, but kept the throw for now to keep
observing. Note: in live mode the same path could fire on legitimate
customerless one-time payments / guest checkouts.
-
**[STACK-BACKEND-1CN](https://stackframe-pw.sentry.io/issues/STACK-BACKEND-1CN)**
— `Recovered N stale outgoing request(s)`. This is a self-healing
recovery notice (0 user impact); the underlying cause is the poller
process dying between the claim `UPDATE` and the delete. Kept at
`captureError` to keep collecting data on how often / why it happens.

## Verification
- `typecheck` clean: `@hexclave/backend`, `@hexclave/template`,
`@hexclave/js`, `@hexclave/react`, `@hexclave/next`,
`@hexclave/tanstack-start`
- `eslint` clean on all touched files
2026-06-25 14:48:49 -07:00
BilalG1
b8e384493d
feat(payments): unified customers table + Create checkout everywhere (#1666)
## Summary

Two related payments/dashboard changes:

1. **Customer page rework** (`/projects/<id>/payments/customers`) —
replaces the old single-customer selector page with **one unified
table** of users, teams, and custom customers, with filtering and
search. Clicking a row opens a customer view that renders the **same
data as the payments tab** on the user/team detail pages, plus a button
to return to the list.
2. **"Create checkout" everywhere** — the existing checkout dialog is
now reachable from every relevant surface (user table, team table,
user/team detail payments tabs, product detail page, product-lines
cards, and the customer detail view), all driven by **one shared
dialog**.

> ℹ️ Screenshots are from a local dev environment (test-mode banner +
dev-tools rail are dev-only chrome).

---

## 1. Customers page rework

A single `DataGrid` lists users + teams + custom customers (custom ones
are derived from transactions, since they aren't otherwise enumerable).
It uses the existing table/filter components: a **Type** filter (All /
Users / Teams / Custom) and quick-search.

![Customers
table](https://gist.githubusercontent.com/BilalG1/20311c5660f8ad04a5b651b1c6bcbc5f/raw/01-customers-table.png)

Filtering by type — e.g. **Custom** customers surfaced from transaction
history:

![Customers filtered to
Custom](https://gist.githubusercontent.com/BilalG1/20311c5660f8ad04a5b651b1c6bcbc5f/raw/02-customers-filter-custom.png)

Clicking a row opens a **read-only customer view** that is identical to
the payments tab on the user/team detail pages (metrics, products &
subscriptions, transaction history, item balances), with a **"Back to
customers"** button and a **Create checkout** button:

![Customer detail
view](https://gist.githubusercontent.com/BilalG1/20311c5660f8ad04a5b651b1c6bcbc5f/raw/03-customer-detail.png)

To guarantee the view is identical, the user/team payments tabs and this
page now share one generic `CustomerPaymentsSection` component keyed by
`(customerType, customerId)`.

---

## 2. Create checkout everywhere (one shared dialog)

The single `CreateCheckoutDialog` now supports:

- **Customer pre-selected** → just choose a product (tables, detail
tabs, customer detail view):

![Dialog with pre-selected
customer](https://gist.githubusercontent.com/BilalG1/20311c5660f8ad04a5b651b1c6bcbc5f/raw/04-dialog-preselected.png)

- **Locked product + customer selector** → launched from a product, the
product is fixed and you pick the customer:

![Dialog launched from a
product](https://gist.githubusercontent.com/BilalG1/20311c5660f8ad04a5b651b1c6bcbc5f/raw/05-dialog-from-product.png)

The customer selector reuses the existing searchable user/team tables
(nested dialog):

![Customer
picker](https://gist.githubusercontent.com/BilalG1/20311c5660f8ad04a5b651b1c6bcbc5f/raw/06-customer-picker.png)

Resulting checkout URL:

![Checkout URL
result](https://gist.githubusercontent.com/BilalG1/20311c5660f8ad04a5b651b1c6bcbc5f/raw/07-checkout-url-result.png)

### Entry points

**Product detail page** — in the ellipsis menu:

![Product detail ellipsis
menu](https://gist.githubusercontent.com/BilalG1/20311c5660f8ad04a5b651b1c6bcbc5f/raw/08-product-ellipsis-menu.png)

**Product-lines** product-card menu:

![Product-lines card
menu](https://gist.githubusercontent.com/BilalG1/20311c5660f8ad04a5b651b1c6bcbc5f/raw/09-productlines-card-menu.png)

**User table** row action (team table is analogous):

![User table action
menu](https://gist.githubusercontent.com/BilalG1/20311c5660f8ad04a5b651b1c6bcbc5f/raw/10-user-table-action.png)

**User detail payments tab** (and **team detail payments tab**) get a
Create-checkout button in the header:

![User payments
tab](https://gist.githubusercontent.com/BilalG1/20311c5660f8ad04a5b651b1c6bcbc5f/raw/11-user-payments-tab.png)

![Team payments
tab](https://gist.githubusercontent.com/BilalG1/20311c5660f8ad04a5b651b1c6bcbc5f/raw/12-team-payments-tab.png)

---

## Implementation notes

- **New SDK method**: `adminApp.createCheckoutUrl({ userId | teamId |
customCustomerId, productId, returnUrl? })` added to the
`@hexclave/template` **server** app (interface + impl). This is what
enables checkout for **custom** customers, which previously had no
checkout path (the old dialog only called
`customer.createCheckoutUrl(...)` on a `ServerUser`/`Team` object).
Regenerate SDKs after pulling (`pnpm -w run generate-sdks`).
- It lives on the server app (not client) deliberately: it targets an
*arbitrary* customer, which is a server/admin capability. The backend
route enforces this — for `client` auth it calls
`ensureClientCanAccessCustomer(...)` ("clients can only create purchase
URLs for their own user or teams they admin"). The client's safe, scoped
path is the existing customer-object method `user.createCheckoutUrl()` /
`team.createCheckoutUrl()`. The new method sits alongside
`grantProduct`/`createItemQuantityChange`/`getItem`, which take the same
`{ userId | teamId | customCustomerId }` shape.
- **New shared components** under
`apps/dashboard/src/components/payments/`:
- `customer-selector.tsx` — `CustomerSelector`, `CustomerTypeSelect`,
`SelectedCustomer`, `customerToMutationOptions` (extracted from the old
customers page).
- `customer-payments-section.tsx` — generic payments view;
`user-payments.tsx` / `team-payments.tsx` are now thin wrappers over it.
- `CreateCheckoutDialog` reworked to take a unified `customer`
descriptor and the new selector / locked-product props.

## Testing

- `pnpm typecheck` and `pnpm lint` pass.
- Manually verified end-to-end against a seeded local project (test
mode): generated real checkout URLs for a **custom** customer and a
**team**, exercised every entry point above, the type filter
(All/Users/Teams/Custom), search, row → detail → back, and the error
states (e.g. "product already granted", "no products for this customer
type").


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

* **New Features**
* Added a unified Customers browser for payments with filter, quick
search, infinite scrolling, and a customer detail view.
* Enabled “Create checkout” directly from product and customer-related
screens (including list/dropdown actions).
* Added streamlined “customer payments” views (metrics, transactions,
product/subscription info, and item balances where available).
* Introduced a flexible customer picker to support user, team, and
custom customers in checkout flows.
* **Bug Fixes**
* Improved checkout validation, dialog open/close behavior, and
empty-state handling when no customer or products are available.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-25 14:48:27 -07:00
github-actions[bot]
c749cf2b62 chore: update package versions 2026-06-25 19:11:40 +00:00
Armaan Jain
81723c3d55
Usage page performance improvements (#1650)
<!--

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
Speed up the Usage page by aggregating metered usage across owned
projects/tenancies with fewer queries and new indexes. Adds E2E tests to
verify team-owned rollups and calendar‑month windows.

- **Performance**
- Added concurrent indexes for `EmailOutbox(tenancyId,
startedSendingAt)` and `SessionReplay(tenancyId, startedAt)`; updated
Prisma schema.
- Group tenancies by (DB client, schema) and run one SQL per group that
counts both emails and session replays; uses `mapWithConcurrency` from
`@hexclave/shared` (concurrency 4, aborts on first error).
- Added helpers `getOwnedProjectAndTenancyIdsForBillingTeam` and
`getNonAnonymousUserCountForTenancies`; made `mapWithConcurrency`
null‑safe with bounds checks.

- **Tests**
- Added E2E tests for the internal plan-usage endpoint covering
team-owned rollups, calendar‑month boundaries, and zero‑usage cases.
- Added unit tests for ownership scope resolution and non‑anonymous user
counting.

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

<a
href="https://cubic.dev/pr/hexclave/hexclave/pull/1650?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 Improvements**
* Improved plan usage rollups by aggregating metered emails and session
replays together across an owned scope.
* Added database indexes to speed up time-window metering lookups for
email outbox and session replays.
* **Tests**
* Extended unit tests for billing-team entitlement aggregation and
non-anonymous user counting.
* Added end-to-end coverage for the internal plan-usage endpoint,
including seeded scenarios and period validation.
* **Refactor**
* Reworked entitlement and usage calculations to reuse shared logic for
more consistent results.
<!-- 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-06-24 12:25:20 -07:00
Konstantin Wohlwend
6883d83ad1 Fix overlay warning 2026-06-24 11:25:58 -07:00
github-actions[bot]
09c9df410a 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
2026-06-24 01:55:58 +00:00
Konsti Wohlwend
bf265abf88
refactor: move esbuild utils from stack-shared to shared-backend (#1653)
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
2026-06-23 16:23:04 -07:00
Konsti Wohlwend
a6c46db72c
perf: prefetch email theme previews during earlier onboarding steps (#1655) 2026-06-23 15:46:03 -07:00
Konsti Wohlwend
59f6e53f7e
chore: upgrade deprecated dependencies (#1654) 2026-06-23 15:44:37 -07:00
Konstantin Wohlwend
012098e1a9 Change Quick Sign Up email address 2026-06-23 13:23:17 -07:00