mirror of
https://github.com/stack-auth/stack.git
synced 2026-06-04 21:04:37 +08:00
Rename port prefix envvar
This commit is contained in:
parent
5a8e0e5112
commit
fa4f25bcdd
@ -12,7 +12,7 @@ A: `packages/stack-cli/src/lib/init-prompt.ts` re-exports `createInitPrompt` fro
|
||||
A: Connected accounts live in `ProjectUserOAuthAccount`. Stored refresh tokens are in `OAuthToken` (`oauthAccountId`, `scopes`, `isValid`), and cached access tokens are in `OAuthAccessToken` (`expiresAt`, `scopes`, `isValid`). A null `OAuthAccessToken.expiresAt` means the OAuth provider did not supply an access-token expiry; `retrieveOrRefreshAccessToken` treats null-expiry tokens as candidates and still calls the provider-specific validity check before returning them. If no usable access token exists, it looks for valid refresh tokens with matching scopes and invalidates only those that the provider explicitly rejects.
|
||||
|
||||
## Q: Which Hexclave rename compatibility layers should be avoided in PR #1475 follow-ups?
|
||||
A: Do not keep backwards compatibility for the MCP tool name, cross-domain auth query parameter names, `NEXT_PUBLIC_STACK_PORT_PREFIX`, or a parallel `hexclaveAppInternalsSymbol`. For refresh/access cookies, read both legacy Stack and new Hexclave cookie names, but only write the canonical Hexclave cookies.
|
||||
A: Do not keep backwards compatibility for the MCP tool name, cross-domain auth query parameter names, `NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX`, or a parallel `hexclaveAppInternalsSymbol`. For refresh/access cookies, read both legacy Stack and new Hexclave cookie names, but only write the canonical Hexclave cookies.
|
||||
|
||||
## Q: How should GitHub Contents API request-body assertions be written in Stack Auth tests?
|
||||
A: Prefer inline snapshots over individual field selectors. For request bodies that contain base64 file content, parse the JSON body, assert it is an object, decode the `content` field back to UTF-8, and snapshot the normalized call object so the test verifies the path, method, headers, branch, message, sha, and rendered file content together.
|
||||
@ -393,7 +393,7 @@ A: Use `getAuthorizationHeader()`, which returns `Bearer stackauth_<base64(getAu
|
||||
A: `RequestLike` accepts both `{ headers: { get(name): string | null } }` and `{ headers: Record<string, string | null> }`. Header lookup is case-insensitive for record-style headers, and supports `authorization`, `x-stack-auth`, and `cookie`.
|
||||
|
||||
### Q: Which env var should emulator onboarding URLs use for dashboard port?
|
||||
A: Use `EMULATOR_DASHBOARD_PORT` (default `26700`) or explicit `STACK_LOCAL_EMULATOR_DASHBOARD_URL`. Do not derive emulator URLs from `NEXT_PUBLIC_STACK_PORT_PREFIX`, because that points to the host dev environment ports (e.g. `92xx`) rather than the emulator host-forwarded ports.
|
||||
A: Use `EMULATOR_DASHBOARD_PORT` (default `26700`) or explicit `STACK_LOCAL_EMULATOR_DASHBOARD_URL`. Do not derive emulator URLs from `NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX`, because that points to the host dev environment ports (e.g. `92xx`) rather than the emulator host-forwarded ports.
|
||||
|
||||
### Q: Why does `PATCH /api/v1/internal/projects/current` fail in local emulator when updating only `onboarding_state`?
|
||||
A: `createOrUpdateProjectWithLegacyConfig` always called `overrideEnvironmentConfigOverride`, even when there were zero config override keys to apply. In local emulator mode, environment config overrides are intentionally blocked, so this threw `Environment configuration overrides cannot be changed in the local emulator` and returned 500. The fix is to skip `overrideEnvironmentConfigOverride` unless `configOverrideOverride` has at least one key.
|
||||
|
||||
@ -34,11 +34,11 @@ You should ALWAYS add new E2E tests when you change the API or SDK interface. Ge
|
||||
Hexclave is a monorepo using Turbo for build orchestration. The main components are:
|
||||
|
||||
### Apps (`/apps`)
|
||||
- **backend** (`/apps/backend`): Next.js API backend running on port `${NEXT_PUBLIC_STACK_PORT_PREFIX:-81}02` (defaults to 8102)
|
||||
- **backend** (`/apps/backend`): Next.js API backend running on port `${NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX:-81}02` (defaults to 8102)
|
||||
- Main API routes in `/apps/backend/src/app/api/latest`
|
||||
- Database models using Prisma
|
||||
- **dashboard** (`/apps/dashboard`): Admin dashboard on port `${NEXT_PUBLIC_STACK_PORT_PREFIX:-81}01` (defaults to 8101)
|
||||
- **dev-launchpad**: Development portal on port `${NEXT_PUBLIC_STACK_PORT_PREFIX:-81}00` (defaults to 8100)
|
||||
- **dashboard** (`/apps/dashboard`): Admin dashboard on port `${NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX:-81}01` (defaults to 8101)
|
||||
- **dev-launchpad**: Development portal on port `${NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX:-81}00` (defaults to 8100)
|
||||
- **e2e**: End-to-end tests
|
||||
|
||||
### Packages (`/packages`)
|
||||
@ -76,7 +76,7 @@ To see all development ports, refer to the index.html of `apps/dev-launchpad/pub
|
||||
- When writing tests, prefer .toMatchInlineSnapshot over other selectors, if possible. You can check (and modify) the snapshot-serializer.ts file to see how the snapshots are formatted and how non-deterministic values are handled.
|
||||
- Whenever you learn something new, or at the latest right before you call the `Stop` tool, write whatever you learned into the .claude/CLAUDE-KNOWLEDGE.md file, in the Q&A format in there. You will later be able to look up knowledge from there (based on the question you asked).
|
||||
- Animations: Keep hover/click transitions snappy and fast. Don't delay the action with a pre-transition (e.g. no fade-in when hovering a button) — it makes the UI feel sluggish. Instead, apply transitions after the action, like a smooth fade-out when the hover ends.
|
||||
- Whenever you make changes in the dashboard, provide the user with a deep link to the dashboard page that you've just changed. Usually, this takes the form of `http://localhost:<whatever-is-in-$NEXT_PUBLIC_STACK_PORT_PREFIX>01/projects/-selector-/...`, although sometimes it's different. If $NEXT_PUBLIC_STACK_PORT_PREFIX is set to 91, 92, or 93, use `a.localhost`, `b.localhost`, and `c.localhost` for the domains, respectively.
|
||||
- Whenever you make changes in the dashboard, provide the user with a deep link to the dashboard page that you've just changed. Usually, this takes the form of `http://localhost:<whatever-is-in-$NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX>01/projects/-selector-/...`, although sometimes it's different. If $NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX is set to 91, 92, or 93, use `a.localhost`, `b.localhost`, and `c.localhost` for the domains, respectively.
|
||||
- To update the list of apps available, edit `apps-frontend.tsx` and `apps-config.ts`. When you're tasked to implement a new app or a new page, always check existing apps for inspiration on how you could implement the new app or page.
|
||||
- NEVER use Next.js dynamic functions if you can avoid them. Instead, prefer using a client component to make sure the page remains static (eg. prefer `usePathname` instead of `await params`).
|
||||
- Whenever you make backwards-incompatible changes to the config schema, you must update the migration functions in `packages/stack-shared/src/config/schema.ts`!
|
||||
|
||||
@ -36,7 +36,7 @@ For any security-related concerns & bug bounties, please email us at [security@h
|
||||
|
||||
NOTE: Every line of code should be reviewed by a human BEFORE you submit a PR. DO NOT waste our time by creating and submitting an AI-generated PR.
|
||||
|
||||
For vibecoding, it can help to have multiple parallel copies of the codebase open in different windows. For this, you can set the environment variable `NEXT_PUBLIC_STACK_PORT_PREFIX` to a different value (default 81). To do this consistently across all coding agents (Claude Code/Cursor Agent/Codex),we recommend you use `direnv` with a `.envrc` file:
|
||||
For vibecoding, it can help to have multiple parallel copies of the codebase open in different windows. For this, you can set the environment variable `NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX` to a different value (default 81). To do this consistently across all coding agents (Claude Code/Cursor Agent/Codex),we recommend you use `direnv` with a `.envrc` file:
|
||||
|
||||
1. Install `direnv` if you haven't already. On Mac, the easiest way is to install it with Homebrew: `brew install direnv`.
|
||||
2. Update ALL your shell configs to append the following lines. On most Mac setups, this is `~/.bash_profile`, `~/.bashrc`, `~/.zprofile`, `~/.zshrc`, and `~/.zshenv`.
|
||||
@ -51,13 +51,13 @@ For vibecoding, it can help to have multiple parallel copies of the codebase ope
|
||||
```sh
|
||||
# .envrc
|
||||
# make sure to install direnv and add it to your shell rc file (e.g. ~/.bashrc or ~/.zshrc)
|
||||
export NEXT_PUBLIC_STACK_PORT_PREFIX=181
|
||||
export NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX=181
|
||||
|
||||
# with this many processes running, it can be useful to add a custom title to all Node.js processes
|
||||
# export NODE_OPTIONS="--require=<path-to-the-workspace-folder>/scripts/set-process-title.js $NODE_OPTIONS"
|
||||
```
|
||||
|
||||
When you do this, it is recommended that you give all workspaces a port prefix other than 81, to prevent accidental conflicts when you forgot to make a feature support the $NEXT_PUBLIC_STACK_PORT_PREFIX environment variable. (for example: first workspace at 181, second workspace at 182, etc.)
|
||||
When you do this, it is recommended that you give all workspaces a port prefix other than 81, to prevent accidental conflicts when you forgot to make a feature support the $NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX environment variable. (for example: first workspace at 181, second workspace at 182, etc.)
|
||||
|
||||
Also, the cookies on different ports may conflict with each other. To prevent this, open `a.localhost:18101` and `b.localhost:18201` instead or normal localhost, so the cookies are scoped differently.
|
||||
|
||||
|
||||
@ -20,7 +20,7 @@ describe('validateRedirectUrl', () => {
|
||||
const stackKeys = [
|
||||
"NEXT_PUBLIC_STACK_HOSTED_HANDLER_URL_TEMPLATE",
|
||||
"NEXT_PUBLIC_STACK_HOSTED_HANDLER_DOMAIN_SUFFIX",
|
||||
"NEXT_PUBLIC_STACK_PORT_PREFIX",
|
||||
"NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX",
|
||||
] as const;
|
||||
const hexclaveOf = (name: string) => name.replace("STACK_", "HEXCLAVE_");
|
||||
const allKeys = [...stackKeys, ...stackKeys.map(hexclaveOf)];
|
||||
@ -28,7 +28,7 @@ describe('validateRedirectUrl', () => {
|
||||
const newValues: Record<string, string | undefined> = {
|
||||
NEXT_PUBLIC_STACK_HOSTED_HANDLER_URL_TEMPLATE: values.hostedHandlerUrlTemplate,
|
||||
NEXT_PUBLIC_STACK_HOSTED_HANDLER_DOMAIN_SUFFIX: values.hostedHandlerDomainSuffix,
|
||||
NEXT_PUBLIC_STACK_PORT_PREFIX: values.stackPortPrefix,
|
||||
NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX: values.stackPortPrefix,
|
||||
};
|
||||
for (const stackKey of stackKeys) {
|
||||
newValues[hexclaveOf(stackKey)] = newValues[stackKey];
|
||||
@ -69,7 +69,7 @@ describe('validateRedirectUrl', () => {
|
||||
describe('exact domain matching', () => {
|
||||
it('should implicitly validate hosted handler domains for the project', () => {
|
||||
withHostedHandlerEnv({
|
||||
hostedHandlerUrlTemplate: "http://{projectId}.localhost:${NEXT_PUBLIC_STACK_PORT_PREFIX:-81}09/{hostedPath}",
|
||||
hostedHandlerUrlTemplate: "http://{projectId}.localhost:${NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX:-81}09/{hostedPath}",
|
||||
stackPortPrefix: "92",
|
||||
}, () => {
|
||||
const tenancy = createMockTenancy({
|
||||
|
||||
@ -9,7 +9,7 @@ export function getHostedHandlerTrustedDomain(projectId: string): string {
|
||||
projectId,
|
||||
hostedHandlerDomainSuffix: getProcessEnv("NEXT_PUBLIC_STACK_HOSTED_HANDLER_DOMAIN_SUFFIX"),
|
||||
hostedHandlerUrlTemplate: getProcessEnv("NEXT_PUBLIC_STACK_HOSTED_HANDLER_URL_TEMPLATE"),
|
||||
stackPortPrefix: getEnvVariable("NEXT_PUBLIC_STACK_PORT_PREFIX", "81"),
|
||||
stackPortPrefix: getEnvVariable("NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX", "81"),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -75,9 +75,9 @@ export NEXT_PUBLIC_BROWSER_STACK_DASHBOARD_URL=${NEXT_PUBLIC_STACK_DASHBOARD_URL
|
||||
# is STACK_ENV_VAR_SENTINEL_NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX, and the sentinel
|
||||
# substitution loop below derives the env var name from the sentinel — so this
|
||||
# MUST export NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX or the sentinel never resolves.
|
||||
# Accept the legacy NEXT_PUBLIC_STACK_PORT_PREFIX as input for back-compat with
|
||||
# Accept the legacy NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX as input for back-compat with
|
||||
# existing self-host configs.
|
||||
export NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX=${NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX:-${NEXT_PUBLIC_STACK_PORT_PREFIX:-81}}
|
||||
export NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX=${NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX:-${NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX:-81}}
|
||||
PORT_PREFIX=${NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX}
|
||||
export NEXT_PUBLIC_SERVER_STACK_DASHBOARD_URL="http://localhost:${PORT_PREFIX}01"
|
||||
export NEXT_PUBLIC_BROWSER_STACK_API_URL=${NEXT_PUBLIC_STACK_API_URL}
|
||||
|
||||
@ -26,7 +26,7 @@ From the repository root:
|
||||
pnpm -C docs-mintlify run dev
|
||||
```
|
||||
|
||||
This starts Mintlify in `docs-mintlify` on `http://localhost:${NEXT_PUBLIC_STACK_PORT_PREFIX:-81}04` (for example, `http://localhost:8104` with the default prefix).
|
||||
This starts Mintlify in `docs-mintlify` on `http://localhost:${NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX:-81}04` (for example, `http://localhost:8104` with the default prefix).
|
||||
|
||||
From inside `docs-mintlify`, you can also run:
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@ This is the documentation site for Stack Auth, built with [Next.js](https://next
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
The docs server runs on port `8104` by default (or `${NEXT_PUBLIC_STACK_PORT_PREFIX}04`).
|
||||
The docs server runs on port `8104` by default (or `${NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX}04`).
|
||||
|
||||
## Project Structure
|
||||
|
||||
|
||||
@ -15,7 +15,7 @@ const hostedHandlerTemplateProjectIdB = "11111111-1111-4111-8111-111111111111";
|
||||
|
||||
function replaceStackPortPrefix(input: string | undefined, stackPortPrefix: string | undefined): string | undefined {
|
||||
if (input == null) return undefined;
|
||||
return stackPortPrefix ? input.replace(/\$\{NEXT_PUBLIC_STACK_PORT_PREFIX:-81\}/g, stackPortPrefix) : input;
|
||||
return stackPortPrefix ? input.replace(/\$\{NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX:-81\}/g, stackPortPrefix) : input;
|
||||
}
|
||||
|
||||
function getHostedHandlerUrlFromTemplate(template: string, projectId: string, hostedPath: string): string {
|
||||
@ -232,7 +232,7 @@ import.meta.vitest?.test("validateRedirectUrl trusts implicit hosted handler dom
|
||||
allowLocalhost: false,
|
||||
trustedDomains: getImplicitlyTrustedDomainsForProject({
|
||||
projectId,
|
||||
hostedHandlerUrlTemplate: "http://{projectId}.localhost:${NEXT_PUBLIC_STACK_PORT_PREFIX:-81}09/{hostedPath}",
|
||||
hostedHandlerUrlTemplate: "http://{projectId}.localhost:${NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX:-81}09/{hostedPath}",
|
||||
stackPortPrefix: "92",
|
||||
}),
|
||||
})).toBe(true);
|
||||
|
||||
@ -173,7 +173,7 @@ describe("handler URL targets", () => {
|
||||
});
|
||||
|
||||
it("uses the full hosted handler URL template when configured", () => {
|
||||
vi.stubEnv("NEXT_PUBLIC_STACK_HOSTED_HANDLER_URL_TEMPLATE", "http://{projectId}.localhost:${NEXT_PUBLIC_STACK_PORT_PREFIX:-81}09/{hostedPath}");
|
||||
vi.stubEnv("NEXT_PUBLIC_STACK_HOSTED_HANDLER_URL_TEMPLATE", "http://{projectId}.localhost:${NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX:-81}09/{hostedPath}");
|
||||
vi.stubEnv("NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX", "93");
|
||||
|
||||
const urls = resolveHandlerUrls({
|
||||
|
||||
@ -188,7 +188,7 @@ Tests use Swift Testing framework against a running backend.
|
||||
swift test
|
||||
```
|
||||
|
||||
The tests connect to `http://localhost:8102` (or `${NEXT_PUBLIC_STACK_PORT_PREFIX}02`).
|
||||
The tests connect to `http://localhost:8102` (or `${NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX}02`).
|
||||
|
||||
## API Reference
|
||||
|
||||
|
||||
@ -6,10 +6,10 @@ import FoundationNetworking
|
||||
|
||||
/// Shared test configuration
|
||||
/// Set environment variables to customize test behavior:
|
||||
/// - NEXT_PUBLIC_STACK_PORT_PREFIX: Port prefix for backend (default: "81")
|
||||
/// - NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX: Port prefix for backend (default: "81")
|
||||
/// - STACK_SKIP_E2E_TESTS: Set to "true" to skip E2E tests
|
||||
struct TestConfig {
|
||||
static let portPrefix = ProcessInfo.processInfo.environment["NEXT_PUBLIC_STACK_PORT_PREFIX"] ?? "81"
|
||||
static let portPrefix = ProcessInfo.processInfo.environment["NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX"] ?? "81"
|
||||
static let baseUrl = "http://localhost:\(portPrefix)02"
|
||||
static let skipE2E = ProcessInfo.processInfo.environment["STACK_SKIP_E2E_TESTS"] == "true"
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user