Files
kolaytercih/docs/ekip-raporlari/2026-09-22/07-guvenlik-denetimi.md
bilalgursen 2b350d0c5d content(rehber): gece vardiyasının 14 yeni yazısı + 2 düzeltme, ekip raporları ve kurallar
14 yeni rehber yazısı (hepsi editör denetiminden geçti, 46 yazıda 829 iç link
tarandı, 0 kırık hedef; 180+ DB rakamı yazıların kendi filtreleriyle yeniden
koşuldu):

  taban-siralamalari-alti-yilda-nasil-degisti · kac-net-ile-hangi-bolum ·
  siralama-bandlari-hangi-kapilar-acilir · ayni-bolum-farkli-universite-siralama-farki ·
  hangi-bolumlerin-kontenjani-azaldi · yeni-acilan-bolumler-nasil-degerlendirilir ·
  bilgisayar-mi-yazilim-muhendisligi-mi · kktc-universiteleri-okunur-mu ·
  yapay-zekaya-tercih-sordum-guvenilir-mi · ek-madde-1-puanim-yetiyor-mu ·
  universitede-ilk-hafta-ders-kaydi-muafiyet-kayit-dondurma · yks-2027-takvimi ·
  rehber-ogretmenler-icin-veri-kaynaklari · bolumumu-sevmedim-hangi-kapilar-var

İki canlı yazı düzeltildi:
- veliler-icin-tercih-rehberi: veli diliyle kapanış; altındaki "sıralamanı gir"
  kutusu artık veliye ölü uç değil
- bos-kontenjanlar-ne-anlatiyor: "birkaç yüz kişilik fark" aslında ~9 bin
  (ÖSYM 265.356 ↔ bizim 256.532); payda açıklaması tersti — ek kontenjan
  paydaya girseydi oran düşerdi. guncelleme alanı eklendi (sitemap lastmod).

Kurallar (AGENTS.md):
- Yayın sonrası arama motoru bildirimi: URL denetimi yalnız canlıda 200 dönen
  adrese; kota sayacı; mülk/hesap notu; sitemap grep kuralı
- Yıkıcı git komutları yasak: reset/checkout --/restore/clean/stash
- Tarayıcı açma: tasarımcı ve UX gerekli gördüğünde açabilir (yetenek için
  .claude/agents/tasarimci.md'ye tarayıcı araçları eklendi)

docs/gece-vardiyasi/2026-09-22/ — 34 rapor: CEO kararları ve kapanış turu,
marka/ödeme analizi, sıfır ödeme teşhisi, SEO konu planı, veri kalitesi,
editör denetimi, CTO şartnamesi, yazılımcı ve güvenlik raporları, SABAH-OZETI.

docs/ekip/YAYIN-KUYRUGU.md — Search Console bildirim kuyruğu.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 23:25:34 +03:00

74 lines
19 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.
# 07 — Güvenlik ve uyum denetimi: üç merge adayı dal + çalışma ağacı
Denetleyen: `guvenlik-uyum` · 22 Eyl 2026 · `main` = `e21cda4`
Kapsam: `funnel/arti-olu-ucu` (22c139a), `funnel/listem-girisi` (cb22faf, 7dc47ee, 419b617), `olcum/liste-uretim-basladi` (f60fbd1, e6fbc62) ve commit'lenmemiş `src/features/rapor/components/liste-uretici.tsx`.
Kod değiştirilmedi, commit atılmadı, canlıya dokunulmadı.
## Özet (5 madde)
1. **Kritik bulgu yok.** Üç dalın hiçbiri yetkilendirme, ödeme bütünlüğü ya da açık yönlendirme açığı açmıyor. Üçü de — aşağıdaki düzeltmelerle — merge edilebilir.
2. **P4 açık yönlendirme iddiası doğrulandı: açık yok.** `giris-karti.tsx:18-19` kalkanı `//evil.com`, `/\evil.com`, mutlak URL ve `javascript:`'i düşürüyor; better-auth 1.6.23 ayrıca hem POST hem magic-link GET yolunda kendi göreli-yol kalkanını koşuyor. **Ama** aynı kalkan `/rehber/ösym` gibi ASCII dışı ya da yüzde-kodlu her yolu better-auth'a 403 olarak gönderiyor → `GirisLinki` bu yolda girişi tamamen kırıyor (yeni regresyon, orta).
3. **P3 rıza iddiası doğrulandı ama yarım.** Ödeme anındaki buton gerçekten "Yapay Zeka listemi kur (3 kredi)" diyor (`tercih-profili-kapisi.tsx:462`) ve `raporVar`/`bekleyen.eslesir` korumaları tutuyor; çift üretim yolu açılmıyor. Kırık olan **girişteki vaat**: + toast'ı ve çekmece paneli hâlâ yalnız "sıralamanı gir → riskini gösterelim" diyor, oysa akış artık 3 kredilik bir satın almayla bitiyor (orta).
4. **P2'de allowlist iki yerde delik.** (a) `kaynak` ham hâliyle URL'de kaldığı için Rybbit'in `trackUrlParams` açık pageview'ına allowlist'ten bağımsız giriyor (`/listem` maskesiz); (b) otomatik üretim yolu **her zaman** `giris_donusu` etiketi atıyor, oysa o yol tam olarak giriş dönüşü *olmayan* yol — hero/arama/+/ödeme-sonrası hepsi bu tek yanlış etikete düşüyor, yani P2'nin ölçmek istediği şey ölçülmüyor (orta, ölçüm doğruluğu).
5. **Çalışma ağacındaki "kredin yeniden harcanmaz" iddiası DOĞRU.** `SunucuYokEkrani` yalnızca `listeOlustur` `ok:true` döndükten sonra görünür; o noktada `reports` satırı yazılmış ve kredi `spendCredits` ile bir kez düşmüştür, "Listemi aç" `?uret=1` taşımadığı için ikinci üretim başlatmaz. `/api/saglik` sabit gövdeli, DB'ye/oturuma dokunmuyor — bilgi sızdırmıyor, rate limit gerektirmiyor (zaten `main`'de, d41120c).
---
## Bulgu tablosu
| # | Dosya:satır | Sorun | Somut istismar / ihlal senaryosu | Önem | Düzeltme | Kesinlik |
|---|---|---|---|---|---|---|
| G1 | `src/features/kullanici/components/giris-linki.tsx:25-30` (+ `giris-karti.tsx:18-19`) | Callback'e konan `usePathname()` değeri ASCII dışı ya da `%` içerebiliyor; better-auth'un göreli-yol regex'i `[\w\-.+/@]` dışına çıkan her şeyi 403 `INVALID_CALLBACK_URL` ile reddediyor. Site içi kalkan geçiyor, auth katmanı geçmiyor. | Ziyaretçi `/{herhangi}/ösym-nedir` ya da `/bolum/t%C4%B1p` gibi bir adrese geliyor (yanlış/dış link, soft-404 sayfası da navbar'ı render ediyor — bkz. BACKLOG #5). Navbar'daki "Giriş yap" `/giris?callback=%2Fbolum%2Ft%25C4%25B1p` üretiyor; kullanıcı e-posta ya da Google'a basıyor, better-auth 403 dönüyor, `giris-form.tsx:99-103` "Bağlantı gönderilemedi" diyor. Kullanıcı o sayfadan **hiç giriş yapamıyor**, tekrar denemek de çözmüyor. `main`'de callback hep `/` olduğu için bu yol yoktu. | **orta** | `giris-linki.tsx`'te href kurmadan önce yolu süz: `/^\/[\w\-./+@]*$/.test(pathname)` değilse sade `/giris`. (Alternatif: `giris-karti.tsx` kalkanını aynı beyaz listeye daraltmak — iki yer yerine tek yer.) | DOĞRULANDI (better-auth 1.6.23 `auth/trusted-origins.mjs` regex'i lokalde payload setiyle koşturuldu; `/rehber/ösym`, `/rehber/%C3%B6sym` → `false`) |
| G2 | `src/features/liste/components/program-ekle-butonu.tsx:73,77,84` · `liste-cekmecesi.tsx:279,283,296` | Kapının **girişindeki** vaat ile **çıkışındaki** bedel uyuşmuyor. Toast: "Sıralamanı girersen bu programın risk seviyesini de gösteririz" + buton "Sıralamamı gir". Çekmece: "Sıralamanı girince her seçimin riskini gösteririz" + "Sıralamamı gir". Dal bu iki kapıyı `hedef="sihirbaz"`e çevirdiği için akışın sonu artık ücretsiz risk rozeti değil, 3 kredilik LLM üretimi. | 17 yaşındaki kullanıcı katalogda + ile program ekliyor, "Sıralamamı gir"e basıyor (beklenti: rozet). Sıra + 3 sihirbaz adımını dolduruyor, son butonda "(3 kredi)" ilk kez görünüyor; basınca `/sonuc?sihirbaz=1` → otomatik `/listem?uret=1` → 5 deneme kredisinin 3'ü yanıyor, kullanıcı baktığı katalog sayfasından koparılıyor. "Vazgeç" derse profil hiç kaydedilmediği için **istediği risk rozetini de alamıyor**. | **orta** | İki seçenek: (a) toast/çekmece metnini akışın gerçek sonucuna eşitle ("…sıralamanı girip birkaç seçim yaparsan 24'lük listeni de 3 krediyle kurarız") — metin `[BİLAL]`; ya da (b) bu iki yüzeyi `hedef=null` bırakıp AI'yı ayrı, adı konmuş bir CTA'ya taşı. Kod tarafı `[KARAR]`, cümle `[BİLAL]`. | DOĞRULANDI (koddan; buton etiketi zinciri `tercih-profili-kapisi.tsx:456-466` ile eşleştirildi) |
| G3 | `src/features/sihirbaz/components/sihirbaz-cagri-karti.tsx:225` (olcum dalı) | Otomatik üretim `kaynak="giris_donusu"` atıyor. Oysa `?sihirbaz=1` üreten **hiçbir** yer giriş dönüşü değil: `hero-form.tsx:104`, `cta-sira-form.tsx:172`, `use-tercih-profili.ts:331` (+ kapısı ve boş durum), `rapor-yok-cta.tsx:24`, `arama-funnel-karti.tsx:94`. Gerçek giriş dönüşü `/giris?callback=/listem?uret=1&kaynak=hazir_cta\|sihirbaz` ile **doğrudan** `/listem`'e iner, `/sonuc`'a uğramaz. | Saldırı değil, ölçüm ihlali: P2'nin tek amacı "üretimi hangi yüzey başlattı" sorusu. Merge edilirse hero (ana huni), katalog araması, + kapısı ve ödeme-sonrası CTA'sının hepsi tek bir `giris_donusu` kovasında toplanıyor; `sihirbaz` ve `hazir_cta` değerleri ise yalnız giriş dönüşünde düşüyor. Etiketler fiilen ters. | **orta** | `?sihirbaz=1`'i üreten taraf kaynağını URL'de taşısın (`sonucHref({sihirbaz:"1", kaynak:"hero"\|"arama"\|"arti"\|"bos_durum"\|"odeme_sonrasi"})`), `otomatikGonder` onu geçirsin; `IZINLI_KAYNAKLAR`'a `hero`, `arama`, `arti` eklensin. `giris_donusu` yalnız `/giris` callback'inden gelen yolda kalsın. | DOĞRULANDI (koddan; `?sihirbaz=1` üreticilerinin tamamı grep'lendi) |
| G4 | `src/features/rapor/components/uretim-basladi-olayi.tsx:25-32,54` · `src/app/layout.tsx:118` | Allowlist yalnız **özel olay özelliğini** koruyor. `kaynak` ham hâliyle adres çubuğunda kalıyor ve Rybbit `trackUrlParams: true` ile çalışıyor (`docs/gece-vardiyasi/2026-09-21/01-analitik-bulgular.md:181`); `data-mask-patterns` yalnız `/sonuc` ve `/odeme/sonuc`'u kapsıyor, `/listem` kapsam dışı. | Ücretsiz hesap açan biri `/listem?uret=1&kaynak=<istediği 200 karakter>` ile geziniyor. `liste_uretim_basladi.kaynak` doğru şekilde `bilinmiyor`a düşüyor **ama** aynı isteğin pageview'ı querystring'i olduğu gibi Rybbit'e yazıyor: panelde keyfi metin + `/listem` için kardinalite şişmesi. Giriş round-trip'i üzerinden de taşınabiliyor (`listem-icerik.tsx:51-53` → better-auth query karakter seti `%` ve `&`'a izin veriyor, yani `%3Cscript%3E` geçiyor; `<`/`>` ham hâli 403'e takılıyor). | **düşük** | `/listem`'i `data-mask-patterns`'a ekle **ya da** `listem/page.tsx`'te `kaynak`ı `ListemIcerik`'e vermeden önce allowlist'ten geçir (tek doğrulama noktası, hem URL hem olay için). İkincisi G3 düzeltmesiyle aynı yere düşüyor. | OLASI (`trackUrlParams: true` ekip raporundan alındı; canlı Rybbit'e sorgu atılmadı) |
| G5 | `src/features/rapor/rapor-actions.ts:118-124` + `liste-uretici.tsx:104,120-126` | Eşzamanlı ikinci üretim kilidi yok: iki paralel `ListeUretici` mount'u iki ayrı `requestId` üretir, `spendCredits` ikisini de geçirir → 6 kredi, 2 LLM çağrısı, tek rapor. | Üretim sürerken (20–60 sn) kullanıcı geri→ileri basıyor ya da `/listem?uret=1`'i ikinci sekmede açıyor: `raporVar` hâlâ `false` olduğu için `listem-icerik.tsx:73` ikinci kez `ListeUretici` render ediyor. **Not:** bu `main`'de de var; `funnel/arti-olu-ucu` yalnızca bu URL'e varan yolu bir tık kısaltarak maruziyeti artırıyor. | **yüksek** (mevcut, dalların doğurduğu değil) | BACKLOG #1 ("dalda") ile aynı iş: `SURUYOR` kodu + kullanıcı başına üretim kilidi. P3/P4'ün merge'i bunu beklemek zorunda değil, ama **aynı yayında** çıkmalı. | DOĞRULANDI (koddan; BACKLOG #1 ile örtüşüyor) |
| G6 | `src/features/rapor/components/listem-bos-cta.tsx:35-36` (listem-girisi) · `src/features/odeme/components/paket-satinal.tsx:157` (olcum) · `rapor-yok-cta.tsx:24-27` · `sihirbaz-cagri-karti.tsx:199-201,333` | Bedeli **hiç** yazmayan tek tık → 3 kredi yolları. "Yapay Zeka listeni kur", "listeni oluştur", "24'lük listeni oluştur", `/sonuc`'un büyük "Yapay Zeka listemi kur" butonu (kayıtlı eşleşen seçim varsa modal hiç açılmaz, `ilerle()` doğrudan koşar). | `rapor-yok-cta.tsx:31` ayrıca yanlış söylüyor: "sonuç sayfasındaki sihirbazla listeni kur" — oysa sihirbaz açılmıyor, `otomatikGonder` üretimi anında başlatıyor. Ödemesini yeni yapmış kullanıcı için zarar düşük (60 kredi), ama deneme kredisiyle gezen öğrenci `/listem` boş durumundan tek tıkla 3 kredisini yakıyor. | **düşük** | Bu dört yüzeyin etiketine "(3 kredi)" ekle — kanonik metin zaten `tercih-profili-kapisi.tsx:462`'de var. `rapor-yok-cta.tsx:31`'in yanlış cümlesi düzeltilsin. Metin `[BİLAL]`. | DOĞRULANDI (koddan) |
| G7 | `src/features/rapor/components/liste-uretici.tsx:56-72,159` (çalışma ağacı) | Sağlık yoklaması artık **mutlu yolda** ve fail-closed: `fetch("/api/saglik")` herhangi bir nedenle başarısız olursa (kurumsal proxy, 5 sn'yi aşan yavaş mobil bağlantı, geçici 503) liste gerçekten hazırken kullanıcıya "sunucuya ulaşamıyoruz" ekranı gösteriliyor. | Zarar sınırlı: liste DB'de, kredi tek düşmüş, "Listemi aç" ikinci yoklamada geçince listeye götürüyor. Yani **para riski yok**, yanlış alarm riski var. `SAGLIK_YOKLAMA_MS = 5000` yavaş 3G'de gerçek bir eşik. | **düşük** | Bulunduğu hâliyle kabul edilebilir. İstenirse: yoklama bir kez başarısız olunca 1 kez daha denensin (toplam ~2 sn ek), ya da eşik 8 sn'ye çıksın. | DOĞRULANDI (koddan; ağ koşulu simüle edilmedi) |
| G8 | `package.json` → `next@16.2.10` | `pnpm audit --prod`: 2 kritik + 12 yüksek. Ulaşılabilirlik denetlendi — **2 kritik ulaşılamıyor**: AVIF RCE için `images.remotePatterns` gerekiyor, `next.config.ts`'te tanımlı değil (optimizer yalnız yerel dosya); Windows RCE'nin karşılığı yok (Linux/Docker). Ulaşılabilir olan: "DoS in App Router using Server Actions" — bu uygulama server action ağırlıklı (`listeOlustur`, `odeme-actions`). | Kimliksiz saldırgan server action uçlarına biçimsiz yük göndererek süreci tüketebiliyor (advisory GHSA detayına bakılmalı). Dallarla ilgisi yok, mevcut durum. | **orta** | `next` 16.2.10 → **16.2.11** (yama sürümü, 9 advisory kapanıyor; 2 kritik için 16.3.3 gerekiyor ama minor atlama ayrı bir iş). | DOĞRULANDI (`pnpm audit --prod`, salt okuma) |
### Bulunamadı (arandı, yok)
- **Açık yönlendirme:** `//evil.com`, `/\evil.com`, `/%2fevil.com`, `/%5cevil.com`, `%2f%2f…`, `https://evil.com`, `javascript:` payload'larının hiçbiri `giris-karti.tsx:18-19` kalkanından geçip dış hedefe çıkmıyor; `/%2f…` kalkanı geçiyor ama tarayıcı `%2f`'i yolda çözmediği için aynı köken içinde 404 oluyor ve better-auth zaten reddediyor. `dogrula-karti.tsx:9-11`'in kalkanı zayıf (`/\evil.com`'u geçiriyor) **ama** better-auth `magic-link/verify` ucunda `originCheck` ile `(?!\/|\\|%2f|%5c)` uyguluyor → sömürülebilir değil. Yine de iki kalkanın farklı olması ileride kırılgan; birleştirilmesi önerilir (düşük, mevcut).
- **Çift üretim / çifte kredi (dalların açtığı):** yok. Otoritatif koruma sunucuda: `listem-icerik.tsx:52,54` raporu her istekte taze okuyor, rapor varsa `ListeUretici` hiç render edilmiyor. `/sonuc`'taki `raporVar` bayatlasa bile sonucu değiştirmiyor. Geri tuşu yolu kapalı (`otomatikGonder` `router.replace` kullanıyor, `ListeUretici` başarıda `router.replace("/listem")`).
- **Kredi iadesi gereken yeni dal:** yok. Üretim hatasında iade `rapor-actions.ts:163-170`'te duruyor; dallar bu yolu değiştirmiyor. `SunucuYokEkrani` iade gerektirmiyor (rapor yazılmış).
- **`/api/saglik` bilgi sızıntısı:** yok. Gövde sabit `{ok:true}`, sürüm/uptime/DB durumu yok, `Cache-Control: no-store`. Kimliksiz erişim sorun değil (Docker HEALTHCHECK zaten kullanıyor); rate limit gerektirmiyor — istek başına DB/AI maliyeti sıfır.
- **`?kaynak=` üzerinden LLM prompt enjeksiyonu / SQL:** yok. `kaynak` yalnız analitik etiketi ve URL olarak dolaşıyor; `raporUret(params)`'a giren tek şey `sihirbazDogrula`'dan geçmiş seçimler ve `siraTurGecerli`'den geçmiş sayı (`rapor-actions.ts:99-110`).
- **Yeni yetkilendirme açığı:** yok. Üç dal da yeni route/action eklemiyor; `kullanicininRaporu(session.user.id)` ve `spendCredits({userId: user.id})` sahiplik kapsamını koruyor. Id tahminiyle başkasının raporuna erişilen yeni yüzey yok.
- **İstemci paketine sızan sır:** yok. Dalların dokunduğu dosyalarda `process.env` okuması yok; `RYBBIT_API_KEY` yalnız `analitik-sunucu.ts`'te ve dosya `server-only`.
---
## Metin × kod uyumsuzlukları
1. **`gizlilik/page.tsx:97-98` — "Yalnızca oturumunu açık tutmak için zorunlu çerezler kullanılır."** Kod ayrıca `PROFIL_CEREZ_ADI` çerezini yazıyor: `max-age=31536000` (1 yıl), içeriği öğrencinin **başarı sıralaması + puan türü + ilgi alanları + iller** (`sihirbaz-profil.ts:51-57`). Reklam/izleme çerezi değil, işlevsel — ama "yalnızca oturum" ifadesi yanlış ve süresi bir yıl. KVKK aydınlatma yükümlülüğü açısından metin genişletilmeli: hangi çerez, ne tutuyor, ne kadar duruyor. **Taslak cümle önerisi ([BİLAL], avukat teyidi gerekir):** "Oturum çerezinin yanında, girdiğin başarı sıralamasını ve tercih seçimlerini cihazında saklayan işlevsel bir çerez kullanılır (1 yıl); bunu tarayıcı ayarlarından silebilirsin." — Mevcut, dalların doğurduğu değil.
2. **`rapor-yok-cta.tsx:31` — "sonuç sayfasındaki sihirbazla listeni kur."** Kod sihirbazı açmıyor; `/sonuc?sihirbaz=1` `otomatikGonder`'i tetikleyip üretimi doğrudan başlatıyor (`sihirbaz-cagri-karti.tsx:218-228`). Yanlış vaat + bedel bildirilmeden harcama. Bkz. G6.
3. **`program-ekle-butonu.tsx:73` / `liste-cekmecesi.tsx:283`** — bkz. G2: "riskini gösteririz" vaadi 3 kredilik üretimle bitiyor.
4. **Uyum — 18 yaş altı:** bu üç dal yeni bir veri toplama noktası açmıyor, ama P3 ile ücretli aksiyona ulaşan tık sayısı azalıyor. Mesafeli satış/cayma hakkı metinlerinde değişiklik gerekmiyor (kredi harcaması satın alma değil, satın alınmış kredinin kullanımı) — yine de G2'nin çözümü bedel şeffaflığının tek gerçek koruması.
## KVKK — yeni kişisel veri akışı
- **Üç dalın doğurduğu yeni akış: yok.** `kaynak` kişisel veri değil; `liste_uretim_basladi` özellikleri (`kaynak`, `paketli`, `profil: var|yok`) kişisel veri taşımıyor ve `src/lib/analitik.ts:10-11` ham sıralama kuralına uyuyor — sıralama hiçbir yeni yerde gönderilmiyor. `GirisLinki` bilinçli olarak yalnız pathname taşıyor, query taşımıyor (doğru tercih).
- **Mevcut, dikkat çekmek istediğim iki akış (dalların dışı):**
- `liste-giris-url.ts:15-17` pathname **+ query**'yi callback'e koyuyor. Eski tip `/sonuc?sira=123456&tur=say` adresinde bu, öğrencinin **ham başarı sıralamasını** `/giris?callback=…` üzerinden better-auth'a, oradan magic-link doğrulama URL'ine ve **Resend ile gönderilen e-postanın gövdesine** taşıyor (`auth.ts:19-24` `hedef.search = kaynak.search`). Gizlilik metninin "ham sıralama analitiğe gönderilmez" sözü analitik için doğru, ama e-posta sağlayıcısı için böyle bir söz yok ve akış var. **orta**, mevcut.
- `rybbit-identify.tsx:29-30` e-posta adresini ve adı Rybbit trait'i olarak gönderiyor. Gizlilik metni bunu **açıkça yazıyor** (`gizlilik/page.tsx:102-105`) ve Rybbit kendi sunucumuzda → uyumlu, aksiyon gerekmiyor.
---
## Dal dal merge hükmü
| Dal | Hüküm | Koşul |
|---|---|---|
| `olcum/liste-uretim-basladi` (P2) | **Şu düzeltmeden sonra merge edilebilir** | **G3 zorunlu** (`giris_donusu` etiketi yanlış — düzeltilmezse dalın tek amacı olan ölçüm yanlış veri üretir, üstelik seri kırılması yaratır). **G4 önerilir** (aynı düzeltmeyle tek noktada çözülüyor: `kaynak`ı `listem/page.tsx`'te allowlist'ten geçirip `ListemIcerik`'e temiz ver). Güvenlik açısından merge engeli yok. |
| `funnel/arti-olu-ucu` (P3) | **Şu düzeltmeden sonra merge edilebilir** | **G2**: + toast'ı ve çekmece panelinin metni akışın gerçek sonucuna eşitlenmeli (cümle `[BİLAL]`). Kod olduğu gibi kalabilir — rıza anı (`(3 kredi)` butonu) ve `raporVar`/`eslesir` korumaları sağlam, çifte harcama yolu açmıyor. Metin düzeltilmeden merge edilirse 17–19 yaş kullanıcıya yanlış vaatle kredi harcatmış oluruz. |
| `funnel/listem-girisi` (P4) | **Şu düzeltmeden sonra merge edilebilir** | **G1 zorunlu**: `giris-linki.tsx`'e yol beyaz listesi eklenmeli, yoksa ASCII dışı/yüzde-kodlu adreslerde giriş tamamen kırılıyor (açık yönlendirme değil ama daha kötü: kullanıcı kaybı). Navbar `/listem` linki ve boş durum CTA'sı güvenlik açısından temiz. Sıra notu: `listem-bos-cta.tsx:35` `kaynak=bos_durum` kullanıyor, bu değer `olcum` dalında tanımlı — CEO'nun "P2 önce merge edilir" kararı korunmalı (aksi hâlde zararsız ama ölçülmeyen bir parametre kalır). |
| Çalışma ağacı — `liste-uretici.tsx` | **Merge edilebilir (düzeltme koşulu yok)** | "Listen oluşturuldu ve hesabına kaydedildi — kredin yeniden harcanmaz" iddiası doğrulandı. G7 (fail-closed yanlış alarm) isteğe bağlı iyileştirme. |
---
## Bilal'den istenen
1. **G2'nin cümlesi** — + toast'ı ve çekmece panelindeki "sıralamanı gir → riskini gösterelim" metni, akış 3 kredilik listeyle bittiği için değişmeli; yeni cümleyi sen yazmalısın (**~10 dk**).
2. **`next` 16.2.10 → 16.2.11 yama yükseltmesi onayı** — 9 advisory kapanıyor, biri gerçekten ulaşılabilir (server action DoS); yama sürümü olduğu için build riski düşük (**~20 dk, build dahil**).
3. **Gizlilik metnindeki çerez cümlesi** — "yalnızca oturum çerezi" ifadesi 1 yıllık tercih profili çerezini kapsamıyor; önerdiğim taslak cümle için avukat teyidi gerekir (**~5 dk karar, teyit ayrı**).