← All tasks

Followups bundle (R1/R2/H4-X polish) PROD · GATE 2

Live on prod 2026-05-20. Three small unblocked carry-overs from the recent slices bundled into one Gate cycle. Each fixes a tracked caveat or footgun guard. No backend migration, no new deps.

12/12 prod · 51/51 regression = 63/63 total green. 1 commit (0ccb15b) with three independent items. Item 2 (pgView guard) caught a real regression in the Lumière demo seed script during the conversion — refactored in the same commit. Test-side fix mid-Gate-2: variant-row testids are name-suffixed, not plain — used prefix matcher.

Prod test — 12/12

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

1. /cafe/reports w/ RankingPost-conversion render — no 5xx, Ranking section visible
2. /cafe/settings/attributesTemplate list — Attributes admin page renders
3. Variant edit modal opensNow has Image URL field below price
4. URL pasted → preview rendersLive preview below input when http(s) URL is valid
5. After save (modal closed)Optimistic update propagated, no 5xx
6. Re-opened — DB round-trip verifiedSaved URL appears in the field on re-open
7. Starter (lumiere-coffee) /cafe/reportsSame shell renders post-conversion

Mid-Gate-2 test-side fix

First prod run failed 5/12 — the variant-row interaction tests couldn't find any variant row to click. Root cause: template-card testids on prod are name-suffixed (template-toggle-${"${"}name${"}"}, template-variant-row-${"${"}defaultCode${"}"}), but my test used plain prefix-only locators (data-testid="template-toggle" exactly). Fix: switched to prefix matchers ([data-testid^="template-toggle-"]). After fix: 12/12. No code change in nix-cafe — just test scaffolding.

What this bundle closes

Item 1 — Multi-shop Ranking of POSaggregateRevenueByPosConfig now accepts shopIds: string[] | string | null. R1's "Ranking only filters when 0/1 shop selected" caveat is gone. Dashboard + daily callers still pass single strings (back-compat).

Item 2 — cafeProducts pgTablepgView — INSERT/UPDATE/DELETE against the view are now compile-time TS errors. The conversion caught a stale db.insert(schema.cafeProducts) in the Lumière demo seed script that H4-X had missed; refactored to call createProduct(…) (the H4-X DAO). Three nested-projection callsites in lib/db/products.ts use a shared PRODUCT_VIEW_COLS column object. cafeOrderLines.productId FK ref retargeted to cafeProductProduct.id for typing accuracy.

Item 3 — Per-variant image edit fieldVariantEditModal at /cafe/settings/attributes now exposes imageUrl + live preview. Threaded through TemplateVariantRow + DAO row builder + onSaved patch + optimistic update. Action + DAO already supported imageUrl from H4-X — pure UI gap close, verified round-trip on prod (set + save + re-open shows saved value).