From 8fc11e1c932fae26142a09dcb02f13cb20cf8ba3 Mon Sep 17 00:00:00 2001 From: Bilal Godil Date: Mon, 1 Jun 2026 17:20:35 -0700 Subject: [PATCH] Rename Stack -> Hexclave in examples, app-internal symbols, and crypto docs - examples: rename the user config module stack.ts/.tsx (and the convex/lovable stack/ dirs) to hexclave and update all importers across .ts/.tsx/.jsx; the public handler/[...stack] route segment is left unchanged. - apps/{dashboard,backend,internal-tool}: rename app-local SDK-init symbols (stackClientApp -> hexclaveClientApp, getStackServerApp -> getHexclaveServerApp) and the dashboard StackCompanion component -> HexclaveCompanion. The public StackClientApp/StackServerApp SDK classes are intentionally left unchanged. - packages/stack-shared: add comments explaining why the crypto/JWT/vault "stack-*" literals must NOT be renamed (key derivation / JWKS / KMS-alias stability would break existing encrypted data and tokens). Deliberately excluded: the STACK_* -> HEXCLAVE_* env-var rename (already works via the dual-read layers; the docker post-build sentinel path is author-deferred), and all public-contract names (SDK classes, env vars, HTTP headers, handler routes). --- .../latest/analytics/events/batch/route.tsx | 4 ++-- .../latest/internal/analytics/query/route.ts | 4 ++-- .../latest/internal/send-test-email/route.tsx | 4 ++-- .../api/latest/session-replays/batch/route.tsx | 4 ++-- apps/backend/src/lib/email-queue-step.tsx | 4 ++-- apps/backend/src/lib/events.tsx | 4 ++-- apps/backend/src/stack.tsx | 2 +- .../(outside-dashboard)/projects/actions.ts | 2 +- .../projects/[projectId]/sidebar-layout.tsx | 4 ++-- .../integrations/featurebase/sso/page.tsx | 4 ++-- .../(main)/integrations/oauth-confirm-page.tsx | 4 ++-- apps/dashboard/src/app/layout-client.tsx | 4 ++-- .../src/components/stack-companion.tsx | 18 +++++++++--------- apps/dashboard/src/lib/version-check.ts | 2 +- apps/dashboard/src/stack/client.tsx | 2 +- apps/dashboard/src/stack/server.tsx | 6 +++--- apps/internal-tool/src/app/layout.tsx | 4 ++-- apps/internal-tool/src/stack.ts | 2 +- .../cjs-test/app/handler/[...stack]/page.jsx | 2 +- examples/cjs-test/app/layout.tsx | 2 +- examples/cjs-test/{stack.tsx => hexclave.tsx} | 0 .../convex/app/handler/[...stack]/page.tsx | 2 +- examples/convex/app/layout.tsx | 2 +- examples/convex/app/server/page.tsx | 2 +- examples/convex/app/user-info.ts | 2 +- .../convex/components/ConvexClientProvider.tsx | 2 +- examples/convex/convex/myActions.ts | 2 +- examples/convex/convex/myFunctions.ts | 4 ++-- examples/convex/{stack => hexclave}/client.tsx | 0 examples/convex/{stack => hexclave}/server.tsx | 0 examples/demo/src/app/apikey-demo/api/route.ts | 2 +- examples/demo/src/app/fallback-test/page.tsx | 2 +- .../demo/src/app/handler/[...stack]/page.tsx | 2 +- examples/demo/src/app/layout.tsx | 2 +- .../payments-demo/api/config-check/route.ts | 2 +- .../api/create-checkout-url/route.ts | 2 +- .../payments-demo/api/send-test-email/route.ts | 2 +- examples/demo/src/app/protected/page.tsx | 2 +- examples/demo/src/app/spotify-server/page.tsx | 2 +- examples/demo/src/{stack.tsx => hexclave.tsx} | 0 .../src/app/handler/[...stack]/page.tsx | 2 +- examples/docs-examples/src/app/layout.tsx | 2 +- .../src/{stack.tsx => hexclave.tsx} | 0 examples/e-commerce/src/app/edit-shop/page.tsx | 2 +- .../src/app/handler/[...stack]/page.tsx | 2 +- examples/e-commerce/src/app/layout.tsx | 2 +- examples/e-commerce/src/app/page.tsx | 2 +- .../e-commerce/src/{stack.tsx => hexclave.tsx} | 0 examples/js-example/{stack.ts => hexclave.ts} | 0 examples/js-example/index-script.ts | 2 +- examples/js-example/oauth-script.ts | 2 +- examples/js-example/otp-sign-in-script.ts | 2 +- examples/js-example/password-sign-in-script.ts | 2 +- examples/js-example/password-sign-up-script.ts | 2 +- examples/lovable-react-18-example/src/App.tsx | 2 +- .../src/{stack => hexclave}/client.ts | 0 .../src/app/handler/[...stack]/page.tsx | 2 +- examples/middleware/src/app/layout.tsx | 2 +- examples/middleware/src/app/page.tsx | 2 +- examples/middleware/src/app/protected/page.tsx | 2 +- .../middleware/src/{stack.tsx => hexclave.tsx} | 0 examples/middleware/src/middleware.tsx | 2 +- examples/react-example/src/App.tsx | 2 +- .../src/{stack.ts => hexclave.ts} | 0 .../supabase/app/handler/[...stack]/page.tsx | 2 +- examples/supabase/app/layout.tsx | 2 +- examples/supabase/{stack.tsx => hexclave.tsx} | 0 examples/supabase/utils/actions.ts | 2 +- .../src/{stack.ts => hexclave.ts} | 0 .../tanstack-start-demo/src/routes/__root.tsx | 2 +- .../src/helpers/vault/client-side.ts | 3 +++ .../src/helpers/vault/server-side.ts | 5 +++++ packages/stack-shared/src/utils/crypto.tsx | 6 ++++++ packages/stack-shared/src/utils/jwt.tsx | 3 +++ 74 files changed, 97 insertions(+), 80 deletions(-) rename examples/cjs-test/{stack.tsx => hexclave.tsx} (100%) rename examples/convex/{stack => hexclave}/client.tsx (100%) rename examples/convex/{stack => hexclave}/server.tsx (100%) rename examples/demo/src/{stack.tsx => hexclave.tsx} (100%) rename examples/docs-examples/src/{stack.tsx => hexclave.tsx} (100%) rename examples/e-commerce/src/{stack.tsx => hexclave.tsx} (100%) rename examples/js-example/{stack.ts => hexclave.ts} (100%) rename examples/lovable-react-18-example/src/{stack => hexclave}/client.ts (100%) rename examples/middleware/src/{stack.tsx => hexclave.tsx} (100%) rename examples/react-example/src/{stack.ts => hexclave.ts} (100%) rename examples/supabase/{stack.tsx => hexclave.tsx} (100%) rename examples/tanstack-start-demo/src/{stack.ts => hexclave.ts} (100%) diff --git a/apps/backend/src/app/api/latest/analytics/events/batch/route.tsx b/apps/backend/src/app/api/latest/analytics/events/batch/route.tsx index c94df8204..79e6c9013 100644 --- a/apps/backend/src/app/api/latest/analytics/events/batch/route.tsx +++ b/apps/backend/src/app/api/latest/analytics/events/batch/route.tsx @@ -1,7 +1,7 @@ import { getClickhouseAdminClient } from "@/lib/clickhouse"; import { arePlanLimitsEnforced, getBillingTeamId } from "@/lib/plan-entitlements"; import { findRecentSessionReplay } from "@/lib/session-replays"; -import { getStackServerApp } from "@/stack"; +import { getHexclaveServerApp } from "@/stack"; import { getPrismaClientForTenancy } from "@/prisma-client"; import { createSmartRouteHandler } from "@/route-handlers/smart-route-handler"; import { KnownErrors } from "@hexclave/shared"; @@ -118,7 +118,7 @@ export const POST = createSmartRouteHandler({ const refreshTokenId = auth.refreshTokenId; const tenancyId = auth.tenancy.id; - const app = getStackServerApp(); + const app = getHexclaveServerApp(); const billingTeamId = getBillingTeamId(auth.tenancy.project); if (billingTeamId != null && arePlanLimitsEnforced()) { diff --git a/apps/backend/src/app/api/latest/internal/analytics/query/route.ts b/apps/backend/src/app/api/latest/internal/analytics/query/route.ts index 941fb4d12..0908d9112 100644 --- a/apps/backend/src/app/api/latest/internal/analytics/query/route.ts +++ b/apps/backend/src/app/api/latest/internal/analytics/query/route.ts @@ -2,7 +2,7 @@ import { getClickhouseExternalClient } from "@/lib/clickhouse"; import { getSafeClickhouseErrorMessage } from "@/lib/clickhouse-errors"; import { arePlanLimitsEnforced, getBillingTeamId } from "@/lib/plan-entitlements"; import { createSmartRouteHandler } from "@/route-handlers/smart-route-handler"; -import { getStackServerApp } from "@/stack"; +import { getHexclaveServerApp } from "@/stack"; import { KnownErrors } from "@hexclave/shared"; import { ITEM_IDS, PLAN_LIMITS } from "@hexclave/shared/dist/plans"; import { adaptSchema, adminAuthTypeSchema, jsonSchema, yupBoolean, yupMixed, yupNumber, yupObject, yupRecord, yupString } from "@hexclave/shared/dist/schema-fields"; @@ -43,7 +43,7 @@ export const POST = createSmartRouteHandler({ let effectiveTimeoutMs = body.timeout_ms; const billingTeamId = getBillingTeamId(auth.tenancy.project); if (billingTeamId != null && arePlanLimitsEnforced()) { - const app = getStackServerApp(); + const app = getHexclaveServerApp(); const timeoutItem = await app.getItem({ itemId: ITEM_IDS.analyticsTimeoutSeconds, teamId: billingTeamId }); // clickHouse treats max_execution_time=0 as // "unlimited", so a customer with zero timeout entitlement (no active diff --git a/apps/backend/src/app/api/latest/internal/send-test-email/route.tsx b/apps/backend/src/app/api/latest/internal/send-test-email/route.tsx index 08d4bbccd..b036065a3 100644 --- a/apps/backend/src/app/api/latest/internal/send-test-email/route.tsx +++ b/apps/backend/src/app/api/latest/internal/send-test-email/route.tsx @@ -1,7 +1,7 @@ import { isSecureEmailPort, lowLevelSendEmailDirectWithoutRetries } from "@/lib/emails-low-level"; import { arePlanLimitsEnforced, getBillingTeamId } from "@/lib/plan-entitlements"; import { createSmartRouteHandler } from "@/route-handlers/smart-route-handler"; -import { getStackServerApp } from "@/stack"; +import { getHexclaveServerApp } from "@/stack"; import { KnownErrors } from "@hexclave/shared"; import { ITEM_IDS } from "@hexclave/shared/dist/plans"; import * as schemaFields from "@hexclave/shared/dist/schema-fields"; @@ -51,7 +51,7 @@ export const POST = createSmartRouteHandler({ const billingTeamId = getBillingTeamId(auth.tenancy.project); const emailItem = billingTeamId == null || !arePlanLimitsEnforced() ? null - : await getStackServerApp().getItem({ itemId: ITEM_IDS.emailsPerMonth, teamId: billingTeamId }); + : await getHexclaveServerApp().getItem({ itemId: ITEM_IDS.emailsPerMonth, teamId: billingTeamId }); if (emailItem != null && billingTeamId != null) { const isDebited = await emailItem.tryDecreaseQuantity(1); if (!isDebited) { diff --git a/apps/backend/src/app/api/latest/session-replays/batch/route.tsx b/apps/backend/src/app/api/latest/session-replays/batch/route.tsx index 9f6c39268..0ec2f9b2d 100644 --- a/apps/backend/src/app/api/latest/session-replays/batch/route.tsx +++ b/apps/backend/src/app/api/latest/session-replays/batch/route.tsx @@ -4,7 +4,7 @@ import { createSmartRouteHandler } from "@/route-handlers/smart-route-handler"; import { Prisma } from "@/generated/prisma/client"; import { arePlanLimitsEnforced, getBillingTeamId } from "@/lib/plan-entitlements"; import { findRecentSessionReplay } from "@/lib/session-replays"; -import { getStackServerApp } from "@/stack"; +import { getHexclaveServerApp } from "@/stack"; import { KnownErrors } from "@hexclave/shared"; import { ITEM_IDS } from "@hexclave/shared/dist/plans"; import { adaptSchema, clientOrHigherAuthTypeSchema, yupArray, yupMixed, yupNumber, yupObject, yupString } from "@hexclave/shared/dist/schema-fields"; @@ -109,7 +109,7 @@ export const POST = createSmartRouteHandler({ const prisma = await getPrismaClientForTenancy(auth.tenancy); const recentSession = await findRecentSessionReplay(prisma, { tenancyId, refreshTokenId }); - const app = getStackServerApp(); + const app = getHexclaveServerApp(); const isNewSession = recentSession == null; const billingTeamId = getBillingTeamId(auth.tenancy.project); diff --git a/apps/backend/src/lib/email-queue-step.tsx b/apps/backend/src/lib/email-queue-step.tsx index 38f8026fb..81e7f4639 100644 --- a/apps/backend/src/lib/email-queue-step.tsx +++ b/apps/backend/src/lib/email-queue-step.tsx @@ -4,7 +4,7 @@ import { getEmailThemeForThemeId, renderEmailsForTenancyBatched } from "@/lib/em import { EmailOutboxRecipient, getEmailConfig, } from "@/lib/emails"; import { generateUnsubscribeLink, getNotificationCategoryById, hasNotificationEnabled, listNotificationCategories } from "@/lib/notification-categories"; import { arePlanLimitsEnforced, getBillingTeamId } from "@/lib/plan-entitlements"; -import { getStackServerApp } from "@/stack"; +import { getHexclaveServerApp } from "@/stack"; import { ITEM_IDS } from "@hexclave/shared/dist/plans"; import { getTenancy, Tenancy } from "@/lib/tenancies"; import { getPrismaClientForTenancy, globalPrismaClient, PrismaClientTransaction } from "@/prisma-client"; @@ -695,7 +695,7 @@ async function processSingleEmail(context: TenancyProcessingContext, row: EmailO } if (context.billingTeamId != null && row.sendRetries === 0 && arePlanLimitsEnforced()) { - const app = getStackServerApp(); + const app = getHexclaveServerApp(); const emailItem = await app.getItem({ itemId: ITEM_IDS.emailsPerMonth, teamId: context.billingTeamId }); const isDebited = await emailItem.tryDecreaseQuantity(1); if (!isDebited) { diff --git a/apps/backend/src/lib/events.tsx b/apps/backend/src/lib/events.tsx index 22e2d1cd1..45e67d58a 100644 --- a/apps/backend/src/lib/events.tsx +++ b/apps/backend/src/lib/events.tsx @@ -1,7 +1,7 @@ import withPostHog from "@/analytics"; import { arePlanLimitsEnforced } from "@/lib/plan-entitlements"; import { globalPrismaClient } from "@/prisma-client"; -import { getStackServerApp } from "@/stack"; +import { getHexclaveServerApp } from "@/stack"; import { runAsynchronouslyAndWaitUntil } from "@/utils/background-tasks"; import { ITEM_IDS } from "@hexclave/shared/dist/plans"; import { urlSchema, yupBoolean, yupMixed, yupNumber, yupObject, yupString } from "@hexclave/shared/dist/schema-fields"; @@ -278,7 +278,7 @@ export async function logEvent( const billingTeamId = options.billingTeamId; if (billingTeamId != null && arePlanLimitsEnforced()) { - const app = getStackServerApp(); + const app = getHexclaveServerApp(); const eventsItem = await app.getItem({ itemId: ITEM_IDS.analyticsEvents, teamId: billingTeamId }); const isDebited = await eventsItem.tryDecreaseQuantity(1); if (!isDebited) { diff --git a/apps/backend/src/stack.tsx b/apps/backend/src/stack.tsx index 5364906b2..e66869f3d 100644 --- a/apps/backend/src/stack.tsx +++ b/apps/backend/src/stack.tsx @@ -1,7 +1,7 @@ import { StackServerApp } from '@hexclave/next'; import { getEnvVariable } from '@hexclave/shared/dist/utils/env'; -export function getStackServerApp() { +export function getHexclaveServerApp() { // Fail fast if the backend self-URL env var is missing — without it the SDK // would silently inherit `defaultBaseUrl` (https://api.stack-auth.com), which // is almost never what we want for backend self-calls. diff --git a/apps/dashboard/src/app/(main)/(protected)/(outside-dashboard)/projects/actions.ts b/apps/dashboard/src/app/(main)/(protected)/(outside-dashboard)/projects/actions.ts index 02df30736..a9b01ce8b 100644 --- a/apps/dashboard/src/app/(main)/(protected)/(outside-dashboard)/projects/actions.ts +++ b/apps/dashboard/src/app/(main)/(protected)/(outside-dashboard)/projects/actions.ts @@ -5,7 +5,7 @@ async function getServerApp() { if (isRemoteDevelopmentEnvironmentEnabled()) { throw new Error("Team invitation management is not available in the remote development environment dashboard."); } - return (await import("@/stack/server")).getStackServerApp(); + return (await import("@/stack/server")).getHexclaveServerApp(); } export async function revokeInvitation(teamId: string, invitationId: string) { diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/sidebar-layout.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/sidebar-layout.tsx index 0ee5681cf..1dab02572 100644 --- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/sidebar-layout.tsx +++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/sidebar-layout.tsx @@ -4,7 +4,7 @@ import { CmdKSearch, CmdKTrigger } from "@/components/cmdk-search"; import { Link } from "@/components/link"; import { Logo } from "@/components/logo"; import { ProjectSwitcher } from "@/components/project-switcher"; -import { StackCompanion } from "@/components/stack-companion"; +import { HexclaveCompanion } from "@/components/stack-companion"; import ThemeToggle from "@/components/theme-toggle"; import { Button, @@ -769,7 +769,7 @@ export default function SidebarLayout(props: { children?: React.ReactNode }) { {/* Stack Companion - overlay with reserved content gutter */}
- +
diff --git a/apps/dashboard/src/app/(main)/integrations/featurebase/sso/page.tsx b/apps/dashboard/src/app/(main)/integrations/featurebase/sso/page.tsx index 8d1944694..6dce866e3 100644 --- a/apps/dashboard/src/app/(main)/integrations/featurebase/sso/page.tsx +++ b/apps/dashboard/src/app/(main)/integrations/featurebase/sso/page.tsx @@ -1,4 +1,4 @@ -import { getStackServerApp } from "@/stack/server"; +import { getHexclaveServerApp } from "@/stack/server"; import { getEnvVariable } from "@hexclave/shared/dist/utils/env"; import { getOrCreateFeaturebaseUser } from "@hexclave/shared/dist/utils/featurebase"; import { urlString } from "@hexclave/shared/dist/utils/urls"; @@ -21,7 +21,7 @@ export default async function FeaturebaseSSO({ return
Missing return_to parameter. Please go back and try again.
; } - const user = await getStackServerApp().getUser(); + const user = await getHexclaveServerApp().getUser(); if (!user) { redirect(urlString`/handler/sign-in?after_auth_return_to=${urlString`/integrations/featurebase/sso?return_to=${returnTo}`}`); } diff --git a/apps/dashboard/src/app/(main)/integrations/oauth-confirm-page.tsx b/apps/dashboard/src/app/(main)/integrations/oauth-confirm-page.tsx index b8915b1ed..508aa07f2 100644 --- a/apps/dashboard/src/app/(main)/integrations/oauth-confirm-page.tsx +++ b/apps/dashboard/src/app/(main)/integrations/oauth-confirm-page.tsx @@ -1,4 +1,4 @@ -import { getStackServerApp } from "@/stack/server"; +import { getHexclaveServerApp } from "@/stack/server"; import { getEnvVariable } from "@hexclave/shared/dist/utils/env"; import { HexclaveAssertionError } from "@hexclave/shared/dist/utils/errors"; import { redirect } from "next/navigation"; @@ -18,7 +18,7 @@ export default async function IntegrationConfirmPage(props: { const onContinue = async (options: { projectId: string, projectName?: string }) => { "use server"; - const user = await getStackServerApp().getUser(); + const user = await getHexclaveServerApp().getUser(); if (!user) { return { error: "unauthorized" }; } diff --git a/apps/dashboard/src/app/layout-client.tsx b/apps/dashboard/src/app/layout-client.tsx index 25587338d..9d4ba38ea 100644 --- a/apps/dashboard/src/app/layout-client.tsx +++ b/apps/dashboard/src/app/layout-client.tsx @@ -6,7 +6,7 @@ import { SiteLoadingIndicatorDisplay } from "@/components/site-loading-indicator import { Toaster } from "@/components/ui"; import { VersionAlerter } from "@/components/version-alerter"; import { getPublicEnvVar } from "@/lib/env"; -import { stackClientApp } from "@/stack/client"; +import { hexclaveClientApp } from "@/stack/client"; import { StackProvider, StackTheme } from "@hexclave/next"; import { runAsynchronouslyWithAlert } from "@hexclave/shared/dist/utils/promises"; import React, { useSyncExternalStore } from "react"; @@ -166,7 +166,7 @@ export function LayoutClient(props: { }) { return ( <> - ["lang"]}> + ["lang"]}> diff --git a/apps/dashboard/src/components/stack-companion.tsx b/apps/dashboard/src/components/stack-companion.tsx index de601c1ad..dca0a8f23 100644 --- a/apps/dashboard/src/components/stack-companion.tsx +++ b/apps/dashboard/src/components/stack-companion.tsx @@ -105,22 +105,22 @@ const CLOSE_THRESHOLD = 100; const SPLIT_SCREEN_BREAKPOINT = 1000; // Context for sharing companion state with layout -type StackCompanionContextType = { +type HexclaveCompanionContextType = { drawerWidth: number, isSplitScreenMode: boolean, }; -const StackCompanionContext = createContext({ +const HexclaveCompanionContext = createContext({ drawerWidth: 0, isSplitScreenMode: false, }); -export function useStackCompanion() { - return useContext(StackCompanionContext); +export function useHexclaveCompanion() { + return useContext(HexclaveCompanionContext); } -export function StackCompanion({ className, glassBg = false }: { className?: string, glassBg?: boolean }) { +export function HexclaveCompanion({ className, glassBg = false }: { className?: string, glassBg?: boolean }) { const [activeItem, setActiveItem] = useState(null); const [mounted, setMounted] = useState(false); const [versionCheckResult, setVersionCheckResult] = useState(null); @@ -524,7 +524,7 @@ export function StackCompanion({ className, glassBg = false }: { className?: str if (isSplitScreenMode) { return ( - +