<!--
Make sure you've read the CONTRIBUTING.md guidelines:
https://github.com/stack-auth/stack-auth/blob/dev/CONTRIBUTING.md
-->
Updates the API Docs auth panel for a new look.
<img width="404" height="346" alt="image"
src="https://github.com/user-attachments/assets/5791a6ea-ac28-4e35-9d8c-c88a64f86386"
/>
<img width="394" height="622" alt="image"
src="https://github.com/user-attachments/assets/ca7ba243-52f0-49e4-ad21-a4acd652bfe1"
/>
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
## Release Notes
* **New Features**
* Added project dropdown selector with automatic authentication setup
* Introduced manual mode for direct header configuration
* Added authentication status indicators
* **Bug Fixes**
* Unified error handling across desktop and mobile views
* **Style**
* Improved mobile interface with better spacing and safe-area
accommodations
* Refined panel layout and transition animations
<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!--
Make sure you've read the CONTRIBUTING.md guidelines:
https://github.com/stack-auth/stack-auth/blob/dev/CONTRIBUTING.md
-->
Conditionally generate secrets. This stops docker image from generating
new secrets upon every restart.
Originally reported in #578.
This fix aims to resolve this issue.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Secret values can now be externally injected during startup without
being overwritten. Pre-configured secrets are preserved instead of being
regenerated.
<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Summary
This PR improves the documentation for GitHub authentication setup and
self-hosting.
## Changes
### GitHub OAuth/App Setup Guide
- Updated
[github.mdx](cci:7://file:///Users/madison/source/stack-auth/docs/content/docs/%28guides%29/concepts/auth-providers/github.mdx:0:0-0:0)
with clearer instructions differentiating between **GitHub OAuth App**
and **GitHub App** setup
- Added better explanations for when to use each option
### Self-Hosting Documentation
- Added prominent danger warning about self-hosting responsibilities
- Migrated inline shell commands to structured code examples using
[PlatformCodeblock](cci:1://file:///Users/madison/source/stack-auth/docs/src/components/mdx/platform-codeblock.tsx:242:0-673:1)
component
- Created
[docs/code-examples/self-host.ts](cci:7://file:///Users/madison/source/stack-auth/docs/code-examples/self-host.ts:0:0-0:0)
with all self-hosting commands
### Info Component
- Added new `danger` type for critical warnings with red accent styling
- Updated component styling with modern left accent bar and gradient
backgrounds
### PlatformCodeblock Component
- Added `hidePlatformSelector` prop to hide platform dropdown for
single-platform code examples
- Added Shell platform support for terminal commands (Docker, Git, pnpm)
- Filtered Shell platform from user-selectable options in both the
codeblock and header selectors
### Platform Config
- Added Shell platform with Docker, Git, and pnpm frameworks
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added comprehensive self-hosting and authentication customization
example collections for copy-paste use.
* New "danger" info style with visual accent for important warnings.
* **Documentation**
* GitHub integration guide now centers on GitHub App with an alternate
OAuth path retained.
* Replaced many inline snippets with platform-driven code blocks and
improved platform/framework selector behavior (single-platform
optimization; option to hide selector).
* Pages now surface "Last updated" above descriptions.
<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!--
Make sure you've read the CONTRIBUTING.md guidelines:
https://github.com/stack-auth/stack-auth/blob/dev/CONTRIBUTING.md
-->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Refactor**
* Centralized email-theme operations (create/read/list/update/delete)
behind a unified handler, simplifying endpoints and improving
consistency.
* **New Features**
* Theme updates now validate and render template previews before
applying changes; create supports generated or provided IDs.
* **Chores**
* Added a reusable CRUD handler factory to standardize backend
data-operation patterns and error handling.
<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<img width="1179" height="965" alt="Screenshot 2026-01-19 at 1 45 19 PM"
src="https://github.com/user-attachments/assets/5583e2e7-08a7-4524-9d16-57dcb9f4fad3"
/>
<!--
Make sure you've read the CONTRIBUTING.md guidelines:
https://github.com/stack-auth/stack-auth/blob/dev/CONTRIBUTING.md
-->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added a Payments Settings page that surfaces a "Settings" screen for
managing payment behavior.
* Added a "Block new purchases" toggle on that page; changing it updates
the project's payment setting immediately.
* Added a "Settings" link to the Payments navigation menu for quick
access.
<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!--
Make sure you've read the CONTRIBUTING.md guidelines:
https://github.com/stack-auth/stack-auth/blob/dev/CONTRIBUTING.md
-->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Refactor**
* Updated internal environment detection mechanism for OAuth flows.
Insecure HTTP requests are now allowed when running outside of
production environments, rather than only during testing scenarios. No
changes to public APIs.
<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
We update the sdk dependencies (the ones present in
`package-template.json`) to the latest versions. Since several packages
have major version bumps, this results in a variety of breaking changes
that have been handled here. Incidentally, when possible, we update
similar dependencies across the codebase.
We decide to defer the tailwind update to another PR owing to its scale.
The rest of the updates and changes have been catalogued below:
1.
[Bumping](https://github.com/panva/oauth4webapi/blob/v3.x/CHANGELOG.md)
`oauth4webapi` to 3.8.3: this was a major version changed. While there
were no compatibility issues in the sdk, there were several breaking
changes in `stack-shared`. Namely:
a. The removal of `isOauth2Error`. We used this to check if the results
of our `oauth4webapi` api invocations had issues. The functions were
changed to explicitly throw either `ResponseBodyErrors` or
`AuthorizationResponseErrors`, so the code was reworked to account for
that with no loss in error handling.
b. Dropping of support for http broadly: `oauth4webapi` now only accepts
https. This is desired, but I add a carve out for our test environments
only.
c. `refreshTokenGrantRequest` and `authorizationCodeGrantRequest` now
require `clientAuthentication` to be passed explicitly to them.
d. Changes in how we handle our `MultiFactorAuthenticationRequired`
error: This is an error that we created and is passed to the
`oauth4webapi` API if there are MFA issues. Since the
`processAuthorizationCodeResponse` now explicitly throws a
`ResponseBodyError`, we access the error cause from the body of the
error instead.
2. [Bumping](https://github.com/Qix-/color/releases) `color` to 5.0.4:
this was a major version bump. Simple type checking change, I checked
the API for the correct interface.
3.
[Bumping](https://github.com/MasterKale/SimpleWebAuthn/blob/master/CHANGELOG.md)
`simplewebauthn` to 13.2.2: two major version bumps, but no
incompatibilities surprisingly
4. [Bumping](https://github.com/jshttp/cookie/releases) `cookie` to
1.1.1: this was a major version bump.
a. Changing `parse` to `parseCookie`. In the most recent version,
`parse` is still maintained as an alias for `parseCookie` for backwards
compatibility, but I thought it would be best to change it over now. No
change in functionality.
b. Typing is now strongly enforced. A cookie can be `string |
undefined`, and the `Cookies` are now `Record<string, string |
undefined>`. We already have code to handle if a cookie is returned as
undefined/ null, so the changes here were more to ensure type
compatibility rather than big changes in functionality.
5. [Bumping ](https://github.com/isaacs/rimraf#readme)`rimraf` to 6.1.2:
No breaking changes, mostly just bug fixes.
6. [Bumping](https://github.com/panva/jose/releases?page=1) `jose` to
6.1.3: This is another major version bump. We update it across the
codebase to ensure compatibility. We use this for importing and
processing jwk tokens. There are a few big changes in the version bump,
but the only one that applies to us is that `importJwk` now yields a
`CryptoKey` instead of a `KeyObject` in Node.js. However, this doesn't
appear to break our code. We use `importJwk` in
`stack-auth/packages/stack-shared/src/utils/jwt.tsx`.
7. [Bumping](https://github.com/react-hook-form/resolvers/releases)
`hookform/resolvers` to 5.2.2 (two major version jumps), and
consequently bumping `react-hook-form` to 7.70.0: We already use the
patterns that `hookform/resolvers`' latest versions seem to be
enforcing. The only other breaking change is that it requires version
7.55.0+ of `react-hook-form`. Though we should pay attention to any
interactions with zod and `hookform/resolvers`, some people have
reported compatibility issues if they aren't using the latest compatible
versions of both.
8. [Bumping](https://github.com/jquense/yup/blob/master/CHANGELOG.md)
`yup` to 1.7.1: this was a minor version change, but we had
incompatibility issues with this change. Versions 1.4.1 and 1.7.1 cannot
exist in the same codebase due to incompatibility, so we bumped it up
across the codebase, including in peer dependencies.
9. Some minor version changes for some packages, but these were mostly
bug fixes.
10. **Edited to add**: Bumping freestyle to 0.1.6, and reworking the
freestyle mock server. In 0.1.6, freestyle changed their API in two
ways:
a. We're now supposed to hit their `execute/v2/...` endpoint and
b. They've flattened the `config` argument to `serverless.runs.create`.
These changes are minor, but are important. As part of a general suite
of dependency bumps, this was judged to fit here.
We have linked the changelogs for the packages on each line.
### Summary of Changes
We had an issue with a test being exceedingly flaky. This was a result
of not enough time having passed between the email being put up for
rendering/ being evaluated for skipped status and it being checked.
Polling reduces our dependency on arbitrary timeout periods. This is in
line with how we poll the inbox in other tests (see
`waitForMessagesWithSubject` in `helpers.ts`). It doesn't solve
flakiness because flakiness is a result of the indeterminism of what
we're testing.
Previously, we were using an old version of `freestyle.sh` and
experienced issues with it failing. We want to update it to the latest
API and also introduce a fallback that can be used when freestyle fails
to improve reliability. We refactor the `freestyle.tsx` wrapper code
around `freestyle` to a `js-execution-engine`, which also offers
opportunities to extend the email rendering engine abstraction in the
future. If `freestyle` encounters runtime errors while running the code
or fails, we retry once and then default to `Vercel sandbox`. Note that
we also introduce a sanity test: 5% of the time, we will run the code
through both `freestyle` and the `Vercel Sandbox` and log it if the
results don't match.
As a chore, we also up the time limit on a `failed-email-digest.test.ts`
test to make it less flakey.
## Summary
- Added missing language codes to the `lang` prop type in StackProvider
documentation
- Added: `ja-JP`, `ko-KR`, `zh-CN`, `zh-TW`
## Context
The `quetzal-translations.ts` file already contains translations for
these languages, but the documentation didn't list them as supported
options for the `lang` prop.
This fixes a documentation inconsistency where users couldn't discover
that Japanese, Korean, and Chinese translations are available.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Documentation**
* Added support for Japanese, Korean, Simplified Chinese, and
Traditional Chinese language options in localization settings.
<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Co-authored-by: Madison <madison.w.kennedy@gmail.com>
Previously, the documentation mentioned importing `stackServerApp` from
`stack/client.ts`. This has been updated to reflect where it is actually
imported from.
Co-authored-by: Konsti Wohlwend <n2d4xc@gmail.com>
https://www.loom.com/share/f218c4d16b4d4306be93685aad7aed7a
<!--
Make sure you've read the CONTRIBUTING.md guidelines:
https://github.com/stack-auth/stack-auth/blob/dev/CONTRIBUTING.md
-->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* One-click subscription switching (client + server) and UI dialog to
choose alternative plans
* Products now show available plan alternatives (switch options)
* **Improvements**
* More robust default payment-method handling, validation, and clearer
errors when none is set
* Improved payment-method retrieval and customer metadata persistence
* **Tests**
* End-to-end tests for plan switching and updated billing snapshots
<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<img width="1193" height="827" alt="Screenshot 2026-01-09 at 1 46 38 PM"
src="https://github.com/user-attachments/assets/2703cb15-0be6-4df5-9c79-a45ac514444e"
/>
<img width="1192" height="750" alt="Screenshot 2026-01-09 at 1 49 01 PM"
src="https://github.com/user-attachments/assets/9cfd4936-ed2f-4e4d-a5f9-0c25c87623f1"
/>
<!
--
Make sure you've read the CONTRIBUTING.md guidelines:
https://github.com/stack-auth/stack-auth/blob/dev/CONTRIBUTING.md
-->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Manage and set default payment methods (user & team) via Setup
Intents; Payments page in Account Settings to view/update card and
active plans.
* Product listings now include type (one_time | subscription) and
subscription details (period end, cancelable, cancel-at-period-end).
* Client/SDK: new billing APIs and Customer methods to fetch billing,
create setup intents, and apply default payment methods.
* **Tests**
* New end-to-end tests for billing flows, setup-intent, and access
control.
* **Chores**
* Added Stripe frontend libraries.
<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!--
Make sure you've read the CONTRIBUTING.md guidelines:
https://github.com/stack-auth/stack-auth/blob/dev/CONTRIBUTING.md
-->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved support for legacy Stripe subscription data handling with
fallback mechanisms.
* Enhanced error handling for missing or invalid subscription metadata
to prevent processing failures.
<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
- restricted users
- onboarding app
- waitlist app
- fixed an exception when setting primary email
- automatically update the JWT token on the client when the user object
changes
# Foreign Key Constraint
When deploying Stack Auth with Docker and changing
`STACK_SEED_INTERNAL_PROJECT_USER_INTERNAL_ACCESS` between container
restarts, the seed script fails with:
```ts
PrismaClientKnownRequestError: Invalid prisma.teamMemberDirectPermission.upsert() invocation:
Foreign key constraint violated on the constraint: TeamMemberDirectPermission_tenancyId_projectUserId_teamId_fkey
```
This is a bug in the seed script's idempotency logic. The issue occurs
in `apps/backend/prisma/seed.ts` (lines 296–388):
- When admin credentials are provided, the script checks if the admin
user already exists (line 297–303)
- If the user exists, it skips the user creation block (line 305–306),
which also skips creating the TeamMember record
- However, the `grantTeamPermission()` call at line 382 is outside the
if/else block and always runs
- This tries to create a TeamMemberDirectPermission record, which has a
foreign key constraint to TeamMember
- If the TeamMember doesn't exist (e.g., user was created with
`STACK_SEED_INTERNAL_PROJECT_USER_INTERNAL_ACCESS=false` previously, or
the TeamMember was never created), the foreign key constraint fails.
## How could this happen?
1. Changed `INTERNAL_ACCESS` setting: First run with
`STACK_SEED_INTERNAL_PROJECT_USER_INTERNAL_ACCESS=false` (user created,
no TeamMember), then restarted with `=true`
2. Partial seed failure/interruption: A previous seed run created the
user but failed before creating the TeamMember
3. Manual database modification: TeamMember was deleted but user still
exists.
The most likely scenario would be 1 here:
### Scenario 1:
1. First deployment:
`STACK_SEED_INTERNAL_PROJECT_USER_INTERNAL_ACCESS=false`
- User created ✓
- TeamMember **_NOT_** created(because `adminInternalAccess=false`)
2. Second deployment:
`STACK_SEED_INTERNAL_PROJECT_USER_INTERNAL_ACCESS=true`
- User already exists → Skip creation
- `grantTeamPermission()` called → tries to create
TeamMemberDirectPermission
- **_FAILS_** because TeamMember doesn't exist.
## Solution
Add a `TeamMember` upsert before granting permissions when
`adminInternalAccess` is true:
```ts
if (adminInternalAccess) {
await internalPrisma.teamMember.upsert({
where: {
tenancyId_projectUserId_teamId: {
tenancyId: internalTenancy.id,
projectUserId: defaultUserId,
teamId: internalTeamId,
},
},
create: {
tenancyId: internalTenancy.id,
teamId: internalTeamId,
projectUserId: defaultUserId,
},
update: {},
});
}
```
This ensures the `TeamMember` record exists before
`grantTeamPermission() is called, regardless of whether the user was
just created or already existed.
## Impact
- Existing deployments: No impact. If `TeamMember` already exists, the
upsert does nothing.
- New deployment: Works correctly.
- Broken deployments: This fix will repair them on the next container
restart.
## Testing
Tested by building a local Docker image and running the reproduction
script that:
- Starts with `INTERNAL_ACCESS=false`
- Restarts with `INTERNAL_ACCESS=true`
- verifies no foreign key constraint error occurs.
---
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Made permission grants resilient to repeated seed runs by ensuring
grants only apply when appropriate admin access is present.
* Prevented duplicate team member entries during setup by making member
creation idempotent, so repeated runs no longer create or alter existing
records.
<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->