Súhrnný balík opráv — category-mapping rule-filter hardening, ERP/loyalty/SSR fixy, PR #39 hardening loop
· Infraštruktúra
Komplexný balík opráv naprieč produktom, ktorý uzatvára niekoľko tried chybových stavov. (1) Category-mapping rule-filter hardening (5e5b74ff) — defense-in-depth na product-filter feature: DTO bounds (attribute MaxLength(200), value MaxLength(500), priceRange Max(1B), 16KB serialized cap proti parameter-bomb shapes), DB CHECK constraint v migrácii 347 odmieta literálny {} product_filter (ktorý by tiché matchol každý produkt na apply), service-layer guards v category-mapping.service (sanitizeProductFilter strip-uje prezentačné kľúče ako search/status pred persistom; apply-time empty-filter guard), 818 riadkov nového spec coverage. UI guards v CreateMappingRuleDialog + MappingRulesDialog. (2) PR #39 hardening loop final pass (ff30e323) — race fixy v paralelných translation pipeline-och, defense-in-depth na boundaries, UX fixy. (3) isNew badge SSR hydration mismatch (f4a98b60) — výpočet isNew badgu sa robil server-side cez Date.now() čo spôsobovalo „Hydration failed" warning v Next.js (server timestamp ≠ client timestamp). Presunuté do client-only effect-u, žiadny SSR mismatch. (4) ERP — skip neaktívnych variantov pri picking Grandus product price anchor (20026d44) — Grandus push provider vyberal cenu z prvého variantu produktu, ale ak bol prvý variant deaktivovaný (sale skončil), Grandus dostal cenu nedostupného variantu. Teraz preskočíme inactive varianty a vyberieme prvý active. (5) Loyalty credit systems fix (0ff849c0, mig 334) — niekoľko race-conditions v loyalty subsystéme: reverseCreditsForOrder ledger findOne presunutý do existujúcej tx (zatvorený revenue leak: cancelled-order credity nikdy nereversnuté), processPendingAwards per-row PENDING→AWARDED flip wrappnutý (zatvorený unbounded queue growth), redeemForCoupon tier lookup presunutý do tx (zatvorené „Reward tier not found" 404 na každom storefront redemption attempte), createPendingAward find+save bundled do jednej tx (zatvorený duplicate-INSERT 23505 na webhook retry). (6) Vendor duplicates 4-round hardening (1320c982 → 2b98c244) — round 1: URL sync + page-0 race + composite indexes; round 2: invalid-index recovery, throttle, sort mutation, search-input clobber; round 3: URL whitelists, Reset URL clear, drop legacy indexes; round 4: KNOWN_STATUSES.linked, i18n Manual, isError UI, date range guard, undoMerge step-2 companyId. Plus URL-parsing utility extraction + 80 nových testov pre round 3-4. (7) Apply_category_mappings step scope (554dfdc3) — flow akcia apply_category_mappings pre per-product flow predtým aplikovala pravidlá na celý katalóg namiesto na current product (cross-product leak); teraz scope-uje len na current product. (8) 5-bug fix v category-mapping/templates (7e18bf9e) — chips renderovanie, template-import fixy, apply-rule UI, new-tab open behavior, modal-scroll lock — 28-iter production hardening loop. (9) CI/migrations/RLS isolation workflow unblock (73ab6603) — PR-level CI bol zablokovaný neúspešným RLS isolation workflow; opravené migrácie aby workflow prebehol; CI gate funkčný. (10) resolve_storefront_by_host() return-type signature (ee70cb51, mig 333) — funkcia mala nesprávnu signatúru po predchádzajúcom rewrite; opravené aby NestJS DataSource ju mohol invokovať. (11) CI lint failures pre PR #39 (5481a473, 0070c971, 8ca678b5) — tri vlny prettier + eslint cleanu; storefront types revert (Record<string, any> rozbil PaymentSection/ShippingSection TS). (12) Pre-existing go vet IPv6 warnings + macOS test bug (771c7761) — staršie go vet warningy zatvorené; macOS-specific test bug v processoroch fixnutý.