mirror of
https://github.com/stack-auth/stack.git
synced 2026-06-21 21:09:49 +08:00
## Stack Auth → Hexclave rename — PR 5 (internal symbols, paths,
packages, brand strings)
PR 5 finishes the **internal / non-wire** half of the Stack→Hexclave
rename. It only touches things where nothing outside the repo depends on
the exact name: internal symbols, file/dir names, the
`@stackframe/template` package, and residual brand strings. Plan +
progress are in `HEXCLAVE-RENAME-PR5-PLAN.md`.
Every step was verified green (`pnpm typecheck` + `pnpm lint`, 28/28)
and committed as its own checkpoint, then a fan-out of review agents
audited all commits and the findings were fixed.
### What changed
- **Internal symbols** (`@hexclave/shared`, `packages/template`, apps):
`stack*`/`Stack*` → `hexclave*`/`Hexclave*` — incl.
`stackGlobalsSymbol`, the `_Stack*AppImpl` classes,
`stackAppInternalsSymbol`, `StackContext`, `getStackStripe`, etc. The
`stack*App` local-variable convention
(`stackServerApp`/`stackClientApp`/…) was renamed across 175
source/example/doc files.
- **File renames**: `hexclave-handler/provider/context.tsx`,
`backend/hexclave.tsx`, `internal-tool/hexclave.ts`,
`hexclave-app-internals.ts`.
- **Directory renames**: `lib/hexclave-app`, `hexclave-companion`,
`[...hexclave]` route segment, `skills/hexclave`,
`dashboard/src/hexclave`, and the package dirs
**`packages/{next,shared,ui,sc,cli}`** (dropping the `stack-` prefix to
match the `@hexclave/*` npm names).
- **Packages**: `@stackframe/template` → `@hexclave/template`; **deleted
`packages/init-stack`** (onboarding lives in `@hexclave/cli init`; the
published npm package is untouched).
- **Brand strings**: reworded `Stack Auth`/`Stack dashboard` prose in
code + docs-mintlify, renamed `hexclave-app.mdx`/`use-hexclave-app.mdx`
with redirects, regenerated OpenAPI, updated coupled e2e assertions;
`doctor`/`init` now prefer `hexclave.config.ts`.
### Intentionally kept (verified, not oversights)
Wire/compat identifiers (`x-stack-*` headers, `stack-*` cookies,
`STACK_*` env names, `*.stack-auth.com`, `stackauth_`, `ask_stack_auth`,
query params), public `Stack*` SDK aliases, crypto/JWT/vault
domain-separation tags, `*-brand-sentinel`s, the
`Symbol.for("StackAuth--…")` string, `_stack_sync_metadata`, Postgres
`stackframe` / docker image names, the `stack-auth-logo*.svg` (used by
the rebrand modal), and `migration.mdx` / "formerly known as Stack Auth"
notes. False positives (Phosphor `StackIcon`/`StackSimple`, `TanStack`,
`OrbStack`, `stackable`/`Stacked` charts) left alone.
### Review pass
Six review agents audited all commits. Found + fixed one real bug — a
build script (`bundle-type-definitions.ts`) hardcoded the old
`lib/stack-app` glob path (not an import, so typecheck/lint were blind),
silently emptying the dashboard AI type bundle — plus stale comments, a
dead CI env var, and stale `.gitignore`/`.dockerignore` entries.
Cross-cutting audit confirmed **zero wire-compat identifiers were
accidentally renamed**.
### ⚠️ Verification note
`typecheck` + `lint` are fully green locally. The **e2e suite was not
run** (needs a live backend+DB), so the brand-string assertion +
OpenAPI-regen changes are verified by grep/codegen only — please let CI
exercise e2e to confirm.
### Base-branch note
This branch was forked from the local-only `cl/friendly-lewin-72293f`
(not on origin, no separate PR), so this PR against `dev` also carries
that branch's ~11 preceding Hexclave-rename commits (config-file rename,
env-var dual-read, AI setup-prompt rebrand). If those should land
separately, re-parent before merge.
<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Finishes the internal Stack Auth → Hexclave rename and cleans up
remaining stragglers, including dev-tool and prompt copy. All changes
are internal-only; public/wire APIs remain unchanged. Re-merged `dev`
and resolved the payments create-purchase-url conflict.
- **Refactors**
- Internal symbols: stack*/Stack* → hexclave*/Hexclave* (e.g.,
`getHexclaveServerApp` via `@/hexclave`, `getHexclaveStripe`,
`hexclaveAppInternalsSymbol`, `hexclaveSchemaInfo`, Prisma
`__hexclave_*`, `data-hexclave-handler-page`, Stripe mock
`hexclavePortPrefix`).
- Files/dirs: moved to `lib/hexclave-app`; handler route
`[...hexclave]`; backend entry `src/hexclave.tsx`; dashboard internals
`hexclave-app-internals`; companion `hexclave-companion`; dropped
`stack-` prefix across package dirs
(`packages/{shared,ui,sc,cli,next}`); workflows/emulator paths now
`packages/cli`; Quetzal codegen env at `packages/next/.env.local`.
- Packages/docs: `@stackframe/template` → `@hexclave/template`; removed
`packages/init-stack`; regenerated OpenAPI and updated docs
slugs/redirects for hexclave-app/use-hexclave-app.
- Brand strings/prompts: reworded remaining “Stack” dashboard strings to
Hexclave; updated dev-tool copy and prompts; `doctor/init` now prefer
`hexclave.config.ts`. Kept all wire-compat identifiers and public
aliases (`x-stack-*`, `stack-*` cookies, `STACK_*` env,
`*.stack-auth.com`, `Stack*` SDK names).
- Rebased/merged onto latest `dev`: retained `@hexclave/template`, kept
`src` in published files, refreshed setup-prompt imports and docs JSON,
adopted 1.0.5 version bumps, and re-merged `dev` again (resolved
`create-purchase-url` with `getHexclaveStripe`).
- **Bug Fixes**
- Restored dashboard AI type bundle by pointing the glob to
`packages/template/src/lib/hexclave-app`.
- Addressed rename leftovers: updated lingering `@/stack` imports and
CSS selector, fixed schema/meta and port-prefix expansions, and aligned
emulator commands to `packages/cli`.
- CI/build: removed a dead env var and stale ignore entries; fixed
Docker by renaming `STACK_SKIP_TEMPLATE_GENERATION` →
`HEXCLAVE_SKIP_TEMPLATE_GENERATION`.
<sup>Written for commit 3c1af3bff3.
Summary will update on new commits.</sup>
<a
href="https://cubic.dev/pr/hexclave/hexclave/pull/1547?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->
115 lines
4.4 KiB
Plaintext
115 lines
4.4 KiB
Plaintext
---
|
|
title: "Restricted Users"
|
|
description: "Understand and handle users with limited access"
|
|
sidebarTitle: "Restricted Users"
|
|
---
|
|
|
|
Restricted users are signed-in users whose account exists, but has not been granted normal application access yet. Stack marks these users with `user.isRestricted === true` and provides a `user.restrictedReason` explaining why.
|
|
|
|
By default, Hexclave treats restricted users like unauthenticated users in most SDK calls. This prevents accounts that still need verification, review, or conversion from accidentally getting access to protected product flows.
|
|
|
|
## When users are restricted
|
|
|
|
Users can be restricted for a few reasons:
|
|
|
|
- **Email not verified**: the project requires email verification before full access.
|
|
- **Anonymous user**: anonymous users can interact with the app, but are always restricted until converted.
|
|
- **Restricted by administrator**: the user was restricted manually or by a [sign-up rule](/guides/apps/authentication/sign-up-rules).
|
|
|
|
You can inspect the reason from the SDK:
|
|
|
|
```ts my-app.ts
|
|
import { hexclaveServerApp } from "../src/stack/server";
|
|
|
|
const user = await hexclaveServerApp.getUser({ includeRestricted: true });
|
|
|
|
if (user?.isRestricted) {
|
|
console.log(user.restrictedReason?.type);
|
|
}
|
|
```
|
|
|
|
The current `restrictedReason.type` values are:
|
|
|
|
| Type | Meaning |
|
|
| --- | --- |
|
|
| `email_not_verified` | The user still needs to verify their email address. |
|
|
| `anonymous` | The user is an anonymous user. |
|
|
| `restricted_by_administrator` | The user was restricted manually or by a sign-up rule. |
|
|
|
|
## Loading restricted users
|
|
|
|
Most calls exclude restricted users unless you explicitly opt in. Use `includeRestricted: true` when you are building onboarding, email verification, account review, or anonymous-user conversion flows.
|
|
|
|
<CodeGroup dropdown>
|
|
```ts my-app.ts
|
|
import { hexclaveServerApp } from "../src/stack/server";
|
|
|
|
const user = await hexclaveServerApp.getUser({ includeRestricted: true });
|
|
|
|
if (user?.isRestricted) {
|
|
console.log("Needs onboarding:", user.restrictedReason?.type);
|
|
}
|
|
```
|
|
|
|
```tsx my-react-component.tsx
|
|
"use client";
|
|
import { hexclaveClientApp } from "../src/stack/client";
|
|
|
|
export default function OnboardingGate() {
|
|
const user = hexclaveClientApp.useUser({ includeRestricted: true });
|
|
|
|
if (!user) {
|
|
return <a href="/handler/sign-in">Sign in</a>;
|
|
}
|
|
|
|
if (user.isRestricted) {
|
|
return <RestrictedUserMessage reason={user.restrictedReason?.type} />;
|
|
}
|
|
|
|
return <div>Welcome back, {user.displayName ?? user.primaryEmail}</div>;
|
|
}
|
|
```
|
|
</CodeGroup>
|
|
|
|
<Info>
|
|
Anonymous users are restricted by definition. Passing `{ or: "anonymous" }` automatically includes restricted users, and cannot be combined with `{ includeRestricted: false }`.
|
|
</Info>
|
|
|
|
## Handling restricted users
|
|
|
|
Treat restricted users as a separate state from both "signed out" and "fully signed in". A good default is to show a page that tells the user what they need to do next.
|
|
|
|
```tsx restricted-user-message.tsx
|
|
function RestrictedUserMessage({ reason }: { reason: string | undefined }) {
|
|
if (reason === "email_not_verified") {
|
|
return <div>Please verify your email address to continue.</div>;
|
|
}
|
|
|
|
if (reason === "anonymous") {
|
|
return <a href="/handler/sign-up">Create an account to save your progress.</a>;
|
|
}
|
|
|
|
return <div>Your account is waiting for review.</div>;
|
|
}
|
|
```
|
|
|
|
For API routes or backend actions, keep using the default behavior unless the endpoint is specifically meant to serve restricted users. This helps prevent partially onboarded accounts from reaching product APIs.
|
|
|
|
## Restricted users in JWTs
|
|
|
|
Restricted users receive tokens with `is_restricted` and `restricted_reason` claims. If your backend verifies Hexclave JWTs directly, make sure you reject restricted users unless the endpoint intentionally supports them.
|
|
|
|
When fetching Hexclave's JWKS, restricted-user signing keys are excluded by default. Include them only for services that intentionally accept restricted users:
|
|
|
|
```txt jwks-url.txt
|
|
/.well-known/jwks.json?include_restricted=true
|
|
```
|
|
|
|
If you also accept anonymous users, use `include_anonymous=true`; anonymous keys imply restricted-user keys.
|
|
|
|
## Admin and sign-up review
|
|
|
|
Sign-up rules can restrict a user instead of rejecting the sign-up outright. This is useful when you want the account to exist, but need manual review before granting access.
|
|
|
|
For more details on creating rules that restrict users, see [Sign-up Rules](/guides/apps/authentication/sign-up-rules).
|