-
-
Notifications
You must be signed in to change notification settings - Fork 978
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
|
WalkthroughThis diff introduces a household of coordinated changes: a new enforcedWhereClause model in the tsql package (types, PrinterContext, printer, tests) and renames WhereClauseFallback → WhereClauseCondition; ClickHouse client and executor now accept enforcedWhereClause and detect maxRows overflow; query execution API now returns ExecuteQueryResult with queryId and requires explicit organization/project/environment fields; adds AIQueryTitleService plus an ai-title route and DB migration adding CustomerQuery.title while removing costInCents; environment schema and several frontend components were updated (chart legend scrollable, AnimatedNumber decimals, table styling, Resizable UI, Callout visuals, chart tweaks), many route/UX changes for query title generation and time-filter maxPeriodDays, and multiple package/test adjustments. 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 review detailsConfiguration used: Repository UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (2)
🧰 Additional context used📓 Path-based instructions (7)**/*.{ts,tsx}📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Files:
**/*.{ts,tsx,js,jsx}📄 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,spec}.{ts,tsx}📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Files:
**/*.test.{ts,tsx,js,jsx}📄 CodeRabbit inference engine (AGENTS.md)
Files:
**/*.test.{ts,tsx}📄 CodeRabbit inference engine (CLAUDE.md)
Files:
🧬 Code graph analysis (1)internal-packages/tsql/src/query/printer.test.ts (3)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (12)
✏️ 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.
.../_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHelpSidebar.tsx
Show resolved
Hide resolved
.../_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHelpSidebar.tsx
Show resolved
Hide resolved
...tes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsx
Show resolved
Hide resolved
...tes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsx
Show resolved
Hide resolved
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.
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.
...tes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsx
Show resolved
Hide resolved
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.
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
This prevents cross-tenancy updates
5b56f6b to
713207e
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: 3
🤖 Fix all issues with AI agents
In `@apps/webapp/app/components/primitives/Resizable.tsx`:
- Around line 29-61: The current Resizable handle uses non-existent
data-[handle-orientation] selectors; remove those selectors and instead accept
an explicit orientation prop (e.g., orientation: 'horizontal' | 'vertical') on
the Resizable/PanelResizer component and use that prop to conditionally apply
classes and render vertical vs horizontal variants (replace every occurrence of
data-[handle-orientation=vertical] with conditional class logic based on
orientation === 'vertical', and branch rendering for the line indicator and dot
groups accordingly), and update callers of Resizable/PanelResizer to pass the
PanelGroup orientation prop through.
In
`@apps/webapp/app/routes/_app.orgs`.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsx:
- Around line 291-319: The clip warning is skipped for "to-only" filters because
requestedFromDate remains null; update the logic so "to-only" requests trigger
the clip callout. Specifically, in the code that sets periodClipped (using
requestedFromDate, maxQueryPeriodDate, and timeFilter), change the condition to
treat requestedFromDate === null as clipped (e.g., periodClipped true when
requestedFromDate === null || requestedFromDate < maxQueryPeriodDate) so the
callout appears for to-only filters; keep the rest of the
requestedFromDate/triggeredAtFallback logic intact.
In `@internal-packages/tsql/src/query/printer.ts`:
- Around line 1868-1882: The generated left identifier for text-column
comparisons loses the original table alias when replacing node.left with
leftTextColumn, causing ambiguous/wrong bindings; change the logic that builds
leftTextColumn (from getTextColumnForExpression(node.left)) to preserve the
original qualifier/alias from node.left (e.g., if node.left is a field/column
reference, copy its table alias/qualifier onto the returned text-column
identifier) before calling printIdentifier(leftTextColumn), so printIdentifier
receives a qualified identifier; update getTextColumnForExpression or the code
just after obtaining leftTextColumn to attach the original qualifier and then
call printIdentifier(leftTextColumn) instead of using an unqualified name.
🧹 Nitpick comments (6)
apps/webapp/app/services/queryService.server.ts (1)
121-126: Inconsistent indentation in acquire block.The concurrency acquisition code has extra indentation that doesn't match the surrounding code structure. This appears to be a formatting inconsistency.
🛠️ Suggested fix
// Acquire concurrency slot - const acquireResult = await queryConcurrencyLimiter.acquire({ - key: organizationId, - requestId, - keyLimit: orgLimit, - globalLimit: GLOBAL_CONCURRENCY_LIMIT, - }); + const acquireResult = await queryConcurrencyLimiter.acquire({ + key: organizationId, + requestId, + keyLimit: orgLimit, + globalLimit: GLOBAL_CONCURRENCY_LIMIT, + });apps/webapp/app/components/code/TSQLResultsTable.tsx (1)
674-678: Handle raw string JSON values without losing quotes.If JSON scalars can arrive as plain strings (not JSON-encoded text), rendering them directly drops quotes and can misrepresent the JSON value. Consider falling back to
JSON.stringifywhen the string isn’t valid JSON text to preserve correct JSON representation.Proposed tweak
- const jsonString = typeof value === "string" ? value : JSON.stringify(value); + const jsonString = + typeof value === "string" + ? (() => { + try { + JSON.parse(value); + return value; + } catch { + return JSON.stringify(value); + } + })() + : JSON.stringify(value);apps/webapp/app/components/code/QueryResultsChart.tsx (1)
49-58: Prefer atypealias for props to match TS conventions.♻️ Suggested refactor
-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:
**/*.{ts,tsx}: Use types over interfaces for TypeScript`.internal-packages/clickhouse/src/client/tsql.ts (1)
33-104: Prefertypealias for ExecuteTSQLOptions.This block was edited; the repo style prefers
typealiases over interfaces. Consider switching to a type alias here.♻️ Suggested refactor
-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; @@ -} +};As per coding guidelines: Use types over interfaces for TypeScript.
internal-packages/tsql/src/index.ts (1)
450-504: Prefertypealias for CompileTSQLOptions.This block was edited; the repo style prefers
typealiases over interfaces. Consider switching to a type alias.♻️ Suggested refactor
-export interface CompileTSQLOptions { +export type CompileTSQLOptions = { /** Schema definitions for allowed tables and columns */ tableSchema: TableSchema[]; @@ -} +};As per coding guidelines: Use types over interfaces for TypeScript.
internal-packages/tsql/src/query/printer.test.ts (1)
83-95: Consider extracting a shared enforcedWhereClause test fixture.The same tenant guard object is repeated across many helper contexts. A shared constant (with per-test overrides as needed) would reduce duplication and make future updates less noisy.
Also applies to: 155-164, 221-229, 481-490, 697-706, 888-897, 1469-1476, 1588-1594, 1813-1820, 2056-2063, 2202-2209, 2901-2920, 3084-3093
📜 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_update_output_error_text_to_extract_data.sqlinternal-packages/clickhouse/src/client/tsql.tsinternal-packages/clickhouse/src/index.tsinternal-packages/clickhouse/src/tsql.test.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/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHelpSidebar.tsx
- apps/webapp/app/presenters/v3/QueryPresenter.server.ts
- internal-packages/tsql/src/query/schema.ts
- apps/webapp/package.json
- apps/webapp/app/components/primitives/AnimatedNumber.tsx
- internal-packages/database/prisma/migrations/20260124203524_customer_query_add_title_remove_cost/migration.sql
- internal-packages/clickhouse/src/tsql.test.ts
- apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHistoryPopover.tsx
- apps/webapp/app/components/primitives/Callout.tsx
- internal-packages/clickhouse/schema/014_update_output_error_text_to_extract_data.sql
- apps/webapp/app/components/primitives/charts/ChartRoot.tsx
- apps/webapp/app/components/primitives/charts/ChartLine.tsx
- apps/webapp/app/v3/querySchemas.ts
- internal-packages/tsql/src/query/printer_context.ts
🧰 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/components/code/TSQLResultsTable.tsxinternal-packages/clickhouse/src/index.tsapps/webapp/app/components/code/QueryResultsChart.tsxapps/webapp/app/components/primitives/charts/ChartLegendCompound.tsxinternal-packages/tsql/src/query/security.test.tsapps/webapp/app/v3/services/aiQueryTitleService.server.tsinternal-packages/tsql/src/query/printer.tsinternal-packages/tsql/src/index.test.tsapps/webapp/app/components/primitives/Resizable.tsxapps/webapp/app/components/primitives/charts/Card.tsxinternal-packages/clickhouse/src/client/tsql.tsinternal-packages/tsql/src/query/printer.test.tsapps/webapp/app/components/runs/v3/SharedFilters.tsxapps/webapp/app/services/queryService.server.tsinternal-packages/tsql/src/index.tsapps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsxapps/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/components/code/QueryResultsChart.tsxapps/webapp/app/components/primitives/charts/ChartLegendCompound.tsxapps/webapp/app/v3/services/aiQueryTitleService.server.tsapps/webapp/app/components/primitives/Resizable.tsxapps/webapp/app/components/primitives/charts/Card.tsxapps/webapp/app/components/runs/v3/SharedFilters.tsxapps/webapp/app/services/queryService.server.tsapps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsxapps/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.tsxinternal-packages/clickhouse/src/index.tsapps/webapp/app/components/code/QueryResultsChart.tsxapps/webapp/app/components/primitives/charts/ChartLegendCompound.tsxinternal-packages/tsql/src/query/security.test.tsapps/webapp/app/v3/services/aiQueryTitleService.server.tsinternal-packages/tsql/src/query/printer.tsinternal-packages/tsql/src/index.test.tsapps/webapp/app/components/primitives/Resizable.tsxapps/webapp/app/components/primitives/charts/Card.tsxinternal-packages/clickhouse/src/client/tsql.tsinternal-packages/tsql/src/query/printer.test.tsapps/webapp/app/components/runs/v3/SharedFilters.tsxapps/webapp/app/services/queryService.server.tsinternal-packages/tsql/src/index.tsapps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsxapps/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/components/code/QueryResultsChart.tsxapps/webapp/app/components/primitives/charts/ChartLegendCompound.tsxapps/webapp/app/v3/services/aiQueryTitleService.server.tsapps/webapp/app/components/primitives/Resizable.tsxapps/webapp/app/components/primitives/charts/Card.tsxapps/webapp/app/components/runs/v3/SharedFilters.tsxapps/webapp/app/services/queryService.server.tsapps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsxapps/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/components/code/QueryResultsChart.tsxapps/webapp/app/components/primitives/charts/ChartLegendCompound.tsxapps/webapp/app/v3/services/aiQueryTitleService.server.tsapps/webapp/app/components/primitives/Resizable.tsxapps/webapp/app/components/primitives/charts/Card.tsxapps/webapp/app/components/runs/v3/SharedFilters.tsxapps/webapp/app/services/queryService.server.tsapps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsxapps/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.tsxinternal-packages/clickhouse/src/index.tsapps/webapp/app/components/code/QueryResultsChart.tsxapps/webapp/app/components/primitives/charts/ChartLegendCompound.tsxinternal-packages/tsql/src/query/security.test.tsapps/webapp/app/v3/services/aiQueryTitleService.server.tsinternal-packages/tsql/src/query/printer.tsinternal-packages/tsql/src/index.test.tsapps/webapp/app/components/primitives/Resizable.tsxapps/webapp/app/components/primitives/charts/Card.tsxinternal-packages/clickhouse/src/client/tsql.tsinternal-packages/tsql/src/query/printer.test.tsapps/webapp/app/components/runs/v3/SharedFilters.tsxapps/webapp/app/services/queryService.server.tsinternal-packages/tsql/src/index.tsapps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsx
**/*.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/clickhouse/src/index.tsinternal-packages/tsql/src/query/security.test.tsapps/webapp/app/v3/services/aiQueryTitleService.server.tsinternal-packages/tsql/src/query/printer.tsinternal-packages/tsql/src/index.test.tsinternal-packages/clickhouse/src/client/tsql.tsinternal-packages/tsql/src/query/printer.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/index.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/query/security.test.tsinternal-packages/tsql/src/index.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/query/security.test.tsinternal-packages/tsql/src/index.test.tsinternal-packages/tsql/src/query/printer.test.ts
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
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 (12)
📚 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.prisma
📚 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:
internal-packages/tsql/src/query/security.test.tsapps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.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-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: 2026-01-28T14:15:09.778Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 2953
File: apps/webapp/app/components/runs/v3/SharedFilters.tsx:441-452
Timestamp: 2026-01-28T14:15:09.778Z
Learning: In apps/webapp/app/components/runs/v3/SharedFilters.tsx, enforce the maxPeriodDays limit based only on the from date (fromValue) using dateRangeToDays(fromValue) to reflect data retention limits. The to date should be ignored for retention checks. Ensure any retention-window logic or validations rely solely on the fromValue, and update related comments/tests if needed.
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.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-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.tsapps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsx
📚 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
📚 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: 2026-01-28T14:15:09.778Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 2953
File: apps/webapp/app/components/runs/v3/SharedFilters.tsx:441-452
Timestamp: 2026-01-28T14:15:09.778Z
Learning: In apps/webapp/app/components/runs/v3/SharedFilters.tsx, the maxPeriodDays limit for date ranges should only check the from date (via dateRangeToDays(fromValue)) because it enforces data retention limits—how far back in history queries can reach. The to date is irrelevant for retention-based limits.
Applied to files:
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsx
🧬 Code graph analysis (8)
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(35-71)
apps/webapp/app/v3/services/aiQueryTitleService.server.ts (1)
apps/webapp/app/env.server.ts (1)
env(1320-1320)
internal-packages/tsql/src/index.test.ts (4)
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/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.test.ts (2)
internal-packages/tsql/src/query/printer_context.ts (2)
createPrinterContext(249-256)PrinterContext(79-214)internal-packages/tsql/src/query/schema.ts (3)
TableSchema(321-339)column(354-366)createSchemaRegistry(371-387)
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.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/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsx (8)
apps/webapp/app/services/platform.v3.server.ts (1)
getLimit(241-250)internal-packages/clickhouse/src/index.ts (1)
WhereClauseCondition(59-59)internal-packages/tsql/src/query/printer_context.ts (1)
WhereClauseCondition(47-47)internal-packages/clickhouse/src/client/noop.ts (1)
query(39-53)apps/webapp/app/routes/_app.orgs.$organizationSlug/route.tsx (1)
useCurrentPlan(22-29)apps/webapp/app/hooks/useSearchParam.ts (1)
useSearchParams(7-64)apps/webapp/app/utils/pathBuilder.ts (1)
organizationBillingPath(116-118)apps/webapp/app/components/primitives/Dialog.tsx (1)
DialogHeader(120-120)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (13)
- GitHub Check: 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 / internal / 🧪 Unit Tests: Internal (6, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 8)
- GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
- GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
- GitHub Check: typecheck / typecheck
🔇 Additional comments (34)
apps/webapp/app/components/primitives/charts/Card.tsx (1)
9-9: LGTM! Spacing refinements align with the broader UI consistency updates.The padding and margin adjustments (
pb-2 → pb-1.5,pt-4 → pt-3,mb-4 → mb-3,px-4 → px-3) create a tighter, more compact card layout that complements the chart legend and other layout tweaks in this PR.Also applies to: 20-20
apps/webapp/app/components/runs/v3/SharedFilters.tsx (9)
1-31: LGTM!The new imports are all used appropriately within the file for the
maxPeriodDaysfeature implementation.
126-140: LGTM!The
periodToDaysanddateRangeToDayshelper functions are well-implemented for calculating retention window checks. The implementation correctly focuses on thefromdate for retention-based limits. Based on learnings: "enforce the maxPeriodDays limit based only on the from date (fromValue) using dateRangeToDays(fromValue) to reflect data retention limits."
374-375: LGTM!Using a string union type for
SectionTypealigns with the coding guidelines preference for string unions over enums.
441-453: LGTM!The
exceedsMaxPeriodcalculation correctly checks only thefromdate for date ranges, which aligns with the data retention semantics. Based on learnings: "The maxPeriodDays limit for date ranges should only check the from date (via dateRangeToDays(fromValue)) because it enforces data retention limits."
[approve_code_changes, duplicate_comment]
455-542: LGTM!The
applySelectioncallback correctly enforces themaxPeriodDayslimit with an early return and appropriate error message. The dependency array is properly updated to includeexceedsMaxPeriodandmaxPeriodDays.
727-790: LGTM!The quick date presets now consistently set both
fromandtodates (e.g., "Today" sets the full day range rather than just a start date). This provides a more intuitive UX and aligns with user expectations for date range selections.
799-808: LGTM!The upgrade Callout is well-implemented with proper conditional rendering, pluralization via
simplur, and a clear CTA linking to the organization's billing page.
825-840: LGTM!Disabling the Apply button when
exceedsMaxPeriodis true provides clear feedback to users and works in conjunction with the upgrade Callout to guide users toward upgrading their plan.
401-401: LGTM!Using
useOptionalOrganizationis appropriate here since the Callout with the upgrade link should only render when an organization context is available.apps/webapp/app/services/queryService.server.ts (2)
186-193: LGTM!The duplicate detection logic correctly compares the query text, scope, and time filter settings. The date comparison using optional chaining properly handles null/undefined cases for database null values.
164-217: LGTM!The return value handling correctly implements the
ExecuteQueryResultcontract:
- Error path returns early with
[error, null, null]- Success path returns
[null, result, queryId]with queryId populated when history tracking is enabledapps/webapp/app/components/code/TSQLResultsTable.tsx (1)
1136-1151: Row divider styling looks good.Adds consistent visual separation for rows in the virtualized body.
apps/webapp/app/components/primitives/Resizable.tsx (1)
20-26: Nice API polish withwithHandle.
Optional toggle with a safe default keeps current behavior intact.internal-packages/database/prisma/schema.prisma (1)
2455-2456: LGTM for optional title storage.apps/webapp/app/v3/services/aiQueryTitleService.server.ts (1)
21-69: Service-level error handling and prompt constraints look solid.apps/webapp/app/components/primitives/charts/ChartLegendCompound.tsx (1)
134-216: Scrollable legend UX changes look clean and consistent.apps/webapp/app/components/code/QueryResultsChart.tsx (1)
724-927: Legend scrollable prop is wired consistently throughChart.Root.apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsx (2)
603-639: Title generation flow wiring looks good.
302-326: No changes needed—Date objects are explicitly supported inWhereClauseCondition.The type definitions for
SimpleComparisonConditionandBetweenConditionexplicitly allowDate | string | numbervalues. The printer automatically serializes Date objects by wrapping them intoDateTime64()calls for ClickHouse compatibility. UsingmaxQueryPeriodDatedirectly is correct and follows the documented patterns throughout the codebase.Likely an incorrect or invalid review comment.
internal-packages/clickhouse/src/client/tsql.ts (2)
10-28: LGTM: WhereClauseCondition re-export keeps the ClickHouse surface aligned.
169-175: LGTM: enforcedWhereClause is now forwarded into compileTSQL.Ensures enforced guards propagate to the compiler path.
internal-packages/clickhouse/src/index.ts (1)
49-60: LGTM: WhereClauseCondition is exposed from the public entrypoint.internal-packages/tsql/src/index.ts (1)
551-563: LGTM: undefined enforcedWhereClause entries are stripped before printing.Nice guard against optional condition keys.
internal-packages/tsql/src/query/security.test.ts (2)
55-61: LGTM: default enforcedWhereClause fixture updated.
414-590: Nice coverage for optional tenant guards.The org-only / org+project / org+project+env cases read clearly and exercise the new API surface.
internal-packages/tsql/src/query/printer.ts (2)
397-401: LGTM: queryHasGroupBy state is saved/restored for JSON type hints.The scoped flag avoids leaking GROUP BY context across nested queries.
Also applies to: 553-553
639-679: LGTM: textColumn optimization preserves user-facing names.Aliasing back to the TSQL column name keeps the UX clean while using the optimized column.
Also applies to: 853-858
internal-packages/tsql/src/query/printer.test.ts (3)
611-663: Good coverage for JSON subfield WHERE handling.These assertions clearly lock in the no-
.:Stringbehavior for WHERE while keeping SELECT/GROUP BY semantics distinct.
666-855: Solid textColumn optimization tests.Nice breadth across SELECT, WHERE, and edge cases—should catch regressions around textColumn substitution.
857-1007: Nice dataPrefix path + aliasing coverage.Covers SELECT/WHERE/GROUP BY and alias behavior well, including edge cases.
internal-packages/tsql/src/index.test.ts (3)
12-75: LGTM for the new schema fixtures + base enforcement setup.These fixtures make the tenant/non-tenant scenarios explicit and improve coverage clarity.
167-231: Nice alignment to WhereClauseCondition in fallback tests.The updated typings keep fallback fixtures consistent with the public API surface.
516-828: Strong enforcedWhereClause coverage.Validation, interaction with fallbacks, and security-focused scenarios are well covered.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
.../app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsx
Show resolved
Hide resolved
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 (1)
internal-packages/tsql/src/query/printer.ts (1)
639-710: Add table qualification to text column references in JOINs.
getTextColumnForFieldreturns only the column name (e.g.,"output_text"), discarding table qualification. When multiple tables in a JOIN have the same text column, this produces ambiguous SQL. The function must preserve table context by returning the table alias alongside the column name and rendering both withprintIdentifierOrIndex.The issue affects three locations:
- Line 644: Bare JSON field selection with text column
- Line 702: Alias expressions with text column
- Line 1871: Arithmetic operation left operand comparison with text column
Update
getTextColumnForFieldandgetTextColumnForExpressionto returnArray<string | number> | nullinstead ofstring | null, and construct qualified references before rendering (e.g.,"runs"."output_text").
🤖 Fix all issues with AI agents
In `@apps/webapp/app/components/runs/v3/SharedFilters.tsx`:
- Around line 799-808: The current Callout for exceedsMaxPeriod only renders
when organization exists, leaving the Apply button disabled with no explanation
if organization is undefined; update the JSX in SharedFilters so that when
exceedsMaxPeriod is true you render a callout regardless of organization: if
organization exists keep the current Callout with the LinkButton CTA (using
organizationBillingPath(organization.slug)), otherwise render a simplified
Callout (no CTA) that displays the same message (e.g., "Your plan allows a
maximum of ${maxPeriodDays} day(s).") so users understand why Apply is disabled;
modify the conditional around Callout (checking only exceedsMaxPeriod) and
branch inside to include or omit the LinkButton accordingly.
🧹 Nitpick comments (2)
internal-packages/clickhouse/src/client/tsql.ts (1)
33-104: Prefer a type alias over an interface for ExecuteTSQLOptions.This keeps the public surface consistent with the project’s TypeScript style guidance.
♻️ Suggested refactor
-export interface ExecuteTSQLOptions<TOut extends z.ZodSchema> { +export type ExecuteTSQLOptions<TOut extends z.ZodSchema> = { /** The name of the operation (for logging/tracing) */ name: string; ... -} +};As per coding guidelines, "Use types over interfaces for TypeScript".
internal-packages/tsql/src/index.ts (1)
450-504: Prefer a type alias over interface for CompileTSQLOptions.This aligns the public API with the TS style guidance.
♻️ Suggested refactor
-export interface CompileTSQLOptions { +export type CompileTSQLOptions = { /** Schema definitions for allowed tables and columns */ tableSchema: TableSchema[]; ... -} +};As per coding guidelines, "Use types over interfaces for TypeScript".
📜 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 (34)
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/ExamplesContent.tsxapps/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/clickhouse/src/tsql.test.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/app/components/code/TSQLResultsTable.tsx
- apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHistoryPopover.tsx
- apps/webapp/app/components/primitives/Callout.tsx
- apps/webapp/package.json
- apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsx
- apps/webapp/app/v3/services/aiQueryTitleService.server.ts
- internal-packages/tsql/src/query/schema.ts
- internal-packages/clickhouse/src/index.ts
- apps/webapp/app/components/primitives/Resizable.tsx
- apps/webapp/app/components/primitives/charts/ChartRoot.tsx
- apps/webapp/app/components/primitives/charts/Card.tsx
- apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/QueryHelpSidebar.tsx
- internal-packages/clickhouse/schema/014_update_output_error_text_to_extract_data.sql
- apps/webapp/app/components/primitives/charts/ChartLine.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/components/primitives/AnimatedNumber.tsxapps/webapp/app/presenters/v3/QueryPresenter.server.tsapps/webapp/app/components/primitives/charts/ChartLegendCompound.tsxinternal-packages/tsql/src/query/security.test.tsinternal-packages/tsql/src/index.test.tsapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/ExamplesContent.tsxinternal-packages/tsql/src/query/printer_context.tsinternal-packages/tsql/src/query/printer.tsapps/webapp/app/components/code/QueryResultsChart.tsxinternal-packages/clickhouse/src/client/tsql.tsapps/webapp/app/components/runs/v3/SharedFilters.tsxapps/webapp/app/services/queryService.server.tsinternal-packages/tsql/src/index.tsinternal-packages/clickhouse/src/tsql.test.tsinternal-packages/tsql/src/query/printer.test.tsapps/webapp/app/v3/querySchemas.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/primitives/AnimatedNumber.tsxapps/webapp/app/presenters/v3/QueryPresenter.server.tsapps/webapp/app/components/primitives/charts/ChartLegendCompound.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/ExamplesContent.tsxapps/webapp/app/components/code/QueryResultsChart.tsxapps/webapp/app/components/runs/v3/SharedFilters.tsxapps/webapp/app/services/queryService.server.tsapps/webapp/app/v3/querySchemas.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/primitives/AnimatedNumber.tsxapps/webapp/app/presenters/v3/QueryPresenter.server.tsapps/webapp/app/components/primitives/charts/ChartLegendCompound.tsxinternal-packages/tsql/src/query/security.test.tsinternal-packages/tsql/src/index.test.tsapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/ExamplesContent.tsxinternal-packages/tsql/src/query/printer_context.tsinternal-packages/tsql/src/query/printer.tsapps/webapp/app/components/code/QueryResultsChart.tsxinternal-packages/clickhouse/src/client/tsql.tsapps/webapp/app/components/runs/v3/SharedFilters.tsxapps/webapp/app/services/queryService.server.tsinternal-packages/tsql/src/index.tsinternal-packages/clickhouse/src/tsql.test.tsinternal-packages/tsql/src/query/printer.test.tsapps/webapp/app/v3/querySchemas.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/primitives/AnimatedNumber.tsxapps/webapp/app/presenters/v3/QueryPresenter.server.tsapps/webapp/app/components/primitives/charts/ChartLegendCompound.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/ExamplesContent.tsxapps/webapp/app/components/code/QueryResultsChart.tsxapps/webapp/app/components/runs/v3/SharedFilters.tsxapps/webapp/app/services/queryService.server.tsapps/webapp/app/v3/querySchemas.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/primitives/AnimatedNumber.tsxapps/webapp/app/presenters/v3/QueryPresenter.server.tsapps/webapp/app/components/primitives/charts/ChartLegendCompound.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/ExamplesContent.tsxapps/webapp/app/components/code/QueryResultsChart.tsxapps/webapp/app/components/runs/v3/SharedFilters.tsxapps/webapp/app/services/queryService.server.tsapps/webapp/app/v3/querySchemas.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/primitives/AnimatedNumber.tsxapps/webapp/app/presenters/v3/QueryPresenter.server.tsapps/webapp/app/components/primitives/charts/ChartLegendCompound.tsxinternal-packages/tsql/src/query/security.test.tsinternal-packages/tsql/src/index.test.tsapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/ExamplesContent.tsxinternal-packages/tsql/src/query/printer_context.tsinternal-packages/tsql/src/query/printer.tsapps/webapp/app/components/code/QueryResultsChart.tsxinternal-packages/clickhouse/src/client/tsql.tsapps/webapp/app/components/runs/v3/SharedFilters.tsxapps/webapp/app/services/queryService.server.tsinternal-packages/tsql/src/index.tsinternal-packages/clickhouse/src/tsql.test.tsinternal-packages/tsql/src/query/printer.test.tsapps/webapp/app/v3/querySchemas.tsapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsx
**/*.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/tsql/src/query/security.test.tsinternal-packages/tsql/src/index.test.tsinternal-packages/tsql/src/query/printer_context.tsinternal-packages/tsql/src/query/printer.tsinternal-packages/clickhouse/src/client/tsql.tsapps/webapp/app/services/queryService.server.tsinternal-packages/tsql/src/index.tsinternal-packages/clickhouse/src/tsql.test.tsinternal-packages/tsql/src/query/printer.test.tsapps/webapp/app/v3/querySchemas.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/index.test.tsinternal-packages/clickhouse/src/tsql.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/query/security.test.tsinternal-packages/tsql/src/index.test.tsinternal-packages/clickhouse/src/tsql.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/query/security.test.tsinternal-packages/tsql/src/index.test.tsinternal-packages/clickhouse/src/tsql.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
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
🧠 Learnings (14)
📚 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/database/prisma/migrations/20260124203524_customer_query_add_title_remove_cost/migration.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:
internal-packages/tsql/src/query/security.test.tsapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/ExamplesContent.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.tsinternal-packages/clickhouse/src/tsql.test.ts
📚 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/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/ExamplesContent.tsx
📚 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: 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.tsinternal-packages/clickhouse/src/tsql.test.ts
📚 Learning: 2026-01-28T14:15:09.778Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 2953
File: apps/webapp/app/components/runs/v3/SharedFilters.tsx:441-452
Timestamp: 2026-01-28T14:15:09.778Z
Learning: In apps/webapp/app/components/runs/v3/SharedFilters.tsx, enforce the maxPeriodDays limit based only on the from date (fromValue) using dateRangeToDays(fromValue) to reflect data retention limits. The to date should be ignored for retention checks. Ensure any retention-window logic or validations rely solely on the fromValue, and update related comments/tests if needed.
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.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-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: 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
📚 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: 2026-01-28T14:15:09.778Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 2953
File: apps/webapp/app/components/runs/v3/SharedFilters.tsx:441-452
Timestamp: 2026-01-28T14:15:09.778Z
Learning: In apps/webapp/app/components/runs/v3/SharedFilters.tsx, the maxPeriodDays limit for date ranges should only check the from date (via dateRangeToDays(fromValue)) because it enforces data retention limits—how far back in history queries can reach. The to date is irrelevant for retention-based limits.
Applied to files:
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsx
🧬 Code graph analysis (9)
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(35-71)
internal-packages/tsql/src/index.test.ts (3)
internal-packages/tsql/src/index.ts (3)
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)
internal-packages/tsql/src/query/printer.ts (4)
internal-packages/tsql/src/query/ast.ts (3)
Alias(372-378)Field(468-472)Expression(47-78)internal-packages/tsql/src/query/schema.ts (3)
TableSchema(321-339)column(354-366)ColumnSchema(52-253)internal-packages/tsql/src/query/errors.ts (1)
QueryError(43-45)internal-packages/tsql/src/query/printer_context.ts (1)
WhereClauseCondition(47-47)
internal-packages/clickhouse/src/client/tsql.ts (1)
internal-packages/tsql/src/query/printer_context.ts (1)
WhereClauseCondition(47-47)
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)
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)
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/v3/querySchemas.ts (1)
internal-packages/tsql/src/query/schema.ts (1)
column(354-366)
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsx (7)
apps/webapp/app/services/platform.v3.server.ts (1)
getLimit(241-250)internal-packages/clickhouse/src/client/tsql.ts (1)
WhereClauseCondition(28-28)internal-packages/clickhouse/src/index.ts (2)
WhereClauseCondition(59-59)OutputColumnMetadata(61-61)internal-packages/tsql/src/query/printer_context.ts (1)
WhereClauseCondition(47-47)apps/webapp/app/presenters/v3/QueryPresenter.server.ts (1)
QueryHistoryItem(5-17)apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsx (1)
action(17-68)apps/webapp/app/routes/_app.orgs.$organizationSlug/route.tsx (1)
useCurrentPlan(22-29)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: units / internal / 📊 Merge Reports
🔇 Additional comments (51)
apps/webapp/app/components/primitives/AnimatedNumber.tsx (1)
4-61: Sanitization + locale formatting looks solid.The
sanitizeDecimals+useMemoflow keepstoLocaleStringsafe and predictable while preserving the auto-detection behavior.internal-packages/database/prisma/migrations/20260124203524_customer_query_add_title_remove_cost/migration.sql (1)
1-7: LGTM for the column swap. Clean, idempotent add/drop with no index side effects.apps/webapp/app/presenters/v3/QueryPresenter.server.ts (2)
5-16: Good addition of title to the public history shape.
21-53: Selection and mapping include title consistently.internal-packages/database/prisma/schema.prisma (1)
2443-2457: Schema update aligns with title usage.apps/webapp/app/components/runs/v3/SharedFilters.tsx (4)
126-140: LGTM!The helper functions are well-implemented.
periodToDayscorrectly uses parse-duration and safely returns 0 for invalid input.dateRangeToDaysappropriately calculates days from a given date to now.
441-453: Correct implementation per retention semantics.The
exceedsMaxPeriodcheck correctly only evaluatesfromValuefor date ranges, aligning with the data retention limit behavior where only how far back in history matters.Based on learnings: "In apps/webapp/app/components/runs/v3/SharedFilters.tsx, enforce the maxPeriodDays limit based only on the from date (fromValue) using dateRangeToDays(fromValue) to reflect data retention limits."
727-790: LGTM!Good improvements to the quick date buttons:
- Grid layout reorganization for better visual hierarchy
- Using
endOfDay(),endOfWeek(), andendOfMonth()for the "to" values ensures the full day/week/month is captured in the date range.
15-29: LGTM!New imports are appropriate for the added functionality -
simplurfor pluralization,CalloutandLinkButtonfor the upgrade prompt UI, anduseOptionalOrganizationwithorganizationBillingPathfor the billing CTA.apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/ExamplesContent.tsx (1)
51-51: LGTM!The column name change from
created_attotriggered_atcorrectly aligns with the user-facing schema defined inquerySchemas.tsand makes this example consistent with the other example queries in the file.apps/webapp/app/components/code/QueryResultsChart.tsx (2)
8-43: LGTM!The expanded color palette is well-organized with clear comment sections (primary, extended, additional) making it easy to understand and maintain. The 30 distinct colors provide good coverage for large datasets.
56-57: LGTM!The
legendScrollableprop is properly typed, has a sensible default value, and is correctly forwarded toChart.Rootin both the bar and line chart variants.Also applies to: 730-731, 901-901, 926-926
apps/webapp/app/v3/querySchemas.ts (2)
170-178: LGTM!The idempotency key schema changes are well-structured:
idempotency_keynow correctly maps to the ClickHouse columnidempotency_key_user- New
idempotency_key_scopefield has a clear description explaining the scope behavior and includes appropriateallowedValues
332-354: LGTM!The JSON column enhancements are well-documented with inline comments. The
textColumnanddataPrefixproperties enable performance optimizations by using pre-materialized text columns and handling the internal{"data": ...}wrapper transparently.internal-packages/tsql/src/query/security.test.ts (2)
55-62: LGTM!The
defaultOptionscorrectly demonstrates the newenforcedWhereClausestructure with explicit equality conditions for tenant guards. This is a clean API that makes the tenant filtering behavior explicit and configurable.
403-589: LGTM!The "Optional Tenant Filters" test suite comprehensively validates the new
enforcedWhereClausebehavior:
- Organization ID is always required
- Project and environment IDs can be selectively omitted for cross-project/environment queries
- Security guarantees are maintained even with partial filters
The helper function
getWhereClauseis a nice utility for precise testing of WHERE clause content.internal-packages/clickhouse/src/tsql.test.ts (2)
105-115: LGTM!The test correctly demonstrates the new
enforcedWhereClauseAPI pattern for tenant filtering. The structure is clear and consistent across all test cases.
506-798: LGTM!The "Optional Tenant Filter Tests" provide excellent coverage of the flexible tenant filtering capability:
- Cross-project queries (omitting
project_idandenvironment_id)- Cross-environment queries (omitting only
environment_id)- Organization isolation is always enforced
- OR clause bypass prevention with org-only filters
These integration tests validate that the security guarantees hold in practice against a real ClickHouse instance.
apps/webapp/app/components/primitives/charts/ChartLegendCompound.tsx (4)
20-22: LGTM!The new
scrollableprop is properly typed and documented with a clear JSDoc comment explaining its purpose.Also applies to: 42-43
134-140: LGTM!The conditional styling correctly applies
max-h-[50%]andmin-h-0when scrollable is enabled. Themin-h-0is essential for allowing flex children to shrink below their content size, enabling the scroll behavior.
159-216: LGTM!The legend items are now properly wrapped in a scrollable container. The structure correctly uses:
min-h-0to allow shrinkingflex-1to fill available spaceoverflow-y-autofor scrolling when content overflowsThe "View more" row is appropriately included inside the scrollable area.
155-158: Plugin is properly configured.The
tailwind-scrollbarplugin (v3.0.1) is installed inapps/webapp/package.jsonand required intailwind.config.js. The classesscrollbar-thin,scrollbar-track-transparent, andscrollbar-thumb-charcoal-600are standard utilities from the plugin using the custom charcoal color palette defined in the theme. No additional configuration is needed.internal-packages/tsql/src/query/printer.ts (6)
397-401: Good guard for JSON subfield hints tied to GROUP BY.Tracking and restoring
queryHasGroupBykeeps JSON type-hint behavior consistent across nested queries.Also applies to: 551-553
853-857: SELECT * expansion correctly prefers text columns for JSON fields.Nice addition that preserves user-facing names while using optimized storage.
1578-1604: Tenant column enforcement validation looks good.Clear error path when organization scoping is missing.
1606-1638: Date normalization for enforced conditions is straightforward and consistent.The UTC DateTime64 formatting path is clean and predictable.
2296-2307: Nice separation of WHERE comparison context.This makes the JSON hinting logic much easier to reason about.
2395-2468: dataPrefix utilities are clean and easy to follow.Nice encapsulation of prefix injection and alias cleanup.
internal-packages/tsql/src/index.test.ts (3)
12-74: Test schema setup for enforcedWhereClause is clear.Good fixtures for tenant/non-tenant scenarios.
167-243: Fallback tests updated cleanly forWhereClauseCondition.Nice alignment with the new condition type.
516-828: Nice coverage for enforcedWhereClause validation and interactions.The validation, operator, and fallback-interaction cases are thorough.
internal-packages/tsql/src/query/printer.test.ts (4)
83-94: Consistent enforcedWhereClause wiring across test contexts.Good to see uniform setup across helpers and inline contexts.
Also applies to: 155-164, 221-229, 248-258, 483-491, 1150-1157, 1469-1477, 1587-1595, 1813-1821, 2056-2064, 2202-2210, 2615-2621, 2633-2639, 2771-2784, 2899-2908, 2913-2920, 3086-3093
611-663: Great coverage for JSON subfield.:Stringbehavior.These cases pin down SELECT/GROUP BY vs WHERE differences well.
666-855: Text-column optimization tests look thorough.Covers SELECT, WHERE, and edge cases nicely.
857-1007: dataPrefix tests cover key SELECT/WHERE/GROUP BY cases.Good coverage of aliasing and nested-path behavior.
internal-packages/tsql/src/query/printer_context.ts (4)
95-118: EnforcedWhereClause storage on context is clear and well-documented.Nice to see the enforcement intent baked into the context.
193-199: Child context correctly inherits enforcedWhereClause.This keeps enforcement consistent across subqueries.
219-243: PrinterContextOptions docs for enforcedWhereClause are clear.The example is helpful for callers.
249-255: createPrinterContext wiring looks good.Clean handoff of enforcedWhereClause into the context.
internal-packages/clickhouse/src/client/tsql.ts (1)
5-5: Enforced WHERE clause propagation is consistent.Docs/examples, type re-exports, and compile-time wiring all align with the new enforcedWhereClause path.
Also applies to: 17-28, 139-175, 294-305
apps/webapp/app/services/queryService.server.ts (1)
89-95: QueryId propagation + dedupe reuse looks good.Returning queryId and reusing lastQuery.id avoids duplicate history entries and gives callers a stable reference.
Also applies to: 169-217
internal-packages/tsql/src/index.ts (3)
26-32: Centralized re-exports for WhereClauseCondition are clear.Exposing the condition types from the index makes the public API easier to consume.
Also applies to: 117-128
316-367: Fallback helpers updated cleanly to WhereClauseCondition.The type updates for fallback ops and injection stay consistent with the new condition model.
Also applies to: 377-413
542-565: Filtering undefined enforcedWhereClause before printer context is a good guard.Helps avoid accidental empty guards propagating into the printer.
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsx (7)
1-73: Import updates align with the new query UX features.
165-180: Plan-aware default period is a nice touch.It keeps the initial query window within plan limits while preserving the 7‑day ideal.
282-327: Retention clipping uses the right “from” basis.Using requestedFromDate (and not the “to” date) to decide periodClipped matches retention semantics and keeps the enforcedWhereClause consistent.
Based on learnings, "In apps/webapp/app/components/runs/v3/SharedFilters.tsx, the maxPeriodDays limit for date ranges should only check the from date (via dateRangeToDays(fromValue)) because it enforces data retention limits—how far back in history queries can reach. The to date is irrelevant for retention-based limits."
413-557: TimeFilter defaults + title callbacks are wired cleanly.defaultPeriod, maxPeriodDays, and the new submit/history callbacks integrate smoothly with the form state.
603-640: Title generation is gated well to new query results.The shouldGenerateTitle + historyTitle checks prevent unnecessary regeneration and keep history titles authoritative.
Also applies to: 684-694
812-842: Results callouts provide clear feedback.Hidden column and period‑limit messaging are concise and actionable.
Also applies to: 988-1033
1035-1093: Chart title loading state and scrollable legend look good.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
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
🤖 Fix all issues with AI agents
In `@internal-packages/tsql/src/query/printer.ts`:
- Around line 1880-1893: getTextColumnForExpression currently returns an
unqualified column name which causes ambiguity in JOINs; update the code that
computes leftTextColumn (used in the left variable) to detect a qualified field
by inspecting node.left.chain and, when an alias/table is present, prepend that
alias to the text column (e.g., alias + "." + textColumn) following the same
pattern used in resolveFieldChainWithTableAlias()/visitField(); ensure you still
call printIdentifier on the fully qualified identifier and fall back to the
existing unqualified behavior when no alias exists.
🧹 Nitpick comments (3)
internal-packages/tsql/src/query/printer.ts (2)
1590-1604: Validation only checksorganizationId- consider documenting this intentional design.The
validateRequiredTenantColumnsmethod only validatesorganizationIdand explicitly comments thatprojectIdandenvironmentIdare optional. This aligns with the test suite's "Optional Tenant Filters" tests.However, if a table defines
tenantColumns.projectIdbut the caller provides onlyorganization_idinenforcedWhereClause, no validation error occurs. This is likely intentional for flexibility, but consider adding a brief JSDoc note explaining why onlyorganizationIdis mandatory for tenant isolation.
2463-2480:buildAliasWithoutDataPrefixcould match unintended parts.The method removes the first occurrence of
dataPrefixfrom the parts array usingindexOfandsplice. If a user has a JSON field path likeoutput.data.data.messagewheredataappears twice, this would only remove the firstdata, resulting inoutput_data_messageinstead ofoutput_message.This is likely the intended behavior since
dataPrefixshould only be injected once, but the edge case where user data naturally contains the prefix string could lead to unexpected alias names.Consider documenting this behavior or using a more targeted removal
private buildAliasWithoutDataPrefix( chain: Array<string | number>, dataPrefix: string | null ): string { // Filter to just string parts and join with underscores const parts = chain.filter((p): p is string => typeof p === "string"); if (dataPrefix) { - // Remove the dataPrefix from the parts (it's an implementation detail) + // Remove the first occurrence of dataPrefix from the parts (it's an implementation detail) + // Note: If user data contains a field named the same as dataPrefix, the alias may differ from expectations const prefixIndex = parts.indexOf(dataPrefix); if (prefixIndex > 0) { // Only remove if it's not the first element (column name) parts.splice(prefixIndex, 1); } } return parts.join("_"); }internal-packages/tsql/src/query/security.test.ts (1)
668-679: Regex pattern could be more precise for alias extraction.The pattern
/(\w+)\.organization_id/gcaptures any word character before.organization_id. This works for simple aliases likerande, but could potentially match unexpected patterns in complex SQL.Consider a more targeted assertion that explicitly checks the WHERE clause structure.
Minor: More explicit assertion
// Count organization_id occurrences with different table prefixes // This ensures each table gets its own guard, not shared/ambiguous references - const orgIdPattern = /(\w+)\.organization_id/g; + const orgIdPattern = /\b(\w+)\.`?organization_id`?/g; const matches = [...sql.matchAll(orgIdPattern)]; const tableAliases = matches.map(m => m[1]); // Should have at least 2 different table aliases for organization_id // (one for task_runs alias 'r' and one for task_events alias 'e') expect(tableAliases).toContain("r"); expect(tableAliases).toContain("e"); + + // Verify we have exactly 2 distinct aliases (no duplicates or unexpected matches) + const uniqueAliases = new Set(tableAliases); + expect(uniqueAliases.size).toBe(2);
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsxinternal-packages/tsql/src/query/printer.tsinternal-packages/tsql/src/query/security.test.ts
🧰 Additional context used
📓 Path-based instructions (10)
**/*.{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.tsxinternal-packages/tsql/src/query/security.test.tsinternal-packages/tsql/src/query/printer.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.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.tsxinternal-packages/tsql/src/query/security.test.tsinternal-packages/tsql/src/query/printer.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.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.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.tsxinternal-packages/tsql/src/query/security.test.tsinternal-packages/tsql/src/query/printer.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.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/security.test.tsinternal-packages/tsql/src/query/printer.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.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.ts
🧠 Learnings (3)
📚 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.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/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.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
🧬 Code graph analysis (2)
apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsx (6)
apps/webapp/app/services/session.server.ts (1)
requireUserId(25-35)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)
internal-packages/tsql/src/query/security.test.ts (1)
internal-packages/tsql/src/grammar/TSQLParser.ts (2)
whereClause(2216-2241)whereClause(8485-8487)
⏰ 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). (7)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 8)
- GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
- GitHub Check: typecheck / typecheck
🔇 Additional comments (15)
apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsx (5)
1-11: LGTM!Imports are well-organized and follow coding guidelines:
@trigger.dev/core/utilsuses subpath import, and environment variables are accessed via theenvexport from~/env.server.
13-34: LGTM!Good use of Zod for request validation. The
tryCatchwrapper aroundrequest.json()properly handles malformed JSON requests, returning a 400 status instead of an unhandled exception.
36-50: LGTM!Proper authorization chain:
findProjectBySlugverifies the user belongs to the organization, andfindEnvironmentBySlugscopes the environment to the authenticated project and user.
52-70: LGTM!Good defensive check for the OpenAI API key at the route level. The configurable model via
env.AI_RUN_FILTER_MODELwith a sensible default is a nice pattern. The quote-stripping regex handles the common AI behavior of adding spurious quotes.
80-81: LGTM!Consistent response structure across success and error cases.
internal-packages/tsql/src/query/printer.ts (7)
117-118: LGTM! GROUP BY context tracking is correctly scoped.The
queryHasGroupByflag is properly saved before processing, set based on the presence ofgroup_by, and restored after query processing completes. This ensures nested queries don't pollute the parent's GROUP BY state.Also applies to: 397-400, 553-553
1672-1702: LGTM! Table-qualified guard expressions address the past review concern.The
createConditionExpressionmethod now accepts an optionaltableAliasparameter and constructs the field chain as[tableAlias, column]when provided. This ensures guards bind to the correct table in multi-join queries, addressing the previously identified security concern.
1721-1774: LGTM! Enforced guard creation with proper table qualification.The
createEnforcedGuardmethod correctly:
- Builds a set of valid columns from both exposed and tenant columns
- Passes
tableAliastocreateConditionExpressionfor all guards- Qualifies required filter guards with
[tableAlias, filter.column]- Returns
nullwhen no guards apply, avoiding unnecessary AND wrappersThis addresses the past review concerns about ambiguous column resolution in multi-table JOINs.
2256-2284: LGTM! Data prefix injection and GROUP BY-aware type hints.The logic correctly:
- Injects
dataPrefixinto field chains for JSON subfield access- Only adds
.:Stringtype hints whenqueryHasGroupByis true AND not in a WHERE comparison context- This avoids the issue where
.:Stringreturns NULL in non-GROUP BY queriesThe
isInWhereComparisonContextmethod properly distinguishes fromisInComparisonContextby excluding GROUP BY context.
2371-2396: Text column resolution handles qualified references correctly.The
getTextColumnForFieldmethod properly distinguishes between:
- Unqualified
column(chain length 1)- Qualified
table.column(chain length 2 with table alias)- JSON path access
column.subfieldortable.column.subfield(returns null)This ensures text column substitution only happens for bare JSON field references, not subfield access.
2438-2456: Potential off-by-one ininjectDataPrefixfor qualified references.For a qualified reference like
[table, column, subfield], the method correctly insertsdataPrefixat position 2:[table, column, dataPrefix, subfield]However, consider this edge case: if
chain.length === 3and the first part is a table alias, butgetDataPrefixForFieldreturns non-null, the slicing at line 2450 (chain.slice(2)) would only include the subfield. This appears correct.But for unqualified
[column, subfield], line 2455 doeschain.slice(1)which includes[subfield]. This also appears correct:[column, dataPrefix, subfield].The logic looks sound.
2707-2730: LGTM! Tenant and required filter columns are now resolvable.The
resolveColumnNamemethod now correctly handles:
- Tenant columns (
organizationId,projectId,environmentId) fromtableSchema.tenantColumns- Required filter columns from
tableSchema.requiredFiltersThese columns are returned as-is since they're already ClickHouse column names, which is correct behavior for the enforced guard system.
internal-packages/tsql/src/query/security.test.ts (3)
55-62: LGTM! Default options correctly migrated toenforcedWhereClause.The migration from direct tenant ID fields to the structured
enforcedWhereClausewith{ op: "eq", value: ... }format is correct and aligns with the new enforcement mechanism.
593-680: Excellent test coverage for multi-join tenant guard qualification.The new test suite comprehensively verifies the security fix:
- Basic JOIN with qualified guards (
r.organization_id,e.organization_id)- LEFT JOIN scenarios
- Multi-way JOINs with three table aliases
- Verification that guards bind to correct tables via distinct alias matching
The regex patterns like
/\br\b[^,]*organization_id/effectively verify that guards are prefixed with the correct table alias.
417-432: Tests correctly verify optional tenant filter behavior.The test structure properly validates that:
- Only
organization_idappears in WHERE when project/env are omitted- The enforced guard mechanism respects optional fields
- Partial provisioning works as expected
This aligns with the
validateRequiredTenantColumnslogic that only mandatesorganizationId.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
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.
...tes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsx
Show resolved
Hide resolved
...tes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsx
Show resolved
Hide resolved
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.
.../app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsx
Show resolved
Hide resolved
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)
internal-packages/tsql/src/query/printer.ts (1)
639-705: Preserve table qualification when substituting text columns in SELECT.
When a user writesr.output(oroutput AS alias) in a JOIN, the substitution emitsoutput_textwithout the table qualifier, which can be ambiguous or bind to the wrong table. This drops the user’s explicit qualification.🛠️ Suggested fix
- sqlResult = `${this.printIdentifier(textColumn)} AS ${this.printIdentifier(outputName)}`; + const textColumnRef = + field.chain.length >= 2 && + typeof field.chain[0] === "string" && + this.tableContexts.has(field.chain[0]) + ? `${this.printIdentifier(field.chain[0])}.${this.printIdentifier(textColumn)}` + : this.printIdentifier(textColumn); + sqlResult = `${textColumnRef} AS ${this.printIdentifier(outputName)}`; @@ - sqlResult = `${this.printIdentifier(textColumn)} AS ${this.printIdentifier(alias.alias)}`; + const textColumnRef = + innerField.chain.length >= 2 && + typeof innerField.chain[0] === "string" && + this.tableContexts.has(innerField.chain[0]) + ? `${this.printIdentifier(innerField.chain[0])}.${this.printIdentifier(textColumn)}` + : this.printIdentifier(textColumn); + sqlResult = `${textColumnRef} AS ${this.printIdentifier(alias.alias)}`;- sqlResult = `${this.printIdentifier(columnSchema.textColumn)} AS ${this.printIdentifier( - columnName - )}`; + sqlResult = `${this.printIdentifier(tableAlias)}.${this.printIdentifier( + columnSchema.textColumn + )} AS ${this.printIdentifier(columnName)}`;Also applies to: 853-857
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
internal-packages/tsql/src/query/printer.test.tsinternal-packages/tsql/src/query/printer.ts
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{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:
internal-packages/tsql/src/query/printer.tsinternal-packages/tsql/src/query/printer.test.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:
internal-packages/tsql/src/query/printer.tsinternal-packages/tsql/src/query/printer.test.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/printer.test.ts
**/*.{js,ts,jsx,tsx,json,md,yaml,yml}
📄 CodeRabbit inference engine (AGENTS.md)
Format code using Prettier before committing
Files:
internal-packages/tsql/src/query/printer.tsinternal-packages/tsql/src/query/printer.test.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/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/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/query/printer.test.ts
🧬 Code graph analysis (1)
internal-packages/tsql/src/query/printer.test.ts (3)
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/tsql/src/query/schema.ts (3)
TableSchema(321-339)column(354-366)createSchemaRegistry(371-387)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (12)
- GitHub Check: 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 (5, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8)
- GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 8)
- GitHub Check: typecheck / typecheck
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
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.
| // If a queryId was provided, update the CustomerQuery record with the title | ||
| if (queryId) { | ||
| await prisma.customerQuery.update({ | ||
| where: { id: queryId, organizationId: project.organizationId }, | ||
| 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.
🔴 AI title endpoint allows any org member to overwrite titles of other users’ saved queries by passing arbitrary queryId
The /resources/.../query/ai-title action updates CustomerQuery.title based only on { id: queryId, organizationId }, without ensuring the CustomerQuery being updated belongs to the requesting user (or otherwise that the user is authorized to mutate that specific history entry).
Actual behavior: any authenticated org member who can obtain another query’s id (e.g. via shared logs, screenshots, leaked network payload, etc.) can POST { queryId: "..." } and overwrite its title.
Expected behavior: only the creator (or an admin role) should be able to mutate that query history record, or the endpoint should avoid taking a client-supplied queryId and instead derive the target record server-side.
Click to expand
The update query only scopes by org:
await prisma.customerQuery.update({
where: { id: queryId, organizationId: project.organizationId },
data: { title },
});apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query.ai-title.tsx:72-77
There is no check against userId, projectId, environmentId, or a role/permission check for mutating arbitrary history items.
Recommendation: Scope the update to the calling user (e.g. include userId in the where clause) or enforce an authorization policy (creator-only, or creator/admin). Alternatively, don’t accept queryId from the client: derive the CustomerQuery row to update from the just-executed query context on the server.
Was this helpful? React with 👍 or 👎 to provide feedback.
Summary
Changes