← All tasks

Followups bundle #2 — default_code uniqueness + CSV exports PROD · GATE 2

Live on prod 2026-05-20. Two more carry-overs from the Reports arc. Backend migration + nix-cafe action + UI all shipped + verified on prod data.

10/10 prod · 51/51 regression = 61/61 total green. Backend 13fc0e0 (migration) + 35b26d7 (view-aware fixes to older migrate.js entries) + nix-cafe c33f269. Prod migration applied via node migrate.js directly; H4-X view-ification surfaced 4 pre-existing cafe.products ALTER/INDEX/UPDATE migrations that needed view-awareness on re-run — patched all of them in a single follow-up commit. Without the pgView guard from yesterday, these wouldn't have surfaced until the next prod migrate.js run.

Prod test — 10/10

Variant modal dup-error — verified via DB probe, not browser flow on prod. The browser flow looks for a template with ≥2 variants that both have non-NULL default_codes. get-coffee's seeded data on prod doesn't currently have any such template (most products are single-default or auto-V001/V002), so the browser-side dup-typing test executed but its "find eligible template" step returned empty and the test short-circuited as a pass without exercising the UI error. DB-level dup rejection IS verified on prod via a direct DAO INSERT of two same-default_code rows under the same template (rejected with 23505 on the new constraint, then cleaned up). The friendly error translation in updateVariantAction was exercised in the Gate 1 local pass, on the same code path. No prod-side UI screenshot — would need to seed eligible variants first.

51/51 regression green — no regressions from this push.
test-phase1-prod.mjs11/11
test-phase2-sso-outdoor-prod.mjs6/6
test-phase2-cafe-multishop-prod.mjs6/6
test-m1-prod.mjs10/10
test-r7-prod.mjs14/14
test-r8-prod.mjs4/4

Screenshots + CSV samples

1. /cafe/reports — Export CSV linkHeader now has the download link instead of cosmetic Export PDF/Excel
2. /cafe/reports/order-analysis — Export CSV linkSame shape; month querystring carries through
3. Starter — /cafe/reportsSame shell + Export link on lumiere-coffee
4. Starter — /cafe/reports/order-analysisSame shell + Export link

Actual CSV bodies captured from prod for reference: summary.csv · order-analysis.csv · dupe-probe.json

Mid-Gate-2 fix — view-aware migrate.js

First node migrate.js run against prod failed twice in cascade. Root cause: H4-X (2026-05-20 earlier) converted cafe.products from a real table to a Postgres view. Three pre-existing entries in migrate.js mutate cafe.products directly (R6.2a / R6.4 / R10 plural tables), and since migrate.js re-runs every entry on every invocation, they tried to ALTER TABLE cafe.products / CREATE INDEX ON cafe.products / CREATE TABLE … REFERENCES cafe.products(id) — all of which Postgres rejects when the target is a view (relation kind 'v', not 'r').

Fixed in commit 35b26d7 by adding a one-shot relkind probe at the top of each affected migration and skipping the ALTER/INDEX block when the relation is a view. The R10 plural-tables migration preserves the surviving cafe.order_lines.variants ALTER (still relevant) but skips the rest of its DDL. Re-runs are now idempotent post-H4-X.

This is a class of issue: any future view-ification of a non-trivial table will need the same defensive guard on pre-existing migration entries. Worth a durable memo if it happens again.

What's now closed (from the followups list)

Still tracked (all need Narong spec or downstream model changes):