# Review — Ofis Ön Yüzü ve Kimlik Yüzeyi Spec v1.2 — 2026-07-28 (r2)

> **Review type:** spec-review (re-review)
> **Previous review:** `docs/reviews/review-ofis-onyuz-spec-2026-07-28.md` (REJECTED, F-1…F-10 + 3 açık soru)
> **Upstream document(s) read:** `docs/specs/omurga-spec.md` (§3.0.2, §5.1–5.5, §14) · `docs/plans/omurga-plan.md` (chunk5 §5.8, chunk6 §6.5.1, kriter sicili) · `design/HANDOFF.md` · `docs/arch/kod-yerlesimi.md` (§3, §4) · `docs/arch/mimari-kararlar.md` (AD-25 ve çevresi) · `CLAUDE.md`
> **Other cross-referenced:** `docs/issues.md` (passkey kayıtları, "tören testle kanıtlanmaz") · `current_todo.md` · kod doğrulamaları: `config/security.php`, `database/migrations/2026_07_27_000100_create_identity_domains.php` (users.status :107 civarı — doğrulandı), `database/migrations/2026_07_27_000200_create_customer_identity.php` (`national_id` :158 — doğrulandı), `app/Models/User.php` (`HasAccountStatus`), `app/Support/Authorization/PermissionFamilies.php`
> **Stage locks:** omurga spec + plan APPROVED; §7'deki revizyon/netleştirme talepleri açıkça listeli, kilit ihlali yok.

---

## Önceki bulguların kapanış doğrulaması

| Bulgu | Durum | Kanıt |
|---|---|---|
| **F-1** — AD-25 revizyon tablosunda yok | **Kapandı (kısmen çürütme kabul edildi)** | Değerlendirme aşağıda ayrı bölümde. §7'de AD-25 netleştirme satırı (:303) + kod-yerlesimi §4 gerçek revizyon satırı (:302); karar 8'e ⚠ bloğu eklendi (spec :98-100) |
| **F-2** — §5.5 ve §14 kriter 25 dokunulmuyor | **Kapandı** | §7 tablosunda dört satır: omurga-spec §5.3 ikinci madde (:297), §5.5 (:298), §14 kriter 25 (:299), plan kriter sicili 25 + chunk6 7c ofis bacağı (:300, "plan aşamasında yapılır" kaydıyla — doğru sınır) |
| **F-3** — ofis magic link'te kapatılamaz teyit adımı tanımsız | **Kapandı** | Yeni §5.4: teyidin yerini ikinci faktör alır; kanıt zinciri doğru — `config/security.php:49` tek seçenek, `users`'ta TCKN yok (migration doğrulandı: `national_id` yalnız `create_customer_identity.php:158`), müşteri/katılımcıda `national_id_last_four` aynen kalıyor; §5.3'e ofis niteleyicisi §7'de revizyon olarak listeli (:297) |
| **F-4** — ikinci faktörsüz kullanıcı magic link'le girerse | **Kapandı** | §5.4 adım 3 (ara ekran, kurulum sonrası akış devam) + kriter 10; backoffice'te çalışan desen (`docs/issues.md` — şifreyle giren passkey'li kullanıcının 2FA kurulumuna düşmesi canlı doğrulanmıştı). Karar 6 ile çatışma açıkça çözülmüş: yol bazlı fark, kaynağı §5.3 (spec :252) — tutarlı |
| **F-5** — "detay" aksiyonunun yüzeyi tanımsız | **Kapandı** | T2 "Kullanıcı detayı" satırı (:276): sade hesap detayı + kişinin denetim izi; kokpit kartları adresli erteleme (satış/mali spec'leri, §2 ile tutarlı) |
| **F-6** — "yetki bekliyor" uyarısı adressiz | **Kapandı — ama koşul metni yeni bulgu doğurdu (R2-1)** | T2 satırı (:277) + kriter 13. Şema itirazı doğru: `users.status` zaten var ve AccountStatus'tür (doğrulandı); §3.0.2'nin iki-statü ayrımı ofiste tek değere yozlaşır (ofiste katılımcı hesabı açılmaz), P-1'in gürültü riski ofiste doğmaz — "yeni kolon gerekmez" savı geçerli. **Ancak** koşuldaki *"etkin"* kelimesi hatalı — bkz. R2-1 |
| **F-7** — dondur/kapat gerekçesi | **Kapandı** | §8.4 (gerekçe zorunlu modal, gerekçe audit satırında, kapatmada şifre onayı) + kriter 12; HANDOFF kural 10 ve `04` destructive modal deseniyle uyumlu |
| **F-8** — kriter 4'ün ölçümü iddiayı kanıtlamıyor | **Kısmen kapandı → R2-2** | Ölçüm gerçekten iyileşti (metin düğümü taraması diakritik sorununu kökten çözer) ve gerekçe kriterin içine yazıldı. Ama iddia–ölçüm boşluğu başka bir kanalda sürüyor — bkz. R2-2 |
| **F-9** — kriter 10'un kanıtı proje kaydıyla çelişiyor | **Kapandı** | Kriter ikiye bölündü: 11 yapısal yarıyı test eder (ayrı tablo/model/RP id, çapraz sorgu boş), tören yarısı gerçek cihaz doğrulaması + rapor kaydı; `docs/issues.md` atfı doğru (kayıt orada, :204) |
| **F-10** — dört-yöntem kararı karar 7'ye atfedilmiş | **Kapandı** | Karar 11 adlandırıldı (:120-126), karar 7 ile karışma uyarısı yazıldı; §7'nin iki satırı (:301, :305) ve §8.3 ilk satırı (:334) karar 11'e taşındı; §3 girişine "numaralar kimliktir, sıra değildir" notu eklendi |
| **Açık soru 1** — müşteri portalı adresi | **Kapandı** | §2 (:35): `EGT-24` (Spec 4) + `EGT-38`; ortak tasarım sistemi notu da eklendi |
| **Açık soru 2** — kriter 7-8 kanıtı | **Kapandı** | Karar 10 (:118): Playwright T1'de zorunlu, dar kapsam (responsive + erişilebilirlik ölçümü, iş mantığı taşınmaz); kriter 7 ve 8 mekanizma kazandı |
| **Açık soru 3** — plan tarafının adresi | **Kapandı** | §7 plan satırı (:300), F-2 ile birlikte |

**Sonuç: 13 kalemin 12'si kapandı; F-8'in kapanışı kısmî (R2-2), F-6'nın kapanışı yeni bir kusur taşıyor (R2-1).**

---

## F-1 çürütmesinin değerlendirmesi

**Kabul — ayrım doğru kurulmuş.** Üç gerekçeyle:

1. **Belge sahibinin kastı AD içeriği için belirleyicidir** ve "her iki taraf = ofis + müşteri" okuması AD-25'in kendi metniyle çelişmez — cümle gerçekten belirsizdir. Yanlış okumanın kaynağı da doğru teşhis edilmiş: cümle, Filament'i tartışan paragrafın sonunda duruyor ve paragraf bağlamı "iki taraf"ı Vue/Filament diye kurduruyor.
2. **Netleştirme/revizyon ayrımı kanıtla hizalı:** `kod-yerlesimi.md` §4 Filament'i **adıyla** sayıyor (*"hem Vue hem Filament tarafına beslenir — iki ayrı palet oluşmaz"*, :73) — orada politika gerçekten değişiyor ve spec bunu **gerçek revizyon** olarak işaretliyor. AD-25'te ise yalnız ifade netleşiyor. Kayıt açısından ikisi de §7'de listeli; onay kuralı 6'nın istediği ("hiçbiri örtük bırakılmaz") sağlanıyor — etiketin adı artefakt izini değiştirmiyor.
3. **Yeni ifade başka bir yeri kırmıyor:** HANDOFF'un token kuralı tasarım tarafındadır ve etkilenmez; arch testlerinde token beslemesine dair kural yok; karar 5'in derleme girişleri bağımsız. Tek not: kod-yerlesimi §4, AD-25'in **uygulama dokümanı** olduğu için "iki okuyucu yanlış okudu" ifadesi eksik sayım — o dokümanın yazımı da aynı okumayı kodlamıştı (üçüncü iz). Bulgu değil; revizyon zaten o dokümanı düzeltiyor.

**Sınır durumu (açık not, bulgu değil):** yeni ifade bir **sayımdır** — "ofis ve müşteri yüzeyleri". Landing (EGT-40) ne ofis ne müşteri kimlik yüzeyidir; o tur geldiğinde ya sayıma eklenir ya landing'in aynı token kaynağından beslendiği kendi spec'inde yazılır. Bugün kıran bir şey yok.

---

## Upstream Coverage Matrix (v1.2'de değişen/yeni içerik + taşınan kilit satırlar)

| Upstream § / madde | Durum | Kanıt |
|---|---|---|
| omurga-spec §5.3 — her magic link oturumunda kapatılamaz teyit | ✓ | §5.4: ofiste teyidin yerini ikinci faktör alır; niteleyici §7:297'de açık revizyon; müşteri/katılımcı aynen (§5.4 son ⚠) |
| omurga-spec §5.3 — panel yetkisini açmaz → ofis daraltması | ✓ | Karar 7 + §7:296; §5.5 (:298) ve §14 kriter 25 (:299) artık kapsam içinde — F-2'nin istediği tam buydu |
| omurga-spec §5.2 v1.15 — "e-posta girişi (ya da magic link) + ikinci faktör" oturum modeli | ✓ | §5.4 akışı bu modelin ofis panel erişimine uygulanması; adım 3'ün "kurulum ekranına düşme" deseni §5.2'nin şifre-yolundaki deseniyle aynı |
| omurga-spec §5.2 — karar 6 (yetki bazlı) ile §5.4 (magic link yolunda zorunlu) çelişkisi | ✓ | Açıkça uzlaştırılmış (:252): yol bazlı fark, kaynağı §5.3'ün kapatılamaz adımı — gerekçe tutarlı |
| omurga-spec §3.0.2 P-1/P-2 — "yetki bekleyen kullanıcınız var", statü bazlı, gürültüsüz | ⚠ | T2 :277 + kriter 13 yüzeyi ve adresi kuruyor; "yeni kolon gerekmez" savı doğrulandı (`users.status` mevcut, ofiste katılımcı hesabı yok → P-1 gürültü riski doğmaz). **Ama koşul "hiç etkin yetki yok" — upstream P-2 "yetkileri henüz tanımlanmadıysa" der; fark MFA-kilitli izinlerde davranış değiştirir → R2-1** |
| omurga-spec §3.0.2 P-3 — kritik bilgiler açılışta | ✓ | §5.4'ün "ofis kimliğinden TCKN toplamıyoruz" tespiti mevcut onaylı şemayla tutarlı (zorunlu alan seti alana göredir; ofis seti bugün TCKN içermiyor) |
| omurga-spec §5.4 A-1 / §8.1 | ✓ | Değişmedi (v1.1'de ✓) |
| HANDOFF bağlayıcı kural 10 — dondur/kısıtla gerekçeli | ✓ | §8.4 + kriter 12; kapatmada şifre onayı §5.2 v1.16'nın modal kuralıyla uyumlu |
| HANDOFF/63 — kullanıcı detayı (kokpit + kişinin logları) | ✓ | T2 detay satırı: denetim izi dahil, kokpit adresli erteleme |
| HANDOFF — erişilebilirlik/responsive kanıtı | ✓ | Kriter 7, 8 artık Playwright'a bağlı; karar 10'un dar kapsam sınırı AD-26 disipliniyle uyumlu |
| AD-25 (:373) — token kaynağı | ✓ | Netleştirme (yukarıdaki değerlendirme); kod-yerlesimi §4 gerçek revizyon olarak ayrışmış |
| AD-26 — grup sözlüğü değişmez | ✓ | Karar 10; Playwright eklenmesi grup sözlüğüne dokunmuyor |
| CLAUDE.md dil kuralı — gömülü kullanıcı metni yasak | ⚠ | Kriter 4'ün yeni ölçümü metin düğümlerini kapatıyor; attribute/prop ve script dizgeleri açık — R2-2 |
| docs/issues.md — passkey kayıtları, "tören testle kanıtlanmaz" | ✓ | Kriter 11'in bölünmesi ve atfı kayıtla birebir |
| Karar 9 — sapmalar gerekçeli + onaylı | ✓ | §8.3 üç satır, üçü de onaylı; üçüncüsü (ara ekran) mevcut desenden türetilmiş, yeni bileşen değil |
| Onay kuralı 6 — örtük revizyon yok | ✓ | §7 tablosu 11 satır; bu turda eklenen her değişiklik (AD-25, §5.5, §14-25, plan adresi, §5.3 ikinci madde) listeli |

---

## ✅ What works (bu turda eklenenler)

- **§5.4 doğru kurulmuş bir uzlaştırma.** Teyit adımının ofiste ikinci faktörle ikamesi, hem §5.3'ün "varlığı seçilemez" kuralını korur (adım atlanmıyor, daha güçlüsüyle değiştiriliyor) hem karar 7'nin oturum modeline oturur; karar 6 ile farkın **yol bazlı** olduğu ve kaynağının §5.3 olduğu açıkça yazılmış — gelecekteki "hangisi geçerli?" tartışması baştan kapatılmış. Kanıt zinciri (config satırı, migration'lar) depoyla birebir.
- **F-6'nın şema itirazı yerinde.** Bulgunun ima ettiği statü kolonu gerçekten gerekmiyor: §3.0.2'nin iki-statü modeli ofiste tek değere yozlaşıyor (ofis alanında katılımcı hesabı açılmıyor), P-1'in gürültü senaryosu ofiste yapısal olarak imkânsız. `users.status`'un AccountStatus olduğu ayrımı da doğru.
- **Kriter 11'in bölünmesi dürüst.** Yapısal iddia testle, tören iddiası gerçek cihazla — proje kaydıyla hizalı ve kapanış raporu şart koşulmuş.
- **Karar 11 + "numaralar kimliktir" notu** izlenebilirliği tamir ediyor; üç atıf da taşınmış.
- **Playwright kararı ölçülü:** zorunluluk dar (kriter 7-8), iş mantığı Pest'te kalıyor — AD-26'nın hız disipliniyle çelişmiyor.

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

**R2-1 — Kriter 13 ve T2 koşulundaki "etkin" kelimesi, MFA-kilitli izin senaryosunda kriteri kendi içinde çelişkili yapıyor.** Koşul *"aktif hesap, hiç **etkin** yetki yok"* (T2 :277, kriter 13). MFA'lı izinler kurulum yapılmamışsa **etkisizdir** (`PermissionFamilies::requiresMfaAndLacksIt()` — izin verilmiş ama etkin değil). Senaryo: yöneticinin yalnız MFA'lı izinler atadığı, ikinci faktörü kurulu olmayan kullanıcı — örn. ilk yetkileri `user.assign_permissions` + `financial.view` olan yeni bir direktör. Etkin yetki sayısı 0 → uyarı **çıkar** ve yetki verildiği hâlde **düşmez**; kriter 13'ün ikinci yarısı (*"yetki verilince düşüyor"*) bu senaryoda yanlışlanır. Mesaj da yanlış kovaya düşer: yönetici "yetki bekliyor" okur, oysa bekleyen şey kullanıcının MFA kurulumudur ve onun uyarısı zaten karar 6'nın bandıdır — aynı durum iki farklı, biri yanıltıcı uyarı üretir. Upstream'in kelimesi de farklı: §3.0.2 *"yetkileri henüz **tanımlanmadıysa**"* der (atanmışlık, etkinlik değil). Koşul "hiç **tanımlı/verilmiş** yetki yok" olduğunda çelişki kaybolur ve iki uyarı ayrışır.

**R2-2 — Kriter 4'ün yeni ölçümü iddianın ikinci büyük kanalını kapsamıyor.** İddia: *"kullanıcıya görünen hiçbir metin Vue dosyasına gömülü değil."* Ölçüm: *"template'te `t()` dışı **metin düğümü** taraması"*, ve gerekçe notu *"metin düğümü taraması iddiayı doğrudan ölçer"* diyor. Ölçmüyor: form-ağırlıklı bu sistemde kullanıcıya görünen metnin önemli bir bölümü **metin düğümü değil, attribute/prop dizgesidir** — `label="Ad Soyad"`, `placeholder="E-posta"`, `aria-label`, `title` (FormField/atom API'si label'ı prop olarak alır, kod-yerlesimi §3 "label+input+hata") — ve `<script>` bloğundaki dizge literal'leri (örn. bir onay metni) de template metin düğümü taramasının dışındadır. F-8'in adlandırdığı hata sınıfı aynen geçerli: kriter yeşilken `label="Durum"` ihlali yaşar. Ya tarama tanımı bu kanalları içerecek şekilde yazılmalı (bilinen kullanıcı-metni attribute/prop listesi + script dizgeleri) ya da iddia ölçümün kapsadığıyla sınırlanıp kalan kanal bilinen sınır olarak kaydedilmelidir.

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

1. **AD-25'in yeni sayım ifadesi ("ofis ve müşteri yüzeyleri") landing'i dışarıda bırakıyor** — EGT-40 turu geldiğinde landing aynı token kaynağından beslenecekse ifade genişletilmeli ya da landing spec'ine yazılmalı. Bugün kıran bir şey yok; kayıt düşülsün diye buradadır.

## 📎 Typos & Nits (non-blocking)

- §8 başlık notu *"Hepsi 27.07.2026'da Sets tarafından kapatıldı"* — §8.3'ün üçüncü satırı (ara ekran) ve §8.4, 28.07.2026 tarihli kararlardır; tarih notu güncellenmeli.
- §5.2 hâlâ "docs/issues.md **#3**" diyor; kayıt numaralı bir madde değil, başlıklı bir bölüm ("Passkey — üç kimlik alanı, tek authenticatable model").

## Verdict: ❌ REJECTED

On üç kalemin on ikisi kanıtla kapandı; F-1 çürütmesi kabul edildi ve netleştirme/revizyon ayrımı doğru kurulmuş. Kalan iki bulgu dar ama davranış değiştiriyor: kriter 13'ün *"etkin"* kelimesi MFA-kilitli izin senaryosunda kriteri kendi ikinci yarısıyla çeliştiriyor ve yanıltıcı bir yönetici uyarısı tanımlıyor (R2-1); kriter 4'ün ölçümü, iddianın en büyük ikinci metin kanalını (attribute/prop dizgeleri ve script literal'leri) hâlâ kapsam dışı bırakıyor (R2-2). İkisi de birkaç cümlelik metin düzeltmesiyle kapanabilir; kapanınca re-review kısa sürer.
