Risk Temelli Doğrulama ve Anomali Motoru

Sürüm: 1.0 · Tarih: 07.09.2026 · İlgili: .claude/plan.md §7, ADR-004, docs/arastirma/hile-senaryolari.md


1. Amaç ve sınır

Sistemin mevcut savunma katmanları (1:1 yüz doğrulama, üç kanallı tazelik bağlaması, rastgele çoklu tur, öğretmen nokta denetimi) anlık çalışır: her tur kendi içinde değerlendirilir. Bu tasarımın kör noktası zaman içinde biriken örüntülerdir:

Tek bir turda bunların hiçbiri anormal değildir. Dönem boyunca bakıldığında sinyaldir.

Risk motoru bu örüntüleri sunucuda sürekli hesaplar, saklar ve yoklama sırasında öğretmene aksiyon önerisi olarak sunar.

Ne yapar, ne yapmaz

YaparYapmaz
Örüntü tespit eder ve kanıtını saklarYoklama durumu belirlemez
Nokta denetimi seçimini yönlendirirÖğrenciyi "yok" saymaz
Ek doğrulama adımı (step-up) tetiklerDisiplin kararı vermez
Öğretmene gerekçeli uyarı gösterirÖğrenciye kalıcı puan/etiket atamaz
Denetim izi üretirDuygu, dikkat, davranış analizi yapmaz

2. Temel ilke — skor karar vermez, insana yönlendirir

Risk skoru bir sonuç değil, bir yönlendirmedir. Tek çıktısı, "bu doğrulamaya bir insan baksın mı?" sorusunun cevabıdır.

Hiçbir risk bandı, hiçbir sinyal kombinasyonu, hiçbir eşik tek başına bir öğrencinin yoklamasını YOK yapamaz. Motorun yapabileceği en sert şey, o oturumda Y4 (öğretmen cihazında yüz yüze doğrulama) talep etmektir. Sonucu yine öğretmen belirler.

Bu bir nezaket kuralı değil, üç zorunluluğun kesişimidir.

① KVKK m.11(g). Veri sahibinin "işlenen verilerin münhasıran otomatik sistemler vasıtasıyla analiz edilmesi suretiyle kişinin kendisi aleyhine bir sonucun ortaya çıkmasına itiraz etme" hakkı vardır. Devamsızlıktan kalmak açık biçimde "aleyhe sonuçtur". Skor doğrudan karar verirse bu hak ihlal edilir. Karar zincirine anlamlı insan müdahalesi konularak madde kapsamı dışına çıkılır. "İnsan onay tuşuna basıyor" yetmez — öğretmenin kararı değiştirebilir olması ve gerekçeyi görebilmesi gerekir. Tasarım bunu sağlar.

② AI Act. m.5(1)(f) eğitimde duygu çıkarımını yasaklar; motorumuz duygu/dikkat/davranış ölçmez, yalnızca teknik olay örüntüsüne bakar — kapsamda değildir. Annex III(3)(d) "sınavlar sırasında öğrencilerin yasaklanmış davranışlarını izleme" sistemlerini yüksek riskli sayar; yoklama sınav değildir ama komşu bir alandır ve hukukçu teyidi gerektirir (§17). Kapsam riskini asgariye indiren tasarım kararı §3'tedir.

③ İtiraz edilebilirlik. Öğrenci "neden benden ek doğrulama istendi?" diye sorduğunda cevap tek cümlelik ve doğrulanabilir olmalıdır: "14 Mart 09:15'te sizin hesabınız için imza üreten cihaz, aynı gün 11:00'de başka bir öğrenci için de imza üretti." Bu cümle kurulamıyorsa sinyal sisteme girmez.


3. Neden kural tabanlı, neden makine öğrenmesi değil

Motor deterministik, elle yazılmış kurallardan oluşur. Anomali tespiti için eğitilmiş bir model (autoencoder, isolation forest, gradient boosting) kullanılmayacaktır. Dört gerekçe:

#Gerekçe
1Etiketli veri yok. Hile nadir ve etiketsizdir. Denetimli öğrenme için pozitif örneğimiz yok. Denetimsiz anomali tespiti ise "bu öğrenci diğerlerine benzemiyor" der — bu hileyi değil farklılığı yakalar. Engelli, geç kalan, farklı cihaz kullanan, farklı saatte gelen öğrenci "anomali" olur.
2Açıklanabilirlik zorunlu. §2③ gereği her bayrak tek cümleyle açıklanmalıdır. "Model 0,87 verdi" bir açıklama değildir ve itiraz sürecinde savunulamaz.
3AI Act kapsamı. AI Act Recital 12, yalnızca gerçek kişilerce tanımlanan kurallara dayanarak otomatik işlem yürüten sistemleri "yapay zekâ sistemi" tanımının dışında tutar. Kural tabanlı kalmak Annex III tartışmasını büyük ölçüde konusuz bırakır. Mimari bir tercihin doğrudan hukuki kazanca dönüştüğü nadir noktalardan biridir.
4Yanlılık denetlenebilirliği. Hangi kuralın hangi grubu neden daha çok işaretlediği ağırlık tablosuna bakılarak görülür ve tek satır değiştirilerek düzeltilir. Öğrenen modelde aynı düzeltme yeniden eğitim gerektirir ve garantisi yoktur.

Sonuç: Motor bir kural motorudur — sürümlenmiş bir yapılandırma dosyası, rules_version ile her değerlendirmeye mühürlenir.


4. Sinyal kataloğu

Her sinyal kaydı: type, severity, evidence (kanıt JSON'u), detected_at, expires_at.

"Tek başına" sütunu: bu sinyal, başka hiçbir sinyal olmadan step-up tetikleyebilir mi?

4.1 Güçlü sinyaller

IDSinyalNasıl hesaplanırAğırlıkYarı ömürTek başına
R1Aynı cihaz, birden fazla öğrenciDonanıma bağlı device_key_id iki farklı student_id için imza üretmiş. Aynı oturumda: doğrudan reddedilir (bir cihaz bir turda tek öğrenci için imzalayabilir) + 60 puan. Dönem içinde farklı oturumlarda: 25 puan.60 / 2590 gün✅
R4Eşzamanlı oturumAynı öğrenci, zaman aralıkları çakışan iki aktif oturumda doğrulanmış. İkisinden biri sahtedir.7090 gün✅
R11Nokta denetimi çelişkisiSistem "doğrulandı" derken öğretmen absent demiş. Motorun sahip olduğu tek yer gerçeği budur.8090 gün✅
R3İmkânsız yer değişimiİki doğrulama arası süre, derslikler arası asgari geçiş süresinden kısa. GPS kullanılmaz — ayrıntı §5.5560 gün✅
R7Şablon taahhüdü uyuşmazlığıcommitment sunucudakiyle tutmuyor (plan §5.1 Katman 2). Zaten fail-closed davranışı tetikler; risk kaydı ayrıca tutulur.5090 gün✅

4.2 Orta sinyaller

IDSinyalNasıl hesaplanırAğırlıkYarı ömürTek başına
R6Attestation bozulmasıverifiedBootState düşmüş, Play Integrity verdict zayıflamış, root belirtisi3060 gün❌
R16Tazelik kanalı tutarsızlığıAğ varken sürekli 3 yerine 2 kanalla doğrulama; veya kanalların zaman damgaları birbirini tutmuyor (plan §4.1)2560 gün❌
R13Cihaz saati oynamasıİmza zaman damgası ile sunucu saati arasındaki sapma, cihazın kendi geçmiş sapma dağılımının dışında2060 gün❌
R2Sık cihaz değişimi90 günde ≥3 farklı cihaza bağlanma2090 gün❌
R15Oturum öncesi yeniden kayıtDoğrulamadan <24 saat önce yeni şablon kaydı yapılmış1530 gün❌
R9RSSI aykırılığıSinyal gücü, o oturumdaki dağılımın alt %5'inde ve tekrarlayan biçimde — koridordan/kapı dışından doğrulama şüphesi1530 gün❌
R10Nonce yaşı aykırılığıNonce tüketim gecikmesi sürekli sınıf p95'inin üstünde — röle saldırısının imzası (S11)1530 gün❌

4.3 Zayıf sinyaller — asla tek başına aksiyon almaz

IDSinyalNasıl hesaplanırAğırlıkYarı ömürTek başına
R5Olağandışı başarısız yüz denemesi⚠️ Mutlak sayı değil, kişinin kendi taban çizgisinden sapma. Yanlılık uyarısı: §6.11030 gün❌
R12Tekrarlayan erken ayrılma örüntüsüSon 10 oturumun ≥%60'ında ERKEN_AYRILDI bayrağı1030 gün❌
R8Sürekli birlikte görülme⚠️ En zayıf ve en çok kötüye kullanılabilir sinyal. Dar tanım: §6.2830 gün❌
R14Gecikme profili aykırılığıDoğrulama süresi cihazın kendi dağılımının dışında (otomasyon şüphesi)830 gün❌

4.4 Riski azaltan sinyaller

Skor yalnızca yukarı gitmemelidir; aksi hâlde her öğrenci zamanla kırmızıya döner.

IDSinyalEtki
N1Nokta denetiminde present teyidi−15 (her teyit)
N2Kararlı cihaz bağlaması — aynı cihaz, ≥60 gün, sıfır anomali−10
N3Step-up sonrası varlığın teyit edilmesi−20 ve step-up'ı tetikleyen sinyali kapatır (resolved_benign)

5. "İmkânsız yer değişimi" — GPS kullanmadan

Bu sinyalin bariz uygulaması öğrencinin konumunu okumaktır. Reddedildi.

Konum verisi toplamak ölçülülük değerlendirmesini (Hat B1) doğrudan zayıflatır: yoklama amacı için sürekli konum takibi orantısızdır, Kurul'un tekrarlayan biçimde eleştirdiği bir aşırılıktır ve "biyometrik veri cihazdan çıkmaz" duruşuyla çelişen yeni bir veri kategorisi ekler.

Bunun yerine sinyal, zaten sahip olduğumuz veriden türetilir:

Girdi:  attendance_sessions.classroom_id   (hangi derslik)
        classrooms.building_id, floor       (kurum tarafından girilir)
        verification.ts                     (ne zaman)

Kurum bir kez "bina geçiş süresi matrisi" tanımlar:
        walk_minutes[bina_A][bina_B]        (varsayılan: aynı bina 2 dk, farklı bina 10 dk)

Kural:  |t2 − t1| < walk_minutes[c1.bina][c2.bina] × 60 × tolerans(0,7)
        → R3 IMPOSSIBLE_TRANSIT

Cihazdan hiçbir konum verisi okunmaz. Sinyal, sistemin kendi ürettiği yoklama olaylarının iç tutarsızlığından doğar. Bu ayrım aydınlatma metnine yazılacaktır — çünkü "imkânsız konum değişimi tespiti" ifadesi okuyanda haklı olarak "beni takip mi ediyorlar?" sorusunu uyandırır. Cevap: hayır, yalnızca iki yoklama kaydının birbiriyle çelişip çelişmediğine bakılır.

Yanlış pozitif kaynakları: hatalı derslik ataması, ders programı değişikliği, bina matrisinin eksik doldurulması, aynı saatte iki derse kayıtlı öğrenci. Bu yüzden R3 tek başına step-up tetikler ama asla kanıt sayılmaz.


6. İki sinyalin özel dikkati

6.1 R5 — başarısız yüz denemesi ve demografik yanlılık tuzağı

Naif kural tehlikelidir. "Çok başarısız deneme = şüpheli" kuralı, yüz tanıma modelinin daha kötü çalıştığı grupları sistematik olarak işaretler. NISTIR 8280, FNMR'nin demografik gruplar arasında 10-100 kat farklılaşabildiğini gösterdi. Böyle bir kural, model yanlılığını doğrudan disiplin şüphesine çevirir. Bu, sistemin yapabileceği en ciddi etik hatadır.

Üç zorunlu önlem:

  1. Mutlak oran değil, kişisel taban çizgisinden sapma. Öğrencinin son 30 gündeki kendi başarısızlık oranı taban alınır; sinyal ancak bu tabandan ani ve büyük sapmada (>2σ) doğar. Kronik yüksek başarısızlık bir kullanılabilirlik sorunudur, şüphe değil — ayrı bir "yeniden kayıt öner" akışına gider.
  2. Bağlam normalizasyonu. Aynı oturumda sınıf genelinde başarısızlık arttıysa (ışık, kalabalık, cihaz ısınması) sinyal bastırılır.
  3. Yanlılık denetimi. §11 RK4: hiçbir demografik grubun step-up oranı genel ortalamanın 1,25 katını aşamaz. Aşarsa sinyal devre dışı bırakılır. Bu, ABD istihdam hukukundaki "dörtte beş kuralı"nın tersten uygulanışıdır — ölçülebilir ve denetlenebilir bir taahhüt.

6.2 R8 — "sürekli birlikte görülme" ve iftira riski

İki öğrenci hep birlikte doğrulanıyorsa bunun en olası açıklaması arkadaş olmalarıdır. Birlikte gelir, yan yana otururlar. Sinyalin ham hâli neredeyse tamamen yanlış pozitiftir.

Ayrıca sosyal yanlılık taşır: birlikte hareket eden öğrenci grupları çoğu zaman aynı şehirden, aynı okuldan, aynı dil veya kültür grubundan gelir. Ham eş-görülme sinyali doğrudan bir grup profillemesine dönüşür.

Bu yüzden R8 dar tanımlanır. Yalnızca şu bileşik koşulda doğar:

A ve B için:
  ① A'nın doğrulamalarının >%90'ı, B'nin doğrulamasından ±3 sn içinde   VE
  ② A, B'nin bulunmadığı hiçbir oturumda doğrulanmamış (n ≥ 10 oturum)   VE
  ③ A veya B için en az bir başka sinyal (R9 / R10 / R6 / R16) mevcut

Yani ölçtüğümüz şey "birlikteler" değil, "A'nın varlığı B'ye teknik olarak bağımlı görünüyor". ③ koşulu sağlanmadan sinyal hiç yazılmaz.

İftira / kirletme saldırısı (S30): Bir öğrenci, başkasının risk skorunu yükseltmek için kasten sinyal tetikleyebilir — arkadaşının cihazını bir kez ödünç alıp kendi hesabıyla giriş yapmak gibi. Karşı önlem: sinyaller eylemi yapan hesaba ve cihaza atfedilir; R1'de puan cihazı ödünç alan tarafa yazılır, sahibine değil. Zayıf sinyaller tek başına aksiyon almadığı için tek noktadan kirletme işe yaramaz.


7. Skorlama

freshness(sinyal) = 0,5 ^ (geçen_gün / yarı_ömür)

risk = clamp(0, 100,  Σ ağırlık_i × freshness_i  +  Σ negatif_j)

band = YEŞİL   if risk <  25
     = SARI    if risk >= 25
     = TURUNCU if risk >= 50
     = KIRMIZI if risk >= 75

8. Aksiyon merdiveni

BandOturum içinde ne olurÖğrenci ne görür
🟢 YEŞİLHiçbir şey. Normal akış.Normal akış
🟡 SARINokta denetimi seçim olasılığı yükselir (p ≈ 0,15)(Seçilirse) normal nokta denetimiyle aynı ekran
🟠 TURUNCUBu oturumda nokta denetimi garantiNormal nokta denetimiyle aynı ekran
🔴 KIRMIZIStep-up: Y4 zorunlu — öğrenci öğretmenin cihazında yüz yüze doğrulanır. Y1 tek başına o oturumda yeterli sayılmaz."Bu derste öğretmeninizin cihazından doğrulama yapmanız gerekiyor"

Hiçbir band YOK üretmez. KIRMIZI bandındaki öğrenci Y4'ü geçerse VAR'dır ve N3 ile skoru düşer. Y4'e gelmezse sonucu öğretmen belirler — sistem değil.

Y4'ün bugünkü hâli (12.09.2026, ADR-024). Yukarıdaki "yüz yüze doğrulanır" ifadesi bir yüz eşleştirmesi anlamına gelmiyor: öğretmen uygulamasında yüz motoru yok ve modeller depoda hiç yok. Y4 bugün "öğretmen adı + numarayı (ve varsa fotoğraf/kartı) öğrenciyle karşılaştırır" demektir. Kanıt sınıfı method="Y4" + source="teacher_device".

Bu tablonun risk açısından değişmeyen kısmı: step-up hâlâ bir yönlendirmedir, sonuç değil, ve Y4 kaydı öğretmenin beyanından (Y3) ayrı bir sınıfta durur. Değişen kısım: Y4 Y1'den zayıftır ve methods.py bunu strength=4 ile söylüyor. KIRMIZI banttaki öğrenciyi Y1'den Y4'e düşürmek, o oturumda kimlik güvencesini artırmaz; yaptığı şey doğrulamayı öğrencinin cihazından çıkarıp öğretmenin gözetimine almaktır. Risk kuralları etkinleştirilmeden önce (RK1-RK4) bu ayrımın yeniden değerlendirilmesi gerekir.

Öğrenciye hangi talebin risk kaynaklı olduğu HİÇ söylenmez — §12'deki kâhin saldırısı. GET /verify/step-up/mine yalnızca öğrencinin kendi açtığı talepleri döndürür; öğretmen kuyruğu da band_at_request ve trigger göstermez.

8.1 İş yükü tavanları — motor dersi felç edemez

TavanDeğerGerekçe
Oturum başına step-up≤ 5 öğrenciBir kural hatası 200 kişilik amfiyi kilitleyemez
Tur başına toplam denetim≤ roster'ın %15'iÖğretmenin fiilen yapabileceği üst sınır
Motor erişilemezseYalnızca rastgele taban uygulanır§10 — fail-open

Bu tavanlar keyfi değildir: çalışma noktası, sınıflandırıcı "doğruluğuna" göre değil öğretmenin iş yüküne göre seçilir. Taban oran argümanı §15'te.


9. Nokta denetimi seçimi — saldırganın seçiciyi kontrol etmesini engellemek

Nokta denetimi eskiden tamamen rastgeleydi. Risk motoru devreye girince seçimi tamamen riske bağlamak cazip ama yanlıştır: skorun nasıl çalıştığını çözen bir öğrenci skorunu sıfırda tutup denetimden tamamen kaçabilir (S29).

Bu yüzden seçim iki bileşenlidir ve rastgele taban asla kaldırılmaz:

seçilenler = rastgele_taban ∪ risk_seçimi

rastgele_taban = max(2, ceil(0,03 × roster))     # riskten TAMAMEN bağımsız
risk_seçimi    = TURUNCU ∪ KIRMIZI
                 + SARI'dan p = 0,15 örnekleme
                 (cap: roster'ın %10'u)

Skoru sıfır olan bir öğrenci bile her turda taban olasılıkla seçilebilir. Risk motoru rastgeleliği yükseltir, yerine geçmez.

Ek olarak: öğrenciye bandı asla gösterilmez ve step-up ekranı, rastgele nokta denetimi ekranıyla görsel olarak aynıdır. Aksi hâlde uygulama bir kâhine (oracle) dönüşür; öğrenci deneme yaparak eşikleri haritalayabilir. Bunun şeffaflık yükümlülüğüyle gerilimi ve çözümü §12'dedir.


10. Arıza davranışı — risk motoru fail-open'dır

Attestation fail-closed'dur (güvenilmeyen kanal kapanır). Risk motoru tam tersidir:

Risk motoru çalışmıyorsa yoklama normal akar; yalnızca rastgele denetim tabanı uygulanır.

Gerekçe: motor varlık kanıtı üretmez, yalnızca inceleme ekler. Çalışmadığında sistem, risk motorundan önceki hâline döner — ki o hâl zaten çalışan bir sistemdir. Motorun arızası öğrenciyi mağdur edemez.

Çevrimdışı çalışma: Oturum açılırken öğretmen cihazına yalnızca band + kısa gerekçe kodu iner. Ham sinyaller, kanıt JSON'ları ve sayısal skor inmez (veri minimizasyonu). SQLCipher ile şifreli tutulur ve oturum kapanınca silinir. Oturum çevrimdışı açıldıysa band bilgisi yoktur → yalnızca rastgele taban.


11. Kalibrasyon — gölge mod zorunlu

Sahada etiketli hile verimiz yok. §4'teki ağırlıklar şu an gerekçeli tahminlerdir, ölçüm değildir. Bunları ölçüm gibi sunmak yanlış olur.

Motor iki aşamada açılır:

Aşama 1 — Gölge mod (Faz 8 pilotunun tamamı). Motor çalışır, sinyalleri ve skorları yazar, hiçbir aksiyon almaz. Nokta denetimi tamamen rastgele kalır. Paralelde kırmızı takım hile-senaryolari.md'deki senaryoları bilinçli olarak uygular — bilinen yer gerçeği bu şekilde üretilir. Sonra ölçülür:

Aşama 2 — Aktif mod. Yalnızca gölge modda kabul kriterlerini geçen sinyaller açılır. Geçmeyen sinyal kodda kalır ama kapalı kalır.

Kabul kriterleri

#KriterHedef
RK1Step-up oranı (normal işletme)≤ tüm doğrulamaların %2'si
RK2Kırmızı takımın enjekte ettiği hilelerin yakalanma oranı≥ %70 (yakalanabilir senaryo alt kümesinde)
RK3Yanlış step-up (step-up sonrası varlığı teyit edilen)≤ tüm doğrulamaların %1'i
RK4Demografik eşitsizlik — grup step-up oranı / genel ortalama≤ 1,25×
RK5Her skorun, saklanan sinyallerden + rules_version'dan birebir yeniden üretilebilmesi%100
RK6Motor kapalıyken yoklamanın tam işlevsel kalmasıOtomatik test
RK7Hiçbir risk skorunun yoklama durumunu otomatik değiştirmemesiOtomatik test — mimari değişmez

RK7 bir test değil bir değişmezdir (invariant): attendance_records.status alanını yazan kod yolunun risk tablolarına erişimi olmayacak biçimde ayrılır.


12. Şeffaflık ve öğrenci hakları

Gerilim: KVKK m.10 profilleme mantığının açıklanmasını ister; §9 ise eşiklerin gizli kalmasını gerektirir — aksi hâlde kaçınılır.

Çözüm — üç katmanlı açıklık:

KatmanİçerikKime
Kamuya açıkBu belgenin §1-§8'i: hangi sinyaller ölçülüyor, mantık nedir, skorun karar vermediğiHerkes · aydınlatma metninde özeti
Talep üzerineÖğrencinin kendi risk kaydı: hangi sinyal, hangi tarih, hangi kanıtVeri sahibi başvurusuyla, kurum eliyle. Uygulama içinde gerçek zamanlı değil — kâhin sorunu
GizliSayısal ağırlıklar, eşikler, örnekleme olasılıklarıKurum yöneticisi + denetim

Sayısal eşiklerin saklanması bir KVKK istisnası değil, meşru bir güvenlik tedbiridir; mantığın kendisi açıklandığı için şeffaflık yükümlülüğü karşılanır. ⚠️ Bu dengenin hukuki yeterliliği avukat teyidi gerektirir (Hat B3).

İtiraz: attendance_appeals akışına risk_flag_contested türü eklenir. Bir risk bayrağının katkıda bulunduğu her yoklama sonucuna itiraz yolu açıktır ve inceleyen yönetici sinyalin kanıt JSON'unu görür. Sinyal hatalıysa resolved_benign işaretlenir, skordan düşer ve aynı türden sinyal o öğrenci için 30 gün bastırılır — aynı hatayı tekrarlamamak için.


13. Veri modeli eklemeleri

risk_signals      (id, student_id, session_id?, type, severity,
                   evidence jsonb,              -- hangi cihaz, hangi zaman, hangi oturum
                   weight_applied, detected_at, expires_at,
                   resolution: open|resolved_benign|resolved_confirmed,
                   resolved_by, resolved_at)

risk_assessments  (id, student_id, session_id, score, band,
                   contributing_signal_ids uuid[], rules_version, computed_at)

risk_rules        (version, definition jsonb, activated_at, activated_by,
                   shadow_mode bool)            -- sürümlü kural seti + gölge mod bayrağı

step_up_requests  (session_id, student_id, trigger: risk|teacher|random,
                   band_at_request, reason_code, required_method: Y4,
                   outcome: present|absent|not_attempted, resolved_by, ts)

device_bindings   (device_key_id, student_id, bound_at, released_at,
                   attestation_level)           -- R1 ve R2'nin temeli

Mevcut tablolarda değişiklik:

Erişim kontrolü: risk_signals ve risk_assessments üzerindeki her okuma audit_log'a yazılır ve gerekçe alanı zorunludur. Öğretmen yalnızca kendi oturumunun band + gerekçe kodunu görür; ham sinyal geçmişi yalnızca kurum yöneticisindedir.


14. Saklama ve imha

VeriSüreGerekçe
risk_signalsTürüne göre 30-180 gün, sonra otomatik silmeÖlçülülük; eski olay kalıcı damga olamaz
risk_assessmentsYoklama kaydıyla aynı (itiraz penceresi + kurum politikası)İtirazda kararın yeniden üretilebilirliği
step_up_requestsYoklama kaydıyla aynıDenetim izi
Teyit edilmiş hile bulgusuKurum belirlerBu artık disiplin sürecidir; veri sorumlusu kurumdur, biz değiliz

Sınır: Sistem hile kanıtı üretir, hile kararı vermez. Disiplin süreci kurumun kendi mevzuatına tabidir. Veri işleyen sözleşmesine bu açıkça yazılacaktır.

Kodda karşılığı: app/risk/retention.py (silen kod) + app/tools/purge_risk_signals.py (bakım betiği). Silme kendiliğinden olmaz; zamanlayıcı kurulumu §18.1'de. Kurulmazsa GET /risk/rules içindeki "en geç 180 günde silinir" cümlesi yerine gelmez.


15. Yanlış pozitif ekonomisi — taban oran sorunu

Hile nadirdir. 10.000 öğrencilik bir kurumda günde 40.000 doğrulama üretiliyorsa ve gerçek hile oranı %0,5 ise:

Bu, tıbbi tarama testlerindeki klasik taban oran yanılgısıdır ve risk motorlarında sürekli yapılan hatadır. Üç sonucu vardır ve üçü de tasarıma yazılmıştır:

  1. Çalışma noktası "doğruluk"a göre değil iş yüküne göre seçilir (§8.1 tavanları, RK1 ≤ %2).
  2. Bayrak asla kanıt değildir — bu yüzden her aksiyon insan teyidiyle biter.
  3. Zayıf sinyaller birleşmeden aksiyon almaz — tek zayıf sinyalin pozitif kestirim değeri düşüktür.

16. Hile senaryolarıyla ilişki

SenaryoMotorun katkısı
S1 — Telefonu arkadaşa vermeR1 doğrudan yakalar. Y2/Y5'te açık kalan boşluğun asıl kapanma noktası burasıdır
S11 — Röle saldırısıR10 (nonce yaşı) + R9 (RSSI) + R16 (kanal tutarsızlığı) örüntüsü, tek turda görünmeyeni dönem boyunca görünür kılar; nokta denetimini hedefe yönlendirir
S15 — Yoklama alıp çıkmaR12 tekrarlayan örüntüyü yakalar
S9 / S26 — Root, şablon kurcalamaR6 / R7 — plan §5.1 Katman 5'in somut hâli
S18 — Başkasının yüzüyle kayıtR15 + R11 birlikte
S27 — Hesap paylaşımı / satışıR1 + R2 + R3 kombinasyonu
S29 — Risk motorunu öğrenip kaçınmaRastgele taban (§9) hiçbir zaman kaldırılmaz
S30 — Risk kirletme / iftiraSinyal eylemi yapana atfedilir; zayıf sinyaller tek başına aksiyon almaz (§6.2)
S31 — Çapa (öğretmen cihazı) ele geçirmeR16 — sunucu kanalı çapadan bağımsız olduğu için tutarsızlık görünür olur (plan §4.1)

17. Açık konular

  1. AI Act Annex III(3)(d) kapsam analizi — yoklama hile tespiti "sınav sırasında yasak davranış izleme" sayılır mı? Kural tabanlı olmak güçlü bir savunmadır ama hukukçu teyidi şarttır. → Hat B3
  2. §12'deki üç katmanlı şeffaflık modelinin KVKK yeterliliği — avukat mütalaası. → Hat B3
  3. Ağırlıkların hiçbiri ölçülmemiştir. §4 tablosu gerekçeli tahmindir. Gölge mod öncesinde hiçbir sinyal aktif edilmeyecektir.
  4. R3 için bina geçiş matrisi kurumdan gelir — eksik veya yanlış doldurulursa sinyal gürültüye döner. Kurulum sihirbazında zorunlu adım olacaktır.
  5. Ölçülülük değerlendirmesi (B1) bu motoru da kapsamalıdır — profilleme ayrı bir işleme faaliyetidir, ayrıca gerekçelendirilir.

18. İşletim — verilen sözlerin kodda ve sunucuda karşılığı

Bu bölüm, §14'ün imha vaadinin, §11'in gölge mod şartının, §5'in bina matrisinin ve §13'ün denetim izinin çalışan karşılıklarını tarif eder. Belgenin geri kalanı tasarımı anlatır; burası kurulumu anlatır ve kurulmazsa ne olmadığını açıkça söyler.

18.1 Sinyal imhası — "en geç 180 günde silinir" (B2)

expires_at bir satırı silmez; yalnızca skordan düşürür. Skordan düşmek imha değildir: satır yedeklenir, sorgulanabilir, mahkeme celbine konu olur.

ParçaYer
Silen kodapp/risk/retention.py — purge_expired()
Bakım betiğiapp/tools/purge_risk_signals.py
Yönetici ucuPOST /risk/retention/purge (kendi kurumu), GET /risk/retention/status

Silme koşulu iki parçalıdır: expires_at <= now veya detected_at <= now − 180 gün. İkincisi emniyet kemeridir — bir kuralın yarı ömrü sonradan büyütülürse ya da bir göç expires_ati yanlış doldurursa, üst sınır yine olayın kendi yaşına bakar.

Her silme audit_loga yazılır: action = risk.retention_purge, yükünde silinen satır sayısı, çalışma zamanı, tür dağılımı ve kurum.

⚠️ Bu depoda zamanlayıcı yoktur. Betik kendiliğinden çalışmaz. Aşağıdaki üç kurulumdan biri yapılmadan vaat yerine gelmez; ayrıntılı örnekler (tam cron satırı, systemd unit/timer, Docker Compose ve Kubernetes CronJob) app/tools/purge_risk_signals.py baş yorumundadır.

# cron
17 3 * * *  yoklama  cd /srv/yoklama/services/api && \
    /srv/yoklama/.venv/bin/python -m app.tools.purge_risk_signals

# systemd timer          OnCalendar=*-*-* 03:17:00 · Persistent=true
# Docker                 docker compose run --rm api python -m app.tools.purge_risk_signals

Kurulum nasıl doğrulanır: GET /risk/retention/status → expired_still_present. Bu sayı gün geçtikçe büyüyorsa zamanlayıcı çalışmıyordur. Betiği yazmış olmak değil, bu sayının sıfıra dönüyor olması sözü tutar.

Bilinen bedel: 180 günden eski bir değerlendirmenin skoru artık sinyallerden birebir yeniden üretilemez — RK5 zayıflar. Bu, §14'ün kendi içindeki bir gerilimdir (sinyale 30–180 gün, karara yoklama kaydı ömrü). İmha vaadi tercih edildi; risk_assessments.contributing_signal_ids "burada bir sinyal vardı ve imha edildi" izini bırakır.

18.2 Kural bazında etkinleştirme — varsayılan KAPALI (B3)

risk_rules tablosu artık kullanılıyor: app/risk/activation.py, uçlar GET|POST /risk/rules/activation.

§3.6 ("yalnızca RK1–RK4'ü geçen sinyaller aktif edilir") nasıl uygulanıyor: Tam otomatik uygulanamıyor, çünkü RK1–RK4 ölçüm gerektirir ve Faz 8 pilotu çalışmadı — o veri yok. Yapılan şey, yapılamayanın yerine geçmeye çalışmıyor: etkinleştirme (ve kapatma) en az 40 karakterlik zorunlu bir gerekçe ister; gerekçe, aktör ve zamanla birlikte hem risk_rules.definition içinde hem audit_logda saklanır.

Bu bir ölçüm değildir. Zorunlu gerekçe alanı RK1–RK4 ölçümünün yerine geçmez. Serbest metindir, doğrulanmaz, yanlış da yazılabilir. Tek yaptığı, ölçümsüz bir etkinleştirmeyi sessiz olmaktan çıkarıp imzalı bir karara dönüştürmektir. Gerçek RK1–RK4 sayıları üretildiğinde bu kapının yerini otomatik bir kontrol almalıdır; o zamana kadar burada duran şey bir kontrol değil, bir kayıttır.

Kapatma da gerekçe ister: RK4 aşıldığında sinyalin kapatılacağı ADR-004 §7'de bir taahhüttür ve gerekçesiz bir kapatma izi olmayan bir geri adımdır.

18.3 Bina geçiş matrisi — R3'ün tek veri kaynağı (B8)

Uçlar: GET|PUT|DELETE /walk-matrix, GET|POST /walk-matrix/buildings, PUT /walk-matrix/classrooms/{id}/building. Hepsi admin, hepsi kurum sınırlı, hepsi denetim kaydına yazar.

Tanımsız çift için sinyal ÜRETİLMEZ. Önceki kod eksik satırı varsayılanla dolduruyordu (aynı bina 2 dk, farklı bina 10 dk). Matrisi hiçbir kurum doldurmadığı için bu varsayılan tek geçerli değer olurdu ve arka arkaya iki dersi olan herkes R3 alırdı. Eksik veriyi bir sayıyla doldurmak — 0 dakika da, 10 dakika da — eksiği ölçülmüş gibi gösterir.

Aynı bina çiftleri de (A → A) ayrıca tanımlanmalıdır: beş katlı bir blokla tek katlı bir atölye aynı değildir ve o süreyi kurumdan başkası bilemez. Matris yön duyarsız okunur (A → B yazıldıysa B → A de tanımlıdır).

R3'ün zinciri: oturum → derslik → bina → matris. Halkalardan biri kopuksa sinyal yoktur. En çok kopan halka derslik–bina bağıdır; toplu yükleme derslikleri binasız açar. GET /walk-matrix/buildings → unassigned_classrooms bunu sayar, GET /walk-matrix → undefined matrisin neresinin boş olduğunu açıkça listeler.

18.4 Denetim kaydını okuma (B10)

GET /audit — admin, gerekçe zorunlu, filtreler: aktör, varlık türü, varlık kimliği, eylem, tarih aralığı; sayfalama limit/offset. GET /audit/actions filtre kutusu için eylem adlarını verir.

Okumanın kendisi denetlenir. Denetim kaydı kişisel veri içerir — kimin, ne zaman, hangi gerekçeyle hangi öğrencinin risk geçmişine baktığı. Yani bu uç, korumak için var olduğu şeyin aynısını işler. Her okuma action = audit.read olarak geri yazılır: aktör, gerekçe, kullanılan filtreler ve dönen satır sayısı. Bir yöneticinin bütün kurumu tarayıp çıkması mümkündür ama sessiz değildir.

Kurum sınırı ve bilinen bir şema eksiği: audit_log tablosunda institution_id sütunu yoktur. Sınır bu yüzden aktör üzerinden çözülür: bir satır, ancak actor alanı okuyanın kurumundaki bir kullanıcıya çözülürse görünür. Sistem satırları (actor boş — cron'la çalışan imha betiği gibi) yalnızca entity_id kurum kimliğine eşitse görünür. Eksik yönde hata verilmesi tercih edildi: görünmeyen kendi satırın, görünen başkasının satırından iyidir. Kalıcı çözüm audit_loga institution_id sütunudur.

Bu sayfa depodaki docs/risk-motoru.md dosyasından scripts/belgeleri-uret.py ile üretilir. Elle düzenlenmez; değişiklik kaynağa yapılır.