Bloga Dönindustry2026-05-2413 dk okuma
Maliye müşaviri fişlerde tek vergi satırı gördü — tax_breakdown_json BEACON eksiği (PR #654 VIII F5)
Bursa Inegol Kale Cad da 52 yaslarinda "Inegol Koftecisi Bedri Usta" sahibi Bedri, 27 yillik kofteci. Iki gelir akimi: (1) hizmet bolumu kofte+piyaz+Turk lokmasi (KDV %10), (2) kasada retail urunler — kavanozlanmis Inegol koftesi+zeytinyagi+ev yapimi recel+paketli baklava (KDV %20). 18 ay once thMenu Pro tier + per-item tax_rate (PR #475 batch I) dogru girilmisti. Mayis ortasi Sali sabahi telefonu caldi: **"Bedri Bey, Bursa Maliye Mudurlugu Mufettis Erkan. Son 90 gun KDV beyannamesinde randomized cross-check yapiyoruz. 12 fis URL i SMS le gonderdim, mufettis gozuyle aciyorum."** Bedri ilk fisi (15 Nisan ₺646.59 mixed order) acti. Beklenen 2 KDV satiri (KDV %10 ₺29.09 + KDV %20 ₺42.50). Goruleni: **TEK satir KDV: ₺71.59**. 11 diger fis ayni. Erkan: "48 saat sure, full breakdown sunmazsan positive finding olarak yazarim." Engineering forensik 4 saatlik race: D1 query order_id ile — tax_breakdown_json kolonu doluydu, 2-rate JSON dogru sekilde. Sorun receipt route apps/web-menu/src/app/api/orders/[id]/receipt/route.ts: `try { breakdown = JSON.parse(...); if (!Array.isArray(breakdown.rates) || breakdown.rates.length === 0) breakdown = null; } catch (e) { console.error("Failed to parse tax_breakdown_json", {...}); breakdown = null; }`. 90-gunluk log grep "Failed to parse" → **0 entry**. Hata firing degildi. Engineering bir kez daha kod a baktilar dikkatlice: JSON.parse exception throw etmiyordu — JSON syntactically valid. Ama Array.isArray(breakdown.rates) FALSE donüyordu cunku breakdown.rates bazi rowlarda Object olarak serialize edilmisti (key i rate-string olan map yerine array). PR #475 initial migration bazi rowlari yanlis sekilde write etmis. Edge case path sessizce single-row variant fallback ediyordu — console.error de console.warn de yok, sadece null a dustu. Hicbir log entry. **PR #654 batch VIII F5** uc katmanli fix: **Layer 1 stable BEACON log prefix**: 3 ayri marker [BEACON:tax_breakdown_parse_rates_not_array] (Bedri scenario, wrong shape), [BEACON:tax_breakdown_parse_rates_empty] (zero-entry edge case, console.warn elevated to console.error), [BEACON:tax_breakdown_parse_exception] (truly malformed JSON). Her marker orderId + restaurantId + diagnostic field icerir. **Layer 2 Cloudflare Logpush + Sentry alert rule**: beacon prefix lerine alert pin; restaurant-level threshold > 5 occurrence / hour → PagerDuty incident → ops team page + proactive operator reach-out. **Layer 3 backfill batch**: tax_breakdown_json IS NOT NULL AND json_array_length(rates) IS NULL olan tum orderlar one-off backfill script (rates Object → Array conversion). ~847 order platform-wide etkilenmis, 18 restaurant a yayilmis, 30 dakikada duzeltildi. 8 saatte Bedri yeni 12 URL gonderdi, Erkan acti — 2 KDV satiri. "Cross-check gecti, vendor surum yapti, audit closed." Pattern: **operator-visible compliance failure path lari icin console.error alone yetmez — stable grep lenebilir [BEACON:event_name] prefix gerekli; log shipper / Sentry alert rule prefix e pin lenir; ops team ilk corrupt row dan dakikalar icinde page lenir.** Implementation checklist: (1) silent degradation kabul edilemez, her fallback branch BEACON emit eder; (2) BEACON prefix stable contract; (3) log shipper alert rule pin; (4) restaurant-level threshold PagerDuty; (5) backfill batch one-off script; (6) degradation tests (malformed JSON, empty array, wrong shape, null, undefined); (7) quarterly BEACON occurrence rate review. Marco Edinburgh Princes Street Trattoria HMRC VAT audit ayni flow.