docs(ekip): 7–10 Ekim raporları, eval sonuçları, seslendirme betiği

- docs/ekip-raporlari/2026-10-07, 2026-10-09, 2026-10-10 raporları ve ekran görüntüleri
  (ses/ altındaki mp3 dosyaları depoya alınmadı, 38 MB)
- BACKLOG #38: rehber yazılarına "Dinle" düğmesi adayı
- scripts/seslendir.py (Türkçe TTS) ve .gitignore'a .venv-tts/
- scripts/eval/sonuc: 8–10 Ekim revizyon eval çıktıları

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
bilalgursen
2026-10-11 00:33:39 +03:00
parent e9dfa354f8
commit da0e9dff7a
81 changed files with 18396 additions and 0 deletions

View File

@@ -0,0 +1,49 @@
# Güvenlik ve uyum geri bildirimi — 7 Ekim 2026 merge paketi
Kapsam: dal `v2`, HEAD `e4c06f5`; `e3d79f5` (revizyon sınırı kaldırıldı), `15f4c4f` (rehber bağlantı düzeltme logu) ve pazarlama/yasal metin tutarlılığı. Kod değiştirilmedi; denetim koddan (statik okuma). Canlıya dokunulmadı.
## Özet (5 madde)
1. **Kritik yok.** Kredi düşme/iade yolu ve paket kapısı doğru: paketsiz-kredili aday revizyon yapamaz (üç bağımsız kapı: prompt, araç, çekirdek). Sınırsız revizyon maliyet riski **düşük** — her revizyon 1 sohbet kredisi ister, kullanıcı başına üretim kilidi var, cevap başına tek revizyon; ölçülü maliyet revizyon başına ~2,4 kuruş (60 kredilik paketin tamamı revizyona gitse ≈1,5 TL).
2. **Metin × kod (orta, avukat teyidi):** "Sınırsız liste revizyonu" vaadi gerçekte **kredili** bir sınırsızlık — her revizyon isteği 1 sohbet kredisi yakar, kredi bitince revizyon da biter. Ana sayfa ve paket kartındaki madde bu şartı söylemiyor; "sınırsız" iddiasının önemli kısıtı aynı yerde açıklanmalı (Ticari Reklam Yönetmeliği m.7 / 6502 m.6 tüketiciyi yanıltıcı beyan riski).
3. **Kullanıcıya giden iki yanıltıcı cümle (düşük):** `liste-revizyon.ts:39,42` "kredin/paketin etkilenmedi" diyor ama o turun 1 sohbet kredisi harcanmış kalıyor; `rapor.ts:712` hâlâ "Revizyon hakkın kullanılmadı" diyor (hak kavramı kalktı).
4. **Bağlantı logu (düşük, OLASI):** `sohbet-akisi.ts:281` yalnız slug logluyor; e-posta/ad/puan taşımıyor. Ancak slug **modelin yazdığı serbest metinden** geliyor; kullanıcı mesajına yazılmış `/rehber/ahmet-yilmaz-plani` gibi bir adres modelce tekrarlanırsa log'a geçer. Sayaç + yalnız `yeniSlug` (kayıtlı slug) loglanması yeterli.
5. **Rate limit yok ama sorun değil:** `/api/soru` üzerinde hız sınırı yok; maliyet kapısı kredi (deneme 5, paket 60). Magic link better-auth varsayılanı 5/60 sn ile sınırlı (`node_modules/better-auth/dist/plugins/magic-link/index.mjs:157-162`). Revizyon paketsize kapalı olduğu için "başkasının parasıyla LLM" saldırısı bu değişiklikle açılmadı.
## Bulgu tablosu
| # | Dosya:satır | Sorun | Senaryo | Önem | Düzeltme | Kesinlik |
|---|---|---|---|---|---|---|
| 1 | `src/app/page.tsx:247`, `src/features/odeme/components/paket-satinal.tsx:37` | "Sınırsız liste revizyonu (danışmanla sohbetten)" — gerçekte her revizyon `spendCreditForMessage` ile 1 kredi düşer (`src/app/api/soru/route.ts:150-156`); 60 kredi bitince revizyon imkânsız, top-up (129 TL) gerekir | Veli 299 TL öder, öğrenci 60 mesajı sorularla bitirir; "sınırsız revizyon" için ikinci ödeme istenir → "sınırsız dediniz" şikâyeti / tüketici hakem heyeti | **Orta** | Maddeyi "Liste revizyonu sayı sınırı yok; her istek 1 sohbet kredisi" biçimine getir ya da revizyonu bedelsiz mesaj yap (`bedelsiz` yoluna `liste_revize` eklemek teknik olarak kolay; o zaman cevap başına tek revizyon + üretim kilidi kötüye kullanımı yine sınırlar). Metin değişikliği `[BİLAL]`, avukat teyidi gerekir | DOĞRULANDI (koddan) |
| 2 | `src/features/rapor/liste-revizyon.ts:39,42` | Hata mesajı "kredin/paketin etkilenmedi" — revizyonu tetikleyen mesajın 1 kredisi iade edilmiyor (route yalnız akış yarım kalırsa iade eder, `route.ts:317-327`) | Aday "havuz yetersiz" hatası alır, 1 kredi gitti ama ekranda "etkilenmedi" yazar; destek talebi/güven kaybı | Düşük | "revizyon bedeli alınmadı; bu mesajın sohbet kredisi düştü" ya da revizyon hatasında chat kredisini de iade et (refId=mesajId zaten var, `grantCredits reason:"refund"` ile idempotent) | DOĞRULANDI |
| 3 | `src/lib/ai/rapor.ts:712` | `RaporUretimHatasi` metni "Revizyon hakkın kullanılmadı." — hak kavramı `e3d79f5` ile kalktı; `hataMesaji` bu metni olduğu gibi araca ve kullanıcıya geçirir (`liste-revizyon.ts:34`) | Çifte doğrulama başarısızlığında aday "hak" diye bir şey olduğunu sanır; pazarlama "sınırsız" diyor | Düşük | Metni "Tekrar dener misin?" ile sınırla | DOĞRULANDI |
| 4 | `src/lib/ai/sohbet-akisi.ts:125,221,281` | `duzeltilenSluglar` modelin cevabındaki ham slug'ı (`[a-z0-9-]+`, üst sınır yok: `baglanti-denetimi.ts:48,58`) stdout'a yazar. Slug kaynağı model çıktısı; model kullanıcının yazdığı adresi tekrar edebilir | Aday sohbete "/rehber/ahmet-yilmaz-icin-liste var mı" yazar, model adresi anıp cevaplar → log'a `ahmet-yilmaz-icin-liste→(düz)` düşer. Docker log'u `docker-compose.yml`'de boyut/süre sınırsız (logging ayarı yok) | Düşük | Yalnız sayı + `yeniSlug` (kayıtlı slug) logla; ham slug'ı atma veya ilk 40 karaktere kırp. Compose'a `logging: max-size/max-file` ekle | OLASI (senaryo kurgu; gerçek log örneği görülmedi) |
| 5 | `src/app/api/soru/route.ts` (tüm POST) | Kullanıcı başına hız sınırı yok; sınır yalnız kredi (`spendCreditForMessage`) | Deneme hesabı başına 5 mesaj × cevap başına ≤8 araç + 1024 token; magic link ile sınırsız hesap → hesap başına ~5–8 kuruş; para kaybı değil, kapasite (1 GB RAM, tek konteyner) | Düşük | Değişiklik gerektirmiyor; ileride e-posta alan adı/IP başına günlük hesap sınırı (önceki raporlarda var) | DOĞRULANDI (ön-mevcut, bu merge'le değişmedi) |
| 6 | `src/lib/ai/sohbet-akisi.ts:111-139`, `liste-revizyon.ts:124` | Sohbet zaman aşımında (`kesici.abort`) araç içindeki `raporUret` iptal sinyali almaz, devam eder ve listeyi yazar; route `onYarim` ile sohbet kredisini iade eder | Sağlayıcı 270 sn'de bitirmezse aday hem iadeyi hem revizyonu alır; kasıtlı tetiklenemez (süre sunucuda), para kaybı 1 kredi | Düşük | Bilgi notu; kabul edilebilir | DOĞRULANDI (koddan çıkarım) |
### Doğrulanan ve sorun bulunmayan noktalar
- **Paket kapısı üç katmanlı:** prompt (`danisman-prompt.ts:77-79` "paketi YOK: liste_revize çağırma"), araç (`araclar.ts:1745-1747` `hasPaket` yoksa hata), çekirdek (`liste-revizyon.ts:69-75` `user.hasPaket` DB'den okunur, `kod:"PAKET"`). Paketsiz-kredili aday revizyon **yapamaz**; `hasPaket` istemciden değil `session.user.id` ile DB'den gelir (`route.ts:116-120`).
- **Kredi/iade yolu:** paketliye `maliyet=0`; `spendCredits` yine `UNIQUE(reason, ref_id)` (`appdb/schema.ts:134`) ile 0-deltalı satır yazar → aynı `mesajId` ikinci kez revizyon tetikleyemez (`liste-revizyon.ts:99-119`). Üretim hatasında `grantCredits(refund, refId=mesajId)` idempotent. `revision_count` yalnız sayaç.
- **Eşzamanlılık:** `uretimKilidiAl` kullanıcı başına tek üretim (`uretim-kilidi.ts:31-59`, bayat eşik 180 sn, koşullu UPDATE). Aynı cevapta ikinci `liste_revize` kotayla reddedilir (`sohbet-akisi.ts:148-151`), cevap başına ≤8, adım başına ≤4 araç.
- **Girdi:** `liste_revize` argümanı `revizyonKuraliKur` ile şema doğrulamasından geçer; `not` ≤1000 karakter ve `kullaniciMetni` ile `<>` temizlenip `<revizyon_istegi>` etiketinde LLM'e gider (`rapor.ts:459,594`). Sohbet mesajı ≤2000 karakter, `clientMessageId` UNIQUE.
- **Bağlantı düzeltme verisi kalıcı depolanmıyor:** `duzeltmeler` yalnız log + `onDenetim` (eval) — `chat_messages.meta`'ya yazılmıyor. `getRehberAramaKayitlari` yalnız slug/başlık/açıklama döner (`rehber.ts:259-265`). Kullanıcı mesajı tampondan geçmez (yalnız model çıktısı), prompt enjeksiyon yüzeyi artmadı.
- **Analitik:** revizyonla ilgili Rybbit olayı yok (`src/lib/analitik*.ts` ve `rybbit-identify.tsx`'te "revizyon" geçmiyor); bu merge'le üçüncü tarafa yeni veri akışı eklenmedi.
## Metin × kod uyumsuzlukları
| Yer | Metin | Kod | Not |
|---|---|---|---|
| `page.tsx:247`, `paket-satinal.tsx:37` | "Sınırsız liste revizyonu (danışmanla sohbetten)" | Her revizyon isteği 1 sohbet kredisi (`route.ts:150-156`); kredi bitince 402 | Bulgu 1 — `[BİLAL]`, avukat teyidi |
| `src/app/paket/page.tsx:13` (meta description) | "liste revizyonları ve soru hakkı" | Uyumlu (sayı vermiyor) | — |
| `src/app/kosullar/page.tsx:50-58` | Paket içeriği için `/paket`'e yönlendiriyor; revizyon/kredi tüketimi hakkında hüküm yok | Krediyle sınırlı revizyon | Koşullarda "revizyon dâhil; her sohbet mesajı 1 kredi" cümlesi eklenirse Bulgu 1'in hukuki tarafı kapanır (taslak, avukat teyidi) |
| `src/app/gizlilik/page.tsx:165-172` | OpenRouter'a "mesajlar, program bilgileri, kaydettiğin tercihler" gider | Revizyonda ek olarak `not` özeti + önceki liste özeti + profil gider (`liste-revizyon.ts:123-129`) — hepsi zaten sayılan kategorilerde | Uyumlu |
| `src/app/gizlilik/page.tsx` (tamamı) | Sunucu günlükleri hiç anılmıyor | `console.info/warn` ile araç adı, slug, denetim sayıları loglanıyor; kişisel veri yok (Bulgu 4 hariç olası) | Bilgi; "teknik günlükler" cümlesi eklenebilir (isteğe bağlı) |
| `docs/urun/vizyon.md:41` | "2 liste revizyonu hakkı" | Sınır kalktı | Eski belge, `[KARAR]` düzeyinde güncellenebilir |
| `src/lib/ai/rapor.ts:712` | "Revizyon hakkın kullanılmadı" | Hak kavramı yok | Bulgu 3 |
## Bilal'den istenen
1. "Sınırsız liste revizyonu" maddesinin yanına kredi şartını ekleyip eklemeyeceğine (ya da revizyonu bedelsiz mesaj yapıp yapmayacağına) karar ver — Bulgu 1; ~5 dk karar, metin değişikliği avukat teyidiyle.
2. Bulgu 2–3'teki iki hata metninin düzeltilmesi için yazılımcıya küçük bir iş aç (~10 dk).
3. Bulgu 4 için log satırını sayaç + kayıtlı slug'a indirmeyi onayla (~5 dk; yazılımcı tek satır).