-
-
Notifications
You must be signed in to change notification settings - Fork 976
Query: time limits, performance improvements, styling #2953
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
WalkthroughThe changes add structured enforcedWhereClause support across the TSQL library (new condition types, printer/context updates, tests) and update the ClickHouse executor API to accept enforcedWhereClause. They introduce textColumn and dataPrefix for JSON handling, adapt many tests, and change public types. Backend changes include executeQuery returning ExecuteQueryResult with queryId, AIQueryTitleService and an ai-title route, DB migration adding CustomerQuery.title and removing costInCents, schema updates, and environment var removal. Frontend updates add legendScrollable props, AnimatedNumber decimals, Resizable handle orientation, chart/table UI tweaks, time-filter maxPeriodDays enforcement, and title-generation wiring in the query UI. Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes 🚥 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
🧹 Recent nitpick comments
📜 Recent review detailsConfiguration used: Repository UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (2)
🧰 Additional context used📓 Path-based instructions (10)**/*.{ts,tsx}📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Files:
**/*.{ts,tsx,js,jsx}📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Files:
**/*.{test,spec}.{ts,tsx}📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Files:
**/*.ts📄 CodeRabbit inference engine (.cursor/rules/otel-metrics.mdc)
Files:
**/*.{js,ts,jsx,tsx,json,md,yaml,yml}📄 CodeRabbit inference engine (AGENTS.md)
Files:
**/*.test.{ts,tsx,js,jsx}📄 CodeRabbit inference engine (AGENTS.md)
Files:
**/*.test.{ts,tsx}📄 CodeRabbit inference engine (CLAUDE.md)
Files:
{packages/core,apps/webapp}/**/*.{ts,tsx}📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Files:
apps/webapp/app/**/*.{ts,tsx}📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)
Files:
apps/webapp/**/*.{ts,tsx}📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)
Files:
🧠 Learnings (4)📚 Learning: 2025-07-12T18:06:04.133ZApplied to files:
📚 Learning: 2025-07-21T12:52:44.342ZApplied to files:
📚 Learning: 2025-11-27T16:27:35.304ZApplied to files:
📚 Learning: 2025-11-27T16:27:35.304ZApplied to files:
⏰ 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). (22)
🔇 Additional comments (10)
✏️ Tip: You can disable this entire section by setting 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 12
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/webapp/app/components/runs/v3/SharedFilters.tsx (1)
529-540: Add missing dependencies toapplySelectioncallback.
Line 529-540 referencesmaxPeriodDaysandexceedsMaxPeriod, but they’re missing from the dependency list, which can stale the validation/error message when props change.🧩 Suggested fix
}, [ activeSection, selectedPeriod, isCustomDurationValid, customValue, customUnit, fromValue, toValue, replace, onApply, onValueChange, + maxPeriodDays, + exceedsMaxPeriod, ]);
🤖 Fix all issues with AI agents
In `@apps/webapp/app/components/code/TSQLResultsTable.tsx`:
- Line 1142: The tbody in TSQLResultsTable uses "divide-y divide-charcoal-700"
which doesn't show dividers for absolutely positioned/virtualized rows; remove
those utilities from the tbody className and instead add "border-b
border-charcoal-700" to the element that renders each virtualized row (the
per-row container/render function used by the virtualizer — e.g., the row
renderer / row element inside the map or renderRow handler) so each row gets its
own bottom border; update any row className/props (not the tbody) to include the
border utilities and remove the divide-y/divide-charcoal-700 from the tbody.
In `@apps/webapp/app/components/primitives/AnimatedNumber.tsx`:
- Around line 22-47: The decimals value used in the useTransform callback must
be clamped and sanitized before being passed to toLocaleString to avoid runtime
throws from invalid values; update the AnimatedNumber component to compute a
safeDecimals (based on decimalPlaces or getDecimalPlaces(value)) by coercing to
a finite number, rounding to an integer, and clamping into the 0–20 range (e.g.,
use Number.isFinite, Math.round, Math.max/Math.min) and then use safeDecimals
inside the display transformer and any branch that checks for zero; ensure NaN,
negatives, non-integers and >20 are handled by this normalization so
toLocaleString always receives a valid 0–20 integer.
In `@apps/webapp/app/components/runs/v3/SharedFilters.tsx`:
- Around line 441-452: The exceedsMaxPeriod calculation only checks fromValue
for date ranges and thus misses cases where only toValue is set; update the
date-range branch in exceedsMaxPeriod to compute the earliest selected date (min
of fromValue and toValue) and compare its age via dateRangeToDays (or convert
the computed range to days) against maxPeriodDays so "to-only" selections that
exceed maxPeriodDays also return true; locate the exceedsMaxPeriod IIFE and
adjust the date range logic that references activeSection, fromValue, toValue,
dateRangeToDays, and maxPeriodDays accordingly.
In
`@apps/webapp/app/routes/_app.orgs`.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHelpSidebar.tsx:
- Around line 70-76: The "guide" tab currently has double padding because
ClientTabsContent (value="guide") has className including "p-3" and its inner
div also has "p-3"; remove the outer padding to match the "ai" tab layout.
Locate the ClientTabsContent element with value="guide" and remove the "p-3"
from its className (leave the inner div wrapping TRQLGuideContent with its
"p-3"), ensuring visual alignment with the other tab; references:
ClientTabsContent and TRQLGuideContent.
- Around line 86-92: The "examples" tab duplicates padding because
ClientTabsContent has p-3 and the inner wrapper div also uses p-3; remove the
extra padding by deleting the p-3 on the inner div (the wrapper around
<ExamplesContent onTryExample={onTryExample} />) or adjust it to a neutral class
(e.g., remove padding or use p-0) so only ClientTabsContent provides the
padding; update the wrapper near ClientTabsContent/ExamplesContent to eliminate
the double padding.
- Around line 78-84: The "schema" tab shows double padding because both
ClientTabsContent (value="schema") and the inner div around TableSchemaContent
apply p-3; remove the redundant padding by deleting or changing the inner div's
padding class (the div wrapping TableSchemaContent) to p-0 (or remove p-3) so
only ClientTabsContent provides spacing; update the inner wrapper surrounding
TableSchemaContent to use no padding.
In
`@apps/webapp/app/routes/_app.orgs`.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsx:
- Around line 849-852: The className passed to ClientTabsContent contains a
typo: replace the incorrect "f-full" token with "h-full" so the height utility
is applied correctly; update the className string in the ClientTabsContent JSX
(the element with value="graph") to use "h-full" instead of "f-full".
In
`@apps/webapp/app/routes/resources.orgs`.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsx:
- Around line 21-27: Wrap the call to request.json() in a try-catch so malformed
JSON returns a 400 instead of throwing; specifically, around the code that calls
request.json() before you call RequestSchema.safeParse, catch any error from
JSON parsing and return json({ success: false, error: "Invalid JSON", title:
null }, { status: 400 }); keep the existing RequestSchema.safeParse logic for
validated bodies and reference the same submission variable and response shape.
- Around line 59-65: The update lets any queryId be changed without verifying it
belongs to the current project/environment; restrict the update by either (A)
replacing prisma.customerQuery.update with prisma.customerQuery.updateMany({
where: { id: queryId, projectId: <currentProjectId>, environmentId:
<currentEnvId> }, data: { title } }) and verifying the returned count > 0, or
(B) first fetch the record with prisma.customerQuery.findUnique/findFirst({
where: { id: queryId } }), confirm its project/environment matches the current
project/env variables, then call prisma.customerQuery.update({ where: { id:
queryId }, data: { title } }); use the existing symbols queryId, title,
prisma.customerQuery.update/updateMany and the current project/env identifiers
in the file to implement this check.
In `@apps/webapp/app/services/queryService.server.ts`:
- Around line 104-112: The tenant inputs (organizationId, projectId,
environmentId) and enforcedWhereClause passed into executeQuery can diverge and
cause mismatched attribution for history/concurrency; update the executeQuery
parameter handling to validate and normalize tenant context by deriving the
enforcedWhereClause and history/concurrency keys from the canonical
organizationId/projectId/environmentId (or reject when inconsistent).
Specifically, in executeQuery (and the similar block around the other usage at
the 153-156 zone) check that any provided enforcedWhereClause matches the
computed clause for the given organizationId/projectId/environmentId (or rebuild
it from those IDs), and use the same canonical IDs to compute history and
customOrgConcurrencyLimit keys so all tenant guards are constructed from the
same source of truth.
In `@internal-packages/tsql/src/query/printer.ts`:
- Around line 2259-2267: The rootColumnSchema lookup currently calls
resolveFieldToColumnSchema([node.chain[0]]) which fails for qualified references
like ['runs','error',...]; change the input to include the table/alias when
present (e.g., use node.chain.length > 1 ? [node.chain[0], node.chain[1]] :
[node.chain[0]]) so resolveFieldToColumnSchema sees the table+column for JSON
columns; this ensures rootColumnSchema is correctly detected (so the .String
type hint is applied when this.queryHasGroupBy &&
!this.isInWhereComparisonContext()).
- Around line 1669-1733: createEnforcedGuard currently builds unqualified guard
expressions which can bind to the wrong table in multi-join queries; update
createConditionExpression to accept an optional tableAlias parameter and, when
provided, construct the Field.chain as [tableAlias, column] (instead of just
[column]) so resolveFieldChain will resolve to the correct table; then call
createConditionExpression(column, condition, tableAlias) from
createEnforcedGuard's loop and ensure existing logic in
createConditionExpression (used for between expressions and CompareOperation
building with createValueExpression and mapConditionOpToCompareOp) uses the new
fieldExpr with the qualified chain.
🧹 Nitpick comments (7)
apps/webapp/app/components/primitives/Callout.tsx (1)
8-14: Remove unusedChartBarIconimport.The
ChartBarIconimport at line 11 is not used anywhere in this file. It was likely replaced byCreditCardIconin the pricing variant (line 65).🧹 Proposed cleanup
import { ArrowTopRightOnSquareIcon, BookOpenIcon, - ChartBarIcon, CheckCircleIcon, ChevronRightIcon, } from "@heroicons/react/24/solid";apps/webapp/app/components/runs/v3/SharedFilters.tsx (1)
288-308: Prefertypealiases over interfaces for the TimeFilter types.
Line 288-308 uses interfaces, but the TS guideline preferstypealiases. Consider switching these totypefor consistency.♻️ Suggested refactor
-export interface TimeFilterApplyValues { +export type TimeFilterApplyValues = { period?: string; from?: string; to?: string; -} +}; -export interface TimeFilterProps { +export type TimeFilterProps = { defaultPeriod?: string; period?: string; from?: string; to?: string; /** Label name used in the filter display, defaults to "Created" */ labelName?: string; hideLabel?: boolean; applyShortcut?: ShortcutDefinition | undefined; /** Callback when the user applies a time filter selection, receives the applied values */ onValueChange?: (values: TimeFilterApplyValues) => void; /** When set an upgrade message will be shown if you select a period further back than this number of days */ maxPeriodDays?: number; -} +};As per coding guidelines, prefer types over interfaces.
apps/webapp/app/components/code/QueryResultsChart.tsx (1)
49-58: Prefer a type alias forQueryResultsChartProps.
This interface was modified; please switch it to atypeto align with repo TS style.♻️ Proposed change
-interface QueryResultsChartProps { +type QueryResultsChartProps = { rows: Record<string, unknown>[]; columns: OutputColumnMetadata[]; config: ChartConfiguration; fullLegend?: boolean; /** Callback when "View all" legend button is clicked */ onViewAllLegendItems?: () => void; /** When true, constrains legend to max 50% height with scrolling */ legendScrollable?: boolean; -} +};As per coding guidelines.
internal-packages/clickhouse/src/client/tsql.ts (1)
33-104: Prefer a type alias forExecuteTSQLOptions.
This interface was modified; please switch it to atypeto align with repo TS style.♻️ Proposed change
-export interface ExecuteTSQLOptions<TOut extends z.ZodSchema> { +export type ExecuteTSQLOptions<TOut extends z.ZodSchema> = { /** The name of the operation (for logging/tracing) */ name: string; /** The TSQL query string to execute */ query: string; /** The Zod schema for validating output rows */ schema: TOut; /** Schema registry defining allowed tables and columns */ tableSchema: TableSchema[]; /** * REQUIRED: Conditions always applied at the table level. * Must include tenant columns (e.g., organization_id) for multi-tenant tables. * Applied to every table reference including subqueries, CTEs, and JOINs. * * `@example` * ```typescript * { * // Tenant isolation * organization_id: { op: "eq", value: "org_123" }, * project_id: { op: "eq", value: "proj_456" }, * environment_id: { op: "eq", value: "env_789" }, * // Plan-based time limit * triggered_at: { op: "gte", value: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000) } * } * ``` */ enforcedWhereClause: Record<string, WhereClauseCondition | undefined>; /** Optional ClickHouse query settings */ clickhouseSettings?: ClickHouseSettings; /** Optional TSQL query settings (maxRows, timezone, etc.) */ querySettings?: Partial<QuerySettings>; /** * Whether to transform result values using the schema's valueMap * When enabled, internal ClickHouse values (e.g., 'COMPLETED_SUCCESSFULLY') * are converted to user-friendly display names (e.g., 'Completed') * `@default` true */ transformValues?: boolean; /** * Runtime field mappings for dynamic value translation. * Maps internal ClickHouse values to external user-facing values. * * `@example` * ```typescript * { * project: { "cm12345": "my-project-ref" }, * } * ``` */ fieldMappings?: FieldMappings; /** * Run EXPLAIN instead of executing the query. * Returns the ClickHouse execution plan with index information. * Should only be used by admins for debugging query performance. * `@default` false */ explain?: boolean; /** * Fallback WHERE conditions to apply when the user hasn't filtered on a column. * Key is the column name, value is the fallback condition. * These are applied at the AST level (top-level query only). * * `@example` * ```typescript * // Apply triggered_at >= 7 days ago if user doesn't filter on triggered_at * whereClauseFallback: { * triggered_at: { op: 'gte', value: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000) } * } * ``` */ whereClauseFallback?: Record<string, WhereClauseCondition>; -} +};As per coding guidelines.
internal-packages/tsql/src/query/printer_context.ts (1)
21-41: Prefer type aliases for new condition types.
Please switch these new interfaces to type aliases to align with the TS guideline. As per coding guidelines, use types over interfaces.♻️ Proposed refactor
-export interface SimpleComparisonCondition { +export type SimpleComparisonCondition = { /** The comparison operator */ op: "eq" | "neq" | "gt" | "gte" | "lt" | "lte"; /** The value to compare against */ value: Date | string | number; -} +}; -export interface BetweenCondition { +export type BetweenCondition = { /** The between operator */ op: "between"; /** The low bound of the range */ low: Date | string | number; /** The high bound of the range */ high: Date | string | number; -} +};apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsx (2)
291-312: Non-null assertion relies on control flow that could be fragile.The
requestedFromDate!assertion at line 311 is safe in the current logic because when we reach theelsebranch, neithertimeFilter.fromnortimeFilter.tois set, sorequestedFromDatewas assigned at line 299. However, this relies on implicit coupling between the two code blocks.Consider restructuring to make the invariant explicit, or add a defensive check:
♻️ Suggested improvement
} else { - triggeredAtFallback = { op: "gte", value: requestedFromDate! }; + // requestedFromDate is guaranteed non-null here because neither from nor to was specified, + // so we calculated it from the period at line 298-299 + triggeredAtFallback = { op: "gte", value: requestedFromDate ?? new Date(Date.now() - 7 * 24 * 60 * 60 * 1000) }; }
618-640: Title generation effect has a potential stale closure issue.The effect depends on
resultsbut also reads fromeditorRef.current?.getQuery(). If the query in the editor changes between the effect trigger and thegetQuery()call, the title generated won't match the results. While this is unlikely in practice due to React's batching, consider capturing the query at submission time instead.Additionally, the dependency array includes
organization.slug,project.slug,environment.slugwhich are used only to construct the action URL—these are unlikely to change during the component lifecycle, but including them is correct for completeness.
📜 Review details
Configuration used: Repository 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 (33)
apps/webapp/app/components/code/QueryResultsChart.tsxapps/webapp/app/components/code/TSQLResultsTable.tsxapps/webapp/app/components/primitives/AnimatedNumber.tsxapps/webapp/app/components/primitives/Callout.tsxapps/webapp/app/components/primitives/Resizable.tsxapps/webapp/app/components/primitives/charts/Card.tsxapps/webapp/app/components/primitives/charts/ChartLegendCompound.tsxapps/webapp/app/components/primitives/charts/ChartLine.tsxapps/webapp/app/components/primitives/charts/ChartRoot.tsxapps/webapp/app/components/runs/v3/SharedFilters.tsxapps/webapp/app/env.server.tsapps/webapp/app/presenters/v3/QueryPresenter.server.tsapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHelpSidebar.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHistoryPopover.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsxapps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsxapps/webapp/app/services/queryService.server.tsapps/webapp/app/v3/querySchemas.tsapps/webapp/app/v3/services/aiQueryTitleService.server.tsapps/webapp/package.jsoninternal-packages/clickhouse/schema/014_add_task_runs_v2_output_error_text.sqlinternal-packages/clickhouse/schema/015_update_output_error_text_to_extract_data.sqlinternal-packages/clickhouse/src/client/tsql.tsinternal-packages/clickhouse/src/index.tsinternal-packages/database/prisma/migrations/20260124203524_customer_query_add_title_remove_cost/migration.sqlinternal-packages/database/prisma/schema.prismainternal-packages/tsql/src/index.test.tsinternal-packages/tsql/src/index.tsinternal-packages/tsql/src/query/printer.test.tsinternal-packages/tsql/src/query/printer.tsinternal-packages/tsql/src/query/printer_context.tsinternal-packages/tsql/src/query/schema.tsinternal-packages/tsql/src/query/security.test.ts
💤 Files with no reviewable changes (1)
- apps/webapp/app/env.server.ts
🧰 Additional context used
📓 Path-based instructions (14)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.{ts,tsx}: Use types over interfaces for TypeScript
Avoid using enums; prefer string unions or const objects instead
**/*.{ts,tsx}: Always import tasks from@trigger.dev/sdk, never use@trigger.dev/sdk/v3or deprecatedclient.defineJobpattern
Every Trigger.dev task must be exported and have a uniqueidproperty with no timeouts in the run function
Files:
apps/webapp/app/components/code/TSQLResultsTable.tsxapps/webapp/app/presenters/v3/QueryPresenter.server.tsapps/webapp/app/components/primitives/Callout.tsxinternal-packages/clickhouse/src/index.tsinternal-packages/tsql/src/query/schema.tsapps/webapp/app/v3/services/aiQueryTitleService.server.tsapps/webapp/app/components/primitives/charts/ChartLine.tsxapps/webapp/app/components/primitives/Resizable.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHelpSidebar.tsxapps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsxapps/webapp/app/components/primitives/charts/ChartRoot.tsxapps/webapp/app/components/primitives/charts/Card.tsxapps/webapp/app/components/primitives/AnimatedNumber.tsxinternal-packages/tsql/src/index.test.tsinternal-packages/tsql/src/query/security.test.tsapps/webapp/app/v3/querySchemas.tsapps/webapp/app/components/runs/v3/SharedFilters.tsxinternal-packages/clickhouse/src/client/tsql.tsinternal-packages/tsql/src/query/printer_context.tsapps/webapp/app/components/code/QueryResultsChart.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHistoryPopover.tsxapps/webapp/app/components/primitives/charts/ChartLegendCompound.tsxinternal-packages/tsql/src/query/printer.tsinternal-packages/tsql/src/query/printer.test.tsinternal-packages/tsql/src/index.tsapps/webapp/app/services/queryService.server.tsapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsx
{packages/core,apps/webapp}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use zod for validation in packages/core and apps/webapp
Files:
apps/webapp/app/components/code/TSQLResultsTable.tsxapps/webapp/app/presenters/v3/QueryPresenter.server.tsapps/webapp/app/components/primitives/Callout.tsxapps/webapp/app/v3/services/aiQueryTitleService.server.tsapps/webapp/app/components/primitives/charts/ChartLine.tsxapps/webapp/app/components/primitives/Resizable.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHelpSidebar.tsxapps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsxapps/webapp/app/components/primitives/charts/ChartRoot.tsxapps/webapp/app/components/primitives/charts/Card.tsxapps/webapp/app/components/primitives/AnimatedNumber.tsxapps/webapp/app/v3/querySchemas.tsapps/webapp/app/components/runs/v3/SharedFilters.tsxapps/webapp/app/components/code/QueryResultsChart.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHistoryPopover.tsxapps/webapp/app/components/primitives/charts/ChartLegendCompound.tsxapps/webapp/app/services/queryService.server.tsapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use function declarations instead of default exports
Import from
@trigger.dev/coreusing subpaths only, never import from root
Files:
apps/webapp/app/components/code/TSQLResultsTable.tsxapps/webapp/app/presenters/v3/QueryPresenter.server.tsapps/webapp/app/components/primitives/Callout.tsxinternal-packages/clickhouse/src/index.tsinternal-packages/tsql/src/query/schema.tsapps/webapp/app/v3/services/aiQueryTitleService.server.tsapps/webapp/app/components/primitives/charts/ChartLine.tsxapps/webapp/app/components/primitives/Resizable.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHelpSidebar.tsxapps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsxapps/webapp/app/components/primitives/charts/ChartRoot.tsxapps/webapp/app/components/primitives/charts/Card.tsxapps/webapp/app/components/primitives/AnimatedNumber.tsxinternal-packages/tsql/src/index.test.tsinternal-packages/tsql/src/query/security.test.tsapps/webapp/app/v3/querySchemas.tsapps/webapp/app/components/runs/v3/SharedFilters.tsxinternal-packages/clickhouse/src/client/tsql.tsinternal-packages/tsql/src/query/printer_context.tsapps/webapp/app/components/code/QueryResultsChart.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHistoryPopover.tsxapps/webapp/app/components/primitives/charts/ChartLegendCompound.tsxinternal-packages/tsql/src/query/printer.tsinternal-packages/tsql/src/query/printer.test.tsinternal-packages/tsql/src/index.tsapps/webapp/app/services/queryService.server.tsapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsx
apps/webapp/app/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)
Access all environment variables through the
envexport ofenv.server.tsinstead of directly accessingprocess.envin the Trigger.dev webapp
Files:
apps/webapp/app/components/code/TSQLResultsTable.tsxapps/webapp/app/presenters/v3/QueryPresenter.server.tsapps/webapp/app/components/primitives/Callout.tsxapps/webapp/app/v3/services/aiQueryTitleService.server.tsapps/webapp/app/components/primitives/charts/ChartLine.tsxapps/webapp/app/components/primitives/Resizable.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHelpSidebar.tsxapps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsxapps/webapp/app/components/primitives/charts/ChartRoot.tsxapps/webapp/app/components/primitives/charts/Card.tsxapps/webapp/app/components/primitives/AnimatedNumber.tsxapps/webapp/app/v3/querySchemas.tsapps/webapp/app/components/runs/v3/SharedFilters.tsxapps/webapp/app/components/code/QueryResultsChart.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHistoryPopover.tsxapps/webapp/app/components/primitives/charts/ChartLegendCompound.tsxapps/webapp/app/services/queryService.server.tsapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsx
apps/webapp/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)
apps/webapp/**/*.{ts,tsx}: When importing from@trigger.dev/corein the webapp, use subpath exports from the package.json instead of importing from the root path
Follow the Remix 2.1.0 and Express server conventions when updating the main trigger.dev webappAccess environment variables via
envexport fromapps/webapp/app/env.server.ts, never useprocess.envdirectly
Files:
apps/webapp/app/components/code/TSQLResultsTable.tsxapps/webapp/app/presenters/v3/QueryPresenter.server.tsapps/webapp/app/components/primitives/Callout.tsxapps/webapp/app/v3/services/aiQueryTitleService.server.tsapps/webapp/app/components/primitives/charts/ChartLine.tsxapps/webapp/app/components/primitives/Resizable.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHelpSidebar.tsxapps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsxapps/webapp/app/components/primitives/charts/ChartRoot.tsxapps/webapp/app/components/primitives/charts/Card.tsxapps/webapp/app/components/primitives/AnimatedNumber.tsxapps/webapp/app/v3/querySchemas.tsapps/webapp/app/components/runs/v3/SharedFilters.tsxapps/webapp/app/components/code/QueryResultsChart.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHistoryPopover.tsxapps/webapp/app/components/primitives/charts/ChartLegendCompound.tsxapps/webapp/app/services/queryService.server.tsapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsx
**/*.{js,ts,jsx,tsx,json,md,yaml,yml}
📄 CodeRabbit inference engine (AGENTS.md)
Format code using Prettier before committing
Files:
apps/webapp/app/components/code/TSQLResultsTable.tsxapps/webapp/app/presenters/v3/QueryPresenter.server.tsapps/webapp/package.jsonapps/webapp/app/components/primitives/Callout.tsxinternal-packages/clickhouse/src/index.tsinternal-packages/tsql/src/query/schema.tsapps/webapp/app/v3/services/aiQueryTitleService.server.tsapps/webapp/app/components/primitives/charts/ChartLine.tsxapps/webapp/app/components/primitives/Resizable.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHelpSidebar.tsxapps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsxapps/webapp/app/components/primitives/charts/ChartRoot.tsxapps/webapp/app/components/primitives/charts/Card.tsxapps/webapp/app/components/primitives/AnimatedNumber.tsxinternal-packages/tsql/src/index.test.tsinternal-packages/tsql/src/query/security.test.tsapps/webapp/app/v3/querySchemas.tsapps/webapp/app/components/runs/v3/SharedFilters.tsxinternal-packages/clickhouse/src/client/tsql.tsinternal-packages/tsql/src/query/printer_context.tsapps/webapp/app/components/code/QueryResultsChart.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHistoryPopover.tsxapps/webapp/app/components/primitives/charts/ChartLegendCompound.tsxinternal-packages/tsql/src/query/printer.tsinternal-packages/tsql/src/query/printer.test.tsinternal-packages/tsql/src/index.tsapps/webapp/app/services/queryService.server.tsapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsx
internal-packages/database/prisma/migrations/**/*.sql
📄 CodeRabbit inference engine (CLAUDE.md)
internal-packages/database/prisma/migrations/**/*.sql: When editing the Prisma schema, remove extraneous migration lines related to specific tables:_BackgroundWorkerToBackgroundWorkerFile,_BackgroundWorkerToTaskQueue,_TaskRunToTaskRunTag,_WaitpointRunConnections,_completedWaitpoints,SecretStore_key_idx, and unrelatedTaskRunindexes
Database indexes must use CONCURRENTLY to avoid table locks and must be in their own separate migration file
Files:
internal-packages/database/prisma/migrations/20260124203524_customer_query_add_title_remove_cost/migration.sql
**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/otel-metrics.mdc)
**/*.ts: When creating or editing OTEL metrics (counters, histograms, gauges), ensure metric attributes have low cardinality by using only enums, booleans, bounded error codes, or bounded shard IDs
Do not use high-cardinality attributes in OTEL metrics such as UUIDs/IDs (envId, userId, runId, projectId, organizationId), unbounded integers (itemCount, batchSize, retryCount), timestamps (createdAt, startTime), or free-form strings (errorMessage, taskName, queueName)
When exporting OTEL metrics via OTLP to Prometheus, be aware that the exporter automatically adds unit suffixes to metric names (e.g., 'my_duration_ms' becomes 'my_duration_ms_milliseconds', 'my_counter' becomes 'my_counter_total'). Account for these transformations when writing Grafana dashboards or Prometheus queries
Files:
apps/webapp/app/presenters/v3/QueryPresenter.server.tsinternal-packages/clickhouse/src/index.tsinternal-packages/tsql/src/query/schema.tsapps/webapp/app/v3/services/aiQueryTitleService.server.tsinternal-packages/tsql/src/index.test.tsinternal-packages/tsql/src/query/security.test.tsapps/webapp/app/v3/querySchemas.tsinternal-packages/clickhouse/src/client/tsql.tsinternal-packages/tsql/src/query/printer_context.tsinternal-packages/tsql/src/query/printer.tsinternal-packages/tsql/src/query/printer.test.tsinternal-packages/tsql/src/index.tsapps/webapp/app/services/queryService.server.ts
internal-packages/clickhouse/schema/**/*.sql
📄 CodeRabbit inference engine (CLAUDE.md)
internal-packages/clickhouse/schema/**/*.sql: ClickHouse migrations must use Goose format with-- +goose Upand-- +goose Downmarkers
Follow ClickHouse naming conventions:raw_prefix for input tables,_v1,_v2suffixes for versioning,_mv_v1suffix for materialized views
Files:
internal-packages/clickhouse/schema/014_add_task_runs_v2_output_error_text.sqlinternal-packages/clickhouse/schema/015_update_output_error_text_to_extract_data.sql
apps/webapp/app/v3/services/**/*.server.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)
Organize services in the webapp following the pattern
app/v3/services/*/*.server.ts
Files:
apps/webapp/app/v3/services/aiQueryTitleService.server.ts
**/*.{test,spec}.{ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use vitest for all tests in the Trigger.dev repository
Files:
internal-packages/tsql/src/index.test.tsinternal-packages/tsql/src/query/security.test.tsinternal-packages/tsql/src/query/printer.test.ts
**/*.test.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.test.{ts,tsx,js,jsx}: Test files should live beside the files under test and use descriptivedescribeanditblocks
Tests should avoid mocks or stubs and use the helpers from@internal/testcontainerswhen Redis or Postgres are needed
Use vitest for running unit tests
**/*.test.{ts,tsx,js,jsx}: Use vitest exclusively for testing and never mock anything - use testcontainers instead
Place test files next to source files with naming pattern: source file (e.g.,MyService.ts) →MyService.test.ts
Files:
internal-packages/tsql/src/index.test.tsinternal-packages/tsql/src/query/security.test.tsinternal-packages/tsql/src/query/printer.test.ts
**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use testcontainers helpers (
redisTest,postgresTest,containerTest) from@internal/testcontainersfor Redis/PostgreSQL testing instead of mocks
Files:
internal-packages/tsql/src/index.test.tsinternal-packages/tsql/src/query/security.test.tsinternal-packages/tsql/src/query/printer.test.ts
apps/webapp/app/services/**/*.server.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)
Separate testable services from configuration files; follow the pattern of
realtimeClient.server.ts(testable service) andrealtimeClientGlobal.server.ts(configuration) in the webapp
Files:
apps/webapp/app/services/queryService.server.ts
🧠 Learnings (24)
📚 Learning: 2026-01-15T11:50:06.067Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to internal-packages/database/prisma/migrations/**/*.sql : When editing the Prisma schema, remove extraneous migration lines related to specific tables: `_BackgroundWorkerToBackgroundWorkerFile`, `_BackgroundWorkerToTaskQueue`, `_TaskRunToTaskRunTag`, `_WaitpointRunConnections`, `_completedWaitpoints`, `SecretStore_key_idx`, and unrelated `TaskRun` indexes
Applied to files:
internal-packages/database/prisma/migrations/20260124203524_customer_query_add_title_remove_cost/migration.sqlinternal-packages/clickhouse/schema/014_add_task_runs_v2_output_error_text.sqlinternal-packages/clickhouse/schema/015_update_output_error_text_to_extract_data.sqlinternal-packages/database/prisma/schema.prisma
📚 Learning: 2025-11-27T16:26:58.661Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/webapp.mdc:0-0
Timestamp: 2025-11-27T16:26:58.661Z
Learning: Applies to apps/webapp/**/*.{ts,tsx} : Follow the Remix 2.1.0 and Express server conventions when updating the main trigger.dev webapp
Applied to files:
apps/webapp/package.jsonapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHelpSidebar.tsxapps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsx
📚 Learning: 2025-11-27T16:26:58.661Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/webapp.mdc:0-0
Timestamp: 2025-11-27T16:26:58.661Z
Learning: Applies to apps/webapp/**/*.{ts,tsx} : When importing from `trigger.dev/core` in the webapp, use subpath exports from the package.json instead of importing from the root path
Applied to files:
apps/webapp/package.json
📚 Learning: 2025-11-27T16:26:37.432Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T16:26:37.432Z
Learning: The webapp at apps/webapp is a Remix 2.1 application using Node.js v20
Applied to files:
apps/webapp/package.json
📚 Learning: 2025-11-27T16:26:58.661Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/webapp.mdc:0-0
Timestamp: 2025-11-27T16:26:58.661Z
Learning: Applies to apps/webapp/app/**/*.{ts,tsx} : Access all environment variables through the `env` export of `env.server.ts` instead of directly accessing `process.env` in the Trigger.dev webapp
Applied to files:
apps/webapp/package.json
📚 Learning: 2025-11-27T16:26:37.432Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T16:26:37.432Z
Learning: Applies to packages/trigger-sdk/**/*.{ts,tsx} : In the Trigger.dev SDK (packages/trigger-sdk), prefer isomorphic code like fetch and ReadableStream instead of Node.js-specific code
Applied to files:
apps/webapp/package.json
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `trigger.dev/sdk/v3` for all imports in Trigger.dev tasks
Applied to files:
apps/webapp/package.json
📚 Learning: 2026-01-15T11:50:06.067Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to **/*.{ts,tsx} : Always import tasks from `trigger.dev/sdk`, never use `trigger.dev/sdk/v3` or deprecated `client.defineJob` pattern
Applied to files:
apps/webapp/package.json
📚 Learning: 2026-01-15T11:50:06.067Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Import from `trigger.dev/core` using subpaths only, never import from root
Applied to files:
apps/webapp/package.json
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `schemaTask()` from `trigger.dev/sdk/v3` with Zod schema for payload validation
Applied to files:
apps/webapp/package.json
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger.config.ts : Use build extensions in trigger.config.ts (additionalFiles, additionalPackages, aptGet, prismaExtension, etc.) to customize the build
Applied to files:
apps/webapp/package.json
📚 Learning: 2026-01-15T11:50:06.067Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to **/*.{ts,tsx} : Every Trigger.dev task must be exported and have a unique `id` property with no timeouts in the run function
Applied to files:
apps/webapp/package.json
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use the `task()` function from `trigger.dev/sdk/v3` to define tasks with id and run properties
Applied to files:
apps/webapp/package.json
📚 Learning: 2025-10-08T11:48:12.327Z
Learnt from: nicktrn
Repo: triggerdotdev/trigger.dev PR: 2593
File: packages/core/src/v3/workers/warmStartClient.ts:168-170
Timestamp: 2025-10-08T11:48:12.327Z
Learning: The trigger.dev runners execute only in Node 21 and 22 environments, so modern Node.js APIs like AbortSignal.any (introduced in v20.3.0) are supported.
Applied to files:
apps/webapp/package.json
📚 Learning: 2026-01-15T11:50:06.067Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to internal-packages/clickhouse/schema/**/*.sql : Follow ClickHouse naming conventions: `raw_` prefix for input tables, `_v1`, `_v2` suffixes for versioning, `_mv_v1` suffix for materialized views
Applied to files:
internal-packages/clickhouse/schema/014_add_task_runs_v2_output_error_text.sqlinternal-packages/clickhouse/schema/015_update_output_error_text_to_extract_data.sql
📚 Learning: 2026-01-15T11:50:06.067Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to internal-packages/clickhouse/schema/**/*.sql : ClickHouse migrations must use Goose format with `-- +goose Up` and `-- +goose Down` markers
Applied to files:
internal-packages/clickhouse/schema/014_add_task_runs_v2_output_error_text.sqlinternal-packages/clickhouse/schema/015_update_output_error_text_to_extract_data.sql
📚 Learning: 2025-12-08T15:19:56.823Z
Learnt from: 0ski
Repo: triggerdotdev/trigger.dev PR: 2760
File: apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx:278-281
Timestamp: 2025-12-08T15:19:56.823Z
Learning: In apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx, the tableState search parameter uses intentional double-encoding: the parameter value contains a URL-encoded URLSearchParams string, so decodeURIComponent(value("tableState") ?? "") is required to fully decode it before parsing with new URLSearchParams(). This pattern allows bundling multiple filter/pagination params as a single search parameter.
Applied to files:
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHelpSidebar.tsxapps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsxinternal-packages/tsql/src/query/security.test.tsapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHistoryPopover.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsx
📚 Learning: 2025-07-21T12:52:44.342Z
Learnt from: ericallam
Repo: triggerdotdev/trigger.dev PR: 2284
File: apps/webapp/app/services/realtimeClient.server.ts:111-127
Timestamp: 2025-07-21T12:52:44.342Z
Learning: Electric (the database service used in the realtimeClient) has built-in SQL injection protection and safely handles whereClause parameters passed via URL parameters, so direct string interpolation of runId values into SQL where clauses is safe when using Electric.
Applied to files:
internal-packages/tsql/src/query/security.test.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Scope idempotency keys globally or to current run using the scope parameter
Applied to files:
apps/webapp/app/v3/querySchemas.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger.config.ts : Set default maximum duration in trigger.config.ts using `maxDuration` property
Applied to files:
apps/webapp/app/components/runs/v3/SharedFilters.tsx
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Limit task duration using the `maxDuration` property (in seconds)
Applied to files:
apps/webapp/app/components/runs/v3/SharedFilters.tsx
📚 Learning: 2025-07-12T18:06:04.133Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 2264
File: apps/webapp/app/services/runsRepository.server.ts:172-174
Timestamp: 2025-07-12T18:06:04.133Z
Learning: In apps/webapp/app/services/runsRepository.server.ts, the in-memory status filtering after fetching runs from Prisma is intentionally used as a workaround for ClickHouse data delays. This approach is acceptable because the result set is limited to a maximum of 100 runs due to pagination, making the performance impact negligible.
Applied to files:
internal-packages/clickhouse/src/client/tsql.ts
📚 Learning: 2025-11-27T16:26:37.432Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T16:26:37.432Z
Learning: Applies to internal-packages/database/**/*.{ts,tsx} : Use Prisma for database interactions in internal-packages/database with PostgreSQL
Applied to files:
apps/webapp/app/services/queryService.server.tsapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsx
📚 Learning: 2026-01-12T17:18:09.451Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 2870
File: apps/webapp/app/services/redisConcurrencyLimiter.server.ts:56-66
Timestamp: 2026-01-12T17:18:09.451Z
Learning: In `apps/webapp/app/services/redisConcurrencyLimiter.server.ts`, the query concurrency limiter will not be deployed with Redis Cluster mode, so multi-key operations (keyKey and globalKey in different hash slots) are acceptable and will function correctly in standalone Redis mode.
Applied to files:
apps/webapp/app/services/queryService.server.ts
🧬 Code graph analysis (10)
apps/webapp/app/v3/services/aiQueryTitleService.server.ts (1)
apps/webapp/app/env.server.ts (1)
env(1320-1320)
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHelpSidebar.tsx (6)
apps/webapp/app/components/primitives/ClientTabs.tsx (3)
ClientTabsList(211-211)ClientTabsTrigger(211-211)ClientTabsContent(211-211)apps/webapp/app/assets/icons/AISparkleIcon.tsx (1)
AISparkleIcon(1-31)apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/AITabContent.tsx (1)
AITabContent(6-65)apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/TRQLGuideContent.tsx (1)
TRQLGuideContent(71-1203)apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/TableSchemaContent.tsx (1)
TableSchemaContent(45-67)apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/ExamplesContent.tsx (1)
ExamplesContent(60-81)
apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsx (6)
apps/webapp/app/utils/pathBuilder.ts (1)
EnvironmentParamSchema(26-28)packages/core/src/v3/apps/http.ts (1)
json(65-75)apps/webapp/app/models/project.server.ts (1)
findProjectBySlug(136-147)apps/webapp/app/models/runtimeEnvironment.server.ts (1)
findEnvironmentBySlug(116-145)apps/webapp/app/env.server.ts (1)
env(1320-1320)apps/webapp/app/v3/services/aiQueryTitleService.server.ts (1)
AIQueryTitleService(15-71)
internal-packages/tsql/src/index.test.ts (2)
internal-packages/tsql/src/index.ts (2)
WhereClauseCondition(127-127)compileTSQL(538-566)internal-packages/tsql/src/query/printer_context.ts (1)
WhereClauseCondition(47-47)
apps/webapp/app/v3/querySchemas.ts (1)
internal-packages/tsql/src/query/schema.ts (1)
column(354-366)
apps/webapp/app/components/runs/v3/SharedFilters.tsx (3)
apps/webapp/app/components/primitives/Callout.tsx (1)
Callout(73-170)apps/webapp/app/components/primitives/Buttons.tsx (1)
LinkButton(335-403)apps/webapp/app/utils/pathBuilder.ts (1)
organizationBillingPath(116-118)
internal-packages/clickhouse/src/client/tsql.ts (3)
internal-packages/tsql/src/index.ts (1)
WhereClauseCondition(127-127)internal-packages/clickhouse/src/index.ts (1)
WhereClauseCondition(59-59)internal-packages/tsql/src/query/printer_context.ts (1)
WhereClauseCondition(47-47)
apps/webapp/app/components/primitives/charts/ChartLegendCompound.tsx (2)
apps/webapp/app/utils/cn.ts (1)
cn(77-79)apps/webapp/app/components/primitives/AnimatedNumber.tsx (1)
AnimatedNumber(22-58)
internal-packages/tsql/src/index.ts (4)
internal-packages/tsql/src/query/printer_context.ts (3)
SimpleComparisonCondition(24-29)WhereClauseCondition(47-47)createPrinterContext(249-256)internal-packages/clickhouse/src/client/tsql.ts (1)
WhereClauseCondition(28-28)internal-packages/clickhouse/src/index.ts (1)
WhereClauseCondition(59-59)internal-packages/tsql/src/query/schema.ts (1)
createSchemaRegistry(371-387)
apps/webapp/app/services/queryService.server.ts (3)
internal-packages/clickhouse/src/client/tsql.ts (1)
TSQLQueryResult(133-133)apps/webapp/app/services/queryConcurrencyLimiter.server.ts (2)
queryConcurrencyLimiter(19-22)GLOBAL_CONCURRENCY_LIMIT(28-28)internal-packages/tsql/src/query/errors.ts (1)
QueryError(43-45)
⏰ 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). (20)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (8, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (5, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (8, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (4, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 8)
- GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
- GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
- GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
- GitHub Check: typecheck / typecheck
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
| height: `${rowVirtualizer.getTotalSize()}px`, | ||
| position: "relative", | ||
| }} | ||
| className="bg-background-dimmed divide-y divide-charcoal-700" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
# First, check the actual file and code at line 1142
wc -l apps/webapp/app/components/code/TSQLResultsTable.tsxRepository: triggerdotdev/trigger.dev
Length of output: 126
🏁 Script executed:
# Read the file around line 1142 to understand the context
sed -n '1130,1170p' apps/webapp/app/components/code/TSQLResultsTable.tsxRepository: triggerdotdev/trigger.dev
Length of output: 1554
🏁 Script executed:
# Search for how virtualization is set up in this file
rg -n "useVirtualizer|rowVirtualizer" apps/webapp/app/components/code/TSQLResultsTable.tsx -B2 -A5Repository: triggerdotdev/trigger.dev
Length of output: 1386
🏁 Script executed:
# Check if divide-y is used elsewhere with virtualized content
rg -n "divide-y" apps/webapp --type tsx -B5 -A5 | head -100Repository: triggerdotdev/trigger.dev
Length of output: 96
🏁 Script executed:
# Find ROW_HEIGHT definition
rg -n "ROW_HEIGHT" apps/webapp/app/components/code/TSQLResultsTable.tsxRepository: triggerdotdev/trigger.dev
Length of output: 168
🏁 Script executed:
# Check if there are other virtualized tables in the codebase
rg -n "useVirtualizer" apps/webapp --type ts --type tsx -lRepository: triggerdotdev/trigger.dev
Length of output: 96
🏁 Script executed:
# Search for divide-y usage in the codebase
rg -n "divide-y" apps/webapp -B3 -A3 --type ts --type tsx | head -60Repository: triggerdotdev/trigger.dev
Length of output: 96
🏁 Script executed:
# Check the Grid and absolute positioning behavior - look for similar patterns
rg -n "display.*grid.*position.*relative" apps/webapp --type ts --type tsx -B2 -A10 | head -80Repository: triggerdotdev/trigger.dev
Length of output: 96
🏁 Script executed:
# Search for virtualized tables without type flags
rg "useVirtualizer" apps/webapp -B2 -A8 | head -100Repository: triggerdotdev/trigger.dev
Length of output: 11147
🏁 Script executed:
# Look for divide-y usage more broadly
rg "divide-y" apps/webapp | head -20Repository: triggerdotdev/trigger.dev
Length of output: 50383
🏁 Script executed:
# Check Tailwind documentation patterns - look for how divide-y is actually implemented in the codebase
rg "divide-y|divide-x|divide-" --max-count=30 apps/webappRepository: triggerdotdev/trigger.dev
Length of output: 50383
🏁 Script executed:
# Look at actual rendered output or comments about this table
grep -n "divide\|border" apps/webapp/app/components/code/TSQLResultsTable.tsx | head -20Repository: triggerdotdev/trigger.dev
Length of output: 562
🏁 Script executed:
# Check if there are any visual tests or storybook files for this component
find apps/webapp -name "*TSQLResultsTable*" -o -name "*results*table*" 2>/dev/nullRepository: triggerdotdev/trigger.dev
Length of output: 121
divide-y won't render visible dividers with absolutely positioned virtualized rows.
The divide-y utility applies borders via CSS sibling selectors (> * + *), but with absolutely positioned children in a grid container, borders paint at the natural flow position (top of container) rather than at each row's transformed Y position. This won't produce visible dividers between rows as intended.
Add border-b border-charcoal-700 directly to each row instead:
Suggested fix
<tr
key={row.id}
data-index={virtualRow.index}
- className="group/row hover:bg-charcoal-800"
+ className="group/row border-b border-charcoal-700 hover:bg-charcoal-800"
style={{
display: "flex",
position: "absolute",
transform: `translateY(${virtualRow.start}px)`,
width: "100%",
}}
>Then remove divide-y divide-charcoal-700 from the tbody className.
🤖 Prompt for AI Agents
In `@apps/webapp/app/components/code/TSQLResultsTable.tsx` at line 1142, The tbody
in TSQLResultsTable uses "divide-y divide-charcoal-700" which doesn't show
dividers for absolutely positioned/virtualized rows; remove those utilities from
the tbody className and instead add "border-b border-charcoal-700" to the
element that renders each virtualized row (the per-row container/render function
used by the virtualizer — e.g., the row renderer / row element inside the map or
renderRow handler) so each row gets its own bottom border; update any row
className/props (not the tbody) to include the border utilities and remove the
divide-y/divide-charcoal-700 from the tbody.
| export function AnimatedNumber({ | ||
| value, | ||
| duration = 0.5, | ||
| decimalPlaces, | ||
| }: { | ||
| value: number; | ||
| duration?: number; | ||
| /** Number of decimal places to display. If not provided, auto-detects based on value. */ | ||
| decimalPlaces?: number; | ||
| }) { | ||
| const motionValue = useMotionValue(value); | ||
| let display = useTransform(motionValue, (current) => Math.round(current).toLocaleString()); | ||
|
|
||
| // Determine decimal places - use provided value or auto-detect | ||
| const decimals = useMemo( | ||
| () => (decimalPlaces !== undefined ? decimalPlaces : getDecimalPlaces(value)), | ||
| [decimalPlaces, value] | ||
| ); | ||
|
|
||
| const display = useTransform(motionValue, (current) => { | ||
| if (decimals === 0) { | ||
| return Math.round(current).toLocaleString(); | ||
| } | ||
| return current.toLocaleString(undefined, { | ||
| minimumFractionDigits: decimals, | ||
| maximumFractionDigits: decimals, | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clamp and sanitize decimalPlaces before toLocaleString.
Invalid values (negative, non-integer, >20, NaN) will throw at runtime and break rendering. Guard by normalizing to a finite integer within 0–20.
✅ Suggested fix
- const decimals = useMemo(
- () => (decimalPlaces !== undefined ? decimalPlaces : getDecimalPlaces(value)),
- [decimalPlaces, value]
- );
+ const decimals = useMemo(() => {
+ const raw =
+ decimalPlaces !== undefined ? decimalPlaces : getDecimalPlaces(value);
+ if (!Number.isFinite(raw)) return 0;
+ return Math.min(20, Math.max(0, Math.round(raw)));
+ }, [decimalPlaces, value]);🤖 Prompt for AI Agents
In `@apps/webapp/app/components/primitives/AnimatedNumber.tsx` around lines 22 -
47, The decimals value used in the useTransform callback must be clamped and
sanitized before being passed to toLocaleString to avoid runtime throws from
invalid values; update the AnimatedNumber component to compute a safeDecimals
(based on decimalPlaces or getDecimalPlaces(value)) by coercing to a finite
number, rounding to an integer, and clamping into the 0–20 range (e.g., use
Number.isFinite, Math.round, Math.max/Math.min) and then use safeDecimals inside
the display transformer and any branch that checks for zero; ensure NaN,
negatives, non-integers and >20 are handled by this normalization so
toLocaleString always receives a valid 0–20 integer.
| // Calculate if the current selection exceeds maxPeriodDays | ||
| const exceedsMaxPeriod = (() => { | ||
| if (!maxPeriodDays) return false; | ||
|
|
||
| if (activeSection === "duration") { | ||
| const periodToCheck = selectedPeriod === "custom" ? `${customValue}${customUnit}` : selectedPeriod; | ||
| if (!periodToCheck) return false; | ||
| return periodToDays(periodToCheck) > maxPeriodDays; | ||
| } else { | ||
| // For date range, check if fromValue is further back than maxPeriodDays | ||
| return dateRangeToDays(fromValue) > maxPeriodDays; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Enforce maxPeriodDays for “to-only” date ranges.
Line 441-452 only checks fromValue, so selecting just a far‑past “to” date bypasses the cap and upgrade prompt. Consider checking the earliest of fromValue/toValue.
🐛 Suggested fix
- } else {
- // For date range, check if fromValue is further back than maxPeriodDays
- return dateRangeToDays(fromValue) > maxPeriodDays;
- }
+ } else {
+ // For date range, check earliest bound (from or to)
+ const earliest =
+ fromValue && toValue ? (fromValue < toValue ? fromValue : toValue) : fromValue ?? toValue;
+ return dateRangeToDays(earliest) > maxPeriodDays;
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Calculate if the current selection exceeds maxPeriodDays | |
| const exceedsMaxPeriod = (() => { | |
| if (!maxPeriodDays) return false; | |
| if (activeSection === "duration") { | |
| const periodToCheck = selectedPeriod === "custom" ? `${customValue}${customUnit}` : selectedPeriod; | |
| if (!periodToCheck) return false; | |
| return periodToDays(periodToCheck) > maxPeriodDays; | |
| } else { | |
| // For date range, check if fromValue is further back than maxPeriodDays | |
| return dateRangeToDays(fromValue) > maxPeriodDays; | |
| } | |
| // Calculate if the current selection exceeds maxPeriodDays | |
| const exceedsMaxPeriod = (() => { | |
| if (!maxPeriodDays) return false; | |
| if (activeSection === "duration") { | |
| const periodToCheck = selectedPeriod === "custom" ? `${customValue}${customUnit}` : selectedPeriod; | |
| if (!periodToCheck) return false; | |
| return periodToDays(periodToCheck) > maxPeriodDays; | |
| } else { | |
| // For date range, check earliest bound (from or to) | |
| const earliest = | |
| fromValue && toValue ? (fromValue < toValue ? fromValue : toValue) : fromValue ?? toValue; | |
| return dateRangeToDays(earliest) > maxPeriodDays; | |
| } |
🤖 Prompt for AI Agents
In `@apps/webapp/app/components/runs/v3/SharedFilters.tsx` around lines 441 - 452,
The exceedsMaxPeriod calculation only checks fromValue for date ranges and thus
misses cases where only toValue is set; update the date-range branch in
exceedsMaxPeriod to compute the earliest selected date (min of fromValue and
toValue) and compare its age via dateRangeToDays (or convert the computed range
to days) against maxPeriodDays so "to-only" selections that exceed maxPeriodDays
also return true; locate the exceedsMaxPeriod IIFE and adjust the date range
logic that references activeSection, fromValue, toValue, dateRangeToDays, and
maxPeriodDays accordingly.
.../_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHelpSidebar.tsx
Show resolved
Hide resolved
| <ClientTabsContent | ||
| value="schema" | ||
| className="min-h-0 flex-1 overflow-y-auto p-3 scrollbar-thin scrollbar-track-transparent scrollbar-thumb-charcoal-600" | ||
| > | ||
| <TableSchemaContent /> | ||
| <div className="min-w-64 p-3"> | ||
| <TableSchemaContent /> | ||
| </div> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same double padding issue on "schema" tab.
♻️ Suggested fix
<ClientTabsContent
value="schema"
- className="min-h-0 flex-1 overflow-y-auto p-3 scrollbar-thin scrollbar-track-transparent scrollbar-thumb-charcoal-600"
+ className="min-h-0 flex-1 overflow-y-auto scrollbar-thin scrollbar-track-transparent scrollbar-thumb-charcoal-600"
>
<div className="min-w-64 p-3">
<TableSchemaContent />
</div>
</ClientTabsContent>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <ClientTabsContent | |
| value="schema" | |
| className="min-h-0 flex-1 overflow-y-auto p-3 scrollbar-thin scrollbar-track-transparent scrollbar-thumb-charcoal-600" | |
| > | |
| <TableSchemaContent /> | |
| <div className="min-w-64 p-3"> | |
| <TableSchemaContent /> | |
| </div> | |
| <ClientTabsContent | |
| value="schema" | |
| className="min-h-0 flex-1 overflow-y-auto scrollbar-thin scrollbar-track-transparent scrollbar-thumb-charcoal-600" | |
| > | |
| <div className="min-w-64 p-3"> | |
| <TableSchemaContent /> | |
| </div> | |
| </ClientTabsContent> |
🤖 Prompt for AI Agents
In
`@apps/webapp/app/routes/_app.orgs`.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHelpSidebar.tsx
around lines 78 - 84, The "schema" tab shows double padding because both
ClientTabsContent (value="schema") and the inner div around TableSchemaContent
apply p-3; remove the redundant padding by deleting or changing the inner div's
padding class (the div wrapping TableSchemaContent) to p-0 (or remove p-3) so
only ClientTabsContent provides spacing; update the inner wrapper surrounding
TableSchemaContent to use no padding.
| // Parse the request body | ||
| const data = await request.json(); | ||
| const submission = RequestSchema.safeParse(data); | ||
|
|
||
| if (!submission.success) { | ||
| return json({ success: false as const, error: "Invalid request data", title: null }, { status: 400 }); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrap request.json() in try-catch for malformed JSON.
If the request body isn't valid JSON, request.json() will throw an unhandled exception, resulting in a 500 error instead of a proper 400 response.
🔧 Proposed fix
- // Parse the request body
- const data = await request.json();
- const submission = RequestSchema.safeParse(data);
-
- if (!submission.success) {
- return json({ success: false as const, error: "Invalid request data", title: null }, { status: 400 });
- }
+ // Parse the request body
+ let data: unknown;
+ try {
+ data = await request.json();
+ } catch {
+ return json({ success: false as const, error: "Invalid JSON body", title: null }, { status: 400 });
+ }
+ const submission = RequestSchema.safeParse(data);
+
+ if (!submission.success) {
+ return json({ success: false as const, error: "Invalid request data", title: null }, { status: 400 });
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Parse the request body | |
| const data = await request.json(); | |
| const submission = RequestSchema.safeParse(data); | |
| if (!submission.success) { | |
| return json({ success: false as const, error: "Invalid request data", title: null }, { status: 400 }); | |
| } | |
| // Parse the request body | |
| let data: unknown; | |
| try { | |
| data = await request.json(); | |
| } catch { | |
| return json({ success: false as const, error: "Invalid JSON body", title: null }, { status: 400 }); | |
| } | |
| const submission = RequestSchema.safeParse(data); | |
| if (!submission.success) { | |
| return json({ success: false as const, error: "Invalid request data", title: null }, { status: 400 }); | |
| } |
🤖 Prompt for AI Agents
In
`@apps/webapp/app/routes/resources.orgs`.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsx
around lines 21 - 27, Wrap the call to request.json() in a try-catch so
malformed JSON returns a 400 instead of throwing; specifically, around the code
that calls request.json() before you call RequestSchema.safeParse, catch any
error from JSON parsing and return json({ success: false, error: "Invalid JSON",
title: null }, { status: 400 }); keep the existing RequestSchema.safeParse logic
for validated bodies and reference the same submission variable and response
shape.
| // If a queryId was provided, update the CustomerQuery record with the title | ||
| if (queryId) { | ||
| await prisma.customerQuery.update({ | ||
| where: { id: queryId }, | ||
| data: { title }, | ||
| }); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Find the Prisma schema file
find . -name "*.prisma" -type f | head -20Repository: triggerdotdev/trigger.dev
Length of output: 528
🏁 Script executed:
#!/bin/bash
# Check the CustomerQuery model in the Prisma schema
rg -A 30 'model CustomerQuery' --glob '*.prisma'Repository: triggerdotdev/trigger.dev
Length of output: 2595
🏁 Script executed:
#!/bin/bash
# Read the actual file to understand the full context
cat -n apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsx | sed -n '1,100p'Repository: triggerdotdev/trigger.dev
Length of output: 173
🏁 Script executed:
#!/bin/bash
# Search for the file with the ai-title pattern
fd "ai-title" -e tsxRepository: triggerdotdev/trigger.dev
Length of output: 180
🏁 Script executed:
#!/bin/bash
# Search for the file and its content using rg
rg "Update the CustomerQuery record with the title" -A 20 -B 20Repository: triggerdotdev/trigger.dev
Length of output: 51
🏁 Script executed:
#!/bin/bash
# Read the file using proper shell quoting
file="apps/webapp/app/routes/resources.orgs.\$organizationSlug.projects.\$projectParam.env.\$envParam.query.ai-title.tsx"
cat -n "$file" | head -100Repository: triggerdotdev/trigger.dev
Length of output: 2994
🏁 Script executed:
#!/bin/bash
# Alternative: use find and xargs
find . -name "*ai-title.tsx" -type f -exec cat -n {} \; | head -100Repository: triggerdotdev/trigger.dev
Length of output: 2994
Scope the CustomerQuery update to the current project/environment.
The queryId is provided directly from the request body without verifying the record belongs to the authenticated user's environment. A malicious user could update another organization's query by supplying a different queryId, causing unauthorized modification of data across tenant boundaries.
🔒 Proposed fix
// If a queryId was provided, update the CustomerQuery record with the title
if (queryId) {
await prisma.customerQuery.update({
- where: { id: queryId },
+ where: {
+ id: queryId,
+ environmentId: environment.id,
+ },
data: { title },
});
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // If a queryId was provided, update the CustomerQuery record with the title | |
| if (queryId) { | |
| await prisma.customerQuery.update({ | |
| where: { id: queryId }, | |
| data: { title }, | |
| }); | |
| } | |
| // If a queryId was provided, update the CustomerQuery record with the title | |
| if (queryId) { | |
| await prisma.customerQuery.update({ | |
| where: { | |
| id: queryId, | |
| environmentId: environment.id, | |
| }, | |
| data: { title }, | |
| }); | |
| } |
🤖 Prompt for AI Agents
In
`@apps/webapp/app/routes/resources.orgs`.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsx
around lines 59 - 65, The update lets any queryId be changed without verifying
it belongs to the current project/environment; restrict the update by either (A)
replacing prisma.customerQuery.update with prisma.customerQuery.updateMany({
where: { id: queryId, projectId: <currentProjectId>, environmentId:
<currentEnvId> }, data: { title } }) and verifying the returned count > 0, or
(B) first fetch the record with prisma.customerQuery.findUnique/findFirst({
where: { id: queryId } }), confirm its project/environment matches the current
project/env variables, then call prisma.customerQuery.update({ where: { id:
queryId }, data: { title } }); use the existing symbols queryId, title,
prisma.customerQuery.update/updateMany and the current project/env identifiers
in the file to implement this check.
| const { | ||
| scope, | ||
| organizationId, | ||
| projectId, | ||
| environmentId, | ||
| enforcedWhereClause, | ||
| history, | ||
| customOrgConcurrencyLimit, | ||
| whereClauseFallback, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ensure tenant guards cannot diverge from organization/project inputs.
executeQuery accepts organizationId/projectId/environmentId and enforcedWhereClause independently; if they diverge, queries can run for one tenant while history/concurrency are attributed to another. Please validate or construct the tenant guards here.
✅ Suggested guard alignment
const {
scope,
organizationId,
projectId,
environmentId,
enforcedWhereClause,
history,
customOrgConcurrencyLimit,
whereClauseFallback,
...baseOptions
} = options;
+ const tenantGuards: Record<string, WhereClauseCondition> = {
+ organization_id: { op: "eq", value: organizationId },
+ };
+ if (scope !== "organization") {
+ if (!projectId) {
+ return [
+ new QueryError("projectId is required for project/environment scope", {
+ query: options.query,
+ }),
+ null,
+ null,
+ ];
+ }
+ tenantGuards.project_id = { op: "eq", value: projectId };
+ }
+ if (scope === "environment") {
+ if (!environmentId) {
+ return [
+ new QueryError("environmentId is required for environment scope", {
+ query: options.query,
+ }),
+ null,
+ null,
+ ];
+ }
+ tenantGuards.environment_id = { op: "eq", value: environmentId };
+ }
+ const effectiveEnforcedWhereClause = { ...enforcedWhereClause, ...tenantGuards };
+
const result = await executeTSQL(clickhouseClient.reader, {
...baseOptions,
- enforcedWhereClause,
+ enforcedWhereClause: effectiveEnforcedWhereClause,
fieldMappings,
whereClauseFallback,
clickhouseSettings: {
...getDefaultClickhouseSettings(),
...baseOptions.clickhouseSettings,
},
});Also applies to: 153-156
🤖 Prompt for AI Agents
In `@apps/webapp/app/services/queryService.server.ts` around lines 104 - 112, The
tenant inputs (organizationId, projectId, environmentId) and enforcedWhereClause
passed into executeQuery can diverge and cause mismatched attribution for
history/concurrency; update the executeQuery parameter handling to validate and
normalize tenant context by deriving the enforcedWhereClause and
history/concurrency keys from the canonical
organizationId/projectId/environmentId (or reject when inconsistent).
Specifically, in executeQuery (and the similar block around the other usage at
the 153-156 zone) check that any provided enforcedWhereClause matches the
computed clause for the given organizationId/projectId/environmentId (or rebuild
it from those IDs), and use the same canonical IDs to compute history and
customOrgConcurrencyLimit keys so all tenant guards are constructed from the
same source of truth.
| private createConditionExpression(column: string, condition: WhereClauseCondition): Expression { | ||
| const fieldExpr: Field = { | ||
| expression_type: "field", | ||
| chain: [column], | ||
| }; | ||
|
|
||
| if (condition.op === "between") { | ||
| const betweenExpr: BetweenExpr = { | ||
| expression_type: "between_expr", | ||
| expr: fieldExpr, | ||
| low: this.createValueExpression(condition.low), | ||
| high: this.createValueExpression(condition.high), | ||
| }; | ||
| guards.push(envGuard); | ||
| return betweenExpr; | ||
| } | ||
|
|
||
| // Add required filters from the table schema | ||
| // Simple comparison | ||
| const compareExpr: CompareOperation = { | ||
| expression_type: "compare_operation", | ||
| left: fieldExpr, | ||
| right: this.createValueExpression(condition.value), | ||
| op: this.mapConditionOpToCompareOp(condition.op), | ||
| }; | ||
| return compareExpr; | ||
| } | ||
|
|
||
| /** | ||
| * Create a WHERE clause expression for enforced conditions and required filters. | ||
| * | ||
| * This method applies: | ||
| * 1. All conditions from enforcedWhereClause (tenant isolation + plan limits) | ||
| * 2. Required filters from the table schema (e.g., engine = 'V2') | ||
| * | ||
| * Conditions are applied if the column exists in either: | ||
| * - The exposed columns (tableSchema.columns) | ||
| * - The tenant columns (tableSchema.tenantColumns) | ||
| * | ||
| * This ensures the same enforcedWhereClause can be used across different tables. | ||
| * | ||
| * Note: We use just the column name without table prefix since ClickHouse | ||
| * requires the actual table name (task_runs_v2), not the TSQL alias (task_runs) | ||
| */ | ||
| private createEnforcedGuard(tableSchema: TableSchema, _tableAlias: string): Expression | null { | ||
| const { requiredFilters, tenantColumns } = tableSchema; | ||
| const guards: Expression[] = []; | ||
|
|
||
| // Build a set of valid columns for this table (exposed + tenant columns) | ||
| const validColumns = new Set<string>(Object.keys(tableSchema.columns)); | ||
| if (tenantColumns) { | ||
| if (tenantColumns.organizationId) validColumns.add(tenantColumns.organizationId); | ||
| if (tenantColumns.projectId) validColumns.add(tenantColumns.projectId); | ||
| if (tenantColumns.environmentId) validColumns.add(tenantColumns.environmentId); | ||
| } | ||
|
|
||
| // Apply all enforced conditions for columns that exist in this table | ||
| for (const [column, condition] of Object.entries(this.context.enforcedWhereClause)) { | ||
| // Skip undefined/null conditions (allows conditional inclusion like project_id?: condition) | ||
| if (condition === undefined || condition === null) { | ||
| continue; | ||
| } | ||
| // Only apply if column exists in this table's schema or is a tenant column | ||
| if (validColumns.has(column)) { | ||
| guards.push(this.createConditionExpression(column, condition)); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
wc -l internal-packages/tsql/src/query/printer.tsRepository: triggerdotdev/trigger.dev
Length of output: 117
🏁 Script executed:
sed -n '1650,1760p' internal-packages/tsql/src/query/printer.tsRepository: triggerdotdev/trigger.dev
Length of output: 4091
🏁 Script executed:
# Search for JOIN handling and multi-table query patterns
rg -n "JOIN|join|inProjectionContext|allowedInternalColumns" internal-packages/tsql/src/query/printer.ts | head -30Repository: triggerdotdev/trigger.dev
Length of output: 1693
🏁 Script executed:
# Look at the full context of createEnforcedGuard and where it's called
rg -n "createEnforcedGuard\|createConditionExpression" internal-packages/tsql/src/query/printer.tsRepository: triggerdotdev/trigger.dev
Length of output: 51
🏁 Script executed:
# Search more carefully for the functions
rg -n "createEnforcedGuard\|createConditionExpression" internal-packages/tsql/src/query/printer.tsRepository: triggerdotdev/trigger.dev
Length of output: 51
🏁 Script executed:
# Look at the rest of createEnforcedGuard and how it's used
sed -n '1700,1800p' internal-packages/tsql/src/query/printer.tsRepository: triggerdotdev/trigger.dev
Length of output: 3812
🏁 Script executed:
# Search for where createEnforcedGuard is called
rg -B3 -A3 "createEnforcedGuard" internal-packages/tsql/src/query/printer.tsRepository: triggerdotdev/trigger.dev
Length of output: 764
🏁 Script executed:
# Look at the field resolution logic mentioned in the proposed fix
sed -n '500,700p' internal-packages/tsql/src/query/printer.ts | grep -A20 "resolveFieldChain\|tableSchema"Repository: triggerdotdev/trigger.dev
Length of output: 51
🏁 Script executed:
# Look for resolveFieldChain or where fields are resolved
rg -n "resolveFieldChain\|resolveField" internal-packages/tsql/src/query/printer.ts -A 5Repository: triggerdotdev/trigger.dev
Length of output: 51
🏁 Script executed:
# Look at the visitField implementation to see how fields with chains are handled
rg -n "visitField" internal-packages/tsql/src/query/printer.ts -A 20Repository: triggerdotdev/trigger.dev
Length of output: 1771
🏁 Script executed:
# Check if there are multi-table JOIN scenarios in tests
find internal-packages/tsql -name "*.test.ts" -o -name "*.spec.ts" | head -5Repository: triggerdotdev/trigger.dev
Length of output: 311
🏁 Script executed:
# Search for join-related test cases
rg -l "join\|JOIN" internal-packages/tsql --type ts | head -5Repository: triggerdotdev/trigger.dev
Length of output: 51
🏁 Script executed:
# Look at parser test to see JOIN examples
rg -n "join\|JOIN" internal-packages/tsql/src/query/parser.test.ts -B2 -A5 | head -50Repository: triggerdotdev/trigger.dev
Length of output: 51
🏁 Script executed:
# Look at the rest of visitField to understand field resolution
sed -n '2197,2320p' internal-packages/tsql/src/query/printer.tsRepository: triggerdotdev/trigger.dev
Length of output: 4877
🏁 Script executed:
# Search for contexts where enforcedWhereClause is set and used
rg -n "enforcedWhereClause" internal-packages/tsql/src/query/printer.ts -B2 -A2Repository: triggerdotdev/trigger.dev
Length of output: 2000
🏁 Script executed:
# Check if there are scenarios with multiple tables in FROM/JOIN
rg -n "visitFromExpr\|visitJoinExpr" internal-packages/tsql/src/query/printer.ts -A 30 | head -80Repository: triggerdotdev/trigger.dev
Length of output: 51
🏁 Script executed:
# Look at resolveFieldChain to understand how fields are resolved
rg -n "private resolveFieldChain" internal-packages/tsql/src/query/printer.ts -A 40Repository: triggerdotdev/trigger.dev
Length of output: 3489
🏁 Script executed:
# Search for actual JOIN scenarios and how they handle column references
sed -n '1300,1500p' internal-packages/tsql/src/query/printer.ts | grep -A 20 -B 5 "join\|JOIN"Repository: triggerdotdev/trigger.dev
Length of output: 2216
🏁 Script executed:
# Look at how the table context is managed when processing JOINs
sed -n '300,450p' internal-packages/tsql/src/query/printer.tsRepository: triggerdotdev/trigger.dev
Length of output: 5492
🏁 Script executed:
# Check the context structure and how tables are tracked
rg -n "class.*Printer\|private tableStack\|private currentTable" internal-packages/tsql/src/query/printer.ts | head -20Repository: triggerdotdev/trigger.dev
Length of output: 51
🏁 Script executed:
# Look for actual JOIN test cases with multiple tables
find internal-packages -name "*.test.ts" -exec grep -l "join\|JOIN" {} \; | head -3Repository: triggerdotdev/trigger.dev
Length of output: 337
🏁 Script executed:
# Check if there are any tests that show multi-table scenarios with tenant columns
rg -n "enforcedWhereClause\|createEnforcedGuard" internal-packages/tsql/src -lRepository: triggerdotdev/trigger.dev
Length of output: 51
🏁 Script executed:
# Look at how the WHERE clause is actually built with enforced guards
sed -n '365,395p' internal-packages/tsql/src/query/printer.tsRepository: triggerdotdev/trigger.dev
Length of output: 1123
🏁 Script executed:
# Check resolveFieldChain more carefully - does it add table qualification?
sed -n '2574,2590p' internal-packages/tsql/src/query/printer.tsRepository: triggerdotdev/trigger.dev
Length of output: 802
🏁 Script executed:
# Check if resolveFieldChain returns qualified results or just column names
sed -n '2547,2595p' internal-packages/tsql/src/query/printer.tsRepository: triggerdotdev/trigger.dev
Length of output: 2083
🏁 Script executed:
# Look at what resolveColumnName returns to understand table qualification
rg -n "private resolveColumnName" internal-packages/tsql/src/query/printer.ts -A 20Repository: triggerdotdev/trigger.dev
Length of output: 997
🏁 Script executed:
# Check if there are actual scenarios in the codebase where multiple tables share column names
rg -n "tenantColumns\|requiredFilters" internal-packages/tsql/src/schema -A 3 | head -40Repository: triggerdotdev/trigger.dev
Length of output: 142
🏁 Script executed:
# Search for actual schema definitions to see if overlap is possible
find internal-packages/tsql -name "*.ts" -not -path "*.test.ts" | xargs grep -l "TableSchema" | head -3Repository: triggerdotdev/trigger.dev
Length of output: 202
🏁 Script executed:
# Check the comment in printer.ts that says "Note: We use just the column name without table prefix since ClickHouse requires the actual table name"
sed -n '1708,1712p' internal-packages/tsql/src/query/printer.tsRepository: triggerdotdev/trigger.dev
Length of output: 392
🏁 Script executed:
# Look at how resolved chains are actually printed (visitField line 2227)
sed -n '2225,2250p' internal-packages/tsql/src/query/printer.tsRepository: triggerdotdev/trigger.dev
Length of output: 1125
🏁 Script executed:
# Check if there are any other guard creation patterns in the codebase
rg -n "createConditionExpression\|createEnforcedGuard" internal-packages/tsql/src/query/printer.tsRepository: triggerdotdev/trigger.dev
Length of output: 51
🏁 Script executed:
# Look at the full context around line 2580 to see if table qualification happens elsewhere
sed -n '2575,2610p' internal-packages/tsql/src/query/printer.tsRepository: triggerdotdev/trigger.dev
Length of output: 1613
🏁 Script executed:
# Look for examples of multi-table joins in tests
rg -n "select_from.*next_join" internal-packages/tsql/src/query/parser.test.ts -B 5 -A 10 | head -60Repository: triggerdotdev/trigger.dev
Length of output: 51
🏁 Script executed:
# Check if tables typically have overlapping tenant columns
rg -n "organizationId\|projectId\|environmentId" internal-packages/tsql/src/query/results.ts -B 2 -A 2 | head -50Repository: triggerdotdev/trigger.dev
Length of output: 51
🏁 Script executed:
# Look for actual table schema definitions with tenantColumns
rg -n "tenantColumns:" internal-packages -A 3 | head -40Repository: triggerdotdev/trigger.dev
Length of output: 2778
🏁 Script executed:
# Verify the iteration order concern - check if Map iteration order is guaranteed
rg -n "tableContexts.values()\|tableContexts.set" internal-packages/tsql/src/query/printer.ts | head -20Repository: triggerdotdev/trigger.dev
Length of output: 51
🏁 Script executed:
# Check how the resolved chain is actually used in SQL
sed -n '2225,2240p' internal-packages/tsql/src/query/printer.tsRepository: triggerdotdev/trigger.dev
Length of output: 760
🏁 Script executed:
# Look at a test case to see actual generated SQL
rg -n "expected.*WHERE\|sql.*WHERE" internal-packages/tsql/src/query/results.test.ts -A 3 | head -40Repository: triggerdotdev/trigger.dev
Length of output: 51
🏁 Script executed:
# Check what printIdentifierOrIndex does
rg -n "private printIdentifierOrIndex" internal-packages/tsql/src/query/printer.ts -A 10Repository: triggerdotdev/trigger.dev
Length of output: 410
🏁 Script executed:
# Look for test cases with JOINs to see generated SQL
rg -n "JOIN\|join" internal-packages/tsql/src/query/results.test.ts -B 5 -A 5 | head -50Repository: triggerdotdev/trigger.dev
Length of output: 51
🏁 Script executed:
# Look at a specific test case to see the actual JOIN and WHERE clause generated
sed -n '1,100p' internal-packages/tsql/src/query/results.test.ts | grep -A 20 "describe\|test.*join"Repository: triggerdotdev/trigger.dev
Length of output: 1579
🏁 Script executed:
# Search for actual multi-table join tests with WHERE clauses
rg -n "next_join\|JOIN" internal-packages/tsql/src/query/results.test.ts -B 10 -A 10 | head -80Repository: triggerdotdev/trigger.dev
Length of output: 51
🏁 Script executed:
# Check what happens in a query with multiple tables and enforced guards
rg -n "enforcedWhereClause\|createEnforcedGuard" internal-packages/tsql/src/query/results.test.ts -B 5 -A 5Repository: triggerdotdev/trigger.dev
Length of output: 51
🏁 Script executed:
# Understand the comment about ClickHouse requiring actual table names - check if there are alias issues documented
sed -n '1700,1720p' internal-packages/tsql/src/query/printer.tsRepository: triggerdotdev/trigger.dev
Length of output: 1192
🏁 Script executed:
# See the exact flow: when createEnforcedGuard creates chain: [column], trace how it gets resolved
sed -n '2574,2610p' internal-packages/tsql/src/query/printer.tsRepository: triggerdotdev/trigger.dev
Length of output: 1669
🏁 Script executed:
# Check the order of operations: when is createEnforcedGuard called relative to tableContexts population?
sed -n '1470,1530p' internal-packages/tsql/src/query/printer.tsRepository: triggerdotdev/trigger.dev
Length of output: 2859
🏁 Script executed:
# Let's see if there are actual production tables that could have overlapping column names
rg -n "organizationId.*:\|projectId.*:" internal-packages -A 1 | grep -B 1 ":" | head -40Repository: triggerdotdev/trigger.dev
Length of output: 51
🏁 Script executed:
# Check if there's actual test coverage for multi-join scenarios with enforced guards
rg -n "tenantColumns.*organizationId" internal-packages/tsql/src/query -lRepository: triggerdotdev/trigger.dev
Length of output: 156
🏁 Script executed:
# Look at the actual Map iteration behavior and when tables get added to tableContexts
sed -n '1458,1495p' internal-packages/tsql/src/query/printer.tsRepository: triggerdotdev/trigger.dev
Length of output: 1585
🏁 Script executed:
# Let me trace the exact SQL output to see if unqualified columns are actually generated
# Create a simple test to understand the output
cat > /tmp/test_join.js << 'EOF'
// Simulate what happens with two tables having organization_id
const tableContexts = new Map();
tableContexts.set('task_runs', { name: 'task_runs', clickhouseName: 'trigger_dev.task_runs_v2', columns: { organization_id: { name: 'organization_id' }, id: { name: 'id' } } });
tableContexts.set('task_queue', { name: 'task_queue', clickhouseName: 'trigger_dev.task_queue_v2', columns: { organization_id: { name: 'organization_id' }, queue_name: { name: 'queue_name' } } });
// Simulate resolveFieldChain when encountering unqualified "organization_id"
function resolveFieldChain(chain) {
const firstPart = chain[0];
// Case 2: Unqualified reference
for (const tableSchema of tableContexts.values()) {
const columnSchema = tableSchema.columns[firstPart];
if (columnSchema) {
console.log(`Found "${firstPart}" in table ${tableSchema.name}`);
return [columnSchema.clickhouseName || columnSchema.name, ...chain.slice(1)];
}
}
return chain;
}
const resolved = resolveFieldChain(['organization_id']);
console.log('Resolved chain:', resolved);
console.log('SQL would be: WHERE organization_id = value');
console.log('This is AMBIGUOUS in: FROM task_runs_v2 AS task_runs JOIN task_queue_v2 AS task_queue WHERE organization_id = value');
EOF
node /tmp/test_join.jsRepository: triggerdotdev/trigger.dev
Length of output: 309
🏁 Script executed:
# Look at what allowedInternalColumns does - does it help with qualification?
sed -n '2606,2625p' internal-packages/tsql/src/query/printer.tsRepository: triggerdotdev/trigger.dev
Length of output: 910
🏁 Script executed:
# Check if there's any protection through validation that prevents actual ambiguity
rg -n "allowedInternalColumns.has\|isAllowedInternalColumn" internal-packages/tsql/src/query/printer.ts -B 2 -A 3Repository: triggerdotdev/trigger.dev
Length of output: 51
🏁 Script executed:
# Now verify if this is actually used in a multi-join scenario - let's check if createEnforcedGuard is called for each joined table
sed -n '1520,1540p' internal-packages/tsql/src/query/printer.tsRepository: triggerdotdev/trigger.dev
Length of output: 1072
🏁 Script executed:
# Verify: is createEnforcedGuard called once per join or once total?
sed -n '1510,1530p' internal-packages/tsql/src/query/printer.tsRepository: triggerdotdev/trigger.dev
Length of output: 997
🏁 Script executed:
# Check if the loop that adds enforced guards handles multiple tables
sed -n '365,390p' internal-packages/tsql/src/query/printer.tsRepository: triggerdotdev/trigger.dev
Length of output: 1009
🏁 Script executed:
# Check if the guards from createEnforcedGuard are truly added to the WHERE clause with unqualified chains still intact
sed -n '1518,1525p' internal-packages/tsql/src/query/printer.tsRepository: triggerdotdev/trigger.dev
Length of output: 620
🏁 Script executed:
# Verify the exact moment when WHERE clause is visited - are tableContexts still populated?
rg -n "this.visit(where)" internal-packages/tsql/src/query/printer.ts -B 5 -A 2Repository: triggerdotdev/trigger.dev
Length of output: 51
🏁 Script executed:
# Critical: check if Map iteration order is deterministic for this scenario
sed -n '330,380p' internal-packages/tsql/src/query/printer.ts | grep -A 50 "tableContexts"Repository: triggerdotdev/trigger.dev
Length of output: 1789
🏁 Script executed:
# Let me confirm: when WHERE is visited, are tableContexts still populated with all joined tables?
sed -n '432,465p' internal-packages/tsql/src/query/printer.tsRepository: triggerdotdev/trigger.dev
Length of output: 1355
🏁 Script executed:
# Check the exact order: when is WHERE visited relative to when tableContexts is set up with all tables
sed -n '365,445p' internal-packages/tsql/src/query/printer.ts | head -60Repository: triggerdotdev/trigger.dev
Length of output: 2353
Qualify enforced guards to avoid ambiguous column resolution in multi-table JOINs.
createEnforcedGuard currently emits unqualified columns (e.g., organization_id instead of task_runs.organization_id). When the WHERE clause is evaluated with multiple joined tables sharing tenant column names, resolveFieldChain iterates through tableContexts.values() in insertion order and returns the first match, potentially binding to the wrong table and undermining isolation. Pass the tableAlias parameter to createConditionExpression to qualify guard columns during creation.
🐛 Proposed fix
- private createConditionExpression(column: string, condition: WhereClauseCondition): Expression {
+ private createConditionExpression(
+ column: string,
+ condition: WhereClauseCondition,
+ tableAlias?: string
+ ): Expression {
const fieldExpr: Field = {
expression_type: "field",
- chain: [column],
+ chain: tableAlias ? [tableAlias, column] : [column],
};
@@
- private createEnforcedGuard(tableSchema: TableSchema, _tableAlias: string): Expression | null {
+ private createEnforcedGuard(tableSchema: TableSchema, tableAlias: string): Expression | null {
@@
- guards.push(this.createConditionExpression(column, condition));
+ guards.push(this.createConditionExpression(column, condition, tableAlias));🤖 Prompt for AI Agents
In `@internal-packages/tsql/src/query/printer.ts` around lines 1669 - 1733,
createEnforcedGuard currently builds unqualified guard expressions which can
bind to the wrong table in multi-join queries; update createConditionExpression
to accept an optional tableAlias parameter and, when provided, construct the
Field.chain as [tableAlias, column] (instead of just [column]) so
resolveFieldChain will resolve to the correct table; then call
createConditionExpression(column, condition, tableAlias) from
createEnforcedGuard's loop and ensure existing logic in
createConditionExpression (used for between expressions and CompareOperation
building with createValueExpression and mapConditionOpToCompareOp) uses the new
fieldExpr with the qualified chain.
0806d27 to
9837a90
Compare
When we store data in JSON columns, if there is data we wrap it in `{
"data": theData }`. We do this because it could be an array, a primitive
or an object. Arrays and primitives can't be stored in a JSON column.
This hides this from the user because it’s an implementation detail and
means their expectation doesn’t match how we store
This includes making the resizable panel work for vertical splits
9837a90 to
87ec51f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
apps/webapp/app/components/runs/v3/SharedFilters.tsx (1)
529-540: MissingmaxPeriodDaysin dependency array.The
applySelectioncallback referencesmaxPeriodDaysin the error message (line 459) but it's not included in the dependency array. While the current flow may work due to the disabled button preventing calls, this could cause stale values if the callback is invoked programmatically.Suggested fix
}, [ activeSection, selectedPeriod, isCustomDurationValid, customValue, customUnit, fromValue, toValue, replace, onApply, onValueChange, + exceedsMaxPeriod, + maxPeriodDays, ]);apps/webapp/app/v3/querySchemas.ts (1)
329-354: Add test coverage for NULL checks on JSON subfields withdataPrefixto verify the semantics are correct.The implementation appears sound:
dataPrefixinjection andnullValuetransformation work together correctly because the NULL comparison is applied after the field reference is visited (which injects the prefix). For example,WHERE output.message IS NULLwithdataPrefix: "data"becomesequals(output.data.message, '{}')— correctly checking the wrapped field against empty object.However, there is no explicit test covering this combined scenario. The test suite includes:
- NULL checks on bare JSON columns with
nullValue(lines 493–544)- NULL checks on bare JSON columns with
textColumn(lines 800–812)dataPrefixinjection in SELECT/WHERE/GROUP BY (lines 901–1005)But no test combines
dataPrefixwith NULL checks on subfields (e.g.,WHERE output.message IS NULLorWHERE error.code IS NULL). Adding a test case would confirm the behavior is correct and prevent future regressions.
🤖 Fix all issues with AI agents
In `@internal-packages/tsql/src/query/printer_context.ts`:
- Around line 21-41: Replace the exported interfaces SimpleComparisonCondition
and BetweenCondition with exported type aliases that preserve the exact same
object shapes and string literal unions (e.g., export type
SimpleComparisonCondition = { op: "eq" | "neq" | "gt" | "gte" | "lt" | "lte";
value: Date | string | number; } and export type BetweenCondition = { op:
"between"; low: Date | string | number; high: Date | string | number; }); keep
JSDoc comments and exports intact so all callers using SimpleComparisonCondition
and BetweenCondition continue to compile.
🧹 Nitpick comments (4)
internal-packages/clickhouse/schema/014_update_output_error_text_to_extract_data.sql (2)
6-15: Consider the repeatedtoJSONString(output)calls.The expression calls
toJSONString(output)up to 3 times per row (lines 8, 11, and 12 or 13). Since this is a MATERIALIZED column computed at insert time rather than query time, the impact is limited to write performance. However, ClickHouse may not optimize away these redundant calls.Unfortunately, ClickHouse's MATERIALIZED column syntax doesn't support CTEs or variable bindings within the expression, so there's no clean way to compute it once. If write performance becomes a concern, an alternative approach would be using a separate materialized view, but that adds complexity.
This is acceptable as-is given the tradeoff favors read performance.
2-2: Minor: Comment says "Update" but the action is "ADD COLUMN".The comment "Update the materialized columns" suggests modifying existing columns, but the migration actually adds new columns. Consider clarifying this if it's intentional (e.g., replacing a previous approach).
-- +goose Up --- Update the materialized columns to extract the 'data' field if it exists +-- Add materialized text columns that extract the 'data' field if it exists -- This avoids the {"data": ...} wrapper in the text representationapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsx (2)
618-640: Consider usingtitleFetcher.statein the dependency array.The effect depends on
titleFetcherobject, but only checkstitleFetcher.statein the condition. Including the entire fetcher object may trigger unnecessary effect runs since the fetcher reference can change between renders. UsingtitleFetcher.statewould be more precise.♻️ Suggested refinement
- }, [results, shouldGenerateTitle, historyTitle, titleFetcher, organization.slug, project.slug, environment.slug]); + }, [results, shouldGenerateTitle, historyTitle, titleFetcher.state, organization.slug, project.slug, environment.slug]);
1086-1090: Minor inconsistency: DialogHeader doesn't show loading state.The main chart header (line 1068) displays a loading spinner during title generation, but the
DialogHeader(line 1089) falls back to "Chart" directly. If the dialog is opened while the title is still generating, users see inconsistent UI.♻️ Suggested fix for consistency
<DialogHeader> - {queryTitle ?? "Chart"} + {titleContent} </DialogHeader>
📜 Review details
Configuration used: Repository 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 (32)
apps/webapp/app/components/code/QueryResultsChart.tsxapps/webapp/app/components/code/TSQLResultsTable.tsxapps/webapp/app/components/primitives/AnimatedNumber.tsxapps/webapp/app/components/primitives/Callout.tsxapps/webapp/app/components/primitives/Resizable.tsxapps/webapp/app/components/primitives/charts/Card.tsxapps/webapp/app/components/primitives/charts/ChartLegendCompound.tsxapps/webapp/app/components/primitives/charts/ChartLine.tsxapps/webapp/app/components/primitives/charts/ChartRoot.tsxapps/webapp/app/components/runs/v3/SharedFilters.tsxapps/webapp/app/env.server.tsapps/webapp/app/presenters/v3/QueryPresenter.server.tsapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHelpSidebar.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHistoryPopover.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsxapps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsxapps/webapp/app/services/queryService.server.tsapps/webapp/app/v3/querySchemas.tsapps/webapp/app/v3/services/aiQueryTitleService.server.tsapps/webapp/package.jsoninternal-packages/clickhouse/schema/014_update_output_error_text_to_extract_data.sqlinternal-packages/clickhouse/src/client/tsql.tsinternal-packages/clickhouse/src/index.tsinternal-packages/database/prisma/migrations/20260124203524_customer_query_add_title_remove_cost/migration.sqlinternal-packages/database/prisma/schema.prismainternal-packages/tsql/src/index.test.tsinternal-packages/tsql/src/index.tsinternal-packages/tsql/src/query/printer.test.tsinternal-packages/tsql/src/query/printer.tsinternal-packages/tsql/src/query/printer_context.tsinternal-packages/tsql/src/query/schema.tsinternal-packages/tsql/src/query/security.test.ts
💤 Files with no reviewable changes (1)
- apps/webapp/app/env.server.ts
🚧 Files skipped from review as they are similar to previous changes (16)
- internal-packages/tsql/src/query/schema.ts
- internal-packages/clickhouse/src/index.ts
- internal-packages/database/prisma/migrations/20260124203524_customer_query_add_title_remove_cost/migration.sql
- apps/webapp/app/components/primitives/AnimatedNumber.tsx
- apps/webapp/app/components/code/QueryResultsChart.tsx
- apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHelpSidebar.tsx
- apps/webapp/app/components/primitives/charts/ChartLine.tsx
- apps/webapp/app/components/code/TSQLResultsTable.tsx
- apps/webapp/app/v3/services/aiQueryTitleService.server.ts
- apps/webapp/app/components/primitives/charts/Card.tsx
- apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsx
- internal-packages/database/prisma/schema.prisma
- apps/webapp/package.json
- apps/webapp/app/presenters/v3/QueryPresenter.server.ts
- internal-packages/clickhouse/src/client/tsql.ts
- apps/webapp/app/components/primitives/Callout.tsx
🧰 Additional context used
📓 Path-based instructions (12)
internal-packages/clickhouse/schema/**/*.sql
📄 CodeRabbit inference engine (CLAUDE.md)
internal-packages/clickhouse/schema/**/*.sql: ClickHouse migrations must use Goose format with-- +goose Upand-- +goose Downmarkers
Follow ClickHouse naming conventions:raw_prefix for input tables,_v1,_v2suffixes for versioning,_mv_v1suffix for materialized views
Files:
internal-packages/clickhouse/schema/014_update_output_error_text_to_extract_data.sql
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.{ts,tsx}: Use types over interfaces for TypeScript
Avoid using enums; prefer string unions or const objects instead
**/*.{ts,tsx}: Always import tasks from@trigger.dev/sdk, never use@trigger.dev/sdk/v3or deprecatedclient.defineJobpattern
Every Trigger.dev task must be exported and have a uniqueidproperty with no timeouts in the run function
Files:
apps/webapp/app/components/primitives/charts/ChartRoot.tsxapps/webapp/app/components/runs/v3/SharedFilters.tsxinternal-packages/tsql/src/query/printer.tsinternal-packages/tsql/src/index.test.tsapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHistoryPopover.tsxinternal-packages/tsql/src/query/printer_context.tsinternal-packages/tsql/src/query/security.test.tsapps/webapp/app/components/primitives/charts/ChartLegendCompound.tsxinternal-packages/tsql/src/query/printer.test.tsapps/webapp/app/components/primitives/Resizable.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsxinternal-packages/tsql/src/index.tsapps/webapp/app/v3/querySchemas.tsapps/webapp/app/services/queryService.server.ts
{packages/core,apps/webapp}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use zod for validation in packages/core and apps/webapp
Files:
apps/webapp/app/components/primitives/charts/ChartRoot.tsxapps/webapp/app/components/runs/v3/SharedFilters.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHistoryPopover.tsxapps/webapp/app/components/primitives/charts/ChartLegendCompound.tsxapps/webapp/app/components/primitives/Resizable.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsxapps/webapp/app/v3/querySchemas.tsapps/webapp/app/services/queryService.server.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use function declarations instead of default exports
Import from
@trigger.dev/coreusing subpaths only, never import from root
Files:
apps/webapp/app/components/primitives/charts/ChartRoot.tsxapps/webapp/app/components/runs/v3/SharedFilters.tsxinternal-packages/tsql/src/query/printer.tsinternal-packages/tsql/src/index.test.tsapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHistoryPopover.tsxinternal-packages/tsql/src/query/printer_context.tsinternal-packages/tsql/src/query/security.test.tsapps/webapp/app/components/primitives/charts/ChartLegendCompound.tsxinternal-packages/tsql/src/query/printer.test.tsapps/webapp/app/components/primitives/Resizable.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsxinternal-packages/tsql/src/index.tsapps/webapp/app/v3/querySchemas.tsapps/webapp/app/services/queryService.server.ts
apps/webapp/app/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)
Access all environment variables through the
envexport ofenv.server.tsinstead of directly accessingprocess.envin the Trigger.dev webapp
Files:
apps/webapp/app/components/primitives/charts/ChartRoot.tsxapps/webapp/app/components/runs/v3/SharedFilters.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHistoryPopover.tsxapps/webapp/app/components/primitives/charts/ChartLegendCompound.tsxapps/webapp/app/components/primitives/Resizable.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsxapps/webapp/app/v3/querySchemas.tsapps/webapp/app/services/queryService.server.ts
apps/webapp/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)
apps/webapp/**/*.{ts,tsx}: When importing from@trigger.dev/corein the webapp, use subpath exports from the package.json instead of importing from the root path
Follow the Remix 2.1.0 and Express server conventions when updating the main trigger.dev webappAccess environment variables via
envexport fromapps/webapp/app/env.server.ts, never useprocess.envdirectly
Files:
apps/webapp/app/components/primitives/charts/ChartRoot.tsxapps/webapp/app/components/runs/v3/SharedFilters.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHistoryPopover.tsxapps/webapp/app/components/primitives/charts/ChartLegendCompound.tsxapps/webapp/app/components/primitives/Resizable.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsxapps/webapp/app/v3/querySchemas.tsapps/webapp/app/services/queryService.server.ts
**/*.{js,ts,jsx,tsx,json,md,yaml,yml}
📄 CodeRabbit inference engine (AGENTS.md)
Format code using Prettier before committing
Files:
apps/webapp/app/components/primitives/charts/ChartRoot.tsxapps/webapp/app/components/runs/v3/SharedFilters.tsxinternal-packages/tsql/src/query/printer.tsinternal-packages/tsql/src/index.test.tsapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHistoryPopover.tsxinternal-packages/tsql/src/query/printer_context.tsinternal-packages/tsql/src/query/security.test.tsapps/webapp/app/components/primitives/charts/ChartLegendCompound.tsxinternal-packages/tsql/src/query/printer.test.tsapps/webapp/app/components/primitives/Resizable.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsxinternal-packages/tsql/src/index.tsapps/webapp/app/v3/querySchemas.tsapps/webapp/app/services/queryService.server.ts
**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/otel-metrics.mdc)
**/*.ts: When creating or editing OTEL metrics (counters, histograms, gauges), ensure metric attributes have low cardinality by using only enums, booleans, bounded error codes, or bounded shard IDs
Do not use high-cardinality attributes in OTEL metrics such as UUIDs/IDs (envId, userId, runId, projectId, organizationId), unbounded integers (itemCount, batchSize, retryCount), timestamps (createdAt, startTime), or free-form strings (errorMessage, taskName, queueName)
When exporting OTEL metrics via OTLP to Prometheus, be aware that the exporter automatically adds unit suffixes to metric names (e.g., 'my_duration_ms' becomes 'my_duration_ms_milliseconds', 'my_counter' becomes 'my_counter_total'). Account for these transformations when writing Grafana dashboards or Prometheus queries
Files:
internal-packages/tsql/src/query/printer.tsinternal-packages/tsql/src/index.test.tsinternal-packages/tsql/src/query/printer_context.tsinternal-packages/tsql/src/query/security.test.tsinternal-packages/tsql/src/query/printer.test.tsinternal-packages/tsql/src/index.tsapps/webapp/app/v3/querySchemas.tsapps/webapp/app/services/queryService.server.ts
**/*.{test,spec}.{ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use vitest for all tests in the Trigger.dev repository
Files:
internal-packages/tsql/src/index.test.tsinternal-packages/tsql/src/query/security.test.tsinternal-packages/tsql/src/query/printer.test.ts
**/*.test.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.test.{ts,tsx,js,jsx}: Test files should live beside the files under test and use descriptivedescribeanditblocks
Tests should avoid mocks or stubs and use the helpers from@internal/testcontainerswhen Redis or Postgres are needed
Use vitest for running unit tests
**/*.test.{ts,tsx,js,jsx}: Use vitest exclusively for testing and never mock anything - use testcontainers instead
Place test files next to source files with naming pattern: source file (e.g.,MyService.ts) →MyService.test.ts
Files:
internal-packages/tsql/src/index.test.tsinternal-packages/tsql/src/query/security.test.tsinternal-packages/tsql/src/query/printer.test.ts
**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use testcontainers helpers (
redisTest,postgresTest,containerTest) from@internal/testcontainersfor Redis/PostgreSQL testing instead of mocks
Files:
internal-packages/tsql/src/index.test.tsinternal-packages/tsql/src/query/security.test.tsinternal-packages/tsql/src/query/printer.test.ts
apps/webapp/app/services/**/*.server.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)
Separate testable services from configuration files; follow the pattern of
realtimeClient.server.ts(testable service) andrealtimeClientGlobal.server.ts(configuration) in the webapp
Files:
apps/webapp/app/services/queryService.server.ts
🧠 Learnings (11)
📚 Learning: 2026-01-15T11:50:06.067Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to internal-packages/clickhouse/schema/**/*.sql : Follow ClickHouse naming conventions: `raw_` prefix for input tables, `_v1`, `_v2` suffixes for versioning, `_mv_v1` suffix for materialized views
Applied to files:
internal-packages/clickhouse/schema/014_update_output_error_text_to_extract_data.sql
📚 Learning: 2026-01-15T11:50:06.067Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to internal-packages/clickhouse/schema/**/*.sql : ClickHouse migrations must use Goose format with `-- +goose Up` and `-- +goose Down` markers
Applied to files:
internal-packages/clickhouse/schema/014_update_output_error_text_to_extract_data.sql
📚 Learning: 2026-01-15T11:50:06.067Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to internal-packages/database/prisma/migrations/**/*.sql : When editing the Prisma schema, remove extraneous migration lines related to specific tables: `_BackgroundWorkerToBackgroundWorkerFile`, `_BackgroundWorkerToTaskQueue`, `_TaskRunToTaskRunTag`, `_WaitpointRunConnections`, `_completedWaitpoints`, `SecretStore_key_idx`, and unrelated `TaskRun` indexes
Applied to files:
internal-packages/clickhouse/schema/014_update_output_error_text_to_extract_data.sql
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger.config.ts : Set default maximum duration in trigger.config.ts using `maxDuration` property
Applied to files:
apps/webapp/app/components/runs/v3/SharedFilters.tsx
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Limit task duration using the `maxDuration` property (in seconds)
Applied to files:
apps/webapp/app/components/runs/v3/SharedFilters.tsx
📚 Learning: 2025-12-08T15:19:56.823Z
Learnt from: 0ski
Repo: triggerdotdev/trigger.dev PR: 2760
File: apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx:278-281
Timestamp: 2025-12-08T15:19:56.823Z
Learning: In apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx, the tableState search parameter uses intentional double-encoding: the parameter value contains a URL-encoded URLSearchParams string, so decodeURIComponent(value("tableState") ?? "") is required to fully decode it before parsing with new URLSearchParams(). This pattern allows bundling multiple filter/pagination params as a single search parameter.
Applied to files:
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHistoryPopover.tsxinternal-packages/tsql/src/query/security.test.tsapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsx
📚 Learning: 2025-07-21T12:52:44.342Z
Learnt from: ericallam
Repo: triggerdotdev/trigger.dev PR: 2284
File: apps/webapp/app/services/realtimeClient.server.ts:111-127
Timestamp: 2025-07-21T12:52:44.342Z
Learning: Electric (the database service used in the realtimeClient) has built-in SQL injection protection and safely handles whereClause parameters passed via URL parameters, so direct string interpolation of runId values into SQL where clauses is safe when using Electric.
Applied to files:
internal-packages/tsql/src/query/security.test.ts
📚 Learning: 2025-11-27T16:26:37.432Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T16:26:37.432Z
Learning: Applies to internal-packages/database/**/*.{ts,tsx} : Use Prisma for database interactions in internal-packages/database with PostgreSQL
Applied to files:
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsxapps/webapp/app/services/queryService.server.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Scope idempotency keys globally or to current run using the scope parameter
Applied to files:
apps/webapp/app/v3/querySchemas.ts
📚 Learning: 2025-08-14T10:53:54.526Z
Learnt from: myftija
Repo: triggerdotdev/trigger.dev PR: 2391
File: apps/webapp/app/services/organizationAccessToken.server.ts:50-0
Timestamp: 2025-08-14T10:53:54.526Z
Learning: In the Trigger.dev codebase, token service functions (like revokePersonalAccessToken and revokeOrganizationAccessToken) don't include tenant scoping in their database queries. Instead, authorization and tenant scoping happens at a higher level in the authentication flow (typically in route handlers) before these service functions are called. This is a consistent pattern across both Personal Access Tokens (PATs) and Organization Access Tokens (OATs).
Applied to files:
apps/webapp/app/services/queryService.server.ts
📚 Learning: 2026-01-12T17:18:09.451Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 2870
File: apps/webapp/app/services/redisConcurrencyLimiter.server.ts:56-66
Timestamp: 2026-01-12T17:18:09.451Z
Learning: In `apps/webapp/app/services/redisConcurrencyLimiter.server.ts`, the query concurrency limiter will not be deployed with Redis Cluster mode, so multi-key operations (keyKey and globalKey in different hash slots) are acceptable and will function correctly in standalone Redis mode.
Applied to files:
apps/webapp/app/services/queryService.server.ts
🧬 Code graph analysis (7)
apps/webapp/app/components/runs/v3/SharedFilters.tsx (3)
apps/webapp/app/components/primitives/Callout.tsx (1)
Callout(73-170)apps/webapp/app/components/primitives/Buttons.tsx (1)
LinkButton(335-403)apps/webapp/app/utils/pathBuilder.ts (1)
organizationBillingPath(116-118)
internal-packages/tsql/src/index.test.ts (5)
internal-packages/tsql/src/index.ts (4)
column(81-81)TableSchema(113-113)WhereClauseCondition(127-127)compileTSQL(538-566)apps/webapp/app/services/queryService.server.ts (1)
TableSchema(21-21)internal-packages/clickhouse/src/client/tsql.ts (2)
TableSchema(28-28)WhereClauseCondition(28-28)internal-packages/clickhouse/src/index.ts (2)
TableSchema(54-54)WhereClauseCondition(59-59)internal-packages/tsql/src/query/printer_context.ts (1)
WhereClauseCondition(47-47)
internal-packages/tsql/src/query/printer_context.ts (2)
internal-packages/tsql/src/index.ts (8)
SimpleComparisonCondition(126-126)BetweenCondition(122-122)WhereClauseCondition(127-127)SchemaRegistry(112-112)FieldMappings(109-109)createPrinterContext(119-119)PrinterContextOptions(123-123)PrinterContext(121-121)internal-packages/tsql/src/query/schema.ts (2)
SchemaRegistry(344-349)FieldMappings(270-270)
apps/webapp/app/components/primitives/charts/ChartLegendCompound.tsx (2)
apps/webapp/app/utils/cn.ts (1)
cn(77-79)apps/webapp/app/components/primitives/AnimatedNumber.tsx (1)
AnimatedNumber(22-58)
internal-packages/tsql/src/query/printer.test.ts (1)
internal-packages/tsql/src/query/printer_context.ts (2)
createPrinterContext(249-256)PrinterContext(79-214)
apps/webapp/app/v3/querySchemas.ts (1)
internal-packages/tsql/src/query/schema.ts (1)
column(354-366)
apps/webapp/app/services/queryService.server.ts (4)
internal-packages/clickhouse/src/client/tsql.ts (1)
TSQLQueryResult(133-133)internal-packages/clickhouse/src/index.ts (2)
TSQLQueryResult(55-55)QueryError(64-64)apps/webapp/app/services/queryConcurrencyLimiter.server.ts (2)
queryConcurrencyLimiter(19-22)GLOBAL_CONCURRENCY_LIMIT(28-28)internal-packages/tsql/src/query/errors.ts (1)
QueryError(43-45)
⏰ 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). (22)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (8, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (4, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (5, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (8, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
- GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
- GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
- GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - npm)
- GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - pnpm)
- GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
- GitHub Check: typecheck / typecheck
🔇 Additional comments (48)
apps/webapp/app/components/primitives/Resizable.tsx (3)
28-40: LGTM!The orientation-aware styling using
data-[handle-orientation=vertical]selectors is well-structured. The base horizontal styles with vertical overrides pattern is clean and maintainable.
44-47: LGTM!The line indicators properly toggle visibility based on orientation using complementary
hidden/blockclasses with thegroup-data-[handle-orientation=vertical]selector. The hover transitions are smooth and provide good visual feedback.
48-63: LGTM!The orientation-aware dot rendering is well-implemented. Using
indexas the key is acceptable here since the array is static, fixed-length, and items never reorder. The visibility logic correctly shows only the relevant orientation's dots while hiding both on hover to reveal the line indicator.internal-packages/clickhouse/schema/014_update_output_error_text_to_extract_data.sql (3)
1-5: Goose format and naming conventions are correct.The migration properly uses
-- +goose Upand-- +goose Downmarkers, andtask_runs_v2follows the versioning suffix convention. As per coding guidelines and learnings.
29-32: Index configuration looks appropriate for text search.The
ngrambf_v1(3, 131072, 3, 0)bloom filter with 3-character ngrams is well-suited for substring matching on JSON text fields.
34-45: Down migration is correctly structured.Indexes are dropped before columns, and
IF EXISTSguards protect against partial migration states. Good defensive practice.apps/webapp/app/components/primitives/charts/ChartLegendCompound.tsx (2)
9-43: Scrollable prop is cleanly added and defaulted.
Good addition to the public API with a sensible default for backward compatibility.
134-216: Scrollable legend layout looks solid.
The max-height constraint, shrink-0 guards, and overflow wrapper are well composed for flex layouts.apps/webapp/app/components/primitives/charts/ChartRoot.tsx (2)
9-105: Legend scrollability is wired through cleanly.
Defaults and prop forwarding are consistent across the root component.
109-170: Inner wiring to ChartLegendCompound is correct.
scrollable is passed through without side effects.apps/webapp/app/components/runs/v3/SharedFilters.tsx (6)
14-29: LGTM!The new imports are well-organized and all are utilized in the component for the upgrade callout feature.
126-140: LGTM!The utility functions are well-implemented.
periodToDaysleverages the existingparse-durationlibrary for consistency, anddateRangeToDaysuses ceiling to ensure partial days count conservatively.
797-806: LGTM!The upgrade callout is well-implemented with proper conditional rendering, pluralization via
simplur, and correct routing to the billing page usingorganizationBillingPath.
738-762: LGTM!The quick date button changes improve semantic correctness. Using
endOfDay,endOfWeek, andendOfMonthfor the "to" values ensures the selected ranges cover the full intended periods rather than stopping at the current timestamp.
823-838: LGTM!Disabling the Apply button when
exceedsMaxPeriodis true provides clear UX feedback and prevents invalid submissions.
93-109: LGTM!Adding the "5 days" preset provides users with a useful intermediate option between 3 and 7 days.
apps/webapp/app/v3/querySchemas.ts (1)
170-178: No action needed. The idempotency scope values are correctly defined and match the backend support. All three scopes—"run", "attempt", and "global"—are officially supported throughout the codebase.internal-packages/tsql/src/query/printer_context.ts (1)
95-199: LGTM: enforcedWhereClause is consistently propagated.Also applies to: 219-255
internal-packages/tsql/src/index.ts (2)
26-32: LGTM: WhereClauseCondition wiring across helpers is consistent.Also applies to: 118-128, 316-367, 377-444
450-504: LGTM: enforcedWhereClause sanitization + context creation look solid.Also applies to: 542-565
internal-packages/tsql/src/query/security.test.ts (2)
55-61: LGTM: default test options migrated to enforcedWhereClause.
417-421: LGTM: optional tenant filter permutations updated for enforcedWhereClause.Also applies to: 438-443, 459-463, 491-496, 516-520, 535-539, 559-563, 578-582
apps/webapp/app/services/queryService.server.ts (1)
57-87: LGTM: 3‑tuple result + queryId propagation look consistent.Also applies to: 89-99, 121-134, 164-218
internal-packages/tsql/src/query/printer.test.ts (4)
88-94: LGTM: test contexts updated for enforcedWhereClause.Also applies to: 155-164, 221-229, 248-258, 481-491, 697-707, 888-898, 1152-1157, 1469-1485, 1585-1604, 1811-1832, 2054-2074, 2201-2227, 2614-2645, 2769-2785, 2899-2921, 3084-3093
611-664: LGTM: JSON subfield type‑hint suppression in WHERE is covered.
666-855: LGTM: textColumn optimization scenarios are well covered.
857-1007: LGTM: dataPrefix injection behavior is well covered.internal-packages/tsql/src/index.test.ts (3)
8-74: LGTM: scaffolding updated for enforcedWhereClause and new schemas.
168-243: LGTM: fallback tests updated to WhereClauseCondition.
516-828: LGTM: enforcedWhereClause behavior suite is comprehensive.internal-packages/tsql/src/query/printer.ts (12)
117-118: LGTM!Good addition of the
queryHasGroupByflag with clear documentation explaining its purpose for JSON subfield type hints in GROUP BY queries.
397-400: LGTM!Proper state management pattern for
queryHasGroupBy- saving before modification and restoring after subquery processing, consistent with the existingsavedTableContextsapproach.
639-678: LGTM!Well-structured logic flow for handling different column types:
- Text column optimization for bare JSON fields
- Virtual column expression aliasing
- JSON subfield aliasing (excluding dataPrefix)
- ClickHouse name mismatch aliasing
The
effectiveOutputNameoverride ensures metadata consistency with the generated alias.
696-710: LGTM!Correctly handles the case where a user explicitly aliases a JSON column with a
textColumnoptimization (e.g.,SELECT output AS myOutput), using the optimized text column while preserving the user's explicit alias.
853-857: LGTM!Consistent application of
textColumnoptimization duringSELECT *expansion, with proper aliasing to preserve the user-facing column name.
1479-1480: LGTM!Good fail-fast validation of required tenant columns early in join processing. This ensures tenant isolation requirements are enforced before query execution.
1590-1604: LGTM!Proper tenant isolation validation - ensures the required
organizationIdcolumn is present inenforcedWhereClause. The error message clearly identifies the missing requirement.
1606-1638: LGTM!Correct date handling for ClickHouse:
- Uses UTC methods consistently for timezone-safe formatting
toDateTime64(..., 3)matchesDateTime64(3)column precision- Format string matches ClickHouse's expected format
1868-1881: LGTM!Good optimization to use
textColumnfor string-based comparisons (Eq, NotEq, Like, ILike, etc.) where the text representation is more efficient. Correctly excludes numeric comparisons (Lt, Gt, etc.) where the text column wouldn't provide correct semantics.
2296-2308: LGTM!Clean implementation of
isInWhereComparisonContext()that correctly identifies WHERE/HAVING comparison contexts without including GROUP BY. This enables proper differentiation for JSON type hint handling.
2351-2419: LGTM!Well-implemented helper methods for text column and data prefix detection:
getTextColumnForFieldcorrectly identifies bare JSON fields vs. subfield accessgetDataPrefixForFieldproperly handles both qualified and unqualified references with correct length checks
2421-2468: LGTM!Correct implementation of data prefix handling:
injectDataPrefixproperly transforms chains for both qualified and unqualified referencesbuildAliasWithoutDataPrefixsafely operates on a filtered copy, removing the internal data prefix for cleaner user-facing aliasesapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHistoryPopover.tsx (2)
38-46: LGTM!The normalization logic is clean and improves SQL display by collapsing whitespace per line while preserving newlines for structure. The increased limit to 500 characters provides better context in history items.
122-136: LGTM!The conditional rendering correctly prioritizes the title when available (with the query shown as secondary context), while maintaining the original query-focused display when no title exists. The styling differentiation is appropriate.
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsx (4)
173-180: LGTM!The default period calculation correctly respects plan limits while preferring the ideal 7-day default. The logic handles edge cases appropriately.
291-326: LGTM!The time filter logic correctly handles all cases (from/to, from-only, to-only, period). The non-null assertion on line 311 is safe because the else branch guarantees
requestedFromDatewas set. TheenforcedWhereClauseproperly enforces tenant isolation and plan-based time limits.
988-1026: LGTM!The
QueryResultsCalloutscomponent provides clear user feedback about result limitations with an actionable upgrade path. Thesimplurusage correctly handles day/days pluralization.
1028-1033: LGTM!Clean helper function that encapsulates the callout visibility logic.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
| /** | ||
| * A simple comparison condition (e.g., column > value) | ||
| */ | ||
| export interface SimpleComparisonCondition { | ||
| /** The comparison operator */ | ||
| op: "eq" | "neq" | "gt" | "gte" | "lt" | "lte"; | ||
| /** The value to compare against */ | ||
| value: Date | string | number; | ||
| } | ||
|
|
||
| /** | ||
| * A between condition (e.g., column BETWEEN low AND high) | ||
| */ | ||
| export interface BetweenCondition { | ||
| /** The between operator */ | ||
| op: "between"; | ||
| /** The low bound of the range */ | ||
| low: Date | string | number; | ||
| /** The high bound of the range */ | ||
| high: Date | string | number; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
🧩 Analysis chain
🏁 Script executed:
cat -n internal-packages/tsql/src/query/printer_context.ts | sed -n '15,50p'Repository: triggerdotdev/trigger.dev
Length of output: 1330
Use type aliases for condition types (repo style).
SimpleComparisonCondition and BetweenCondition are declared as interfaces, but the TypeScript guideline requires using type aliases instead.
♻️ Proposed change
-export interface SimpleComparisonCondition {
+export type SimpleComparisonCondition = {
/** The comparison operator */
op: "eq" | "neq" | "gt" | "gte" | "lt" | "lte";
/** The value to compare against */
value: Date | string | number;
-}
+};
-export interface BetweenCondition {
+export type BetweenCondition = {
/** The between operator */
op: "between";
/** The low bound of the range */
low: Date | string | number;
/** The high bound of the range */
high: Date | string | number;
-}
+};🤖 Prompt for AI Agents
In `@internal-packages/tsql/src/query/printer_context.ts` around lines 21 - 41,
Replace the exported interfaces SimpleComparisonCondition and BetweenCondition
with exported type aliases that preserve the exact same object shapes and string
literal unions (e.g., export type SimpleComparisonCondition = { op: "eq" | "neq"
| "gt" | "gte" | "lt" | "lte"; value: Date | string | number; } and export type
BetweenCondition = { op: "between"; low: Date | string | number; high: Date |
string | number; }); keep JSDoc comments and exports intact so all callers using
SimpleComparisonCondition and BetweenCondition continue to compile.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| const applySelection = useCallback(() => { | ||
| setValidationError(null); | ||
|
|
||
| if (exceedsMaxPeriod) { | ||
| setValidationError(`Your plan allows a maximum of ${maxPeriodDays} days. Upgrade for longer retention.`); | ||
| return; | ||
| } | ||
|
|
||
| if (activeSection === "duration") { | ||
| // Validate custom duration | ||
| if (selectedPeriod === "custom" && !isCustomDurationValid) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🟡 TimeDropdown applySelection uses stale exceedsMaxPeriod/maxPeriodDays due to missing hook dependencies
applySelection closes over exceedsMaxPeriod/maxPeriodDays but they are not listed in the useCallback dependency array.
Actual behavior: if maxPeriodDays changes (e.g. plan loads async) or if the user changes inputs that affect exceedsMaxPeriod, the callback may still use the previous value and either:
- incorrectly block Apply with an outdated validation error, or
- incorrectly allow Apply and update URL/state even though the selection exceeds the limit.
Expected behavior: the Apply handler should always reflect the current exceedsMaxPeriod and maxPeriodDays.
Click to expand
exceedsMaxPeriodis computed fromactiveSection,selectedPeriod,customValue/customUnit,fromValue, andmaxPeriodDays.applySelectionchecksif (exceedsMaxPeriod) { setValidationError(...${maxPeriodDays}...) ; return; }but the dependency list omits bothexceedsMaxPeriodandmaxPeriodDays.
Cited code: apps/webapp/app/components/runs/v3/SharedFilters.tsx:455-540.
(Refers to lines 455-540)
Recommendation: Add exceedsMaxPeriod and maxPeriodDays to the dependency array (or compute exceedsMaxPeriod inside the callback).
Was this helpful? React with 👍 or 👎 to provide feedback.
...tes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsx
Show resolved
Hide resolved
This prevents cross-tenancy updates
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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/webapp/app/components/runs/v3/SharedFilters.tsx (1)
455-540: AddexceedsMaxPeriodandmaxPeriodDaysto theuseCallbackdependencies.The callback reads both values (line 458–459), but they're missing from the dependency array. Since
exceedsMaxPeriodis recalculated on each render andmaxPeriodDaysis a prop, omitting them causes the callback to close over stale values when these change.Proposed fix
], [ activeSection, selectedPeriod, isCustomDurationValid, customValue, customUnit, fromValue, toValue, replace, onApply, onValueChange, + exceedsMaxPeriod, + maxPeriodDays, ]);
🧹 Nitpick comments (2)
internal-packages/clickhouse/schema/014_update_output_error_text_to_extract_data.sql (1)
7-14: Consider extracting repeatedtoJSONString()call.
toJSONString(output)andtoJSONString(error)are each called up to 3 times within their respective expressions. While ClickHouse may optimize this for MATERIALIZED columns computed at insert time, this could be cleaner. Unfortunately, ClickHouse doesn't support CTEs or variable bindings within MATERIALIZED expressions, so this is likely unavoidable—just noting for awareness.Also applies to: 19-26
apps/webapp/app/components/runs/v3/SharedFilters.tsx (1)
289-308: Prefertypealiases overinterfacein TSX.This file uses interfaces for
TimeFilterApplyValuesandTimeFilterProps; please align with the project rule to use types instead.
As per coding guidelines, use type aliases over interfaces in TS/TSX.♻️ Proposed refactor
-export interface TimeFilterApplyValues { +export type TimeFilterApplyValues = { period?: string; from?: string; to?: string; -} +}; -export interface TimeFilterProps { +export type TimeFilterProps = { defaultPeriod?: string; period?: string; from?: string; to?: string; /** Label name used in the filter display, defaults to "Created" */ labelName?: string; hideLabel?: boolean; applyShortcut?: ShortcutDefinition | undefined; /** Callback when the user applies a time filter selection, receives the applied values */ onValueChange?: (values: TimeFilterApplyValues) => void; /** When set an upgrade message will be shown if you select a period further back than this number of days */ maxPeriodDays?: number; -} +};
📜 Review details
Configuration used: Repository 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 (32)
apps/webapp/app/components/code/QueryResultsChart.tsxapps/webapp/app/components/code/TSQLResultsTable.tsxapps/webapp/app/components/primitives/AnimatedNumber.tsxapps/webapp/app/components/primitives/Callout.tsxapps/webapp/app/components/primitives/Resizable.tsxapps/webapp/app/components/primitives/charts/Card.tsxapps/webapp/app/components/primitives/charts/ChartLegendCompound.tsxapps/webapp/app/components/primitives/charts/ChartLine.tsxapps/webapp/app/components/primitives/charts/ChartRoot.tsxapps/webapp/app/components/runs/v3/SharedFilters.tsxapps/webapp/app/env.server.tsapps/webapp/app/presenters/v3/QueryPresenter.server.tsapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHelpSidebar.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHistoryPopover.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsxapps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsxapps/webapp/app/services/queryService.server.tsapps/webapp/app/v3/querySchemas.tsapps/webapp/app/v3/services/aiQueryTitleService.server.tsapps/webapp/package.jsoninternal-packages/clickhouse/schema/014_update_output_error_text_to_extract_data.sqlinternal-packages/clickhouse/src/client/tsql.tsinternal-packages/clickhouse/src/index.tsinternal-packages/database/prisma/migrations/20260124203524_customer_query_add_title_remove_cost/migration.sqlinternal-packages/database/prisma/schema.prismainternal-packages/tsql/src/index.test.tsinternal-packages/tsql/src/index.tsinternal-packages/tsql/src/query/printer.test.tsinternal-packages/tsql/src/query/printer.tsinternal-packages/tsql/src/query/printer_context.tsinternal-packages/tsql/src/query/schema.tsinternal-packages/tsql/src/query/security.test.ts
💤 Files with no reviewable changes (1)
- apps/webapp/app/env.server.ts
🚧 Files skipped from review as they are similar to previous changes (14)
- apps/webapp/package.json
- apps/webapp/app/v3/services/aiQueryTitleService.server.ts
- internal-packages/tsql/src/query/schema.ts
- apps/webapp/app/components/code/QueryResultsChart.tsx
- internal-packages/clickhouse/src/index.ts
- apps/webapp/app/components/primitives/AnimatedNumber.tsx
- apps/webapp/app/presenters/v3/QueryPresenter.server.ts
- apps/webapp/app/components/primitives/charts/ChartRoot.tsx
- apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHelpSidebar.tsx
- internal-packages/database/prisma/migrations/20260124203524_customer_query_add_title_remove_cost/migration.sql
- apps/webapp/app/v3/querySchemas.ts
- apps/webapp/app/components/code/TSQLResultsTable.tsx
- apps/webapp/app/components/primitives/Callout.tsx
- apps/webapp/app/components/primitives/charts/Card.tsx
🧰 Additional context used
📓 Path-based instructions (12)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.{ts,tsx}: Use types over interfaces for TypeScript
Avoid using enums; prefer string unions or const objects instead
**/*.{ts,tsx}: Always import tasks from@trigger.dev/sdk, never use@trigger.dev/sdk/v3or deprecatedclient.defineJobpattern
Every Trigger.dev task must be exported and have a uniqueidproperty with no timeouts in the run function
Files:
apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsxapps/webapp/app/components/runs/v3/SharedFilters.tsxinternal-packages/tsql/src/query/printer.tsinternal-packages/tsql/src/query/security.test.tsapps/webapp/app/components/primitives/charts/ChartLine.tsxinternal-packages/tsql/src/query/printer.test.tsinternal-packages/clickhouse/src/client/tsql.tsinternal-packages/tsql/src/query/printer_context.tsinternal-packages/tsql/src/index.test.tsapps/webapp/app/services/queryService.server.tsapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsxapps/webapp/app/components/primitives/Resizable.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHistoryPopover.tsxapps/webapp/app/components/primitives/charts/ChartLegendCompound.tsxinternal-packages/tsql/src/index.ts
{packages/core,apps/webapp}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use zod for validation in packages/core and apps/webapp
Files:
apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsxapps/webapp/app/components/runs/v3/SharedFilters.tsxapps/webapp/app/components/primitives/charts/ChartLine.tsxapps/webapp/app/services/queryService.server.tsapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsxapps/webapp/app/components/primitives/Resizable.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHistoryPopover.tsxapps/webapp/app/components/primitives/charts/ChartLegendCompound.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use function declarations instead of default exports
Import from
@trigger.dev/coreusing subpaths only, never import from root
Files:
apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsxapps/webapp/app/components/runs/v3/SharedFilters.tsxinternal-packages/tsql/src/query/printer.tsinternal-packages/tsql/src/query/security.test.tsapps/webapp/app/components/primitives/charts/ChartLine.tsxinternal-packages/tsql/src/query/printer.test.tsinternal-packages/clickhouse/src/client/tsql.tsinternal-packages/tsql/src/query/printer_context.tsinternal-packages/tsql/src/index.test.tsapps/webapp/app/services/queryService.server.tsapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsxapps/webapp/app/components/primitives/Resizable.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHistoryPopover.tsxapps/webapp/app/components/primitives/charts/ChartLegendCompound.tsxinternal-packages/tsql/src/index.ts
apps/webapp/app/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)
Access all environment variables through the
envexport ofenv.server.tsinstead of directly accessingprocess.envin the Trigger.dev webapp
Files:
apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsxapps/webapp/app/components/runs/v3/SharedFilters.tsxapps/webapp/app/components/primitives/charts/ChartLine.tsxapps/webapp/app/services/queryService.server.tsapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsxapps/webapp/app/components/primitives/Resizable.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHistoryPopover.tsxapps/webapp/app/components/primitives/charts/ChartLegendCompound.tsx
apps/webapp/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)
apps/webapp/**/*.{ts,tsx}: When importing from@trigger.dev/corein the webapp, use subpath exports from the package.json instead of importing from the root path
Follow the Remix 2.1.0 and Express server conventions when updating the main trigger.dev webappAccess environment variables via
envexport fromapps/webapp/app/env.server.ts, never useprocess.envdirectly
Files:
apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsxapps/webapp/app/components/runs/v3/SharedFilters.tsxapps/webapp/app/components/primitives/charts/ChartLine.tsxapps/webapp/app/services/queryService.server.tsapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsxapps/webapp/app/components/primitives/Resizable.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHistoryPopover.tsxapps/webapp/app/components/primitives/charts/ChartLegendCompound.tsx
**/*.{js,ts,jsx,tsx,json,md,yaml,yml}
📄 CodeRabbit inference engine (AGENTS.md)
Format code using Prettier before committing
Files:
apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsxapps/webapp/app/components/runs/v3/SharedFilters.tsxinternal-packages/tsql/src/query/printer.tsinternal-packages/tsql/src/query/security.test.tsapps/webapp/app/components/primitives/charts/ChartLine.tsxinternal-packages/tsql/src/query/printer.test.tsinternal-packages/clickhouse/src/client/tsql.tsinternal-packages/tsql/src/query/printer_context.tsinternal-packages/tsql/src/index.test.tsapps/webapp/app/services/queryService.server.tsapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsxapps/webapp/app/components/primitives/Resizable.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHistoryPopover.tsxapps/webapp/app/components/primitives/charts/ChartLegendCompound.tsxinternal-packages/tsql/src/index.ts
**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/otel-metrics.mdc)
**/*.ts: When creating or editing OTEL metrics (counters, histograms, gauges), ensure metric attributes have low cardinality by using only enums, booleans, bounded error codes, or bounded shard IDs
Do not use high-cardinality attributes in OTEL metrics such as UUIDs/IDs (envId, userId, runId, projectId, organizationId), unbounded integers (itemCount, batchSize, retryCount), timestamps (createdAt, startTime), or free-form strings (errorMessage, taskName, queueName)
When exporting OTEL metrics via OTLP to Prometheus, be aware that the exporter automatically adds unit suffixes to metric names (e.g., 'my_duration_ms' becomes 'my_duration_ms_milliseconds', 'my_counter' becomes 'my_counter_total'). Account for these transformations when writing Grafana dashboards or Prometheus queries
Files:
internal-packages/tsql/src/query/printer.tsinternal-packages/tsql/src/query/security.test.tsinternal-packages/tsql/src/query/printer.test.tsinternal-packages/clickhouse/src/client/tsql.tsinternal-packages/tsql/src/query/printer_context.tsinternal-packages/tsql/src/index.test.tsapps/webapp/app/services/queryService.server.tsinternal-packages/tsql/src/index.ts
**/*.{test,spec}.{ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use vitest for all tests in the Trigger.dev repository
Files:
internal-packages/tsql/src/query/security.test.tsinternal-packages/tsql/src/query/printer.test.tsinternal-packages/tsql/src/index.test.ts
**/*.test.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.test.{ts,tsx,js,jsx}: Test files should live beside the files under test and use descriptivedescribeanditblocks
Tests should avoid mocks or stubs and use the helpers from@internal/testcontainerswhen Redis or Postgres are needed
Use vitest for running unit tests
**/*.test.{ts,tsx,js,jsx}: Use vitest exclusively for testing and never mock anything - use testcontainers instead
Place test files next to source files with naming pattern: source file (e.g.,MyService.ts) →MyService.test.ts
Files:
internal-packages/tsql/src/query/security.test.tsinternal-packages/tsql/src/query/printer.test.tsinternal-packages/tsql/src/index.test.ts
**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use testcontainers helpers (
redisTest,postgresTest,containerTest) from@internal/testcontainersfor Redis/PostgreSQL testing instead of mocks
Files:
internal-packages/tsql/src/query/security.test.tsinternal-packages/tsql/src/query/printer.test.tsinternal-packages/tsql/src/index.test.ts
internal-packages/clickhouse/schema/**/*.sql
📄 CodeRabbit inference engine (CLAUDE.md)
internal-packages/clickhouse/schema/**/*.sql: ClickHouse migrations must use Goose format with-- +goose Upand-- +goose Downmarkers
Follow ClickHouse naming conventions:raw_prefix for input tables,_v1,_v2suffixes for versioning,_mv_v1suffix for materialized views
Files:
internal-packages/clickhouse/schema/014_update_output_error_text_to_extract_data.sql
apps/webapp/app/services/**/*.server.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)
Separate testable services from configuration files; follow the pattern of
realtimeClient.server.ts(testable service) andrealtimeClientGlobal.server.ts(configuration) in the webapp
Files:
apps/webapp/app/services/queryService.server.ts
🧠 Learnings (13)
📚 Learning: 2026-01-15T11:50:06.067Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to internal-packages/database/prisma/migrations/**/*.sql : When editing the Prisma schema, remove extraneous migration lines related to specific tables: `_BackgroundWorkerToBackgroundWorkerFile`, `_BackgroundWorkerToTaskQueue`, `_TaskRunToTaskRunTag`, `_WaitpointRunConnections`, `_completedWaitpoints`, `SecretStore_key_idx`, and unrelated `TaskRun` indexes
Applied to files:
internal-packages/database/prisma/schema.prismainternal-packages/clickhouse/schema/014_update_output_error_text_to_extract_data.sql
📚 Learning: 2025-12-08T15:19:56.823Z
Learnt from: 0ski
Repo: triggerdotdev/trigger.dev PR: 2760
File: apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx:278-281
Timestamp: 2025-12-08T15:19:56.823Z
Learning: In apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx, the tableState search parameter uses intentional double-encoding: the parameter value contains a URL-encoded URLSearchParams string, so decodeURIComponent(value("tableState") ?? "") is required to fully decode it before parsing with new URLSearchParams(). This pattern allows bundling multiple filter/pagination params as a single search parameter.
Applied to files:
apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsxinternal-packages/tsql/src/query/security.test.tsapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHistoryPopover.tsx
📚 Learning: 2025-11-27T16:26:58.661Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/webapp.mdc:0-0
Timestamp: 2025-11-27T16:26:58.661Z
Learning: Applies to apps/webapp/**/*.{ts,tsx} : Follow the Remix 2.1.0 and Express server conventions when updating the main trigger.dev webapp
Applied to files:
apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsx
📚 Learning: 2025-08-14T10:53:54.526Z
Learnt from: myftija
Repo: triggerdotdev/trigger.dev PR: 2391
File: apps/webapp/app/services/organizationAccessToken.server.ts:50-0
Timestamp: 2025-08-14T10:53:54.526Z
Learning: In the Trigger.dev codebase, token service functions (like revokePersonalAccessToken and revokeOrganizationAccessToken) don't include tenant scoping in their database queries. Instead, authorization and tenant scoping happens at a higher level in the authentication flow (typically in route handlers) before these service functions are called. This is a consistent pattern across both Personal Access Tokens (PATs) and Organization Access Tokens (OATs).
Applied to files:
apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsxapps/webapp/app/services/queryService.server.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger.config.ts : Set default maximum duration in trigger.config.ts using `maxDuration` property
Applied to files:
apps/webapp/app/components/runs/v3/SharedFilters.tsx
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Limit task duration using the `maxDuration` property (in seconds)
Applied to files:
apps/webapp/app/components/runs/v3/SharedFilters.tsx
📚 Learning: 2025-07-21T12:52:44.342Z
Learnt from: ericallam
Repo: triggerdotdev/trigger.dev PR: 2284
File: apps/webapp/app/services/realtimeClient.server.ts:111-127
Timestamp: 2025-07-21T12:52:44.342Z
Learning: Electric (the database service used in the realtimeClient) has built-in SQL injection protection and safely handles whereClause parameters passed via URL parameters, so direct string interpolation of runId values into SQL where clauses is safe when using Electric.
Applied to files:
internal-packages/tsql/src/query/security.test.ts
📚 Learning: 2025-07-12T18:06:04.133Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 2264
File: apps/webapp/app/services/runsRepository.server.ts:172-174
Timestamp: 2025-07-12T18:06:04.133Z
Learning: In apps/webapp/app/services/runsRepository.server.ts, the in-memory status filtering after fetching runs from Prisma is intentionally used as a workaround for ClickHouse data delays. This approach is acceptable because the result set is limited to a maximum of 100 runs due to pagination, making the performance impact negligible.
Applied to files:
internal-packages/clickhouse/src/client/tsql.ts
📚 Learning: 2025-11-27T16:26:37.432Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T16:26:37.432Z
Learning: Applies to packages/trigger-sdk/**/*.{ts,tsx} : In the Trigger.dev SDK (packages/trigger-sdk), prefer isomorphic code like fetch and ReadableStream instead of Node.js-specific code
Applied to files:
internal-packages/tsql/src/query/printer_context.ts
📚 Learning: 2026-01-15T11:50:06.067Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to internal-packages/clickhouse/schema/**/*.sql : Follow ClickHouse naming conventions: `raw_` prefix for input tables, `_v1`, `_v2` suffixes for versioning, `_mv_v1` suffix for materialized views
Applied to files:
internal-packages/clickhouse/schema/014_update_output_error_text_to_extract_data.sql
📚 Learning: 2026-01-15T11:50:06.067Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to internal-packages/clickhouse/schema/**/*.sql : ClickHouse migrations must use Goose format with `-- +goose Up` and `-- +goose Down` markers
Applied to files:
internal-packages/clickhouse/schema/014_update_output_error_text_to_extract_data.sql
📚 Learning: 2025-11-27T16:26:37.432Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T16:26:37.432Z
Learning: Applies to internal-packages/database/**/*.{ts,tsx} : Use Prisma for database interactions in internal-packages/database with PostgreSQL
Applied to files:
apps/webapp/app/services/queryService.server.tsapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsx
📚 Learning: 2026-01-12T17:18:09.451Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 2870
File: apps/webapp/app/services/redisConcurrencyLimiter.server.ts:56-66
Timestamp: 2026-01-12T17:18:09.451Z
Learning: In `apps/webapp/app/services/redisConcurrencyLimiter.server.ts`, the query concurrency limiter will not be deployed with Redis Cluster mode, so multi-key operations (keyKey and globalKey in different hash slots) are acceptable and will function correctly in standalone Redis mode.
Applied to files:
apps/webapp/app/services/queryService.server.ts
🧬 Code graph analysis (7)
apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsx (5)
apps/webapp/app/utils/pathBuilder.ts (1)
EnvironmentParamSchema(26-28)apps/webapp/app/models/project.server.ts (1)
findProjectBySlug(136-147)apps/webapp/app/models/runtimeEnvironment.server.ts (1)
findEnvironmentBySlug(116-145)apps/webapp/app/env.server.ts (1)
env(1320-1320)apps/webapp/app/v3/services/aiQueryTitleService.server.ts (1)
AIQueryTitleService(15-71)
apps/webapp/app/components/runs/v3/SharedFilters.tsx (3)
apps/webapp/app/components/primitives/Callout.tsx (1)
Callout(73-170)apps/webapp/app/components/primitives/Buttons.tsx (1)
LinkButton(335-403)apps/webapp/app/utils/pathBuilder.ts (1)
organizationBillingPath(116-118)
internal-packages/tsql/src/query/printer.test.ts (2)
internal-packages/tsql/src/index.ts (5)
createPrinterContext(119-119)TableSchema(113-113)column(81-81)createSchemaRegistry(82-82)PrinterContext(121-121)internal-packages/tsql/src/query/printer_context.ts (2)
createPrinterContext(249-256)PrinterContext(79-214)
internal-packages/clickhouse/src/client/tsql.ts (3)
internal-packages/tsql/src/index.ts (1)
WhereClauseCondition(127-127)internal-packages/clickhouse/src/index.ts (1)
WhereClauseCondition(59-59)internal-packages/tsql/src/query/printer_context.ts (1)
WhereClauseCondition(47-47)
internal-packages/tsql/src/query/printer_context.ts (1)
internal-packages/tsql/src/query/schema.ts (2)
SchemaRegistry(344-349)FieldMappings(270-270)
internal-packages/tsql/src/index.test.ts (3)
internal-packages/tsql/src/index.ts (4)
column(81-81)TableSchema(113-113)WhereClauseCondition(127-127)compileTSQL(538-566)internal-packages/clickhouse/src/index.ts (2)
TableSchema(54-54)WhereClauseCondition(59-59)internal-packages/tsql/src/query/printer_context.ts (1)
WhereClauseCondition(47-47)
apps/webapp/app/components/primitives/charts/ChartLegendCompound.tsx (2)
apps/webapp/app/utils/cn.ts (1)
cn(77-79)apps/webapp/app/components/primitives/AnimatedNumber.tsx (1)
AnimatedNumber(22-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). (18)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (5, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (8, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 8)
- GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
- GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
- GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
- GitHub Check: typecheck / typecheck
🔇 Additional comments (15)
apps/webapp/app/components/primitives/charts/ChartLegendCompound.tsx (3)
20-22: LGTM!The
scrollableprop is well-documented and defaults tofalseto maintain backward compatibility.Also applies to: 42-42
134-158: LGTM!The scrollable container implementation is correct:
min-h-0on flex children properly allows shrinking below content size.shrink-0on the total row and separator prevents them from being compressed.flex-1withoverflow-y-autoon the items container enables proper scrolling behavior.
159-216: LGTM!Legend items rendering is clean with proper hover interactions and active state highlighting preserved within the new scrollable structure.
apps/webapp/app/components/primitives/charts/ChartLine.tsx (1)
175-175: LGTM!Consistent reduction of
strokeWidthfrom 2 to 1 for both Area and Line chart variants results in a cleaner, thinner visual appearance as intended.Also applies to: 223-223
internal-packages/clickhouse/schema/014_update_output_error_text_to_extract_data.sql (3)
1-1: Goose format and naming conventions followed correctly.The migration properly uses
-- +goose Upand-- +goose Downmarkers, and the tabletask_runs_v2follows the required_v2suffix convention. Based on learnings and coding guidelines.Also applies to: 34-34
34-45: Down migration is correctly ordered.Dropping indexes before columns is the correct order (ClickHouse would fail otherwise), and
IF EXISTSguards provide safe rollback behavior.
6-15: ADD COLUMN is correct—these are new columns, not existing ones to modify.The columns
output_textanderror_textdo not exist in any previous migration (001–013). This migration is their initial creation, soADD COLUMNis the appropriate statement. TheMODIFY COLUMNconcern is not applicable here.The migration correctly uses Goose format (
-- +goose Upand-- +goose Downmarkers) and includes proper rollback operations.Likely an incorrect or invalid review comment.
apps/webapp/app/components/primitives/Resizable.tsx (3)
29-38: Verifydata-handle-orientationis emitted byPanelResizer.
These selectors depend on the library setting that attribute; if it differs, vertical styling won’t apply. Please confirm the actual attribute name and adjust if needed.
44-47: Orientation-specific line indicators look good.
The separate horizontal/vertical indicators and hover transitions are clear and consistent.
50-61: Dot layout switching per orientation is clear.
The hidden/flex toggles make the handle dots adapt cleanly for each orientation.internal-packages/database/prisma/schema.prisma (1)
2455-2456: Optional query title field looks good.This aligns with the new AI title feature without forcing existing rows to migrate.
internal-packages/clickhouse/src/client/tsql.ts (1)
42-103: enforcedWhereClause documentation and examples read well.The API intent is clear and aligns with the enforced tenant/plan guard behavior.
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHistoryPopover.tsx (1)
122-135: Title + query rendering looks solid.The two-line layout with expanded clamp and preserved whitespace fits the new title feature nicely.
internal-packages/tsql/src/query/security.test.ts (1)
55-61: Tests updated cleanly for enforcedWhereClause.The new default options and optional-guard cases still cover tenant isolation paths well.
internal-packages/tsql/src/query/printer.test.ts (1)
666-1006: Great coverage for JSON textColumn/dataPrefix behavior.These scenarios should catch regressions in SELECT/WHERE/GROUP BY handling.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
Summary
Changes