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>
426 lines
38 KiB
Markdown
426 lines
38 KiB
Markdown
# 28 — CTO şartnamesi: G1, G3, G2+G5
|
||
|
||
Hazırlayan: CTO ajanı · Taban commit: **`9bd448b`** (`main`, push edilmiş; `origin/main == main`).
|
||
Kaynak kararlar: `05-ceo-kararlari.md` §3, `24-ceo-kapanis.md` §A/§D, `04-sifir-odeme-teshisi.md` Ö1–Ö5, `00-kurucu-brief.md` ("sade ve basit, over-engineering yok").
|
||
Yöntem: **yalnız okuma**. Kod değiştirilmedi, commit atılmadı, `pnpm install`/`build`/`typegen`/`tsc`/`lint` **koşulmadı** (disk kısıtı — orkestratör talimatı). `git status` bu raporun yazımı dışında değişmedi.
|
||
İşaret: **[D]** bu gece açıp satırını doğruladığım kod · **[Ç]** koddan çıkarım (çalıştırılmadı).
|
||
|
||
---
|
||
|
||
## Özet (5 madde)
|
||
|
||
1. **CEO'nun satır numaralarının çoğu tuttu, ikisi tutmadı.** `rapor-actions.ts` bu gece `9bd448b` ile değişti: liste harcaması artık `98-99/118-124` değil **`153-158`**, iade **`212-217`**, revizyon harcaması **`285-290`**, revizyon iadesi **`339-344`**. Ayrıca `giris-karti.tsx` `src/features/auth/` altında **değil**, `src/features/kullanici/components/giris-karti.tsx`. Aşağıdaki tüm atıflar `9bd448b` üzerinde tek tek açılarak yazıldı. [D]
|
||
2. **G3'ün gizli dördüncü satırı var.** `spendCredits`/`grantCredits` koşullansa bile `rapor-actions.ts:243` ve `:363`'teki `kredi: user.creditBalance - RAPOR_KREDI` paketliye **düşmemiş krediyi düşmüş gibi gösterir**; ayrıca `tercih-degisti-modali.tsx` paketliye "Listemi güncelle — 3 kredi" yazmaya devam eder. Tek bir `maliyet` değişkeni dört yeri birden kapatıyor — kapsam bu kadar büyütülmeli, daha fazlası değil. [D]
|
||
3. **G1'in CTA'sı için `?kaynak=` allowlist'i şart.** `/listem?uret=1&kaynak=tadimlik` yazmadan önce `uretim-basladi-olayi.tsx:25-41`'deki `IZINLI_KAYNAKLAR`'a `"tadimlik"` eklenmezse değer `"bilinmiyor"`a düşer ve bu değişikliğin ölçümü kaybolur. Dosyanın kendi notu bunu zaten emrediyor. [D]
|
||
4. **İki sessiz build tuzağı var ve ikisi de G1'in metin işinde patlar:** `rapor-maske.ts` `import "server-only"` (satır 6), `credits.ts` `appdb`'yi import ediyor (satır 2) — **ikisi de `"use client"` olan `tadimlik-satiri.tsx`'e import EDİLEMEZ**. Yeni CTA cümlesi `ACIK_SATIR`/`DENEME_KREDISI` sabitlerine uzanamaz; sayı gerekiyorsa cümle sayısız yazılır. [D]
|
||
5. **`/meraklisina` şeması üç pakette de değişmiyor.** `huni-semasi.tsx`'teki `SEMA` yalnızca sihirbaz adımları, aday havuzu, 24'lük iskelet, filtre gevşetme ve havuz-dışı kuralını belgeliyor (satır 11-41). G1 sayfa sırası + CTA hedefi, G3 kredi muhasebesi, G5 metin değiştiriyor — hiçbiri bu beş şeyden biri değil. **Yazılımcı `huni-semasi.tsx`'e dokunmayacak.** [D]
|
||
|
||
---
|
||
|
||
## Dosya sahipliği tablosu
|
||
|
||
Paketler **teker teker** koşacak (disk), yine de kümeler ayrık tutuldu — dal sırası bozulsa bile çakışma olmaz.
|
||
|
||
| Dosya | G1 `funnel/sonuc-ilk-ekran` | G3 `odeme/paket-vaadi` | G2+G5 `odeme/kasa-ve-metin` |
|
||
|---|:--:|:--:|:--:|
|
||
| `src/app/sonuc/page.tsx` | ✅ | | |
|
||
| `src/features/liste/components/manuel-harita.tsx` | ✅ | | |
|
||
| `src/features/rapor/components/tadimlik-satiri.tsx` | ✅ | | |
|
||
| `src/features/sihirbaz/sihirbaz-sabitler.ts` | ✅ | | |
|
||
| `src/features/sihirbaz/components/sihirbaz-cagri-karti.tsx` | ✅ | | |
|
||
| `src/features/rapor/components/uretim-basladi-olayi.tsx` | ✅ | | |
|
||
| `src/features/rapor/rapor-actions.ts` | | ✅ | |
|
||
| `src/features/rapor/components/listem-icerik.tsx` | | ✅ | |
|
||
| `src/features/rapor/components/tercih-degisti-modali.tsx` | | ✅ | |
|
||
| `src/features/odeme/odeme-actions.ts` | | | ✅ |
|
||
| `src/features/odeme/components/satin-al-form.tsx` | | | ✅ |
|
||
| `src/features/odeme/components/paket-satinal.tsx` | | | ✅ |
|
||
| `src/features/kullanici/components/giris-karti.tsx` | | | ✅ |
|
||
| `src/lib/analitik.ts` | | | ✅ |
|
||
|
||
**Hiçbir pakette yok (yasak listesi):** `src/features/rapor/components/liste-uretici.tsx` (Bilal'in dosyası — `9bd448b` ile commit'li ama gece kuralı gereği dokunulmaz), `docs/ekip/BACKLOG.md`, `docs/ekip/KARARLAR.md`, `AGENTS.md`, `content/rehber/**`, `data/**`, `src/features/pazarlama/components/huni-semasi.tsx`, `src/lib/credits.ts`.
|
||
|
||
### Çakışma kararları
|
||
|
||
1. **`src/lib/analitik.ts` → G2'nin.** G1'in `tadimlik_goruntulendi` olayında bir **seri kırılması** yaratacağı doğru (olay bugün ~2.200 px aşağıdaydı, yarın ilk ekranda olacak; 30 günlük değer 0 → `01-analitik-bulgular`), ve bu repoda seri kırılmasını `analitik.ts`'in `OlayAdi` yorumuna yazma geleneği var (`program_eklendi`, satır 29-31). Buna rağmen G1 bu dosyaya **dokunmaz**: G2 aynı birliğe `odeme_hata` ekliyor, iki dal bitişik satırlarda çakışır. G1 seri kırılmasını (a) `tadimlik-satiri.tsx:100-102`'deki `useGorunumOlayi` çağrısının üstündeki yoruma, (b) commit mesajına yazar. Kalıcı notun `analitik.ts`'e taşınması backlog önerisi #B1.
|
||
2. **`paket-satinal.tsx` ve `tercih-degisti-modali.tsx` → G5/G3'ün, A2'nin değil.** CEO'nun A2 paketi (`odeme/paket-adi`, "Tercih Dönemi Paketi" → "KolayTercih Paketi") bu iki dosyaya da girmek zorunda: ad **8 dosyada** geçiyor ve ikisi bu dalların içinde (`paket-satinal.tsx:64`, `tercih-degisti-modali.tsx:329`) [D]. A2 CEO'nun sırasında **10.** ve kesme sırasının başında; bu yüzden A2 en sonda koşar, G1/G3/G5 dalları yazıldıktan **sonra** taban alır. G1/G3/G5'teki hiçbir yazılımcı paket adına dokunmaz.
|
||
3. **`liste-uretici.tsx` kimsenin değil.** G3 uygulandığında o dosyadaki `hasPaket` dalı ("+30 kredi yükle") liste üretimi için **ölü koda** dönüşür (paketli artık hiç `KREDI` kodu alamaz, bkz. G3 adım 1). Bu doğru ama zararsız bir tutarsızlıktır; dosya Bilal'e ait olduğu için **düzeltilmez**, backlog önerisi #B2 olarak kaydedilir.
|
||
|
||
---
|
||
|
||
## Tüm yazılımcılar için ortak kurallar
|
||
|
||
1. Yalnız orkestratörün verdiği **worktree + dalda** lokal commit. Push yok, merge yok, `main`'e commit yok.
|
||
2. **`git add -A` / `git add .` yasak.** Yalnız kendi dosya kümenden, yol vererek ekle. Commit öncesi `git status --porcelain` çıktısında kümen dışında bir şey görünüyorsa dur ve raporla.
|
||
3. **Doğrulama sırası:** `pnpm exec next typegen && pnpm exec tsc --noEmit && pnpm lint`. Dev sunucusu yok, tarayıcı yok, `pnpm build` **yok** (disk ~5 GB; tam build'i Bilal sabah C3 komut bloğunda tek seferde alır).
|
||
4. **Taze worktree'de `next typegen` olmadan `tsc` baseline'da kırıktır** — `PageProps` gibi global tipler `.next/types`'tan gelir. Kırmızı çıktıyı kendi değişikliğine yorma; önce typegen koş.
|
||
5. **Worktree'de `node_modules` symlink'i Turbopack'te patlar** — klon kullanılır (`cp -Rc ../kolaytercih/node_modules node_modules`). Kurulumu orkestratör yapar; `pnpm install` çalıştırma.
|
||
6. `next build` env'siz koşar: modül yüklenirken env zorunlu kılan kod yazma. Bu üç pakette yeni env yok.
|
||
7. **Next'e özgü bir API'ye dokunmadan önce ilgili dokümanı oku** (her paketin altında yolu yazılı). Eğitim verisindeki Next bu sürüm değil.
|
||
8. AGENTS.md: rozet gerekiyorsa `SectionEyebrow`, CTA'da ikon **metnin sonunda** `<ArrowRight className="size-4" aria-hidden />`, `Sparkles` yok; modal kapatma çarpısı `DialogContent` varsayılanı. Sihirbaz/liste **mimarisi** değişirse `/meraklisina` şeması aynı commit'te — bu üç pakette **değişmiyor** (bkz. Özet #5), dokunma.
|
||
9. Uydurma sayı yok: ekranda görünen her rakam ya tek kaynak sabitten (`URUNLER`, `RAPOR_KREDI`, `ACIK_SATIR`) gelir ya da hiç yazılmaz.
|
||
10. Rapor: `docs/gece-vardiyasi/2026-09-22/` altına, orkestratörün verdiği numarayla; kabul kriterlerinin her birinin çıktısını yapıştır.
|
||
|
||
---
|
||
|
||
# G1 · `funnel/sonuc-ilk-ekran`
|
||
|
||
**Amaç:** Ödeme öncesi tek gerçek önizleme (tadımlık) `/sonuc`'un ilk ekranında görünsün ve kullanıcıyı giriş sonrası listenin üretildiği yere göndersin.
|
||
|
||
**Dal:** `funnel/sonuc-ilk-ekran` · **Taban:** `9bd448b` · **Öncelik: 1 (kesilmez).**
|
||
|
||
### Dokunulacak dosyalar (tam liste)
|
||
|
||
| Dosya | Satır | Ne |
|
||
|---|---|---|
|
||
| `src/features/liste/components/manuel-harita.tsx` | 67-80 | Boş placeholder yerine `null` |
|
||
| `src/app/sonuc/page.tsx` | 100-118 | Tadımlık tablodan önce + yorum düzeltmesi |
|
||
| `src/features/sihirbaz/sihirbaz-sabitler.ts` | ~165 (`sonucHref` yanı) | `listemUretHref` export edilir (yeni fonksiyon, taşınma) |
|
||
| `src/features/sihirbaz/components/sihirbaz-cagri-karti.tsx` | 20-26, 195, 231, 260 | Yerel `listemUretHref` silinir, import edilir |
|
||
| `src/features/rapor/components/uretim-basladi-olayi.tsx` | 25-41 | `IZINLI_KAYNAKLAR`'a `"tadimlik"` |
|
||
| `src/features/rapor/components/tadimlik-satiri.tsx` | 28, 100-102, 111, 114, 186 | CTA hedefi, seri-kırılması yorumu, `first:mt-0`, yanlış iddia |
|
||
|
||
### Kapsam dışı (yazılımcı taşmasın)
|
||
|
||
- Maskenin kaç satır açtığı (`ACIK_SATIR = 3`) — **değişmiyor** (24-ceo-kapanis R5).
|
||
- `/sonuc` tablosunun sıralaması, filtreleri, `<h1>` eksikliği (A3 ayrı dal), Suspense fallback'inin iskeleti (`sonuc/page.tsx:45-54`) — fallback bugün de haritayı temsil etmiyor (pill + başlık + `h-36` + tablo satırları = `ProgramTablosu`'nun başlığı), boş harita kalkınca yanlışlığı **artmıyor**. [Ç]
|
||
- Tadımlığın başka yüzeylere (`/`, `/paket`) taşınması.
|
||
- Profil çerezi olmayan ziyaretçiye özel CTA dalı yazmak — **bilerek yapılmayacak**, gerekçesi aşağıda (Riskler #2).
|
||
- `huni-semasi.tsx`, `analitik.ts`, `liste-uretici.tsx`.
|
||
|
||
### Adım adım
|
||
|
||
**1) Boş harita ilk ekranı işgal etmesin** — `manuel-harita.tsx:67-80`
|
||
`if (liste.length === 0) return null;` Yorum da düzeltilir: bugünkü not "197 KB'lık il geometrisi inmesin diye placeholder alanı rezerve eder" diyor; yeni not, boş durumda hiç yer tutulmadığını ve ilk eklemede haritanın belireceğini söylesin. `TercihHaritasiLazy` zaten `dynamic` — ölçü davranışı değişmez. [D]
|
||
|
||
**2) Tadımlık tablodan önce** — `sonuc/page.tsx:103-118`
|
||
Yeni sıra: `<ManuelHarita />` → `<TadimlikBolumu … />` → `<SonucProgramTablosu … />` → `<SonucSihirbazi … />` → dipnot. Satır 100-102'deki "Sayfa hiyerarşisi: önce Türkiye haritası, sonra liste" yorumu yeni sıraya göre yeniden yazılır (neden: tadımlık ödeme öncesi tek gerçek önizleme, ilk ekranda durur; harita yalnız manuel liste doluyken görünür). Props değişmez, bileşenlerin içine dokunulmaz.
|
||
|
||
**3) Tadımlık ilk eleman olduğunda tepede boşluk bırakmasın** — `tadimlik-satiri.tsx:114`
|
||
`className="mt-16 min-w-0"` → `className="mt-16 min-w-0 first:mt-0"`. Gerekçe: `ManuelHarita` `null` döndüğünde bu `<section>` `main`'in **gerçek ilk DOM çocuğu** olur (JSX yorumları DOM düğümü üretmez), `:first-child` eşleşir ve `main`'in `py-12`'si tek başına yeterli üst boşluğu verir; harita görünürken `mt-16` aynen çalışır. Tek utility, koşullu prop yok. [Ç]
|
||
|
||
**4) `listemUretHref` tek kaynağa** — `sihirbaz-sabitler.ts` + `sihirbaz-cagri-karti.tsx`
|
||
`sihirbaz-cagri-karti.tsx:25-27`'deki yerel fonksiyon `sihirbaz-sabitler.ts`'e (`sonucHref`'in hemen altına) taşınır ve export edilir; üstündeki "`uret=1` HER ZAMAN ilk parametre kalmalı — `giris-karti.tsx` funnel metnini `startsWith("/listem?uret=1")` ile seçiyor" yorumu da birlikte taşınır. Çağrı yerleri (`:195`, `:231`, `:260`) import'a çevrilir, davranış birebir aynı kalır.
|
||
*Neden tek satırlık kopyala-yapıştır değil:* bu sözleşmenin kopyası bugün **üç** dosyada yorum olarak yaşıyor (`listem-icerik.tsx:48-50`, `sihirbaz-cagri-karti.tsx:22-24`, `giris-karti.tsx:28-31`) [D]; dördüncü bir literal kopya, funnel metnini sessizce kaybettiren bir hata sınıfı açar. Taşıma 2 satır, riski sıfır.
|
||
|
||
**5) Ölçüm yüzeyi allowlist'e** — `uretim-basladi-olayi.tsx:25-41`
|
||
`IZINLI_KAYNAKLAR`'a `"tadimlik"` eklenir + tek satır yorum ("/sonuc'taki girişsiz tadımlık CTA'sı"). Dosyanın kendi kuralı: "Yeni bir üretim yüzeyi eklerken değerini önce buraya ekle, sonra href'e koy."
|
||
|
||
**6) CTA doğru yere gitsin** — `tadimlik-satiri.tsx:111`
|
||
`const girisUrl = \`/giris?callback=${encodeURIComponent(listemUretHref("tadimlik"))}\`;`
|
||
Import satırı 28 düzeltilir: `sonucHref` **kaldırılır** (başka kullanımı yok → `no-unused-vars` lint hatası verir), `listemUretHref` eklenir; `PROFIL_DEGISTI_EVENT` kalır. `onClick`'teki `olay("giris_cta_tiklandi", { kaynak: "tadimlik" })` **aynen kalır** (mevcut seri korunur).
|
||
Doğrulanmış zincir: `/giris` callback'i `/^\/(?![/\\])/` kalkanından geçer (`giris-karti.tsx:18-19`) ✅ · `startsWith("/listem?uret=1")` funnel metni korunur ✅ · dönüşte `listem/page.tsx:29-31` → `ListemIcerik uret` → `ListeUretici` üretimi kendiliğinden başlatır (`liste-uretici.tsx:243-256`) ✅. [D]
|
||
|
||
**7) Seri kırılması yorumu** — `tadimlik-satiri.tsx:100-102`
|
||
`useGorunumOlayi("tadimlik_goruntulendi", …)` çağrısının üstüne 2-3 satır: olayın bu değişiklikten önce sayfanın ~2.200 px altında yaşadığı, sonrasında ilk ekranda olduğu, iki dönemin karşılaştırılamayacağı. (`analitik.ts`'e **yazılmaz** — çakışma kararı #1.)
|
||
|
||
**8) Teslim edilmeyen iddia kalkar** — `tadimlik-satiri.tsx:186`
|
||
`24 satırın tamamı için giriş yap — 5 deneme kredin hazır` → **`Giriş yap ve listeni oluştur`** (+ mevcut `<ArrowRight className="size-4" aria-hidden />` aynen kalır — AGENTS.md CTA deseni).
|
||
Gerekçe: maske paketsize 24 satırın **3'ünün** analizini açıyor (`rapor-maske.ts:12, 28-46`); "tamamı" teslim edilmiyor. Bu commit **yeni vaat eklemez**, yalnız yanlış olanı kaldırır. Üstteki `<p>`'deki "Bu, 24 satırlık Yapay Zeka listenden yalnızca bir örnek." cümlesi **doğrudur ve kalır** (üretilen liste gerçekten 24 satır).
|
||
|
||
**9) `[Bilal]` commit'i — CTA'nın yeni vaadi** (ayrı, en son commit)
|
||
Önerilen: buton `Kendi listemi oluştur`, alt satır (`:174-176`) `Kredi kartı gerekmez · Google ya da e-posta ile 30 saniyede · Giriş sonrası liste hemen üretilir`.
|
||
**Kısıt:** bu dosya `"use client"`. `ACIK_SATIR` (`rapor-maske.ts`, `import "server-only"` satır 6) ve `DENEME_KREDISI`/`RAPOR_KREDI` (`credits.ts`, satır 2'de `./appdb` import ediyor) **import edilemez** — build'i kırar. Sayı gerekiyorsa cümle sayısız yazılır; elle "3"/"5" yazmak yasak (tek kaynak kuralı). Commit en sona konur ki Bilal `git reset --hard HEAD~1` ile tek hamlede düşürebilsin.
|
||
|
||
### Kabul kriterleri (tarayıcısız, komutla)
|
||
|
||
```sh
|
||
# 1) Tadımlık tablodan önce (ilk sayı küçük olmalı)
|
||
grep -n "<TadimlikBolumu\|<SonucProgramTablosu$" src/app/sonuc/page.tsx
|
||
|
||
# 2) Boş harita hiç render edilmiyor
|
||
grep -n "liste.length === 0" src/features/liste/components/manuel-harita.tsx # 1 sonuç
|
||
grep -c "haritada belirir" src/features/liste/components/manuel-harita.tsx # 0
|
||
grep -c "haritada belirir" -r src/ # 0
|
||
|
||
# 3) CTA doğru hedefe gidiyor, eski hedef kalmadı
|
||
grep -n "listemUretHref" src/features/rapor/components/tadimlik-satiri.tsx # 1
|
||
grep -c "sonucHref" src/features/rapor/components/tadimlik-satiri.tsx # 0
|
||
grep -n "export function listemUretHref" src/features/sihirbaz/sihirbaz-sabitler.ts # 1
|
||
grep -c "function listemUretHref" src/features/sihirbaz/components/sihirbaz-cagri-karti.tsx # 0
|
||
|
||
# 4) Ölçüm yüzeyi allowlist'te
|
||
grep -n '"tadimlik"' src/features/rapor/components/uretim-basladi-olayi.tsx # 1
|
||
|
||
# 5) Teslim edilmeyen iddia yok
|
||
grep -rc "24 satırın tamamı" src/ # 0
|
||
|
||
# 6) Şema ve yasak dosyalar el değmemiş
|
||
git diff --name-only HEAD~N | grep -E "huni-semasi|analitik.ts|liste-uretici|credits.ts" # boş
|
||
|
||
# 7) Tipler ve lint
|
||
pnpm exec next typegen && pnpm exec tsc --noEmit && pnpm lint
|
||
```
|
||
|
||
Ek el kontrolü (dosya:satır okuyarak): `TadimlikBolumu` girişli kullanıcıda ve havuz boşken **hâlâ `null` dönüyor** (`tadimlik-bolumu.tsx:18-21` değişmedi) · `ManuelHarita` liste doluyken haritayı aynen render ediyor.
|
||
|
||
### Riskler ve tuzaklar
|
||
|
||
1. **`sonucHref` import'unu silmeyi unutmak** → lint kırmızısı. (Adım 6.)
|
||
2. **Profil çerezi olmayan ziyaretçi.** `/listem?uret=1`, seçim yoksa "profil-yok" → boş durum + sihirbaz CTA'sı gösterir (`liste-uretici.tsx:243-251`); **kredi harcanmaz, hata ekranı çıkmaz** [D]. Bu durum yalnızca eski `?sira=` linkiyle gelen ziyaretçide oluşabilir, çünkü geçerli bir profil `tercihProfiliDogrula` gereği **en az 1 ilgi alanı içermek zorundadır** (`sihirbaz-sabitler.ts:90, 143-145`) [D]. Bu yüzden CTA'ya koşullu ikinci bir dal **yazılmayacak** — kurucunun "over-engineering yok" kısıtı.
|
||
3. **Giriş dönüşünde onaysız 3 kredi.** `giris-linki.tsx:13-16` navbar butonu için bunu bilerek yasaklıyor; burada sorun değil çünkü kullanıcı "listemi oluştur" diyen bir CTA'ya **açıkça tıklıyor** ve bu, `hazir_cta` (`sihirbaz-cagri-karti.tsx:260`) ile birebir aynı, onaylı desen. [D] CTA metni bu yüzden üretimi söylemeli (adım 8-9).
|
||
4. **Layout kayması:** boş harita `null` iken ilk "+" tıklamasında harita belirir ve tablo aşağı iner. Bugün de placeholder→harita geçişi var; kaybı kabul edilen bilinçli takas (CEO §3 G1-b).
|
||
5. `tadimlik_goruntulendi` sayısı bir gecede 0'dan yüksek bir sayıya fırlayacak — **kırık ölçüm değil, kazanılan payda**. Adım 7 bunu koda yazar.
|
||
|
||
### Commit planı
|
||
|
||
1. `fix(sonuc): boş harita ilk ekranı işgal etmez` — `manuel-harita.tsx`
|
||
2. `fix(sonuc): tadımlık tablonun üstüne alınır` — `sonuc/page.tsx`, `tadimlik-satiri.tsx` (`first:mt-0`)
|
||
3. `refactor(sihirbaz): listemUretHref tek kaynağa taşınır` — `sihirbaz-sabitler.ts`, `sihirbaz-cagri-karti.tsx`
|
||
4. `fix(tadimlik): CTA girişten dönüşte üretimi başlatır` — `tadimlik-satiri.tsx`, `uretim-basladi-olayi.tsx`
|
||
5. `content(tadimlik): teslim edilmeyen "24 satırın tamamı" iddiası kalkar` — `tadimlik-satiri.tsx`
|
||
6. `[Bilal] content(tadimlik): CTA'nın yeni vaadi` — `tadimlik-satiri.tsx` *(en son, tek başına düşürülebilir)*
|
||
|
||
### Okunacak Next dokümanı (kod yazmadan önce)
|
||
|
||
- `node_modules/next/dist/docs/01-app/01-getting-started/05-server-and-client-components.md` — client sınırı ve `server-only` (Adım 9'un tuzağı).
|
||
- `node_modules/next/dist/docs/01-app/01-getting-started/04-linking-and-navigating.md` — `<Link href>` ve sorgu parametresi.
|
||
|
||
---
|
||
|
||
# G3 · `odeme/paket-vaadi`
|
||
|
||
**Amaç:** Paket sayfasındaki söz kodla eşitlensin — paketli kullanıcıdan liste ve revizyon için kredi düşmesin, "60 danışman sorusu" gerçekten 60 olsun.
|
||
|
||
**Dal:** `odeme/paket-vaadi` · **Taban:** `9bd448b` · **Öncelik: 2 (kesilmez).** · **Merge öncesi `guvenlik-uyum` denetimi zorunlu.**
|
||
|
||
### Dokunulacak dosyalar
|
||
|
||
| Dosya | Satır | Ne |
|
||
|---|---|---|
|
||
| `src/features/rapor/rapor-actions.ts` | 152-158, 212-217, 243, 285-290, 339-344, 363 | `maliyet` değişkeni; 4 harcama/iade + 2 bakiye satırı |
|
||
| `src/features/rapor/components/listem-icerik.tsx` | 167 | `raporKredi` prop'u paketliye 0 iner |
|
||
| `src/features/rapor/components/tercih-degisti-modali.tsx` | 129, 188, 250, 275 | 0 bedelde "kredi" dili yerine "pakete dâhil" |
|
||
|
||
### KRİTİK KISIT (CEO kararı, tartışmaya kapalı)
|
||
|
||
`spendCredits` ve `grantCredits` çağrıları **KALDIRILMAZ**, yalnız **tutarları koşullanır**. Gerekçe koddan doğrulandı:
|
||
- `credit_ledger` üzerinde `uniqueIndex("ledger_reason_ref").on(reason, refId)` var (`src/lib/appdb/schema.ts:133`) [D]. Üretimin tek idempotency çapası bu. Çağrı kaldırılırsa aynı `requestId` ile ikinci üretim `DUPLICATE` dönmez → BACKLOG #1'deki çifte üretim kapısı yeniden açılır.
|
||
- `amount: 0` ile `spendCredits` **INSUFFICIENT dönmez**: `gte(creditBalance, 0)` her zaman eşleşir ve `updatedAt` değiştiği için `rowsAffected = 1` olur (`credits.ts:65-74`) [Ç — SQLite `rowsAffected` semantiği; QA'nın DB duman testiyle teyit edilmeli].
|
||
- İade dalındaki `grantCredits(delta: 0, reason: "refund")` satırı **silinmemeli**: `rapor-actions.ts:171-184` ve `:303-316` "önceki deneme başarısız mıydı" sorusunu tam olarak bu `refund` satırının varlığıyla cevaplıyor. Satır yazılmazsa paketlinin başarısız denemesi `SURUYOR` ("Listen zaten hazırlanıyor") gibi görünür — yanlış mesaj. [D]
|
||
- `delta`'yı koşullamazsak paketliye her başarısız üretimde **bedava 3 kredi** yazılır. (CEO'nun uyardığı sızıntı.)
|
||
|
||
### Kapsam dışı
|
||
|
||
- Fiyat (299 TL), kredi adedi (60/30), top-up kuralları, maske (`ACIK_SATIR`) — hepsi R5 ile kapalı.
|
||
- Sohbet kredisi (`spendCreditForMessage`, mesaj başına 1) — **doğru davranış, dokunulmaz**; G3'ün tüm amacı bu 60 sorunun gerçekten 60 kalması.
|
||
- `credits.ts`, `liste-uretici.tsx`, paket adı (A2), `kredi-hatirlatma.ts`.
|
||
- `/paket`, `/` ve `listem-govde.tsx`'teki "60 danışman sorusu" metinleri: **üçü de `URUNLER.paket.credits`'ten türüyor** (`app/page.tsx:201`, `paket-satinal.tsx:40`, `listem-govde.tsx:345`) [D] — G3 sonrası hiçbir metin değişikliği gerektirmeden doğru hâle gelirler. Dokunma.
|
||
|
||
### Adım adım
|
||
|
||
**1) `listeOlustur` yolu** — `rapor-actions.ts:152` civarı (fonksiyon: `listeOlusturKilitli`)
|
||
`spendCredits` çağrısının hemen üstüne:
|
||
```ts
|
||
// Paket vaadi (docs/urun/vizyon.md): liste ve revizyon pakete dâhil; krediler
|
||
// yalnız danışman sorusu için. Çağrı BİLEREK duruyor — ledger'daki
|
||
// UNIQUE(reason, ref_id) (appdb/schema.ts:133) üretimin tek idempotency
|
||
// çapası; paketliye delta 0 satır yazılır, aynı requestId ikinci kez
|
||
// DUPLICATE döner.
|
||
const maliyet = user.hasPaket ? 0 : RAPOR_KREDI;
|
||
```
|
||
Kullanım yerleri:
|
||
- `:155` `amount: RAPOR_KREDI` → `amount: maliyet`
|
||
- `:165` hata metni `${RAPOR_KREDI} kredi gerekli` → **değişmez** (bu dal yalnız `maliyet > 0` iken erişilebilir).
|
||
- `:214` `delta: RAPOR_KREDI` → `delta: maliyet`
|
||
- `:243` `kredi: user.creditBalance - RAPOR_KREDI` → `kredi: user.creditBalance - maliyet`
|
||
|
||
**2) `listeRevize` yolu** — `rapor-actions.ts:285` civarı
|
||
Aynı `maliyet` satırı (`user.hasPaket ? 0 : RAPOR_KREDI`) `spendCredits`'ten önce tanımlanır; `:287 amount`, `:341 delta`, `:363 kredi` aynı şekilde bağlanır. Not olarak yazılır: `:256`'daki `if (!user.hasPaket) return PAKET` guard'ı yüzünden burada `maliyet` **her zaman 0**'dır; ifade guard değişirse davranışın bozulmaması için koşullu bırakılıyor.
|
||
|
||
**3) Sunucu davranışı dışına taşma yasak.** `krediBittiIsaretle`, `uretimKilidiAl/Birak`, `reports` yazımı, maskeleme dalları (`user.hasPaket ? sonuc : raporMaskele(sonuc)`) **aynen kalır**.
|
||
|
||
**4) Arayüz aynı şeyi söylesin** — `listem-icerik.tsx:167` + `tercih-degisti-modali.tsx`
|
||
`raporKredi={RAPOR_KREDI}` → `raporKredi={user.hasPaket ? 0 : RAPOR_KREDI}`.
|
||
Modalda tek türetilmiş bayrak: `const ucretsiz = raporKredi === 0;` ve üç metin yeri:
|
||
- `:188` "…geçer ve {raporKredi} kredi düşer." → ücretsizse "…geçer; güncelleme paketine dâhil, kredi düşmez."
|
||
- `:250` "Güncelleme {raporKredi} kredi; bakiyen {kredi} kredi." → ücretsizse bu satır **gösterilmez**.
|
||
- `:275` buton "Listemi güncelle — {raporKredi} kredi" → ücretsizse "Listemi güncelle" (ok ikonu deseni aynen).
|
||
`:129 krediYeter` ve `KrediYetersiz` dalına dokunulmaz: `kredi >= 0` her zaman doğru olduğu için o dal paketliye zaten hiç render edilmez. [Ç]
|
||
*Neden bu adım zorunlu:* aksi hâlde kullanıcıya "3 kredi düşer" denip düşülmez — yalanın yönü değişir, kalitesi değişmez.
|
||
|
||
### Kabul kriterleri
|
||
|
||
```sh
|
||
# 1) Çağrılar duruyor (idempotency çapası sağlam)
|
||
grep -c "spendCredits(" src/features/rapor/rapor-actions.ts # 2
|
||
grep -c "grantCredits(" src/features/rapor/rapor-actions.ts # 2
|
||
|
||
# 2) Tutarlar koşullu; sabit tutar hiçbir harcama/iade satırında kalmadı
|
||
grep -c "hasPaket ? 0 : RAPOR_KREDI" src/features/rapor/rapor-actions.ts # 2
|
||
grep -n "amount: maliyet\|delta: maliyet" src/features/rapor/rapor-actions.ts # 4 satır
|
||
grep -c "delta: RAPOR_KREDI\|amount: RAPOR_KREDI" src/features/rapor/rapor-actions.ts # 0
|
||
grep -c "creditBalance - RAPOR_KREDI" src/features/rapor/rapor-actions.ts # 0
|
||
|
||
# 3) requestId/refId zinciri değişmedi
|
||
grep -n "refId: requestId\|refId: input.requestId" src/features/rapor/rapor-actions.ts # 4 satır
|
||
|
||
# 4) Arayüz aynı şeyi söylüyor
|
||
grep -n "raporKredi={" src/features/rapor/components/listem-icerik.tsx # hasPaket ? 0 : RAPOR_KREDI
|
||
grep -c "ucretsiz" src/features/rapor/components/tercih-degisti-modali.tsx # >=3
|
||
|
||
# 5) Paket vaadi metinleri tek kaynaktan (hardcoded 60 yok)
|
||
grep -rn "danışman sorusu" src/ # 3 sonuç, üçü de credits/paketKredi interpolasyonu
|
||
|
||
# 6) Kapsam dışı dosyalar el değmemiş
|
||
git diff --name-only HEAD~2 # yalnız 3 dosya; credits.ts / liste-uretici.tsx YOK
|
||
|
||
pnpm exec next typegen && pnpm exec tsc --noEmit && pnpm lint
|
||
```
|
||
|
||
**QA'ya devredilen davranış kriterleri (statik grep ile kanıtlanamaz, oturum ister):** paketlide liste ve revizyon bakiyeyi düşürmez · `credit_ledger`'da `delta = 0` satır yazılır · aynı `requestId` ile ikinci üretim `DUPLICATE`/`SURUYOR` döner · üretim hatasında paketliye kredi **eklenmez** · paketsizde davranış bit-bit aynı.
|
||
|
||
### Riskler ve tuzaklar
|
||
|
||
1. **`user.hasPaket` 0/1 olabilir** (drizzle/SQLite boolean); `? :` her iki temsille de doğru çalışır — `=== true` **yazma**.
|
||
2. **Revizyon dalında `maliyet` daima 0** — bu bir hata değil, paket vaadinin ta kendisi (`MAX_REVIZYON = 2` hak sayacı sınırı korur, `:274-280`).
|
||
3. **Delta-0 ledger satırı ve iyzico mutabakatı:** `credit_ledger` bir muhasebe defteri değil, kredi hareket kaydıdır; iyzico tarafı `orders` + `grantCredits(reason: "purchase")` üzerinden yürüyor (`krediKaydiVarMi`, `credits.ts:202-212`). Delta-0 satırının mutabakata etkisi **olmaması gerekir** ama bu benim çıkarımım [Ç] — **`guvenlik-uyum` merge öncesi açıkça cevaplasın** (aşağıda soru metni).
|
||
4. `kredi-hatirlatma.ts:36` paketliyi de tarayabilir (sohbet kredisi 3'ün altına inerse); e-posta metni "listenin tamamını açmak istersen" diyor (`eposta.ts:188`) — paketliye yanlış. **G3'ten önce de var olan bir hata**, kapsam dışı, backlog #B3.
|
||
|
||
### Commit planı
|
||
|
||
1. `fix(kredi): paketliden liste ve revizyon kredisi düşmez` — `rapor-actions.ts`
|
||
2. `fix(listem): fark modalı paketliye kredi bedeli göstermez` — `listem-icerik.tsx`, `tercih-degisti-modali.tsx`
|
||
|
||
`[Bilal]` commit'i **yok** — paket içeriği kararı CEO'da verildi (24-ceo-kapanis §B).
|
||
|
||
### Okunacak Next dokümanı
|
||
|
||
- `node_modules/next/dist/docs/01-app/01-getting-started/07-mutating-data.md` — Server Action sözleşmesi (dönüş tipi, `"use server"`).
|
||
- `node_modules/next/dist/docs/01-app/02-guides/data-security.md` — server/client sınırında veri ve `server-only`.
|
||
|
||
---
|
||
|
||
# G2 + G5 · `odeme/kasa-ve-metin`
|
||
|
||
**Amaç:** Ödeme yüzeyinde iki delik kapanır — hatanın ölçüsü yok (G2) ve satın alma niyetiyle gelen kişiye "sonra al" deniyor (G5).
|
||
|
||
**Dal:** `odeme/kasa-ve-metin` · **Taban:** `9bd448b` · **Öncelik: 3 (vakit yetmezse ilk kesilecek paket budur).** · **Merge öncesi `guvenlik-uyum` denetimi (para yüzeyi).**
|
||
CEO'nun birleştirme gerekçesi: ikisi de aynı yüzeyin küçük düzeltmesi, ayrı dal maliyeti faydasından büyük (24-ceo-kapanis §D-9).
|
||
|
||
### Dokunulacak dosyalar
|
||
|
||
| Dosya | Satır | Ne |
|
||
|---|---|---|
|
||
| `src/lib/analitik.ts` | 36 civarı (`OlayAdi`) | `odeme_hata` adı |
|
||
| `src/features/odeme/odeme-actions.ts` | 16, 35, 45, 48, 87, 91, 102, 108 | Hata dönüşlerine `kod` alanı |
|
||
| `src/features/odeme/components/satin-al-form.tsx` | 48-55 | İki hata dalında `olay("odeme_hata", { kod })` |
|
||
| `src/features/odeme/components/paket-satinal.tsx` | 140-144 | "Paketi sonra alırsın." kalkar |
|
||
| `src/features/kullanici/components/giris-karti.tsx` | 28-31, 52-66 | `/paket` callback'i için üçüncü metin dalı |
|
||
|
||
### Kapsam dışı
|
||
|
||
- **Birincil CTA metni ve hedefi** (`paket-satinal.tsx:131-139`) — 21 Eylül kararı, R4 ile kalıcı kapalı. Buton metnine, rengine, hedefine **dokunulmaz**.
|
||
- Fiyatın girişsiz dala eklenmesi (ürün Ö2a) — R4.
|
||
- `odeme_tamamlandi` sunucu olayı, yeni sayfa görüntüleme enstrümanı, `/odeme` ve `/odeme/sonuc` yüzeyleri, iyzico entegrasyonu, `GirisBaslik`'in typewriter mesajları, paket adı (A2).
|
||
|
||
### Adım adım — G2 (ölçüm)
|
||
|
||
**1) Olay adı** — `analitik.ts` `OlayAdi` birliğine `| "odeme_hata"` (`odeme_baslatildi`'nın hemen altına) + 2 satır yorum: ne zaman atıldığı ve `kod` özelliğinin allowlist'li olduğu.
|
||
|
||
**2) Hata kodu sunucudan gelsin** — `odeme-actions.ts`
|
||
`OdemeBaslatDurum`'un hata dalı kod taşısın:
|
||
```ts
|
||
export type OdemeHataKodu = "URUN" | "ZATEN_PAKETLI" | "TOPUP_PAKETSIZ" | "SUNUCU";
|
||
export type OdemeBaslatDurum = { error: string; kod: OdemeHataKodu } | { yonlendir: string };
|
||
```
|
||
Eşleme: `:35` → `"URUN"` · `:45` → `"ZATEN_PAKETLI"` · `:48` → `"TOPUP_PAKETSIZ"` · `:87`, `:91`(initialize başarısız), `:102`(imza geçersiz) → `"SUNUCU"`. Kullanıcıya giden `error` metinleri ve `console.error` satırları **aynen kalır**; iyzico'nun `errorCode`/`errorMessage` değerleri **Rybbit'e gönderilmez** (yalnız log'da kalır — kardinalite ve sızıntı).
|
||
*Kapsam düzeltmesi:* CEO G2'yi yalnız `satin-al-form.tsx` + `analitik.ts` olarak tanımlamıştı; sunucu bugün yalnız serbest metin `error` döndürüyor (`odeme-actions.ts:16`) [D], dolayısıyla istemci "anahtar eksik" ile "paketin zaten aktif"i ayıramaz — G2'nin tek amacı olan teşhis oluşmaz. 6 satırlık `kod` alanı bunu çözer. **Vakit darsa asgari sürüm:** sunucuya dokunmadan yalnız iki kod (`"BAGLANTI"`, `"SUNUCU"`); kabul kriteri yine sağlanır, teşhis gücü düşer.
|
||
|
||
**3) İstemci olayı** — `satin-al-form.tsx:48-55`
|
||
- `catch` dalı (`:48`): `olay("odeme_hata", { kod: "BAGLANTI" })`, sonra mevcut `toast.error(BAGLANTI_HATASI)`.
|
||
- `"error" in sonuc` dalı (`:52`): `olay("odeme_hata", { kod: sonuc.kod, urun })`, sonra mevcut `toast.error(sonuc.error)`.
|
||
`olay("odeme_baslatildi", { urun })` (`:43`) ve `disabled`/`gidiyor` mantığı **değişmez**. Toast metinleri değişmez. Kullanıcı girdisi/serbest metin olay özelliği olarak **gönderilmez**.
|
||
|
||
### Adım adım — G5 (metin)
|
||
|
||
**4) "Paketi sonra alırsın." kalkar** — `paket-satinal.tsx:140-144`
|
||
Kalan cümle: "Girişte {DENEME_KREDISI} deneme kredisi tanımlanır; liste {RAPOR_KREDI} kredi, ilk {ACIK_SATIR} satır açık." (21 Eyl kararıyla korunan ilk iki cümle). Üç import'un üçü de kullanımda kalır → lint temiz. Birincil butona dokunulmaz.
|
||
|
||
**5) `/giris`'te üçüncü metin dalı** — `giris-karti.tsx:28-31, 52-66`
|
||
```ts
|
||
// Ödeme niyeti: /paket callback'i ile gelen kişiye üçüncü kez ücretsiz
|
||
// deneme anlatılmaz; girişin tek işi ödemeyi sürdürmek.
|
||
const odeme = callbackURL.startsWith("/paket");
|
||
```
|
||
`funnel` ifadesi **değişmez** (`/sonuc` ve `/listem?uret=1` dalları birebir korunur — `/paket` zaten ikisiyle de eşleşmiyor [D]). Paragraf üç dallı olur: `odeme ? (…) : funnel ? (…) : (…)`.
|
||
Önerilen `odeme` metni: **"Girişten sonra ödemeye kaldığın yerden devam edersin — paketin hesabına tanımlanır."** Deneme kredisi vaadi bu dalda **birincil cümle olmaz**; istenirse ikincil küçük satır olarak kalabilir.
|
||
`<GirisBaslik funnel={funnel} />` **değişmez**: `/paket` dalında `funnel === false` olduğu için başlık sade "Giriş yap" olur — typewriter mesajları liste dilinde (`giris-baslik.tsx:6-13`), ödeme niyetine uymaz. [D]
|
||
|
||
### Kabul kriterleri
|
||
|
||
```sh
|
||
grep -n "odeme_hata" src/lib/analitik.ts # 1 (OlayAdi)
|
||
grep -n "odeme_hata" src/features/odeme/components/satin-al-form.tsx # 2
|
||
grep -n "odeme_baslatildi" src/features/odeme/components/satin-al-form.tsx # 1 (davranış korunmuş)
|
||
grep -n "kod:" src/features/odeme/odeme-actions.ts # 6 hata dönüşü
|
||
grep -rn "errorMessage\|errorCode" src/features/odeme/components/ # 0 (iyzico detayı istemcide yok)
|
||
|
||
grep -rc "Paketi sonra alırsın" src/ # 0
|
||
grep -n "Giriş yap — ilk" src/features/odeme/components/paket-satinal.tsx # 1 (CTA metni değişmemiş)
|
||
|
||
grep -n 'startsWith("/paket")' src/features/kullanici/components/giris-karti.tsx # 1
|
||
grep -n 'startsWith("/sonuc")\|startsWith("/listem?uret=1")' src/features/kullanici/components/giris-karti.tsx # değişmemiş
|
||
|
||
pnpm exec next typegen && pnpm exec tsc --noEmit && pnpm lint
|
||
```
|
||
|
||
### Riskler ve tuzaklar
|
||
|
||
1. **`OdemeBaslatDurum` tipi değişince tüm dönüş yolları güncellenmeli** — `tsc` bunu yakalar; `"error" in sonuc` daraltması aynen çalışır.
|
||
2. **`kod` değerleri allowlist'li sabit dizgiler olmalı** — kullanıcı girdisinden türeyen hiçbir şey Rybbit'e gitmez (PROTOKOL 9 + `uretim-basladi-olayi.tsx:18-24`'teki yerleşik kural).
|
||
3. `satin-al-form.tsx` `"use client"`; `olay()` zaten import edili (`:8`), yeni bağımlılık yok.
|
||
4. **Yayın koşulu (CEO):** G2, Bilal'in gerçek test ödemesiyle **aynı yayında** çıkar — tek başına canlıya alınırsa ölçüm boş kalır.
|
||
5. A2 (paket adı) bu dosyaya sonra girecek — paket adına **dokunma** (çakışma kararı #2).
|
||
|
||
### Commit planı
|
||
|
||
1. `feat(olcum): odeme_hata olayı — ödeme hunisine payda` — `analitik.ts`, `odeme-actions.ts`, `satin-al-form.tsx`
|
||
2. `content(paket): "Paketi sonra alırsın." kalkar` — `paket-satinal.tsx`
|
||
3. `content(giris): /paket callback'i ödemeye devam metni alır` — `giris-karti.tsx`
|
||
|
||
### Okunacak Next dokümanı
|
||
|
||
- `node_modules/next/dist/docs/01-app/01-getting-started/07-mutating-data.md` — Server Action dönüş tipleri.
|
||
- `node_modules/next/dist/docs/01-app/02-guides/analytics.md` — istemci olay enstrümanı.
|
||
|
||
---
|
||
|
||
## Merge sırası ve bağımlılıklar
|
||
|
||
Dosya kümeleri ayrık → **teknik bağımlılık yok**, sıra yalnız öncelik. Önerilen: **G1 → G3 → G2+G5 → (A2, en son)**.
|
||
Tam `pnpm build`i **hiçbir dal koşmaz**; entegrasyon build'i Bilal'in sabah komut sırasında (24-ceo-kapanis §C3), push edilecek commit'in kendisi üzerinde APFS klonlu worktree ile alınır.
|
||
|
||
## Uzman yönlendirmesi
|
||
|
||
| Kim | Ne | Ne zaman |
|
||
|---|---|---|
|
||
| **`guvenlik-uyum`** | **G3 merge öncesi zorunlu:** "`credit_ledger`'a `delta = 0` satır yazmak iyzico mutabakatını ya da iade/uyuşmazlık takibini bozar mı? `refund` satırının delta'sı 0 olduğunda `rapor-actions.ts:171-184`'teki 'önceki deneme başarısızdı' çıkarımı hâlâ geçerli mi?" | Bu gece (24-ceo-kapanis §D-11) |
|
||
| **`guvenlik-uyum`** | G2: `kod` allowlist'inin kişisel veri/kart verisi taşımadığı, iyzico hata detayının istemciye inmediği | G2 merge öncesi |
|
||
| **`tasarimci`** | G1 adım 9'un `[Bilal]` cümlesi + `first:mt-0` sonrası ilk ekran hiyerarşisi; G5'in üçüncü `/giris` metni | Dallar yazıldıktan sonra, tek raporda |
|
||
| **`qa-muhendisi`** | G3'ün davranış kriterleri (oturum + `data/app.db` okuması ister); G1'in giriş→üretim zinciri | Dal başına tek rapor satırı; düşen kriterde commit alınmaz |
|
||
| **`analitik`** | `tadimlik_goruntulendi` seri kırılması notu; `odeme_hata` için pano/huni | G1 ve G2 merge sonrası |
|
||
| **`yapay-zeka-muhendisi`** | Gerek yok — prompt, havuz kuralları ve LLM çıktısı üç pakette de değişmiyor (T12 tetiği açılmıyor) | — |
|
||
| **`veri-muhendisi`** | Gerek yok — `yokatlas.db` ve veri hattı dışarıda | — |
|
||
|
||
## İtirazlar
|
||
|
||
1. **G2'nin kapsamı eksikti (düzeltildi).** Sunucu bugün yalnız serbest metin `error` döndürüyor; istemci hatayı sınıflandıramaz, dolayısıyla "kasa neden çalışmıyor" sorusu ölçülemez. `odeme-actions.ts`'e `kod` alanı eklenmeden G2 yalnız "bir hata oldu" sayar. Düzeltilmiş kapsam yukarıda; asgari sürüm de yazıldı.
|
||
2. **G3'ün kapsamı eksikti (düzeltildi).** CEO iki harcama + iki iade dalını saydı; `rapor-actions.ts:243` ve `:363`'teki bakiye dönüşü ile `tercih-degisti-modali.tsx`'in kredi metni dışarıda kalmıştı. Onlar kapatılmazsa paketli kullanıcı "3 kredi düştü" görür, düşmez — G3'ün amacı olan "söz = kod" sağlanmaz. Kapsam 1 dosya + 1 türetilmiş bayrak kadar büyütüldü.
|
||
3. **CEO'nun `giris-karti.tsx` yolu yanlıştı** (`src/features/auth/…` → doğrusu `src/features/kullanici/components/giris-karti.tsx`), `rapor-actions.ts` satır numaraları `84fc88e` referanslıydı ve `9bd448b`'de kaydı. Tüm atıflar bu şartnamede güncellendi.
|
||
4. **G1'de CEO'nun yazmadığı iki zorunlu adım var:** `?kaynak=` allowlist'i (yoksa ölçüm `bilinmiyor`a düşer) ve `sonucHref` import'unun kaldırılması (yoksa lint kırmızı). İkisi de tek satır.
|
||
5. **İtiraz etmediğim yer:** `spendCredits`'in kaldırılmaması kısıtı doğru ve koddan doğrulandı (`uniqueIndex("ledger_reason_ref")`, `schema.ts:133`). Daha "sade" görünen "paketliyse hiç çağırma" yolu idempotency çapasını **ve** başarısız-deneme işaretini birlikte kaybettirirdi.
|
||
|
||
## Backlog önerileri (BACKLOG.md'ye dokunulmadı)
|
||
|
||
- **B1** — `tadimlik_goruntulendi` seri kırılması notu `analitik.ts`'e taşınsın (G1 ile G2 aynı dosyada çakışmasın diye bu gece `tadimlik-satiri.tsx`'te kalıyor). XS.
|
||
- **B2** — `liste-uretici.tsx:263-285`'teki `hasPaket` "kredi yetersiz" dalı G3 sonrası liste üretimi için ölü kod; Bilal'in dosyası olduğu için bu gece dokunulmadı. XS.
|
||
- **B3** — Kredi-bitti hatırlatma e-postası paketliyi de tarayabiliyor (`kredi-hatirlatma.ts:29-38`) ve metni "listenin tamamını açmak istersen" diyor (`eposta.ts:188`) — paketliye yanlış. Sorgu `hasPaket = false` koşulu ya da metin dalı istiyor. S.
|
||
- **B4** — `ACIK_SATIR` `rapor-maske.ts`'te `server-only` modülde yaşıyor; istemci metinleri bu sayıyı tek kaynaktan okuyamıyor (bugün `liste-uretici.tsx:274` "3 kredi"yi elle yazıyor). Sabitlerin client-safe bir modüle ayrılması. S.
|
||
- **B5** — `/sonuc` tadımlığının `useGorunumOlayi` eşiği ilk ekrana taşındıktan sonra gözden geçirilsin; "görüntülendi" artık neredeyse her ziyaretle eşit olacağı için huni değeri düşecek — anlamlı ölçüt "tadımlık CTA tıklaması / tadımlık görüntülenmesi" oranıdır. XS.
|
||
|
||
## Bilal'den istenen (2 madde)
|
||
|
||
1. **G1'in son commit'i (`[Bilal] content(tadimlik): CTA'nın yeni vaadi`) onayı** — tadımlık butonunun yeni cümlesi senin diline mi uysun, yoksa kendi cümleni mi yazacaksın? Commit tek başına düşürülebilir hazırlanıyor. ~2 dk.
|
||
2. **Üç dalın tek build'de doğrulanması** — sabahki C3 komut bloğunu çalıştırırken `funnel/sonuc-ilk-ekran`, `odeme/paket-vaadi`, `odeme/kasa-ve-metin` dallarını entegrasyon worktree'sinde birleştirip `pnpm build`i o commit üzerinde al; ajanlar disk yüzünden build koşmadı. ~10 dk.
|