Skip to content

Commit 39099af

Browse files
committed
merge dev
2 parents 9f501c8 + 2e1634e commit 39099af

73 files changed

Lines changed: 6743 additions & 1635 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/CLAUDE-KNOWLEDGE.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,9 +178,9 @@ const [result1, result2] = await Promise.all([
178178
```
179179

180180
### Q: What's the correct way to update project configuration in E2E tests?
181-
A: Use the `/api/v1/internal/config/override` endpoint with PATCH method and admin access token:
181+
A: Use the `/api/v1/internal/config/override/environment` endpoint with PATCH method and admin access token:
182182
```typescript
183-
await niceBackendFetch("/api/v1/internal/config/override", {
183+
await niceBackendFetch("/api/v1/internal/config/override/environment", {
184184
method: "PATCH",
185185
accessType: "admin",
186186
headers: {

.github/workflows/db-migration-backwards-compatibility.yaml

Lines changed: 42 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
1-
name: DB migrations are backwards-compatible with main branch
1+
name: DB migrations are backwards-compatible
22

33
on:
44
push:
5-
branches:
5+
branches-ignore:
66
- main
7-
- dev
87
pull_request:
98

109
concurrency:
1110
group: ${{ github.workflow }}-${{ github.ref }}
12-
cancel-in-progress: ${{ github.ref != 'refs/heads/main' && github.ref != 'refs/heads/dev' }}
11+
cancel-in-progress: ${{ github.ref != 'refs/heads/dev' }}
1312

1413
jobs:
1514
check-migrations-changed:
1615
name: Check if migrations changed
1716
runs-on: ubuntu-latest
1817
outputs:
1918
migrations_changed: ${{ steps.check-diff.outputs.migrations_changed }}
19+
base_branch: ${{ steps.check-diff.outputs.base_branch }}
2020
steps:
2121
- name: Checkout current branch
2222
uses: actions/checkout@v6
@@ -26,9 +26,17 @@ jobs:
2626
- name: Check for migration changes
2727
id: check-diff
2828
run: |
29-
# Get the merge base with main
30-
git fetch origin main
31-
MERGE_BASE=$(git merge-base HEAD origin/main)
29+
# Determine base branch: dev compares to main, all others compare to dev
30+
if [ "${{ github.ref }}" = "refs/heads/dev" ]; then
31+
BASE_BRANCH="main"
32+
else
33+
BASE_BRANCH="dev"
34+
fi
35+
echo "base_branch=$BASE_BRANCH" >> $GITHUB_OUTPUT
36+
37+
# Get the merge base with the base branch
38+
git fetch origin $BASE_BRANCH
39+
MERGE_BASE=$(git merge-base HEAD origin/$BASE_BRANCH)
3240
3341
# Check if there are any changes in the migrations folder
3442
if git diff --quiet "$MERGE_BASE" HEAD -- apps/backend/prisma/migrations/; then
@@ -40,7 +48,7 @@ jobs:
4048
fi
4149
4250
backwards-compatibility:
43-
name: Test migrations with main branch code
51+
name: Test migrations with ${{ needs.check-migrations-changed.outputs.base_branch }} branch code
4452
needs: check-migrations-changed
4553
if: needs.check-migrations-changed.outputs.migrations_changed == 'true'
4654
runs-on: ubicloud-standard-8
@@ -62,25 +70,19 @@ jobs:
6270
mkdir -p saved-migrations
6371
cp -r current-branch/apps/backend/prisma/migrations/* saved-migrations/
6472
65-
# Now checkout main branch
66-
- name: Checkout main branch
73+
# Now checkout base branch (main for dev, dev for all others)
74+
- name: Checkout base branch
6775
uses: actions/checkout@v6
6876
with:
69-
ref: main
70-
path: main-branch
77+
ref: ${{ needs.check-migrations-changed.outputs.base_branch }}
78+
path: base-branch
7179

72-
# Replace main's migrations with current branch's migrations
73-
- name: Replace migrations with current branch migrations
74-
run: |
75-
rm -rf main-branch/apps/backend/prisma/migrations/*
76-
cp -r saved-migrations/* main-branch/apps/backend/prisma/migrations/
77-
78-
# Move main-branch to the root for the rest of the workflow
80+
# Move base-branch to the root for the rest of the workflow (keep base's migrations for now)
7981
- name: Setup working directory
8082
run: |
8183
shopt -s dotglob
82-
mv main-branch/* .
83-
rm -rf main-branch current-branch saved-migrations
84+
mv base-branch/* .
85+
rm -rf base-branch current-branch
8486
8587
- name: Setup Node.js
8688
uses: actions/setup-node@v6
@@ -194,9 +196,27 @@ jobs:
194196
- name: Wait 10 seconds
195197
run: sleep 10
196198

197-
- name: Run tests
199+
# First test run: base branch with base's migrations
200+
- name: Run tests (base branch with original migrations)
198201
run: pnpm test
199202

203+
# Now copy over current branch's migrations and run migrate
204+
- name: Replace migrations with current branch migrations
205+
run: |
206+
rm -rf apps/backend/prisma/migrations/*
207+
cp -r saved-migrations/* apps/backend/prisma/migrations/
208+
rm -rf saved-migrations
209+
210+
- name: Run database migrations
211+
run: pnpm run db:migrate
212+
213+
# Second test run: base branch code with new migrations applied
214+
- name: Run tests (base branch with new migrations)
215+
run: pnpm test
216+
217+
- name: Verify data integrity
218+
run: pnpm run verify-data-integrity
219+
200220
- name: Print Docker Compose logs
201221
if: always()
202222
run: docker compose -f docker/dependencies/docker.compose.yaml logs

.vscode/settings.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"typescript.tsdk": "node_modules/typescript/lib",
88
"editor.tabSize": 2,
99
"cSpell.words": [
10+
"pushable",
1011
"autoupdate",
1112
"backlinks",
1213
"Cancelation",

AGENTS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,15 @@ To see all development ports, refer to the index.html of `apps/dev-launchpad/pub
8383
- NEVER try-catch-all, NEVER void a promise, and NEVER .catch(console.error) (or similar). In most cases you don't actually need to be asynchronous, especially when UI is involved (instead, use a loading indicator! eg. our <Button> component already takes an async callback for onClick and sets its loading state accordingly — if whatever component doesn't do that, update the component instead). If you really do need things to be asynchronous, use `runAsynchronously` or `runAsynchronouslyWithAlert` instead as it deals with error logging.
8484
- WHENEVER you create hover transitions, avoid hover-enter transitions, and just use hover-exit transitions. For example, `transition-colors hover:transition-none`.
8585
- Any environment variables you create should be prefixed with `STACK_` (or NEXT_PUBLIC_STACK_ if they are public). This ensures that their changes are picked up by Turborepo (and helps readability).
86+
- NEVER just silently use fallback values or whatever when you don't know how to fix type errors. If there is a state that should never happen because of higher-level logic, and the type system doesn't represent that, either update the types or throw an error. Stuff like `?? 0` or `?? ""` is often code smell when `?? throwErr("this should never happen because XYZ")` would be better.
8687
- Code defensively. Prefer `?? throwErr(...)` over non-null assertions, with good error messages explicitly stating the assumption that must've been violated for the error to be thrown.
8788
- Try to avoid the `any` type. Whenever you need to use `any`, leave a comment explaining why you're using it (optimally it explains why the type system fails here, and how you can be certain that any errors in that code path would still be flagged at compile-, test-, or runtime).
8889
- Don't use Date.now() for measuring elapsed (real) time, instead use `performance.now()`
8990
- Use urlString`` or encodeURIComponent() instead of normal string interpolation for URLs, for consistency even if it's not strictly necessary.
9091
- When making config updates, use path notation (`{ "path.to.field": my-value }`) to avoid overwriting sibling properties
9192
- IMPORTANT: Any assumption you make should either be validated through type system (preferred), assertions, or tests. Optimally, two out of three.
9293
- If there is an external browser tool connected, use it to test changes you make to the frontend when possible.
94+
- Whenever you update an SDK implementation in `sdks/implementations`, make sure to update the specs accordingly in `sdks/specs` such that if you reimplemented the entire SDK from the specs again, you would get the same implementation. (For example, if the specs are not precise enough to describe a change you made, make the specs more precise.)
9395

9496
### Code-related
9597
- Use ES6 maps instead of records wherever you can.

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,17 @@
22

33
---
44

5+
## 2026.01.21
6+
7+
### Payments
8+
- Payments page updated with new UI changes
9+
- Added a new Payments Settings page with an option to temporarily disable all payments
10+
- Subscription renewal emails are now sent automatically to users
11+
- Past payment invoices are now visible on the Account Settings page
12+
13+
### Documentation
14+
- Updated JWT documentation to include `isRestricted` and `restrictedReason`
15+
516
## 2026.01.19
617
- Updated package dependencies to their newest versions.
718

CONTRIBUTING.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,9 @@ For vibecoding, it can help to have multiple parallel copies of the codebase ope
4343
```sh
4444
# ~/.bash_profile, ~/.bashrc, ~/.zprofile, ~/.zshrc, ~/.zshenv, etc.
4545
# note that different coding agents use a different shell in a different mode (login, non-login, interactive, non-interactive, etc.); from my experimentation, as of 2025-10-17 on a Mac, Cursor uses non-interactive zsh (requiring ~/.zshenv), whereas Codex uses a non-interactive login bash (requiring ~/.bash_profile). It's easiest to just add these lines of code to all of your shell configs.
46-
eval "$(direnv hook <bash|zsh>)"
47-
eval "$(direnv export <bash|zsh>)"
46+
# also, make sure to use the correct path to the direnv binary; for example, on a Mac with Homebrew installed, it is /opt/homebrew/bin/direnv
47+
eval "$(/path/to/direnv hook <bash|zsh>)"
48+
eval "$(/path/to/direnv export <bash|zsh>)"
4849
```
4950
3. Now, create a `.envrc` file in the root of Stack Auth's codebase with the following content:
5051
```sh
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
-- CreateTable
2+
CREATE TABLE "BranchConfigOverride" (
3+
"projectId" TEXT NOT NULL,
4+
"branchId" TEXT NOT NULL,
5+
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
6+
"updatedAt" TIMESTAMP(3) NOT NULL,
7+
"config" JSONB NOT NULL,
8+
9+
CONSTRAINT "BranchConfigOverride_pkey" PRIMARY KEY ("projectId","branchId")
10+
);
11+
12+
-- AddForeignKey
13+
ALTER TABLE "BranchConfigOverride" ADD CONSTRAINT "BranchConfigOverride_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE CASCADE ON UPDATE CASCADE;
14+
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
-- Migration to set testMode to true for existing environment config overrides
2+
-- This is needed because testMode default is changing from true to false,
3+
-- and we want existing projects to retain their current behavior.
4+
--
5+
-- The config can store testMode in two ways:
6+
-- 1. Top-level key: "payments.testMode": true
7+
-- 2. Nested syntax: "payments": { "testMode": true }
8+
--
9+
-- We need to set testMode to true only if it's not already set in either form.
10+
11+
-- Create temporary index to speed up the migration
12+
-- SPLIT_STATEMENT_SENTINEL
13+
-- SINGLE_STATEMENT_SENTINEL
14+
-- RUN_OUTSIDE_TRANSACTION_SENTINEL
15+
CREATE INDEX CONCURRENTLY IF NOT EXISTS "temp_eco_testmode_idx" ON /* SCHEMA_NAME_SENTINEL */."EnvironmentConfigOverride" USING GIN ("config");
16+
-- SPLIT_STATEMENT_SENTINEL
17+
18+
-- SPLIT_STATEMENT_SENTINEL
19+
-- SINGLE_STATEMENT_SENTINEL
20+
-- CONDITIONALLY_REPEAT_MIGRATION_SENTINEL
21+
WITH to_update AS (
22+
SELECT "projectId", "branchId", "config"
23+
FROM "EnvironmentConfigOverride"
24+
WHERE NOT "config" ? 'payments.testMode'
25+
AND NOT ("config" ? 'payments' AND ("config" -> 'payments') ? 'testMode')
26+
LIMIT 10000
27+
)
28+
UPDATE "EnvironmentConfigOverride" eco
29+
SET "config" = jsonb_set(
30+
COALESCE(eco."config", '{}'::jsonb),
31+
'{payments.testMode}',
32+
'true'::jsonb,
33+
true
34+
)
35+
FROM to_update
36+
WHERE eco."projectId" = to_update."projectId"
37+
AND eco."branchId" = to_update."branchId"
38+
RETURNING true AS should_repeat_migration;
39+
-- SPLIT_STATEMENT_SENTINEL
40+
41+
-- Clean up temporary index
42+
DROP INDEX IF EXISTS "temp_eco_testmode_idx";
43+
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
-- Add source column to BranchConfigOverride
2+
-- This tracks where the branch config was pushed from (GitHub, CLI, or dashboard)
3+
ALTER TABLE "BranchConfigOverride" ADD COLUMN "source" JSONB;
4+
5+
-- Set existing rows to unlinked source (they were configured before source tracking existed)
6+
UPDATE "BranchConfigOverride" SET "source" = '{"type": "unlinked"}' WHERE "source" IS NULL;
7+

0 commit comments

Comments
 (0)