Files
kolaytercih/docs/ekip-raporlari/2026-10-07/guvenlik-uyum-geri-bildirim.md
bilalgursen da0e9dff7a 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>
2026-10-11 00:33:39 +03:00

50 lines
9.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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).