# Review — Potansiyel müşteri — implementasyon planı (v1.2) — 2026-10-19 (re-review 2)

> **Review type:** plan-re-review
> **Previous review:** `docs/reviews/review-potansiyel-musteri-plan-re-review-2026-10-19.md` (heyet 810, REJECTED, F-7); öncesinde `docs/reviews/review-potansiyel-musteri-plan-2026-10-19.md` (heyet 809, REJECTED, F-1…F-6)
> **Upstream document(s) read:** `proje-haritasi.md` §4.4 (dokuz madde + iki yeni Sets kararı: vergi no uyarıdır/engel değildir — Vitsan gerekçesi; temas telefonu açık + erişim logu + müşteri kartına aynı kural), `docs/arch/mimari-kararlar.md` (AD-04, AD-05, AD-06, AD-08, AD-11, AD-16, AD-21, AD-23, AD-25, AD-26), `CLAUDE.md`. Spec turu yoktur (Sets kararı, 19.10.2026).
> **Other cross-referenced documents:** v1.2'nin tek yeni kararı (K-25) ve ona bağlı dosya/satır iddiaları koddan açıldı: `app/Support/Audit/AccessLogger.php` (tam dosya — `record`, `tenantOf`, `persist` çağrısı), `app/Support/Audit/Concerns/PersistsAuditRows.php` (`persist`, `refuseCustomerRowWithoutTenant` — `tenantId === null` + ofis aktörü için reddetmediği doğrulandı), `app/Support/Audit/CurrentActor.php:70-86` (NULL'un "ofis olayı" anlamı, `ambientScope()` davranışı), mevcut dört `AccessLogger::record` çağrısı (`InstitutionDocumentController.php:87`, `InstructorController.php:466`, `RevealInstructorIdentifier.php:63`, `ReadTrainingRegister.php:54` — v1.2'nin "dört mevcut ofis okuması" iddiasıyla birebir eşleşti) ve bunların subject modellerinin (`Instructor`, `InstitutionDocument`, `TrainingRegister`) tenant'sız olduğu doğrulandı, `app/Queries/Customer/MyQuotes.php:134-137` (K-25'in "genel kural değişmez" iddiasının kanıtı — `TenantContext::forWrite` ile sarmalanmış, `tenantOf` için doğru kiracıyı zaten doğru yoldan alıyor). Önceki iki turun kendi kod kanıtları (`TenantContext.php`, `SessionScopeResolver.php`, `CreateCustomerPerson.php`, `Masker.php`, `config/tenancy.php`, `CloseMeeting.php`, `CustomerPeople.php`, `AddCustomerNote.php`/`RecordNotePolicy.php`, `design/32`) bu turda tekrar açılmadı — doğrulanmış ve v1.2'de değişmemiş.
> **Stage locks in effect:** Sets'in dokuz önceki kararı + bir önceki turun iki yeni kararı (vergi no uyarı, temas telefonu açık+loglu) kilitli. Bu turda yalnız K-25'in F-7'yi çözüp çözmediği ve çözümün yeni bir problem yaratıp yaratmadığı değerlendirildi.

---

## Upstream Coverage Matrix

(Sıfırdan üretildi; önceki iki turun matrisleri kopyalanmadı.)

| Upstream § / madde | Reviewed doc'ta durumu | Kanıt |
|---|---|---|
| F-7 (heyet 810): `AccessLogger`'ın tenant çözümlemesi tenant'sız subject'te yanlış müşteriye yazabiliyordu | ✓ | K-25: `AccessLogger::recordOfficeRead(Model $subject, array\|string $fields, array $context = []): AuditAccess` → `persist(…, tenantId: null, …)` — `tenantOf()` hiç çağrılmaz, `CurrentActor::tenantId()`'nin ambient-scope fallback'ına hiç düşülmez. K-22 bu yolu kullanıyor (dosya haritası: `AccessLogger.php` değişikliği `recordOfficeRead` olarak sınırlı, "`record` ve `tenantOf` değişmez" açıkça yazılı) |
| F-7'nin çözümünün genel `tenantOf` sözleşmesini bozmaması | ✓ | `persist()` (`PersistsAuditRows.php:38-58`) `tenantId === null` → doğrudan yazar, `refuseCustomerRowWithoutTenant` yalnız `ActorType::CustomerUser` + null'da patlar (office aktörü için sorun yok); `MyQuotes.php:134-137` kendi `TenantContext::forWrite` sarmalamasıyla hâlâ doğru kiracıyı yazıyor — K-25 bu yolu hiç değiştirmiyor |
| K-23 (`CustomerPeople`) F-7'den etkilenmiyor mu | ✓ | K-23/Görev 5b hâlâ `TenantContext::run([müşteri])` içinde genel `AccessLogger::record` kullanıyor (v1.1'den değişmedi) — `tenantOf()` `TenantContext::current()`'ı bulur, ambient fallback'a hiç düşmez; K-25 bu çağrıyı değiştirmiyor |
| K-25'in "dört mevcut ofis okuması da aynı kusuru taşıyor, kapsam dışı" iddiası | ✓ | Bağımsız grep dört çağrıyı da buldu (`InstitutionDocumentController.php:87`, `InstructorController.php:466`, `RevealInstructorIdentifier.php:63`, `ReadTrainingRegister.php:54`); üç subject modeli (`Instructor`, `InstitutionDocument`, `TrainingRegister`) tenant kolonu taşımıyor — iddia doğru ve dürüst; plan bu dört okumayı sessizce "düzeltmiyor", kapsam kararını Sets'e sorduğunu revizyon geçmişinde yazıyor (ticket kapsamı disiplinine uygun — CLAUDE.md "ticket'ın kapsamı ticket kadardır") |
| Görev 5b testi: tenant_id NULL'ın doğrulanması | ✓ | `PotentialCustomerTest`'te uçtan uca senaryo (tam bir müşteriye atanmış satışçı → NULL, atanmış müşterinin id'si değil) + ayrı `AccessLoggerTest`'te mekanizma seviyesinde (`recordOfficeRead` istek kapsamından bağımsız, uygulama rolüyle INSERT politikasının kabul ettiği) — iki katmanlı, doğru ayrışmış |
| F-1…F-6 (heyet 809) | ✓ (değişmedi) | v1.2 bu kararlara dokunmamış; önceki re-review'da tek tek doğrulanmıştı |
| AD-06/AD-16/kırmızı çizgi 13 (audit transaction + maskeleme) | ✓ | K-24 değişmedi, hâlâ doğru |
| AD-21 (erişim logu bütünlüğü — "kim neye baktı" doğru cevaplanır) | ✓ | K-25 ile artık hem potansiyel tarafı hem mevcut `MyQuotes` yolu doğru kiracı/NULL ayrımını koruyor |
| AD-25 (kod yerleşimi) | ✓ | `recordOfficeRead` aynı sınıfa (`app/Support/Audit/`) ekleniyor, yeni bir katman/sorumluluk karışıklığı yok |
| AD-26 (test grubu disiplini) | ✓ | `CustomersWithTaxNumberTest` emsaliyle tutarlı; `AccessLoggerTest`'in grubu dosya haritasında adı geçmeden bırakılmış ama arch testi (grupsuz test reddi) bunu zaten mekanik olarak zorunlu kılıyor — bkz. "What works" |

---

## ✅ What works

- **F-7 gerçek bir mimari düzeltmeyle kapatılmış, yama değil.** `recordOfficeRead` ayrı, dar bir metot: genel `record()`/`tenantOf()` sözleşmesine hiç dokunmadan (dosya haritası bunu açıkça söylüyor), yalnız gerçekten tenant'sız olan subject'ler için `tenantId: null`'ı doğrudan `persist()`'e veriyor. Bu, önceki turun F-1'inde eleştirilen "altyapı sınıfının varsayımlarının sınanmadan miras alınması" hatasının tam tersi bir disiplinle yazılmış: yeni bir çağrı biçimi, eski çağrı biçimini sabit bırakarak.
- **Regresyon taraması bağımsız olarak doğrulandı:** `MyQuotes`'ın mevcut `TenantContext::forWrite` sarmalaması ve K-23'ün `TenantContext::run` sarmalaması ikisi de `recordOfficeRead`'den etkilenmiyor; her ikisi de zaten doğru kiracıyı `tenantOf()` üzerinden alıyordu ve bu yol değişmedi.
- **Plan, kendi bulduğu yan etkiyi (dört mevcut okumanın aynı kusuru taşıması) örtmek yerine açıkça yazmış ve kapsam dışı bırakmış** — ticket disiplinine (CLAUDE.md "ticket'ın kapsamı ticket kadardır") tam uygun bir davranış; sessizce "madem buradayım düzelteyim" demek yerine Sets'e sorulmuş.
- **Test katmanlaması isabetli:** uçtan uca regresyon senaryosu (`PotentialCustomerTest`, gerçek bir dar-kapsamlı kullanıcı fixture'ıyla) ile mekanizma-seviyesi doğrulama (`AccessLoggerTest`, uygulama rolüyle INSERT politikası) ayrı tutulmuş — biri davranışı, biri alt yapıyı kanıtlıyor.
- Önceki tüm bulgular (809'un altısı + 810'un biri) gerçek kod kanıtlarıyla yeniden doğrulandı ve hiçbiri rejenere olmamış.

## ⚠️ Findings & Risks (in-scope for this review type)

Yok. Matrix'te ❌/⚠ satır yok.

(Küçük bir not, bulgu değil: Görev 5b'nin yeni `AccessLoggerTest`'i "Yeni" dosya haritası tablosuna eklenmemiş — yalnız Görev 5b'nin düz metninde anılıyor. Bu, AD-26'nın "grupsuz test arch testiyle reddedilir" kuralı implementasyon sırasında zaten mekanik olarak zorlayacağı için bir belirsizlik/risk doğurmuyor — dosya adı ve grup, kardeş test `CustomersWithTaxNumberTest`'in deseninden açıkça çıkarılabilir. Blocker değil.)

## ❓ Open Questions (to be answered before next stage)

Yok — önceki turdaki iki açık soru (savepoint sonrası kalıntı kapsamın test görünürlüğü; Görev 5b'nin ticket kapsamına dahil edilme gerekçesinin plan metninde de bir cümleyle yer alması) blocker değildi ve bu turda yeniden gündeme getirilmedi; isteniyorsa implementasyon sırasında ayrıca sorulabilir.

## Previous Findings Status (re-review only)

| Bulgu | Durum |
|---|---|
| F-1…F-6 (heyet 809) | ✅ Resolved (önceki turda doğrulandı, bu turda değişmediği teyit edildi) |
| F-7 (heyet 810) | ✅ Resolved |

Düzeltme yeni bir problem yaratmadı; planın ana hedefinden sapma yok.

## Verdict: ✅ APPROVED

Üç turun yedi bulgusu da gerçek, doğrulanabilir kod kanıtıyla kapatıldı; son düzeltme (K-25) önceki turun kendi ölçütüyle (bir altyapı sınıfının varsayımlarının sınanması) titizce yazılmış ve regresyon taraması temiz çıktı. Upstream Coverage Matrix'te açık satır yok. Plan implementasyona hazırdır.

```
docs/reviews/review-potansiyel-musteri-plan-re-review-2-2026-10-19.md
```
