From a0a3ec32a3a0eb8a4f3d9728c0163a5c7294bc45 Mon Sep 17 00:00:00 2001 From: mAi Date: Mon, 18 May 2026 16:52:38 +0200 Subject: [PATCH] fix(mig 098): relax submission_code shape regex to allow digits in suffix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mig 098 (t-paliad-209, ohm) crash-looped paliad.de prod for ~2h: §6.1 assertion regex `^[a-z_]+\.[a-z_]+\.[a-z_]+\.[a-z_]+(\..*)?$` rejects EPA rule codes that carry the statutory rule number in the suffix — e.g. `epa.opp.boa.r106`, `epa.grant.exa.r71_3`, `epa.opp.opd.r116`, `epa.opp.opd.r79_further`, `epa.opp.boa.entsch2`, `epa.opp.boa.r116`. Migration's UPDATE step succeeds against these rows; the transactional assertion blows them up; rollback leaves the migration tracker dirty at version 98 and the container refuses to start. Patch: allow `[a-z_0-9]` per segment instead of `[a-z_]` in both the SQL assertion (mig 098 §6.1) and the matching Go shape regex (submission_codes_shape_test.go). Same change in both spots so the runtime sanity test stays aligned with the SQL invariant. Manual recovery already applied: forced `paliad.paliad_schema_migrations.version` back to 97 with `dirty=false` so the next deploy retries mig 098 from scratch against the patched file. No data state changed (mig 098 ran inside a transaction and fully rolled back — snapshot table, prefix UPDATE, and column rename all reverted). go build ./... clean. TestProceedingCodeShapeRegexStandalone green. --- .../098_submission_codes_prefix_and_rename.up.sql | 5 ++++- internal/services/submission_codes_shape_test.go | 14 ++++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/internal/db/migrations/098_submission_codes_prefix_and_rename.up.sql b/internal/db/migrations/098_submission_codes_prefix_and_rename.up.sql index 4894221..6980afe 100644 --- a/internal/db/migrations/098_submission_codes_prefix_and_rename.up.sql +++ b/internal/db/migrations/098_submission_codes_prefix_and_rename.up.sql @@ -226,11 +226,14 @@ BEGIN -- 6.1 Every active+published row has the proceeding-code-prefixed -- 4+-segment shape. Archived rows (`_archived_litigation` ones) -- keep their shorter shape by design — they're carved out. + -- Suffix segments may include digits (existing data — e.g. EPA rule + -- codes like `epa.opp.boa.r106` / `epa.grant.exa.r71_3` carry the + -- statutory rule number in the suffix). Allow [a-z_0-9] per segment. SELECT count(*) INTO v_bad_shape FROM paliad.deadline_rules WHERE is_active = true AND lifecycle_state = 'published' - AND submission_code !~ '^[a-z_]+\.[a-z_]+\.[a-z_]+\.[a-z_]+(\..*)?$'; + AND submission_code !~ '^[a-z_0-9]+\.[a-z_0-9]+\.[a-z_0-9]+\.[a-z_0-9]+(\..*)?$'; IF v_bad_shape <> 0 THEN RAISE EXCEPTION 'mig 098: expected every active+published deadline_rules row to match the 4+-segment submission_code shape, got % violators', diff --git a/internal/services/submission_codes_shape_test.go b/internal/services/submission_codes_shape_test.go index f5eeabf..d618bbb 100644 --- a/internal/services/submission_codes_shape_test.go +++ b/internal/services/submission_codes_shape_test.go @@ -14,13 +14,15 @@ import ( // submissionCodeShapeRegex is the proceeding-code-prefixed shape // installed by mig 098 (t-paliad-209): the proceeding's 3-segment code -// (`^[a-z_]+\.[a-z_]+\.[a-z_]+\.`) followed by at least one suffix -// segment (and optional further dot-separated segments). The regex -// allows underscores so the legacy archived bucket (`_archived_…`) and -// hand-seeded test rules (e.g. `s11a.initial`) match alongside the -// canonical taxonomy. Mirrors the assertion in mig 098 §6.1. +// (`^[a-z_0-9]+\.[a-z_0-9]+\.[a-z_0-9]+\.`) followed by at least one +// suffix segment (and optional further dot-separated segments). The +// regex allows digits so EPA suffixes like `r106` / `r71_3` / `r116` +// (statutory rule numbers in the suffix) pass alongside canonical +// dotted-word codes. Underscores cover the legacy archived bucket +// (`_archived_…`) and hand-seeded test rules. Mirrors the assertion in +// mig 098 §6.1. var submissionCodeShapeRegex = regexp.MustCompile( - `^[a-z_]+\.[a-z_]+\.[a-z_]+\.[a-z_]+(\..*)?$`) + `^[a-z_0-9]+\.[a-z_0-9]+\.[a-z_0-9]+\.[a-z_0-9]+(\..*)?$`) // TestSubmissionCodeShape walks every active+published row in // paliad.deadline_rules and asserts that submission_code matches the