Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
95 commits
Select commit Hold shift + click to select a range
9e41309
added external-db-sync
aadesh18 Nov 30, 2025
3879001
stopped using yupArray
aadesh18 Nov 30, 2025
937db90
fixed build errors
aadesh18 Nov 30, 2025
3f2a8ef
Revert "fixed build errors"
aadesh18 Nov 30, 2025
dcda402
Update apps/backend/scripts/run-cron-jobs.ts
aadesh18 Dec 1, 2025
9e954b9
Update apps/backend/src/app/api/latest/internal/external-db-sync/poll…
aadesh18 Dec 1, 2025
f0cc311
Update apps/backend/src/app/api/latest/internal/external-db-sync/poll…
aadesh18 Dec 1, 2025
1d7a0de
pr changes
aadesh18 Dec 2, 2025
8c2d1c3
merge dev
BilalG1 Jan 28, 2026
409d89b
Merge remote-tracking branch 'origin/dev' into external-db-sync
BilalG1 Jan 29, 2026
0d2b3b9
fix pnpm lock
BilalG1 Jan 29, 2026
ef8f74e
fix typecheck
BilalG1 Jan 29, 2026
8cdd107
prisma fix
BilalG1 Jan 29, 2026
871fe12
fix tests
BilalG1 Jan 29, 2026
5d6bde2
fix lint
BilalG1 Jan 29, 2026
c4ed09a
fix
BilalG1 Jan 29, 2026
b102db3
fix tests
BilalG1 Jan 29, 2026
2eeb537
fix tests
BilalG1 Jan 29, 2026
c61a2b9
fix test
BilalG1 Jan 30, 2026
ac261d2
increase session test time
BilalG1 Jan 30, 2026
0c1a02e
fix flaky test and external sot sync
BilalG1 Jan 30, 2026
79e330f
comment resolving
BilalG1 Jan 30, 2026
939b1a9
resolve pr comments
BilalG1 Jan 30, 2026
2974c83
retry
BilalG1 Jan 30, 2026
0799a0b
attempt test fixes
BilalG1 Jan 30, 2026
1f67742
fix env
BilalG1 Jan 30, 2026
bd788b4
fix env
BilalG1 Jan 30, 2026
4b7dd53
attempt test fixes
BilalG1 Jan 30, 2026
044377e
fix tests
BilalG1 Jan 30, 2026
744b871
Merge branch 'dev' into external-db-sync
BilalG1 Jan 30, 2026
74c634b
fix lint
BilalG1 Jan 30, 2026
ce5a1bb
fix tests
BilalG1 Jan 30, 2026
2c5440b
fix tests
BilalG1 Jan 30, 2026
f726f61
Merge remote-tracking branch 'origin/dev' into external-db-sync
BilalG1 Jan 31, 2026
665c084
fix tests
BilalG1 Jan 31, 2026
85bb893
Merge branch 'dev' into external-db-sync
BilalG1 Jan 31, 2026
856aaf3
fix tests
BilalG1 Jan 31, 2026
8f3ad45
m
BilalG1 Jan 31, 2026
fe393e9
merge dev
BilalG1 Feb 2, 2026
b9c0ef4
fix lockfile
BilalG1 Feb 2, 2026
b5781a1
Merge remote-tracking branch 'origin/dev' into external-db-sync
BilalG1 Feb 2, 2026
b841f7b
fix tests
BilalG1 Feb 2, 2026
2e0d8de
m
BilalG1 Feb 2, 2026
e5cbc1a
Merge branch 'dev' into external-db-sync
BilalG1 Feb 2, 2026
ba1df26
fix tests
BilalG1 Feb 2, 2026
093eaf0
e2e: isolate external DB sync cleanup per suite (#1148)
BilalG1 Feb 3, 2026
5192875
CI: run dev tests single-worker (#1153)
BilalG1 Feb 3, 2026
686a1e6
Merge branch 'dev' into external-db-sync
BilalG1 Feb 3, 2026
8910138
fixes
BilalG1 Feb 3, 2026
62171dc
single test run
BilalG1 Feb 3, 2026
1038d1a
Merge branch 'dev' into external-db-sync
BilalG1 Feb 3, 2026
3370e63
test fixes (#1155)
BilalG1 Feb 3, 2026
d04e944
concurrent fix
BilalG1 Feb 3, 2026
61f2b79
Merge branch 'external-db-sync' of https://github.com/stack-auth/stac…
BilalG1 Feb 3, 2026
bbac70e
Merge branch 'dev' into external-db-sync
BilalG1 Feb 3, 2026
8e92205
fix routes, external-db dashboard
BilalG1 Feb 4, 2026
3b9c22e
merge dev
BilalG1 Feb 4, 2026
c0a3f7a
replace trigger
BilalG1 Feb 4, 2026
d34a2c7
fusebox
BilalG1 Feb 4, 2026
c91998e
add tracing
BilalG1 Feb 4, 2026
64d9d93
remove old tests
BilalG1 Feb 4, 2026
7fd7886
fix sot test
BilalG1 Feb 4, 2026
719d1c2
Merge remote-tracking branch 'origin/dev' into external-db-sync
BilalG1 Feb 4, 2026
43c1f15
clickhouse user sync
BilalG1 Feb 4, 2026
04970c2
Update vercel.json
N2D4 Feb 4, 2026
4abd410
Various fixes
N2D4 Feb 4, 2026
8247481
test: disable direct external db sync in CI
BilalG1 Feb 5, 2026
362e1fb
merge dev
BilalG1 Feb 5, 2026
98d451d
increase test timeout
BilalG1 Feb 5, 2026
6b89370
cmd k query analytics (#1160)
BilalG1 Feb 5, 2026
ff370b6
Merge branch 'external-db-sync' into external-db-sync-clickhouse-default
BilalG1 Feb 5, 2026
8be639d
Merge branch 'dev' into external-db-sync
BilalG1 Feb 5, 2026
caa3dca
remove fusebox sync engine col
BilalG1 Feb 5, 2026
445e889
Merge branch 'external-db-sync' of https://github.com/stack-auth/stac…
BilalG1 Feb 5, 2026
63df87a
fix test
BilalG1 Feb 5, 2026
9c340f4
Merge branch 'external-db-sync' into external-db-sync-clickhouse-default
BilalG1 Feb 5, 2026
45e7d2d
merge dev
BilalG1 Feb 5, 2026
925a865
fix zod version
BilalG1 Feb 5, 2026
b83063c
move test
BilalG1 Feb 5, 2026
b673ab5
fix lint
BilalG1 Feb 5, 2026
fcf493e
Merge branch 'dev' into external-db-sync-clickhouse-default
BilalG1 Feb 6, 2026
8534caa
Merge branch 'dev' into external-db-sync-clickhouse-default
BilalG1 Feb 9, 2026
2f7acb4
Add STACK_OPENAI_API_KEY to .env.development
N2D4 Feb 10, 2026
cf5558e
pr comment fixes
BilalG1 Feb 12, 2026
4ab4be8
merge dev
BilalG1 Feb 12, 2026
1421461
Add TEST_TIMEOUT to ClickHouse sync tests
BilalG1 Feb 12, 2026
90eb9ae
Merge branch 'dev' into external-db-sync-clickhouse-default
BilalG1 Feb 12, 2026
afa76be
token refresh event change (#1162)
BilalG1 Feb 12, 2026
a509be3
fix type issue
BilalG1 Feb 12, 2026
02b6ef6
Merge branch 'dev' into external-db-sync-clickhouse-default
BilalG1 Feb 12, 2026
62d054e
fix tests
BilalG1 Feb 12, 2026
558d0f6
Merge branch 'external-db-sync-clickhouse-default' of https://github.…
BilalG1 Feb 12, 2026
0dc2e94
fix clickhouse needsResync
BilalG1 Feb 12, 2026
3db832e
Increase ClickHouse poll interval from 500ms to 2s
BilalG1 Feb 12, 2026
3cde6fa
fix test ordering
BilalG1 Feb 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
178 changes: 0 additions & 178 deletions .github/workflows/e2e-source-of-truth-api-tests.yaml

This file was deleted.

3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -174,5 +174,6 @@
"((?:<!-- *)?(?:#|// @|//|./\\*+|<!--|--|\\* @|{!|{{!--|{{!) *(?:IDEA)(?:\\s*\\([^)]+\\))?:?)((?!\\w)(?: *-->| *\\*/| *!}| *--}}| *}}|(?= *(?:[^:]//|/\\*+|<!--|@|--|{!|{{!--|{{!))|(?: +[^\\n@]*?)(?= *(?:[^:]//|/\\*+|<!--|@|--(?!>)|{!|{{!--|{{!))|(?: +[^@\\n]+)?))": [],
},
"editor.formatOnSaveMode": "file",
"git.ignoreLimitWarning": true
"git.ignoreLimitWarning": true,
"chatgpt.commentCodeLensEnabled": false
}
103 changes: 103 additions & 0 deletions apps/backend/scripts/clickhouse-migrations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,24 @@ export async function runClickhouseMigrations() {
});
// todo: create migration files
await client.exec({ query: EXTERNAL_ANALYTICS_DB_SQL });
await client.exec({ query: SYNC_METADATA_TABLE_SQL });
await client.exec({ query: EVENTS_TABLE_BASE_SQL });
await client.exec({ query: EVENTS_VIEW_SQL });
await client.exec({ query: USERS_TABLE_BASE_SQL });
await client.exec({ query: USERS_VIEW_SQL });
await client.exec({ query: TOKEN_REFRESH_EVENT_ROW_FORMAT_MUTATION_SQL });
const queries = [
"REVOKE ALL PRIVILEGES ON *.* FROM limited_user;",
"REVOKE ALL FROM limited_user;",
"GRANT SELECT ON default.events TO limited_user;",
"GRANT SELECT ON default.users TO limited_user;",
];
await client.exec({
query: "CREATE ROW POLICY IF NOT EXISTS events_project_isolation ON default.events FOR SELECT USING project_id = getSetting('SQL_project_id') AND branch_id = getSetting('SQL_branch_id') TO limited_user",
});
await client.exec({
query: "CREATE ROW POLICY IF NOT EXISTS users_project_isolation ON default.users FOR SELECT USING project_id = getSetting('SQL_project_id') AND branch_id = getSetting('SQL_branch_id') TO limited_user",
});
for (const query of queries) {
await client.exec({ query });
}
Expand Down Expand Up @@ -52,6 +60,101 @@ SELECT *
FROM analytics_internal.events;
`;

// Normalizes legacy $token-refresh rows (camelCase JSON) to the new format:
// - Row identity stays in columns (project_id/branch_id/user_id)
// - data JSON becomes { refresh_token_id, is_anonymous, ip_info } (snake_case)
// Assumption: all legacy rows have the camelCase format.
const TOKEN_REFRESH_EVENT_ROW_FORMAT_MUTATION_SQL = `
ALTER TABLE analytics_internal.events
UPDATE
data = CAST(concat(
'{',
'\"refresh_token_id\":', toJSONString(JSONExtractString(toJSONString(data), 'refreshTokenId')), ',',
'\"is_anonymous\":', toJSONString(JSONExtract(toJSONString(data), 'isAnonymous', 'Bool')), ',',
'\"ip_info\":', if(
JSONExtractString(toJSONString(data), 'ipInfo.ip') = '',
'null',
concat(
'{',
'\"ip\":', toJSONString(JSONExtractString(toJSONString(data), 'ipInfo.ip')), ',',
'\"is_trusted\":', toJSONString(JSONExtract(toJSONString(data), 'ipInfo.isTrusted', 'Bool')), ',',
'\"country_code\":', toJSONString(JSONExtract(toJSONString(data), 'ipInfo.countryCode', 'Nullable(String)')), ',',
'\"region_code\":', toJSONString(JSONExtract(toJSONString(data), 'ipInfo.regionCode', 'Nullable(String)')), ',',
'\"city_name\":', toJSONString(JSONExtract(toJSONString(data), 'ipInfo.cityName', 'Nullable(String)')), ',',
'\"latitude\":', toJSONString(JSONExtract(toJSONString(data), 'ipInfo.latitude', 'Nullable(Float64)')), ',',
'\"longitude\":', toJSONString(JSONExtract(toJSONString(data), 'ipInfo.longitude', 'Nullable(Float64)')), ',',
'\"tz_identifier\":', toJSONString(JSONExtract(toJSONString(data), 'ipInfo.tzIdentifier', 'Nullable(String)')),
'}'
)
),
'}'
) AS JSON)
WHERE event_type = '$token-refresh'
AND JSONHas(toJSONString(data), 'refreshTokenId');
`;

const USERS_TABLE_BASE_SQL = `
CREATE TABLE IF NOT EXISTS analytics_internal.users (
project_id String,
branch_id String,
id UUID,
display_name Nullable(String),
profile_image_url Nullable(String),
primary_email Nullable(String),
primary_email_verified UInt8,
signed_up_at DateTime64(3, 'UTC'),
client_metadata JSON,
client_read_only_metadata JSON,
server_metadata JSON,
is_anonymous UInt8,
Comment thread
BilalG1 marked this conversation as resolved.
restricted_by_admin UInt8,
restricted_by_admin_reason Nullable(String),
restricted_by_admin_private_details Nullable(String),
sync_sequence_id Int64,
sync_is_deleted UInt8,
sync_created_at DateTime64(3, 'UTC') DEFAULT now64(3)
)
ENGINE ReplacingMergeTree(sync_sequence_id)
PARTITION BY toYYYYMM(signed_up_at)
ORDER BY (project_id, branch_id, id);
`;

const USERS_VIEW_SQL = `
CREATE OR REPLACE VIEW default.users
SQL SECURITY DEFINER
AS
SELECT
project_id,
branch_id,
id,
display_name,
profile_image_url,
primary_email,
primary_email_verified,
signed_up_at,
client_metadata,
client_read_only_metadata,
server_metadata,
is_anonymous,
restricted_by_admin,
restricted_by_admin_reason,
restricted_by_admin_private_details
FROM analytics_internal.users
FINAL
WHERE sync_is_deleted = 0;
`;

const SYNC_METADATA_TABLE_SQL = `
CREATE TABLE IF NOT EXISTS analytics_internal._stack_sync_metadata (
tenancy_id UUID,
mapping_name String,
last_synced_sequence_id Int64,
updated_at DateTime64(3, 'UTC') DEFAULT now64(3)
)
ENGINE ReplacingMergeTree(updated_at)
ORDER BY (tenancy_id, mapping_name);
`;

const EXTERNAL_ANALYTICS_DB_SQL = `
CREATE DATABASE IF NOT EXISTS analytics_internal;
`;
Loading
Loading