Commit Graph
1428 Commits
Author SHA1 Message Date
BilalG1andGitHub 2a67053758 Fix Elysia production compatibility (#1757)
DB migration compat / Check if migrations changed (push) Has been cancelled
DB migration compat / Back-compat — Current branch migrations with ${{ needs.check-migrations-changed.outputs.base_branch }} branch code (push) Has been cancelled
DB migration compat / Forward-compat — Current branch code with ${{ needs.check-migrations-changed.outputs.base_branch }} branch migrations (push) Has been cancelled
DB migration compat / No migration changes (skipped) (push) Has been cancelled
## Summary

- use Vercel's native Elysia framework support with `src/index.ts` as
the deployment entrypoint
- remove the manual `api/` entrypoints and all `vercel.json` rewrites
- continue loading the prebuilt `dist/vercel.mjs` bundle so the
backend's existing tsdown bundling remains unchanged
- keep API-version migration paths internal instead of exposing them
through `x-middleware-rewrite`
- add integration coverage for the migration branch's global Elysia
error boundary and sanitized 500 response
- inherit the Vercel project's 800-second maximum duration for every
backend route

## Why

The staging deployment timed out every request at the configured
60-second function limit. The serverless entrypoint returned a Web
`Response` from a default-exported function, but Vercel interpreted that
export shape as the legacy Node `(request, response)` handler contract
and waited for the unused response object to be ended.

The Elysia migration also exposed the internal API-version migration
destination through `x-middleware-rewrite`. That header was internal
Next.js routing state and was not exposed by the previous production
transport.

Consolidating the backend into one function initially hardcoded a
60-second duration. That was especially significant for the external DB
sync poller and sequencer, whose normal work loops allow up to 180
seconds. The Vercel project is already configured with an 800-second
maximum, so the backend now inherits that setting directly instead of
maintaining route-specific wrapper files.

Vercel's native Elysia builder recognizes `src/index.ts` when it
contains a direct `elysia` import, and automatically routes requests to
that application. This makes the manual catch-all rewrite and root
`api/` directory unnecessary.

## Production behavior

- Vercel requests are routed directly to the Elysia application through
the native Elysia builder.
- API migration routes retain their public URL without revealing
internal migration paths.
- Uncaught middleware or dispatch errors are captured by the global
boundary and return a generic `500 Internal Server Error` with the
global security headers.
- All external DB sync endpoints—`fusebox`, `poller`, `sequencer`,
`status`, and `sync-engine`—inherit the project's 800-second function
duration.
- GitHub config `apply`, `commit`, and `cancel` also inherit 800
seconds. This raises the previous 120-second `commit` and 60-second
`cancel` maximums; normal successful behavior is unchanged, but a stuck
invocation can run and be billed for longer before Vercel terminates it.

## Tradeoffs

The function-duration policy is now controlled in one place—the Vercel
project—rather than split between dashboard configuration and route
wrappers. This is simpler and ensures long-running backend routes have
enough time, but changing the project setting affects every endpoint.

The native entrypoint remains a thin wrapper around the tsdown-generated
bundle rather than asking Vercel to bundle the backend source graph.
This preserves the existing alias and dependency bundling behavior while
still using Vercel's native Elysia routing.

The remaining lower-priority Elysia migration compatibility items are
intentionally deferred to follow-up PRs.

## Validation

- `pnpm test run apps/backend/src/server/app.ts` — 2 tests passed
- focused TypeScript check for the native entrypoint and bundle
declaration
- the installed Vercel Elysia builder identifies `src/index.ts` as the
application entrypoint
- `pnpm test run
apps/e2e/tests/backend/endpoints/api/migration-tests.test.ts` against
the running local backend — 13 tests passed
- live browser and raw HTTP checks confirmed a migrated route returns
200 and does not expose `x-middleware-rewrite`
- backend build not run locally, per repository policy
2026-07-16 14:40:09 -07:00
Konstantin WohlwendandCursor b11257fd5b Re-add Elysia backend transport
Keep the transport migration isolated on a dedicated branch so development can continue without blocking dev.

Co-authored-by: Cursor <[email protected]>
2026-07-13 12:41:55 -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 WohlwendandGitHub f33cb4cbc5 Fix flaky payment e2e tests: await async Stripe webhook processing + deterministic fixtures (#1746)
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
MantraGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>mantraCursorBilal Godil
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 <[email protected]>
Co-authored-by: Cursor <[email protected]>
Co-authored-by: Bilal Godil <[email protected]>
2026-07-09 21:45:15 -07:00
MantraGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>mantraCursorBilal Godil
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 `[email protected]`.

- **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 <[email protected]>
Co-authored-by: Cursor <[email protected]>
Co-authored-by: Bilal Godil <[email protected]>
2026-07-09 21:39:28 -07:00
Konsti WohlwendGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
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 WohlwendandGitHub 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
github-actions[bot] 105f03fb94 chore: update package versions 2026-07-06 23:34:27 +00:00
Konsti WohlwendandGitHub 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
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
Armaan JainGitHubarmaanDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
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 <[email protected]>
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
nams1570 b6a5fb2ac6 fix: fail loud if batch size not passed correctly 2026-07-03 16:28:35 -07:00
Konstantin Wohlwend b9694ea031 Much faster backfill script 2026-07-03 10:34:20 -07:00
Konstantin Wohlwend b6444e0164 More and better Bulldozer logs 2026-07-03 10:31:41 -07:00
nams1570 08d0528f2e feat: customizable batch size + better logging on backfill 2026-07-03 10:09:02 -07:00
Konstantin Wohlwend 121793595d Decrease Bulldozer Payments init batch size to 50 2026-07-03 09:43:53 -07:00
Konstantin Wohlwend 1ae0611248 Decrease Bulldozer payments init batch size to 100 from 500, add timings 2026-07-02 15:55:38 -07:00
github-actions[bot] 976aaffd56 chore: update package versions 2026-07-02 17:12:34 +00:00
Aman GanapathyandGitHub ec35b067eb [Feat] [Refactor]: Implement Bulldozer JS (#1700) 2026-07-02 10:09:46 -07:00
github-actions[bot] 484850e8d2 chore: update package versions
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
aadesh18andGitHub 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
Konsti WohlwendandGitHub 56b7acea93 feat: add AI tool to read the branch config object (#1702) 2026-07-01 11:51:34 -07:00
github-actions[bot] e883f112fb chore: update package versions 2026-07-01 18:33:02 +00:00
github-actions[bot] c9612539c7 chore: update package versions 2026-06-30 23:15:23 +00:00
Konsti WohlwendandGitHub 6a979e8b3e chore: remove unused dependencies from package.json files (#1698) 2026-06-30 15:45:25 -07:00
Konsti WohlwendandGitHub 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
BilalG1andGitHub 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
github-actions[bot] 9b52f76520 chore: update package versions 2026-06-30 18:27:55 +00:00
BilalG1andGitHub bdb511f6a9 Make analytics include_all_branches a no-op with TODO (#1678)
## What

The `/internal/analytics/query` route accepts an `include_all_branches`
flag (defaults to `false`). Previously, passing `true` threw a
`HexclaveAssertionError`. Since the flag is reachable from user input,
that assertion surfaced as a 500 / error-tracking noise rather than a
clean response.

This makes the flag a **no-op** for now and documents the intended
behavior with a TODO.

## Behavior

- Regardless of `include_all_branches`, queries remain scoped to the
current branch via the ClickHouse row policy that filters on
`SQL_branch_id` (set from `auth.tenancy.branchId`).
- Callers passing `include_all_branches=true` will still only receive
data for the **current branch** until cross-branch filtering is
implemented.

## Note / follow-up

Because the flag is silently ignored, a caller asking for "all branches"
gets single-branch results with no signal. The TODO tracks implementing
real cross-branch querying. Flagging in case we'd rather surface a
proper client-facing error in the interim instead of a silent no-op.

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Made the `include_all_branches` flag on `/internal/analytics/query` a
no-op so `true` no longer throws and avoids 500s from user input.
Branching isn’t implemented yet, so queries always scope to the current
branch via the ClickHouse `SQL_branch_id` row policy; TODO added for
real cross-branch querying.

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

<a
href="https://cubic.dev/pr/hexclave/hexclave/pull/1678?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**
* Analytics requests now accept the “include all branches” option
without failing.
* Branch-scoped analytics queries continue to run as before, while the
option is treated as a no-op for now.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-30 11:16:37 -07:00
BilalG1andGitHub 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
BilalG1andGitHub 4cd766e406 fix(backend): use structured output for QA reviewer instead of JSON.parse (#1688)
## Problem

The QA reviewer (`apps/backend/src/lib/ai/qa-reviewer.ts`) extracted the
model's JSON verdict from free-form text with a greedy `/\{[\s\S]*\}/`
regex followed by `JSON.parse`. Whenever Haiku wrapped its JSON in prose
or tool-call text, the captured slice was malformed and `JSON.parse`
threw:

```
SyntaxError: Expected property name or '}' in JSON at position 1 (line 1 column 2)
```

This is Sentry issue **STACK-BACKEND-18F** — **218 occurrences in the
last 30 days** (262 all-time), still ongoing. It's caught (background QA
task, 0 users impacted) but noisy, and on failure the review is silently
marked failed.

### Root cause
The brace-matching heuristic assumes the first `{` in the response
starts the JSON object and the last `}` ends it. Any stray brace in
surrounding prose (a preamble like `"Here's my review {note}: {...}"`,
unquoted/single-quoted keys, or `<function_calls>` tool text) breaks the
extraction. The reviewer output is non-deterministic, so a low steady
fraction of reviews fail.

## Fix

Switch to schema-enforced **structured output** via `generateText`'s
`output: Output.object({ schema })` (AI SDK v6), which keeps the
existing tool-calling loop while constraining the final result to a
validated object. The verdict is read directly off `result.output`,
removing the regex, `JSON.parse`, and manual `typeof` shape validation.

- Net **−12 lines**.
- Trimmed the now-redundant "respond with ONLY valid JSON … {inline
schema}" block from the system prompt (the schema enforces structure);
kept the semantic guidance (flag types, scoring, `needsHumanReview`
rule).
- Kept the existing `overallScore` clamp.

## Verification

- **Typecheck** (`tsc --noEmit`): clean.
- **Lint** (`eslint`): clean.
- **Live end-to-end**: ran the real Haiku-4.5 reviewer against the exact
prompt/input that failed **11/15** on the old path → **15/15** return a
validated object on the new path, zero parse failures.

## Follow-ups (out of scope, noted during investigation)
- These Sentry events leak a live access token + publishable key into
the request-context payload; the OpenRouter key sits in plaintext
(commented) in `apps/backend/.env.local`. Worth rotating/scrubbing.
- Consider capturing `result.text` on the failure path so any residual
structured-output failures are inspectable (currently discarded).

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Replaced regex/JSON.parse extraction in the QA reviewer with
schema-enforced structured output using `ai`’s `generateText` +
`Output.object`. Also defaulted `improvementSuggestions` to an empty
string to avoid false failures when the model omits suggestions.

- **Bug Fixes**
  - Added a `zod` verdict schema and read result from `result.output`.
  - Removed greedy JSON extraction and manual shape checks.
- Defaulted `improvementSuggestions` to "" to tolerate omission and
prevent false `needsHumanReview` verdicts.
- Slimmed prompt by dropping “respond with ONLY JSON” block; kept review
guidance.
  - Kept `overallScore` clamp; tool-calling loop unchanged.
- Verification: typecheck/lint clean; 15/15 successful runs on a
previously failing case.

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

<a
href="https://cubic.dev/pr/hexclave/hexclave/pull/1688?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**
* QA reviews now use structured output, making review results more
reliable and consistently formatted.
* Review flags now include clearer details such as type, severity, and
explanation.

* **Bug Fixes**
* Improved handling of review output by removing fragile text parsing
and manual JSON extraction.
  * Added safer defaults for missing review suggestions.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-30 11:15:46 -07:00
github-actions[bot] ea2915faa8 chore: update package versions 2026-06-30 18:04:45 +00:00
Konsti WohlwendandGitHub 09c8ef1946 Keep local emulator removal in a new migration, not edits to applied ones (#1694) 2026-06-30 10:43:10 -07:00
09bb1a8974 chore: use glm-5.2:nitro for unauthenticated AI tiers; document CLI exec & config sync (#1693)
## Summary
- Standardize the unauthenticated `smart` and `smartest` model tiers in
`apps/backend/src/lib/ai/models.ts` on `z-ai/glm-5.2:nitro` (previously
a mix of `z-ai/glm-5.2` and `z-ai/glm-5:nitro`).
- Document the `npx @hexclave/cli exec <javascript>` command (runs JS
with a pre-configured `hexclaveServerApp`) in the agent reminders.
- Note that the config file is automatically synced when using the local
dashboard/dev environment via `npx @hexclave/cli dev --config-file
<path>`.

These reminder updates are reflected across `docs-mintlify/llms.txt`,
`docs-mintlify/snippets/hexclave-agent-reminders.jsx`,
`docs-mintlify/snippets/home-prompt-island.jsx`, and
`docs-mintlify/guides/getting-started/setup.mdx`.

## Test plan
- [ ] Verify unauthenticated AI requests resolve to `z-ai/glm-5.2:nitro`
for smart/smartest tiers.
- [ ] Confirm docs render the new agent-reminder bullets correctly.

Made with [Cursor](https://cursor.com)

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Standardized unauthenticated `smart` and `smartest` tiers to
`z-ai/glm-5.2:nitro` for both slow and fast paths to ensure consistent
model selection. Updated docs to include `npx @hexclave/cli exec
<javascript>` (preloads `hexclaveServerApp`) and to note config
auto-sync when using `npx @hexclave/cli dev --config-file <path>`.

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

<a
href="https://cubic.dev/pr/hexclave/hexclave/pull/1693?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**
* Updated unauthenticated AI model selection to use a newer variant for
faster and more reliable responses in supported smart modes.

* **Documentation**
* Added clearer CLI guidance for running JavaScript with a
pre-configured app context.
* Expanded reminder text to better explain local config syncing during
development and dashboard runs.

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

Co-authored-by: Cursor <[email protected]>
2026-06-30 10:39:27 -07:00
Konsti WohlwendandGitHub 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 d31d29c112 Clean up AI tools 2026-06-30 10:08:08 -07:00