Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughAdds ClickHouse integration: infra and CI updates, client library and utilities, migrations, dual-write event logging, admin analytics query and backfill APIs, dashboard query/migration UIs, types/interfaces, E2E tests, and two analytics-specific KnownErrors. Changes
Sequence Diagram(s)sequenceDiagram
actor User
participant Dashboard as "Dashboard (React)"
participant Backend as "Backend API"
participant ClickHouse as "ClickHouse"
participant QueryLog as "system.query_log"
User->>Dashboard: Run SQL query (query, params, timeout_ms)
Dashboard->>Backend: POST /internal/analytics/query
Backend->>Backend: Authenticate (admin), generate query_id
Backend->>ClickHouse: Execute parameterized query (scoped settings, limits)
ClickHouse-->>Backend: JSON result rows
Backend->>ClickHouse: SYSTEM FLUSH LOGS
Backend->>QueryLog: SELECT cpu_time_ms, wall_clock_time_ms WHERE query_id=...
QueryLog-->>Backend: timing stats
Backend-->>Dashboard: { result, timing }
Dashboard->>User: Display results + timing
sequenceDiagram
actor User
participant Dashboard as "Migration UI"
participant Backend as "Backend API"
participant Postgres as "Postgres"
participant ClickHouse as "ClickHouse"
User->>Dashboard: Start migration (min,max,cursor,limit)
loop per batch
Dashboard->>Backend: POST /internal/clickhouse/migrate-events
Backend->>Postgres: SELECT events WHERE created_at BETWEEN range ORDER BY created_at,id LIMIT N
Postgres-->>Backend: rows
Backend->>Backend: Transform rows → ClickHouse JSONEachRow
Backend->>ClickHouse: INSERT INTO analytics_internal.events (JSONEachRow, async_insert)
ClickHouse-->>Backend: insert ack
Backend-->>Dashboard: { processed_events, inserted_rows, progress, next_cursor }
Dashboard->>User: Update progress
end
Dashboard->>User: Migration complete
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Greptile OverviewGreptile SummaryThis PR establishes the foundational ClickHouse integration for analytics, adding database infrastructure, client library, API endpoint, and comprehensive security controls. Major Changes:
Issues Found:
Confidence Score: 2/5
Important Files ChangedFile Analysis
Sequence DiagramsequenceDiagram
participant Client
participant AnalyticsAPI
participant ClickHouse
participant AdminConnection
Client->>AnalyticsAPI: POST analytics query
AnalyticsAPI->>ClickHouse: Execute with limited user
alt Success
ClickHouse-->>AnalyticsAPI: Result data
AnalyticsAPI->>AdminConnection: Get timing stats
AdminConnection-->>AnalyticsAPI: Stats
AnalyticsAPI-->>Client: Result with stats
else Timeout or Error
ClickHouse-->>AnalyticsAPI: Error
AnalyticsAPI-->>Client: Error response
end
|
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Nitpick comments (3)
apps/backend/scripts/clickhouse-migrations.ts (1)
9-12: Using plaintext password authentication.While
plaintext_passwordis acceptable for development environments, consider documenting this choice or usingsha256_passwordfor better security practices.Example with SHA256:
import { createHash } from 'crypto'; const passwordHash = createHash('sha256') .update(clickhouseExternalPassword) .digest('hex'); await client.exec({ query: "CREATE USER IF NOT EXISTS limited_user IDENTIFIED WITH sha256_password BY {passwordHash:String}", query_params: { passwordHash }, });apps/e2e/tests/backend/endpoints/api/v1/analytics-query.test.ts (2)
1-29: Good test coverage for basic query execution.The tests appropriately use inline snapshots as per coding guidelines. Consider adding a negative test case verifying that
clientaccessType is rejected, since the route requiresserverOrHigherAuthTypeSchema.
274-387: Security tests are comprehensive.Good coverage of dangerous operations (CREATE TABLE, system tables, KILL QUERY, INSERT). Note that error messages expose the internal username
limited_user- consider whether this level of detail should be sanitized in the route handler before returning to clients.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (11)
apps/backend/.env.development(1 hunks)apps/backend/package.json(1 hunks)apps/backend/scripts/clickhouse-migrations.ts(1 hunks)apps/backend/scripts/db-migrations.ts(2 hunks)apps/backend/src/app/api/latest/analytics/query/route.tsx(1 hunks)apps/backend/src/lib/clickhouse.tsx(1 hunks)apps/dev-launchpad/public/index.html(2 hunks)apps/e2e/tests/backend/endpoints/api/v1/analytics-query.test.ts(1 hunks)apps/e2e/tests/snapshot-serializer.ts(1 hunks)docker/dependencies/docker.compose.yaml(2 hunks)packages/stack-shared/src/known-errors.tsx(2 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Ensure code passespnpm typecheckfor TypeScript type validation
Never usetoastfor blocking alerts and errors; use alerts instead as they are more visible to users
Keep hover/click transitions snappy and fast; apply transitions after the action (e.g., smooth fade-out on hover end) rather than delaying actions with pre-transitions to avoid sluggish UI
Never use try-catch-all, never void a promise, never use .catch(console.error) or similar; userunAsynchronouslyorrunAsynchronouslyWithAlertfor error handling instead of try-catch blocks
Use loading indicators instead of try-catch blocks for asynchronous UI operations; button components like support async callbacks with built-in loading state
Use ES6 maps instead of records wherever possible
Files:
apps/backend/scripts/clickhouse-migrations.tsapps/e2e/tests/backend/endpoints/api/v1/analytics-query.test.tsapps/e2e/tests/snapshot-serializer.tsapps/backend/src/app/api/latest/analytics/query/route.tsxapps/backend/src/lib/clickhouse.tsxpackages/stack-shared/src/known-errors.tsxapps/backend/scripts/db-migrations.ts
apps/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Prefer client components and dynamic functions like
usePathnameover Next.js dynamic functions to keep pages static; avoid usingawait paramsor similar dynamic patterns
Files:
apps/backend/scripts/clickhouse-migrations.tsapps/e2e/tests/backend/endpoints/api/v1/analytics-query.test.tsapps/e2e/tests/snapshot-serializer.tsapps/backend/src/app/api/latest/analytics/query/route.tsxapps/backend/src/lib/clickhouse.tsxapps/backend/scripts/db-migrations.ts
apps/e2e/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Always add new E2E tests when you change the API or SDK interface
Files:
apps/e2e/tests/backend/endpoints/api/v1/analytics-query.test.tsapps/e2e/tests/snapshot-serializer.ts
**/*.{test,spec}.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{test,spec}.{ts,tsx}: Run all tests usingpnpm test run; run specific tests usingpnpm test run <file-filters>with Vitest
Use.toMatchInlineSnapshotfor test assertions instead of other selectors when possible; check snapshot-serializer.ts for formatting and non-deterministic value handling
Files:
apps/e2e/tests/backend/endpoints/api/v1/analytics-query.test.ts
apps/backend/src/app/api/latest/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
In the Stack Auth monorepo backend API, organize routes by resource type (auth, user management, team management, OAuth providers) in
/apps/backend/src/app/api/latest/*
Files:
apps/backend/src/app/api/latest/analytics/query/route.tsx
🧠 Learnings (4)
📚 Learning: 2025-11-25T02:09:03.104Z
Learnt from: CR
Repo: stack-auth/stack-auth PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T02:09:03.104Z
Learning: Applies to packages/stack-shared/src/config/** : When making backwards-incompatible changes to the config schema, update the migration functions in `packages/stack-shared/src/config/schema.ts`
Applied to files:
apps/backend/scripts/clickhouse-migrations.tsapps/backend/scripts/db-migrations.ts
📚 Learning: 2025-11-25T02:09:03.104Z
Learnt from: CR
Repo: stack-auth/stack-auth PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T02:09:03.104Z
Learning: Applies to apps/e2e/**/*.{ts,tsx} : Always add new E2E tests when you change the API or SDK interface
Applied to files:
apps/e2e/tests/backend/endpoints/api/v1/analytics-query.test.ts
📚 Learning: 2025-11-25T02:09:03.104Z
Learnt from: CR
Repo: stack-auth/stack-auth PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T02:09:03.104Z
Learning: Applies to **/*.{test,spec}.{ts,tsx} : Use `.toMatchInlineSnapshot` for test assertions instead of other selectors when possible; check snapshot-serializer.ts for formatting and non-deterministic value handling
Applied to files:
apps/e2e/tests/snapshot-serializer.ts
📚 Learning: 2025-11-25T02:09:03.104Z
Learnt from: CR
Repo: stack-auth/stack-auth PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T02:09:03.104Z
Learning: Applies to apps/backend/src/app/api/latest/**/*.{ts,tsx} : In the Stack Auth monorepo backend API, organize routes by resource type (auth, user management, team management, OAuth providers) in `/apps/backend/src/app/api/latest/*`
Applied to files:
apps/backend/src/app/api/latest/analytics/query/route.tsx
🧬 Code graph analysis (3)
apps/backend/scripts/clickhouse-migrations.ts (2)
apps/backend/src/lib/clickhouse.tsx (1)
createClickhouseClient(11-19)packages/stack-shared/src/utils/env.tsx (1)
getEnvVariable(16-58)
packages/stack-shared/src/known-errors.tsx (2)
packages/stack-shared/src/index.ts (1)
KnownError(14-14)packages/stack-shared/src/utils/results.tsx (1)
error(36-41)
apps/backend/scripts/db-migrations.ts (1)
apps/backend/scripts/clickhouse-migrations.ts (1)
runClickhouseMigrations(4-24)
🪛 dotenv-linter (4.0.0)
apps/backend/.env.development
[warning] 75-75: [SubstitutionKey] The CLICKHOUSE_URL key is not assigned properly
(SubstitutionKey)
[warning] 76-76: [UnorderedKey] The CLICKHOUSE_ADMIN_USER key should go before the CLICKHOUSE_URL key
(UnorderedKey)
[warning] 77-77: [UnorderedKey] The CLICKHOUSE_ADMIN_PASSWORD key should go before the CLICKHOUSE_ADMIN_USER key
(UnorderedKey)
[warning] 78-78: [UnorderedKey] The CLICKHOUSE_EXTERNAL_USER key should go before the CLICKHOUSE_URL key
(UnorderedKey)
[warning] 79-79: [UnorderedKey] The CLICKHOUSE_EXTERNAL_PASSWORD key should go before the CLICKHOUSE_EXTERNAL_USER key
(UnorderedKey)
[warning] 80-80: [UnorderedKey] The CLICKHOUSE_DATABASE key should go before the CLICKHOUSE_EXTERNAL_PASSWORD key
(UnorderedKey)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Vercel Agent Review
🔇 Additional comments (12)
apps/e2e/tests/snapshot-serializer.ts (1)
71-72: LGTM!Adding timing fields to
stripFieldsis appropriate for test stability, as these values are non-deterministic and would cause snapshot tests to fail.apps/backend/.env.development (1)
73-80: LGTM!The ClickHouse environment variables follow the established patterns in this file. The port interpolation and password placeholder conventions are consistent with other services.
Note: The static analysis warnings about SubstitutionKey and UnorderedKey can be safely ignored—these are false positives given the standard patterns used throughout this
.envfile.apps/dev-launchpad/public/index.html (2)
132-132: LGTM!The ClickHouse background service entry is consistent with other services and correctly uses port suffix 33.
304-312: LGTM!The ClickHouse app tile follows the established pattern and correctly references port suffix 33, matching the Docker service configuration.
apps/backend/scripts/db-migrations.ts (2)
11-11: LGTM!The import is correctly structured.
155-156: LGTM!Running ClickHouse migrations after Prisma migrations complete is the correct sequencing. The async/await usage is proper.
apps/backend/src/lib/clickhouse.tsx (1)
11-19: LGTM!The client factory function correctly handles both admin and external authentication modes with optional timeout configuration.
docker/dependencies/docker.compose.yaml (1)
225-241: ClickHouse 25.10 is a stable release (verified Oct 31, 2025), and a patch update (25.10.1) is also available.The image version specified in the docker-compose configuration is current, well-supported, and appropriate for use. No concerns with the version choice or service configuration.
apps/backend/package.json (1)
46-46: @clickhouse/client version 1.14.0 is current and has no known security vulnerabilities.Version 1.14.0 is the latest stable release (released November 20, 2025), and the
^1.14.0specifier is appropriate. No known security vulnerabilities were identified for the @clickhouse/client npm package.apps/e2e/tests/backend/endpoints/api/v1/analytics-query.test.ts (1)
217-244: LGTM!The timeout test using
SELECT sleep(3)with a 100ms timeout is a reliable way to verify timeout handling.packages/stack-shared/src/known-errors.tsx (2)
1632-1652: LGTM!The new
AnalyticsQueryTimeoutandAnalyticsQueryErrorconstructors follow the established pattern for known errors. The HTTP 400 status is appropriate, and theconstructorArgsFromJsonimplementations correctly deserialize the error details.
1784-1785: LGTM!The new error types are properly exported in the
KnownErrorsobject.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (2)
apps/backend/scripts/clickhouse-migrations.ts (1)
4-23: Migration GRANT targets a likely non-existent table and hardcodes the external userThis script still has the two issues called out in earlier reviews:
GRANT SELECT ON analytics.allowed_table1 TO limited_user;will fail ifanalytics.allowed_table1doesn’t exist yet (which seems likely given the TODO about creating migration files).- The external user name is hardcoded as
limited_user, even thoughSTACK_CLICKHOUSE_EXTERNAL_USERexists and is used elsewhere; that can drift.You could make this more robust along these lines:
export async function runClickhouseMigrations() { console.log("Running Clickhouse migrations..."); const client = createClickhouseClient("admin"); - const clickhouseExternalPassword = getEnvVariable("STACK_CLICKHOUSE_EXTERNAL_PASSWORD"); - // todo: create migration files - await client.exec({ - query: "CREATE USER IF NOT EXISTS limited_user IDENTIFIED WITH plaintext_password BY {clickhouseExternalPassword:String}", - query_params: { clickhouseExternalPassword }, - }); - const queries = [ - "GRANT SELECT ON analytics.allowed_table1 TO limited_user;", - "REVOKE ALL ON system.* FROM limited_user;", - "REVOKE CREATE, ALTER, DROP, INSERT ON *.* FROM limited_user;" - ]; - for (const query of queries) { - console.log(query); - await client.exec({ query }); - } - console.log("Clickhouse migrations complete"); - await client.close(); + const externalUser = getEnvVariable("STACK_CLICKHOUSE_EXTERNAL_USER", "limited_user"); + const clickhouseExternalPassword = getEnvVariable("STACK_CLICKHOUSE_EXTERNAL_PASSWORD"); + + try { + // TODO: create proper ClickHouse schema migrations + await client.exec({ + query: "CREATE USER IF NOT EXISTS {externalUser:Identifier} IDENTIFIED WITH plaintext_password BY {clickhouseExternalPassword:String}", + query_params: { externalUser, clickhouseExternalPassword }, + }); + + const queries = [ + // Enable GRANTs once the target tables exist. + // "GRANT SELECT ON analytics.some_table TO {externalUser:Identifier};", + `REVOKE ALL ON system.* FROM ${externalUser};`, + `REVOKE CREATE, ALTER, DROP, INSERT ON *.* FROM ${externalUser};`, + ]; + + for (const query of queries) { + console.log(query); + await client.exec({ query }); + } + + console.log("Clickhouse migrations complete"); + } finally { + await client.close(); + } }Adjust the GRANT line once your analytics tables are in place.
apps/backend/src/lib/clickhouse.tsx (1)
22-55: FixgetQueryTimingStatstyping and guard against missing query_log rowsThis function still has the issues called out in earlier reviews:
profile.jsonis typed as if it returns a flat{ cpu_time_ms, wall_clock_time_ms }, but you then accessstats.data[0]; this doesn’t match the ClickHouse JSON shape and will likely fail type-checking.- At runtime,
system.query_logcan legitimately return an emptydataarray (log entry not flushed yet), makingstats.data[0]undefinedand crashing callers that assume stats are always present.A safer version would be:
-export const getQueryTimingStats = async (client: ClickHouseClient, queryId: string) => { +export const getQueryTimingStats = async ( + client: ClickHouseClient, + queryId: string, +): Promise<{ cpu_time_ms: number; wall_clock_time_ms: number }> => { @@ - const stats = await profile.json<{ - cpu_time_ms: number, - wall_clock_time_ms: number, - }>(); - return stats.data[0]; + const stats = await profile.json<{ + data: Array<{ + cpu_time_ms: number; + wall_clock_time_ms: number; + }>; + }>(); + + if (!stats.data || stats.data.length === 0) { + throw new Error( + `Query timing stats not found for query_id=${queryId}; query_log entry may not be available yet.`, + ); + } + + return stats.data[0]; };Callers can then convert this error into a
KnownErrors.AnalyticsQueryErroror similar, as appropriate for the API surface.
🧹 Nitpick comments (2)
.github/workflows/docker-server-test.yaml (1)
26-30: Consider adding a lightweight readiness check for ClickHouseThe container may not always be ready within 5 seconds, especially on a busy CI runner. A transient slow start would make this job flaky.
Consider replacing the fixed
sleepwith a small readiness loop, for example:- name: Setup clickhouse run: | docker run -d --name clickhouse \ -e CLICKHOUSE_DB=analytics \ -e CLICKHOUSE_USER=stackframe \ -e CLICKHOUSE_PASSWORD=password \ -p 8133:8123 clickhouse/clickhouse-server:25.10 for i in {1..30}; do if docker exec clickhouse clickhouse-client --query "SELECT 1" >/dev/null 2>&1; then echo "ClickHouse is ready" break fi echo "Waiting for ClickHouse..." sleep 1 done docker logs clickhouse </blockquote></details> <details> <summary>apps/backend/.env.development (1)</summary><blockquote> `74-80`: **ClickHouse env block looks consistent with backend usage** The new `STACK_CLICKHOUSE_*` variables line up with `createClickhouseClient` and the CI ClickHouse setup (DB `analytics`, admin user `stackframe`, external user `limited_user`), so this should wire up cleanly for local dev. The `dotenv-linter` warnings here (substitution and key ordering) are stylistic only; the same `${NEXT_PUBLIC_STACK_PORT_PREFIX:-81}` pattern is already used above. You can reorder the keys if you want to silence the linter, but it’s not functionally required. </blockquote></details> </blockquote></details> <details> <summary>📜 Review details</summary> **Configuration used**: CodeRabbit UI **Review profile**: CHILL **Plan**: Pro <details> <summary>📥 Commits</summary> Reviewing files that changed from the base of the PR and between 0c088962934cdf829c9e6b282d2fa5a4e07723a3 and 41287db62997e2a54a1084037a90136517fcbbe5. </details> <details> <summary>📒 Files selected for processing (5)</summary> * `.github/workflows/docker-server-test.yaml` (1 hunks) * `apps/backend/.env.development` (1 hunks) * `apps/backend/scripts/clickhouse-migrations.ts` (1 hunks) * `apps/backend/src/lib/clickhouse.tsx` (1 hunks) * `docker/server/.env.example` (1 hunks) </details> <details> <summary>🧰 Additional context used</summary> <details> <summary>📓 Path-based instructions (2)</summary> <details> <summary>**/*.{ts,tsx}</summary> **📄 CodeRabbit inference engine (AGENTS.md)** > `**/*.{ts,tsx}`: Ensure code passes `pnpm typecheck` for TypeScript type validation > Never use `toast` for blocking alerts and errors; use alerts instead as they are more visible to users > Keep hover/click transitions snappy and fast; apply transitions after the action (e.g., smooth fade-out on hover end) rather than delaying actions with pre-transitions to avoid sluggish UI > Never use try-catch-all, never void a promise, never use .catch(console.error) or similar; use `runAsynchronously` or `runAsynchronouslyWithAlert` for error handling instead of try-catch blocks > Use loading indicators instead of try-catch blocks for asynchronous UI operations; button components like <Button> support async callbacks with built-in loading state > Use ES6 maps instead of records wherever possible Files: - `apps/backend/src/lib/clickhouse.tsx` - `apps/backend/scripts/clickhouse-migrations.ts` </details> <details> <summary>apps/**/*.{ts,tsx}</summary> **📄 CodeRabbit inference engine (AGENTS.md)** > Prefer client components and dynamic functions like `usePathname` over Next.js dynamic functions to keep pages static; avoid using `await params` or similar dynamic patterns Files: - `apps/backend/src/lib/clickhouse.tsx` - `apps/backend/scripts/clickhouse-migrations.ts` </details> </details><details> <summary>🧠 Learnings (1)</summary> <details> <summary>📚 Learning: 2025-11-25T02:09:03.104Z</summary>Learnt from: CR
Repo: stack-auth/stack-auth PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T02:09:03.104Z
Learning: Applies to packages/stack-shared/src/config/** : When making backwards-incompatible changes to the config schema, update the migration functions inpackages/stack-shared/src/config/schema.ts**Applied to files:** - `apps/backend/scripts/clickhouse-migrations.ts` </details> </details><details> <summary>🧬 Code graph analysis (2)</summary> <details> <summary>apps/backend/src/lib/clickhouse.tsx (1)</summary><blockquote> <details> <summary>packages/stack-shared/src/utils/env.tsx (1)</summary> * `getEnvVariable` (16-58) </details> </blockquote></details> <details> <summary>apps/backend/scripts/clickhouse-migrations.ts (2)</summary><blockquote> <details> <summary>apps/backend/src/lib/clickhouse.tsx (1)</summary> * `createClickhouseClient` (11-19) </details> <details> <summary>packages/stack-shared/src/utils/env.tsx (1)</summary> * `getEnvVariable` (16-58) </details> </blockquote></details> </details><details> <summary>🪛 dotenv-linter (4.0.0)</summary> <details> <summary>docker/server/.env.example</summary> [warning] 20-20: [UnorderedKey] The STACK_CLICKHOUSE_ADMIN_PASSWORD key should go before the STACK_CLICKHOUSE_URL key (UnorderedKey) --- [warning] 21-21: [UnorderedKey] The STACK_CLICKHOUSE_EXTERNAL_PASSWORD key should go before the STACK_CLICKHOUSE_URL key (UnorderedKey) </details> <details> <summary>apps/backend/.env.development</summary> [warning] 75-75: [SubstitutionKey] The STACK_CLICKHOUSE_URL key is not assigned properly (SubstitutionKey) --- [warning] 76-76: [UnorderedKey] The STACK_CLICKHOUSE_ADMIN_USER key should go before the STACK_CLICKHOUSE_URL key (UnorderedKey) --- [warning] 77-77: [UnorderedKey] The STACK_CLICKHOUSE_ADMIN_PASSWORD key should go before the STACK_CLICKHOUSE_ADMIN_USER key (UnorderedKey) --- [warning] 78-78: [UnorderedKey] The STACK_CLICKHOUSE_EXTERNAL_USER key should go before the STACK_CLICKHOUSE_URL key (UnorderedKey) --- [warning] 79-79: [UnorderedKey] The STACK_CLICKHOUSE_EXTERNAL_PASSWORD key should go before the STACK_CLICKHOUSE_EXTERNAL_USER key (UnorderedKey) --- [warning] 80-80: [UnorderedKey] The STACK_CLICKHOUSE_DATABASE key should go before the STACK_CLICKHOUSE_EXTERNAL_PASSWORD key (UnorderedKey) </details> </details> </details> <details> <summary>⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)</summary> * GitHub Check: Vercel Agent Review * GitHub Check: docker * GitHub Check: restart-dev-and-test-with-custom-base-port * GitHub Check: check_prisma_migrations (22.x) * GitHub Check: setup-tests * GitHub Check: build (22.x) * GitHub Check: lint_and_build (latest) * GitHub Check: all-good * GitHub Check: build (22.x) * GitHub Check: restart-dev-and-test * GitHub Check: build (22.x) </details> </details> <!-- This is an auto-generated comment by CodeRabbit for review status -->
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
docker/server/.env.example (1)
19-21: Reorder ClickHouse keys for consistency with dotenv-linter and env-var conventions.The three ClickHouse environment variables should be in alphabetical order to match the Postgres connection strings pattern and resolve the dotenv-linter UnorderedKey warnings.
Apply this diff:
-STACK_CLICKHOUSE_URL=http://host.docker.internal:8133 STACK_CLICKHOUSE_ADMIN_PASSWORD=password STACK_CLICKHOUSE_EXTERNAL_PASSWORD=password +STACK_CLICKHOUSE_URL=http://host.docker.internal:8133
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
docker/server/.env.example(1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-25T02:09:03.104Z
Learnt from: CR
Repo: stack-auth/stack-auth PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T02:09:03.104Z
Learning: When making dashboard changes, provide deep links to the dashboard page in the format `http://localhost:<$NEXT_PUBLIC_STACK_PORT_PREFIX>01/projects/-selector-/...` (or use a.localhost, b.localhost, c.localhost for port prefixes 91, 92, 93)
Applied to files:
docker/server/.env.example
🪛 dotenv-linter (4.0.0)
docker/server/.env.example
[warning] 20-20: [UnorderedKey] The STACK_CLICKHOUSE_ADMIN_PASSWORD key should go before the STACK_CLICKHOUSE_URL key
(UnorderedKey)
[warning] 21-21: [UnorderedKey] The STACK_CLICKHOUSE_EXTERNAL_PASSWORD key should go before the STACK_CLICKHOUSE_URL key
(UnorderedKey)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
- GitHub Check: Vercel Agent Review
- GitHub Check: lint_and_build (latest)
- GitHub Check: restart-dev-and-test-with-custom-base-port
- GitHub Check: check_prisma_migrations (22.x)
- GitHub Check: build (22.x)
- GitHub Check: build (22.x)
- GitHub Check: setup-tests
- GitHub Check: build (22.x)
- GitHub Check: all-good
- GitHub Check: restart-dev-and-test
- GitHub Check: docker
🔇 Additional comments (1)
docker/server/.env.example (1)
19-21: ✓ Critical issue resolved: ClickHouse URL correctly targets host-exposed service.The change from
localhost:8133tohost.docker.internal:8133ensures the server container correctly reaches the ClickHouse service. This aligns with the Postgres connection pattern and will allow ClickHouse operations to function properly in Docker environments.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (2)
apps/backend/scripts/clickhouse-migrations.ts (2)
14-14: GRANT statement references non-existent table.This grants SELECT on
analytics.allowed_table1, which doesn't exist yet and will cause the migration to fail.Comment or remove this line until the table is created in a prior migration step.
22-23: Move client cleanup to a finally block.If any query fails before line 23, the client won't be closed, leaving the connection open.
Apply this diff to guarantee cleanup:
- console.log("Clickhouse migrations complete"); - await client.close(); + try { + // existing migration logic here + console.log("Clickhouse migrations complete"); + } finally { + await client.close(); + }Note: Per coding guidelines, avoid try-catch-all for error handling. Let errors propagate naturally while ensuring cleanup in the finally block.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (2)
apps/backend/package.json(1 hunks)apps/backend/scripts/clickhouse-migrations.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: For blocking alerts and errors, never usetoast, as they are easily missed by the user. Instead, use alerts
Keep hover/click transitions snappy and fast. Don't delay the action with a pre-transition; apply transitions after the action instead
NEVER try-catch-all, NEVER void a promise, and NEVER .catch(console.error). UserunAsynchronouslyorrunAsynchronouslyWithAlertinstead for asynchronous error handling
When creating hover transitions, avoid hover-enter transitions and just use hover-exit transitions (e.g.,transition-colors hover:transition-none)
Use ES6 maps instead of records wherever possible
Files:
apps/backend/scripts/clickhouse-migrations.ts
🧠 Learnings (1)
📚 Learning: 2025-11-28T21:21:39.123Z
Learnt from: CR
Repo: stack-auth/stack-auth PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-28T21:21:39.123Z
Learning: Applies to packages/stack-shared/src/config/schema.ts : Whenever making backwards-incompatible changes to the config schema, update the migration functions in `packages/stack-shared/src/config/schema.ts`
Applied to files:
apps/backend/scripts/clickhouse-migrations.ts
🧬 Code graph analysis (1)
apps/backend/scripts/clickhouse-migrations.ts (2)
apps/backend/src/lib/clickhouse.tsx (1)
createClickhouseClient(11-19)packages/stack-shared/src/utils/env.tsx (1)
getEnvVariable(16-58)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
- GitHub Check: Vercel Agent Review
- GitHub Check: docker
- GitHub Check: check_prisma_migrations (22.x)
- GitHub Check: build (22.x)
- GitHub Check: build (22.x)
- GitHub Check: setup-tests
- GitHub Check: restart-dev-and-test-with-custom-base-port
- GitHub Check: lint_and_build (latest)
- GitHub Check: restart-dev-and-test
- GitHub Check: all-good
- GitHub Check: build (22.x)
🔇 Additional comments (1)
apps/backend/package.json (1)
46-46: Version 1.14.0 is current and has no known vulnerabilities.The @clickhouse/client package version 1.14.0 is the latest available on npm with no direct security vulnerabilities reported in Snyk or other vulnerability databases.
Older cmux preview screenshots (latest comment is below)Preview ScreenshotsOpen Workspace (1 hr expiry) · Open Dev Browser (1 hr expiry) · Open Diff Heatmap Captured 3 screenshots for commit Element screenshot of the new ClickHouse service tile at port 8133 Full page screenshot of the Dev Launchpad showing the new ClickHouse and MCPJam Inspector service tiles added in this PR, along with ClickHouse in the Background services list Element screenshot of the new MCPJam Inspector service tile at port 8126 Generated by cmux preview system |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
.github/workflows/docker-server-build-run.yaml (1)
26-30: ClickHouse setup step looks good and maintains consistency.The step is well-configured:
- Uses the same ClickHouse version (25.10) as the docker-compose file for consistency
- Port mapping (8133:8123) aligns with the development environment configuration
- Environment variables match those in
.env.development- Logging output helps with debugging startup issues
Consider whether 5 seconds is sufficient for ClickHouse to fully initialize. Depending on the CI environment performance, you might want to add a health check loop similar to the "Check server health" step, or increase the sleep duration to ensure ClickHouse is ready before subsequent steps.
apps/backend/.env.development (1)
75-82: Consider alphabetically reordering the ClickHouse configuration keys for improved maintainability.While the variable substitution pattern is already supported via the backend's custom environment variable handling, the ClickHouse keys should follow alphabetical order:
STACK_CLICKHOUSE_ADMIN_PASSWORD,STACK_CLICKHOUSE_ADMIN_USER,STACK_CLICKHOUSE_DATABASE,STACK_CLICKHOUSE_EXTERNAL_PASSWORD,STACK_CLICKHOUSE_EXTERNAL_USER,STACK_CLICKHOUSE_URL.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (6)
.github/workflows/docker-server-build-run.yaml(1 hunks)apps/backend/.env.development(1 hunks)apps/backend/package.json(1 hunks)apps/dev-launchpad/public/index.html(2 hunks)docker/dependencies/docker.compose.yaml(2 hunks)packages/stack-shared/src/known-errors.tsx(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- apps/backend/package.json
- apps/dev-launchpad/public/index.html
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Always add new E2E tests when changing the API or SDK interface
For blocking alerts and errors, never use toast; use alerts instead as they are less easily missed by the user
NEVER try-catch-all, NEVER void a promise, and NEVER .catch(console.error); use loading indicators and async callbacks instead, or use runAsynchronously/runAsynchronouslyWithAlert for error handling
Use ES6 maps instead of records wherever you can
Files:
packages/stack-shared/src/known-errors.tsx
**/*.{ts,tsx,css}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,css}: Keep hover/click transitions snappy and fast; avoid fade-in delays on hover. Apply transitions after action completion instead, like smooth fade-out when hover ends
Use hover-exit transitions instead of hover-enter transitions; for example, use 'transition-colors hover:transition-none' instead of fade-in on hover
Files:
packages/stack-shared/src/known-errors.tsx
{.env*,**/*.{ts,tsx,js}}
📄 CodeRabbit inference engine (AGENTS.md)
Prefix environment variables with STACK_ (or NEXT_PUBLIC_STACK_ if public) so changes are picked up by Turborepo and improves readability
Files:
packages/stack-shared/src/known-errors.tsx
🧠 Learnings (1)
📚 Learning: 2025-12-04T18:03:49.984Z
Learnt from: CR
Repo: stack-auth/stack-auth PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-04T18:03:49.984Z
Learning: Applies to {.env*,**/*.{ts,tsx,js}} : Prefix environment variables with STACK_ (or NEXT_PUBLIC_STACK_ if public) so changes are picked up by Turborepo and improves readability
Applied to files:
apps/backend/.env.development
🪛 dotenv-linter (4.0.0)
apps/backend/.env.development
[warning] 77-77: [SubstitutionKey] The STACK_CLICKHOUSE_URL key is not assigned properly
(SubstitutionKey)
[warning] 78-78: [UnorderedKey] The STACK_CLICKHOUSE_ADMIN_USER key should go before the STACK_CLICKHOUSE_URL key
(UnorderedKey)
[warning] 79-79: [UnorderedKey] The STACK_CLICKHOUSE_ADMIN_PASSWORD key should go before the STACK_CLICKHOUSE_ADMIN_USER key
(UnorderedKey)
[warning] 80-80: [UnorderedKey] The STACK_CLICKHOUSE_EXTERNAL_USER key should go before the STACK_CLICKHOUSE_URL key
(UnorderedKey)
[warning] 81-81: [UnorderedKey] The STACK_CLICKHOUSE_EXTERNAL_PASSWORD key should go before the STACK_CLICKHOUSE_EXTERNAL_USER key
(UnorderedKey)
[warning] 82-82: [UnorderedKey] The STACK_CLICKHOUSE_DATABASE key should go before the STACK_CLICKHOUSE_EXTERNAL_PASSWORD key
(UnorderedKey)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (13)
- GitHub Check: Vercel Agent Review
- GitHub Check: build (22.x)
- GitHub Check: setup-tests-with-custom-base-port
- GitHub Check: setup-tests
- GitHub Check: restart-dev-and-test
- GitHub Check: build (22.x)
- GitHub Check: docker
- GitHub Check: all-good
- GitHub Check: lint_and_build (latest)
- GitHub Check: restart-dev-and-test-with-custom-base-port
- GitHub Check: E2E Tests (Node 22.x, Freestyle prod)
- GitHub Check: E2E Tests (Node 22.x, Freestyle mock)
- GitHub Check: check_prisma_migrations (22.x)
🔇 Additional comments (2)
docker/dependencies/docker.compose.yaml (1)
208-226: ClickHouse service configuration looks good.The ClickHouse service is well-configured with:
- Specific image version (25.10) for reproducibility
- Proper environment variables for database initialization
- Persistent volume mount
- Increased ulimits for production-like behavior
packages/stack-shared/src/known-errors.tsx (1)
1636-1656: LGTM! Analytics error constructors follow established patterns.The new
AnalyticsQueryTimeoutandAnalyticsQueryErrorerror constructors are well-implemented:
- Follow the existing
createKnownErrorConstructorpattern consistently- Use appropriate 400 status codes for client errors
- Include descriptive messages and properly structured details objects
- Correctly implement
constructorArgsFromJsonfor deserialization- Properly exported in the
KnownErrorscollectionAlso applies to: 1788-1789
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (2)
apps/backend/scripts/clickhouse-migrations.ts (2)
14-14: Migration will fail:analytics.allowed_table1doesn't exist.This GRANT references a table that hasn't been created. The migration will fail at runtime. Per past discussion, this is noted as temporary, but it should be commented out or removed until the table exists.
9-21: Add try-finally to ensure client cleanup on failure.If any
client.exec()call throws,client.close()on line 23 won't be reached, causing a resource leak. Wrap the migration logic in a try-finally block.export async function runClickhouseMigrations() { console.log("[Clickhouse] Running Clickhouse migrations..."); - const client = clickhouseAdminClient; + const client = createClickhouseClient("admin"); const clickhouseExternalPassword = getEnvVariable("STACK_CLICKHOUSE_EXTERNAL_PASSWORD"); - // todo: create migration files - await client.exec({ - query: "CREATE USER IF NOT EXISTS limited_user IDENTIFIED WITH plaintext_password BY {clickhouseExternalPassword:String}", - query_params: { clickhouseExternalPassword }, - }); - const queries = [ - "GRANT SELECT ON analytics.allowed_table1 TO limited_user;", - "REVOKE ALL ON system.* FROM limited_user;", - "REVOKE CREATE, ALTER, DROP, INSERT ON *.* FROM limited_user;" - ]; - for (const query of queries) { - console.log("[Clickhouse] " + query); - await client.exec({ query }); + try { + await client.exec({ + query: "CREATE USER IF NOT EXISTS limited_user IDENTIFIED WITH plaintext_password BY {clickhouseExternalPassword:String}", + query_params: { clickhouseExternalPassword }, + }); + const queries = [ + "GRANT SELECT ON analytics.allowed_table1 TO limited_user;", + "REVOKE ALL ON system.* FROM limited_user;", + "REVOKE CREATE, ALTER, DROP, INSERT ON *.* FROM limited_user;" + ]; + for (const query of queries) { + console.log("[Clickhouse] " + query); + await client.exec({ query }); + } + console.log("[Clickhouse] Clickhouse migrations complete"); + } finally { + await client.close(); } - console.log("[Clickhouse] Clickhouse migrations complete"); - await client.close(); }
🧹 Nitpick comments (2)
apps/backend/src/app/api/latest/internal/analytics/query/route.ts (1)
52-53: Consider wrappinggetQueryTimingStatserrors.If
getQueryTimingStatsfails (e.g., query log entry not found), it throws aStackAssertionErrorwhich will propagate as an internal error rather than a user-friendlyAnalyticsQueryError. Consider wrapping this call for consistent error responses.const rows = await resultSet.data.json<Record<string, unknown>[]>(); - const stats = await getQueryTimingStats(client, queryId); + let stats; + try { + stats = await getQueryTimingStats(client, queryId); + } catch (error) { + const message = error instanceof Error ? error.message : "Failed to retrieve query timing statistics"; + throw new KnownErrors.AnalyticsQueryError(message); + }apps/e2e/tests/backend/endpoints/api/v1/analytics-query.test.ts (1)
217-239: Test timeout behavior may be unstable across ClickHouse versionsThe
SELECT sleep(3)with 100ms timeout can be affected by ClickHouse versions where sleep queries behave inconsistently with max_execution_time enforcement. Recent ClickHouse versions show timeout behavior inconsistencies where max_execution_time is sometimes treated differently.Consider adding an inline comment explaining that the test expects
ANALYTICS_QUERY_ERRORdue to server-side timeout enforcement, and note any specific ClickHouse version constraints if the timeout behavior is known to be reliable only in certain versions.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
apps/backend/scripts/clickhouse-migrations.ts(1 hunks)apps/backend/src/app/api/latest/internal/analytics/query/route.ts(1 hunks)apps/backend/src/lib/clickhouse.tsx(1 hunks)apps/dev-launchpad/public/index.html(2 hunks)apps/e2e/tests/backend/endpoints/api/v1/analytics-query.test.ts(1 hunks)docker/dependencies/docker.compose.yaml(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/dev-launchpad/public/index.html
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Always add new E2E tests when changing the API or SDK interface
For blocking alerts and errors, never use toast; use alerts instead as they are less easily missed by the user
NEVER try-catch-all, NEVER void a promise, and NEVER .catch(console.error); use loading indicators and async callbacks instead, or use runAsynchronously/runAsynchronouslyWithAlert for error handling
Use ES6 maps instead of records wherever you can
Files:
apps/backend/src/app/api/latest/internal/analytics/query/route.tsapps/e2e/tests/backend/endpoints/api/v1/analytics-query.test.tsapps/backend/scripts/clickhouse-migrations.tsapps/backend/src/lib/clickhouse.tsx
**/*.{ts,tsx,css}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,css}: Keep hover/click transitions snappy and fast; avoid fade-in delays on hover. Apply transitions after action completion instead, like smooth fade-out when hover ends
Use hover-exit transitions instead of hover-enter transitions; for example, use 'transition-colors hover:transition-none' instead of fade-in on hover
Files:
apps/backend/src/app/api/latest/internal/analytics/query/route.tsapps/e2e/tests/backend/endpoints/api/v1/analytics-query.test.tsapps/backend/scripts/clickhouse-migrations.tsapps/backend/src/lib/clickhouse.tsx
apps/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
NEVER use Next.js dynamic functions if you can avoid them; prefer using client components and hooks like usePathname instead of await params to keep pages static
Files:
apps/backend/src/app/api/latest/internal/analytics/query/route.tsapps/e2e/tests/backend/endpoints/api/v1/analytics-query.test.tsapps/backend/scripts/clickhouse-migrations.tsapps/backend/src/lib/clickhouse.tsx
{.env*,**/*.{ts,tsx,js}}
📄 CodeRabbit inference engine (AGENTS.md)
Prefix environment variables with STACK_ (or NEXT_PUBLIC_STACK_ if public) so changes are picked up by Turborepo and improves readability
Files:
apps/backend/src/app/api/latest/internal/analytics/query/route.tsapps/e2e/tests/backend/endpoints/api/v1/analytics-query.test.tsapps/backend/scripts/clickhouse-migrations.tsapps/backend/src/lib/clickhouse.tsx
**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Prefer .toMatchInlineSnapshot over other selectors in tests when possible; check snapshot-serializer.ts for formatting details
Files:
apps/e2e/tests/backend/endpoints/api/v1/analytics-query.test.ts
apps/e2e/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Always add new E2E tests when changing API or SDK interface; err on the side of creating too many tests due to the critical nature of the industry
Files:
apps/e2e/tests/backend/endpoints/api/v1/analytics-query.test.ts
apps/**/*.tsx
📄 CodeRabbit inference engine (AGENTS.md)
Check existing apps for inspiration when implementing new apps or pages; update apps-frontend.tsx and apps-config.ts to add new apps
Files:
apps/backend/src/lib/clickhouse.tsx
🧠 Learnings (5)
📚 Learning: 2025-12-17T01:23:07.460Z
Learnt from: N2D4
Repo: stack-auth/stack-auth PR: 1032
File: apps/backend/src/app/api/latest/analytics/query/route.tsx:20-20
Timestamp: 2025-12-17T01:23:07.460Z
Learning: In apps/backend/src/app/api/latest/analytics/query/route.tsx, the include_all_branches field controls which ClickHouse user type is used: when true, use "admin" authType for access to all branches; when false (default), use "external" authType for limited/filtered branch access.
Applied to files:
apps/backend/src/app/api/latest/internal/analytics/query/route.tsapps/backend/scripts/clickhouse-migrations.tsapps/backend/src/lib/clickhouse.tsx
📚 Learning: 2025-12-04T18:03:49.984Z
Learnt from: CR
Repo: stack-auth/stack-auth PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-04T18:03:49.984Z
Learning: Applies to **/*.{ts,tsx} : NEVER try-catch-all, NEVER void a promise, and NEVER .catch(console.error); use loading indicators and async callbacks instead, or use runAsynchronously/runAsynchronouslyWithAlert for error handling
Applied to files:
apps/backend/src/app/api/latest/internal/analytics/query/route.ts
📚 Learning: 2025-12-04T18:03:49.984Z
Learnt from: CR
Repo: stack-auth/stack-auth PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-04T18:03:49.984Z
Learning: Applies to apps/e2e/**/*.{ts,tsx} : Always add new E2E tests when changing API or SDK interface; err on the side of creating too many tests due to the critical nature of the industry
Applied to files:
apps/e2e/tests/backend/endpoints/api/v1/analytics-query.test.ts
📚 Learning: 2025-12-04T18:03:49.984Z
Learnt from: CR
Repo: stack-auth/stack-auth PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-04T18:03:49.984Z
Learning: Applies to **/*.{ts,tsx} : Always add new E2E tests when changing the API or SDK interface
Applied to files:
apps/e2e/tests/backend/endpoints/api/v1/analytics-query.test.ts
📚 Learning: 2025-12-04T18:03:49.984Z
Learnt from: CR
Repo: stack-auth/stack-auth PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-04T18:03:49.984Z
Learning: Applies to packages/stack-shared/src/config/schema.ts : Whenever making backwards-incompatible changes to the config schema, update the migration functions in packages/stack-shared/src/config/schema.ts
Applied to files:
apps/backend/scripts/clickhouse-migrations.ts
🧬 Code graph analysis (2)
apps/backend/src/app/api/latest/internal/analytics/query/route.ts (4)
apps/backend/src/route-handlers/smart-route-handler.tsx (1)
createSmartRouteHandler(211-296)packages/stack-shared/src/schema-fields.ts (8)
yupObject(247-251)adminAuthTypeSchema(499-499)adaptSchema(330-330)yupBoolean(195-198)yupString(187-190)yupRecord(283-322)yupMixed(210-212)jsonSchema(410-410)apps/backend/src/prisma-client.tsx (1)
client(133-138)apps/backend/src/lib/clickhouse.tsx (2)
clickhouseExternalClient(22-22)getQueryTimingStats(24-60)
apps/backend/src/lib/clickhouse.tsx (2)
packages/stack-shared/src/utils/env.tsx (1)
getEnvVariable(16-58)packages/stack-shared/src/utils/errors.tsx (1)
StackAssertionError(69-85)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (12)
- GitHub Check: check_prisma_migrations (22.x)
- GitHub Check: lint_and_build (latest)
- GitHub Check: all-good
- GitHub Check: Vercel Agent Review
- GitHub Check: E2E Tests (Node 22.x, Freestyle prod)
- GitHub Check: E2E Tests (Node 22.x, Freestyle mock)
- GitHub Check: build (22.x)
- GitHub Check: setup-tests-with-custom-base-port
- GitHub Check: restart-dev-and-test-with-custom-base-port
- GitHub Check: build (22.x)
- GitHub Check: setup-tests
- GitHub Check: restart-dev-and-test
🔇 Additional comments (6)
docker/dependencies/docker.compose.yaml (1)
208-226: ClickHouse service configuration looks good.The service is properly configured with appropriate ports, environment variables, volume mount, and ulimits for file descriptors. The port conflict with drizzle-gateway has been resolved by moving drizzle-gateway to port suffix 35.
apps/backend/src/app/api/latest/internal/analytics/query/route.ts (1)
8-67: Good use of singleton client pattern.Using the pre-configured
clickhouseExternalClientsingleton avoids the per-request client creation and resource leak issues flagged in past reviews. The route structure follows the established patterns with proper schema validation.apps/e2e/tests/backend/endpoints/api/v1/analytics-query.test.ts (1)
4-382: Comprehensive E2E test coverage for the analytics query endpoint.The tests cover:
- Basic query execution with admin access
- Parameterized queries (single and multiple params)
- Custom timeout handling
- Required field validation
- Invalid SQL handling
- Multiple row results
- Tenancy ID verification
- Security restrictions (CREATE, system tables, KILL, INSERT)
This aligns well with the coding guidelines requiring E2E tests for API changes.
apps/backend/src/lib/clickhouse.tsx (3)
5-10: Environment variables correctly useSTACK_prefix.The environment variables follow the coding guidelines with the
STACK_CLICKHOUSE_*prefix, ensuring they're picked up by Turborepo and maintaining naming consistency.
52-59: Proper validation for query log results.The code now validates that exactly one result is returned from the query log and throws a
StackAssertionErrorwith context if not, addressing the past review concern about undefined access.
21-22: Singleton clients created at module load time.The singleton clients are instantiated when the module is imported. If required environment variables (like
STACK_CLICKHOUSE_URL) are missing, this will throw at startup rather than at first use. This matches the pattern used elsewhere (e.g., Prisma client) and provides early failure detection.
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/dev-launchpad/public/index.html (1)
123-135: Fix port suffix collision on "33".Both "ClickHouse native interface" (line 133, backgroundServices) and "Drizzle Gateway" (line 302, apps) use suffix "33". Since the port formula concatenates
${stackPortPrefix}${suffix}, both services will attempt to bind to the same port (e.g., 8133 with default prefix 81), causing a startup failure. Change one of the suffixes to an unused value.
Summary by CodeRabbit
New Features
Dashboard
Infrastructure
Tests
Docs / Errors
✏️ Tip: You can customize this high-level summary in your review settings.
Note
Add ClickHouse-backed analytics: readonly query API with timing, dual-write event storage and migration, dashboard query editor/migration UI, and local/CI setup.
@/lib/clickhouseclient, env vars, and migrations creatinganalytics.events; row policy and restrictedlimited_usergrants.analytics.events(src/lib/events.tsx).POST /api/v1/internal/analytics/queryexecuting readonly, tenant-scoped ClickHouse queries and returning results + CPU/wall times; addsKnownErrorsfor analytics.queryAnalytics, ClickHouse migration) and analytics types..envexamples andclickhousescripts; Dev Launchpad entries.Written by Cursor Bugbot for commit 1134883. This will update automatically on new commits. Configure here.