Files
sp/behavioral-insight-pipeline-prd-1.md
Semih fc6a3f7a39 feat(phase6a-v1.2): dual-mode custom-event enrichment (v1.0 + v2.0 aliases)
- Prisma: posthog_person_cache (24h TTL), posthog_group_cache, session_custom_events
- SessionMeta: +posthogDistinctId, +groupKey, +customEventCount
- PostHog client: listSessionEvents, getPerson, getGroup
- posthog-cache.ts: cache-with-stale-refresh for person + group properties
- event-taxonomy.ts: dual-mode alias map (vin_decoded↔vin_decode_initiated,
  vin_decode_success↔vin_decode_succeeded, vin_decode_error↔vin_decode_failed,
  payment_success↔payment_succeeded). 56 tracked event names total.
- enrich.ts: per-session custom events fetch, persist to session_custom_events,
  attach user_properties + group_properties via cache.
- tagger.ts: 14 new custom-event tags
  (vin_decode_fail_pattern, provider_reliability_issue, payment_friction,
   payment_ui_silent_failure (P0), payment_failed_session, checkout_abandonment,
   downgrade_pending, compatibility_quality_gap, parts_export_abandoned,
   search_validation_friction, onboarding_stuck, upgrade_hesitation,
   power_user_path, at_risk_active_session, provider_mismatch,
   api_key_friction, webhook_setup_struggle); group-context priority bump.
- heuristic.ts: customEventPromoteReasons() — 10 custom-event promote signals.
- compress.ts: merge_rrweb_and_custom_events interleaving with ⤷ EVENT: prefix,
  ±1.5s grouping, standalone flush for events with no nearby rrweb. Adds
  company_context header line; key_events lists top-5 custom event counts.
- /insights page: +Events column. /insights/sessions/[id]: collapsible custom
  events table + group key display.

Graceful: when Sase.tr emits 0 custom events the pipeline falls back to
rrweb-only tagging from Phase 6a v1.1.

PRD: behavioral-insight-pipeline-prd-1.md (v1.2),
     sase-posthog-events-prd.md (Sase.tr-side, separate codebase).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-13 22:17:18 +00:00

120 KiB
Raw Blame History

Behavioral Insight Pipeline — Sase.tr Pilot

Proje Kodu: BIP-001 Ana Sistem: Süper Panel — Phase 6 Pilot Proje: Sase.tr Doküman Türü: Feature PRD (detaylı) Durum: Draft v1.2 Sahip: Founder (Thinxtra SaaS Studio) Domain İntegrasyonu: sp.semih.ai/insights

v1.1 değişiklikleri (2026-05-13):

  • Provider: DeepSeek V4 primary (Anthropic-compatible endpoint)
  • PostHog deployment: Cloud (EU region) doğrulandı
  • Maliyet planlaması yeniden yapıldı (aylık $30 cap, eski $300'den)
  • Cache stratejisi DeepSeek-native pricing'e optimize edildi
  • KVKK / Çin altyapısı için ek sanitization katmanı eklendi

v1.2 değişiklikleri (2026-05-13):

  • Sase.tr custom event taxonomy entegrasyonu (referans: sase-posthog-events-prd.md)
  • Bölüm 5.1.5 eklendi: Custom event stream pipeline entegrasyonu
  • Bölüm 7.5 timeline format güncellendi (custom event'lerle zenginleşmiş örnekler)
  • Bölüm 17 Faz planına "Faz 0: Sase.tr Event Prep" prerequisite eklendi
  • Group analytics ve cohort context'i tag detection'a (Bölüm 6.2) entegre edildi
  • ık sorulardan event taxonomi ile ilgili olanlar çözüldü

İçindekiler

  1. Vizyon ve Bağlam
  2. Hedefler ve Hedef Olmayanlar
  3. Pilot Kararı: Neden Sase.tr?
  4. Üst Düzey Mimari
  5. Katman 1: Ingestion & Heuristic Filter
  6. Katman 2: Signal Detection (Tagging)
  7. Katman 3: Semantic Compression
  8. Katman 4: LLM Analysis
  9. Maliyet Yönetimi (Cost Governance)
  10. Insight Storage & Triage
  11. Action Loop (Insight → Issue → Validation)
  12. UI / UX
  13. Veri Modeli
  14. Konfigürasyon Sistemi
  15. Privacy, KVKK ve Veri Güvenliği
  16. Observability ve Operations
  17. Faz Planı
  18. Riskler ve Azaltma
  19. Başarı Metrikleri
  20. ık Sorular

İlgili Dokümanlar

  • sase-posthog-events-prd.md — Sase.tr custom event taxonomy ve implementation rehberi. Phase 0 prerequisite (BIP Phase 6a'yı bloklar). Identification flow, group analytics, 30+ yeni event, data-private audit, KVKK uyumu, payment dual-capture stratejisi.

1. Vizyon ve Bağlam

Problem

Sase.tr B2B bir VIN lookup ve parça uyumluluk SaaS'ı. Solo founder olarak şu friction'lar var:

  • Sessiz kullanıcı problemi: B2B teknik kullanıcılar (yedek parçacılar) bug bulduklarında nadiren raporlar; onun yerine sessizce ayrılır veya alternative tool'lara döner
  • Onboarding görünmezliği: Yeni kayıt olan kullanıcının ilk 24 saatte ne yapmaya çalıştığı, nerede takıldığı görünmez
  • Feature gap'leri: Kullanıcının yapmaya çalışıp yapamadığı şey neyse — bunu öğrenmenin yapılandırılmış bir yolu yok
  • Çoklu provider karmaşası: PL24, PCAT, RMEX, TecDoc arası uyumsuzluklar kullanıcı tarafında nasıl yaşanıyor görünmez
  • Subscription tier friction: Starter → Full geçişi olmuyorsa neden olmuyor? Hangi feature'ın olmaması engelliyor?

Çözüm Yaklaşımı

PostHog session recording (rrweb) verilerini sürekli ingest eden, heuristic filtreleme ile gürültüyü ayıklayan, geri kalan ilginç session'ları semantic compression ile token-efficient hale getiren, LLM ile yapılandırılmış insight'lara dönüştüren ve bu insight'ları GitHub issue'larına otomatik bağlayan bir pipeline.

Bu Sistem Neden Değer Üretir?

Solo founder leverage: 50 saat manuel session replay izleme ≈ 30 dakika insight inbox triage. AI hiçbir session'ı otomatik aksiyon almak için kullanmaz — sadece founder'a sunulacak kaliteli sinyali damıtmak için kullanılır. Karar her zaman insanda.

Süper Panel ile İlişki

Bu sistem Süper Panel'in Phase 6 modülüdür. Süper Panel'in mevcut altyapısını kullanır:

  • Panel PostgreSQL (insight ve metadata storage)
  • Panel Redis + BullMQ (job orchestration)
  • MinIO (compressed session storage)
  • Better Auth (tek kullanıcı access)
  • Audit log (tüm AI çağrıları audit'lenir)
  • Cost dashboard yeni eklenir

Sase.tr read-only DB connection (Süper Panel Katman 1) zaten Phase 2'de kurulmuş varsayılır. Bu PRD'de PostHog ayrı bir external data source olarak ele alınır.


2. Hedefler ve Hedef Olmayanlar

Hedefler

# Hedef Ölçü
G1 Sase.tr kullanıcı davranışlarından eyleme dönüştürülebilir insight çıkarmak Haftada en az 5 validated insight
G2 Pipeline maliyetinin founder kontrolünde olması Panel'den $/token budget set edilebilir, hard cap'ler çalışır
G3 Founder triage süresinin minimize edilmesi Günde ≤15 dakika insight inbox
G4 Insight → Issue → Validation döngüsünün kapanması Shipped insight'ların %50+'sı regression-free
G5 False positive oranının düşürülmesi Discard oranı 4 hafta içinde %60'tan %30'a iner
G6 KVKK uyumlu data handling Hiçbir PII LLM'e ham olarak gitmez
G7 Sıfır external dependency on prod data PostHog dışındaki tüm pipeline self-hosted (Süper Panel container'larında)

Hedef Olmayanlar

  • Gerçek zamanlı analiz: Session bittikten sonra 1-24 saat içinde insight üretilmesi yeterli, real-time değil
  • Otomatik fix uygulama: AI önerir, founder uygular; otomatik kod commit'i yok
  • A/B test platformu olmak: Sadece gözlem, deney tasarımı bu modülde değil
  • Kullanıcıya geri bildirim (in-app): Insight engine sadece founder'a konuşur, kullanıcıya değil
  • Multi-tenant insight izolasyonu: Tek kullanıcı (founder), izolasyon gereksiz
  • Diğer projelere otomatik genişleme: Phase 6 sadece Sase.tr. Diğer projeler ayrı feature PRD'leriyle eklenir
  • Custom LLM training: Mevcut frontier model'ler (Claude/GPT) yeterli, fine-tuning yok

3. Pilot Kararı: Neden Sase.tr?

Sase.tr'nin Pipeline İçin İdeal Özellikleri

Özellik Sase.tr'deki Durum Pipeline İçin Avantaj
Kullanıcı sayısı Düşük-orta (B2B niche) Tüm session'lar ele alınabilir, sampling drama'sı yok
Kullanıcı değeri Yüksek (subscription paying) Her insight yüksek $ değerinde, AI cost'u haklı
Task karmaşıklığı Yüksek (VIN sorgu, multi-provider lookup) Friction noktaları zengin, sinyal bol
User feedback kanalı Zayıf (B2B teknik kullanıcılar sessiz) AI insight'ın diferansiyel değeri yüksek
Backend hata yüzeyi Geniş (4 provider entegrasyonu) Backend hatası → frontend friction → AI yakalar
Subscription tier yapısı Net (Starter → Brand-specific → Full) Conversion friction noktaları analiz edilebilir
Feature seti Olgun ve dokümante LLM context için repo map kurulabilir

Pilot Sonrası Başarı Sinyali

Pilot 6 hafta sonunda şunlar gerçekleşmişse "başarılı" sayılır ve diğer projelere genişler:

  • En az 1 bug, AI insight'tan tetiklenip shipped ve regression-free
  • En az 1 feature/UX fix, AI insight'tan ilham almış ve shipped
  • Aylık AI maliyeti < $200 (Sase.tr için tek başına)
  • Founder'ın insight UI'ında haftalık ≥3 oturum geçmesi (kullanım sinyali)

4. Üst Düzey Mimari

Veri Akışı

┌──────────────────────────────────────────────────────────────────────┐
│                         Sase.tr (Production)                          │
│  ┌────────────────┐                                                   │
│  │ posthog-js SDK │ ← rrweb recorder + event capture                  │
│  └───────┬────────┘                                                   │
│          │                                                            │
│          ▼                                                            │
│  ┌────────────────────────┐                                           │
│  │ PostHog Cloud / Self   │  ← session_recordings storage             │
│  └──────────┬─────────────┘                                           │
└─────────────┼──────────────────────────────────────────────────────────┘
              │ HTTPS / API key
              │
              ▼
┌──────────────────────────────────────────────────────────────────────┐
│                Süper Panel (sp.semih.ai infrastructure)               │
│                                                                       │
│  ┌─────────────────────────────────────────────────────────────────┐ │
│  │ Katman 1: Ingestion Worker (BullMQ)                             │ │
│  │  - PostHog API poller (her 5 dakikada)                          │ │
│  │  - Heuristic filter (95% session burada elenir)                 │ │
│  │  - sessions_meta tablosuna metadata yazılır                     │ │
│  └────────────────────┬────────────────────────────────────────────┘ │
│                       │ filtered session_ids                          │
│                       ▼                                               │
│  ┌─────────────────────────────────────────────────────────────────┐ │
│  │ Katman 2: Signal Detection Worker                               │ │
│  │  - Tag assignment (bug_suspected, ux_friction, vb.)             │ │
│  │  - Severity scoring                                             │ │
│  │  - Sub-threshold session arşivlenir, üstü Katman 3'e            │ │
│  └────────────────────┬────────────────────────────────────────────┘ │
│                       │ tagged sessions                               │
│                       ▼                                               │
│  ┌─────────────────────────────────────────────────────────────────┐ │
│  │ Katman 3: Compression Worker                                    │ │
│  │  - PostHog'tan full rrweb snapshot fetch                        │ │
│  │  - Semantic timeline transformation                             │ │
│  │  - PII sanitization                                             │ │
│  │  - MinIO'ya compressed_sessions yazılır                         │ │
│  │  - Fingerprint hesaplanır → cache check                         │ │
│  └────────────────────┬────────────────────────────────────────────┘ │
│                       │ compressed timelines                          │
│                       ▼                                               │
│  ┌─────────────────────────────────────────────────────────────────┐ │
│  │ Katman 4: Analysis Worker (rate-limited + budget-gated)         │ │
│  │  - Budget guard: bugünkü harcama < daily cap?                   │ │
│  │  - Prompt template selection (tag bazlı)                        │ │
│  │  - Model tier selection (severity bazlı)                        │ │
│  │  - LLM call (Anthropic API / OpenRouter)                        │ │
│  │  - JSON validation → insights tablosuna yazım                   │ │
│  └────────────────────┬────────────────────────────────────────────┘ │
│                       │ insights                                      │
│                       ▼                                               │
│  ┌─────────────────────────────────────────────────────────────────┐ │
│  │ Katman 5: Triage UI & Action Loop                               │ │
│  │  - Insight inbox (Next.js)                                      │ │
│  │  - Manual / auto GitHub issue creation                          │ │
│  │  - Validation period tracking                                   │ │
│  │  - Pattern aggregation                                          │ │
│  └─────────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────┘

Pipeline Latency Hedefleri

Aşama P50 P95
Session bitişi → Katman 1 ingestion 5 dk 15 dk
Katman 1 → Katman 2 tagging 30 sn 2 dk
Katman 2 → Katman 3 compression 1 dk 5 dk
Katman 3 → Katman 4 LLM 30 sn 2 dk
Toplam: Session → Insight ~8 dk ~25 dk

Real-time gerekmiyor; batch processing kabul edilebilir. Latency düşmesi gerekirse Katman 1'in polling frequency'si artırılır.

Sistem Bileşenleri (Coolify Container Eklemeleri)

Container Ne yapar CPU/RAM Yeni mi?
panel-web UI + API (insight inbox, settings) mevcut Hayır (genişler)
panel-worker BullMQ workers (mevcut worker'a yeni queue'lar) mevcut +0.5GB Hayır (genişler)
panel-postgres Yeni tablolar mevcut Hayır (şema genişler)
panel-redis Yeni queue'lar, cache mevcut Hayır
MinIO compressed_sessions bucket mevcut Maestro Hayır

Yeni container yok. Mevcut worker process'i yeni job tipleri kazanır.


5. Katman 1: Ingestion & Heuristic Filter

5.1 PostHog API Entegrasyonu

PostHog Deployment Modeli

Karar: PostHog Cloud (self-hosted değil).

Etkileri:

  • Veri konumu: PostHog Cloud EU region (KVKK için tercih edilen)
  • Rate limit: 240 req/min API rate (240 res/dakika polling için yeterli)
  • Recording storage: PostHog tarafında, panel sadece API ile erişir
  • Maliyet: PostHog Cloud usage-based pricing (recording sayısına göre, free tier ile başlanır, scale ile ücretlendirme)
  • Backup/uptime: PostHog SLA, panel kendi tarafında yedek tutmaz

KVKK ek değerlendirme:

  • PostHog Cloud EU region kullanılmalı (US region KVKK için ek değerlendirme gerektirir)
  • PostHog ile Veri İşleyici Sözleşmesi (DPA) imzalanmalı
  • Kullanıcı consent flow Sase.tr'de zaten varsa PostHog'a aktarılır

Polling Stratejisi

  • BullMQ scheduled job: posthog-ingest-sase her 5 dakikada bir tetiklenir
  • Job, son ingestion timestamp'inden itibaren yeni session'ları çeker
  • INGESTION_WATERMARK adlı bir tablo'da projeye özel last_polled_at tutulur

PostHog Endpoint'leri

GET /api/projects/{project_id}/session_recordings/
  ?date_from={last_polled_at}
  &date_to={now}
  &limit=100
  &offset={cursor}

Cevap olarak session metadata listesi (snapshot data hariç) gelir. Snapshot ham veri bu aşamada çekilmez, sadece metadata bakılır — gereksiz network/storage maliyeti önlenir.

Rate Limit ve Kotalar

  • PostHog Cloud rate limit: 240 req/min (cloud); self-hosted'da limit yok
  • Burst koruması: BullMQ rate limiter, posthog-ingest queue'sunda 5 concurrent worker max
  • 429 yanıtında exponential backoff: 1s, 2s, 4s, 8s... max 5 retry, sonra failed queue
  • 5xx yanıtında aynı backoff, ama 10 retry'a kadar

Watermark Resume

İngestion failure durumunda watermark güncellenmez, böylece retry'da aynı window yeniden işlenir. PostHog session ID'leri benzersizdir, panel tarafında INSERT ... ON CONFLICT DO NOTHING ile duplicate önlenir.

5.2 Heuristic Filter Kuralları

Session metadata'sı şu kurallardan en az birini sağlamıyorsa discard edilir (sessions_meta'ya yazılmaz):

Eliminasyon Kriterleri (ANY-OF, session reddedilir)

Kural Eşik Gerekçe
Süre < 10 saniye Strict Bot veya bounce, sinyal yok
Süre > 30 dakika Strict Idle/tab açık unutulmuş
Pageview sayısı = 1 VE bounce flag VE auth_user = false Strict Anonim bounce, low value
User agent bot list Strict Crawler
Internal IP (Sase.tr ekibi) Strict Self-test

Promosyon Kriterleri (ANY-OF, session geçer)

Eliminasyonu geçen session, en az bir promosyon kriterini sağlamalı:

Kural Etki
Auth'lu kullanıcı Always promote (B2B değerli)
Console error count ≥ 1 Promote
Network 5xx response count ≥ 1 Promote
Network 4xx response count ≥ 3 Promote (potential perm/auth issue)
Rage click detected (PostHog autocapture) Promote
Dead click detected Promote
Form abandonment (form fill + no submit) Promote
Yüksek değerli sayfa ziyareti (/vin/, /upgrade, /api-keys) Promote
Funnel drop-off (signup'tan sonra ilk VIN sorgusunu yapmadan ayrılma) Promote
Yeni kullanıcı (signup_at son 7 gün içinde) Promote
Subscription tier upgrade sayfasını ziyaret etti ama upgrade etmedi Promote

Promote olmayan anonim session'lar %5 rastgele sampling ile yine de geçer (baseline kalibrasyon için). Bu sample rate panelden ayarlanabilir.

5.3 Filter Output

Geçen her session için sessions_meta tablosuna kayıt atılır:

type SessionMeta = {
  id: string;                    // PostHog session_id
  project_key: 'sase';
  user_id_hash: string | null;   // hash'li, raw user_id değil
  is_authenticated: boolean;
  subscription_tier: string | null;
  started_at: Date;
  duration_ms: number;
  pageview_count: number;
  click_count: number;
  error_count: number;
  rage_click_count: number;
  dead_click_count: number;
  network_5xx_count: number;
  network_4xx_count: number;
  promotion_reasons: string[];   // ['rage_click', 'auth_user']
  raw_metadata_url: string;      // MinIO key, ham PostHog metadata kopyası
  status: 'pending_signal' | 'tagged' | 'compressed' | 'analyzed' | 'discarded';
  processed_at: Date | null;
  created_at: Date;
}

raw_metadata_url'deki ham metadata MinIO'da 30 gün saklanır, sonra silinir (compression artifact yeterli).

5.4 Storage Footprint Tahmini

Sase.tr için günde tahmini:

  • Toplam session: ~500 (kabul ihtiyatlı tahmin)
  • Eliminasyon sonrası: ~150
  • Promote olan: ~50
  • Sample %5 anonim: ~10
  • Pipeline'a giren: ~60 session/gün

Bu ~1800 session/ay → AI maliyeti hesabı buradan yapılır (Bölüm 9).

5.5 Custom Event Stream Entegrasyonu (Sase.tr Event Taxonomy)

Referans doküman: sase-posthog-events-prd.md — Sase.tr custom event taxonomy ve implementation rehberi. BIP pilot'unun yüksek-kalite insight üretmesi için Sase.tr'de 30+ custom event ile identification + group analytics kurulumu gerekli. Bu bölüm o event stream'in pipeline'a nasıl entegre olduğunu açıklar.

Custom Event'lerin Pipeline'daki Rolü

PostHog'tan gelen veri iki ana akışta:

  1. Session recordings (rrweb): Görsel session, click/scroll/network — generic timeline
  2. Custom events: Sase.tr-specific semantic event'ler (vin_decode_succeeded, provider_fallback_triggered, compatibility_check_completed, vb.)

Bu iki akış session_id ile join edilir:

session_recording (rrweb)
  + custom_events (filtered by session_id)
  + user_properties (identify cache)
  + group_properties (company group cache)
  = enriched_session

enriched_session Katman 2'de tagging için, Katman 3'te compression için kullanılır.

PostHog API'sinden Custom Event Fetch

Session metadata'sı çekildikten sonra (Bölüm 5.1), o session'ın custom event'leri ayrı bir API call ile çekilir:

GET /api/projects/{project_id}/events/
  ?event=vin_decode_initiated,vin_decode_succeeded,vin_decode_failed,
         provider_response_received,provider_fallback_triggered,
         parts_panel_viewed,parts_filter_applied,
         compatibility_check_initiated,compatibility_check_completed,
         payment_initiated,payment_succeeded,payment_failed,
         plan_selected,checkout_started,trial_urgency_banner_cta_clicked,
         search_input_validation_failed,help_clicked,feature_discovered,
         downgrade_offer_shown,downgrade_offer_accepted,downgrade_offer_declined
  &properties=[{"key":"$session_id","value":"<session_id>"}]
  &date_from={session_started_at}
  &date_to={session_ended_at}
  &limit=200

Bu API call session başına ortalama 5-20 custom event döner. Her event'in property'leri Sase.tr event taxonomy'sine (sase-posthog-events-prd.md Bölüm 5-7) uyar.

User Properties & Group Properties Caching

posthog.identify() ile setlenmiş user property'leri ve posthog.group('company') group property'leri her event'te ayrı ayrı çekmek yerine cached olarak panel DB'sinde tutulur:

-- Yeni tablo
CREATE TABLE posthog_person_cache (
  distinct_id TEXT PRIMARY KEY,
  properties JSONB NOT NULL,         -- identify ile setlenmiş property'ler
  groups JSONB,                       -- {company: "comp_123"}
  refreshed_at TIMESTAMPTZ NOT NULL,
  ttl_at TIMESTAMPTZ NOT NULL
);

CREATE TABLE posthog_group_cache (
  group_type TEXT NOT NULL,           -- 'company'
  group_key TEXT NOT NULL,            -- company_id
  properties JSONB NOT NULL,
  refreshed_at TIMESTAMPTZ NOT NULL,
  ttl_at TIMESTAMPTZ NOT NULL,
  PRIMARY KEY (group_type, group_key)
);

TTL 24 saat. Süresi dolduğunda PostHog API'sinden refresh edilir.

Enriched Session Object

Katman 2 öncesi pipeline enriched_session objesi inşa eder:

type EnrichedSession = {
  // Session-level (rrweb metadata)
  session_id: string;
  started_at: Date;
  duration_ms: number;
  // ... (Bölüm 5.3'teki sessions_meta)
  
  // Custom events (chronological)
  custom_events: Array<{
    event: string;            // 'vin_decode_failed'
    timestamp: Date;
    properties: Record<string, any>;
  }>;
  
  // User properties cache
  user_properties: {
    plan_tier?: 'free' | 'starter' | 'brand_specific' | 'full';
    days_since_signup?: number;
    total_vin_queries?: number;
    preferred_provider?: string;
    company_id?: string;
    company_role?: string;
    subscription_status?: string;
    trial_ends_at?: Date | null;
    // ... (sase-posthog-events-prd.md Bölüm 4.1)
  };
  
  // Group (company) properties cache
  group_properties?: {
    tier?: string;
    seat_count?: number;
    seats_used?: number;
    industry?: string;
    mrr_usd?: number;
    churn_risk_score?: number;
    // ... (sase-posthog-events-prd.md Bölüm 4.2)
  };
}

Pipeline Akışına Etkisi

[PostHog API Poller]
     │
     ├─→ Session metadata fetch (Bölüm 5.1)
     │
     ├─→ Custom events fetch (filtered by session_id)
     │
     ├─→ User properties cache lookup (refresh if stale)
     │
     └─→ Group properties cache lookup (refresh if stale)
            │
            ▼
     [Enriched Session]
            │
            ├─→ Katman 1: Heuristic Filter (custom event'ler ekstra promote sinyali)
            ├─→ Katman 2: Tagging (custom event'ler tag detection'ı zenginleştirir)
            └─→ Katman 3: Compression (custom event'ler timeline'a inline edilir)

Custom Event'lerin Heuristic Filter'a Etkisi (Promote Sinyalleri)

Mevcut promote kurallarına (Bölüm 5.2) custom event'ler ek sinyal olarak eklenir:

Custom Event Pattern Action
vin_decode_failed count ≥ 1 Promote
provider_fallback_triggered count ≥ 1 Promote
payment_failed exists Promote (P1 severity hint)
checkout_started without payment_succeeded Promote
trial_urgency_banner_cta_clicked without conversion Promote
downgrade_offer_shown without acceptance/decline Promote
compatibility_check_completed result = 'incompatible' Promote (product quality)
search_input_validation_failed count ≥ 3 Promote (UX friction)
subscription_cancelled Always promote (P0/P1)
feature_discovered for new feature Promote (discoverability tracking)

Bu sinyaller mevcut rrweb-based promote kriterleriyle birleşince filter sıkılığı artar; pipeline'a sadece sinyal-zengin session'lar girer.


6. Katman 2: Signal Detection (Tagging)

6.1 Tag Sistemi

Her session 0+ tag alabilir. Tag'siz session arşivlenir (compress edilmez). 1+ tag'li session Katman 3'e geçer.

Tag Tanımları

Tag Tetikleyici Severity Default
bug_suspected Console error + (rage_click OR dead_click OR abandonment) P1
server_error_impact Network 5xx + sonrasında session sonu veya retry P1
vin_decode_fail_pattern vin_decode_failed ≥ 2 (same provider) P1
provider_reliability_issue provider_fallback_triggered ≥ 1 P2
payment_friction payment_initiated exists, no payment_succeeded, no payment_failed P1
payment_ui_silent_failure payment_succeeded (backend) exists, no payment_success_ui (frontend) P0
checkout_abandonment checkout_started without conversion P2
trial_conversion_lost trial_started, trial ended, no payment_succeeded P2
downgrade_pending downgrade_offer_shown without accepted/declined P2
compatibility_quality_gap compatibility_check_completed result = 'unknown' or 'incompatible' P2
parts_export_abandoned parts_export_initiated without success P3
search_validation_friction search_input_validation_failed ≥ 3 P3
ux_friction Dead click veya rage click (error yokken) P2
form_abandonment Form input event'leri var, submit yok, çıkış var P2
discovery_loop Aynı sayfaya 3+ giriş + conversion yok P3
feature_discoverability_gap New feature deploy'undan 7+ gün, 0 feature_discovered event P3
onboarding_stuck signup_date < 24h + 0 vin_decode_succeeded + session > 2 dk P2
upgrade_hesitation /upgrade ziyareti var, plan_selected yok, geri çıkış P2
power_user_path 10+ vin_decode_succeeded, multi-provider, parts_export_initiated INFO
at_risk_active_session at_risk_users cohort üyesi, low engagement P2
slow_perf LCP > 4s veya FID > 300ms tekrarlanan sayfa load'da P3
api_key_friction api_key_revoked reason='rotation' veya keys sayfasında 60sn+, key yaratmadı P3
webhook_setup_struggle /webhooks ziyaret, no webhook_configured event, repeat visit P3
provider_mismatch Aynı VIN'i farklı provider'larda sorgu, provider_fallback_triggered manuel P2

Severity Levels

  • P0: Critical (production down impact). Otomatik issue açılır.
  • P1: High (bug, broken flow). Insight inbox top priority.
  • P2: Medium (UX friction, conversion impact). Normal triage.
  • P3: Low (nice-to-have, pattern needed). Pattern'lenmediği sürece beklemede.
  • INFO: Bilgi amaçlı, action gerekmez (örn. power_user_path, learning için).

6.2 Tagging Algoritması

Algoritma artık iki veri kaynağı kullanır: rrweb session metrikleri ve custom event timeline. Custom event tabanlı kurallar daha güçlüdür (semantic context içerir), öncelik onlara verilir.

for enriched_session in pending_signal_sessions:
    tags = []
    severity = 'INFO'
    custom_events = enriched_session.custom_events  # chronological
    user_props = enriched_session.user_properties
    group_props = enriched_session.group_properties
    
    # ─── Bug detection (custom event tabanlı, daha güçlü) ───
    vin_failures = filter(custom_events, event='vin_decode_failed')
    if len(vin_failures) >= 2 and same_provider(vin_failures):
        tags.append('vin_decode_fail_pattern')
        severity = max(severity, 'P1')
    
    if any(e for e in custom_events if e.event == 'provider_fallback_triggered'):
        tags.append('provider_reliability_issue')
        severity = max(severity, 'P2')
    
    # ─── Payment criticality ───
    payment_started = any(custom_events, event='payment_initiated')
    payment_done_backend = any(custom_events, event='payment_succeeded')
    payment_done_ui = any(custom_events, event='payment_success_ui')
    payment_failed = any(custom_events, event='payment_failed')
    
    if payment_done_backend and not payment_done_ui:
        tags.append('payment_ui_silent_failure')
        severity = max(severity, 'P0')  # auto-issue trigger
    
    if payment_started and not (payment_done_backend or payment_failed):
        tags.append('payment_friction')
        severity = max(severity, 'P1')
    
    # ─── Conversion funnel ───
    if any(custom_events, event='checkout_started'):
        if not any(custom_events, event='payment_succeeded'):
            tags.append('checkout_abandonment')
            severity = max(severity, 'P2')
    
    if any(custom_events, event='downgrade_offer_shown'):
        offered = any(custom_events, event='downgrade_offer_accepted')
        declined = any(custom_events, event='downgrade_offer_declined')
        if not (offered or declined):
            tags.append('downgrade_pending')
            severity = max(severity, 'P2')
    
    # ─── Parts / compatibility ───
    compat_checks = filter(custom_events, event='compatibility_check_completed')
    if any(c.properties.get('result') in ('unknown', 'incompatible') for c in compat_checks):
        tags.append('compatibility_quality_gap')
        severity = max(severity, 'P2')
    
    export_init = any(custom_events, event='parts_export_initiated')
    export_done = any(custom_events, event='parts_export_completed')  # if added in Faz 1
    if export_init and not export_done:
        tags.append('parts_export_abandoned')
        severity = max(severity, 'P3')
    
    # ─── Search friction ───
    validation_failures = count(custom_events, event='search_input_validation_failed')
    if validation_failures >= 3:
        tags.append('search_validation_friction')
        severity = max(severity, 'P3')
    
    # ─── Onboarding ───
    if user_props.get('days_since_signup', 999) < 1:
        first_vin = any(custom_events, event='vin_decode_succeeded')
        if not first_vin and enriched_session.duration_ms > 120_000:
            tags.append('onboarding_stuck')
            severity = max(severity, 'P2')
    
    # ─── Power user signal ───
    vin_successes = count(custom_events, event='vin_decode_succeeded')
    if vin_successes >= 10:
        providers_used = unique_providers(vin_successes)
        if len(providers_used) >= 2 and any(custom_events, event='parts_export_initiated'):
            tags.append('power_user_path')
            # severity stays INFO
    
    # ─── At-risk segment override ───
    if user_props.get('subscription_status') == 'active':
        # Cohort context: at_risk_users (last 14d: 0 vin_decode_initiated)
        if user_props.get('total_vin_queries_last_30d', 0) == 0:
            tags.append('at_risk_active_session')
            severity = max(severity, 'P2')
    
    # ─── Generic rrweb-based fallback rules (no custom event) ───
    # bug_suspected, ux_friction, slow_perf, etc.
    # ... (önceki rrweb-only kurallar korunur)
    
    # ─── Score calculation ───
    score = calculate_score(severity, user_props, group_props, tags)
    
    if tags and score >= 30:
        update_session(enriched_session.id, tags=tags, severity=severity, 
                       score=score, status='tagged')
    else:
        update_session(enriched_session.id, status='discarded')

Önemli farklar (önceki versiyondan):

  1. fetch_sase_user() artık çağrılmaz; user state PostHog identify cache'inden gelir (Bölüm 5.5). Süper Panel'in Sase.tr RO database connection'ı sadece doğrulama amaçlı kullanılır (örn. company churn risk hesaplama gibi event'lerle yakalanamayan veriler).

  2. Custom event tabanlı kurallar rrweb-based kurallardan daha öncelikli çünkü semantic context taşır: "vin_decode_failed" net bir sinyal iken "network 500" generic.

  3. Group properties tag'ler at_risk_active_session gibi B2B-aware tag'lerde kullanılır.

  4. Score threshold (>= 30) altındaki session'lar tag varsa bile discard edilir. Pipeline budget'ı yüksek-değer session'lara odaklanır.

6.3 Scoring (Priority Calculation)

Her session'a bir interestingness score verilir (0-100):

score = (
    severity_weight * 30 +
    user_value_weight * 25 +
    novelty_weight * 20 +
    recency_weight * 15 +
    pattern_strength * 10
)

severity_weight: P0=1.0, P1=0.8, P2=0.5, P3=0.3, INFO=0.1
user_value_weight: Full=1.0, Brand-specific=0.7, Starter=0.5, anonymous=0.2
novelty_weight: Bu tag bu kullanıcıdan ilk kez geliyorsa 1.0, tekrar ise 0.3
recency_weight: Son 1h=1.0, son 24h=0.7, son 7g=0.4
pattern_strength: Bu fingerprint son 7 günde 1=0.2, 5+=1.0

Skor < 30 olan session'lar Katman 3'e geçmez, sadece arşivlenir (ileride pattern analysis için).


7. Katman 3: Semantic Compression

7.1 Amaç

rrweb JSON event stream'i (~50-500 KB) → AI-friendly semantic timeline (~500-2000 token). %95+ token tasarrufu.

7.2 Compression Pipeline

PostHog snapshot fetch
    ↓
rrweb event parsing
    ↓
Event normalization (timestamps, paths)
    ↓
PII sanitization (BEFORE anything else)
    ↓
Event deduplication (consecutive same events)
    ↓
DOM mutation → semantic action
    ↓
Network event correlation
    ↓
Pattern annotation (← hints)
    ↓
Timeline serialization (text)
    ↓
Token count check
    ↓
MinIO upload + fingerprint hash

7.3 rrweb Event Kategorileri

rrweb 6+ event tipi gönderir. İşleme stratejisi:

Event Type İşlem
0 DomContentLoaded İşaretle, devamı için baseline
1 Load Page load işaretle, LCP timing al
2 FullSnapshot İlk DOM, sadece ilk session için reference
3 IncrementalSnapshot Asıl iş burada, sub-event'lere bak
4 Meta URL, viewport, user agent al
5 Custom PostHog event'leri (autocapture, custom)
6 Plugin Network panel data (önemli)

IncrementalSnapshot sub-types:

Sub-type Anlamı İşlem
Mutation DOM değişikliği Skip (çok gürültülü, sadece form input için tut)
MouseMove Mouse pozisyonu Skip tamamen
MouseInteraction Click, mousedown Tut (en kritik sinyal)
Scroll Scroll position Aggregate: scroll_depth max %
ViewportResize Resize Tut
Input Form input Tut (sanitize edilmiş)
TouchMove Mobile touch Skip detaylı, sadece tap'ları tut
MediaInteraction Video play/pause Tut (Sase.tr için unlikely)
StyleSheetRule CSS değişikliği Skip
CanvasMutation Canvas Skip
Font Font load Skip
Log console.log Tut (özellikle error/warn)
Drag Drag event Tut

7.4 PII Sanitization

Sanitization compression öncesi yapılır. Sanitize-then-compress, asla compress-then-sanitize.

Field-Level Rules

Pattern Detection Replacement
VIN (17 char alphanumeric) Regex: [A-HJ-NPR-Z0-9]{17} WAUZZZ8K**** (ilk 8 + ****)
Email Regex standard email u***@***.com (ilk char + domain)
Telefon (TR) Regex TR numara 5XX***1234 (operator + last 4)
TC Kimlik 11 digit ***********
Plaka TR plate regex 34***123
Kredi kartı Luhn algorithm validated 13-19 digit [REDACTED_CC]
API Key (Sase.tr format) `sase_(live test)_[a-z0-9]+`
Authorization headers Network event'lerde [REDACTED]
Password fields input[type=password] veya name matches Hiç kayıt edilmemeli (PostHog config'de mask)

Selector-Level Rules

rrweb'in data-private attribute'lu element'leri zaten skip etmesi sağlanır. Sase.tr frontend'inde sensitive alanlara bu attribute eklenir:

<input data-private="true" name="vin" ... />
<div data-private="true">{userEmail}</div>

Bu compression aşamasında değil, kaynak Sase.tr kodunda yapılır. Bu PRD'nin scope'unda Sase.tr'ye config rehberi yer alır (Bölüm 15).

Sanitization Audit

Her compression job'ı şu metrikleri loglar:

  • Sanitization match count (kaç PII match'lendi)
  • Match type breakdown
  • Original token count vs sanitized token count

Anomali (örn. 0 sanitization match ama 10000 token) insight engineer alert tetikler.

7.5 Semantic Timeline Formatı

Timeline formatı iki sinyal kaynağını birleştirir: rrweb event'leri (görsel/network/click) ve Sase.tr custom event'leri (semantic). Custom event'ler timeline'a inline interleaved olarak yerleştirilir, böylece LLM'in görüş alanında hem ne olduğunu (click) hem ne anlama geldiğini (vin_decode_failed) görür.

Genel Format (Custom Event Enrichment ile)

=== SESSION ===
id: s_abc123
project: sase.tr
user_segment: authenticated, tier=brand_specific, signup_days_ago=4
  total_vin_queries_30d=87 (power_user_ish)
  preferred_provider=PL24
  subscription_status=active
company_context: tier=full, seats=5/3_active, mrr=$199, industry=auto_service
device: macOS Chrome 138, 1920x1080
duration: 4m12s
tags: [vin_decode_fail_pattern, provider_reliability_issue]
severity: P1
score: 78

=== TIMELINE ===
00:00 → page_load /vin-lookup (lcp=1.2s)
00:03 → click [button:"Sorgula"] near input "vin"
00:04 → input [field:"vin"] (sanitized: WAUZZZ8K****)
00:05 → click [button:"Sorgula"]
       ⤷ EVENT: vin_decode_initiated { vin_brand:"VAG", query_source:"manual" }
00:05 → network POST /api/v1/vin-lookup
00:07 → network response 500 (rt=2.1s, err="Provider PL24 timeout")
       ⤷ EVENT: vin_decode_failed { error_code:"PROVIDER_TIMEOUT", 
                                   provider_attempted:"PL24", retry_count:0 }
00:07 → console_error "Cannot read property 'parts' of undefined"
00:07 → no_response_ui (kullanıcı 3sn bekledi, loading spinner takıldı)
00:10 → click [button:"Sorgula"] ← RETRY
       ⤷ EVENT: vin_decode_initiated { vin_brand:"VAG", query_source:"manual" }
00:13 → network POST /api/v1/vin-lookup → 500 (rt=2.1s)
       ⤷ EVENT: vin_decode_failed { error_code:"PROVIDER_TIMEOUT",
                                   provider_attempted:"PL24", retry_count:1 }
00:13 → rage_click [button:"Sorgula"] (3 clicks/1.2s) ← FRICTION
00:18 → click [link:"VIN Geçmişi"] ← workaround denedi
00:18 → page_load /history (lcp=0.8s)
00:20 → click [button:"Yeni Sorgu"] ← farklı yol denedi
00:21 → page_load /vin-lookup
00:22 → input [field:"vin"] (sanitized: WBA3****)  ← farklı VIN
00:23 → click [button:"Sorgula"]
       ⤷ EVENT: vin_decode_initiated { vin_brand:"BMW", query_source:"manual" }
00:25 → network POST /api/v1/vin-lookup → 200 (rt=0.8s)
       ⤷ EVENT: vin_decode_succeeded { provider:"PL24", response_time_ms:800,
                                      cache_hit:false, ml_decoder_used:false }
00:25 → ui_render parts_table (12 rows)
       ⤷ EVENT: parts_panel_viewed { vehicle_id:"v_8821", parts_count:12,
                                    load_time_ms:140, source_provider:"PL24" }
00:35 → click [row:parts_table item 3]
       ⤷ EVENT: compatibility_check_initiated { part_id:"p_551", target:"v_8821" }
00:36 → ui_render compatibility_modal
       ⤷ EVENT: compatibility_check_completed { result:"compatible",
                                              confidence:0.92, duration_ms:850 }
00:50 → close modal
00:52 → session_end (user closed tab)

=== KEY EVENTS ===
Custom events (4 critical):
- 2x vin_decode_failed (provider=PL24, same error code)
- 1x rage click correlated with 2nd failure
- 1x vin_decode_succeeded (different VIN, BMW brand)
- 0x conversion / payment events

rrweb signals:
- 1x console error (frontend null handling)
- 1x workaround attempt (VIN History)
- 0x rage click outside Sorgula button

=== HYPOTHESES (mechanical, no LLM) ===
- Provider PL24 timeout for VAG VIN; BMW VIN works on same provider
  → Possible VAG-specific upstream issue at PL24
- Frontend doesn't handle 500 gracefully (no error toast?)
  → vin_decode_failed event captures backend signal, but UI silence
- User abandoned VAG VIN, switched to BMW (likely test, not their target)
- Power user (87 queries/30d, full tier) → high-value friction

=== METADATA ===
url_path_sequence: /vin-lookup → /history → /vin-lookup → /vin-lookup
referrer: direct
funnel_step: vin_lookup_attempted (failed first VIN, succeeded second)
user_value: $199 MRR (full tier, 5-seat company)

Format Karakteristikleri

  • Newline-separated, GitHub-flavored markdown'a yakın
  • Timestamp prefix her satırda
  • Custom events inline (⤷ EVENT: prefix ile rrweb satırlarına bağlı)
  • Semantic selectors ([button:"Sorgula"]) not brittle CSS
  • "← hint" annotations: AI'a yön gösterir
  • Network + custom event correlation: aynı saniyede ki rrweb network + custom event birlikte görünür
  • User segment context: pipeline'ın PostHog identify cache'inden gelen properties
  • Company context (B2B): group analytics properties
  • Pre-computed hypotheses: deterministik analiz LLM'e çıktı bandwidth'i kazandırır
  • Token budget: Ortalama 1000-2000 token (custom event'lerle %30 büyür), max 3500 token

Custom Event Insertion Algoritması

def merge_rrweb_and_custom_events(rrweb_events, custom_events):
    """
    Custom event'leri rrweb event'lerine timestamp-based interleave eder.
    Aynı timestamp'te olan custom event rrweb event'inin altına ⤷ ile bağlanır.
    """
    sorted_all = sorted(
        [(e.ts, 'rrweb', e) for e in rrweb_events] +
        [(e.ts, 'custom', e) for e in custom_events],
        key=lambda x: x[0]
    )
    
    timeline = []
    last_rrweb = None
    
    for ts, kind, event in sorted_all:
        if kind == 'rrweb':
            timeline.append(format_rrweb(event))
            last_rrweb = event
        else:  # custom
            # Aynı saniyede rrweb event'i varsa onun altına bağla
            if last_rrweb and abs((ts - last_rrweb.ts).total_seconds()) <= 1:
                timeline.append(f"       ⤷ EVENT: {format_custom(event)}")
            else:
                timeline.append(format_standalone_custom(event))
    
    return '\n'.join(timeline)

Multi-Session Bundle (Pattern Mode)

Aynı fingerprint'e sahip 3+ session geldiyse bundle modu (custom event aggregation eklendi):

=== PATTERN BUNDLE ===
fingerprint: bug_vin_lookup_500_pl24
first_seen: 2026-05-10
last_seen: 2026-05-13
occurrences: 7
affected_users: 4

=== SESSION 1/7 (representative) ===
[full timeline above]

=== SESSION 2-7 SUMMARY ===
- All 6 sessions: same /api/v1/vin-lookup 500 pattern
- All 6: provider param differs (PL24, PCAT, TecDoc)
- 4/6: rage click present
- 3/6: workaround attempted
- 0/6: completed lookup on first attempt

Bundle mode tek session göndermekten daha yüksek değer üretir, ama AI maliyeti aynı (tek prompt). LLM'e daha güçlü pattern verir.

7.6 Fingerprinting

Her compressed session'a deterministik bir fingerprint atanır:

fingerprint = hash(
    sorted(tags),
    primary_url_path,
    primary_error_message_normalized,  // null fields removed
    primary_failed_endpoint,
    severity
)

Aynı fingerprint'e sahip session'lar:

  • Tek tek LLM'e gönderilmez
  • Bundle'a eklenir
  • Bundle'ın LLM analizi 6 saatte bir refresh edilir (yeni session'lar pattern'i güçlendirir mi?)

7.7 Compression Output

type CompressedSession = {
  session_id: string;
  fingerprint: string;
  semantic_timeline_minio_key: string;
  token_count_input: number;        // GPT-tokenizer ile sayıldı
  token_count_estimate_output: number;  // Beklenen LLM response
  compression_ratio: number;        // Original bytes / compressed tokens
  sanitization_match_count: number;
  sanitization_breakdown: Record<string, number>;
  is_bundle: boolean;
  bundle_session_ids: string[];     // bundle ise
  ready_for_analysis_at: Date;
}

8. Katman 4: LLM Analysis

8.1 Prompt Architecture

Tek bir "generic" prompt yok. Her tag tipinin kendi prompt template'i var. Prompt'lar versiyonludur ve panel'den editlenebilir.

Prompt Registry

prompt_templates tablosu:

type PromptTemplate = {
  id: string;
  tag: string;                      // 'bug_suspected', 'ux_friction', vb.
  version: number;
  name: string;
  system_prompt: string;
  user_prompt_template: string;     // {{timeline}} placeholder içerir
  output_schema_json: object;       // JSON schema validation
  model_tier: 'cheap' | 'standard' | 'premium';
  max_output_tokens: number;
  temperature: number;
  active: boolean;
  created_at: Date;
  performance_stats: {
    avg_cost_usd: number;
    avg_input_tokens: number;
    avg_output_tokens: number;
    validation_pass_rate: number;
    insight_action_rate: number;    // founder kaç tanesini "act" yaptı
  };
}

8.2 Prompt Türleri

8.2.1 bug_triage Prompt'u

System:

Sen Sase.tr adlı bir B2B VIN lookup SaaS'ında oluşan bug'ları analiz eden bir uzmansın.
Sana semantic session timeline'ı verilecek. Görevin:

1. Bug'ı net şekilde reproduce etmek için adımları çıkarmak
2. Etkilenen route ve component'i tahmin etmek
3. Hipoteze dayalı root cause önermek
4. Severity belirlemek (P0/P1/P2/P3)
5. Suggested fix effort tahmin etmek (S/M/L)

Sadece geçerli JSON döndür. Açıklama, markdown, code fence yazma.
Hayal ürünü iddia etme; emin değilsen confidence düşür.

Sase.tr context:
- Stack: NestJS backend, Next.js frontend
- 4 provider: PL24 (Partslink24), PCAT, RMEX, TecDoc
- Database: PostgreSQL with Prisma
- Auth: JWT-based, sticky session routing

User template:

{{timeline}}

Bu session'da bug var. Yukarıdaki schema'ya göre JSON yanıt ver.

Output schema:

{
  "type": "object",
  "required": ["type", "severity", "title", "reproduce_steps", "hypothesis", "confidence"],
  "properties": {
    "type": {"const": "bug"},
    "severity": {"enum": ["P0", "P1", "P2", "P3"]},
    "title": {"type": "string", "maxLength": 120},
    "reproduce_steps": {
      "type": "array",
      "items": {"type": "string"},
      "minItems": 2,
      "maxItems": 10
    },
    "affected_route": {"type": "string"},
    "affected_component_hypothesis": {"type": "string"},
    "error_signature": {"type": "string"},
    "hypothesis": {"type": "string", "maxLength": 500},
    "suggested_investigation": {
      "type": "array",
      "items": {"type": "string"}
    },
    "suggested_fix_effort": {"enum": ["S", "M", "L"]},
    "confidence": {"type": "number", "minimum": 0, "maximum": 1},
    "user_impact_estimate": {"type": "string"},
    "is_likely_provider_issue": {"type": "boolean"},
    "implicated_provider": {"enum": ["PL24", "PCAT", "RMEX", "TecDoc", null]}
  }
}

8.2.2 ux_friction Prompt'u

System: UX uzmanı persona, friction noktasını teşhis etme görevi.

Output schema (kısaltılmış):

  • intent_hypothesis (kullanıcı ne yapmaya çalışıyordu?)
  • friction_point (nerede takıldı?)
  • friction_type (copy, layout, affordance, performance, terminology)
  • quick_fix (1 günde yapılabilir öneri)
  • long_term_fix (1 hafta+ effort gerektiren öneri)
  • affected_user_segment

8.2.3 onboarding_stuck Prompt'u

System: Yeni kullanıcı onboarding deneyimi uzmanı.

Output schema:

  • time_to_first_value_estimate
  • block_point (hangi adımda kaldı?)
  • unclear_concept (anlamadığı kavram nedir?)
  • documentation_gap (hangi yardım eksik?)
  • suggested_in_app_help
  • suggested_email_followup

8.2.4 upgrade_hesitation Prompt'u

System: Conversion ve pricing uzmanı.

Output schema:

  • viewed_tier
  • time_on_pricing_page
  • comparison_signals (kullanıcı tier'ları karşılaştırdı mı?)
  • likely_concern (price, feature, trust)
  • feature_gap_hypothesis
  • suggested_intervention

8.2.5 pattern_analysis Prompt'u (bundle mode için)

System: Pattern recognition uzmanı, multi-session aggregate analysis.

Output schema:

  • pattern_name (kısa, akılda kalıcı)
  • root_cause_hypothesis
  • affected_user_count
  • business_impact_estimate
  • priority_recommendation

8.3 Model Tier Seçimi (DeepSeek)

Provider: DeepSeek API (api.deepseek.com) Endpoint: Anthropic-compatible endpoint (Anthropic SDK ile native kullanım) Konfigürasyon:

ANTHROPIC_BASE_URL=https://api.deepseek.com/anthropic
ANTHROPIC_AUTH_TOKEN=<deepseek_api_key>

DeepSeek 3 tier yerine 2 tier'a sadeleşir — flagship modeli zaten Claude Sonnet seviyesinde performans verir.

Tier Model Cache Miss In $/M Cache Hit In $/M Output $/M Kullanım
flash deepseek-v4-flash $0.14 $0.0028 (98% off) $0.28 INFO, P2, P3, batch, ilk pass
pro deepseek-v4-pro $0.435* $0.003625 (99% off) $0.87* P0, P1, complex pattern bundles

* V4 Pro 31 Mayıs 2026'ya kadar %75 indirimli. Sonrası normal fiyat (~$1.74 input / $3.48 output beklentisi). Pilot bu pencerede başlarsa avantajlı.

Tier Atama Mantığı

def select_model_tier(session: CompressedSession) -> Tier:
    if session.severity in ('P0', 'P1'):
        return 'pro'   # bug + critical path

    if session.is_bundle and session.bundle_size >= 5:
        return 'pro'   # pattern analysis premium analiz hak ediyor

    return 'flash'  # P2/P3/INFO için yeterli, dramatik ucuz

Cache Hit'i Maksimize Etmek (Kritik)

DeepSeek'in cache discount'u o kadar agresif ki (%98-99), pipeline tasarımı cache hit oranını maksimize edecek şekilde optimize edilir:

  1. Prompt prefix discipline: System prompt'lar ASLA değişmemeli (versiyonlama dışında). Tag, severity, project context system prompt'un sabit prefix'inde tutulur, kullanıcı verisi (timeline) en sona konur.
  2. Batch within cache window: DeepSeek cache TTL'i prompt tabanlı; aynı system prompt 5-15 dakika içinde tekrar gelirse hit eder. BullMQ worker'ı tag bazlı batch'leyerek 3-5 dakikalık pencerelerde aynı prompt'la birden fazla çağrı yapar.
  3. Off-peak batching (opsiyonel Phase 6e): Düşük priority job'lar (INFO, P3) 16:30-00:30 UTC arasında işlenir, V3/R1'de tarihi olarak %50-75 ek indirim sağlamış (V4'te henüz teyit edilmedi, eval ile ölçülecek).

Fallback Stratejisi

Çoklu provider failover (Phase 6b'den itibaren):

Primary:    DeepSeek api.deepseek.com (Çin)
Fallback 1: DeepSeek via OpenRouter (5-10% markup, US/EU edge)
Fallback 2: Anthropic Claude Sonnet 4.6 (price spike ama always-on)

Hard error (auth, billing) → Telegram alert, queue pause. 503/timeout → exponential backoff, sonra fallback.

Quality Validation (Eval-Driven)

DeepSeek V4'ün structured JSON output disiplini Sonnet kadar olmayabilir. Pilot başlangıcında paralel eval:

  • Aynı eval set Sonnet 4.6 ve DeepSeek V4 Flash'ta çalıştırılır
  • Schema validation pass rate, hallucination rate, severity accuracy karşılaştırılır
  • Eğer DeepSeek %85+ Sonnet performansını veriyorsa: tamamen DeepSeek'e geç
  • %85'in altındaysa: P0/P1 için Sonnet, P2/P3 için DeepSeek hibrit
  • Sonuçlar prompt_templates.performance_stats JSONB'sinde tutulur

8.4 LLM Call Flow

1. Compression complete, ready_for_analysis_at = now()
2. Analysis worker job picks up
3. Budget check (Bölüm 9)
   - Daily budget exceeded? → queue with 'budget_paused' status
   - OK → continue
4. Cache check (fingerprint)
   - Cache hit + insight younger than 6h → return cached, don't call LLM
   - Miss or stale → continue
5. Model tier select
6. Prompt assembly (system + user with timeline)
7. LLM API call
   - Timeout: 60 seconds
   - Retry on 5xx: 3x with exponential backoff
8. Response validation
   - JSON parse → fail = retry once
   - Schema validate (ajv) → fail = log + retry with "Your previous response was invalid: <error>"
   - 2 fails → discard, mark insight as 'llm_failed'
9. Cost calculation
   - input_tokens * tier.input_rate + output_tokens * tier.output_rate
   - Append to cost_ledger table
10. Insight creation
    - Insert into insights table
    - Update sessions_meta.status = 'analyzed'
    - Update cost tracking
11. Notification
    - If severity=P0 → Telegram immediate
    - Else → daily digest queue

8.5 Eval Set (Prompt Quality Control)

Bu en kritik kısımlardan biri. Prompt'ları subjektif olarak iyileştirmek time-sink. Eval set olmadan prompt geliştirme yapılmaz.

Eval Set Yapısı

Her prompt tipi için 15-25 gerçek session örneği:

  • Session timeline'ı (compressed)
  • Beklenen output JSON (founder tarafından elle yazılmış "ground truth")
  • Subjective scoring rubric (0-5):
    • Reproduce step doğruluğu
    • Hypothesis makullüğü
    • Severity uygunluğu
    • Hallucination yok mu?
    • Actionability

Eval Çalıştırma

pnpm eval:bug-triage --version 3 --model sonnet-4.6

Output:

Eval Set: bug_triage v3
Cases: 22
Success: 18 (82%)
Failed: 4
  - case_07: severity hatası (returned P2, expected P1)
  - case_12: hallucination ("PL24 timeout" — timeline'da yok)
  - case_15: reproduce steps incomplete
  - case_19: JSON schema fail

Avg Cost: $0.018
Avg Tokens In: 1240
Avg Tokens Out: 380

Yeni prompt versiyonu sadece eval set'te eski versiyon ile eşit veya daha iyi ise production'a alınır.


9. Maliyet Yönetimi (Cost Governance)

Bu bölüm kullanıcının özellikle istediği detaydadır. Süper Panel'den maliyet token/$ olarak yönetilebilir.

9.1 Cost Tracking Modeli

Her LLM çağrısı için cost_ledger tablosuna kayıt:

type CostLedgerEntry = {
  id: string;
  insight_id: string | null;          // null ise eval/test call
  project_key: 'sase';
  prompt_template_id: string;
  prompt_version: number;
  provider: 'deepseek' | 'anthropic' | 'openrouter';
  model: 'deepseek-v4-flash' | 'deepseek-v4-pro' | 'claude-sonnet-4.6' | 'claude-opus-4.7';
  tier: 'flash' | 'pro';
  tokens_input_cache_miss: number;
  tokens_input_cache_hit: number;
  tokens_output: number;
  cost_input_cache_miss_usd: number;
  cost_input_cache_hit_usd: number;
  cost_output_usd: number;
  cost_total_usd: number;
  cache_hit_ratio: number;            // tokens_cache_hit / total_input
  is_off_peak: boolean;               // 16:30-00:30 UTC?
  call_duration_ms: number;
  was_fallback: boolean;              // primary provider fail mı?
  was_retry: boolean;
  created_at: Date;
}

9.2 Budget Settings (Panel UI'dan Editlenebilir)

Settings sayfasında "Insight AI Budget" sekmesi:

Global Budget

DeepSeek pricing'i 20-50x daha ucuz olduğu için defaults dramatik düşürüldü:

Setting Default (DeepSeek) Eski Plan (Anthropic) ıklama
Monthly hard cap (USD) $30 $300 Bu rakam aşılırsa pipeline DURUR
Daily soft cap (USD) $1.50 $15 ılırsa V4 Pro kapanır, Flash'a fallback
Daily hard cap (USD) $3 $25 ılırsa pipeline DURUR
Per-call max cost (USD) $0.20 $2 Tek bir LLM call'ı bu rakamı geçemez
Min insight value threshold $0.05 $0.50 Üzeri için confirmation gerekmez

Bu rakamlar panel UI'dan değiştirilebilir. Eval sürecinde quality yeterli değil çıkarsa fallback Anthropic kullanımı için bütçe rezervi: aylık ek $50 (toplam $80) öneriliyor.

Per-Project Budget (Sase.tr için)

Setting Default
Sase.tr aylık alokasyon %100 (pilot'ta tek proje)
Sase.tr günlük tahmin token 1M-2M (Flash cache-hit ağırlıklı)

İleride diğer projeler eklendiğinde:

sase.tr: 30%
catvicer: 25%
otoyedekparca: 20%
kokpit: 15%
diğer: 10%

Aylık $30 cap × 5 proje genişlemesi ile bile toplam $30-50/ay beklenir. Anthropic ile $1000+/ay olacak miktar.

Per-Tag Budget Allocation

Bazı tag'ler maliyetli olabilir ama düşük value. Tag bazlı limit:

Tag Daily Max Call Daily Max Cost
bug_suspected unlimited $1.00
ux_friction 50 $0.50
discovery_loop 20 $0.20
power_user_path 10 $0.05 (INFO)
onboarding_stuck 30 $0.30
upgrade_hesitation 30 $0.30
pattern_analysis (bundle) 30 $0.50

Limit'ler eski plana göre 5-10x daha cömert, çünkü maliyet o kadar düşük ki call sayısı sınırlamak yerine quality threshold'a (score, confidence) odaklanmak daha mantıklı.

Model Tier Routing Rules

Panel'den editlenebilir mapping:

Default: severity→tier mapping
  P0, P1 → pro
  P2, P3, INFO → flash
  Bundle (5+ sessions) → pro

Override examples:
  - "When daily_spent_usd > $2, force all calls to flash tier (no pro)"
  - "When monthly_spent_usd > $25, send alert"
  - "Off-peak (16:30-00:30 UTC) batch: route all P2/P3 to off-peak queue"

Provider Routing Settings

Primary Provider: [DeepSeek ▼]
Fallback Provider 1: [DeepSeek via OpenRouter ▼]
Fallback Provider 2: [Anthropic ▼]

DeepSeek API Key: [••••••••••••]  [Test Connection]
Anthropic API Key (fallback): [••••••••••••]
OpenRouter API Key (fallback): [••••••••••••]

Auto-failover threshold:
  Error rate > [20%] in last [5 minutes] → switch to Fallback 1
  Error rate > [50%] in last [5 minutes] → switch to Fallback 2

9.3 Cost Dashboard UI

Panel'de /insights/costs sayfası. Bileşenler:

Üst Bilgi Kartları

┌─────────────────┬─────────────────┬─────────────────┬─────────────────┐
│  Today          │  This Month     │  Avg per Insight│  Forecast EOM   │
│  $0.42          │  $8.75          │  $0.04          │  $24.50         │
│  ▓▓▓░░ 28%      │  ▓▓▓░░░░ 29%    │  ↓ 12% vs prev  │  Within budget  │
└─────────────────┴─────────────────┴─────────────────┴─────────────────┘

Provider Status:
🟢 DeepSeek (Primary)      99.2% uptime, 0% errors last 24h
⚪ DeepSeek/OpenRouter      Standby (fallback)
⚪ Anthropic Sonnet 4.6     Standby (fallback)

Grafikler

  • Daily Cost (last 30 days): Bar chart, USD; provider breakdown stacked
  • Token Usage (last 30 days): Stacked bar (cache_hit vs cache_miss vs output), per tier
  • Cache Hit Rate Trend: Line chart (target: > %60 with DeepSeek caching)
  • Cost per Insight Type: Pie chart
  • Cost per Severity: Bar chart
  • Off-peak Usage Ratio: Line chart (kaç % çağrı off-peak window'da)

Tablolar

  • Top 10 Most Expensive Insights: cost desc, expandable to see prompt+response
  • Provider Performance: per-provider error rate, latency, cache hit rate
  • Failed Calls Cost: retry maliyet eder, tracking

Kontrol Paneli

┌─────────────────────────────────────────────────┐
│ Budget Controls                                  │
├─────────────────────────────────────────────────┤
│ Monthly Cap:         [$30         ] [Save]      │
│ Daily Soft Cap:      [$1.50       ] [Save]      │
│ Daily Hard Cap:      [$3          ] [Save]      │
│                                                  │
│ Current State: 🟢 ACTIVE                         │
│ Provider: DeepSeek V4 (primary)                  │
│                                                  │
│ [PAUSE PIPELINE]  [EMERGENCY STOP]               │
│ [SWITCH TO FALLBACK]                             │
│                                                  │
│ ☑ Auto-pause non-P0 if daily > $2.50            │
│ ☑ Email alert at 80% monthly                    │
│ ☑ Telegram alert at 100% daily hard             │
│ ☑ Auto-switch to Anthropic if DS error >20%     │
│ ☐ Force off-peak only for P3/INFO               │
└─────────────────────────────────────────────────┘

Tier Routing Editor

Severity → Tier Mapping:
  P0  → [pro ▼]      (~$0.05-$0.20 per call)
  P1  → [pro ▼]      
  P2  → [flash ▼]    (~$0.005-$0.02 per call)
  P3  → [flash ▼]    
  INFO → [flash ▼]   

Pattern Bundle (5+ sessions) → [pro ▼]

[Save Changes]  [Reset Defaults]

9.4 Circuit Breakers

Pipeline'da otomatik koruyucu mekanizmalar:

Trigger Action
Daily soft cap reached ($1.50) Pro tier disabled, fallback to Flash for everything
Daily soft cap + 50% reached ($2.25) Flash continues only for P0/P1, P2/P3 paused
Daily hard cap reached ($3) All non-P0 paused, P0 queue continues
Monthly hard cap reached ($30) All LLM calls paused, pipeline halts at Katman 3
Per-call cost > max ($0.20) Job marked failed, manual review needed
DeepSeek error rate > 20% in 5min Auto-switch to Fallback provider
DeepSeek error rate > 50% in 5min Switch to Anthropic Sonnet fallback
Failure rate > 30% across all providers Pipeline paused, alert
Cost ledger anomaly (10x normal) Pipeline paused, alert
Off-peak window suddenly priced normally Auto-disable off-peak routing, alert

Her circuit breaker tetiklendiğinde:

  • Audit log'a yazılır
  • Telegram bildirim
  • Panel'de visible alert banner

9.5 Cache Stratejisi (DeepSeek-Optimized)

DeepSeek'in cache pricing'i (V4 Flash'ta cache-hit input %98 indirim) bu sistem için kritik kazanç. Cache hit rate'i yüksek tutmak için mimari kararlar:

DeepSeek Native Prompt Caching

DeepSeek otomatik prompt prefix caching yapar (manuel cache_control header'a gerek yok, otomatik). Mekanizma:

  • Cache TTL: ~5-15 dakika (DeepSeek docs net süre vermiyor, ampirik ölçülecek)
  • Cache hit determinasyonu: Prompt'un baştan tam karakter eşleşmesi gereken bir prefix var, o prefix cache'de mi?
  • Cache write fee yok (Anthropic'tan farklı olarak), sadece read discount
  • API response'unda prompt_cache_hit_tokens ve prompt_cache_miss_tokens ayrı dönüyor

Cache hit'i maksimize etmek için:

  1. System prompt struct order: SABIT prefix (template + Sase.tr context + JSON schema) → DEĞIŞKEN suffix (timeline). Stable prefix uzun olsun (1500-3000 token), çünkü cache discount oranda lineer.

  2. Worker concurrency tuning: Aynı tag'in worker'ları concurrent çalıştığında system prompt cache hit ediyor. 5 dakikalık batch window'da 10 call → 1 full + 9 cached = %95 input cost tasarrufu.

  3. Tag-based queue partitioning: Her tag tipi kendi BullMQ queue'sunda, aynı worker process'ler ardışık call yapar. Tag karışımı cache hit'i bozmaz.

Application-Level Fingerprint Cache (DeepSeek üstüne)

DeepSeek cache 15 dakika TTL ile sınırlı. Daha uzun süreli cache için panel kendi cache'i:

  • Aynı fingerprint için son insight 6 saatten yeniyse → LLM çağrılmaz, cached insight referansı verilir
  • Cache key: fingerprint + prompt_template_version
  • Storage: Redis (panel'in mevcut instance'ı)
  • TTL: 6 saat default, panel'den ayarlanabilir
  • Invalidation: Manual UI butonu + prompt template versiyonu değişince otomatik

Bundle Mode

3+ session'lık bundle 1 LLM call'a denk gelir. Pattern güçlendikçe maliyet kişi başı düşer:

  • 1 session @ 1500 token input = $0.21 (cache miss) → tek başına analiz
  • 5 session bundle @ 6000 token input = $0.84 (cache miss) → kişi başı $0.17, %19 tasarruf
  • Bundle aynı zamanda LLM'e daha güçlü pattern verir, output kalitesi yükselir

Off-Peak Batch Window (Opsiyonel, Phase 6e)

DeepSeek'in tarihi off-peak indirimi (16:30-00:30 UTC, %50-75) V4'te henüz teyit edilmedi. Phase 6e'de test edilir:

  • Düşük priority job'lar (P3, INFO, non-pattern) off-peak-queue'ya yazılır
  • BullMQ scheduled processor 16:30 UTC'de queue'yu drain etmeye başlar
  • Real-time karşılaştırma: aynı job'u peak'te ve off-peak'te çalıştır, fiyat farkını cost_ledger'a kaydet
  • Tasarruf > %30 ise default'a alınır, değilse devre dışı bırakılır

9.6 Maliyet Tahmini (Pilot için Aylık — DeepSeek)

Konservatif senaryo (Sase.tr pilot, DeepSeek V4 fiyatlarıyla):

60 session/gün × 30 gün = 1800 session/ay

Eliminasyon (Katman 1) sonrası: ~1800
Tag'siz arşivlenen: -540 (%30)
Bundle birleştirme: -300 (3-5x ortalama bundle)
Application cache hit (6h): -200 (%15)

Net LLM call: ~760/ay

Tier dağılımı:
  P0+P1 (pro):     ~150 call
  P2+P3+INFO (flash): ~560 call
  Pattern bundle (pro): ~50 call

DeepSeek native cache hit oranı (system prompt): %70 (worker concurrency ile)

Cost hesabı (V4 Pro 75% discount ile):
  Pro tier (200 call):
    Avg input cache_miss: 500 token × 200 × $0.435/M = $0.044
    Avg input cache_hit: 1500 token × 200 × $0.003625/M = $0.001
    Avg output: 600 token × 200 × $0.87/M = $0.104
    Pro subtotal: ~$0.15

  Flash tier (560 call):
    Avg input cache_miss: 500 token × 560 × $0.14/M = $0.039
    Avg input cache_hit: 1500 token × 560 × $0.0028/M = $0.002
    Avg output: 400 token × 560 × $0.28/M = $0.063
    Flash subtotal: ~$0.10

TOPLAM: ~$0.25/ay  ← evet, gerçek bu

Konservatif çarpan + overhead:
  Retry'lar, eval call'ları, debug call'ları: ×3
  
GERÇEKÇI AYLIK MALIYET: ~$1-3/ay (pilot fazında)

V4 Pro promo bittikten sonra (Haziran 2026 itibarıyla):

  • Pro tier fiyatı 4x'leniyor: $1.74 input cache miss / $3.48 output
  • Pro subtotal: ~$0.60
  • Toplam: ~$3-8/ay

Diğer projeler eklendiğinde (Phase 7-8):

  • 5 proje × 2x faktör (Sase.tr'den hacimli olabilirler) = ~$30-80/ay

Default monthly hard cap $30 bu yüzden geniş güvenlik marjı; gerçek kullanım büyük olasılıkla $5-15 civarı kalır.

Karşılaştırma: Anthropic Sonnet 4.6 olsaydı

  • Aynı volume için: ~$130-200/ay
  • DeepSeek'in 20-50x tasarrufu bu projenin economic viability'sini değiştirdi
  • Diğer projeleri eklemek ekonomik olarak çok daha kolay

9.7 Cost Reporting

Aylık raporlar:

  • En çok harcanan 10 fingerprint
  • Tag bazlı cost breakdown
  • Provider kullanım dağılımı (DeepSeek primary %, fallback %)
  • Saatlik dağılım (peak detection, off-peak window kullanımı)
  • Cache hit rate trend (DeepSeek native + application-level)
  • "Cost per actioned insight" (toplam cost / GitHub issue açılan insight sayısı) — efficiency metriği
  • DeepSeek vs Anthropic comparison (eğer fallback aktif olduysa)

10. Insight Storage & Triage

10.1 Insight Data Model

type Insight = {
  id: string;
  project_key: 'sase';
  type: 'bug' | 'ux_friction' | 'feature_request' | 'performance' | 'copy_fix' | 'onboarding' | 'conversion' | 'pattern';
  severity: 'P0' | 'P1' | 'P2' | 'P3' | 'INFO';
  status: InsightStatus;
  fingerprint: string;
  title: string;
  body: object;                       // LLM JSON output (schema-validated)
  related_session_ids: string[];
  occurrence_count: number;           // bu fingerprint kaç session'da görüldü
  unique_user_count: number;
  first_seen_at: Date;
  last_seen_at: Date;
  confidence: number;
  source_prompt_template_id: string;
  source_prompt_version: number;
  source_model: string;
  source_cost_usd: number;
  
  // Action tracking
  github_issue_url: string | null;
  github_issue_id: number | null;
  github_issue_state: 'open' | 'closed' | null;
  shipped_at: Date | null;
  
  // Validation
  validation_started_at: Date | null;
  validation_period_days: number;
  regression_detected: boolean;
  validated_at: Date | null;
  
  // Manual overrides
  founder_notes: string | null;
  founder_severity_override: string | null;
  founder_priority: number | null;
  
  created_at: Date;
  updated_at: Date;
}

type InsightStatus = 
  | 'new'              // henüz triage edilmemiş
  | 'triaged'          // bakıldı, henüz aksiyon yok
  | 'in_backlog'       // GitHub issue açıldı
  | 'in_progress'      // PR var
  | 'shipped'          // merge edildi
  | 'validating'       // shipped, regression bekleniyor
  | 'validated'        // pattern düştü, başarılı
  | 'regressed'        // pattern devam ediyor
  | 'deferred'         // ileride
  | 'dismissed'        // alakasız, false positive
  | 'duplicate'        // başka insight'a merge edildi

10.2 Dedupe & Fingerprint Grouping

Yeni insight oluştuğunda:

1. Yeni insight'ın fingerprint'i hesaplanır (Bölüm 7.6)
2. Existing insights tablosunda aynı fingerprint var mı?
   - Yok: yeni insight olarak insert
   - Var:
     - Existing insight status = 'shipped', 'validated', 'dismissed' ise:
       → yeni insight oluştur, "potential_regression" flag ile
     - Existing status = 'in_progress', 'in_backlog' ise:
       → yeni insight yaratma, existing.occurrence_count++ , last_seen_at update
       → related_session_ids array'ine yeni session_id eklenir
     - Existing status = 'new', 'triaged', 'deferred' ise:
       → yeni insight yaratma, occurrence_count++, score güncellenir

10.3 Priority Calculation (Auto-sorting)

Insight inbox'ta default sort:

priority_score = (
  severity_weight * 30 +
  occurrence_weight * 25 +
  recency_weight * 15 +
  user_impact_weight * 15 +
  confidence * 10 +
  business_critical_path_bonus * 5
)

severity_weight: P0=1.0, P1=0.8, P2=0.5, P3=0.3, INFO=0.1
occurrence_weight: log10(occurrence_count + 1) / 2  (1=0.15, 10=0.5, 100=1.0)
recency_weight: 1.0 if last_seen_at < 1h, decays exponentially
user_impact_weight: unique_user_count / total_active_users
confidence: LLM çıktısından (0-1)
business_critical_path_bonus: VIN lookup, signup, payment yolundaysa +1

Founder elle priority override edebilir; founder_priority set edilirse otomatik sıralamayı bypass eder.

10.4 Pattern Aggregation

Birden çok insight aynı root cause'a işaret edebilir. Pattern aggregation:

  • Aynı affected_route + aynı tag → grup
  • Aynı error_signature (normalized) → grup
  • Cross-fingerprint cluster (LLM embedding similarity) — Phase 6e'de eklenir

Pattern UI'da görünür:

🔴 Pattern: VIN lookup 500 errors (PL24)
   12 insights, 8 unique users, last 5 days
   ├── Insight #142: rage click on retry
   ├── Insight #156: workaround attempt
   ├── Insight #178: provider switch (PCAT) successful
   └── ... 9 more
   
   [Create Master Issue] [View All Sessions] [Mark Pattern Resolved]

11. Action Loop (Insight → Issue → Validation)

11.1 GitHub Integration

Auth

GitHub App veya Personal Access Token (panel settings'te):

  • Read/write issues
  • Read repos (file map için)
  • Repository scope sınırlı (sadece sase.tr repo'su)

Issue Creation Flow

Insight detail page'inde "Create GitHub Issue" butonu:

Workflow:
1. Founder "Create Issue" tıklar
2. Panel openModal:
   - Title (LLM'in title'ı, editlenebilir)
   - Body (LLM body + session evidence linkleri, editlenebilir)
   - Labels suggested:
     - 'insight-driven'
     - severity-{P0,P1,P2,P3}
     - type-{bug,ux,feature,perf}
     - 'sase-pilot' (track pilot insight'larını)
   - Assignee: self (founder)
   - Milestone: optional
3. Founder confirm → GitHub API call
4. Issue oluştu, panel insight.github_issue_url set
5. insight.status = 'in_backlog'
6. Webhook config: GitHub issue close → panel update

Issue Template

## Bağlam (Insight-Driven)

Bu issue Süper Panel Behavioral Insight Pipeline tarafından üretildi.
- Insight ID: #142
- Tag: bug_suspected
- Severity: P1
- Pattern Occurrences: 7 sessions, 4 unique users
- First Seen: 2026-05-10
- Last Seen: 2026-05-13
- AI Confidence: 0.87
- Model: claude-sonnet-4.6

## Reproduce Steps (AI-extracted)

1. Login as authenticated user
2. Navigate to /vin-lookup
3. Enter a valid VIN (provider PL24 default)
4. Click "Sorgula"
5. Observe 500 response from /api/v1/vin-lookup

## Affected Component (Hypothesis)

- Route: `/vin-lookup`
- Backend: VinLookupController, PL24Provider
- Likely cause: Upstream PL24 timeout, frontend error handling silent

## User Behavior Observed

- 86% of affected users retry 2-5 times before giving up
- 43% try workaround via /history
- 0% complete lookup on first attempt with PL24

## Evidence

- Session #s_abc123 (representative): [View Timeline](https://sp.semih.ai/insights/sessions/s_abc123)
- All affected sessions: [Filter View](https://sp.semih.ai/insights/142/sessions)

## Suggested Investigation

1. Check PL24 API health/timeout config
2. Review error handling in VinLookupController
3. Add error toast for 500 responses
4. Consider auto-fallback to next provider on PL24 timeout

## Definition of Done

- [ ] Fix deployed
- [ ] Validation period (14 days) clean (no similar pattern)

---
*Tracking: insight #142, panel link: https://sp.semih.ai/insights/142*

11.2 Status Tracking

GitHub webhook events panel'de işlenir:

GitHub Event Panel Action
issue.opened insight.status = 'in_backlog' (already done from creation)
pull_request linked to issue insight.status = 'in_progress'
issue.closed insight.status = 'shipped', validation_started_at = now()
issue.reopened insight.status = 'in_progress'

11.3 Validation Period

Issue close olduktan sonra:

validation_period_days = 14 (configurable)

For 14 days:
  Daily check (cron):
    new_sessions = sessions_meta.where(
      fingerprint == insight.fingerprint,
      created_at > insight.shipped_at
    )
    
    if new_sessions.count >= 3:
      insight.status = 'regressed'
      Alert founder
      Auto-open GitHub issue: "Regression: <original title>"
    
After 14 days:
  if no regression:
    insight.status = 'validated'
    insight.validated_at = now()
    Update success metrics

11.4 Bulk Operations

Founder bulk action:

  • Multiple insights → dismiss (false positive cleanup)
  • Multiple insights → defer (low priority week)
  • Multiple insights → merge as pattern

12. UI / UX

12.1 Route Hiyerarşisi (Süper Panel içinde)

/insights                          — Inbox (default route)
/insights/inbox                    — Alias
/insights/all                      — Tüm insights (history view)
/insights/[id]                     — Single insight detail
/insights/[id]/sessions            — Insight'ın bağlı session'ları
/insights/sessions/[session_id]    — Session timeline viewer
/insights/patterns                 — Pattern view (cross-insight)
/insights/patterns/[fingerprint]   — Specific pattern detail
/insights/costs                    — Cost dashboard (Bölüm 9.3)
/insights/settings                 — Budget, prompts, model tier config
/insights/settings/prompts         — Prompt template editor
/insights/settings/prompts/[id]    — Single template
/insights/settings/eval-sets       — Eval set management
/insights/settings/budgets         — Cost configuration

12.2 Inbox UI

Ana çalışma alanı. shadcn block önerileri: sidebar-07 + custom inbox layout.

Layout

┌────────────────────────────────────────────────────────────────────┐
│ Header: Sase.tr Insights        [🔍 Cmd+K]  [Cost: $4.23 today]   │
├──────────┬─────────────────────────────────────────────────────────┤
│ Sidebar  │  Filter Bar: [Severity ▼] [Type ▼] [Status ▼] [Date ▼]  │
│          ├─────────────────────────────────────────────────────────┤
│ - Inbox  │  Insight List (sortable)                                │
│   (24)   │  ┌────────────────────────────────────────────────┐    │
│ - All    │  │ 🔴 P1 BUG  VIN lookup 500 (PL24)              │    │
│ - Pat.   │  │ 12 occurrences · 8 users · 2h ago · conf 0.87 │    │
│ - Costs  │  │ Auto-fingerprinted bug pattern                 │    │
│ - Sttgs  │  └────────────────────────────────────────────────┘    │
│          │  ┌────────────────────────────────────────────────┐    │
│ Filters  │  │ 🟡 P2 UX   Form abandonment on /api-keys      │    │
│ - P0 (0) │  │ 5 occurrences · 5 users · 6h ago · conf 0.72  │    │
│ - P1 (3) │  └────────────────────────────────────────────────┘    │
│ - P2 (9) │  ...                                                    │
│ - P3 (12)│                                                          │
└──────────┴─────────────────────────────────────────────────────────┘

Keyboard Shortcuts

  • j/k — next/prev insight
  • Enter — open detail
  • a — act (create GH issue)
  • d — dismiss
  • e — defer
  • m — mark as duplicate
  • Cmd+K — global search/command palette
  • ? — shortcut help

Cmd+K Command Palette

Hızlı navigasyon ve aksiyon:

  • "Show only bugs"
  • "Filter by route: /vin-lookup"
  • "Find sessions with rage click"
  • "Open costs dashboard"
  • "Create issue for #142"

12.3 Insight Detail UI

┌────────────────────────────────────────────────────────────────────┐
│ ← Back to Inbox                                                     │
├────────────────────────────────────────────────────────────────────┤
│ 🔴 P1 BUG · VIN lookup 500 (PL24)                                  │
│ 12 occurrences · 8 unique users · First seen 3 days ago            │
│                                                                     │
│ [Create GitHub Issue]  [Dismiss]  [Defer]  [Mark Duplicate]        │
├────────────────────────────────────────────────────────────────────┤
│ Tabs: [Summary] [Sessions (12)] [Raw AI Output] [Cost Detail]      │
├────────────────────────────────────────────────────────────────────┤
│ Summary Tab:                                                        │
│                                                                     │
│   📍 Affected Route: /vin-lookup                                   │
│   🎯 Suggested Component: VinLookupController                       │
│   🔍 Error Signature: Cannot read property 'parts' of undefined    │
│   💡 AI Hypothesis: PL24 provider timeout cascade...               │
│   ⚙ Suggested Fix Effort: M                                        │
│   🎲 Confidence: 0.87                                              │
│                                                                     │
│   Reproduce Steps:                                                  │
│   1. Login as authenticated user                                    │
│   2. Navigate to /vin-lookup                                        │
│   3. ...                                                            │
│                                                                     │
│   Suggested Investigation:                                          │
│   - Check PL24 API health/timeout                                  │
│   - Review error handling                                           │
│   - ...                                                             │
│                                                                     │
│   Founder Notes:                                                    │
│   [────────────────────────────────────────────────]              │
└────────────────────────────────────────────────────────────────────┘

Sessions Tab

Bu insight'a bağlı tüm session'ların listesi, her birine drill-down link.

Raw AI Output Tab

JSON output gösterimi, copy butonu (debug için).

Cost Detail Tab

Model: claude-sonnet-4.6
Prompt Template: bug_triage v3
Input Tokens: 1,240 ($0.0037)
Output Tokens: 380 ($0.0057)
Cache Read: 0
Total Cost: $0.0094
Call Duration: 2.4s
Retry Count: 0

12.4 Session Timeline Viewer

Compressed timeline'ı human-readable şekilde gösterir:

┌────────────────────────────────────────────────────────────────────┐
│ Session s_abc123                                                    │
│ user_segment: authenticated, tier=brand_specific, signup_days_ago=4 │
│ device: macOS Chrome 138 · 1920x1080                                │
│ duration: 4m12s                                                     │
│                                                                     │
│ [Open in PostHog] [View Raw Snapshot]                              │
├────────────────────────────────────────────────────────────────────┤
│                                                                     │
│ Timeline:                                                           │
│                                                                     │
│  00:00 📄 page_load /vin-lookup (lcp=1.2s)                         │
│  00:03 🖱 click [button:"Sorgula"]                                  │
│  00:04 ⌨ input [field:"vin"] (sanitized)                           │
│  00:05 🖱 click [button:"Sorgula"]                                  │
│  00:07 🌐 POST /api/v1/vin-lookup → ❌ 500                          │
│  00:07 ⚠ console_error                                              │
│  00:10 🔁 click [button:"Sorgula"] · RETRY                          │
│  00:13 🌐 POST /api/v1/vin-lookup → ❌ 500                          │
│  00:13 😡 rage_click (3 in 1.2s)                                    │
│  00:18 🔀 navigation /history · WORKAROUND                          │
│  ...                                                                │
│                                                                     │
│ Key Events:                                                         │
│  • 2x /api/v1/vin-lookup 500 errors                                │
│  • 1x console error                                                │
│  • 1x rage click (Sorgula)                                         │
│  • Conversion: ❌ none                                              │
└────────────────────────────────────────────────────────────────────┘

12.5 Daily Brief (Bonus Feature)

Her sabah 08:00, panel ana sayfasında:

┌────────────────────────────────────────────────────────────────────┐
│ 🌅 Günaydın · 13 Mayıs 2026                                        │
├────────────────────────────────────────────────────────────────────┤
│ Dün gece pipeline:                                                  │
│  • 47 session işlendi                                              │
│  • 18 insight üretildi (3 P1, 7 P2, 8 P3)                          │
│  • Maliyet: $3.40                                                  │
│  • Cache hit: %22                                                  │
│                                                                     │
│ Bugünkü öncelikler:                                                │
│  1. 🔴 P1 yeni: VIN lookup 500 (12. tekrar) → [Aksiyon Al]         │
│  2. 🟡 Yeni pattern: /api-keys form abandonment (5 user)            │
│  3. ✅ #134 validation tamamlandı, regression yok                   │
│                                                                     │
│ 📊 Bu hafta:                                                       │
│  • 5 shipped insight (geçen hafta 3)                               │
│  • Cost per shipped insight: $4.20 (geçen hafta $5.10)              │
└────────────────────────────────────────────────────────────────────┘

Telegram/email gönderim opsiyonel.


13. Veri Modeli

13.1 Yeni Tablolar (Panel PostgreSQL)

-- Bölüm 5'te tanımlı
CREATE TABLE sessions_meta (
  id TEXT PRIMARY KEY,
  project_key TEXT NOT NULL,
  user_id_hash TEXT,
  is_authenticated BOOLEAN NOT NULL,
  subscription_tier TEXT,
  started_at TIMESTAMPTZ NOT NULL,
  duration_ms INTEGER NOT NULL,
  pageview_count INTEGER DEFAULT 0,
  click_count INTEGER DEFAULT 0,
  error_count INTEGER DEFAULT 0,
  rage_click_count INTEGER DEFAULT 0,
  dead_click_count INTEGER DEFAULT 0,
  network_5xx_count INTEGER DEFAULT 0,
  network_4xx_count INTEGER DEFAULT 0,
  promotion_reasons TEXT[],
  tags TEXT[],
  severity TEXT,
  score INTEGER,
  raw_metadata_url TEXT,
  status TEXT NOT NULL DEFAULT 'pending_signal',
  fingerprint TEXT,
  processed_at TIMESTAMPTZ,
  created_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX idx_sessions_meta_status ON sessions_meta(status, created_at);
CREATE INDEX idx_sessions_meta_fingerprint ON sessions_meta(fingerprint);
CREATE INDEX idx_sessions_meta_project_status ON sessions_meta(project_key, status);
CREATE INDEX idx_sessions_meta_user ON sessions_meta(user_id_hash, started_at);

-- Compressed sessions metadata (Bölüm 7.7)
CREATE TABLE compressed_sessions (
  session_id TEXT PRIMARY KEY REFERENCES sessions_meta(id),
  fingerprint TEXT NOT NULL,
  semantic_timeline_minio_key TEXT NOT NULL,
  token_count_input INTEGER NOT NULL,
  token_count_estimate_output INTEGER NOT NULL,
  compression_ratio NUMERIC(10,2),
  sanitization_match_count INTEGER DEFAULT 0,
  sanitization_breakdown JSONB,
  is_bundle BOOLEAN DEFAULT FALSE,
  bundle_session_ids TEXT[],
  ready_for_analysis_at TIMESTAMPTZ DEFAULT NOW(),
  created_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX idx_compressed_fingerprint ON compressed_sessions(fingerprint);

-- Insights (Bölüm 10.1)
CREATE TABLE insights (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  project_key TEXT NOT NULL,
  type TEXT NOT NULL,
  severity TEXT NOT NULL,
  status TEXT NOT NULL DEFAULT 'new',
  fingerprint TEXT NOT NULL,
  title TEXT NOT NULL,
  body JSONB NOT NULL,
  related_session_ids TEXT[] NOT NULL,
  occurrence_count INTEGER DEFAULT 1,
  unique_user_count INTEGER DEFAULT 1,
  first_seen_at TIMESTAMPTZ NOT NULL,
  last_seen_at TIMESTAMPTZ NOT NULL,
  confidence NUMERIC(3,2),
  source_prompt_template_id TEXT,
  source_prompt_version INTEGER,
  source_model TEXT,
  source_cost_usd NUMERIC(10,6),
  github_issue_url TEXT,
  github_issue_id BIGINT,
  github_issue_state TEXT,
  shipped_at TIMESTAMPTZ,
  validation_started_at TIMESTAMPTZ,
  validation_period_days INTEGER DEFAULT 14,
  regression_detected BOOLEAN DEFAULT FALSE,
  validated_at TIMESTAMPTZ,
  founder_notes TEXT,
  founder_severity_override TEXT,
  founder_priority INTEGER,
  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX idx_insights_status ON insights(status, project_key);
CREATE INDEX idx_insights_fingerprint ON insights(fingerprint);
CREATE INDEX idx_insights_severity ON insights(severity, status);
CREATE INDEX idx_insights_last_seen ON insights(last_seen_at DESC);
CREATE UNIQUE INDEX idx_insights_active_fingerprint 
  ON insights(project_key, fingerprint) 
  WHERE status NOT IN ('dismissed', 'validated');

-- Cost ledger (Bölüm 9.1)
CREATE TABLE cost_ledger (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  insight_id UUID REFERENCES insights(id),
  project_key TEXT NOT NULL,
  prompt_template_id TEXT,
  prompt_version INTEGER,
  model TEXT NOT NULL,
  tier TEXT NOT NULL,
  tokens_input INTEGER NOT NULL,
  tokens_output INTEGER NOT NULL,
  tokens_cache_read INTEGER DEFAULT 0,
  tokens_cache_write INTEGER DEFAULT 0,
  cost_input_usd NUMERIC(10,6) NOT NULL,
  cost_output_usd NUMERIC(10,6) NOT NULL,
  cost_cache_usd NUMERIC(10,6) DEFAULT 0,
  cost_total_usd NUMERIC(10,6) NOT NULL,
  call_duration_ms INTEGER,
  was_cached BOOLEAN DEFAULT FALSE,
  was_retry BOOLEAN DEFAULT FALSE,
  created_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX idx_cost_ledger_date ON cost_ledger(created_at);
CREATE INDEX idx_cost_ledger_project_date ON cost_ledger(project_key, created_at);
CREATE INDEX idx_cost_ledger_insight ON cost_ledger(insight_id);

-- Budget settings (Bölüm 9.2)
CREATE TABLE budget_settings (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  project_key TEXT,  -- null = global
  setting_key TEXT NOT NULL,
  setting_value JSONB NOT NULL,
  updated_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE UNIQUE INDEX idx_budget_settings_unique 
  ON budget_settings(COALESCE(project_key, ''), setting_key);

-- Prompt templates (Bölüm 8.1)
CREATE TABLE prompt_templates (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tag TEXT NOT NULL,
  version INTEGER NOT NULL,
  name TEXT NOT NULL,
  system_prompt TEXT NOT NULL,
  user_prompt_template TEXT NOT NULL,
  output_schema_json JSONB NOT NULL,
  model_tier TEXT NOT NULL,
  max_output_tokens INTEGER DEFAULT 2000,
  temperature NUMERIC(3,2) DEFAULT 0.3,
  active BOOLEAN DEFAULT TRUE,
  created_at TIMESTAMPTZ DEFAULT NOW(),
  performance_stats JSONB DEFAULT '{}'::jsonb
);

CREATE UNIQUE INDEX idx_prompt_templates_active 
  ON prompt_templates(tag, version);

-- Eval sets (Bölüm 8.5)
CREATE TABLE eval_sets (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  prompt_tag TEXT NOT NULL,
  name TEXT NOT NULL,
  cases JSONB NOT NULL,  -- array of {session_timeline, expected_output, rubric}
  created_at TIMESTAMPTZ DEFAULT NOW()
);

-- Ingestion watermarks
CREATE TABLE ingestion_watermarks (
  project_key TEXT PRIMARY KEY,
  last_polled_at TIMESTAMPTZ NOT NULL,
  posthog_cursor TEXT,
  updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- Audit log (Süper Panel'in mevcut audit_log'una append)
-- Bu PRD'de yeni tablo değil, mevcut audit_log'a 'insight_*' action_type'ları eklenir

13.2 Materialized Views

-- Daily cost summary (cron refresh)
CREATE MATERIALIZED VIEW mv_daily_insight_cost AS
SELECT 
  date_trunc('day', created_at) AS day,
  project_key,
  tier,
  COUNT(*) AS call_count,
  SUM(tokens_input) AS total_input_tokens,
  SUM(tokens_output) AS total_output_tokens,
  SUM(cost_total_usd) AS total_cost
FROM cost_ledger
GROUP BY day, project_key, tier;

-- Insight efficiency
CREATE MATERIALIZED VIEW mv_insight_efficiency AS
SELECT 
  date_trunc('week', i.created_at) AS week,
  i.project_key,
  COUNT(*) AS total_insights,
  COUNT(*) FILTER (WHERE i.github_issue_url IS NOT NULL) AS actioned,
  COUNT(*) FILTER (WHERE i.status = 'shipped') AS shipped,
  COUNT(*) FILTER (WHERE i.status = 'validated') AS validated,
  COUNT(*) FILTER (WHERE i.status = 'dismissed') AS dismissed,
  SUM(i.source_cost_usd) AS total_cost,
  SUM(i.source_cost_usd) FILTER (WHERE i.status = 'shipped') / NULLIF(COUNT(*) FILTER (WHERE i.status = 'shipped'), 0) AS cost_per_shipped
FROM insights i
GROUP BY week, project_key;

Refresh nightly via BullMQ scheduled job.


14. Konfigürasyon Sistemi

14.1 Settings Hiyerarşisi

Global Settings (panel-wide)
  └── Project Settings (Sase.tr override)
        └── Tag Settings (per-tag override)
              └── Runtime Settings (panel UI'dan anlık)

14.2 Editable Configurations

Tüm config panel UI üzerinden değişebilir; restart gerektirmez (hot reload via DB poll).

Budget Settings

  • Monthly hard cap
  • Daily soft/hard cap
  • Per-call max
  • Per-tag daily limits
  • Severity → Tier mapping
  • Sample rates (anonymous baseline)

Filtering Thresholds

  • Min session duration
  • Max session duration
  • Bot UA list
  • Internal IP allowlist (skip)
  • Promote criteria toggles

Compression Settings

  • PII regex patterns (Sase.tr-specific eklenebilir)
  • Max timeline tokens (split threshold)
  • Include/exclude event types

LLM Settings

  • API key (Anthropic veya OpenRouter)
  • Default model per tier
  • Temperature per prompt
  • Retry policy

GitHub Integration

  • Repo allowlist
  • Default labels
  • Default assignee
  • Issue template override

14.3 Config Versioning

Önemli config değişiklikleri audit log'a:

  • Kim değiştirdi
  • Eski değer → yeni değer
  • Timestamp

Tehlikeli config'ler (örn. monthly cap düşürme, prompt template aktivasyonu) confirmation modal ile.


15. Privacy, KVKK ve Veri Güvenliği

15.1 PostHog SDK Konfigürasyonu (Sase.tr Tarafı)

Sase.tr frontend'inde PostHog init'i güncellenir:

posthog.init(POSTHOG_KEY, {
  api_host: 'https://posthog.semih.ai',
  
  // Session recording
  session_recording: {
    maskAllInputs: true,           // tüm input default mask
    maskInputOptions: {
      password: true,
      email: false,                // email maskleme compression'da
      tel: true,
      number: false,
    },
    maskTextSelector: '[data-private], .sensitive',  // CSS-based mask
    blockSelector: '[data-block]',                   // tamamen kayıt edilmez
    blockClass: 'rrweb-block',
    ignoreClass: 'rrweb-ignore',
    
    // Network
    recordNetworkPayloads: false,  // payload yok, sadece metadata
    recordHeaders: false,           // auth header asla
  },
  
  // PII
  property_denylist: ['$ip', 'email', 'phone', 'vin'],
  
  // Cookieless mode for anonymous
  persistence: 'localStorage',
  
  // GDPR/KVKK
  opt_out_capturing_by_default: false,  // explicit consent flow ayrı
})

Sase.tr UI'da data-private Etiketleme

Sensitive content'i taşıyan tüm component'ler:

<Input data-private name="vin" ... />
<div data-private>{user.email}</div>
<div data-private>{user.phoneNumber}</div>
<TableCell data-private>{customer.taxNumber}</TableCell>

Bu Sase.tr tarafında ayrı bir checklist olarak iletilir, PR template'ine eklenir ("data-private kontrol edildi mi?").

15.2 Compression Tarafı (İkinci Savunma Hattı)

Bölüm 7.4'teki sanitization rules, kaynak (PostHog) mask'i bypass etse bile yedek savunma sağlar.

15.3 Veri Saklama (Retention)

Veri Türü Saklama Süresi Sonra
PostHog raw recordings PostHog'un kendi config'i (30 gün default) PostHog siler
sessions_meta (panel) 90 gün Silinir
Raw metadata (MinIO) 30 gün Silinir
Compressed timelines (MinIO) 180 gün Silinir
Insights (panel) Sınırsız (silmemek için audit value)
Cost ledger Sınırsız
Audit log 7 yıl Cold storage'a taşınır

Retention BullMQ cron job ile günlük çalışır.

15.4 Kullanıcı Hakları (KVKK Madde 11)

KVKK'ya göre kullanıcı talepleri:

  • Veri silme talebi: Sase.tr admin'i kullanıcının user_id'sini panel'e bildirir. Panel:

    • sessions_meta'da user_id_hash matching tüm kayıtları siler
    • compressed_sessions MinIO key'leri siler
    • insights'tan related_session_ids array'lerinden çıkarır (insight kalır ama session referansı silinir)
    • Audit log'a "right_to_erasure_executed" kaydı
  • Veri taşıma talebi: User'a ait tüm panel verisi JSON export'u alınır

15.5 Veri Erişim Kontrolü

  • Tek kullanıcı (founder), Better Auth + TOTP
  • Cloudflare Access ek katman
  • Tüm panel DB query'leri parametrize edilir (SQL injection koruması Prisma ile zaten var)
  • MinIO erişimi: presigned URL, max 15 dakika TTL

15.6 LLM Provider Veri Politikası (DeepSeek + Fallback)

Primary: DeepSeek API

Veri konumu uyarısı: DeepSeek altyapısı Çin'de yer alıyor (Hangzhou-based). KVKK Madde 9 kapsamında yurtdışına veri aktarımı olarak değerlendirilir. Bu konuda alınacak önlemler:

  1. Sıkı PII sanitization: Bölüm 7.4'teki iki katmanlı (kaynak + compression) sanitization MİNİMUM standarttır. Şüpheli durumlarda compression'da extra "aggressive mode" — VIN'leri tamamen [VIN_REDACTED] yap, email'i tamamen [EMAIL_REDACTED]. Cache hit oranını düşürür ama güvenlik kazanır.

  2. Sanitization audit zorunlu: Her LLM call'ı öncesi sanitization match count log'lanır. Sıfır match ama büyük token sayısı varsa call iptal edilir, founder alert alır.

  3. Aydınlatma metni güncelleme: Sase.tr KVKK aydınlatma metni "AI-destekli ürün geliştirme analizi" maddesi eklenir; üçüncü taraf işleyici olarak DeepSeek belirtilir.

  4. Önemli sınırlama: Hassas kategori veri (sağlık, etnik köken, biyometrik, vb.) kesinlikle pipeline'a girmez. Sase.tr B2B context'inde bu zaten beklenmiyor ama sanitization kuralları olası leak'leri yakalayacak şekilde tasarlanır.

  5. DeepSeek Privacy Policy değerlendirmesi: DeepSeek API verisi model training'de kullanmadığınııkça belirtmeli. Eğer bu garanti yoksa OpenRouter veya alternatif provider kullanımı zorunlu olur (US/EU based).

Fallback Provider Politikaları

OpenRouter (Fallback 1):

  • Edge: US/EU PoP'lar
  • Privacy: OpenRouter'ın kendi privacy policy + underlying provider'ın policy'si geçerli
  • DeepSeek route üzerinden olsa bile request'ler genelde OpenRouter'ın edge'inden DeepSeek'e gider; veri transfer chain daha uzun ama EU'dan başlar

Anthropic (Fallback 2):

  • Veri konumu: US (AWS)
  • Anthropic Zero Data Retention enable edilmeli (Anthropic ile DPA imzalanır)
  • Avrupa'dan US'e veri transferi için SCC (Standart Sözleşmesel Hükümler) gerekli

Provider Geçiş Senaryosu

Eğer pilot sırasında DeepSeek için:

  • Privacy garantisi yeterli bulunmazsa
  • Latency Türkiye'den >2s P95 olursa
  • Quality eval'da %85 threshold tutmazsa

→ Anthropic primary'ye geçiş. Bu durumda budget cap'leri 10x artırmak gerekir (~$300/ay). Karar audit log'una yazılır.

Veri Akışı Diagramı (Privacy Perspective)

[Sase.tr User Browser]
        │ Session recording (rrweb)
        │ NOT: Sensitive fields data-private ile masked
        ▼
[PostHog Cloud EU]
        │ Stored encrypted, EU region
        │ Retention: 30 days (panel ingest'ten sonra silinir)
        ▼
[Panel Ingestion Worker] ← Hetzner FSN (Almanya)
        │ Heuristic filter, %95 elendi
        ▼
[Panel Compression Worker] ← Hetzner FSN
        │ İkinci katman PII sanitization
        │ Audit: kaç PII match'lendi loglandı
        ▼
[Panel LLM Worker] ← Hetzner FSN
        │ Sanitization audit: > 0 match olmuşsa veya 
        │ token > X iken match=0 ise alert + abort
        │
        ▼ HTTPS, TLS 1.3
[DeepSeek API] ← Hangzhou, China
        │ Request: sanitized timeline only
        │ Response: JSON insight
        ▼
[Panel LLM Worker]
        │ JSON validation, insight oluştur
        ▼
[Panel PostgreSQL] ← Hetzner FSN
        │ Insight + cost ledger persisted EU

Bu diagramda Çin'e giden veri sadece sanitized semantic timeline. PII içermez. Insight kendisi Panel DB'de EU'da kalır.


16. Observability ve Operations

16.1 Pipeline Metrics

Her worker job'ı şu metrikleri yazar (OpenObserve'a):

pipeline.posthog_ingest.duration_ms
pipeline.posthog_ingest.sessions_fetched
pipeline.posthog_ingest.sessions_promoted
pipeline.posthog_ingest.sessions_discarded
pipeline.posthog_ingest.api_errors

pipeline.tagging.duration_ms
pipeline.tagging.sessions_tagged
pipeline.tagging.tag_distribution{tag=...}

pipeline.compression.duration_ms
pipeline.compression.input_bytes
pipeline.compression.output_tokens
pipeline.compression.compression_ratio
pipeline.compression.sanitization_matches

pipeline.llm.duration_ms
pipeline.llm.calls_total
pipeline.llm.input_tokens
pipeline.llm.output_tokens
pipeline.llm.cost_usd
pipeline.llm.cache_hit_rate
pipeline.llm.validation_failures
pipeline.llm.errors_by_type{type=...}

pipeline.insights.created
pipeline.insights.actioned
pipeline.insights.shipped
pipeline.insights.validated
pipeline.insights.regressed
pipeline.insights.dismissed

16.2 Alert Rules

Telegram/email alerts:

Trigger Severity Action
Daily cost > soft cap Info Notification only
Daily cost > hard cap Critical Auto-pause, immediate notify
Monthly cost > 80% Warning Daily reminder
PostHog ingestion error rate > 10% Warning Investigation needed
LLM error rate > 20% Warning Investigation
LLM error rate > 50% Critical Auto-pause LLM stage
Sanitization 0 matches but >1000 tokens Critical Possible PII leak risk
P0 insight created Info Immediate notify
Regression detected Warning Daily summary
BullMQ queue depth > 1000 Warning Backpressure investigation

16.3 Dashboards

OpenObserve'da pipeline dashboard:

  • Hourly throughput (sessions → insights)
  • Cost trend
  • Error rate by stage
  • Latency P50/P95/P99 by stage
  • Queue depths
  • Cache hit rates

16.4 Runbook (Acil Durum Senaryoları)

Önemli runbook'lar (panel docs sayfasında):

  1. "PostHog tamamen erişilemez": Watermark donmuştur, manual replay nasıl yapılır
  2. "LLM provider down": Tier fallback'i nasıl çalışır, manual model switch
  3. "Cost cap aşıldı": Nasıl reset edilir, beklemeden tekrar açmak için
  4. "PII leak şüphesi": Audit query nasıl yapılır, ilgili insight'ları nasıl purge edilir
  5. "Founder TOTP kaybı": Recovery flow, Cloudflare Access fallback

17. Faz Planı

Phase 0 — Sase.tr Event Prep (Pilot Prerequisite, BIP Phase 6a'yı bloklar)

Süre: 2 gün (Sase.tr-side work) Referans: sase-posthog-events-prd.md Bölüm 9, Faz 0

Bu faz Sase.tr tarafındadır, panel tarafı bekler. Tamamlanmadan Phase 6a başlatılamaz.

Gün 1

  • posthog.identify() audit + user properties schema implementation
  • posthog.group('company') çağrısı ekleme
  • posthog.alias() signup flow'a entegrasyon
  • data-private audit ve attribute eklemeleri
  • PostHog SDK config update (EU region, mask config)

Gün 2

  • 5 critical parts/compatibility event'i ekleme
  • Existing oem_code_copied zenginleştirme
  • docs/posthog-events.md documentation
  • PR review + production deploy

Çıkış kriteri:

  • Tüm authenticated session'lar identify + group ile gelir
  • Parts layer event'leri PostHog'da görünür
  • rrweb recording'lerde VIN/email masked
  • KVKK aydınlatma metni güncel

Phase 6a — Ingestion + Filter + Compression (Pilot Foundation)

Süre: 3 hafta Paralel work: Sase.tr'de sase-posthog-events-prd.md Faz 1 (5-7 gün, BIP Phase 6a Hafta 1-2 boyunca)

Hafta 1

  • PostHog API entegrasyonu (poller, watermark)
  • sessions_meta tablosu, BullMQ queue
  • Heuristic filter rules
  • Custom events fetch endpoint integration (Bölüm 5.5)
  • posthog_person_cache ve posthog_group_cache tabloları

Hafta 2

  • Signal detection (tagging) layer
  • Custom event tabanlı tag rules (Bölüm 6.2)
  • Tagging eval set (manuel 20 case, custom event dahil)
  • User properties + group properties enrichment

Hafta 3

  • Semantic compression algoritması (custom event interleaving dahil)
  • PII sanitization
  • Fingerprinting
  • MinIO storage
  • Compression eval (token count, output kalitesi manuel check)

Çıkış kriteri: 1 hafta boyunca Sase.tr'den gelen session'lar (rrweb + custom events + user/group props) compress edilmiş ve MinIO'da. Manuel inceleme ile timeline kalitesi onaylanır. LLM henüz yok.

Phase 6b — LLM Analysis MVP

Süre: 2 hafta

Hafta 1

  • Prompt template registry (DB tablosu, panel CRUD)
  • İlk prompt: bug_triage v1 (Sase.tr-specific context dahil)
  • Eval set: 15 case (custom event'li compressed timeline)
  • DeepSeek API client (Anthropic-compatible endpoint)
  • JSON validation pipeline

Hafta 2

  • 3 ek prompt: ux_friction v1, onboarding_stuck v1, payment_friction v1
  • Model tier routing (Flash/Pro)
  • Insights tablosu + basic UI list view
  • Cost ledger + temel cost dashboard

Çıkış kriteri: Pipeline uçtan uca çalışıyor. İlk insight'lar üretiliyor. Cost tracking aktif.

Phase 6c — Cost Governance + Insight Inbox

Süre: 2 hafta

Hafta 1

  • Tam cost dashboard (Bölüm 9.3)
  • Budget settings UI
  • Circuit breakers (Bölüm 9.4)
  • Cache stratejisi (prompt caching, fingerprint cache)

Hafta 2

  • Insight inbox tam UI (Bölüm 12.2)
  • Keyboard shortcuts
  • Cmd+K command palette
  • Insight detail page
  • Session timeline viewer

Çıkış kriteri: Founder günlük olarak panel'de geçirir, aksiyon alır, maliyet kontrol altında.

Phase 6d — Action Loop

Süre: 2 hafta

Hafta 1

  • GitHub integration (App veya PAT)
  • Issue creation flow
  • Issue template
  • Status tracking webhook

Hafta 2

  • Validation period tracking
  • Regression detection
  • Pattern aggregation UI
  • Bulk operations

Çıkış kriteri: Insight → Issue → Shipped → Validated tam döngü çalışır.

Phase 6e — Quality & Optimization

Süre: 3 hafta

Hafta 1

  • Eval framework production-grade
  • Prompt versioning + A/B testing
  • More prompts: upgrade_hesitation, discovery_loop, pattern_analysis

Hafta 2

  • Daily Brief (Bölüm 12.5)
  • Cross-fingerprint pattern detection (embedding similarity)
  • Bundle mode optimization

Hafta 3

  • Hardening: retention, security review
  • Documentation
  • Runbook'lar
  • Sase.tr-side data-private audit

Çıkış kriteri: Pilot tam başarılı, diğer projelere genişleme için template hazır.

Toplam Süre: 12 hafta + 2 gün Phase 0 prerequisite (~3 ay) part-time effort.

Faz Dağılımı Özeti:

Faz Süre Yer Bağımlılık
Phase 0 2 gün Sase.tr codebase Yok (başlangıç)
Phase 6a 3 hafta Süper Panel Phase 0
Sase.tr Faz 1 (paralel) 5-7 gün Sase.tr codebase Phase 0, Phase 6a Hafta 1-2 paralel
Phase 6b 2 hafta Süper Panel Phase 6a
Phase 6c 2 hafta Süper Panel Phase 6b
Phase 6d 2 hafta Süper Panel Phase 6c
Phase 6e 3 hafta Süper Panel Phase 6d

18. Riskler ve Azaltma

Risk Olasılık Etki Azaltma
Maliyet patlaması (LLM cost explosion) Düşük (DeepSeek ucuz) Orta Çok katmanlı circuit breaker (Bölüm 9.4); aylık $30 hard cap; tier fallback
DeepSeek output quality yetersiz (JSON format hatası, hallucination) Orta Yüksek Pilot başında eval seti Sonnet ile paralel; threshold %85; gerekirse hybrid routing
DeepSeek API downtime / latency (Çin altyapısı) Orta Orta OpenRouter fallback + Anthropic ultimate fallback; auto-failover 20% error rate'te
DeepSeek privacy concerns (Çin veri yasaları) Orta Yüksek Aggressive PII sanitization; sanitize audit zorunlu; aydınlatma metni güncel; provider geçiş seçeneği hazır
PII leak (KVKK ihlali) Düşük Kritik Üç katmanlı sanitize (kaynakta + compression + pre-LLM audit); 0 match anomaly alert
PostHog Cloud outage Düşük Orta Watermark + retry; PostHog SLA güvencesi
PostHog Cloud rate limit hit Düşük Düşük Polling concurrency 5'i geçmez; 240/min limit'ten çok altında
Hallucination (yanlış insight) Orta Orta Eval set discipline; confidence score; manuel triage zorunlu; auto-action yok
False positive flood Yüksek Orta Heuristic filter sıkı tutulur; dismiss rate izlenir; filter rules iyileştirilir
Schema drift (Sase.tr backend değişir) Yüksek Orta Sase.tr Prisma schema diff CI check; insight component path'leri güncel kalır
Compression algoritması bozulur (rrweb yeni version) Düşük Orta rrweb version pin; integration test
Founder triage süresi tutmaz (>30dk/gün) Orta Yüksek Daily brief; auto-dismiss low-confidence; severity filter
Insight pattern'leri kendini tekrarlar Yüksek Orta Fingerprint deduplication + dismissed pattern memory
LLM context window aşımı Çok düşük Düşük DeepSeek 1M context window var; token check yine de yapılır
Cache poisoning (cached yanlış insight her seferinde döner) Düşük Yüksek Cache TTL kısa (6h); manual cache invalidation UI
Audit log büyümesi (cost ledger 1M satır/yıl) Orta Düşük Aylık partition; eski partitionlar archive
DeepSeek pricing değişikliği (promo bitmesi) Yüksek (Haziran 2026) Düşük V4 Pro promo bittiğinde 4x fiyat artar; budget cap zaten margin'li, sorun olmaz; tier mix optimize edilebilir

19. Başarı Metrikleri

North Star Metric

"Cost per Validated Insight" — $X harcayıp Y validated insight ürettiysek, başarı oranı.

  • Target Phase 6 sonu (DeepSeek): < $0.50 per validated insight
  • Stretch target: < $0.20

Anthropic-only senaryoda hedef $20 idi. DeepSeek 50x ucuzlattığı için hedef de orantılı düştü.

Operational Metrics

Metrik Target (Phase 6 sonu)
Aylık pipeline maliyeti < $5 (Sase.tr tek başına, DeepSeek primary)
Insight production rate 15-30/hafta
Insight → Issue rate > %30 (yarısından fazlası actionable)
Issue → Shipped rate > %60
Shipped → Validated rate > %70
Average triage time (per insight) < 90 saniye
Pipeline latency P95 (session → insight) < 30 dakika
DeepSeek native cache hit rate > %60 (worker concurrency + stable prefix)
Application-level fingerprint cache hit > %15
LLM validation failure rate < %5 (DeepSeek için kalibrasyon gerekir)
Provider error rate < %1 (DeepSeek primary), fallback rate < %5
Dismiss rate < %30 (Phase 6e sonu, başlangıçta %50 normal)

Business Impact Metrics (Lagging)

Pipeline'ın ürün etkisi (3-6 ay sonra ölçülür):

  • Sase.tr error rate düşüşü (öncesi-sonrası)
  • Onboarding completion rate artışı
  • Subscription upgrade conversion artışı
  • Churn rate düşüşü
  • Support ticket azalması (varsa)

20. Açık Sorular

Çözülen Sorular (önceki versiyonlardan)

  1. PostHog Cloud mu Self-Hosted mı?PostHog Cloud (EU region)
  2. OpenRouter mı doğrudan Anthropic mi?DeepSeek primary, OpenRouter + Anthropic fallback
  3. Sase.tr data-private audit'i kim/ne zaman yapacak?sase-posthog-events-prd.md Faz 0 (2 gün)
  4. Sase.tr custom event taxonomy nedir?sase-posthog-events-prd.md Bölüm 5-7 (30+ event, 3 fazda)
  5. Group analytics kurulumu var mı?Hayır, sase-posthog-events-prd.md Faz 0'da kurulacak
  6. User identification property schema nedir?sase-posthog-events-prd.md Bölüm 4.1

Phase başlamadan netleşmesi gerekenler

  1. DeepSeek API key'i kimde, faturalama nasıl? Founder kişisel kart mı, Thinxtra LLC mı? Mercury entegrasyonu için Thinxtra LLC önerilir (USD invoicing).

  2. DeepSeek Privacy Policy verification: DeepSeek API verilerini model training'de kullanmama garantisi resmi olarak doğrulanmalı. Eğer net değilse (Çin yasal çerçevesi nedeniyle):

    • Opsiyon A: OpenRouter via DeepSeek (US/EU edge, daha temiz veri yolu)
    • Opsiyon B: Direkt Anthropic'e dön ($30 → $300 budget cap)
    • Opsiyon C: Self-host DeepSeek (Hetzner GPU instance ~$500/ay, scale gerektirir, pilot için anlamsız)
  3. DeepSeek Anthropic-compatible endpoint olgunluğu: Production'da kullanılır mı stabil? Phase 6a'da test edilecek. Değilse OpenAI-compatible endpoint kullanılır.

  4. DeepSeek aydınlatma metni ekleme: Sase.tr KVKK aydınlatma metnine "AI-destekli analiz için DeepSeek (Çin) kullanımı" maddesi eklenmesi. Hukuki tarafla netleştirilmeli. (sase-posthog-events-prd.md Bölüm 8.4'te taslak hazır.)

  5. GitHub Issues mi yoksa Linear mı? Sase.tr şu an GitHub Issues kullanıyor (kabul) — Linear'a geçiş plansı var mı? Integration adapter tek noktada tutulursa geçiş ucuz.

  6. Eval set'i kim yazacak? Founder tarafından 15-25 case elle yazmak gerekir. Phase 6a'nın 3. haftası rezerv. DeepSeek + Sonnet paralel eval'i için ek 1 hafta gerekebilir.

  7. Daily/Weekly Brief'i nereye? Email (kendi domain) vs Telegram bot vs panel-only. Bandwidth ve dikkat yönetimi farklı.

  8. DeepSeek V4 Pro promo bittiğinde (1 Haziran 2026) plan? Promo bittikten sonra Pro 4x pahalanır. Senaryo:

    • Pilot Phase 6a-6c bu süre içinde tamamlanırsa düşük maliyet kazanılır
    • Sonrasında: ya Flash-only mode'a geç (quality eval ile karar), ya pro tier'ı sadece P0/P1 ve pattern bundle'larla sınırla, ya da budget cap arttırılır
  9. Off-peak window'u V4 için aktif mi? Tarihi olarak V3/R1'de %50-75 indirim varmış. V4'te Phase 6e'de empirik test edilir; aktifse routing buna göre optimize.

  10. PostHog Cloud usage maliyeti: Sase.tr session sayısı PostHog Cloud free tier'ı (5K recording/ay) aşıyorsa ek maliyet ($0.005/recording). Aylık session sayısı kontrolü ve PostHog cost monitoring panel'de gösterilmeli.

  11. Sase.tr Phase 0 ne zaman başlar? Pilot tüm zamanlamasını blokluyor. Önerim: önümüzdeki 1 hafta içinde 2 günü bu work'e ayır, sonra BIP Phase 6a başlat.

  12. Faz 1 paralel work senkronizasyonu: Sase.tr Faz 1 (5-7 gün) BIP Phase 6a Hafta 1-2 ile paralel. Eğer Sase.tr Faz 1 gecikirse, BIP Phase 6a Hafta 3 (compression) zenginleştirilmiş event'leri test edemez. Olası gecikme contingency plan'ı?

  13. Founder bu sistemin kendisini "dogfood" edecek mi? Süper Panel'in kendi UX'ini panel'in kendisi mi analiz etsin? Meta seviye ama eğlenceli ve değerli olabilir.


Karar Logu

Tarih Karar Gerekçe
2026-05-13 Sase.tr pilot, diğer projeler sonra B2B değer/sinyal oranı en yüksek; technical user sessizliği differantiated value
2026-05-13 4 katmanlı triyaj (heuristic → tagging → compression → LLM) %95 gürültü heuristic'te elenir, LLM cost makul kalır
2026-05-13 rrweb event'leri inline'da network correlation ile zenginleşir Tek timeline AI için daha actionable
2026-05-13 Per-tag specialized prompt'lar (generic değil) Prompt kalite > prompt sayısı; eval discipline
2026-05-13 Tier-based model routing Cost optimization; severity bazlı
2026-05-13 Cost governance panel-controlled (token/$ budget) Founder runtime control; circuit breaker katmanları
2026-05-13 PII sanitization iki katmanlı (kaynak + compression) Defense in depth; KVKK uyumu
2026-05-13 Eval set discipline mecburi Prompt iteration subjektifliği önler
2026-05-13 Action loop GitHub Issues üzerinden Mevcut workflow'a entegre; webhook'la status track
2026-05-13 Validation period 14 gün Regression için makul süre; configurable
2026-05-13 Phase 6 toplam 12 hafta Solo founder part-time gerçekçi tahmin
2026-05-13 PostHog Cloud (EU region) kullanılacak KVKK için EU veri konumu; self-host complexity gereksiz; PostHog SLA güvenilir
2026-05-13 DeepSeek V4 primary LLM provider 20-50x daha ucuz; OpenAI/Anthropic compatible endpoint; 1M context; aylık ~$5/ay vs $150/ay
2026-05-13 3 tier yerine 2 tier (flash + pro) DeepSeek V4'ün model çeşidi bu pattern'e daha uygun; sadeleşme
2026-05-13 Anthropic-compatible endpoint kullanılacak SDK uyumluluğu; provider switch kolay
2026-05-13 3 katmanlı provider failover: DeepSeek → DeepSeek/OpenRouter → Anthropic Çin altyapısı resilience; quality fallback garanti
2026-05-13 PII sanitization üçüncü katman: pre-LLM audit (anomaly = abort) DeepSeek Çin altyapısı için ek güvence
2026-05-13 DeepSeek cache hit'i maksimize etmek için stable system prompt prefix discipline %95+ cache hit ile maliyet 50x'e ulaşan ekstra tasarruf
2026-05-13 Default monthly cap $300 → $30 DeepSeek pricing 10x güvenlik marjı ile yeterli
2026-05-13 (v1.2) Sase.tr custom event taxonomy ayrı PRD'ye çıkarıldı (sase-posthog-events-prd.md) Sase.tr-side work BIP'ten ayrılabilir; pilot blocker'lar net görünür
2026-05-13 (v1.2) Phase 0 (2 gün Sase.tr event prep) Phase 6a prerequisite olarak eklendi Pilot insight kalitesi event taxonomy'ye bağımlı; bloklayıcı dependency açık görünmeli
2026-05-13 (v1.2) PostHog person/group cache panel DB'de tutulur, 24h TTL Her event'te PostHog API'sini hammer etmemek; identify property'leri stable
2026-05-13 (v1.2) Custom event'ler timeline'a inline interleaved (⤷ EVENT: prefix) rrweb + custom event LLM görüş alanında birleşir; semantic enrichment
2026-05-13 (v1.2) Tag detection custom event tabanlı kurallar öncelikli Semantic context (vin_decode_failed) generic sinyalden (network 500) daha kaliteli tag üretir
2026-05-13 (v1.2) payment_ui_silent_failure tag yeni eklendi (P0 severity) Backend payment succeeded ama UI confirm yok = critical bug pattern
2026-05-13 (v1.2) Group analytics (posthog.group('company')) B2B insight için zorunlu Account-level pattern detection bireysel session'dan çok daha leverage'lı
2026-05-13 (v1.2) Score threshold (>= 30) altındaki session'lar tag varsa bile discard Pipeline budget yüksek-değer session'lara odaklanır

Doküman Sonu