- 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 -->
<img width="1299" height="967" alt="Screenshot 2025-12-12 at 5 26 23 PM"
src="https://github.com/user-attachments/assets/5a33482a-510c-464c-a770-e71222ffc336"
/>
<!--
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 "Payouts" section to the Payments dashboard with a dedicated
page and navigation link.
* Integrated a Stripe Connect payouts UI, allowing users to manage and
configure payout options (instant payouts, standard payouts, edit payout
schedule, external account collection).
* **Chores**
* Internal module path updates (no user-facing behavior changes).
<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
* **Documentation**
* ~~Consolidated all release notes into a single root changelog as the
authoritative source for all changes~~
* ~~Updated individual package changelogs with deprecation notices
directing users to the root changelog~~
* Removes all changelog.md files from each app/package and consolidates
into root changelog.app.
* **Chores**
* ~~Updated build directory exclusions~~
<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->