← all branches

fix/split-uuid

safe
5492f0a · fullPR #285reviewed 2026-07-09 01:43 UTC0H · 0M · 1L · 3I
The branch
Purpose
One-shot data remediation: split sites incorrectly merged (same RPU assigned to multiple site records), creating separate site records per contract.
Goal
Fix the postgres.js driver-level bug caught during staging rehearsal so the prod remediation run succeeds
Sub-goals
  • SG-1: Add ::uuid casts to all sql`` parameter bindings that land in uuid-typed columns
  • SG-2: Preserve all existing split logic (site INSERT, location copy, assignee copy, contract repoint)
The changes (whole branch)
What
Added ::uuid casts to 8 parameter bindings in splitSite(): FOR UPDATE SELECT, site INSERT (RETURNING-derived newSiteId), site_locations INSERT (×4), site_assignees INSERT, UPDATE site_utility_contracts. Added explanatory comment on driver-level cause.
Why
postgres.js binds JS strings as text; Postgres rejects text in uuid assignment position. First staging run failed 8/8 — clean rollbacks (correct failure mode), requiring this fix before prod.
Areas
scripts/split-merged-sites.ts+1410
Blast
1 file, +14/−10 lines. One-shot script only — no production code, no schema changes, no API surface.
one-shot-script staging-validated prod-ready
ci· CI rollup not accessible via current token — verify manuallycoderabbit· No .coderabbit.yaml presentstaging-rehearsal· 8/8 sites split on staging, locations+assignees copied, read-model converged, self-verify OK

Findings · 4

conventions1

info

Comment placement is one statement early — appears before step 2 but first cast is in step 1

scripts/split-merged-sites.ts:223

The NOTE explaining ::uuid cast rationale is placed before site_locations INSERT (step 2) but the first cast appears in the site INSERT immediately above. Minor discoverability issue.

improvement3

low

Explanatory comment only covers step 2; steps 1/3/4 have unadorned ::uuid casts

scripts/split-merged-sites.ts:223

Moving the comment before step 1 or to the top of the transaction block would make the pattern self-documenting throughout.

info

Uncast ${ORG_FILTER}/${SITE_FILTER} are intentional (text columns) — worth a note for future auditors

scripts/split-merged-sites.ts:170

A maintainer auditing for ::uuid casts and adding one here would break the filter. A brief inline note prevents an incorrect future 'fix'.

info

Broader audit: other scripts using sql`` with uuid-typed bindings may share this issue

The postgres.js text-vs-uuid problem applies to any script using Drizzle sql`` with uuid-typed columns. A grep for sql`` + ${...} in scripts/ would surface candidates.