mirror of
https://github.com/stack-auth/stack.git
synced 2026-06-30 21:01:54 +08:00
Some checks failed
all-good: Did all the other checks pass? / all-good (push) Has been cancelled
Ensure Prisma migrations are in sync with the schema / check_prisma_migrations (22.x) (push) Has been cancelled
DB migration compat / Check if migrations changed (push) Has been cancelled
Docker Server Build and Push / Docker Build and Push Server (push) Has been cancelled
Docker Server Build and Run / docker (push) Has been cancelled
Runs E2E API Tests (Local Emulator) / E2E Tests (Local Emulator, Node ${{ matrix.node-version }}) (22.x) (push) Has been cancelled
Runs E2E API Tests / E2E Tests (Node ${{ matrix.node-version }}, Freestyle ${{ matrix.freestyle-mode }}) (mock, 22.x) (push) Has been cancelled
Runs E2E API Tests / E2E Tests (Node ${{ matrix.node-version }}, Freestyle ${{ matrix.freestyle-mode }}) (prod, 22.x) (push) Has been cancelled
Runs E2E API Tests with custom port prefix / build (22.x) (push) Has been cancelled
Runs E2E Fallback Tests / E2E Fallback Tests (Node ${{ matrix.node-version }}) (22.x) (push) Has been cancelled
Lint & build / lint_and_build (24) (push) Has been cancelled
TOC Generator / TOC Generator (push) Has been cancelled
DB migration compat / Back-compat — Current branch migrations with ${{ needs.check-migrations-changed.outputs.base_branch }} branch code (push) Has been cancelled
DB migration compat / Forward-compat — Current branch code with ${{ needs.check-migrations-changed.outputs.base_branch }} branch migrations (push) Has been cancelled
DB migration compat / No migration changes (skipped) (push) Has been cancelled
## Summary
Completes the env-var side of the Hexclave rebrand: every
`STACK_*`-prefixed variable (including `NEXT_PUBLIC_STACK_*` and
`VITE_STACK_*`) is renamed to `HEXCLAVE_*` across all checked-in `.env`,
`.env.development`, and `.env.example` files (30 files, ~135 keys).
Legacy `STACK_*` names keep working everywhere via dual-read, so
**existing deployments, `.env.local` files, and self-hosted setups need
no immediate migration**.
## How legacy names keep working
- **Server code** already resolves `HEXCLAVE_*` first with `STACK_*`
fallback via `getEnvVariable`. Direct `process.env.STACK_X` readers fed
by the renamed files (prisma seed, e2e tests/helpers, internal-tool
scripts, examples, `prisma.config.ts`) now read `HEXCLAVE_X || STACK_X`.
- **Client code** (Next.js build-time inlining) uses literal dual-read
expressions; the dashboard's `_inlineEnvVars` already had them.
- **Docker/self-hosting**: `docker/server/entrypoint.sh` (shared by the
server and local-emulator images) gets a generic two-way
`HEXCLAVE_`↔`STACK_` env mirror — runs at startup and again before
sentinel replacement — replacing the previous URL-trio-only mirror.
Operators can use either prefix.
## The empty-placeholder trap (`||` vs `??`)
The checked-in templates define empty placeholders (`HEXCLAVE_X=#
comment` parses to `""` via dotenv). With `?? `-based fallbacks, that
empty string would silently shadow a real value under the legacy name —
including legacy vars set in Vercel/CI env at build time, since the
tracked `.env` is present during builds. All fallback chains therefore
treat empty-as-unset (`||`):
- `getEnvVariable` and `getProcessEnv` in `packages/shared`
- the dashboard/docs/example literal dual-reads
- the generated SDK env getters (via
`packages/template/scripts/generate-env.ts`; the generated
`src/generated/env.ts` files are gitignored and regenerate at build)
## Other notable changes
- Tests that override env now set the canonical `HEXCLAVE_*` name (it
wins over `STACK_*`): e2e `cross-domain-auth`, backend
`internal-feedback-emails` in-source test.
- e2e `helpers.ts` port-prefix expansion loop also matches the
`HEXCLAVE_` prefixes.
- `docker/local-emulator/generate-env-development.mjs` reads source keys
canonically (legacy fallback) and emits canonical keys; regenerated
output matches.
- `rotate-secrets.sh` falls back to
`HEXCLAVE_DATABASE_CONNECTION_STRING`.
- Docs code snippets (`docs/code-examples`) renamed outright to
canonical names, consistent with #1571.
- OAuth callback `console.warn` in `packages/template/src/lib/auth.ts`
now says Hexclave.
## Migration note for the team
Local `.env.local` files with legacy `STACK_*` overrides keep working
**unless** the override targets a var that `.env.development` now sets
to a real (non-empty) `HEXCLAVE_*` value — the canonical name wins over
file precedence. Rename those keys in your `.env.local` once.
## Verification
- `typecheck` + `lint` pass on every touched package (shared, backend,
dashboard, e2e, internal-tool, cli, docs, template). Pre-existing
failures on dev (`admin-app-impl.ts` typecheck, dashboard metrics-page
errors) are unchanged (identical error counts with/without this change).
- `getEnvVariable`/`getProcessEnv` fallback semantics smoke-tested
directly (empty-HEXCLAVE → legacy fallback, HEXCLAVE wins when set,
defaults intact).
- `internal-feedback-emails` in-source vitest passes; emulator env
generator `--check` passes; `bash -n` on touched shell scripts.
- Two independent review agents audited the diff for correctness bugs
and coverage gaps; all confirmed findings are fixed in the third commit.
<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Renamed all `STACK_*` env vars (including
`NEXT_PUBLIC_STACK_*`/`VITE_STACK_*`) to `HEXCLAVE_*` across env
templates and code, with dual‑read that treats empty as unset, detects
conflicts, ignores post‑build sentinels, and falls back to legacy names.
All GitHub Actions now use `HEXCLAVE_*`; local‑emulator e2e is fixed by
setting `NEXT_PUBLIC_HEXCLAVE_IS_LOCAL_EMULATOR` in CI.
- **Refactors**
- Added conflict‑aware dual‑read helpers (prefer `HEXCLAVE_*`,
empty‑as‑unset, ignore post‑build sentinels, preserve empty passthrough)
and used them across `packages/shared` (resolver + tests),
`apps/dashboard` inline/public envs (with tests), `apps/backend` Prisma
config/seed and vitest (accept both prefixes), `packages/cli`
(API/Dashboard URLs, project ID, `HEXCLAVE_EMULATOR_HOME`; tests),
Docker (`entrypoint.sh` mirroring + `rotate-secrets.sh` DB URL),
docs/components (`docs/src/lib/env.ts`), and examples; hosted/Vite apps
now error if both spellings differ.
- Port‑prefix expansion includes `HEXCLAVE_*`; backend tests use a new
helper to resolve DB connection strings; Prisma prefers
`HEXCLAVE_DATABASE_CONNECTION_STRING` with legacy fallback.
- Generated SDK env getters use plain `HEXCLAVE_*` || `STACK_*` (no
conflict throw); dashboard inline resolver preserves empty/sentinel
passthrough to avoid build failures; docs/examples include dual‑read
utilities.
- Tests now stub canonical `HEXCLAVE_*` flags (e.g., plan limits, bot
challenge, OAuth tokens, hosted handler) to avoid shadowing/conflict
with committed defaults.
- **Migration**
- No immediate action; legacy `STACK_*` names still work.
- If both names are set with different values, builds/scripts error. Set
only `HEXCLAVE_*` or make both equal.
- SDK consumers won’t see conflict throws; update env names to
`HEXCLAVE_*` over time.
<sup>Written for commit 7539fb9fbf.
Summary will update on new commits.</sup>
<a
href="https://cubic.dev/pr/hexclave/hexclave/pull/1588?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
* **Chores**
* Migrated environment variable names from the legacy `STACK_*` prefix
to the new `HEXCLAVE_*` prefix across backend, dashboard, tooling,
Docker, and examples.
* Updated environment/config resolution to prefer `HEXCLAVE_*`, treat
empty strings as unset, and detect conflicts when both `STACK_*` and
`HEXCLAVE_*` are set to different values.
* Updated local emulator, server startup, and env-generation workflows
to use the new names (with legacy fallback where applicable).
* **Documentation**
* Updated docs and code examples to reference `HEXCLAVE_*` variables.
* **Tests**
* Refreshed unit and e2e coverage to validate dual-read behavior,
conflict detection, and empty-value handling.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
128 lines
9.2 KiB
Bash
128 lines
9.2 KiB
Bash
# Basic
|
|
NEXT_PUBLIC_HEXCLAVE_API_URL=# the base URL of Stack's backend/API. For local development, this is `http://localhost:8102`; for the managed service, this is `https://api.hexclave.com`.
|
|
NEXT_PUBLIC_HEXCLAVE_DASHBOARD_URL=# the URL of Stack's dashboard. For local development, this is `http://localhost:8101`; for the managed service, this is `https://app.hexclave.com`.
|
|
NEXT_PUBLIC_HEXCLAVE_IS_LOCAL_EMULATOR=# set to true to enable local emulator-only behaviors (internal local emulator endpoints, read-only environment config overrides, and local emulator auth UX)
|
|
HEXCLAVE_SECRET_SERVER_KEY=# a random, unguessable secret key generated by `pnpm generate-keys`
|
|
|
|
|
|
# seed script settings
|
|
HEXCLAVE_SEED_INTERNAL_PROJECT_SIGN_UP_ENABLED=# true to enable user sign up to the dashboard when seeding
|
|
HEXCLAVE_SEED_INTERNAL_PROJECT_OTP_ENABLED=# true to add OTP auth to the dashboard when seeding
|
|
HEXCLAVE_SEED_INTERNAL_PROJECT_ALLOW_LOCALHOST=# true to allow running dashboard on the localhost, set this to true only in development
|
|
HEXCLAVE_SEED_INTERNAL_PROJECT_OAUTH_PROVIDERS=# list of oauth providers to add to the dashboard when seeding, separated by comma, for example "github,google,facebook"
|
|
HEXCLAVE_SEED_INTERNAL_PROJECT_USER_EMAIL=# default user added to the dashboard
|
|
HEXCLAVE_SEED_INTERNAL_PROJECT_USER_PASSWORD=# default user's password, paired with HEXCLAVE_SEED_INTERNAL_PROJECT_USER_EMAIL
|
|
HEXCLAVE_SEED_INTERNAL_PROJECT_USER_INTERNAL_ACCESS=# if the default user has access to the internal dashboard project
|
|
HEXCLAVE_SEED_INTERNAL_PROJECT_USER_GITHUB_ID=# add github oauth id to the default user
|
|
HEXCLAVE_INTERNAL_PROJECT_PUBLISHABLE_CLIENT_KEY=# default publishable client key for the internal project
|
|
HEXCLAVE_INTERNAL_PROJECT_SECRET_SERVER_KEY=# default secret server key for the internal project
|
|
HEXCLAVE_SEED_INTERNAL_PROJECT_SUPER_SECRET_ADMIN_KEY=# default super secret admin key for the internal project
|
|
|
|
# OAuth mock provider settings
|
|
HEXCLAVE_OAUTH_MOCK_URL=# enter the URL of the mock OAuth provider here. For local development, use `http://localhost:8114`.
|
|
|
|
# OAuth shared keys
|
|
# Can be set to MOCK to use mock OAuth providers
|
|
HEXCLAVE_GITHUB_CLIENT_ID=# client
|
|
HEXCLAVE_GITHUB_CLIENT_SECRET=# client secret
|
|
HEXCLAVE_GOOGLE_CLIENT_ID=# client id
|
|
HEXCLAVE_GOOGLE_CLIENT_SECRET=# client secret
|
|
HEXCLAVE_MICROSOFT_CLIENT_ID=# client id
|
|
HEXCLAVE_MICROSOFT_CLIENT_SECRET=# client secret
|
|
HEXCLAVE_SPOTIFY_CLIENT_ID=# client id
|
|
HEXCLAVE_SPOTIFY_CLIENT_SECRET=# client secret
|
|
|
|
HEXCLAVE_ALLOW_SHARED_OAUTH_ACCESS_TOKENS=# allow shared oauth provider to also use connected account access token, this should only be used for development and testing
|
|
|
|
HEXCLAVE_DISABLE_PLAN_LIMITS=# set to "true" to bypass enforcement of Hexclave's own internal-tenancy plan limits (analytics_events, session_replays, emails_per_month, dashboard_admins seat cap, auth_users soft cap, analytics_timeout_seconds). Default unset/false preserves enforcement. Intended as a temporary cutover safety net while the plan-limits infrastructure rolls out — customer projects' own item APIs are unaffected by this flag.
|
|
|
|
# Email
|
|
# For local development, you can spin up a local SMTP server like inbucket
|
|
HEXCLAVE_EMAIL_HOST=# for local inbucket: 127.0.0.1
|
|
HEXCLAVE_EMAIL_PORT=# for local inbucket: 8129
|
|
HEXCLAVE_EMAIL_USERNAME=# for local inbucket: test
|
|
HEXCLAVE_EMAIL_PASSWORD=# for local inbucket: none
|
|
HEXCLAVE_EMAIL_SENDER=# for local inbucket: noreply@test.com
|
|
HEXCLAVE_EMAILABLE_API_KEY=# Emailable API key for email validation, see https://emailable.com. Use a test key (starting with "test_") for local dev — it does not consume credits. Set to "disable_email_validation" to disable.
|
|
|
|
HEXCLAVE_DEFAULT_EMAIL_CAPACITY_PER_HOUR=# the number of emails a new project can send. Defaults to 200
|
|
|
|
# Email branching configuration
|
|
# If you have multiple deployments of compute accessing the same DB or multiple copies of a DBs connected to compute (as
|
|
# you would in preview/branching environments), you may want to either disable the auto-triggered email queue steps
|
|
# (those that trigger whenever an email is sent, besides the cron job), or disable email sending as a whole.
|
|
HEXCLAVE_EMAIL_BRANCHING_DISABLE_QUEUE_AUTO_TRIGGER=# set to 'true' to disable the automatic triggering of the email queue step. the cron job must call /email-queue-step to run the queue step. Most useful on production domains where you know the cron job will run on the correct deployment and you don't need the auto-trigger (which may be on the wrong deployment)
|
|
HEXCLAVE_EMAIL_BRANCHING_DISABLE_QUEUE_SENDING=# set to 'true' to throw an error instead of sending emails in the email queue step. Most useful on development branches that have a copy of the production DB, but should not send any emails (as otherwise some emails could be sent twice)
|
|
|
|
|
|
# Database
|
|
# For local development: `docker run -it --rm -e POSTGRES_PASSWORD=password -p "8128:5432" postgres`
|
|
HEXCLAVE_DATABASE_CONNECTION_STRING=# enter your connection string here. For local development: `postgres://postgres:PASSWORD-PLACEHOLDER--uqfEC1hmmv@localhost:8128/stackframe`
|
|
|
|
# Webhooks
|
|
HEXCLAVE_SVIX_SERVER_URL=# For prod, leave it empty. For local development, use `http://localhost:8113`
|
|
HEXCLAVE_SVIX_API_KEY=# enter the API key for the Svix webhook service here. Use `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE2NTUxNDA2MzksImV4cCI6MTk3MDUwMDYzOSwibmJmIjoxNjU1MTQwNjM5LCJpc3MiOiJzdml4LXNlcnZlciIsInN1YiI6Im9yZ18yM3JiOFlkR3FNVDBxSXpwZ0d3ZFhmSGlyTXUifQ.En8w77ZJWbd0qrMlHHupHUB-4cx17RfzFykseg95SUk` for local development
|
|
|
|
# S3
|
|
HEXCLAVE_S3_PUBLIC_ENDPOINT=# publicly accessible endpoint
|
|
HEXCLAVE_S3_ENDPOINT=# S3 API endpoint URL (e.g., 'https://s3.amazonaws.com' for AWS or custom endpoint for S3-compatible services)
|
|
HEXCLAVE_S3_REGION=
|
|
HEXCLAVE_S3_ACCESS_KEY_ID=
|
|
HEXCLAVE_S3_SECRET_ACCESS_KEY=
|
|
HEXCLAVE_S3_BUCKET=
|
|
HEXCLAVE_S3_PRIVATE_BUCKET=
|
|
|
|
# AWS configuration
|
|
HEXCLAVE_AWS_REGION=
|
|
HEXCLAVE_AWS_KMS_ENDPOINT=
|
|
HEXCLAVE_AWS_ACCESS_KEY_ID=
|
|
HEXCLAVE_AWS_SECRET_ACCESS_KEY=
|
|
HEXCLAVE_AWS_VERCEL_OIDC_ROLE_ARN=
|
|
|
|
# Upstash configuration
|
|
HEXCLAVE_QSTASH_URL=
|
|
HEXCLAVE_QSTASH_TOKEN=
|
|
HEXCLAVE_QSTASH_CURRENT_SIGNING_KEY=
|
|
HEXCLAVE_QSTASH_NEXT_SIGNING_KEY=
|
|
|
|
# Email monitor
|
|
HEXCLAVE_EMAIL_MONITOR_RESEND_EMAIL_API_KEY=# enter the resend poller api key here
|
|
HEXCLAVE_EMAIL_MONITOR_RESEND_EMAIL_DOMAIN=# enter the resend domain that should receive the emails
|
|
HEXCLAVE_EMAIL_MONITOR_PROJECT_ID=# enter the project id for the project that the email monitor will attempt to sign up for
|
|
HEXCLAVE_EMAIL_MONITOR_PUBLISHABLE_CLIENT_KEY=# enter the publishable client key for email monitor to use when attempting a sign up
|
|
HEXCLAVE_EMAIL_MONITOR_VERIFICATION_CALLBACK_URL=# enter a valid verification callback url for the project that the email monitor will attempt to sign up for
|
|
HEXCLAVE_EMAIL_MONITOR_INBUCKET_API_URL=# enter a valid inbucket api url for the email monitor to check emails from in test mode
|
|
HEXCLAVE_EMAIL_MONITOR_USE_INBUCKET=# enter true/false based on whether the email monitor should use inbucket or resend. Note that if this is set to true in prod, the email monitor will throw an error.
|
|
HEXCLAVE_EMAIL_MONITOR_SECRET_TOKEN=# enter the secret token value needed for the request to the email monitor to be accepted
|
|
|
|
# Clickhouse
|
|
HEXCLAVE_CLICKHOUSE_URL=# URL of the Clickhouse instance
|
|
HEXCLAVE_CLICKHOUSE_ADMIN_USER=# username of the admin account
|
|
HEXCLAVE_CLICKHOUSE_ADMIN_PASSWORD=# password of the admin account
|
|
HEXCLAVE_CLICKHOUSE_EXTERNAL_PASSWORD=# a randomly generated secure string. The user account will be created automatically
|
|
|
|
|
|
# Misc
|
|
HEXCLAVE_ACCESS_TOKEN_EXPIRATION_TIME=# enter the expiration time for the access token here. Optional, don't specify it for default value
|
|
HEXCLAVE_SETUP_ADMIN_GITHUB_ID=# enter the account ID of the admin user here, and after running the seed script they will be able to access the internal project in the Stack dashboard. Optional, don't specify it for default value
|
|
OTEL_EXPORTER_OTLP_ENDPOINT=# enter the OpenTelemetry endpoint here. Optional, default is `http://localhost:8131`
|
|
HEXCLAVE_INTEGRATION_CLIENTS_CONFIG=# a list of oidc-provider clients for integrations. If not provided, disables integrations
|
|
HEXCLAVE_FREESTYLE_API_KEY=# enter your freestyle.sh api key
|
|
HEXCLAVE_VERCEL_SANDBOX_PROJECT_ID=# enter the project id for the vercel project that the vercel engine will use
|
|
HEXCLAVE_VERCEL_SANDBOX_TEAM_ID=# enter the team id for the vercel project that the vercel engine will use
|
|
HEXCLAVE_VERCEL_SANDBOX_TOKEN=# enter the token for the vercel project that the vercel engine will use
|
|
HEXCLAVE_OPENAI_API_KEY=# enter your openai api key
|
|
HEXCLAVE_FEATUREBASE_API_KEY=# enter your featurebase api key
|
|
HEXCLAVE_STRIPE_SECRET_KEY=# enter your stripe api key
|
|
HEXCLAVE_STRIPE_WEBHOOK_SECRET=# enter your stripe webhook secret
|
|
HEXCLAVE_TELEGRAM_BOT_TOKEN= # enter you telegram bot token
|
|
HEXCLAVE_TELEGRAM_CHAT_ID=# enter your telegram chat id
|
|
|
|
# Docs AI tool bundle
|
|
HEXCLAVE_MINTLIFY_MCP_URL=# override the Mintlify MCP server used by the backend's AI docs tool bundle. Defaults to https://stackauth-e0affa27.mintlify.app/mcp
|
|
|
|
# MCP review tool (SpacetimeDB)
|
|
HEXCLAVE_SPACETIMEDB_URI=# SpacetimeDB host URI; default empty (logging disabled)
|
|
HEXCLAVE_SPACETIMEDB_DB_NAME=# SpacetimeDB database name
|
|
HEXCLAVE_MCP_LOG_TOKEN=# shared secret gating the log_mcp_call reducer; must match EXPECTED_LOG_TOKEN in apps/internal-tool/spacetimedb/src/index.ts
|