Skip to content

Commit ec562c0

Browse files
claude[bot]claude
andauthored
fix(webapp): remove unused Electric sync trace routes (#4400)
<!-- ccr-slack-attribution --> _Requested by **Eric Allam** · [Slack thread](https://triggerdotdev.slack.com/archives/C0AU83M3136/p1785222101937829?thread_ts=1785207509.304669&cid=C0AU83M3136)_ Removes two dead Remix routes and the helpers only they used. `app/routes/sync.traces.runs.$traceId.ts` (`/sync/traces/runs/:traceId`) and `app/routes/sync.traces.$traceId.ts` (`/sync/traces/:traceId`) were added with the original ElectricSQL run page and lost their only consumers when the dashboard hooks that called them were deleted. Nothing in the repo references either route today. Also removed, because the deleted routes were their only callers: - `OtelTraceIdSchema`, `RESERVED_ELECTRIC_SHAPE_PARAMS`, `TraceScope`, `buildElectricTraceWhereClause` from `app/v3/electricShape.server.ts` (the file stays — `UNSAFE_REALTIME_TAG_CHARS` / `sanitizeRealtimeTagForSql` / `sanitizeRealtimeTagsForSql` are still used by `realtime.v1.runs.ts` and `realtimeClient.server.ts`) - the loader-specific cases in `apps/webapp/test/spanTraceRoutes.replicaLag.test.ts` and `internal-packages/run-store/src/runOpsStore.routesSpanTraceReadView.replicaLag.test.ts` `app/utils/longPollingFetch.ts` is untouched — `realtimeClient.server.ts` still uses it. `runOpsStore.ts` / `PostgresRunStore.ts` are untouched too; the unrouted-lookup mechanism there is generic and stays. As a plain code fact: the run lookup these loaders performed keyed on `TaskRun.traceId` alone, which is not an index-backed query shape. That is noted only as context for why the code is not worth keeping around unused. ### Judgement call worth a maintainer's opinion The request was specifically about `/sync/traces/runs/:traceId`, the route that looks up a run by `traceId`. This PR **also** deletes its sibling `/sync/traces/:traceId`. The reasoning: - both routes came in with the same ElectricSQL run-page work - both lost their only consumers in the same later commit - neither has any caller anywhere in the repo - they share the same helper module, so keeping one means keeping the helpers half-used If you would rather keep the sibling, reverting just that one file deletion is easy and does not affect the rest of this PR — say the word and I will restore it along with the helpers it needs. ## ✅ Checklist - [x] I have followed every step in the [contributing guide](https://github.com/triggerdotdev/trigger.dev/blob/main/CONTRIBUTING.md) - [x] The PR title follows the convention. - [x] I ran and tested the code works --- ## Testing Verification run locally from the repo root: | Command | Result | | --- | --- | | `pnpm run format` | clean, no changes produced | | `pnpm run lint:fix` | clean | | `pnpm run lint` | pass (exit 0, no findings) | | `pnpm run typecheck --filter webapp` | pass | | `pnpm run typecheck --filter @internal/run-store` | pass | A ripgrep sweep for `sync.traces`, `sync/traces`, `syncTraceRunsLoader`, `buildElectricTraceWhereClause`, `OtelTraceIdSchema` and `RESERVED_ELECTRIC_SHAPE_PARAMS` (excluding `node_modules`) returns zero hits. **Not fully verified:** both edited test files are testcontainers suites and need a Docker runtime, which was not available in my environment. I confirmed each file *collects* correctly with exactly the three intended remaining tests and no import errors — notably, dropping the `session.server` / `controlPlaneResolver.server` / `longPollingFetch` / `env.server` mocks does not break module loading for the surviving loaders. The assertions themselves then failed only on `Could not find a working container runtime strategy`. CI should be the real signal here. Per `apps/webapp/CLAUDE.md`, `pnpm run build --filter webapp` was deliberately not run. --- ## Changelog Removed two unused sync routes left over from the original ElectricSQL run page, along with the helpers and tests that existed only to serve them. No behaviour change — neither route had any caller. --- ## Screenshots _n/a — no user-visible surface changes._ 💯 --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 3ed4851 commit ec562c0

6 files changed

Lines changed: 14 additions & 422 deletions

File tree

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
area: webapp
3+
type: fix
4+
---
5+
6+
Removed an unused internal dashboard sync route that is no longer part of any product surface.

apps/webapp/app/routes/sync.traces.$traceId.ts

Lines changed: 0 additions & 95 deletions
This file was deleted.

apps/webapp/app/routes/sync.traces.runs.$traceId.ts

Lines changed: 0 additions & 117 deletions
This file was deleted.

apps/webapp/app/v3/electricShape.server.ts

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,3 @@
1-
import { z } from "zod";
2-
3-
/**
4-
* OTel trace IDs are 32 lowercase hex chars. The traceparent parser only
5-
* checks the dash-delimited format, so crafted ids can be persisted and later
6-
* interpolated into shape `where` clauses. Validate here to close the SQLi vector.
7-
*/
8-
export const OtelTraceIdSchema = z
9-
.string()
10-
.regex(/^[0-9a-f]{32}$/, "traceId must be 32 lowercase hex characters");
11-
12-
/** Params the sync routes set themselves; stripped from incoming requests. */
13-
export const RESERVED_ELECTRIC_SHAPE_PARAMS = new Set(["where", "table", "columns"]);
14-
15-
const CUID_LIKE = /^[a-z][a-z0-9_]*$/i;
16-
17-
/**
18-
* Tenant column a trace shape is scoped by. TaskEvent scopes by non-null
19-
* organizationId; TaskRun scopes by non-null projectId (its organizationId is
20-
* nullable). The column is from this fixed union, never user input, so it's
21-
* safe to interpolate.
22-
*/
23-
export type TraceScope =
24-
| { column: "organizationId"; id: string }
25-
| { column: "projectId"; id: string };
26-
27-
/**
28-
* Build the Electric Shape `where` clause for the trace sync routes. Both ids
29-
* are re-validated as defense-in-depth so a missed call site can't bypass scope.
30-
*/
31-
export function buildElectricTraceWhereClause(args: {
32-
traceId: string;
33-
scope: TraceScope;
34-
}): string {
35-
const { traceId, scope } = args;
36-
if (!OtelTraceIdSchema.safeParse(traceId).success) {
37-
throw new Error("buildElectricTraceWhereClause: unsafe traceId");
38-
}
39-
if (!CUID_LIKE.test(scope.id)) {
40-
throw new Error("buildElectricTraceWhereClause: unsafe scope id");
41-
}
42-
return `"traceId"='${traceId}' AND "${scope.column}"='${scope.id}'`;
43-
}
44-
451
/**
462
* Characters rejected in realtime tag values — the single source of truth
473
* shared by the apiBuilder Zod refine (`realtime.v1.runs.ts`) and the runtime

0 commit comments

Comments
 (0)