# Review — Ofis T4 Planı v2.2 — Re-review 4 — 2026-07-28

> **Review type:** plan-review (re-review)
> **Previous review:** `docs/reviews/review-ofis-t4-plan-2026-07-28-r3.md` (REJECTED, 5 bulgu)
> **Upstream document(s) read:** AD-23 (28.07 güncel — "etkin kapsam dar olandır; `all` ağaçtan bağımsız" hükmü), AD-08/09/10/11/15/24/27 · `egitmen-spec` §1–§4 (kilitli) · çatı §174/§178/§220
> **Other cross-referenced code:** `SessionScopeResolver.php:70-86` (iki kademeli davranışın korunduğu iddiası) · `config/authorization.php` (R3-3'ün "bildirim izni yok" tespiti) · `ChangeOfficeAccountStatus` + `routes/office.php:201` (R3-4 tetikleyicisi)
> **Stage locks in effect:** `egitmen-spec` kilitli (heyet 158).

---

## Önceki bulguların kapanışı (R3: 5/5)

| # | Durum | Kanıt |
|---|---|---|
| R3-1 | ✓ Kapandı | Adım 3b yeniden yazıldı: seviye tavanı **yalnız `.group`** ekini daraltır; `.all`/`.own` seviyeden ve üyelikten bağımsız. Beş satırlık tablo artık ⚠ paragrafıyla ve AD-23'le tutarlı; iki gerekçe (ölü kapsam + A-12 çöküşü) metinde. A-11a doğru ölçüyor |
| R3-2 | ✓ Kapandı | Adım 4: değişiklik minimuma indirildi — iki kademeli davranış (izinli → tümü, izinsiz → atamalar) aynen korunuyor, yalnız ad güncelleniyor; `customer.view.group`/`.own` **üretilmiyor**, iki gerekçe yazılı; A-11b/A-11c. Kalıntı: Adım 1 tablosu → R4-1 |
| R3-3 | ✓ Kapandı | Assignee izni `user.update` (boş küme → `office_user.update`, K-E) + gerekçe ("bakanlık iznine sahip ad sözlükte yok, uydurulmaz") + kapanış adresi (bakanlık bildirimi turu kendi iznini tanımlayınca kural taşınır) |
| R3-4 | ✓ Kapandı | İki tetikleyici tek görev türü (`context.change: hired | left`); ayrılış `ChangeOfficeAccountStatus` üzerinden bu turda bağlanıyor; eğitmen kaydı olmayan pasifleşme görev açmıyor; A-15b. Dosya listesi eksiği → R4-3 |
| R3-5 | ✓ Kapandı | Adım 6: "kapsamsız isimde **istisna** (`null` dönmez)" + bileşim tablosunun beş satırı test kapsamında |

---

## Upstream Coverage Matrix (v2.2 farkları; kalan ✓ satırlar r2/r3 matrisleriyle aynı)

| Upstream § / madde | Durum | Kanıt |
|---|---|---|
| AD-23 — "etkin kapsam dar olandır; `all` ağaçtan bağımsız" | ✓ | Adım 3b tablosu artık birebir uyumlu; A-11a/A-13 doğru bileşimlerle |
| A-12 güvencesi (aynı küme) | ✓ | `.all` üyeliksiz de `all`; izinsiz-atanmış müşteri kapsamı korunuyor (A-11b) |
| Y-2016 md.13/j — "her türlü değişiklik" | ✓ | İşe alım + ayrılış, iki tetikleyici bu turda (A-15a/A-15b) |
| egitmen-spec §2 — "eğitici belgesi bitiş tarihi takip edilir, **süresi dolmadan uyarı**" (kilitli) | ⚠ | `certificate_valid_until` bu turda doğuyor; süre-dolumu uyarısı (kademeli bildirim — AD-10, çatı §220/14) ne bu turda ne kapanış tablosunda → R4-2 |
| Kapsam sözdizimi tutarlılığı (T-1) | ✓ | İzin başına üretilen sürüm kümesi zaten değişkendi (`user.create` `.own` üretmiyor); `customer.view`'ın yalnız `.all`'u belgelenmiş ve A-11c ile sabit |

---

## ✅ What works

- **R3-1'in kapanışı tam:** kural tek cümleye inmiş ("seviye tavanı yalnız `.group` ekini daraltır"), tablo-paragraf-AD üçlüsü aynı şeyi söylüyor ve iki gerekçe (ölü kapsam, A-12 çöküşü) davranışın **neden** böyle olduğunu geleceğe taşıyor.
- **R3-2'nin "minimum değişiklik" kararı doğru sınıf:** izinsiz-atanmış kullanıcıların default davranışını izne çevirmemek, sessiz kapsam sıfırlanmasını kökten kapatıyor; `.group`/`.own`'u üretmemek de yarım-semantikli izni ekrandan uzak tutuyor.
- **R3-3'ün gerekçe + kapanış adresi çifti** tam istenen desen: bugünkü sözlükten seçim, seçimin kaydı, taşınacağı yerin adı.
- **R3-4 simetrik ve doğru sınırlı:** tek görev türü, `context.change` ayrımı, eğitmen-olmayan pasifleşmenin görev açmaması.

## ⚠️ Findings & Risks (in-scope)

**R4-1 — Adım 1 tablosunda R3-2 öncesinden kalma satır: `customer.view_all` için "`.group` ve `.own` eklenir".** Görev 2 Adım 1'in tablosu (satır 214) hâlâ *"Ad zaten kapsam söylüyordu; `.group` ve `.own` eklenir"* diyor; Adım 4 ⛔ ve A-11c ise bu iki sürümün **üretilmediğini** söylüyor. R3-5 ile aynı sınıf bir kalıntı: migration'ı Adım 1 tablosundan yazan geliştirici, A-11c'nin yasakladığı izinleri üretir. Satır *"yalnız `customer.view.all` (yeniden adlandırma); `.group`/`.own` üretilmez → Adım 4"* olarak düzeltilmeli.

**R4-2 — Kilitli spec'in "süresi dolmadan uyarı" davranışı ne yapılıyor ne erteleniyor.** `egitmen-spec` §2: eğitici belgesi *"bitiş tarihi takip edilir, süresi dolmadan uyarı"* (Y-2016 md.7/3); çatı §220/14 bunu kademeli bildirim kapsamına koyar (AD-10: 90/60/45/30/15/7 gün taramaları). Plan `certificate_valid_until` alanını bu turda doğuruyor ama uyarı taramasını ne kuruyor ne kapanış tablosuna yazıyor. Bu R3-4 sınıfı bir "canlı tetikleyici" **değildir** — tetikleyici insan eylemi değil zamanın geçmesi ve tarama altyapısı (AD-10) henüz hiçbir turda kurulmadı; erteleme meşru. Eksik olan yalnız **adres satırıdır**: kapanış tablosuna "belge süre-dolumu uyarısı → kademeli bildirim/süre takibi turu" kalemi eklenmeli.

**R4-3 — Ayrılış tetikleyicisinin dokunduğu dosya Görev 7'nin listesinde yok.** Adım 2b ayrılışı `ChangeOfficeAccountStatus`'a bağlıyor ("pasifleşen kullanıcının `instructor` kaydı varsa aynı görev açılır") ama Görev 7'nin **Dosyalar** listesi yalnız yeni instructor dosyalarını sayıyor — `app/Actions/Office/ChangeOfficeAccountStatus.php` (Değiştir) yok. Dosya haritası bu planda kontrat işlevi görüyor (disjoint-file partition, subagent politikası); değişecek mevcut dosyanın listede olmaması o kontratı deler. Listeye eklenmeli.

*Not (bulgu değil):* Adım 4'teki karşılaştırma tablosunun başlığı "v2.1'den sonra" diyor — sürüm artık 2.2; kozmetik.

## ❓ Open Questions

Yok — kalan üç bulgu da karar değil düzeltme istiyor.

## Sorulara cevaplar (talep edilen dört nokta)

1. **`.all`'ın üyelikten bağımsızlığı `staff`'ı zayıflatıyor mu?** Hayır. `staff` seviyesinin işi `.group` ekinin **ne demek olduğunu** tanımlamaktır (grubu yönetmeyen kişi için grup = kendisi); `.all` ise ağaca hiç referans vermeyen, devir kurallarının (A-9: veren `all` taşımalı + hedef kapsamda olmalı) koruması altında **bilinçli** verilen bir yetkidir. `staff`'a `.all` verilmişse bu verenin kararıdır ve kayıtlıdır. Aksi model `.all`'u tümüyle öldürüyordu — plan doğru tarafı seçti.
2. **Yalnız `.all` üretmek sözdizimi tutarsızlığı mı?** Hayır. Sözdizimi tektir (`resource.action.scope`); izin başına üretilen sürüm kümesi zaten değişkendi (`user.create` `.own` üretmiyor, gerekçesiyle). `customer.view`'ın asimetrisi de aynı desenle belgelenmiş ve A-11c ile sabitlenmiş. Tek koşul, Adım 1 tablosunun bununla çelişmemesi (R4-1).
3. **`user.update` seçimi doğru mu?** Evet, bugünkü sözlükteki en yakın ad bu — kaydı yönetebilen, kaydın doğurduğu yükümlülüğü üstlenendir; `user.view` pasif-genel, diğerleri alakasız. Görevi sahipsiz bırakmak iki şeyi bozardı: K-E'nin "görev her zaman birine düşer" ilkesini ve hatırlatmanın varlık sebebini (kimsenin görmediği hatırlatma yoktur). Kapanış adresi de yazıldığı için seçim geçici olduğunu kendisi söylüyor — doğru kurgu.
4. **Başka bağlanmamış tetikleyici var mı?** R3-4 sınıfında (insan eylemli, bu turda canlı) **yok** — iki kuruluş sınırı kayıtta kontrol ediliyor (A-15), belge zorunlulukları `document_types` verisinden, dört göz bu turda onay akışı olmadığından konu dışı. Zaman-tabanlı bir kalem açık kaldı: belge süre-dolumu uyarısı — canlı bir eylem tetikleyicisi değil ama kilitli spec davranışı ve adressiz (R4-2).

## ⚠️ Upstream Findings

Yok.

## Verdict: ❌ REJECTED

5/5 bulgu gerçek işle kapandı; R3-1 ve R3-2'nin kapanışları davranışı doğru yere oturttu. Kalan üç bulgu dar ve mekanik: bir kalıntı tablo satırı (R4-1), bir eksik kapanış adresi (R4-2), bir eksik dosya listesi girdisi (R4-3). Üçü de karar gerektirmiyor; bir sonraki sürüm dakikalık bir düzeltme olmalı ve bu haliyle APPROVED'a çok yakın.
