Skip to content

Commit e7fb6bd

Browse files
committed
fix(run-store): drop force-injected id from findRunsByIds results when unrequested
findRunsByIds forces `id` into the select so it can key the result map, but did not remove it afterwards, so returned rows carried an `id` the declared payload type did not include. Delete the injected id from each value when the caller's select did not request it; the map stays keyed by id.
1 parent c642427 commit e7fb6bd

4 files changed

Lines changed: 26 additions & 3 deletions

File tree

internal-packages/run-store/src/PostgresRunStore.findRunsByIds.test.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,11 @@ describe("PostgresRunStore.findRunsByIds", () => {
162162
expect(byId.get(runId2)?.friendlyId).toBe("run_findbyids_2_friendly");
163163
expect(byId.get(runId2)?.status).toBe("PENDING");
164164

165+
// The select omitted `id`; the id we force-inject for keying must not leak into the value
166+
// (it would otherwise violate the declared payload type and expose an unrequested id).
167+
expect("id" in (byId.get(runId1) as object)).toBe(false);
168+
expect("id" in (byId.get(runId2) as object)).toBe(false);
169+
165170
// GROUPED: one findMany for the WHOLE batch, never one findFirst per id.
166171
expect(counting.counts.taskRun.findMany).toBe(1);
167172
expect(counting.counts.taskRun.findFirst).toBe(0);

internal-packages/run-store/src/PostgresRunStore.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1540,8 +1540,15 @@ export class PostgresRunStore implements RunStore {
15401540
client
15411541
)) as Record<string, unknown>[];
15421542
const byId = new Map<string, unknown>();
1543+
// Strip the id we force-injected for map keying when the caller's select did not ask for it,
1544+
// so returned values match the declared payload type and never leak an unrequested id.
1545+
const stripInjectedId = args?.select != null && !("id" in args.select);
15431546
for (const row of rows) {
1544-
byId.set(row.id as string, row);
1547+
const key = row.id as string;
1548+
if (stripInjectedId) {
1549+
delete row.id;
1550+
}
1551+
byId.set(key, row);
15451552
}
15461553
return byId;
15471554
}

internal-packages/run-store/src/runOpsStore.groupedReads.test.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ describe("RoutingRunStore.findRunsByIds — grouped, residency-partitioned read
178178
newCounting.counts.findFirst = 0;
179179

180180
const result = await router.findRunsByIds(allIds, {
181-
select: { id: true, friendlyId: true },
181+
select: { friendlyId: true },
182182
});
183183

184184
// All N rows returned, keyed by id.
@@ -189,6 +189,10 @@ describe("RoutingRunStore.findRunsByIds — grouped, residency-partitioned read
189189
expect(result.get(legacyIds[0])?.friendlyId).toBe("run_grp_leg_0");
190190
expect(result.get(newIds[0])?.friendlyId).toBe("run_grp_new_0");
191191

192+
// The select omitted `id`; the id we force-inject for keying must not leak into the value.
193+
expect("id" in (result.get(legacyIds[0]) as object)).toBe(false);
194+
expect("id" in (result.get(newIds[0]) as object)).toBe(false);
195+
192196
// GROUPED: exactly one findMany call per store queried (NEW always queried for the whole
193197
// set; LEGACY queried once more for the misses) — never N per-id findFirst calls.
194198
expect(newCounting.counts.findMany).toBe(1);

internal-packages/run-store/src/runOpsStore.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,8 +419,15 @@ export class RoutingRunStore implements RunStore {
419419
client
420420
)) as Record<string, unknown>[];
421421
const byId = new Map<string, unknown>();
422+
// Strip the id we force-injected for map keying when the caller's select did not ask for it,
423+
// so returned values match the declared payload type and never leak an unrequested id.
424+
const stripInjectedId = args?.select != null && !("id" in (args.select as object));
422425
for (const row of rows) {
423-
byId.set(row.id as string, row);
426+
const key = row.id as string;
427+
if (stripInjectedId) {
428+
delete row.id;
429+
}
430+
byId.set(key, row);
424431
}
425432
return byId;
426433
}

0 commit comments

Comments
 (0)