---
title: 'Güvenli Geliştirme Yaşam Döngüsü'
source: 'https://academia.sh/tr/kurslar/guvenli-yasam-dongusu'
language: tr
updated: '2026-08-17T04:38:40+00:00'
license: 'CC BY-SA 4.0'
lessons: 11
outcomes:
    - 'Güvenlik etkinliklerini aşamalara dağıtır ve aşama başına düzeltme maliyetini hesaplar'
    - 'Veri akış çizgesi ve güven sınırlarıyla tehdit modelleme oturumu yürütür'
    - 'Güvenlik gereksinimlerini otomatik sınanabilir biçimde yazar'
---

# Güvenli Geliştirme Yaşam Döngüsü

Bir açığın hangi aşamada doğduğu, hangi aşamada yakalandığı ve geç yakalandığında maliyetinin kaç kat arttığı: güvenliğin akışa dahil edilmesiyle ayrı bir kapı olarak durmasının farkı, sola kaydırmanın kazancı ve tasarımda görülemeyecek kalem sınıfı, kötüye kullanım senaryolarının sınanabilir gereksinime çevrilmesi, ekip içi güvenlik yetkinliğinin dağıtılması, sınırlı geliştirme kapasitesinin risk temelli dağıtımı, tehdit modellemenin tasarım aşamasında bulduğu açık, veri akış çizgesinde güven sınırını geçen akışların sayılması, sistematik tehdit üretme yöntemlerinin ürettiği anlamlı ve anlamsız tehdit oranı, saldırı ağaçlarında en ucuz yolun hesaplanması ve model çıktısının kaçının iş öğesine dönüştüğü.

## DevSecOps Yaklaşımı

Güvenliğin geliştirme akışına dahil edilmesiyle ayrı bir kapı olarak durmasının ölçülen farkı: aynı kalem kümesinin hangi aşamada doğduğu, hangi aşamada yakalandığı ve kaç aşama geç kaldığı, sola kaydırmanın aşama başına düzeltme maliyetini kaç kat düşürdüğü ve erken yakalamanın hiç işe yaramadığı kalem sınıfı, güvenlik gereksinimlerinin otomatik sınanabilirliği, kötüye kullanım senaryolarının ortaya çıkardığı gereksinimler, güvenlik yetkinliğinin ekiplere dağıtılması ve sınırlı geliştirme kapasitesinin risk temelli dağıtımı.

### DevSecOps ve DevOps Farkı

Source: https://academia.sh/tr/kurslar/guvenli-yasam-dongusu/devsecops-ve-devops-farki

Aynı 23 kalemlik küme iki akışta koşturulur: dağıtım öncesinde duran tek güvenlik kapısı 10 kalem yakalar, 5 kalemi hiç görmez ve 60. günde 120 değişikliği kuyrukta bekletir; denetim altı aşamaya dağıtıldığında 23 kalemin tamamı yakalanır ve ortalama gecikme 1,94 aşamadan 0,13 aşamaya iner. Dağıtmanın bedeli 200 uyarının 177'sinin yanlış pozitif olmasıdır.

Önceki müfredat on kurs boyunca savunmanın kapattığı yolu saydı ve kapanışında kıt bir bütçenin
hangi kaleme gideceğini sordu. Bütün o ölçümlerin ortak ve sessiz bir varsayımı vardı: **yazılım
zaten yazılmıştı.** Yol kümesi çalışan bir sistemden çıkarılıyor, denetim çalışan bir sisteme
konuyordu. Bu kurs o varsayımı kaldırır ve aynı ölçüm ağının yazılımını üretilirken ele alır.

Ölçü birimi değişir. Yol yerine **aşama** sayılır: bir açık ya da yanlış karar hangi aşamada
doğuyor, hangi aşamada yakalanabiliyor ve aradaki fark kaç aşama. Bu ilk ders farkın en kaba
biçimini ölçer — güvenliğin akışa **dahil** olmasıyla akışın sonunda **ayrı bir kapı** olarak
durması arasındaki fark. İki düzenek aynı kalem kümesi üzerinde koşturulur; üç sütun çıkar: kaç
kalem yakalanıyor, kaç aşama geç yakalanıyor, karşılığında ne ödeniyor.

- **DY1.** Ağ ve yazılımı kurgusaldır: bölgesel ölçüm ağının abone portalı, sayaç toplama servisi,
  faturalama ve saha uygulaması beş ekipçe geliştiriliyor. Değişiklik akışı ve kalem kümesi `node`
  ile modellenir; ölçülen şey bu modeldir.
- **DY2.** Aşama kümesi altı ögedir: gereksinim, tasarım, kod, yapı, dağıtım, çalışma zamanı. Bir
  kalem tek bir aşamada doğar ve doğduğu aşamadan önce yakalanamaz.
- **DY3.** Görünürlük vektörü model kararıdır: o aşamaya konan bir denetimin kalemi görüp
  göremeyeceğini söyler. Gerçekte bu eşleme denenerek çıkarılır; dersin noktası eşleme değil,
  üzerinde yapılan sayımdır.
- **DY4.** Bir denetim kalemi ya görür ya görmez. Kısmi görme ve gözden kaçırma olasılığı
  modellenmiyor; ikisi de yakalanan kalem sayısını düşürür, yönünü değiştirmez.
- **DY5.** Kapı incelemesi paket düzeyinde yapılır. Bir pakette kapının gördüğü bir kalem varsa
  paketin tamamı geri döner; paketteki öbür değişiklikler de bekler.
- **DY6.** Uyarı sayıları ve dakika değerleri verilmiş model değerleridir. Yanlış pozitif sayısı
  verilmez, uyarı sayısından gerçekten yakalanan kalem çıkarılarak bulunur.

#### Kalem Kümesi ve Değişiklik Akışı

Model iki şeyi ayrı tutar: akıştan geçen **değişiklikler** ve o değişikliklerin bir bölümünün
taşıdığı **kalemler**. Kalem, doğduğu aşamayla ve altı basamaklı bir görünürlük vektörüyle
tanımlanır.

```js
// akis.mjs — kurgusal olcum agi yaziliminin degisiklik akisi ve kalem kumesi (model)
export const ASAMA = ['gereksinim', 'tasarim', 'kod', 'yapi', 'dagitim', 'calisma-zamani'];
export const EKIP = [['abone-portali', 10], ['sayac-toplama', 8], ['faturalama', 6],
  ['saha-uygulamasi', 5], ['ortak-kitaplik', 6]];
export const GUN = 60; // 12 haftalik olcum penceresi, is gunu
// kalem: ad | dogdugu asama | gorunurluk vektoru (asama basina 1/0: oraya konan bir
// denetim bu kalemi gorebilir mi). Vektorler model kararidir, olcum degil.
export const KALEM = `
  veri-siniflandirmasi-yok      0 100000
  saklama-suresi-tanimsiz       0 100001
  kisisel-veri-kapsami-belirsiz 0 100010
  kimlik-dogrulamasiz-ic-cagri  1 011110
  zayif-oturum-modeli           1 010011
  guven-sinirsiz-veri-akisi     1 010000
  yetki-modelinde-eksik-rol     1 011001
  eksik-yetki-denetimi          2 001101
  gomulu-gizli-anahtar          2 001110
  dogrulanmamis-girdi           2 001001
  gunluge-yazilan-kisisel-veri  2 001001
  yarim-kalan-hata-yolu         2 001000
  zayif-rastgelelik             2 001000
  sinirsiz-sorgu-boyu           2 000001
  guncel-olmayan-bagimlilik     3 000110
  imzasiz-yapi-ciktisi          3 000110
  gereksiz-yapi-araci           3 000100
  varsayilan-parola             4 000011
  asiri-genis-ag-kurali         4 000011
  sifresiz-yedek                4 000010
  acik-yonetim-ucu              4 000011
  olcek-altinda-yaris           5 000001
  ucuncu-tarafta-aciklanan-acik 5 000001`
  .trim().split('\n').map((r) => {
    const [ad, d, g] = r.trim().split(/\s+/);
    return { ad, dogus: +d, g };
  });
export const GUNLUK = EKIP.reduce((s, [, n]) => s + n, 0) / 5;
export const TOPLAM_DEGISIKLIK = GUNLUK * GUN;
// Kalem tasiyan degisiklik, akista esit araliklarla yerlestirilir (model).
export const TASIYAN = new Map(KALEM.map((k, i) =>
  [Math.floor((i * TOPLAM_DEGISIKLIK) / KALEM.length), k]));
// Ilk gorulebilen asama: dogustan sonra gorunurluk vektorunun 1 oldugu ilk asama.
export const ilkGorulen = (k, asamalar) =>
  asamalar.find((i) => i >= k.dogus && k.g[i] === '1') ?? null;
```

Vektörler dersin asıl bilgisini taşır. `veri-siniflandirmasi-yok` yalnız gereksinim aşamasında
görülebilir; sonraki hiçbir denetim onu bulamaz, çünkü ortada yanlış bir satır yoktur, eksik bir
karar vardır. `sinirsiz-sorgu-boyu` kod aşamasında doğar ama yalnız çalışma zamanında görünür:
kodda hatalı bir şey yoktur, veri büyüdüğünde ortaya çıkan bir sınır yokluğu vardır.

#### Ayrı Kapının Kuyruğu

İlk düzenek güvenliği tek noktaya koyar: dağıtımdan önce duran bir inceleme kapısı. Kapının günlük
kapasitesi sınırlıdır, geliş hızı ise ekiplerin toplamıdır.

```js
// kosum1.mjs — ayri kapi: degisiklikler dagitim oncesi tek noktada kuyruga girer
import { GUN, GUNLUK, TOPLAM_DEGISIKLIK, TASIYAN, KALEM } from './akis.mjs';

const KAPASITE = 5; // kapinin gunde bitirebildigi inceleme sayisi (model)

function kos(b) {
  const paket = [];
  for (let i = 0; i < TOPLAM_DEGISIKLIK; i += b) {
    const son = Math.min(i + b, TOPLAM_DEGISIKLIK) - 1, ic = [];
    for (let c = i; c <= son; c++) if (TASIYAN.has(c)) ic.push(TASIYAN.get(c));
    paket.push({ ilk: i, n: son - i + 1, hazir: Math.floor(son / GUNLUK), ic, biten: null });
  }
  for (let g = 0; g < GUN * 20; g++) {
    let yer = KAPASITE;
    for (const p of paket) if (p.biten === null && p.hazir <= g && yer-- > 0) p.biten = g;
  }
  // Bir degisikligin beklemesi: kendi geldigi gunden paketinin bittigi gune kadar.
  let bekleme = 0;
  for (const p of paket)
    for (let c = p.ilk; c < p.ilk + p.n; c++) bekleme += p.biten - Math.floor(c / GUNLUK);
  const acik = paket.filter((p) => p.hazir < GUN && p.biten >= GUN);
  return { gunluk: paket.length / GUN, bekleyen: acik.reduce((s, p) => s + p.n, 0),
    ort: bekleme / TOPLAM_DEGISIKLIK,
    donen: paket.filter((p) => p.ic.some((k) => k.g[4] === '1')).reduce((s, p) => s + p.n, 0) };
}

const gorulen = KALEM.filter((k) => k.g[4] === '1').length;
console.log(`${GUNLUK} degisiklik/gun, ${GUN} gun, ${TOPLAM_DEGISIKLIK} degisiklik; ` +
  `kapi ${KAPASITE} inceleme/gun; kapinin gorebildigi kalem ${gorulen}/${KALEM.length}`);
console.log('\npaket  inceleme/gun  60. gunde bekleyen degisiklik  ortalama bekleme gun  geri donen degisiklik');
for (const b of [1, 2, 3, 5, 7]) {
  const r = kos(b);
  console.log(String(b).padEnd(7) + r.gunluk.toFixed(1).padEnd(14) +
    String(r.bekleyen).padEnd(30) + r.ort.toFixed(1).padEnd(22) + r.donen);
}
```

```
7 degisiklik/gun, 60 gun, 420 degisiklik; kapi 5 inceleme/gun; kapinin gorebildigi kalem 10/23

paket  inceleme/gun  60. gunde bekleyen degisiklik  ortalama bekleme gun  geri donen degisiklik
1      7.0           120                           12.0                  10
2      3.5           0                             0.1                   20
3      2.3           0                             0.1                   30
5      1.4           0                             0.3                   50
7      1.0           0                             0.0                   70
```

İlk satır kapının kapasite sorununu veriyor: günde yedi değişiklik geliyor, kapı beşini
bitirebiliyor. Aradaki iki değişiklik biriktiği için altmışıncı günde 120 değişiklik hâlâ
kuyrukta, ortalama bekleme 12 gündür. Bu bir yavaşlama değil, **doymuş bir kuyruktur**: fark
kapanmadıkça bekleme süresi süre geçtikçe büyümeye devam eder.

Ekiplerin bu duruma verdiği karşılık paketlemedir — değişiklikleri biriktirip tek incelemeye
sokmak. Tablo paketlemenin çalıştığını gösteriyor: paket boyu ikiye çıktığında kuyruk kapanıyor ve
ortalama bekleme onda bir güne iniyor. Son sütun bedeli yazıyor. Kapının gerçekten gördüğü kalem
sayısı her satırda **onda** sabit kalırken, o on kalem yüzünden geri dönen değişiklik sayısı 10'dan
70'e çıkıyor. Paket boyu yedide, tek bir kalem için altı meşru değişiklik daha bekletiliyor.

Kapının ikinci sınırı en baştaki satırda duruyor: yirmi üç kalemin yalnız onu kapının bakabildiği
biçimdedir. Kalan on üç kalem kapıdan sorunsuz geçer, çünkü kapı bir gereksinim kararına ya da bir
tasarım boşluğuna bakmaz — elindeki tek şey dağıtılmak üzere olan yapının kendisidir.

#### Aynı Kalem Kümesi, Dağıtılmış Denetim

İkinci düzenek aynı kalem kümesini alır ve denetimi altı aşamaya dağıtır. Karşılaştırma bu yüzden
adildir: değişen tek şey denetimin **nerede durduğudur**.

İki düzeneğin adlandırılması burada anlam kazanır. Geliştirme ve işletimin tek akışta birleşmesi
(DevOps) bir araç seçimi değil, bir geri bildirim kuralıdır: her karar, sonucunu gördüğü döngü ne
kadar kısaysa o kadar ucuza düzeltilir. Kapı düzeneği bu kuralı teslim hızı için uygular ama
güvenlik kalemini kuralın dışında bırakır; güvenliğin geri bildirim döngüsü, ne kadar hızlı
çalışırsa çalışsın, akışın en sonundaki tek noktadan geçer. Güvenliğin akışa dahil edilmesi
(DevSecOps) aynı kuralı güvenlik kalemine de uygulamaktan ibarettir. Ayırt edici olan yeni bir
denetim türü eklemek değildir — tablodaki altı denetimin beşi kapı düzeneğinde de kurulabilir.
Ayırt edici olan, denetimin kalemin **doğduğu** döngüye yerleştirilmesidir.

```js
// kosum2.mjs — ayni kalem kumesi iki akista: denetim tek kapida ve asamalara dagitilmis
import { ASAMA, KALEM, ilkGorulen } from './akis.mjs';

// Akisa dahil denetimin asama basina uretimi (model): calisan birim, uretilen uyari,
// uyari basina gelistirici dakikasi.
const DENETIM = [['gereksinim incelemesi', 18, 5, 25], ['tasarim oturumu', 12, 9, 30],
  ['statik kod cozumlemesi', 420, 96, 6], ['bagimlilik taramasi', 420, 54, 8],
  ['yapilandirma denetimi', 60, 22, 12], ['calisma zamani gozlemi', 60, 14, 20]];

const akislar = [['ayri kapi', [4, 5]], ['akisa dahil', [0, 1, 2, 3, 4, 5]]];
console.log('akis         yakalanan  hic gorulmeyen  toplam gecikme asama  ortalama gecikme');
const sonuc = new Map();
for (const [ad, asamalar] of akislar) {
  const y = KALEM.map((k) => [k, ilkGorulen(k, asamalar)]);
  const bulunan = y.filter(([, i]) => i !== null);
  const gec = bulunan.reduce((s, [k, i]) => s + i - k.dogus, 0);
  sonuc.set(ad, y);
  console.log(ad.padEnd(13) + String(bulunan.length).padEnd(11) +
    String(KALEM.length - bulunan.length).padEnd(16) + String(gec).padEnd(22) +
    (gec / bulunan.length).toFixed(2));
}

console.log('\nasama           dogan  kapi akisinda yakalanan  dagitilmis akista yakalanan');
for (const [i, a] of ASAMA.entries())
  console.log(a.padEnd(16) + String(KALEM.filter((k) => k.dogus === i).length).padEnd(7) +
    String(sonuc.get('ayri kapi').filter(([, j]) => j === i).length).padEnd(24) +
    sonuc.get('akisa dahil').filter(([, j]) => j === i).length);

console.log('\ndenetim                 birim  uyari  gercek  yanlis pozitif  gelistirici dakikasi');
let uy = 0, dk = 0;
for (const [i, [ad, birim, uyari, dak]] of DENETIM.entries()) {
  const gercek = sonuc.get('akisa dahil').filter(([, j]) => j === i).length;
  uy += uyari; dk += uyari * dak;
  console.log(ad.padEnd(24) + String(birim).padEnd(7) + String(uyari).padEnd(7) +
    String(gercek).padEnd(8) + String(uyari - gercek).padEnd(16) + uyari * dak);
}
console.log(`\ntoplam ${uy} uyari, ${dk} dakika (${(dk / 60).toFixed(1)} saat), ` +
  `kalem basina ${(dk / 60 / 23).toFixed(1)} saat`);
const kapiSaat = 300 * 3;
console.log(`kapi: 300 inceleme x 3 saat = ${kapiSaat} saat, 10 kalem, ` +
  `kalem basina ${(kapiSaat / 10).toFixed(0)} saat`);
```

```
akis         yakalanan  hic gorulmeyen  toplam gecikme asama  ortalama gecikme
ayri kapi    18         5               35                    1.94
akisa dahil  23         0               3                     0.13

asama           dogan  kapi akisinda yakalanan  dagitilmis akista yakalanan
gereksinim      3      0                       3
tasarim         4      0                       4
kod             7      0                       6
yapi            3      0                       3
dagitim         4      10                      4
calisma-zamani  2      8                       3

denetim                 birim  uyari  gercek  yanlis pozitif  gelistirici dakikasi
gereksinim incelemesi   18     5      3       2               125
tasarim oturumu         12     9      4       5               270
statik kod cozumlemesi  420    96     6       90              576
bagimlilik taramasi     420    54     3       51              432
yapilandirma denetimi   60     22     4       18              264
calisma zamani gozlemi  60     14     3       11              280

toplam 200 uyari, 1947 dakika (32.5 saat), kalem basina 1.4 saat
kapi: 300 inceleme x 3 saat = 900 saat, 10 kalem, kalem basina 90 saat
```

Birinci tablo iki ayrı sayı veriyor ve ikisini karıştırmamak gerekir. Kapı akışında **18** kalem
yakalanıyor, ama bunların yalnız onu kapıda yakalanıyor; kalan sekizi çalışma zamanında bir olayla
ortaya çıkıyor. Ortaya çıkma yakalama değildir, ama kalem hiç değilse bilinir hâle gelir. **5**
kalem ise hiçbir düzeneğin görmediği kalemdir: gereksinimdeki sınıflandırma boşluğu, tasarımdaki
sınırsız veri akışı, koddaki yarım hata yolu ve zayıf rastgelelik, yapıdaki gereksiz araç. Bunlar
kayıtta yoktur, sıralamaya girmez, bütçede yer tutmaz.

Gecikme sütunu farkı tek sayıya indiriyor. Kapı akışında yakalanan kalemler toplam **35 aşama**
geç bulunuyor, kalem başına 1,94 aşama. Dağıtılmış akışta toplam gecikme **3 aşamadır** ve tamamı
tek bir kalemden gelir: kod aşamasında doğan `sinirsiz-sorgu-boyu`, ancak çalışma zamanında görünür.

İkinci tablo bu tek kalemi doğrudan gösteriyor. Kod aşamasında yedi kalem doğuyor, dağıtılmış akış
altısını kod aşamasında yakalıyor. Yedincisi hiçbir erken denetimin bakamayacağı sınıftandır ve
denetimi ne kadar sola alırsanız alın orada kalır. Bu kursun ikinci dersi tam olarak o sınıfı sayar.

#### Dağıtmanın Bedeli

Üçüncü tablo dağıtılmış akışın faturasıdır. Altı denetim toplam **200 uyarı** üretiyor; bunların
**23'ü** gerçek kalem, **177'si** yanlış pozitiftir. Oran denetimden denetime değişir: gereksinim
incelemesi beş uyarının üçünü doğru yazar, statik kod çözümlemesi doksan altı uyarının altısını.
Sıklık arttıkça isabet düşer, çünkü kod çözümlemesi 420 değişikliğin her birinde koşarken
gereksinim incelemesi on sekiz kez toplanır.

Toplam yük **1.947 geliştirici dakikası**, yani 32,5 saattir. Kapı akışının aynı pencerede
harcadığı süre 300 inceleme çarpı üç saat, yani 900 saattir. Kalem başına ödenen bedel dağıtılmış
akışta 1,4 saat, kapı akışında 90 saattir — altmış dört katlık bir fark. İki sayının aynı işi
ölçmediği not edilmelidir: kapı her değişikliğe bakar, dağıtılmış denetim yalnız uyarı üretenlere
bakar. Farkın kaynağı da budur.

Bedelin ikinci kalemi tabloda görünmez. 177 yanlış pozitif, 177 kez bir geliştiricinin işini
bölmesi demektir; bunların doksanı tek bir denetimden gelir. Bir denetimin gerçek maliyeti
çalıştığı süre değil, **ürettiği uyarının kaçının bir insan tarafından okunmak zorunda olduğudur.**
Yanlış pozitif oranı yükseldiğinde uyarılar okunmaz hâle gelir ve o denetimin yakaladığı gerçek
kalemler de görünmez olur — bu, denetimi hiç koymamakla aynı sonucu verir, ancak maliyeti sürer.

#### Özet

- Kurgusal ölçüm ağı yazılımında 60 iş gününde 420 değişiklik akıyor ve 23 kalem taşıyor; kalemler
  altı aşamanın hepsinde doğuyor, en çok kod aşamasında (7 kalem).
- Dağıtım öncesinde duran tek kapı 23 kalemin yalnız 10'unu görebilir. Günde 7 değişiklik gelir, 5
  inceleme biter; 60. günde 120 değişiklik kuyrukta bekler ve ortalama bekleme 12 gündür.
- Paketleme kuyruğu kapatır ama bedeli geri dönen meşru değişikliktir: paket boyu 1'de 10, paket
  boyu 7'de 70 değişiklik aynı 10 kalem yüzünden bekletilir.
- Denetim altı aşamaya dağıtıldığında 23 kalemin tamamı yakalanır; hiç görülmeyen kalem 5'ten 0'a,
  toplam gecikme 35 aşamadan 3 aşamaya, kalem başına gecikme 1,94'ten 0,13 aşamaya iner.
- Dağıtmanın bedeli 200 uyarının 177'sinin yanlış pozitif olmasıdır; 1.947 geliştirici dakikasının
  576'sı tek bir denetimin ürettiği 96 uyarıya gider.
- Kod aşamasında doğan 7 kalemin 6'sı kod aşamasında yakalanır, biri yalnız çalışma zamanında
  görünür; erken denetim bu kalemin gecikmesini düşürmez.

#### Sonraki Adım

Bu ders denetimin yerini değiştirdi ve yakalanan kalem sayısının arttığını, gecikmenin düştüğünü
saydı. Ölçülmeyen tek şey **bu gecikmenin ne kadara mal olduğudur**. Otuz beş aşamalık gecikme bir
sayıdır, ama bir kalemi tasarım aşamasında düzeltmekle çalışma zamanında düzeltmek arasındaki fark
aşama sayısı değil, harcanan iştir: bir tasarım kararını değiştirmek bir toplantıdır, aynı kararı
dağıtılmış bir sistemden geri almak veri göçü, sürüm planı ve kesinti penceresidir. Sonraki ders
aşama başına düzeltme maliyetini modelin içine koyar, aynı kalem kümesini geç ve erken denetimli
iki akışta koşturur ve toplam katı hesaplar. Aynı ders ikinci bir soruyu da sorar: bu katın hangi
kalemler için geçerli **olmadığını**, yani erken yakalamanın hiçbir şey kazandırmadığı kalem
sınıfının ne kadar büyük olduğunu.

### Sola Kaydırma

Source: https://academia.sh/tr/kurslar/guvenli-yasam-dongusu/sola-kaydirma

Düzeltme maliyeti aşama başına geri alınan işten türetilir ve aynı 23 kalemlik küme iki akışta koşturulur: ortak 18 kalemde geç akış 318 saat, erken akış 68 saat, kat 4,68 ve önlenen 250 saatten denetim yükü düşünce net kazanç 217,5 saat kalır. Kat tek bir sayı değildir, gereksinimde doğan kalemde 22,5, dağıtımda doğanda 13'tür; erken akış bedelinin yarısı sola kaydırmanın hiç dokunamadığı tek kalemden gelir.

Önceki ders denetimin yerini değiştirdi: tek kapı yerine altı aşamaya dağıtılmış denetimle
yakalanan kalem 18'den 23'e çıktı, toplam gecikme 35 aşamadan 3 aşamaya indi. Gecikme bir sayıydı,
ama **aşama** bir para birimi değildir. Bir kalemi tasarım aşamasında düzeltmek bir toplantı
kararıdır; aynı kalemi çalışan bir sistemden geri almak veri göçü, sürüm planı ve kesinti
penceresidir. İki iş aynı birimle ölçülemez.

Bu ders o birimi kurar. Denetimin akışta öne alınmasına **sola kaydırma** (shift left) denir ve
tek başına bu ifade bir karar taşımaz — ne kadar sola, hangi kalem için ve ne pahasına sorusunun
yanıtı yoktur. Burada aşama başına düzeltme maliyeti modele girer, aynı kalem kümesi geç ve erken
denetimli iki akışta koşar, toplam kat hesaplanır. Dersin ikinci yarısı ters yöne bakar: kaydırmanın
hiçbir şey kazandırmadığı kalem sınıfı ayrılır ve o sınıfın bedeldeki payı sayılır.

- **DY7.** Kalem kümesi önceki dersle aynıdır ve değişmez; eklenen tek şey maliyettir.
- **DY8.** Düzeltme maliyeti verilmiş bir çarpan değildir, **geri alınan işten türetilir**: kalem
  doğduğu aşamadan sonra kaç aşama geçtiyse, o aşamalarda üretilmiş iş de yeniden yapılır.
- **DY9.** Aşama başına geri alma bedelleri ve temel düzeltme emeği model değerleridir; birim
  **kurgu geliştirici-saattir**. Gerçek bir kurumda bu sayılar geçmiş düzeltme kayıtlarından
  çıkarılır.
- **DY10.** Karşılaştırma yalnız **iki akışta da yakalanan** kalemler üzerinde yapılır. Geç akışın
  hiç görmediği kalemin bedeli sıfır değildir, **ödenmemiştir**; ayrı yazılır.
- **DY11.** Erken denetimlerin koşum yükü önceki dersten alınır ve tek kalemde net kazançtan
  düşülür. Kurulum, eğitim ve bakım yükü modelde yoktur; hepsi net kazancı düşürür.

#### Aşama Başına Düzeltme Maliyeti

Maliyet bir çarpan olarak verilmez, kurulur. Her aşama bir iş üretir; kalem o aşamayı geçtikten
sonra düzeltilirse üretilen iş de geri alınır. Toplam bedel, temel düzeltme emeği artı geçilen
aşamaların geri alma bedelidir.

```js
// maliyet.mjs — ayni kalem kumesi, artik asama basina duzeltme maliyetiyle (model)
export const ASAMA = ['gereksinim', 'tasarim', 'kod', 'yapi', 'dagitim', 'calisma-zamani'];
// Bir asamayi gecmenin geri alinma bedeli (kurgu gelistirici-saat): kalem o asamayi
// gectiyse, duzeltme o asamada uretilmis isi de yeniden yaptirir.
export const YENIDEN = [0, 3, 8, 2, 6, 24];
export const TEMEL = 2; // kalemin kendi duzeltme emegi, asamadan bagimsiz
// Maliyet: temel emek arti dogus ile yakalama arasinda gecilen her asamanin geri alinmasi.
export const bedel = (dogus, yakalanan) =>
  TEMEL + YENIDEN.slice(dogus + 1, yakalanan + 1).reduce((s, x) => s + x, 0);
export const KALEM = `
  veri-siniflandirmasi-yok      0 100000
  saklama-suresi-tanimsiz       0 100001
  kisisel-veri-kapsami-belirsiz 0 100010
  kimlik-dogrulamasiz-ic-cagri  1 011110
  zayif-oturum-modeli           1 010011
  guven-sinirsiz-veri-akisi     1 010000
  yetki-modelinde-eksik-rol     1 011001
  eksik-yetki-denetimi          2 001101
  gomulu-gizli-anahtar          2 001110
  dogrulanmamis-girdi           2 001001
  gunluge-yazilan-kisisel-veri  2 001001
  yarim-kalan-hata-yolu         2 001000
  zayif-rastgelelik             2 001000
  sinirsiz-sorgu-boyu           2 000001
  guncel-olmayan-bagimlilik     3 000110
  imzasiz-yapi-ciktisi          3 000110
  gereksiz-yapi-araci           3 000100
  varsayilan-parola             4 000011
  asiri-genis-ag-kurali         4 000011
  sifresiz-yedek                4 000010
  acik-yonetim-ucu              4 000011
  olcek-altinda-yaris           5 000001
  ucuncu-tarafta-aciklanan-acik 5 000001`
  .trim().split('\n').map((r) => {
    const [ad, d, g] = r.trim().split(/\s+/);
    return { ad, dogus: +d, g };
  });
export const ilkGorulen = (k, asamalar) =>
  asamalar.find((i) => i >= k.dogus && k.g[i] === '1') ?? null;
```

```js
// kosum1.mjs — kat, tek bir sayi degildir: dogdugu asamaya gore degisir
import { ASAMA, YENIDEN, bedel, KALEM } from './maliyet.mjs';

console.log('dogus asamasi   yeniden yapma  en erken bedel  en gec bedel  kat   kalem');
for (const [i, a] of ASAMA.entries()) {
  const erken = bedel(i, i), gec = bedel(i, ASAMA.length - 1);
  console.log(a.padEnd(16) + String(YENIDEN[i]).padEnd(15) + String(erken).padEnd(16) +
    String(gec).padEnd(14) + (gec / erken).toFixed(1).padEnd(6) +
    KALEM.filter((k) => k.dogus === i).length);
}
console.log('\nayni kalem, asama asama gecikirse (tasarimda dogan bir kalem)');
console.log('yakalandigi asama  bedel  bir onceki asamaya gore artis');
let onceki = null;
for (let j = 1; j < ASAMA.length; j++) {
  const b = bedel(1, j);
  console.log(ASAMA[j].padEnd(19) + String(b).padEnd(7) +
    (onceki === null ? '-' : `${b - onceki} saat, ${(b / onceki).toFixed(2)} kat`));
  onceki = b;
}
```

```
dogus asamasi   yeniden yapma  en erken bedel  en gec bedel  kat   kalem
gereksinim      0              2               45            22.5  3
tasarim         3              2               42            21.0  4
kod             8              2               34            17.0  7
yapi            2              2               32            16.0  3
dagitim         6              2               26            13.0  4
calisma-zamani  24             2               2             1.0   2

ayni kalem, asama asama gecikirse (tasarimda dogan bir kalem)
yakalandigi asama  bedel  bir onceki asamaya gore artis
tasarim            2      -
kod                10     8 saat, 5.00 kat
yapi               12     2 saat, 1.20 kat
dagitim            18     6 saat, 1.50 kat
calisma-zamani     42     24 saat, 2.33 kat
```

Birinci tablo kat sütununu tek bir sayıya indirmenin neden yanlış olduğunu gösteriyor. Gereksinim
aşamasında doğan bir kalem en geç yakalandığında 22,5 kat pahalıya düzeltilir; dağıtımda doğan bir
kalem için aynı sayı 13'tür. Aradaki fark kalemin ciddiyetinden değil, **doğduğu noktadan sonra
kaç aşamalık iş üretildiğinden** gelir. "Geç bulunan açık kat kat pahalıdır" cümlesi doğru, ama
hangi kat olduğu kalemin nereden geldiğine bağlıdır ve ikisi arasında 1,7 katlık bir fark vardır.

İkinci tablo daha keskin bir şey söylüyor: artış düzgün değildir. Tasarımda doğan bir kalem kod
aşamasına sarktığında bedel beş katına çıkar; oradan yapı aşamasına geçtiğinde yalnız 1,2 katına.
Artışın yoğunlaştığı iki sınır vardır — kodun yazıldığı aşama ve sistemin çalışır hâle geldiği
aşama. Aralarındaki yapı ve dağıtım sınırları ucuzdur. Bu, kaydırmanın nereye yapılacağını doğrudan
belirler: bir denetimi dağıtımdan yapıya çekmek 6 saat kazandırır, koddan tasarıma çekmek 8 saat.
Aynı çabayla farklı sınırlar geçilir ve hepsi eşit değildir.

#### İki Akış, Toplam Kat

Aynı kalem kümesi iki akışta koşuyor: denetimin yalnız dağıtım ve çalışma zamanında bulunduğu geç
akış ile altı aşamanın hepsinde bulunduğu erken akış.

```js
// kosum2.mjs — ayni kalem kumesi iki akista: gec denetimli ve erken denetimli
import { ASAMA, bedel, KALEM, ilkGorulen } from './maliyet.mjs';

const GEC = [4, 5], ERKEN = [0, 1, 2, 3, 4, 5];
const DENETIM_YUKU = 32.5; // erken denetimlerin kosum yuku (onceki dersten, saat)
const satir = KALEM.map((k) => {
  const g = ilkGorulen(k, GEC), e = ilkGorulen(k, ERKEN);
  return { k, g, e, gb: g === null ? null : bedel(k.dogus, g), eb: bedel(k.dogus, e) };
});
const ortak = satir.filter((s) => s.g !== null);
const yalnizErken = satir.filter((s) => s.g === null);
const kazanmayan = ortak.filter((s) => s.g === s.e);
const top = (l, f) => l.reduce((a, s) => a + f(s), 0);

console.log(`${KALEM.length} kalem; ikisinde de yakalanan ${ortak.length}, ` +
  `gec akisin hic gormedigi ${yalnizErken.length}`);
const gt = top(ortak, (s) => s.gb), et = top(ortak, (s) => s.eb);
console.log(`gec akis ${gt} saat, erken akis ${et} saat, kat ${(gt / et).toFixed(2)}, ` +
  `onlenen ${gt - et} saat`);
console.log(`net kazanc: ${gt - et} - ${DENETIM_YUKU} = ${(gt - et - DENETIM_YUKU).toFixed(1)} saat`);
console.log(`gec akisin hic gormedigi ${yalnizErken.length} kalem erken akista ` +
  `${top(yalnizErken, (s) => s.eb)} saate kapaniyor; gec akista bedeli hic odenmez`);

console.log('\nkazanc nerede yogunlasiyor');
console.log('dogus asamasi   kalem  gec bedel  erken bedel  onlenen  pay %');
for (const [i, a] of ASAMA.entries()) {
  const l = ortak.filter((s) => s.k.dogus === i);
  if (l.length === 0) { console.log(a.padEnd(16) + '0'); continue; }
  const g = top(l, (s) => s.gb), e = top(l, (s) => s.eb);
  console.log(a.padEnd(16) + String(l.length).padEnd(7) + String(g).padEnd(11) +
    String(e).padEnd(13) + String(g - e).padEnd(9) + (((g - e) / (gt - et)) * 100).toFixed(1));
}

// Kazandirmayan kalemler iki ayri sinif: gec dogduklari icin erisilemeyenler ile
// erken dogup yalnizca gec gorunebilenler.
const gecDogan = kazanmayan.filter((s) => s.k.dogus >= 4);
const gecGorunen = kazanmayan.filter((s) => s.k.dogus < 4);
console.log(`\nerken denetimin kazandirmadigi ${kazanmayan.length} kalem, iki sinif`);
console.log('sinif                     kalem  erken akistaki bedel  erken akis bedelinin %');
for (const [ad, l] of [['erken dogup gec gorunen', gecGorunen], ['gec dogan', gecDogan]])
  console.log(ad.padEnd(26) + String(l.length).padEnd(7) + String(top(l, (s) => s.eb)).padEnd(22) +
    ((top(l, (s) => s.eb) / et) * 100).toFixed(1));
for (const s of gecGorunen)
  console.log(`  ${s.k.ad}: ${ASAMA[s.k.dogus]} asamasinda dogar, ${ASAMA[s.e]} ` +
    `asamasinda gorunur, iki akista da ${s.eb} saat`);
```

```
23 kalem; ikisinde de yakalanan 18, gec akisin hic gormedigi 5
gec akis 318 saat, erken akis 68 saat, kat 4.68, onlenen 250 saat
net kazanc: 250 - 32.5 = 217.5 saat
gec akisin hic gormedigi 5 kalem erken akista 10 saate kapaniyor; gec akista bedeli hic odenmez

kazanc nerede yogunlasiyor
dogus asamasi   kalem  gec bedel  erken bedel  onlenen  pay %
gereksinim      2      66         4            62       24.8
tasarim         3      78         6            72       28.8
kod             5      146        42           104      41.6
yapi            2      16         4            12       4.8
dagitim         4      8          8            0        0.0
calisma-zamani  2      4          4            0        0.0

erken denetimin kazandirmadigi 7 kalem, iki sinif
sinif                     kalem  erken akistaki bedel  erken akis bedelinin %
erken dogup gec gorunen   1      34                    50.0
gec dogan                 6      12                    17.6
  sinirsiz-sorgu-boyu: kod asamasinda dogar, calisma-zamani asamasinda gorunur, iki akista da 34 saat
```

Ortak on sekiz kalem üzerinde geç akış **318 saat**, erken akış **68 saat** harcıyor; toplam kat
**4,68**. Bu, tek kalem üzerinden okunan 13–22,5 aralığından epey düşüktür ve düşük olması
gerekir: kat, kalemlerin doğuş dağılımına göre ağırlıklanır ve kümenin dörtte biri zaten dağıtım
ya da çalışma zamanında doğduğu için kazanç üretmez. Bir programın gerçek katı, kaydırmanın
erişebildiği tek bir kalemin katından her zaman küçüktür.

Önlenen 250 saatten erken denetimlerin koşum yükü düşüldüğünde **net kazanç 217,5 saat** kalır.
Sayının kendisi kadar biçimi önemlidir: sola kaydırma bir ilke olarak değil, iki kalemli bir
çıkarma olarak yazılabilir hâle gelmiştir. Modelde bulunmayan kurulum, eğitim ve bakım yükleri bu
sayıyı düşürür; bir kurumda karar, önlenen saatin bu üç kalemi de karşılayıp karşılamadığına bakar.

Aynı çıkarma bir başabaş noktası da verir. Önlenen 250 saat, koşum yükünün üstüne en çok 217,5
saatlik kurulum, eğitim ve bakım kaldırabilir; bu eşiğin üstündeki her saat kaydırmayı zarara
çevirir. Altı denetimin kurulumu bu bütçeye sığmıyorsa doğru karar hepsini kurmak değil, kazanç
payı en yüksek olan aşamalardan başlamaktır — ve o sıra bu tablodaki pay sütununda yazılıdır.

Modelin sessiz bir varsayımı burada söylenmelidir: **yakalanan her kalem düzeltiliyor sayıldı.**
Gerçekte yakalanan kalemlerin bir bölümü bilerek ertelenir. Ertelenen kalem, yakalanmamış kalemle
aynı yolu izler ve sonunda geç akıştaki bedeli öder; erken denetim yalnız ödemeyi **görünür**
kılmıştır. Bu yüzden 250 saatlik önleme bir kazanç değil, bir **üst sınırdır**: gerçekleşmesi
yakalanan kalemleri düzeltecek kapasitenin bulunmasına bağlıdır.

Geç akışın hiç görmediği beş kalem karşılaştırmanın dışında tutuldu. Erken akış onları 10 saate
kapatıyor; geç akışta bedelleri **sıfır değil, ödenmemiştir**. Bir düzeltme maliyeti tablosunun en
yanıltıcı satırı budur: hiç bulunmayan kalem, tabloda en ucuz kalem gibi görünür.

Kazanç dağılımı kaydırmanın nereye yapılacağını söylüyor. Önlenen 250 saatin **%41,6'sı** kod
aşamasında doğan kalemlerden, %28,8'i tasarımda, %24,8'i gereksinimde doğanlardan gelir. Yapı
aşamasında doğan kalemler toplamın yalnız %4,8'ini üretir; dağıtım ve çalışma zamanında doğanlar
sıfır üretir. İlk üç aşamaya konan denetim kazancın %95'ini taşır.

#### Kaydırmanın Kazandırmadığı Kalem

Son tablo bu dersin asıl bulgusudur. On sekiz kalemin **yedisi** erken denetimden hiçbir şey
kazanmıyor ve bu yedi kalem iki ayrı sınıftır.

Birinci sınıf altı kalemdir ve tanım gereği erişilemez: dağıtımda ya da çalışma zamanında doğarlar.
Bir yapılandırma kalemi ya da sonradan açıklanan bir bağımlılık açığı, tasarım oturumunda
konuşulamaz çünkü o oturum yapıldığında henüz yoktur. Bu sınıfın bedeli düşüktür — erken akış
bedelinin %17,6'sı — çünkü zaten doğdukları aşamada yakalanırlar.

İkinci sınıf tek bir kalemdir ve dersin sert bulgusu odur. `sinirsiz-sorgu-boyu` kod aşamasında
doğar, ancak çalışma zamanında görünür ve iki akışta da **34 saate** mal olur. Erken akışın toplam
68 saatlik bedelinin **tam yarısı** bu tek kalemden gelir. Denetimi ne kadar sola alırsanız alın bu
sayı düşmez, çünkü kodda görülecek bir şey yoktur: yanlış yazılmış bir satır değil, konulmamış bir
sınır vardır ve sınırın gerekli olduğu ancak veri büyüdüğünde ortaya çıkar.

Bu sınıfın ortak yanı, kalemin **varlığının bir ölçeğe, bir veri dağılımına ya da bir dış olaya
bağlı olmasıdır**. Yük altında ortaya çıkan yarışlar, belirli veri hacminden sonra anlam kazanan
sınır yoklukları ve ancak bir dış duyuruyla bilinir hâle gelen bağımlılık açıkları buraya girer.
Bu kalemler için doğru karar kaydırmak değil, çalışma zamanında **görmeyi ucuzlatmaktır** — ölçüm,
sınır denetimi ve geri alma hazırlığı. Sola kaydırmanın kapsamını yazmayan bir program, bu sınıfın
maliyetini de kaydırmanın başarısızlığı olarak okur ve yanlış yere daha çok denetim koyar. Ayrımın
ölçülebilir karşılığı şudur: bir kalemin geç yakalanması denetimin eksikliğinden geliyorsa erken
akış onu ucuzlatır; kalemin kendisi geç görünüyorsa erken akışın bedeli geç akışınkiyle **birebir
aynı** kalır. Tablodaki son sütun tam olarak bu eşitliği arar.

#### Özet

- Düzeltme maliyeti çarpan olarak verilmez, geri alınan işten türetilir: temel emek artı doğuştan
  yakalamaya kadar geçilen her aşamanın geri alma bedeli.
- Kat tek bir sayı değildir: gereksinimde doğan kalemde 22,5, dağıtımda doğanda 13. Artış da düzgün
  değildir — tasarımdan koda geçmek 5 kat, koddan yapıya geçmek 1,2 kattır.
- Ortak 18 kalemde geç akış 318 saat, erken akış 68 saat harcar; toplam kat 4,68, önlenen 250 saat.
  Denetim yükü düşüldüğünde net kazanç 217,5 saattir.
- Geç akışın hiç görmediği 5 kalem karşılaştırmanın dışındadır: bedelleri sıfır değil ödenmemiştir,
  erken akış onları 10 saate kapatır.
- Önlenen saatin %95'i ilk üç aşamada doğan kalemlerden gelir; yapıda doğanlar %4,8, dağıtım ve
  çalışma zamanında doğanlar %0 üretir.
- 18 kalemin 7'si erken denetimden hiçbir şey kazanmaz. Altısı geç doğduğu için erişilemez;
  yedincisi kodda doğup yalnız çalışma zamanında görünür ve tek başına erken akış bedelinin
  yarısını taşır.

#### Sonraki Adım

Bu ders kaydırmanın kazancını ve sınırını sayıya bağladı, ama kazancın en büyük payını taşıyan
aşamayı kutu içinde bıraktı. Önlenen saatin dörtte biri gereksinim aşamasında doğan kalemlerden
geliyor ve o kalemleri yakalayan denetim tabloda tek satırla geçti: on sekiz gereksinim
incelemesi, beş uyarı, üç gerçek kalem. Bir gereksinim incelemesinin bir kalemi nasıl yakaladığı
hiç açılmadı. Yakalayabilmesi için gereksinimin **sınanabilir** yazılmış olması gerekir; "sistem
güvenli olmalıdır" biçiminde yazılmış bir satır hiçbir incelemede hiçbir kalem üretmez. Sonraki
ders güvenlik gereksinimlerini sınanabilirlik ekseninde sınıflandırır: kaç gereksinim otomatik
sınanabiliyor, kaçı yalnız gözle denetlenebiliyor, kaçı hiç sınanamıyor ve kötüye kullanım
senaryosu yazıldığında listeye kaç yeni gereksinim giriyor.

### Güvenlik Gereksinimleri

Source: https://academia.sh/tr/kurslar/guvenli-yasam-dongusu/guvenlik-gereksinimleri

Sınanabilirlik üç parçadan türetilir ve 20 güvenlik gereksinimi üzerinde koşturulur: 13'ü otomatik sınanabilir, 3'ü tek bir eksik parça yüzünden gözle denetlenir, 4'ü nitel yüklemi yüzünden yeniden yazılmadan hiçbir sınıfa geçemez. Beş kötüye kullanım senaryosu listeyi yüzde 40 büyütür ve gelen 8 gereksinimin 7'si engelleyici kiptedir; gözle sınamanın 40 saatlik yükü eksik parçalar yazıldığında tamamen düşer.

Önceki ders önlenen 250 saatin dörtte birinin gereksinim aşamasında doğan kalemlerden geldiğini
saydı, ama o kalemleri yakalayan denetimi tek satırda bıraktı: on sekiz gereksinim incelemesi, beş
uyarı, üç gerçek kalem. Bir incelemenin bir kalemi nasıl yakaladığı açılmadı. Yakalayabilmesinin
tek koşulu vardır: gereksinimin, karşılanıp karşılanmadığı **sınanabilir** biçimde yazılmış olması.
"Sistem güvenli olmalıdır" satırı hiçbir incelemede hiçbir kalem üretmez, çünkü ihlal edildiğini
gösterecek bir gözlem yoktur.

Bu ders sınanabilirliği bir sıfat olmaktan çıkarıp üç parçaya ayırır ve yirmi gereksinimlik bir
liste üzerinde koşturur. İkinci yarıda listenin nereden geldiği sorulur: özellik listesini okuyarak
yazılan gereksinimlerle, sistemin **engellemesi** gereken bir hedefi izleyen bir aktör düşünülerek
yazılan gereksinimler aynı kümeyi vermez.

- **DY12.** Gereksinim listesi kurgusaldır ve `node` ile modellenir. Her gereksinim dört alanla
  yazılır: özne, yüklem türü, eşik, kapsam.
- **DY13.** Sınanabilirlik verilmez, **türetilir**: yüklem gözlenebilirse ve hem eşik hem kapsam
  yazılmışsa gereksinim otomatik sınanabilir. Parçalardan biri eksikse gözle denetlenir; yüklem
  nitelse hiç sınanamaz.
- **DY14.** Yüklem türü ve kip alanları gereksinimin **yazılış biçiminin** kaydıdır, içeriğinin
  değeri değil. Sınanamaz yazılmış bir gereksinim önemsiz değildir; yalnız denetlenemez.
- **DY15.** Kötüye kullanım senaryosu bir aktör ve bir hedefle modellenir; hiçbir adım
  çalıştırılabilir biçimde verilmez. Senaryonun bir kurumun kendi sistemi dışında denenmesi
  **yazılı yetki ve tanımlı kapsam** gerektirir, aksi hem yasadışı hem de meslek dışıdır.
- **DY16.** Koşum sayıları ve gözle denetim dakikası model değerleridir; önceki derslerin değişiklik
  ve dağıtım sayılarıyla uyumludur.

#### Sınanabilirliğin Üç Parçası

Bir gereksinimin otomatik sınanabilmesi için üç şey gerekir: ihlalin görüleceği **gözlenebilir bir
yüklem**, karşılandığını söyleyecek bir **eşik** ve nerede geçerli olduğunu söyleyen bir **kapsam**.
Üçünden biri eksikse sınama bir insana devredilir.

```js
// gereksinim.mjs — olcum agi yaziliminin guvenlik gereksinimleri (model)
// satir: ad | ozne | yuklem turu | esik | kapsam | kip
// yuklem: olay = gozlenebilir olay, durum = denetlenebilir durum, nitelik = nitel sifat
// kip: saglar = sistemin yaptigi is, engeller = sistemin reddettigi is
const oku = (s) => s.trim().split('\n').map((r) => {
  const [ad, ozne, yuklem, esik, kapsam, kip] = r.trim().split(/\s+/);
  return { ad, ozne, yuklem, esik, kapsam, kip };
});
export const GEREKSINIM = oku(`
  oturum-suresi-siniri     oturum            durum    30-dk           abone-portali    engeller
  hatali-giris-siniri      giris-ucu         olay     5-deneme        abone-portali    engeller
  aktarim-sifrelemesi      dis-baglanti      durum    zorunlu         tum-uclar        saglar
  olcum-verisi-saklama     olcum-kaydi       durum    24-ay           olcum-deposu     saglar
  yetki-denetimi-kapsami   okuma-ucu         olay     her-istek       faturalama       saglar
  gizli-deger-kaynakta     kaynak-dosya      durum    0-adet          tum-depolar      engeller
  kisisel-veri-gunlukte    gunluk-satiri     durum    0-alan          tum-servisler    engeller
  bagimlilik-yasi          bagimlilik        durum    180-gun         tum-yapilar      saglar
  yonetim-ucu-erisimi      yonetim-ucu       olay     ic-ag           sayac-toplama    engeller
  yedek-sifrelemesi        yedek-dosyasi     durum    zorunlu         fatura-vt        saglar
  istek-hiz-siniri         genel-uc          olay     60-istek-dk     abone-portali    engeller
  oturum-sonlandirma       cikis-eylemi      olay     1-istek         abone-portali    saglar
  dosya-yukleme-boyu       yukleme-ucu       durum    10-mb           saha-uygulamasi  engeller
  hata-mesaji-icerigi      hata-yaniti       durum    -               tum-uclar        engeller
  denetim-kaydi-tutma      yetki-degisikligi olay     her-degisiklik  -                saglar
  parola-saklama-bicimi    abone-kaydi       durum    -               abone-portali    saglar
  kimlik-dogrulama-gucu    abone-girisi      nitelik  -               abone-portali    saglar
  arayuz-guvenligi         saha-uygulamasi   nitelik  -               -                saglar
  veri-butunlugu           olcum-kaydi       nitelik  -               -                saglar
  gorev-ayrimi             fatura-onayi      nitelik  -               faturalama       engeller`);

// Sinanabilirlik turetilir: gozlenebilir yuklem + esik + kapsam varsa otomatik sinanir.
export function sinif(g) {
  if (g.yuklem === 'nitelik') return 'sinanamaz';
  const eksik = ['esik', 'kapsam'].filter((a) => g[a] === '-');
  return eksik.length === 0 ? 'otomatik' : 'gozle';
}
export const eksikParca = (g) => ['esik', 'kapsam'].filter((a) => g[a] === '-');

// Kotuye kullanim senaryosu: bir aktor, sistemin engellemesi gereken bir hedefi izler.
// Model olarak yazilir; hicbir adim calistirilabilir bicimde verilmez.
export const SENARYO = [
  ['abone-hesabini-ele-gecirme', 'dis-aktor',
    ['hatali-giris-siniri', 'oturum-suresi-siniri', 'oturum-sonlandirma', 'giris-bildirimi']],
  ['baskasinin-faturasini-okuma', 'yetkili-abone',
    ['yetki-denetimi-kapsami', 'kayit-kimligi-tahmini']],
  ['olcum-kaydini-degistirme', 'saha-personeli',
    ['denetim-kaydi-tutma', 'olcum-yazma-yetkisi', 'olcum-degisikligi-onayi']],
  ['toplu-abone-verisi-cekme', 'yetkili-abone',
    ['istek-hiz-siniri', 'toplu-indirme-siniri', 'disari-akan-hacim-esigi']],
  ['cihazi-baskasi-adina-kaydetme', 'dis-aktor',
    ['cihaz-kayit-dogrulamasi', 'kayit-hiz-siniri']],
];
// Senaryolardan cikan ve listede olmayan gereksinimler, ayni bicimde yazildiginda:
export const YENI = oku(`
  giris-bildirimi          basarili-giris    olay     her-giris       abone-portali    saglar
  kayit-kimligi-tahmini    fatura-kaydi      durum    tahmin-edilemez  faturalama      engeller
  olcum-yazma-yetkisi      olcum-kaydi       olay     rol-esli        olcum-deposu     engeller
  olcum-degisikligi-onayi  olcum-duzeltmesi  olay     iki-imza        olcum-deposu     engeller
  toplu-indirme-siniri     dis-aktarim       durum    -               abone-portali    engeller
  disari-akan-hacim-esigi  dis-aktarim       durum    50-mb-gun       tum-uclar        engeller
  cihaz-kayit-dogrulamasi  cihaz-kaydi       olay     saha-onayi      saha-uygulamasi  engeller
  kayit-hiz-siniri         cihaz-kaydi       olay     10-kayit-saat   -                engeller`);
```

```js
// kosum1.mjs — gereksinimler sinanabilirlige gore ayrilir; eksik parca sayilir
import { GEREKSINIM, sinif, eksikParca } from './gereksinim.mjs';

const say = (l, s) => l.filter((g) => sinif(g) === s).length;
console.log(`${GEREKSINIM.length} gereksinim; otomatik ${say(GEREKSINIM, 'otomatik')}, ` +
  `gozle ${say(GEREKSINIM, 'gozle')}, sinanamaz ${say(GEREKSINIM, 'sinanamaz')}`);

console.log('\nsinif       gereksinim  esigi olan  kapsami olan  gozlenebilir yuklem');
for (const s of ['otomatik', 'gozle', 'sinanamaz']) {
  const l = GEREKSINIM.filter((g) => sinif(g) === s);
  console.log(s.padEnd(12) + String(l.length).padEnd(12) +
    String(l.filter((g) => g.esik !== '-').length).padEnd(13) +
    String(l.filter((g) => g.kapsam !== '-').length).padEnd(14) +
    l.filter((g) => g.yuklem !== 'nitelik').length);
}

console.log('\notomatige gecmeyen gereksinimler ve eksik parcalari');
for (const g of GEREKSINIM.filter((x) => sinif(x) !== 'otomatik'))
  console.log('  ' + g.ad.padEnd(25) + sinif(g).padEnd(12) +
    (g.yuklem === 'nitelik' ? 'yuklem nitel: yeniden yazilmadan sinif degistiremez'
      : `eksik: ${eksikParca(g).join(', ')}`));

const tekEksik = GEREKSINIM.filter((g) => sinif(g) === 'gozle' && eksikParca(g).length === 1);
console.log(`\ntek parca eklenerek otomatige gecen ${tekEksik.length} gereksinim; ` +
  `yeniden yazim gerektiren ${say(GEREKSINIM, 'sinanamaz')} gereksinim`);
console.log(`onarimdan sonra otomatik ${say(GEREKSINIM, 'otomatik') + tekEksik.length}/` +
  `${GEREKSINIM.length}, kalan ${GEREKSINIM.length - say(GEREKSINIM, 'otomatik') - tekEksik.length}`);
```

```
20 gereksinim; otomatik 13, gozle 3, sinanamaz 4

sinif       gereksinim  esigi olan  kapsami olan  gozlenebilir yuklem
otomatik    13          13           13            13
gozle       3           1            2             3
sinanamaz   4           0            2             0

otomatige gecmeyen gereksinimler ve eksik parcalari
  hata-mesaji-icerigi      gozle       eksik: esik
  denetim-kaydi-tutma      gozle       eksik: kapsam
  parola-saklama-bicimi    gozle       eksik: esik
  kimlik-dogrulama-gucu    sinanamaz   yuklem nitel: yeniden yazilmadan sinif degistiremez
  arayuz-guvenligi         sinanamaz   yuklem nitel: yeniden yazilmadan sinif degistiremez
  veri-butunlugu           sinanamaz   yuklem nitel: yeniden yazilmadan sinif degistiremez
  gorev-ayrimi             sinanamaz   yuklem nitel: yeniden yazilmadan sinif degistiremez

tek parca eklenerek otomatige gecen 3 gereksinim; yeniden yazim gerektiren 4 gereksinim
onarimdan sonra otomatik 16/20, kalan 4
```

Yirmi gereksinimin on üçü otomatik sınanabilir, üçü gözle denetlenir, dördü hiç sınanamaz. Asıl
bilgi ikinci ve üçüncü satırların ayrımındadır. Gözle denetlenen üç gereksinimin **yüklemi
gözlenebilirdir**; eksik olan tek bir alandır. `hata-mesaji-icerigi` hata yanıtının ne
içermeyeceğini söyler ama eşik yazmaz; `denetim-kaydi-tutma` her yetki değişikliğinin kaydını
ister ama hangi servislerde geçerli olduğunu söylemez. İkisi de bir satır eklenerek otomatiğe
geçer.

Sınanamaz dördün durumu farklıdır. `veri-butunlugu` ya da `arayuz-guvenligi` eksik alanı olan
gereksinimler değildir; yüklemleri bir gözleme karşılık gelmez. Bunlara eşik yazmak da işe
yaramaz, çünkü neyin ölçüleceği belli değildir. Sınıf değiştirmeleri için gereken şey tamamlama
değil **yeniden yazımdır**: her biri, ihlalinin görüleceği bir olaya ya da duruma çevrilmelidir ve
bu çeviri genellikle tek bir gereksinimi birkaç gereksinime böler.

Ayrımın karar karşılığı nettir. Üç gereksinim için yapılacak iş bir alan doldurmaktır; dört
gereksinim için yapılacak iş bir tasarım tartışmasıdır. Onarımdan sonra liste 16 otomatik ve 4
sınanamaz gereksinime ayrılır — ve bu dört gereksinim, ne kadar denetim kurulursa kurulsun kod
aşamasında hiçbir uyarı üretmez.

Bir uyarı burada gereklidir: sınanabilirlik **doğruluk değildir**. Oturum süresi sınırının otuz
dakika yazılmış olması onu otomatik sınanabilir yapar, ama otuz dakikanın doğru sayı olduğunu
göstermez; yanlış bir eşik de kusursuz biçimde sınanır. Bu sınıflandırma gereksinimin denetime
uygun olup olmadığını ölçer, isabetli olup olmadığını değil. İkisinin karıştırılması yaygın bir
kusur üretir: eşik, sınanabilir olsun diye yazılır ve sayının nereden geldiği hiç tartışılmaz.

#### Kötüye Kullanım Senaryosunun Kattığı

Yukarıdaki yirmi gereksinim özellik listesi okunarak yazılmıştır: sistemin **yapması** gereken
işlerden türetilmiştir. **Kötüye kullanım senaryosu** (misuse case) ters yönden başlar — bir aktör,
sistemin engellemesi gereken bir hedefi izler ve bu hedefin engellenmesi için hangi gereksinimlerin
gerektiği yazılır.

```js
// kosum2.mjs — kotuye kullanim senaryolari listeyi ne kadar buyutuyor, ne bicimde
import { GEREKSINIM, YENI, SENARYO, sinif } from './gereksinim.mjs';

const mevcut = new Set(GEREKSINIM.map((g) => g.ad));
console.log('senaryo                        aktor           gereksinim  listede  yeni');
let ref = 0, varOlan = 0;
for (const [ad, aktor, uretilen] of SENARYO) {
  const v = uretilen.filter((x) => mevcut.has(x)).length;
  ref += uretilen.length; varOlan += v;
  console.log(ad.padEnd(31) + aktor.padEnd(16) + String(uretilen.length).padEnd(12) +
    String(v).padEnd(9) + (uretilen.length - v));
}
console.log(`${SENARYO.length} senaryo, ${ref} gereksinim referansi, ${varOlan} listede, ` +
  `${ref - varOlan} yeni; liste %${(((ref - varOlan) / GEREKSINIM.length) * 100).toFixed(0)} buyuyor`);

const say = (l, s) => l.filter((g) => sinif(g) === s).length;
const kip = (l, k) => l.filter((g) => g.kip === k).length;
console.log('\nkume                 gereksinim  otomatik  gozle  sinanamaz  engeller  engeller %');
for (const [ad, l] of [['ozellik listesinden', GEREKSINIM], ['senaryolardan', YENI]])
  console.log(ad.padEnd(21) + String(l.length).padEnd(12) + String(say(l, 'otomatik')).padEnd(10) +
    String(say(l, 'gozle')).padEnd(7) + String(say(l, 'sinanamaz')).padEnd(11) +
    String(kip(l, 'engeller')).padEnd(10) + ((kip(l, 'engeller') / l.length) * 100).toFixed(0));

// Sinanabilirlik sinifi, gereksinimin hangi asamada sinandigini ve bedelini belirler.
const DAGITIM = 60, DEGISIKLIK = 420, GOZLE_DK = 8;
console.log('\nsinif       sinandigi asama  kosum sayisi  insan dakikasi');
const tum = [...GEREKSINIM, ...YENI];
for (const [s, asama, kosum, dk] of [['otomatik', 'kod', DEGISIKLIK, 0],
  ['gozle', 'dagitim', DAGITIM, GOZLE_DK], ['sinanamaz', 'calisma-zamani', 0, 0]])
  console.log(s.padEnd(12) + asama.padEnd(17) + String(say(tum, s) * kosum).padEnd(14) +
    say(tum, s) * kosum * dk);
const gozleDk = say(tum, 'gozle') * DAGITIM * GOZLE_DK;
console.log(`\n${tum.length} gereksinimin ${say(tum, 'otomatik')}'i kod asamasinda, ` +
  `${say(tum, 'gozle')}'i dagitim asamasinda sinaniyor, ${say(tum, 'sinanamaz')}'u hic sinanmiyor`);
console.log(`gozle sinamanin yillik yaklasigi ${gozleDk} dakika (${(gozleDk / 60).toFixed(1)} saat); ` +
  `eksik parcalar yazilirsa ${(gozleDk / 60).toFixed(1)} saatin tamami dusuyor`);
```

```
senaryo                        aktor           gereksinim  listede  yeni
abone-hesabini-ele-gecirme     dis-aktor       4           3        1
baskasinin-faturasini-okuma    yetkili-abone   2           1        1
olcum-kaydini-degistirme       saha-personeli  3           1        2
toplu-abone-verisi-cekme       yetkili-abone   3           1        2
cihazi-baskasi-adina-kaydetme  dis-aktor       2           0        2
5 senaryo, 14 gereksinim referansi, 6 listede, 8 yeni; liste %40 buyuyor

kume                 gereksinim  otomatik  gozle  sinanamaz  engeller  engeller %
ozellik listesinden  20          13        3      4          9         45
senaryolardan        8           6         2      0          7         88

sinif       sinandigi asama  kosum sayisi  insan dakikasi
otomatik    kod              7980          0
gozle       dagitim          300           2400
sinanamaz   calisma-zamani   0             0

28 gereksinimin 19'i kod asamasinda, 5'i dagitim asamasinda sinaniyor, 4'u hic sinanmiyor
gozle sinamanin yillik yaklasigi 2400 dakika (40.0 saat); eksik parcalar yazilirsa 40.0 saatin tamami dusuyor
```

Beş senaryo on dört gereksinime dokunuyor; altısı listede zaten var, **sekizi yeni**. Liste yüzde
kırk büyüyor ve büyümenin nerede yoğunlaştığı önemlidir: son senaryonun ürettiği iki gereksinimin
**ikisi de** yeni. Cihaz kaydı özellik listesinde bir işlevdir ve o işlevin gereksinimleri
yazılmıştır; kaydın **başkası adına** yapılabilmesi bir işlev değildir, bu yüzden hiçbir özellik
satırından türemez.

Burada bir terim ayrımı gerekir. Bir **senaryo**, sistemin desteklediği bir kullanımı adım adım
yazar ve o kullanımın doğru sonuç vermesini ister. Kötüye kullanım senaryosu aynı biçimi kullanır
ama sahibi sistemin karşı tarafındadır ve istediği sonuç sistemin **vermemesi** gereken sonuçtur.
İkinci tablo farkı sayıya çeviriyor: özellik listesinden gelen yirmi gereksinimin yüzde 45'i
engelleyici kiptedir, senaryolardan gelen sekiz gereksinimin yüzde 88'i. Bir gereksinim listesinde
engelleyici kipin payı düşükse eksik olan güvenlik dikkati değil, **kaynaktır**.

Senaryolardan gelen sekiz gereksinimin altısı doğrudan otomatik sınanabilir yazılmıştır. Bunun
nedeni yazanın daha dikkatli olması değil, sorunun biçimidir: engellenecek bir hedef zaten bir
gözlem, bir eşik ve bir kapsam ister. "Cihaz kaydı saha onayına bağlıdır" cümlesi hem ihlalin
görüleceği olayı hem eşiği taşır; "arayüz güvenli olmalıdır" taşımaz.

Tablonun ölçmediği bir şey var ve bu dersin sınırı orasıdır: **beş senaryonun nereden geldiği.**
Senaryolar birinin aklına geldiği için listededir. Altıncı bir senaryo yazılsaydı listeye kaç
gereksinim daha eklenirdi sorusunun bu tabloda yanıtı yoktur, çünkü senaryo kümesinin kendisi
sistematik bir yöntemle üretilmemiştir. Ölçülen şey senaryo **başına** kazançtır, kapsanan hedef
oranı değildir; ikisi karıştırıldığında beş senaryo yazmış bir ekip işini bitirmiş sayar.

#### Sınanabilirliğin Aşama Karşılığı

Son tablo bu kursun ölçü eksenine bağlanıyor. Yirmi sekiz gereksinimin on dokuzu otomatik
sınanabilir olduğu için **kod aşamasında** sınanır ve yılda 7.980 koşum üretir; bu koşumların insan
maliyeti sıfırdır. Beş gereksinim yalnız gözle denetlenebildiği için sınanma noktası **dağıtım
aşamasına** kayar: yılda 300 denetim, 2.400 dakika, yani 40 saat.

İki sayı yan yana okunmalıdır. Otomatik sınanan gereksinim, doğduğu aşamadan sonraki ilk fırsatta
ve her değişiklikte sınanır; ihlali kod aşamasında yakalanır. Gözle sınanan gereksinim ancak bir
dağıtım hazırlanırken bakılır ve ihlali önceki dersin tablosunda üç aşama geç yakalanan kalem
olarak görünür. Sınanabilirlik bir yazım niteliği gibi durur ama sonucu doğrudan **yakalama
aşamasıdır**.

Dört sınanamaz gereksinim üçüncü satırdadır ve hiçbir koşum üretmez. Bunlar sistemde yok sayılmaz;
yalnız ihlalleri bir denetim tarafından değil, bir olay tarafından bildirilir. Önceki dersin
diliyle: bu dört gereksinim, hiçbir denetimin görmediği kalem sınıfının gereksinim aşamasındaki
kaynağıdır. Bir gereksinim listesinin güvenlik değeri, kaç satır içerdiğiyle değil, kaç satırının
bir koşum sayısına karşılık geldiğiyle ölçülür; bu listede oran yirmi sekizde on dokuzdur.

#### Özet

- Otomatik sınanabilirlik üç parçadan türer: gözlenebilir yüklem, eşik, kapsam. Üçünden biri
  eksikse gereksinim gözle denetlenir, yüklem nitelse hiç sınanamaz.
- 20 gereksinimin 13'ü otomatik, 3'ü gözle, 4'ü sınanamazdır. Gözle denetlenen 3'ü tek bir alan
  eklenerek otomatiğe geçer; sınanamaz 4'ü yeniden yazılmadan sınıf değiştiremez.
- 5 kötüye kullanım senaryosu 14 gereksinime dokunur, 6'sı listede vardır, 8'i yenidir; liste yüzde
  40 büyür ve tamamen yeni olan senaryo, özellik listesinde bir işlev karşılığı olmayan senaryodur.
- Özellik listesinden gelen gereksinimlerin yüzde 45'i engelleyici kiptedir, senaryolardan gelenin
  yüzde 88'i; engelleyici kipin düşük payı yazarın dikkatini değil listenin kaynağını gösterir.
- 28 gereksinimin 19'u kod aşamasında yılda 7.980 kez sıfır insan maliyetiyle sınanır; 5'i dağıtım
  aşamasında 300 denetimde 40 saat tüketir, 4'ü hiç sınanmaz.
- Eksik parçalar yazıldığında gözle sınamanın 40 saatlik yükünün tamamı düşer; sınanamaz dört
  gereksinim ise hiçbir denetimde uyarı üretmemeye devam eder.

#### Sonraki Adım

Bu ders gereksinimin nasıl yazılacağını ölçtü ve iki iş çıkardı: üç gereksinime eksik alan
yazmak, dört gereksinimi yeniden düşünmek. İkisi de birinin yapması gereken işlerdir ve o birinin
kim olduğu hiç sorulmadı. Eksik eşiği yazacak kişi, kötüye kullanım senaryosunu yürütecek kişi ve
tasarım oturumunda gözlenemez bir yüklemi fark edecek kişi aynı kişi değildir; beş ekibin hepsinde
de bulunmaz. Önceki iki ders denetimleri aşamalara dağıttı, bu ders gereksinimleri sınanabilir
biçime çevirdi — ama her ikisi de yapacak **yetkinliğin** her ekipte hazır bulunduğunu varsaydı.
Sonraki ders o varsayımı ölçer: kaç ekip var, kaçında güvenlik gözü olan biri var, bir kişinin
kapasitesi kaç ekibe yetiyor ve kapasite yetmediğinde kaç inceleme güvenlik gözü olmadan geçiyor.

### Güvenlik Şampiyonları

Source: https://academia.sh/tr/kurslar/guvenli-yasam-dongusu/guvenlik-sampiyonlari

Beş ekibin haftalık 35 incelemesi üzerinde güvenlik yetkinliğinin dağılımı ölçülür: merkezî ekip tek başına 16 incelemeyi kapsar ve 19'u güvenlik gözü olmadan geçer, dört şampiyonla kapsam doyar. Bir şampiyon ortalama 0,86 ekibe yeter ve her ekipte bir şampiyon olsa bile haftada 6 inceleme merkeze kalır; beşinci şampiyon eklendiğinde uzmanlık isteyen kalemlerin yakalanması 2'den 1'e düşer, çünkü merkez o incelemeleri artık görmez.

Önceki üç ders sırasıyla denetimleri aşamalara dağıttı, aşama başına maliyeti hesapladı ve
gereksinimleri sınanabilir biçime çevirdi. Üçü de bir kişiyi çağırdı ama adını hiç koymadı:
tasarım oturumunda gözlenemez bir yüklemi fark eden, statik çözümlemenin doksan uyarısından altı
gerçek kalemi ayıran, kötüye kullanım senaryosunu yürüten kişi. Bu kişinin her ekipte hazır
bulunduğu varsayıldı.

Bu ders o varsayımı ölçer. **Güvenlik şampiyonu** (security champion), kendi ekibinin içinde
çalışan ve zamanının bir bölümünü güvenlik incelemesine ayıran bir geliştiricidir; merkezî bir
güvenlik ekibinin alternatifi değil, kapasitesinin uzantısıdır. Ölçülecek üç şey vardır: kaç
incelemede güvenlik gözü var, kaçı bekliyor ve bir şampiyonun kapasitesi kaç ekibe yetiyor.

- **DY17.** Ekipler, geliştirici sayıları ve haftalık inceleme sayıları kurgusaldır; toplam
  inceleme yükü önceki derslerin değişiklik akışıyla uyumludur.
- **DY18.** Bir şampiyon yalnız **kendi ekibinin** incelemesine bakar; bağlam bilgisi
  aktarılamayan bir kaynaktır. Merkezî uzman herhangi bir ekibe bakabilir ve kapasitesi ortak
  havuzdadır.
- **DY19.** Kalem zorluğu üç düzeydir: 1 kontrol listesiyle, 2 eğitimli gözle, 3 uzmanlıkla
  görülür. Şampiyon en çok 2. düzeyi yakalar; 3. düzey merkezî uzmanın işidir.
- **DY20.** Bir kalem ancak güvenlik gözü olan bir incelemede yakalanır. Kapsanmayan incelemeden
  geçen kalem, önceki derslerin diliyle geç akışa düşer.
- **DY21.** Eskalasyon oranı, şampiyonun göremediği bir kalemi yine de merkeze ilettiği durumların
  payıdır ve model değeridir. Sıfır olduğunda şampiyon modelinin derinlik tavanı görünür hâle gelir.

#### Kapsanan ve Kapsanmayan İnceleme

Model ekipleri inceleme yüküyle sıralar ve iki kapasite kaynağını ayırır: şampiyonların kendi
ekiplerinde harcadığı zaman ile merkezî ekibin ortak havuzu.

```js
// ekip.mjs — bes ekip, inceleme yuku ve guvenlik yetkinliginin dagilimi (model)
// satir: ekip | gelistirici | haftalik inceleme
export const EKIP = `
  abone-portali    6  10
  sayac-toplama    5   8
  faturalama       4   6
  saha-uygulamasi  4   5
  ortak-kitaplik   3   6`
  .trim().split('\n').map((r) => {
    const [ad, g, i] = r.trim().split(/\s+/);
    return { ad, gelistirici: +g, inceleme: +i };
  });
export const SAMPIYON_PAY = 0.2;   // sampiyonun kendi zamanindan ayirdigi oran
export const SAMPIYON_INCELEME = 6; // bu payla haftada bakabildigi inceleme sayisi
export const MERKEZ_KISI = 2, MERKEZ_INCELEME = 8; // merkezi guvenlik ekibi
// Kalem zorlugu: 1 kontrol listesiyle, 2 egitimli gozle, 3 uzmanlikla gorulur.
// Dagilim onceki derslerin 23 kalemlik kumesi uzerine modellenmistir.
export const ZORLUK = [[1, 11], [2, 7], [3, 5]];
export const SAMPIYON_DERINLIK = 2; // sampiyonun yakalayabildigi en yuksek zorluk
export const TOPLAM_INCELEME = EKIP.reduce((s, e) => s + e.inceleme, 0);
export const TOPLAM_GELISTIRICI = EKIP.reduce((s, e) => s + e.gelistirici, 0);
```

```js
// kosum1.mjs — sampiyon sayisi arttikca guvenlik gozu olan inceleme ve bekleyen inceleme
import { EKIP, SAMPIYON_PAY, SAMPIYON_INCELEME, MERKEZ_KISI, MERKEZ_INCELEME,
  TOPLAM_INCELEME, TOPLAM_GELISTIRICI } from './ekip.mjs';

const merkez = MERKEZ_KISI * MERKEZ_INCELEME;
// Sampiyon yalniz kendi ekibinin incelemesine bakar; merkez havuzdan herhangi bir ekibe.
const sirali = [...EKIP].sort((a, b) => b.inceleme - a.inceleme);
console.log(`${EKIP.length} ekip, ${TOPLAM_GELISTIRICI} gelistirici, ` +
  `${TOPLAM_INCELEME} inceleme/hafta; merkez ${merkez} inceleme/hafta`);
console.log('\nsampiyon  sampiyon kapsami  merkez kullanilan  bosta merkez  kapsanan  bekleyen  kisi-esdeger');
for (let s = 0; s <= EKIP.length; s++) {
  const kaps = sirali.slice(0, s).reduce((a, e) => a + Math.min(e.inceleme, SAMPIYON_INCELEME), 0);
  const kalan = TOPLAM_INCELEME - kaps, kullanilan = Math.min(kalan, merkez);
  const esdeger = (s * SAMPIYON_PAY + MERKEZ_KISI).toFixed(1);
  console.log(String(s).padEnd(10) + String(kaps).padEnd(18) + String(kullanilan).padEnd(19) +
    String(merkez - kullanilan).padEnd(14) + String(kaps + kullanilan).padEnd(10) +
    String(kalan - kullanilan).padEnd(10) + esdeger);
}

console.log('\nbir sampiyon kendi ekibine yetiyor mu');
console.log('ekip             inceleme  sampiyon kapasitesi  acik  merkeze kalan %');
for (const e of sirali)
  console.log(e.ad.padEnd(17) + String(e.inceleme).padEnd(10) +
    String(SAMPIYON_INCELEME).padEnd(21) +
    String(Math.max(0, e.inceleme - SAMPIYON_INCELEME)).padEnd(6) +
    ((Math.max(0, e.inceleme - SAMPIYON_INCELEME) / e.inceleme) * 100).toFixed(0));
const acik = sirali.reduce((a, e) => a + Math.max(0, e.inceleme - SAMPIYON_INCELEME), 0);
console.log(`her ekipte bir sampiyon olsa bile ${acik} inceleme/hafta merkeze kalir; ` +
  `bir sampiyon ortalama ${(SAMPIYON_INCELEME / (TOPLAM_INCELEME / EKIP.length)).toFixed(2)} ekibe yeter`);
```

```
5 ekip, 22 gelistirici, 35 inceleme/hafta; merkez 16 inceleme/hafta

sampiyon  sampiyon kapsami  merkez kullanilan  bosta merkez  kapsanan  bekleyen  kisi-esdeger
0         0                 16                 0             16        19        2.0
1         6                 16                 0             22        13        2.2
2         12                16                 0             28        7         2.4
3         18                16                 0             34        1         2.6
4         24                11                 5             35        0         2.8
5         29                6                  10            35        0         3.0

bir sampiyon kendi ekibine yetiyor mu
ekip             inceleme  sampiyon kapasitesi  acik  merkeze kalan %
abone-portali    10        6                    4     40
sayac-toplama    8         6                    2     25
faturalama       6         6                    0     0
ortak-kitaplik   6         6                    0     0
saha-uygulamasi  5         6                    0     0
her ekipte bir sampiyon olsa bile 6 inceleme/hafta merkeze kalir; bir sampiyon ortalama 0.86 ekibe yeter
```

Sıfırıncı satır başlangıç durumunu veriyor: iki kişilik merkezî ekip haftada 16 incelemeye
bakabiliyor, 19 inceleme güvenlik gözü olmadan geçiyor. Kapsanan oran yüzde 46'dır ve bu sayı
merkezî ekibin çalışkanlığıyla ilgili değildir — 35 incelemeye 16 kapasite ayrılmıştır.

Şampiyon eklendikçe kapsanan sayı 16'dan 22'ye, 28'e, 34'e çıkıyor ve **dördüncü şampiyonda
doyuyor**. Beşinci şampiyon kapsanan sayıyı hiç değiştirmiyor; yalnız merkezin boşta kalan
kapasitesini 5'ten 10'a çıkarıyor. Kişi eşdeğeri sütunu bedeli veriyor: dört şampiyonla toplam
güvenlik yetkinliği 2,8 tam zamanlı kişiye denk gelir ve bunun 0,8'i yirmi iki geliştiricinin
içinden çıkar. Aynı kapsamı merkezî ekibi büyüterek elde etmek için 35 incelemeye yetecek kadar
uzman gerekirdi; şampiyon modeli, kapsamı yeni kişi almadan doyurmanın yoludur.

#### Bir Şampiyon Kaç Ekibe Yetiyor

İkinci tablo yaygın bir tasarım varsayımını sayıyla yanlışlıyor. "Her ekipte bir şampiyon" cümlesi
kapsamın tamamlandığını ima eder; sayılar öyle demiyor. Bir şampiyonun haftalık kapasitesi altı
inceleme, ortalama ekip yükü yedi incelemedir — yani bir şampiyon ortalama **0,86 ekibe** yeter.

Dağılım ortalamadan daha keskindir. Abone portalı haftada on inceleme üretir; şampiyon altısına
bakar, dördü merkeze kalır ve bu, o ekibin incelemelerinin yüzde 40'ıdır. Sayaç toplama servisinde
oran yüzde 25'tir. Küçük üç ekipte açık sıfırdır ve saha uygulamasında şampiyonun bir incelemelik
boş kapasitesi vardır, ama o kapasite başka bir ekibe aktarılamaz — bağlam taşınmaz.

Sonuç şudur: her ekipte bir şampiyon bulunsa bile haftada altı inceleme merkeze kalır. Şampiyon
sayısı kapsamı **ekip sınırında** doyurur, kurum genelinde doyurmaz; kalan yükü karşılayacak bir
merkezî kapasite her durumda gerekir. Kapasitenin ekip yüküne göre dağıtılmaması durumunda ise en
çok inceleme üreten ekip en çok açığı taşır — tabloyu sıralayan sütun budur.

#### Derinlik Kapsamla Birlikte Büyümüyor

Kapsanan inceleme sayısı yakalanan kalem sayısı demek değildir. Bir incelemede kimin oturduğu,
hangi zorluktaki kalemin görüleceğini belirler.

```js
// kosum2.mjs — kapsam buyurken derinlik ne oluyor: zorluk 3 kalemler kimin gozunden geciyor
import { EKIP, SAMPIYON_INCELEME, MERKEZ_KISI, MERKEZ_INCELEME, ZORLUK,
  SAMPIYON_DERINLIK, TOPLAM_INCELEME } from './ekip.mjs';

const merkez = MERKEZ_KISI * MERKEZ_INCELEME;
const sirali = [...EKIP].sort((a, b) => b.inceleme - a.inceleme);
const sig = ZORLUK.filter(([z]) => z <= SAMPIYON_DERINLIK).reduce((a, [, n]) => a + n, 0);
const derin = ZORLUK.filter(([z]) => z > SAMPIYON_DERINLIK).reduce((a, [, n]) => a + n, 0);
const ESKALASYON = 0.6; // sampiyonun "emin degilim" deyip merkeze ilettigi derin kalem orani

console.log(`${sig + derin} kalem: sampiyonun gorebildigi ${sig}, uzmanlik isteyen ${derin}`);
console.log('\nsampiyon  sampiyon kapsami  merkez kapsami  sig yakalanan  derin yakalanan  eskalasyonla  toplam');
for (let s = 0; s <= EKIP.length; s++) {
  const kaps = sirali.slice(0, s).reduce((a, e) => a + Math.min(e.inceleme, SAMPIYON_INCELEME), 0);
  const mk = Math.min(TOPLAM_INCELEME - kaps, merkez);
  const sy = Math.round((sig * (kaps + mk)) / TOPLAM_INCELEME);
  const dy = Math.round((derin * mk) / TOPLAM_INCELEME);
  const de = Math.round((derin * (mk + ESKALASYON * kaps)) / TOPLAM_INCELEME);
  console.log(String(s).padEnd(10) + String(kaps).padEnd(18) + String(mk).padEnd(16) +
    String(sy).padEnd(15) + String(dy).padEnd(17) + String(de).padEnd(14) + (sy + de));
}
console.log(`\neskalasyonun merkeze getirdigi ek yuk 5 sampiyonda ` +
  `${(derin * ESKALASYON * 29 / TOPLAM_INCELEME).toFixed(1)} kalem; ` +
  `merkezin bosta kapasitesi ${merkez - 6} inceleme/hafta`);
```

```
23 kalem: sampiyonun gorebildigi 18, uzmanlik isteyen 5

sampiyon  sampiyon kapsami  merkez kapsami  sig yakalanan  derin yakalanan  eskalasyonla  toplam
0         0                 16              8              2                2             10
1         6                 16              11             2                3             14
2         12                16              14             2                3             17
3         18                16              17             2                4             21
4         24                11              18             2                4             22
5         29                6               18             1                3             21

eskalasyonun merkeze getirdigi ek yuk 5 sampiyonda 2.5 kalem; merkezin bosta kapasitesi 10 inceleme/hafta
```

Sığ kalem sütunu beklendiği gibi davranıyor: sekizden on sekize çıkıyor ve dördüncü şampiyonda
tamamlanıyor. Derin kalem sütunu davranmıyor. Merkezî ekip tek başına iki derin kalem yakalıyor ve
bu sayı şampiyon sayısı dörde çıkana kadar **hiç değişmiyor**; beşinci şampiyonda **bire düşüyor**.

Düşüşün nedeni tabloda yan sütunda duruyor. Şampiyonlar 29 incelemeyi kapsadığında merkeze yalnız 6
inceleme kalır; merkezin baktığı inceleme sayısı azaldıkça uzmanlık isteyen kalemleri görme
olasılığı da azalır. Şampiyon o incelemelerde oturmaktadır ama derin kalemi görecek düzeyde
değildir. **Kapsamı büyüten karar, derinliği küçültmüştür.** Toplam sütunu bunu tek sayıyla veriyor:
en iyi sonuç dört şampiyonda 22 kalem, beş şampiyonda 21 kalemdir.

Son sütun karşı önlemi ölçüyor. Şampiyonun göremediği bir kalemi yine de merkeze iletebildiği bir
**eskalasyon yolu** varsa derin kalem sayısı beş şampiyonda 1'den 3'e çıkar. Bunun bedeli merkeze
gelen 2,5 kalemlik ek yüktür ve merkezin haftada 10 incelemelik boş kapasitesi bunu karşılar.
Şampiyon modelinin işe yaraması yetkinliğin dağıtılmasına değil, **yetersizliğin bildirilebilmesine**
bağlıdır: "emin değilim" diyebilen bir şampiyon, emin olmaya çalışan bir şampiyondan daha çok kalem
yakalatır.

Bir sınırlama yazılmalıdır. Model, şampiyonun derinlik tavanını sabit tutuyor; gerçekte tavan
eğitimle yükselir ve bu ölçümün dışındadır. Ölçülen şey belirli bir tavanla kapsamın nasıl
davrandığıdır; eğitimin katkısı ayrı bir karardır ve kendi bedeli vardır.

#### Kapsanmayan İnceleme Ne Oluyor

Kapsanmayan bir incelemenin akıbeti kapasite sorusu değil, kural sorusudur. Güvenlik incelemesi
zorunluysa kapsanmayan değişiklik bekler; zorunlu değilse geçer ve taşıdığı kalem kaçar.

```js
// kosum3.mjs — kapsanmayan inceleme iki ayri kurala baglanabilir: bloklayan ve bloklamayan
import { EKIP, SAMPIYON_INCELEME, MERKEZ_KISI, MERKEZ_INCELEME, ZORLUK,
  SAMPIYON_DERINLIK, TOPLAM_INCELEME } from './ekip.mjs';

const HAFTA = 12, merkez = MERKEZ_KISI * MERKEZ_INCELEME;
const sirali = [...EKIP].sort((a, b) => b.inceleme - a.inceleme);
const sig = ZORLUK.filter(([z]) => z <= SAMPIYON_DERINLIK).reduce((a, [, n]) => a + n, 0);
const derin = ZORLUK.filter(([z]) => z > SAMPIYON_DERINLIK).reduce((a, [, n]) => a + n, 0);

console.log('           acik      bloklayan kural            bloklamayan kural');
console.log('sampiyon  /hafta  bekleyen degisiklik  kacan  bekleyen  kacan kalem');
for (let s = 0; s <= EKIP.length; s++) {
  const kaps = sirali.slice(0, s).reduce((a, e) => a + Math.min(e.inceleme, SAMPIYON_INCELEME), 0);
  const mk = Math.min(TOPLAM_INCELEME - kaps, merkez), acik = TOPLAM_INCELEME - kaps - mk;
  const yakalanan = Math.round((sig * (kaps + mk)) / TOPLAM_INCELEME) +
    Math.round((derin * (mk + 0.6 * kaps)) / TOPLAM_INCELEME);
  console.log(String(s).padEnd(10) + String(acik).padEnd(8) + String(acik * HAFTA).padEnd(21) +
    '0'.padEnd(7) + '0'.padEnd(10) + (sig + derin - yakalanan));
}
console.log('\nbloklayan kuralda hicbir kalem kacmaz, 12 haftada 228 degisiklige kadar beklenir;');
console.log('bloklamayan kuralda hicbir degisiklik beklemez, 13 kaleme kadar gozsuz gecer.');
```

```
           acik      bloklayan kural            bloklamayan kural
sampiyon  /hafta  bekleyen degisiklik  kacan  bekleyen  kacan kalem
0         19      228                  0      0         13
1         13      156                  0      0         9
2         7       84                   0      0         6
3         1       12                   0      0         2
4         0       0                    0      0         1
5         0       0                    0      0         2

bloklayan kuralda hicbir kalem kacmaz, 12 haftada 228 degisiklige kadar beklenir;
bloklamayan kuralda hicbir degisiklik beklemez, 13 kaleme kadar gozsuz gecer.
```

Aynı açık sayısı iki bambaşka sonuç veriyor. Yetkinlik hiç dağıtılmamışken bloklayan kural on iki
haftada **228 değişikliği** bekletir ve hiçbir kalem kaçırmaz; bloklamayan kural hiçbir değişikliği
bekletmez ve **13 kalem** güvenlik gözü görmeden geçer. İlk dersin kapı tablosuyla aynı takas
buradadır, ama bu kez bekletmenin nedeni kapının kapasitesi değil, **inceleyecek yetkinliğin
bulunmamasıdır**.

Kararın yönü şampiyon sayısına bağlıdır. Sıfır ve bir şampiyonda bloklayan kural işletilemez —
biriken 228 ve 156 değişiklik ekipleri durdurur, kural birkaç hafta içinde bir istisna listesine
dönüşür ve fiilen bloklamayan kurala iner. Üçüncü şampiyondan sonra açık haftada bir incelemeye
düşer; on iki haftada 12 değişiklik bekler ve bloklayan kural artık taşınabilir hâle gelir.
**Bloklayan bir kural yetkinlik dağıtılmadan yazılamaz**; yazılırsa uygulanmaz ve uygulanmayan bir
kural, kapsandığı sanılan incelemeleri de kapsamsız bırakır.

Son satır önceki tablonun bulgusunu bir kez daha gösteriyor. Beşinci şampiyonda açık sıfırdır,
bekleyen değişiklik sıfırdır ve her şey kapsanmış görünür; buna rağmen kaçan kalem sayısı dört
şampiyondaki 1'den **2'ye çıkar**. Kapsam sütununa bakan bir ölçüm bu artışı hiç görmez.

#### Özet

- 5 ekip haftada 35 inceleme üretiyor; iki kişilik merkezî ekip 16'sını kapsıyor ve 19 inceleme
  güvenlik gözü olmadan geçiyor.
- Şampiyon eklendikçe kapsanan inceleme 16'dan 34'e çıkar ve dördüncü şampiyonda 35'e doyar;
  beşinci şampiyon kapsamı değiştirmez, yalnız merkezin boş kapasitesini 5'ten 10'a çıkarır.
- Bir şampiyonun kapasitesi 6 inceleme, ortalama ekip yükü 7 incelemedir: bir şampiyon 0,86 ekibe
  yeter. Her ekipte bir şampiyon olsa bile haftada 6 inceleme merkeze kalır ve bunun 4'ü tek bir
  ekipten gelir.
- Dört şampiyonlu düzenin bedeli 2,8 kişi eşdeğeridir ve 0,8'i mevcut 22 geliştiricinin içinden
  çıkar; kapsam yeni kişi alınmadan doyar. Kapsanmayan inceleme için bloklayan kural 12 haftada 228
  değişikliği bekletir ve hiç kalem kaçırmaz, bloklamayan kural hiç bekletmez ve 13 kalem kaçırır;
  bloklayan kural ancak üçüncü şampiyondan sonra taşınabilir hâle gelir.
- Uzmanlık isteyen 5 kalemin yakalanması şampiyon sayısıyla artmaz: dört şampiyona kadar 2'de
  sabit kalır, beşinci şampiyonda 1'e düşer, çünkü merkez o incelemeleri artık görmez.
- Eskalasyon yolu derin kalem sayısını beş şampiyonda 1'den 3'e çıkarır; bedeli merkeze gelen 2,5
  kalemlik ek yüktür ve merkezin 10 incelemelik boş kapasitesi bunu karşılar.

#### Sonraki Adım

Bu ders yetkinliğin nereye konacağını ölçtü ve dört şampiyonlu bir düzende 23 kalemin 22'sinin
yakalandığını buldu. Yakalanmak bir kalemi kapatmaz. Önceki derslerin hepsi bulunan kalemin
düzeltildiğini varsaydı; sola kaydırmanın 250 saatlik kazancı bile o varsayımın üstünde duruyordu
ve orada bir üst sınır olduğu yazılmıştı. Bulunan kalemi düzeltecek olan aynı yirmi iki
geliştiricidir ve onların zamanı özellik işiyle paylaşılır. Sonraki ders sınırlı geliştirme
kapasitesini kalem kümesine dağıtır: bir sprint kapasitesi kaç kalem alıyor, birim kapasite başına
kaç kalem kapanıyor, sıralama ölçütü değiştiğinde kaç kalem dışarıda kalıyor ve dışarıda kalanların
kümesi ölçüt değiştiğinde ne kadar değişiyor.

### Risk Temelli Önceliklendirme

Source: https://academia.sh/tr/kurslar/guvenli-yasam-dongusu/risk-temelli-onceliklendirme

23 kalemlik yığın 68 geliştirici-gün efor ve 667 saat ertelenmiş bedel taşır; 22 günlük sprint kapasitesi dört farklı sıralama ölçütüne verilir. Doğuş sırası 6 kalem kapatırken efor sırası aynı bütçeyle 13 kalem kapatır ve birim başına önlenen saat 10,95'ten 17,10'a çıkar. Yığının yalnız 2 kalemi her ölçütte içeride, 5'i her ölçütte dışarıdadır; kalan 16 kalemin kaderini ölçüt seçimi belirler.

Önceki dört ders yakalamayı ölçtü: denetimler aşamalara dağıtıldı, aşama başına maliyet
hesaplandı, gereksinimler sınanabilir biçime çevrildi ve yetkinlik ekiplere yayıldı. Dördü de aynı
yerde durdu — bulunan kalemin **düzeltildiğini** varsaydılar. Sola kaydırmanın 250 saatlik kazancı
o varsayımın üstünde duruyordu ve orada bir üst sınır olduğu açıkça yazılmıştı.

Bu ders varsayımı kaldırır. Düzeltmeyi yapacak olan aynı yirmi iki geliştiricidir ve zamanları
özellik işiyle paylaşılır. Yığın kapasiteden büyük olduğunda soru "hangi kalem önce" hâline gelir
ve bu soru bir sıralama ölçütü ister. Ders dört ölçütü aynı bütçede koşturur, birim kapasite başına
kapanan kalemi karşılaştırır ve son olarak hangi ölçüt seçilirse seçilsin dışarıda kalan kümeyi
ayırır.

Bir noktayı baştan ayırmak gerekir: buradaki sıralama bir **risk** sıralaması değildir. Risk
sıralaması gerçekleşmemiş bir olayla çalışır ve bir olasılık terimi taşır. Bu yığındaki kalemler
zaten yakalanmıştır; bulunmuş bir kalemin var olma olasılığı yoktur, yalnız ertelenme bedeli
vardır. Ölçütlerin hiçbirinde olasılık terimi geçmez.

- **DY22.** Kalem kümesi önceki derslerle aynıdır. Eklenen iki alan düzeltme eforu ve ertelenmiş
  bedeldir.
- **DY23.** Düzeltme eforu **kurgu geliştirici-gün** cinsindendir ve model değeridir. Ertelenmiş
  bedel türetilir: kalem şimdi kapatılmazsa çalışma zamanına kadar taşınır ve aradaki geri alma
  farkını öder.
- **DY24.** Sprint kapasitesi, ekiplerin güvenlik işine ayırdığı toplam geliştirici-gündür; bir
  kalem ya tamamen kapatılır ya hiç açılmaz, yarım kapanma yoktur.
- **DY25.** Bütçe ölçüt sırasına göre harcanır ve sığmayan kalem atlanır, sıra orada durmaz. Bu
  kural küçük eforlu kalemlerin lehine çalışır ve etkisi tabloda görünür.
- **DY26.** Ölçütlerin hiçbiri olasılık ya da etki terimi taşımaz. Sıralamalar yalnız doğuş
  aşaması, ertelenmiş bedel ve efor üzerinden kurulur.

#### Kapasite ve Ertelenmiş Bedel

Model iki yeni sayı taşır: bir kalemi kapatmanın kaç geliştirici-gün tuttuğu ve kapatılmadığında
çalışma zamanına kadar taşınmanın kaç saat ekleyeceği. İkincisi verilmez, önceki dersin geri alma
bedelinden türetilir.

```js
// kapasite.mjs — ayni 23 kalem, artik duzeltme eforu ve ertelemenin kat bedeliyle (model)
export const YENIDEN = [0, 3, 8, 2, 6, 24], TEMEL = 2;
export const bedel = (d, y) => TEMEL + YENIDEN.slice(d + 1, y + 1).reduce((s, x) => s + x, 0);
// satir: ad | dogus asamasi | gorunurluk | duzeltme eforu (kurgu gelistirici-gun)
export const KALEM = `
  veri-siniflandirmasi-yok      0 100000 5
  saklama-suresi-tanimsiz       0 100001 3
  kisisel-veri-kapsami-belirsiz 0 100010 4
  kimlik-dogrulamasiz-ic-cagri  1 011110 6
  zayif-oturum-modeli           1 010011 4
  guven-sinirsiz-veri-akisi     1 010000 7
  yetki-modelinde-eksik-rol     1 011001 5
  eksik-yetki-denetimi          2 001101 2
  gomulu-gizli-anahtar          2 001110 3
  dogrulanmamis-girdi           2 001001 2
  gunluge-yazilan-kisisel-veri  2 001001 1
  yarim-kalan-hata-yolu         2 001000 1
  zayif-rastgelelik             2 001000 2
  sinirsiz-sorgu-boyu           2 000001 4
  guncel-olmayan-bagimlilik     3 000110 1
  imzasiz-yapi-ciktisi          3 000110 3
  gereksiz-yapi-araci           3 000100 1
  varsayilan-parola             4 000011 1
  asiri-genis-ag-kurali         4 000011 2
  sifresiz-yedek                4 000010 2
  acik-yonetim-ucu              4 000011 1
  olcek-altinda-yaris           5 000001 6
  ucuncu-tarafta-aciklanan-acik 5 000001 2`
  .trim().split('\n').map((r) => {
    const [ad, d, g, e] = r.trim().split(/\s+/);
    const dogus = +d, yakalanan = [...g].findIndex((c, i) => i >= dogus && c === '1');
    // Ertelemenin bedeli: kalem simdi kapatilmazsa calisma zamanina kadar tasinir.
    return { ad, dogus, yakalanan, efor: +e, onlenen: bedel(dogus, 5) - bedel(dogus, yakalanan) };
  });
export const SPRINT = 22; // sprint basina guvenlik isine ayrilan gelistirici-gun
export const TOPLAM_EFOR = KALEM.reduce((s, k) => s + k.efor, 0);
export const TOPLAM_ONLENEN = KALEM.reduce((s, k) => s + k.onlenen, 0);
// Sira olcutleri: hicbiri olasilik icermez, kalem zaten yakalanmistir.
export const OLCUT = {
  'dogus-once': (a, b) => a.dogus - b.dogus || a.efor - b.efor,
  'kat-buyuk': (a, b) => b.onlenen - a.onlenen || a.efor - b.efor,
  'efor-kucuk': (a, b) => a.efor - b.efor || b.onlenen - a.onlenen,
  'birim-basina': (a, b) => b.onlenen / b.efor - a.onlenen / a.efor,
};
export function dagit(ad, butce) {
  const alinan = [];
  let h = 0;
  for (const k of [...KALEM].sort(OLCUT[ad])) if (h + k.efor <= butce) { alinan.push(k); h += k.efor; }
  return { alinan, h, kapanan: alinan.length,
    onlenen: alinan.reduce((s, k) => s + k.onlenen, 0),
    disarida: KALEM.filter((k) => !alinan.includes(k)) };
}
```

```js
// kosum1.mjs — ayni sprint kapasitesi dort siralama olcutune veriliyor
import { KALEM, SPRINT, TOPLAM_EFOR, TOPLAM_ONLENEN, OLCUT, dagit } from './kapasite.mjs';

console.log(`${KALEM.length} kalem, ${TOPLAM_EFOR} gelistirici-gun efor, ` +
  `${TOPLAM_ONLENEN} saat ertelenmis bedel; sprint kapasitesi ${SPRINT} gun ` +
  `(yigin ${(TOPLAM_EFOR / SPRINT).toFixed(1)} sprint)`);
console.log('\nolcut          kapanan  harcanan  onlenen saat  gun basina kalem  gun basina saat  disarida');
for (const ad of Object.keys(OLCUT)) {
  const r = dagit(ad, SPRINT);
  console.log(ad.padEnd(15) + String(r.kapanan).padEnd(9) + String(r.h).padEnd(10) +
    String(r.onlenen).padEnd(14) + (r.kapanan / r.h).toFixed(2).padEnd(18) +
    (r.onlenen / r.h).toFixed(2).padEnd(17) + r.disarida.length);
}

console.log('\nkapasite buyudukce kapanan kalem (olcut basina)');
console.log('kapasite  ' + Object.keys(OLCUT).map((a) => a.padEnd(14)).join(''));
for (const b of [11, 22, 33, 44, 68])
  console.log(String(b).padEnd(10) +
    Object.keys(OLCUT).map((a) => {
      const r = dagit(a, b);
      return `${r.kapanan} kalem`.padEnd(14);
    }).join(''));
```

```
23 kalem, 68 gelistirici-gun efor, 667 saat ertelenmis bedel; sprint kapasitesi 22 gun (yigin 3.1 sprint)

olcut          kapanan  harcanan  onlenen saat  gun basina kalem  gun basina saat  disarida
dogus-once     6        22        241           0.27              10.95            17
kat-buyuk      6        22        241           0.27              10.95            17
efor-kucuk     13       21        359           0.62              17.10            10
birim-basina   13       22        391           0.59              17.77            10

kapasite buyudukce kapanan kalem (olcut basina)
kapasite  dogus-once    kat-buyuk     efor-kucuk    birim-basina  
11        3 kalem       3 kalem       8 kalem       8 kalem       
22        6 kalem       6 kalem       13 kalem      13 kalem      
33        10 kalem      10 kalem      16 kalem      16 kalem      
44        14 kalem      14 kalem      19 kalem      18 kalem      
68        23 kalem      23 kalem      23 kalem      23 kalem      
```

İlk satır ölçeği veriyor: 23 kalem 68 geliştirici-gün ister, sprint kapasitesi 22 gündür, yani
yığın 3,1 sprint tutar. Bu, kapasitenin yetersiz olduğu anlamına gelmez; sıralamanın **üç sprint
boyunca** anlamlı olduğu anlamına gelir.

İlk iki satırın aynı olması bir tesadüf değildir ve okunması gerekir. Ertelenmiş bedel yalnız
doğuş aşamasından türetilir; bu yüzden "en çok kat" sıralaması, doğuş sıralamasının yeniden
adlandırılmış hâlidir ve **bağımsız bir bilgi taşımaz**. Aynı ölçüyü iki farklı adla sıralayan bir
program iki seçenek arasında karar verdiğini sanır, oysa tek seçeneği vardır.

Bağımsız bilgi eforda duruyor ve farkı o üretiyor. Aynı 22 günle doğuş sıralaması **6 kalem**, efor
sıralaması **13 kalem** kapatır; birim başına önlenen saat 10,95'ten 17,10'a çıkar. İki katına
yakın bir fark, tek bir sütun değiştirilerek elde ediliyor ve ek kapasite gerektirmiyor.

Alt tablo bunun her bütçede sürdüğünü gösteriyor, ama bir yerde tersine dönüyor: 44 günde efor
sıralaması 19, birim başına sıralaması 18 kalem kapatıyor. Oran sıralaması yüksek oranlı ama büyük
eforlu bir kalemi erken alır ve o kalem sonradan iki küçük kalemin yerini kaplar. **Birim başına en
iyi olan sıra, kalem sayısı için en iyi sıra değildir**; hangisinin istendiği önceden söylenmelidir.
Altmış sekiz günde dört ölçüt de aynı yere varır — sıralama yalnız kapasite kıtken bir karardır.

#### Üç Sprint Boyunca Taşınan Bedel

Tek sprintlik bakış eksiktir, çünkü yığın üç sprintte kapanır. Asıl ölçü, ertelenmiş bedelin kaç
sprint boyunca açık kaldığıdır: her sprint sonunda kapanmamış kalemlerin taşıdığı saat toplanır.

```js
// kosum3.mjs — uc sprint boyunca tasinan ertelenmis bedel: siralama neyi hizlandiriyor
import { KALEM, SPRINT, TOPLAM_ONLENEN, OLCUT } from './kapasite.mjs';

console.log('olcut          sprint 1 kalan  sprint 2 kalan  sprint 3 kalan  3 sprintte tasinan');
for (const ad of Object.keys(OLCUT)) {
  const kalan = [...KALEM].sort(OLCUT[ad]);
  const izi = [];
  let tasinan = 0;
  for (let s = 0; s < 3; s++) {
    let h = 0;
    for (const k of [...kalan]) if (h + k.efor <= SPRINT) { h += k.efor; kalan.splice(kalan.indexOf(k), 1); }
    const acik = kalan.reduce((a, k) => a + k.onlenen, 0);
    izi.push(acik); tasinan += acik;
  }
  console.log(ad.padEnd(15) + izi.map((x) => String(x).padEnd(16)).join('') + tasinan);
}
console.log(`\nyigin toplami ${TOPLAM_ONLENEN} saat; tasinan sayi, ertelenmis bedelin ` +
  'kac sprint boyunca acik kaldigini olcer');
```

```
olcut          sprint 1 kalan  sprint 2 kalan  sprint 3 kalan  3 sprintte tasinan
dogus-once     426             158             0               584
kat-buyuk      426             158             0               584
efor-kucuk     308             163             40              511
birim-basina   276             80              0               356

yigin toplami 667 saat; tasinan sayi, ertelenmis bedelin kac sprint boyunca acik kaldigini olcer
```

Üç ölçüt yığını üç sprintte kapatıyor, biri kapatmıyor. Efor sıralaması ilk sprintte en çok kalemi
kapatan ölçüttü, ama üçüncü sprint sonunda hâlâ **40 saatlik** açık taşıyor: küçük kalemleri öne
aldığı için büyük eforlu kalemler her sprintte kalan bütçeye sığmadan sona atılıyor. Bir sıralamanın
ilk sprint başarısı, yığını bitirip bitirmediğini söylemez.

Taşınan sütun ölçütler arasındaki farkı tek sayıya indiriyor. Doğuş sıralaması üç sprint boyunca
**584 saat-sprint** açık taşıyor, birim başına sıralaması **356**. Aradaki fark yüzde 39'dur ve
hiçbir ek kapasite harcanmadan elde edilir; yalnız aynı işlerin sırası değişmiştir. İlk sprintte
kalan bedel de aynı yönü gösteriyor: 426 saate karşı 276 saat.

#### Sıralama Kimin Kaderini Belirliyor

Kapanan kalem sayısı ölçütün değerini verir ama asıl soru şudur: ölçüt değiştiğinde **kimler**
dışarıda kalır. İki ölçüt aynı sayıda kalem bırakabilir ve tamamen farklı kalemler bırakabilir.

```js
// kosum2.mjs — siralama degisince disarida kalan kume ne kadar degisiyor
import { KALEM, SPRINT, OLCUT, dagit } from './kapasite.mjs';

const adlar = Object.keys(OLCUT);
const disarida = new Map(adlar.map((a) => [a, new Set(dagit(a, SPRINT).disarida)]));
console.log('olcut ciftleri arasinda disarida kalan kumenin ortak kalemi (sprint 22 gun)');
console.log('           ' + adlar.map((a) => a.padEnd(14)).join(''));
for (const a of adlar)
  console.log(a.padEnd(15) + adlar.map((b) => {
    const ortak = [...disarida.get(a)].filter((k) => disarida.get(b).has(k)).length;
    return String(ortak).padEnd(14);
  }).join(''));

const hep = KALEM.filter((k) => adlar.every((a) => disarida.get(a).has(k)));
const hic = KALEM.filter((k) => adlar.every((a) => !disarida.get(a).has(k)));
const degisken = KALEM.length - hep.length - hic.length;
console.log(`\n${KALEM.length} kalem: her olcutte icerde ${hic.length}, her olcutte disarida ` +
  `${hep.length}, olcute gore yer degistiren ${degisken}`);
console.log(`her olcutte disarida kalanin ertelenmis bedeli ` +
  `${hep.reduce((s, k) => s + k.onlenen, 0)} saat, kapatma eforu ` +
  `${hep.reduce((s, k) => s + k.efor, 0)} gun`);

console.log('\nher olcutte disarida kalan kalemler');
console.log('kalem                          efor  onlenen saat  saat/gun');
for (const k of [...hep].sort((a, b) => b.onlenen / b.efor - a.onlenen / a.efor))
  console.log(k.ad.padEnd(31) + String(k.efor).padEnd(6) + String(k.onlenen).padEnd(14) +
    (k.onlenen / k.efor).toFixed(1));
```

```
olcut ciftleri arasinda disarida kalan kumenin ortak kalemi (sprint 22 gun)
           dogus-once    kat-buyuk     efor-kucuk    birim-basina  
dogus-once     17            17            6             6             
kat-buyuk      17            17            6             6             
efor-kucuk     6             6             10            9             
birim-basina   6             6             9             10            

23 kalem: her olcutte icerde 2, her olcutte disarida 5, olcute gore yer degistiren 16
her olcutte disarida kalanin ertelenmis bedeli 110 saat, kapatma eforu 26 gun

her olcutte disarida kalan kalemler
kalem                          efor  onlenen saat  saat/gun
imzasiz-yapi-ciktisi           3     30            10.0
kimlik-dogrulamasiz-ic-cagri   6     40            6.7
guven-sinirsiz-veri-akisi      7     40            5.7
sinirsiz-sorgu-boyu            4     0             0.0
olcek-altinda-yaris            6     0             0.0
```

Kesişim tablosu bu dersin en sert sayısını taşıyor. Doğuş sıralamasının dışarıda bıraktığı 17
kalemle efor sıralamasının bıraktığı 10 kalemin **yalnız 6'sı ortaktır**. İki program aynı yığına
bakıyor, aynı bütçeyi harcıyor ve büyük ölçüde farklı kalemleri erteliyor.

Alt satır bunu tek cümlede topluyor: 23 kalemin **2'si** her ölçütte içeride, **5'i** her ölçütte
dışarıda, **16'sı** ölçüte göre yer değiştiriyor. Yığının yüzde 70'inin kaderini kalemlerin kendi
nitelikleri değil, sıralama ölçütünün seçimi belirliyor. Bir güvenlik programının en belirleyici
kararı, bu yüzden, hangi kalemin önemli olduğuna karar vermek değil, **hangi sütunla sıralandığını
yazmaktır**; yazılmadığında karar yine verilir, yalnız kimsenin görmediği bir yerde verilir.

#### Her Ölçütte Dışarıda Kalan

Son liste ölçüt seçiminden bağımsız olan artığı gösteriyor: beş kalem, 110 saat ertelenmiş bedel,
26 günlük kapatma eforu. Bu beş kalem iki ayrı nedenle dışarıdadır ve ikisi ayrı karar gerektirir.

Üçü büyük eforludur. Güven sınırı çizilmemiş veri akışını düzeltmek yedi gün, kimlik doğrulaması
olmayan iç çağrıyı düzeltmek altı gün ister; ikisi de kırkar saat önler, ama saat başına oranları
listenin ortasında kalır ve 22 günlük bir bütçeye hiçbir sıralamayla giremezler. Bunların doğru
karşılığı sıralamayı zorlamak değil, **eforu bölmektir**: yedi günlük tek bir kalem üç günlük iki
adıma ayrılabiliyorsa listeye girer, ayrılamıyorsa ayrı bir bütçe ister. Bir sprint kapasitesiyle
ölçülen bir yığın, bölünmeyen büyük eforlu kalemleri yapısal olarak dışarıda tutar.

Kalan ikisi farklıdır ve önlenen saatleri sıfırdır. Ölçek altında ortaya çıkan yarış ile sınırsız
sorgu boyu, ikinci derste ayrılan sınıftır: erken doğar, yalnız çalışma zamanında görünür. Bunlar
sıralamada sona düşmez, sıralamaya **hiç girmez**, çünkü erken kapatmak hiçbir şey önlemez. Bu iki
kalem için doğru karar önceliklendirme değildir; bunları çalışma zamanında ucuza görmenin yolunu
kurmaktır ve o iş bu bütçenin dışındadır. Bir yığın listesinde sıfır değerli satırların ayrı
tutulmaması, sıralamanın kendisini bozar.

#### Özet

- 23 kalemlik yığın 68 geliştirici-gün efor ve 667 saat ertelenmiş bedel taşır; 22 günlük sprint
  kapasitesiyle yığın 3,1 sprint tutar ve sıralama üç sprint boyunca karar üretir.
- Doğuş sırasıyla en çok kat sırası aynı sonucu verir, çünkü ertelenmiş bedel yalnız doğuş
  aşamasından türer; iki ad tek bir ölçüttür.
- Aynı 22 günle doğuş sıralaması 6, efor sıralaması 13 kalem kapatır; birim başına önlenen saat
  10,95'ten 17,10'a çıkar ve bunun için ek kapasite gerekmez.
- Birim başına en iyi sıra kalem sayısı için en iyi sıra değildir: 44 günde efor sıralaması 19,
  oran sıralaması 18 kalem kapatır. Üç sprint boyunca taşınan bedel doğuş sıralamasında 584, birim
  başına sıralamasında 356 saat-sprinttir ve efor sıralaması, ilk sprintte en iyi olmasına karşın
  üçüncü sprint sonunda 40 saatlik açık bırakır.
- 23 kalemin 2'si her ölçütte içeride, 5'i her ölçütte dışarıda, 16'sı ölçüte göre yer değiştirir;
  yığının yüzde 70'inin kaderini ölçüt seçimi belirler.
- Her ölçütte dışarıda kalan 5 kalem 110 saat taşır: üçü büyük eforludur ve bölünmedikçe
  giremez, ikisinin önlenen saati sıfırdır ve sıralamaya hiç girmemeleri gerekir.

#### Sonraki Adım

Bu konu güvenliği bir aşama olmaktan çıkarıp her aşamada farklı fiyatı olan bir karara çevirdi.
Kapının kuyruğu sayıldı, aşama başına düzeltme maliyeti geri alınan işten türetildi, gereksinimler
sınanabilirlik sınıflarına ayrıldı, yetkinliğin kapsamı ve derinliği ölçüldü ve son olarak sınırlı
kapasite dört ayrı ölçütle dağıtıldı. Bütün bu ölçümlerin girdisi tek bir şeydi: **elimizde
yakalanmış bir kalem kümesi olduğu.** Yirmi üç kalem baştan verildi ve nereden geldiği hiç
sorulmadı.

Kazancın en büyük payını taşıyan aşamalar tasarım ve gereksinimdi — önlenen saatin yarıdan fazlası
oradan geliyordu. Ama bir tasarım oturumunda hangi kalemin bulunacağı, bulanın gözüne
bırakılamayacak kadar belirleyicidir. Üçüncü derste beş kötüye kullanım senaryosunun nereden
geldiğinin ölçülmediği yazılmıştı; dördüncü derste şampiyonun görebildiği zorluk düzeyi bir tavan
olarak duruyordu. İkisi de aynı boşluğu gösteriyor: **tasarım aşamasında hangi kalemin doğduğunu
sistematik olarak bulmanın kendi yöntemi vardır ve o yöntem hiç anlatılmadı.** Sonraki konu
**Tehdit Modelleme** o yöntemi kurar: sistemin veri akışı bir çizge olarak yazılır, güven sınırını
geçen akışlar sayılır, çizge ögelerine sistematik bir sınıflandırma uygulanarak tehdit üretilir ve
üretilenlerin kaçının anlamlı olduğu, kaçının karşı önleme dönüştüğü ölçülür.

## Tehdit Modelleme

Tasarım aşamasında hangi kalemin bulunabildiğinin ve bulmanın kaç saate mal olduğunun ölçülmesi: tehdit modelleme oturumunun süresi ve kalem başına saati, veri akış çizgesinde güven sınırını geçen akışların sayılması, sınır çizilmediğinde görünmez kalan akışlar, sistematik tehdit üretiminin verdiği ham tehdit sayısı ile bunların anlamlı olan payı, eleme süresi, senaryo temelli modellemenin kapsaması ve sistematik yöntemle kesişimi, saldırı ağacında en ucuz yolun maliyeti ve bir düğümü kapatmanın kök maliyeti kaç kat artırdığı, model çıktısının kaçının iş öğesine dönüştüğü ve artık riskin yazılı kabulü.

### Tehdit Modellemenin Amacı

Source: https://academia.sh/tr/kurslar/guvenli-yasam-dongusu/tehdit-modellemenin-amaci

Tehdit modelleme oturumunun kendi ölçüsü: 18 kalemlik envanterde oturumun 40 geliştirici saati sürüp 10 kalem bulması, kalem başına 4,0 saate karşılık 866 saat kurtarması, aynı kalemin geç yakalandığında 4 ile 30 kat arasında değişen bir maliyet farkı üretmesi, toplam düzeltme saatinin 1.872'den 1.006'ya inmesi ve oturumun hiç dokunmadığı sekiz kalemin toplam saatin %48,4'ünü taşıması.

Önceki konu güvenlik işini aşamalara dağıttı, gereksinimi sınanabilir biçimde yazdı ve sınırlı
geliştirme kapasitesinin nasıl bölüneceğini sordu. Bütün o hesapların ortak girdisi hazır bir
kalem listesiydi: hangi açığın var olduğu biliniyordu, tartışılan yalnız sırasıydı. Oysa tasarım
aşamasında böyle bir liste kendiliğinden ortaya çıkmaz.

**Tehdit modelleme**, o listeyi tasarım aşamasında üretmenin yöntemidir. Bu ders yöntemin
adımlarını değil, **amacını ve fiyatını** ölçer: oturum kaç saat sürer, kaç kalem bulur, kalem
başına kaç saat harcar ve bulduğu kalem geç yakalansaydı kaç kat pahalıya gelirdi. Konu boyunca
aynı kurgu bölgesel ölçüm ağının yazılımı üzerinde çalışılır.

#### Oturum Nerede Durur

Aşağıdaki envanter bir **modeldir**: gerçek bir ürün, gerçek bir ekip ölçümü ya da gerçek bir
kayıt yoktur. Kalemler yalnız üç sütunla anılır — nerede doğdukları, nerede görülebildikleri ve
düzeltmelerinin kaç geliştirici saati tuttuğu. Hiçbir istismar adımı yazılmaz.

**TD1:** düzeltme işi geliştirici saati olarak ölçülür; taban saat kalemin tasarım aşamasındaki
karşılığıdır ve sonraki aşamalarda bir çarpanla büyür. **TD2:** her kalemin doğduğu aşama ile
**görülebildiği** aşama ayrı şeylerdir; kodda doğan bir kalem yalnız çalışma zamanında
görülebilir olabilir. **TD3:** oturum tasarım aşamasında koşar ve yalnız görülür aşaması
tasarımdan geç olmayan kalemleri bulur. **TD4:** oturumun bedeli katılımcı sayısı ile süresinin
çarpımıdır.

```js
// tehdit/kalem.mjs — asama kumesi ve kalem envanteri (model): kurgu bolgesel olcum agi
// yaziliminin gelistirme kayitlarindan turetilmistir, gercek bir olcum degildir. Hicbir
// istismar adimi yoktur; kalem yalnizca nerede dogdugu, nerede gorulebildigi ve
// duzeltmesinin kac gelistirici saati oldugu ile yazilir.

export const ASAMA = ["gereksinim", "tasarim", "kod", "yapi", "dagitim", "calisma-zamani"];

// TD1: duzeltme isi gelistirici saati olarak olculur. `taban`, kalemin tasarim asamasinda
// duzeltilmesinin saatidir; sonraki asamalarda asagidaki carpanla buyur.
export const CARPAN = { gereksinim: 1, tasarim: 1, kod: 4, yapi: 6, dagitim: 12,
  "calisma-zamani": 30 };

// TD2: satirlar "ad dogus gorulur varsayilan taban" biciminde yazilir. `dogus` kalemin
// uretildigi, `gorulur` en erken gorulebildigi, `varsayilan` tehdit modelleme oturumu
// olmadiginda fiilen yakalandigi asamadir.
export const KALEM = `
  guven-siniri-cizilmemis          tasarim     tasarim         dagitim          6
  sayac-kimligi-dogrulanmiyor      tasarim     tasarim         calisma-zamani   8
  fatura-kaydi-degistirilebilir    tasarim     tasarim         dagitim         10
  abone-verisi-korumasiz-akiyor    tasarim     tasarim         dagitim          4
  yetki-karari-istemcide           tasarim     tasarim         kod              7
  denetim-gunlugu-eksik            gereksinim  tasarim         calisma-zamani   5
  saha-cihazi-sir-tasiyor          tasarim     tasarim         dagitim          9
  rapor-ucu-kimliksiz              tasarim     tasarim         kod              3
  olcum-yedegi-korumasiz           tasarim     tasarim         calisma-zamani   6
  oturum-suresi-tanimsiz           gereksinim  tasarim         kod              2
  girdi-uzunlugu-sinirsiz          kod         kod             yapi             2
  sorgu-birlestirmesi-elle         kod         kod             yapi             4
  zamanlama-farki-sizdiriyor       kod         kod             calisma-zamani   5
  eszamanli-istek-yaris-kosulu     kod         calisma-zamani  calisma-zamani  12
  bagimlilik-surumu-sabitlenmemis  yapi        yapi            dagitim          3
  imaj-icinde-artik-arac           yapi        yapi            dagitim          2
  varsayilan-kimlik-bilgisi-acik   dagitim     dagitim         calisma-zamani   4
  gunluk-kaydinda-kimlik-bilgisi   kod         calisma-zamani  calisma-zamani   6`
  .trim().split("\n").map((r) => {
    const [ad, dogus, gorulur, varsayilan, taban] = r.trim().split(/\s+/);
    return { ad, dogus, gorulur, varsayilan, taban: +taban };
  });

export const sira = (a) => ASAMA.indexOf(a);
export const maliyet = (k, asama) => k.taban * CARPAN[asama];

// TD3: tehdit modelleme oturumu tasarim asamasinda kosar ve yalnizca `gorulur` asamasi
// tasarimdan gec olmayan kalemleri bulur; kalanlarina hic dokunmaz.
export const bulunur = (k) => sira(k.gorulur) <= sira("tasarim");

// TD4: oturumun bedeli katilimci sayisi x oturum sayisi x oturum suresidir.
export const OTURUM = { katilimci: 5, sayi: 4, saat: 2 };
export const OTURUM_SAAT = OTURUM.katilimci * OTURUM.sayi * OTURUM.saat;
```

```js
// tehdit/oturum.mjs — oturum kac saat suruyor, kac kalem buluyor, kalem basina kac saat
// ve ayni kalem gec yakalandiginda maliyeti kac kat.
import { ASAMA, CARPAN, KALEM, OTURUM, OTURUM_SAAT, sira, maliyet, bulunur } from "./kalem.mjs";

const yaz = (g, ...s) => console.log(s.map((v, i) =>
  (g[i] < 0 ? String(v).padEnd(-g[i]) : String(v).padStart(g[i]))).join(""));
const topla = (ks, f) => ks.reduce((s, k) => s + f(k), 0);
const bulunan = KALEM.filter(bulunur), kacan = KALEM.filter((k) => !bulunur(k));

console.log(`${KALEM.length} kalem, ${ASAMA.length} asama; carpanlar ` +
  `${ASAMA.map((a) => `${a} x${CARPAN[a]}`).join(", ")}`);

const A = [-33, -12, -16, -16, 9, 11, 14, 6];
console.log("\n1. kalem nerede doguyor, nerede gorulebiliyor, nerede yakalaniyor");
yaz(A, "kalem", "dogus", "gorulur", "varsayilan", "gecikme", "tasarimda", "varsayilanda", "kat");
for (const k of KALEM) {
  const t = maliyet(k, "tasarim"), v = maliyet(k, k.varsayilan);
  yaz(A, k.ad, k.dogus, k.gorulur, k.varsayilan,
    sira(k.varsayilan) - sira(k.dogus), t, v, (v / t).toFixed(1));
}

const B = [-16, 8, 10, 17, 9, 9];
console.log("\n2. gorulur asamasina gore kalem sinifi");
yaz(B, "gorulur asama", "kalem", "kalem %", "varsayilan saat", "saat %", "oturum");
for (const a of ASAMA) {
  const g = KALEM.filter((k) => k.gorulur === a);
  if (!g.length) continue;
  const s = topla(g, (k) => maliyet(k, k.varsayilan));
  yaz(B, a, g.length, ((g.length / KALEM.length) * 100).toFixed(1), s,
    ((s / topla(KALEM, (k) => maliyet(k, k.varsayilan))) * 100).toFixed(1),
    sira(a) <= sira("tasarim") ? "bulur" : "bulmaz");
}

const OTURUMSUZ = topla(KALEM, (k) => maliyet(k, k.varsayilan));
const OTURUMLU = topla(bulunan, (k) => maliyet(k, "tasarim")) +
  topla(kacan, (k) => maliyet(k, k.varsayilan)) + OTURUM_SAAT;
const C = [-34, 14, 22];
console.log("\n3. oturumun kendi olcusu");
for (const [ad, x, y] of [
  ["oturum sayisi x katilimci x saat", `${OTURUM.sayi}x${OTURUM.katilimci}x${OTURUM.saat}`,
    OTURUM_SAAT + " saat"],
  ["bulunan kalem", bulunan.length, (OTURUM_SAAT / bulunan.length).toFixed(1) + " saat/kalem"],
  ["dokunulmayan kalem", kacan.length, ((kacan.length / KALEM.length) * 100).toFixed(1) + " %"],
  ["oturumsuz toplam duzeltme", OTURUMSUZ + " saat", "-"],
  ["oturumlu toplam duzeltme", OTURUMLU + " saat", (OTURUMSUZ / OTURUMLU).toFixed(2) + " kat"],
  ["oturumun kurtardigi saat", OTURUMSUZ - OTURUMLU + " saat",
    ((OTURUMSUZ - OTURUMLU) / OTURUM_SAAT).toFixed(1) + " x oturum saati"],
]) yaz(C, ad, x, y);

const D = [-22, 8, 16, 15, 8];
console.log("\n4. oturumun degdigi ve degmedigi kalemler ayri ayri");
yaz(D, "kume", "kalem", "oturumsuz saat", "oturumlu saat", "kat");
for (const [ad, ks, saat] of [
  ["oturumun buldugu", bulunan, topla(bulunan, (k) => maliyet(k, "tasarim"))],
  ["oturumun bulmadigi", kacan, topla(kacan, (k) => maliyet(k, k.varsayilan))],
]) {
  const o = topla(ks, (k) => maliyet(k, k.varsayilan));
  yaz(D, ad, ks.length, o, saat, (o / saat).toFixed(1));
}
const enGec = [...KALEM].sort((x, y) =>
  maliyet(y, y.varsayilan) - maliyet(x, x.varsayilan))[0];
console.log(`en pahali tek kalem ${enGec.ad}: ${maliyet(enGec, enGec.varsayilan)} saat, ` +
  `oturum bunu ${bulunur(enGec) ? "bulur" : "bulmaz"}; oturumun bulmadigi ` +
  `${kacan.length} kalem toplam duzeltme saatinin ` +
  `%${((topla(kacan, (k) => maliyet(k, k.varsayilan)) / OTURUMSUZ) * 100).toFixed(1)}'ini tasiyor`);
```

```
18 kalem, 6 asama; carpanlar gereksinim x1, tasarim x1, kod x4, yapi x6, dagitim x12, calisma-zamani x30

1. kalem nerede doguyor, nerede gorulebiliyor, nerede yakalaniyor
kalem                            dogus       gorulur         varsayilan        gecikme  tasarimda  varsayilanda   kat
guven-siniri-cizilmemis          tasarim     tasarim         dagitim                 3          6            72  12.0
sayac-kimligi-dogrulanmiyor      tasarim     tasarim         calisma-zamani          4          8           240  30.0
fatura-kaydi-degistirilebilir    tasarim     tasarim         dagitim                 3         10           120  12.0
abone-verisi-korumasiz-akiyor    tasarim     tasarim         dagitim                 3          4            48  12.0
yetki-karari-istemcide           tasarim     tasarim         kod                     1          7            28   4.0
denetim-gunlugu-eksik            gereksinim  tasarim         calisma-zamani          5          5           150  30.0
saha-cihazi-sir-tasiyor          tasarim     tasarim         dagitim                 3          9           108  12.0
rapor-ucu-kimliksiz              tasarim     tasarim         kod                     1          3            12   4.0
olcum-yedegi-korumasiz           tasarim     tasarim         calisma-zamani          4          6           180  30.0
oturum-suresi-tanimsiz           gereksinim  tasarim         kod                     2          2             8   4.0
girdi-uzunlugu-sinirsiz          kod         kod             yapi                    1          2            12   6.0
sorgu-birlestirmesi-elle         kod         kod             yapi                    1          4            24   6.0
zamanlama-farki-sizdiriyor       kod         kod             calisma-zamani          3          5           150  30.0
eszamanli-istek-yaris-kosulu     kod         calisma-zamani  calisma-zamani          3         12           360  30.0
bagimlilik-surumu-sabitlenmemis  yapi        yapi            dagitim                 1          3            36  12.0
imaj-icinde-artik-arac           yapi        yapi            dagitim                 1          2            24  12.0
varsayilan-kimlik-bilgisi-acik   dagitim     dagitim         calisma-zamani          1          4           120  30.0
gunluk-kaydinda-kimlik-bilgisi   kod         calisma-zamani  calisma-zamani          3          6           180  30.0

2. gorulur asamasina gore kalem sinifi
gorulur asama      kalem   kalem %  varsayilan saat   saat %   oturum
tasarim               10      55.6              966     51.6    bulur
kod                    3      16.7              186      9.9   bulmaz
yapi                   2      11.1               60      3.2   bulmaz
dagitim                1       5.6              120      6.4   bulmaz
calisma-zamani         2      11.1              540     28.8   bulmaz

3. oturumun kendi olcusu
oturum sayisi x katilimci x saat           4x5x2               40 saat
bulunan kalem                                 10        4.0 saat/kalem
dokunulmayan kalem                             8                44.4 %
oturumsuz toplam duzeltme              1872 saat                     -
oturumlu toplam duzeltme               1006 saat              1.86 kat
oturumun kurtardigi saat                866 saat   21.6 x oturum saati

4. oturumun degdigi ve degmedigi kalemler ayri ayri
kume                     kalem  oturumsuz saat  oturumlu saat     kat
oturumun buldugu            10             966             60    16.1
oturumun bulmadigi           8             906            906     1.0
en pahali tek kalem eszamanli-istek-yaris-kosulu: 360 saat, oturum bunu bulmaz; oturumun bulmadigi 8 kalem toplam duzeltme saatinin %48.4'ini tasiyor
```

Sayılar **ölçüm** sınıfındadır; girdileri TD1–TD4'tür.

#### Kırk Saatlik Oturum

Üçüncü tablo bu dersin ana sorusunu yanıtlar. Dört oturum, beş katılımcı, oturum başına iki saat:
toplam **40 geliştirici saati**. Oturum on kalem bulur, yani **kalem başına 4,0 saat**. Bu sayı
tehdit modellemeyi bir yöntem olarak değil, bir **iş kalemi** olarak yazar; onay isteyen bir ekip
için tartışılabilir olan tek biçim budur.

Karşılığı aynı satırda durur. Oturum olmasaydı on sekiz kalemin toplam düzeltme işi **1.872
saat** olurdu; oturumla birlikte 1.006 saate iner. Fark 866 saattir ve harcanan 40 saatin
**21,6 katıdır**. Bu oranın büyüklüğü tek bir şeyden gelir: oturumun bulduğu kalemler zaten geç
aşamada yakalanacak kalemlerdi ve geç aşamanın çarpanı yüksekti.

Toplam üzerinden bakıldığında ise kazanç çok daha ölçülüdür: 1.872 saat 1.006 saate iner, yani
**1,86 kat**. Aynı ölçüm iki farklı büyüklük verir ve ikisi de doğrudur. Oturumun değdiği kalemler
için oran 16,1'dir; bütün envanter için 1,86. Hangi sayının yazıldığı, oturumun neyi kapsadığının
açıkça söylenip söylenmediğine bağlıdır.

#### Aynı Kalem, Üç Aşama Sonra

Birinci tablonun son sütunu her kalem için tek soruyu yanıtlar: aynı kalem varsayılan aşamasında
yakalandığında tasarımdakinin kaç katına mal olur. Değerler **4,0 ile 30,0 arasında** dağılır ve
bu aralık dersin en önemli bulgusudur — "geç yakalamak pahalıdır" cümlesi tek bir kat sayısı
taşımaz, kalemin nereye kadar gidebildiğine bağlı bir dağılım taşır.

Uçları karşılaştırmak yeterlidir. `yetki-karari-istemcide` kodda yakalanır: 7 saat yerine 28 saat,
kat 4,0. `sayac-kimligi-dogrulanmiyor` çalışma zamanına kadar gider: 8 saat yerine **240 saat**,
kat 30,0. İki kalemin taban saati birbirine yakındır; aradaki otuz katlık farkı üreten şey kalemin
kendi büyüklüğü değil, **kaç aşama boyunca görülmeden ilerlediğidir**.

`gecikme` sütunu bunu doğrudan sayar. `denetim-gunlugu-eksik` gereksinim aşamasında doğar ve
çalışma zamanında yakalanır: **beş aşama** geç. Aynı kalemin taban saati yalnız 5'tir; beş aşama
gecikme onu 150 saate çıkarır. Buna karşılık `imaj-icinde-artik-arac` yapı aşamasında doğar ve
dağıtımda yakalanır — bir aşama geç, 2 saat yerine 24. Envanterin en pahalı kalemi olan
`eszamanli-istek-yaris-kosulu` ise üç aşama gecikmeyle 360 saate ulaşır ve tek başına oturumsuz
toplamın yaklaşık beşte birini taşır.

#### Kapsama Tavanı

Birinci tablonun `dogus` sütunu tek başına okunduğunda oturumun üst sınırını verir. Envanterin
2 kalemi gereksinim, 8 kalemi tasarım, 5 kalemi kod, 2 kalemi yapı, 1 kalemi dağıtım aşamasında
doğar. Tasarım aşaması bittiğinde henüz **doğmamış** olan kalem sayısı sekizdir.

Bir kalem doğmadan görülemez; `gorulur` sütunu hiçbir satırda `dogus` sütunundan erken olamaz.
Bu, oturumun kapsamına yapısal bir tavan koyar: **tasarımdan sonra doğan hiçbir kalem tasarım
oturumunda bulunamaz** — o kalem oturum yürütülürken henüz yoktur. Sekiz kalemin dışarıda kalması
oturumun kalitesizliğinden değil, sırasından gelir.

Tavanın altında ise oturumun kendi başarısı ölçülür. Gereksinim ve tasarım aşamasında doğan on
kalemin onunda da `gorulur` sütunu tasarımı gösterir; bu envanterde oturum **tavanın tamamına**
ulaşır. Gerçek bir oturumda bu oran daha düşüktür ve iki sayı ayrı yazılmalıdır: kaç kalem
yapısal olarak bulunabilirdi, bunların kaçı fiilen bulundu. İkisi karıştırıldığında %100 kapsama
bildiren bir ekip, envanterin %44,4'ünü hiç ölçmemiş olur.

İki kalem bu ayrımı doğrudan gösterir. `eszamanli-istek-yaris-kosulu` ve
`gunluk-kaydinda-kimlik-bilgisi` kod aşamasında doğar ama ancak çalışma zamanında görülür;
ikisinin de gecikmesi üç aşamadır. Bunlar ne tasarım oturumunun ne de kodu okuyan bir denetimin
kapsamındadır — doğdukları aşamada bile görünmezler.

#### Tasarımda Görülemeyen Sekiz Kalem

Dördüncü tablo bu dersin sınırını yazar. Oturumun değdiği on kalem 966 saatten 60 saate iner —
16,1 kat. Oturumun **bulmadığı** sekiz kalem ise 906 saatten 906 saate iner; kat **1,0**. Oturum
ne kadar iyi yürütülürse yürütülsün bu sekiz kaleme hiçbir şey yapmaz.

İkinci tablo o sekizin nerede durduğunu ayırır. Üç kalem ancak kodda görülebilir, iki kalem yapıda,
bir kalem dağıtımda, iki kalem yalnız çalışma zamanında. Kalem sayısı olarak envanterin
**%44,4'ü**, düzeltme saati olarak **%48,4'üdür**. Yani tasarım aşamasında yürütülen en eksiksiz
oturum bile toplam işin yarısına yaklaşan bir bölümünü olduğu yerde bırakır.

Bu sınıf rastgele değildir. Yarış koşulu, zamanlama farkı ve günlük kaydına düşen kimlik bilgisi,
tasarımda bir kutu ya da bir ok olarak görünmez; ancak yazılmış kodun ya da koşan sistemin
davranışında ortaya çıkar. Tasarım belgesi bu kalemleri **taşımaz**, dolayısıyla tasarımı okuyan
hiçbir oturum onları bulamaz. Çalışma zamanında görülebilen iki kalem tek başına 540 saat taşır —
oturumun kurtardığı 866 saatin yaklaşık üçte ikisi kadar.

Buradan çıkan karar sadedir: tehdit modelleme oturumu, kendisinden sonra gelen denetimlerin
yerine geçmez. Oturumun kapsama sınırı yazılmadan verilen "tasarımda hepsini yakalarız" cümlesi,
ölçüldüğünde envanterin yarısını dışarıda bırakan bir iddiadır.

#### Özet

- Tehdit modelleme oturumu ölçülebilir bir iş kalemidir: dört oturum, beş katılımcı, iki saat —
  **40 geliştirici saati**, 10 kalem, **kalem başına 4,0 saat**.
- Oturum 866 saat kurtarır; bu, harcanan 40 saatin 21,6 katıdır. Aynı ölçüm bütün envanter
  üzerinden 1,86 kat, yalnız değdiği kalemler üzerinden 16,1 kat verir.
- Aynı kalemin geç yakalanma katı 4,0 ile 30,0 arasında dağılır; katı belirleyen şey kalemin
  büyüklüğü değil, kaç aşama boyunca görülmeden ilerlediğidir.
- Beş aşama geciken 5 saatlik bir kalem 150 saate, bir aşama geciken 2 saatlik bir kalem 24 saate
  çıkar; gecikme sayısı taban saatten daha belirleyicidir.
- Envanterin 8 kalemi tasarımda görülemez ve oturum onlara hiç dokunmaz — kalem sayısının
  %44,4'ü, düzeltme saatinin **%48,4'ü**. Bu kalemler için oturumun katı 1,0'dır.

#### Sonraki Adım

Bu ders oturumun fiyatını ve kapsama sınırını yazdı, ama oturumun **içinde ne yapıldığını** hiç
açmadı. On kalemin nasıl bulunduğu bir kutu olarak kaldı: "tasarım okundu ve kalemler çıktı."

Tasarımı okumak bir yöntem değildir; bir tasarım metni yüzlerce cümle içerir ve hangi cümlenin
güvenlik kalemi doğurduğu belli değildir. Yöntemin ilk adımı, tasarımı **üzerinde sayım
yapılabilir** bir yapıya çevirmektir: hangi bileşen hangi veriyi kimden alıp kime veriyor ve bu
alışverişlerin hangileri bir güven düzeyinden başka bir güven düzeyine geçiyor. Sonraki ders bu
yapıyı kurar ve konunun temel ölçümünü yapar: veri akış çizgesinde **güven sınırını geçen akış
sayısı**, sınırı geçen her akışın taşıdığı kalem ve sınır çizilmediğinde kaç akışın görünmez
kaldığı.

### Veri Akış Diyagramları

Source: https://academia.sh/tr/kurslar/guvenli-yasam-dongusu/veri-akis-diyagramlari

Konunun temel ölçümü: 17 düğüm, 26 akış ve altı güven bölgesinden oluşan çizgede 23 akışın güven sınırını geçmesi, bu geçişlerin akış başına 2,52 olmak üzere toplam 58 kalem doğurması, kalemlerin %58,6'sının düşükten yükseğe geçen akışlardan gelmesi, kaba bir dış/iç çiziminin 23 geçişin yalnız 7'sini ve 58 kalemin yalnız 15'ini görmesi ve görünmez kalan 16 geçişin 43 kalem taşıması.

Önceki ders oturumun fiyatını ve kapsama tavanını yazdı, ama oturumun içinde ne yapıldığını bir
kutu olarak bıraktı. Tasarım metnini okumak bir yöntem değildir: yüzlerce cümlenin hangisinin
güvenlik kalemi doğurduğu belli değildir ve iki kişi aynı metinden iki ayrı liste çıkarır.

Yöntemin ilk adımı tasarımı **üzerinde sayım yapılabilir** bir yapıya çevirmektir. O yapı **veri
akış çizgesidir (data flow diagram)**: hangi bileşen hangi veriyi kimden alıp kime veriyor. Bu
ders çizgeyi kurar ve konunun temel ölçümünü yapar — **güven sınırını geçen akış sayısı**, her
geçişin doğurduğu kalem ve sınır çizilmediğinde kaç akışın görünmez kaldığı.

#### Çizge, Diyagram Değildir

Bir diyagram çizimdir; üzerinde sayım yapılan şey çizim değil, çizimin arkasındaki çizgedir.
Mimari Karar ve Dokümantasyon kursundaki ayrımla söylenirse diyagram bir **görünümdür**, çizge ise
görünümün türetildiği yapıdır. Aynı çizge kutu-ok çizimi olarak da, aşağıdaki gibi satır satır da
yazılabilir; ölçüm ikisinde de aynı sayıyı verir.

Aşağıdaki çizge bir **modeldir**: gerçek bir sistem, gerçek bir ana makine adı ya da gerçek bir
hizmet ucu yoktur. Kurgu bölgesel ölçüm ağının yazılımı ele alınır.

**TD5:** her düğüm bir **güven bölgesine** yerleşir ve bölgenin sayısal bir güven düzeyi vardır.
**TD6:** düğüm üç türden biridir — dış varlık, süreç, veri deposu. **TD7:** her akış bir veri
sınıfı taşır. **TD8:** iki ucunun bölgesi farklı olan akış **güven sınırını (trust boundary)**
geçer; sınırı geçen her akış aşağıdaki dört kuralla kalem doğurur, sınırı geçmeyen akış hiçbir
kalem doğurmaz.

```js
// tehdit/cizge.mjs — kurgu bolgesel olcum agi yaziliminin veri akis cizgesi (model):
// gercek bir sistem, gercek bir ana makine adi ya da gercek bir hizmet ucu yoktur.
// Cizge yalnizca "kim kimden ne aliyor" der; hicbir saldiri adimi tasimaz.

// TD5: her dugum bir guven bolgesine yerlesir ve bolgenin bir guven duzeyi vardir.
export const BOLGE = { internet: 0, saha: 1, "dis-uc": 2, ic: 3, yonetim: 4, veri: 5 };

// TD6: dugum "ad tur bolge" biciminde yazilir; tur dis varlik (D), surec (S) ya da depo (P).
export const DUGUM = Object.fromEntries(`
  abone D internet | denetim-kurumu D internet | sayac-cihazi D saha | saha-ekibi D saha
  abone-portali S dis-uc | toplama-ucu S dis-uc | saha-uygulamasi S saha
  dogrulayici S ic | faturalama S ic | is-emri S ic | rapor-ureteci S ic | kimlik-servisi S ic
  yonetim-konsolu S yonetim | olcum-deposu P veri | fatura-deposu P veri
  kimlik-deposu P veri | denetim-gunlugu P veri`
  .trim().split(/\s*[|\n]\s*/).map((r) => {
    const [ad, tur, bolge] = r.trim().split(/\s+/);
    return [ad, { ad, tur, bolge, duzey: BOLGE[bolge] }];
  }));

// TD7: akis "kaynak hedef sinif" biciminde yazilir; sinif tasinan veri sinifidir.
export const AKIS = `
  abone            abone-portali    kimlik      | abone-portali   kimlik-servisi  kimlik
  kimlik-servisi   kimlik-deposu    kimlik      | abone-portali   faturalama      fatura
  faturalama       fatura-deposu    fatura      | faturalama      abone-portali   fatura
  sayac-cihazi     toplama-ucu      olcum       | toplama-ucu     dogrulayici     olcum
  dogrulayici      olcum-deposu     olcum       | dogrulayici     faturalama      olcum
  saha-ekibi       saha-uygulamasi  kimlik      | saha-uygulamasi is-emri         emir
  is-emri          saha-uygulamasi  emir        | is-emri         olcum-deposu    olcum
  saha-uygulamasi  toplama-ucu      olcum       | yonetim-konsolu dogrulayici     ayar
  yonetim-konsolu  toplama-ucu      ayar        | yonetim-konsolu kimlik-servisi  ayar
  rapor-ureteci    olcum-deposu     olcum       | rapor-ureteci   fatura-deposu   fatura
  denetim-kurumu   rapor-ureteci    kimlik      | rapor-ureteci   denetim-kurumu  fatura
  faturalama       denetim-gunlugu  kayit       | kimlik-servisi  denetim-gunlugu kayit
  is-emri          denetim-gunlugu  kayit       | faturalama      is-emri         emir`
  .trim().split(/\s*[|\n]\s*/).map((r) => {
    const [kaynak, hedef, sinif] = r.trim().split(/\s+/);
    return { kaynak, hedef, sinif, ad: `${kaynak}->${hedef}` };
  });

// TD8: bir akis, iki ucunun bolgesi farkliysa guven sinirini gecer. Sinir gecen her akis
// asagidaki dort kuralla kalem dogurur; sinir gecmeyen akis hicbir kalem dogurmaz.
export function kalemler(a, bolgeAl = (d) => DUGUM[d].bolge, duzeyAl = (d) => DUGUM[d].duzey) {
  if (bolgeAl(a.kaynak) === bolgeAl(a.hedef)) return [];
  const k = [];
  if (duzeyAl(a.kaynak) < duzeyAl(a.hedef)) k.push("girdi-dogrulama", "kaynak-kimligi");
  if (duzeyAl(a.kaynak) > duzeyAl(a.hedef)) k.push("cikti-suzme");
  if (a.sinif === "kimlik" || a.sinif === "fatura") k.push("aktarim-korumasi");
  if (DUGUM[a.hedef].tur === "P") k.push("yetkilendirme");
  return k;
}
```

```js
// tehdit/sinir.mjs — guven sinirini gecen akis sayisi, her gecisin tasidigi kalem ve
// sinir cozunurlugu dustugunde kac akisin gorunmez kaldigi.
import { BOLGE, DUGUM, AKIS, kalemler } from "./cizge.mjs";

const yaz = (g, ...s) => console.log(s.map((v, i) =>
  (g[i] < 0 ? String(v).padEnd(-g[i]) : String(v).padStart(g[i]))).join(""));
const gecen = AKIS.filter((a) => DUGUM[a.kaynak].bolge !== DUGUM[a.hedef].bolge);

console.log(`${Object.keys(DUGUM).length} dugum, ${AKIS.length} akis, ` +
  `${Object.keys(BOLGE).length} guven bolgesi; sinir gecen akis ${gecen.length}, ` +
  `sinir gecmeyen ${AKIS.length - gecen.length}`);

const A = [-12, 8, 12, 8, 7, 12, 13];
console.log("\n1. bolgeler ve icerdikleri");
yaz(A, "bolge", "duzey", "dis varlik", "surec", "depo", "cikan akis", "sinir gecen");
for (const [b, d] of Object.entries(BOLGE)) {
  const ds = Object.values(DUGUM).filter((x) => x.bolge === b);
  const cikan = AKIS.filter((a) => DUGUM[a.kaynak].bolge === b);
  yaz(A, b, d, ds.filter((x) => x.tur === "D").length, ds.filter((x) => x.tur === "S").length,
    ds.filter((x) => x.tur === "P").length, cikan.length,
    cikan.filter((a) => DUGUM[a.hedef].bolge !== b).length);
}

const B = [-33, -9, -9, -50];
console.log("\n2. sinir gecen her akis ve dogurdugu kalem");
yaz(B, "akis", "sinif", "duzey", "dogan kalem");
for (const a of gecen)
  yaz(B, a.ad, a.sinif, `${DUGUM[a.kaynak].duzey}->${DUGUM[a.hedef].duzey}`,
    kalemler(a).join(" "));
const TUM = gecen.flatMap((a) => kalemler(a));
console.log(`sinir gecen ${gecen.length} akis toplam ${TUM.length} kalem doguruyor, ` +
  `akis basina ${(TUM.length / gecen.length).toFixed(2)}`);

const C = [-20, 10, 12, 12];
console.log("\n3. kalem turune gore");
yaz(C, "kalem turu", "sayi", "kalem %", "akis %");
for (const t of [...new Set(TUM)].sort()) {
  const n = TUM.filter((x) => x === t).length;
  yaz(C, t, n, ((n / TUM.length) * 100).toFixed(1), ((n / AKIS.length) * 100).toFixed(1));
}

// Cozunurluk: ayni cizge uc ayri sinir cizimiyle olculur. Kaba cizim yalnizca dis/ic
// ayrimini tanir; sinirsiz cizim butun dugumleri tek bolgede sayar.
const KABA = { internet: "dis", saha: "dis", "dis-uc": "ic", ic: "ic", yonetim: "ic",
  veri: "ic" };
const cizim = {
  "sinir cizilmemis": { b: () => "tek", d: () => 0 },
  "kaba: dis/ic": { b: (x) => KABA[DUGUM[x].bolge],
    d: (x) => (KABA[DUGUM[x].bolge] === "dis" ? 0 : 1) },
  "ayrintili: 6 bolge": { b: (x) => DUGUM[x].bolge, d: (x) => DUGUM[x].duzey },
};
const D = [-20, 12, 12, 13, 12];
console.log("\n4. sinir cozunurlugu dustugunde ne gorunmez kaliyor");
yaz(D, "cizim", "gorulen akis", "gorulen %", "dogan kalem", "kalem %");
const tam = { akis: gecen.length, kalem: TUM.length };
for (const [ad, c] of Object.entries(cizim)) {
  const g = AKIS.filter((a) => c.b(a.kaynak) !== c.b(a.hedef));
  const k = g.flatMap((a) => kalemler(a, c.b, c.d));
  yaz(D, ad, g.length, ((g.length / tam.akis) * 100).toFixed(1), k.length,
    ((k.length / tam.kalem) * 100).toFixed(1));
}
const kaba = cizim["kaba: dis/ic"];
const kabaG = AKIS.filter((a) => kaba.b(a.kaynak) !== kaba.b(a.hedef));
const kacan = gecen.filter((a) => !kabaG.includes(a));
console.log(`kaba cizimde gorunmeyen ${kacan.length} sinir gecisi ` +
  `${kacan.flatMap((a) => kalemler(a)).length} kalem tasiyor; bunlarin ` +
  `${kacan.filter((a) => DUGUM[a.hedef].tur === "P").length} tanesi bir veri deposuna giriyor`);
```

```
17 dugum, 26 akis, 6 guven bolgesi; sinir gecen akis 23, sinir gecmeyen 3

1. bolgeler ve icerdikleri
bolge          duzey  dis varlik   surec   depo  cikan akis  sinir gecen
internet           0           2       0      0           2            2
saha               1           2       1      0           4            3
dis-uc             2           0       2      0           3            3
ic                 3           0       5      0          14           12
yonetim            4           0       1      0           3            3
veri               5           0       0      4           0            0

2. sinir gecen her akis ve dogurdugu kalem
akis                             sinif    duzey    dogan kalem
abone->abone-portali             kimlik   0->2     girdi-dogrulama kaynak-kimligi aktarim-korumasi
abone-portali->kimlik-servisi    kimlik   2->3     girdi-dogrulama kaynak-kimligi aktarim-korumasi
kimlik-servisi->kimlik-deposu    kimlik   3->5     girdi-dogrulama kaynak-kimligi aktarim-korumasi yetkilendirme
abone-portali->faturalama        fatura   2->3     girdi-dogrulama kaynak-kimligi aktarim-korumasi
faturalama->fatura-deposu        fatura   3->5     girdi-dogrulama kaynak-kimligi aktarim-korumasi yetkilendirme
faturalama->abone-portali        fatura   3->2     cikti-suzme aktarim-korumasi
sayac-cihazi->toplama-ucu        olcum    1->2     girdi-dogrulama kaynak-kimligi
toplama-ucu->dogrulayici         olcum    2->3     girdi-dogrulama kaynak-kimligi
dogrulayici->olcum-deposu        olcum    3->5     girdi-dogrulama kaynak-kimligi yetkilendirme
saha-uygulamasi->is-emri         emir     1->3     girdi-dogrulama kaynak-kimligi
is-emri->saha-uygulamasi         emir     3->1     cikti-suzme
is-emri->olcum-deposu            olcum    3->5     girdi-dogrulama kaynak-kimligi yetkilendirme
saha-uygulamasi->toplama-ucu     olcum    1->2     girdi-dogrulama kaynak-kimligi
yonetim-konsolu->dogrulayici     ayar     4->3     cikti-suzme
yonetim-konsolu->toplama-ucu     ayar     4->2     cikti-suzme
yonetim-konsolu->kimlik-servisi  ayar     4->3     cikti-suzme
rapor-ureteci->olcum-deposu      olcum    3->5     girdi-dogrulama kaynak-kimligi yetkilendirme
rapor-ureteci->fatura-deposu     fatura   3->5     girdi-dogrulama kaynak-kimligi aktarim-korumasi yetkilendirme
denetim-kurumu->rapor-ureteci    kimlik   0->3     girdi-dogrulama kaynak-kimligi aktarim-korumasi
rapor-ureteci->denetim-kurumu    fatura   3->0     cikti-suzme aktarim-korumasi
faturalama->denetim-gunlugu      kayit    3->5     girdi-dogrulama kaynak-kimligi yetkilendirme
kimlik-servisi->denetim-gunlugu  kayit    3->5     girdi-dogrulama kaynak-kimligi yetkilendirme
is-emri->denetim-gunlugu         kayit    3->5     girdi-dogrulama kaynak-kimligi yetkilendirme
sinir gecen 23 akis toplam 58 kalem doguruyor, akis basina 2.52

3. kalem turune gore
kalem turu                sayi     kalem %      akis %
aktarim-korumasi             9        15.5        34.6
cikti-suzme                  6        10.3        23.1
girdi-dogrulama             17        29.3        65.4
kaynak-kimligi              17        29.3        65.4
yetkilendirme                9        15.5        34.6

4. sinir cozunurlugu dustugunde ne gorunmez kaliyor
cizim               gorulen akis   gorulen %  dogan kalem     kalem %
sinir cizilmemis               0         0.0            0         0.0
kaba: dis/ic                   7        30.4           15        25.9
ayrintili: 6 bolge            23       100.0           58       100.0
kaba cizimde gorunmeyen 16 sinir gecisi 43 kalem tasiyor; bunlarin 9 tanesi bir veri deposuna giriyor
```

Sayılar **ölçüm** sınıfındadır; girdileri TD5–TD8'dir.

#### Yirmi Üç Geçiş

On yedi düğüm, yirmi altı akış, altı güven bölgesi. Bu üç sayıdan hiçbiri tehdit modellemenin
girdisi değildir; girdi olan sayı **23'tür** — güven sınırını geçen akış sayısı. Yirmi altı akışın
yalnız üçü aynı bölge içinde kalır: saha ekibinin kendi uygulamasıyla konuşması, doğrulayıcının
faturalamaya ölçüm vermesi ve faturalamanın iş emri üretmesi.

Bu oran çizgenin biçiminden gelir. Bölgeler yalıtımı artırmak için konur, ama iş akışı bölgeleri
dolaşmak zorundadır: abonenin isteği internet bölgesinden başlar ve veri bölgesinde biter, yani
tek bir işlemde üç ayrı sınır geçilir. Birinci tablonun son sütunu bunu bölge bölge yazar. `ic`
bölgesinden çıkan on dört akışın **on ikisi** bölgeyi terk eder; `veri` bölgesinden hiçbir akış
çıkmaz, çünkü depolar yalnız yazılan ve okunan uçlardır.

Güvenlik açısından tek başına anlamlı olan sayı budur. Saldırı Yüzeyi dersinde yüzey bir yol
sayısıyla ölçülmüştü; tasarım aşamasında elde henüz yol yoktur, yalnız akış vardır. Bu aşamada
yüzeyin sayılabilir karşılığı **güven sınırını geçen akış sayısıdır** ve o sayı sınırların nereye
çizildiğine bağlıdır.

#### Geçişin Doğurduğu Kalem

İkinci tablo her sınır geçişini kalem listesine çevirir. Yirmi üç geçiş **58 kalem** doğurur;
geçiş başına 2,52. Kural kümesi dört maddedir ve hiçbiri sezgiye dayanmaz: güven düzeyi düşükten
yükseğe geçen akış girdi doğrulama ve kaynak kimliği ister, tersi yönde giden akış çıktı süzme
ister, kimlik ya da fatura sınıfı veri taşıyan akış aktarım koruması ister, bir veri deposuna
giren akış yetkilendirme ister.

Üçüncü tablo dağılımı verir. `girdi-dogrulama` ve `kaynak-kimligi` on yedişer kalemle ilk
sıradadır; ikisi birlikte 58 kalemin **%58,6'sını** taşır. İkisinin de tek kaynağı vardır: yirmi
üç geçişin on yedisi düşük güven düzeyinden yükseğe gider. `cikti-suzme` altı kalemle en küçük
gruptur, `aktarim-korumasi` ve `yetkilendirme` dokuzar kalemle ortadadır.

En kalabalık satırlar dört kalem birden doğurur: `kimlik-servisi->kimlik-deposu`,
`faturalama->fatura-deposu` ve `rapor-ureteci->fatura-deposu`. Üçü de düşükten yükseğe gider,
korunması gereken bir veri sınıfı taşır ve bir depoya yazar. En yalın satır ise
`is-emri->saha-uygulamasi`: tek kalem, `cikti-suzme`. Kalem sayısı akışın önemiyle değil,
**kaç kuralı birden tetiklediğiyle** belirlenir; bu ayrım yöntemin sistematik olmasını sağlayan
şeydir.

Aynı sistematiklik kuralın kör noktasını da üretir. Yönetim konsolu beşinci güven düzeyinden
sonraki en yüksek düzeydedir ve çıkan üç akışının üçü de aşağı yönlüdür; bu yüzden üçünde de
yalnız `cikti-suzme` doğar, hiçbirinde `girdi-dogrulama` doğmaz. Kural kümesi açısından bu
tutarlıdır — daha güvenilir bir kaynaktan gelen veri doğrulanmaz — ama üç akışın taşıdığı şey
`ayar` sınıfıdır ve doğrulayıcının ayarını değiştirmek ölçüm zincirinin tamamını etkiler.
**Güven düzeyi bir sıralamadır, bir bağışıklık belgesi değildir.** Sistematik üretimin ürettiği
kalem kümesi, güven düzeyi atamalarının doğruluğunun ötesine geçemez; atama yanlışsa yöntem sessiz
kalır ve bu sessizlik hiçbir tabloda bir sıfır olarak görünmez.

#### Sınır Çizilmediğinde

Dördüncü tablo bu dersin en dikkat çekici sonucudur. Aynı yirmi altı akış üç ayrı çizim
çözünürlüğüyle ölçülür ve sonuç üç ayrı sayı verir.

Sınır hiç çizilmemişse bütün düğümler tek bölgede sayılır: **sıfır geçiş, sıfır kalem**. Sistem
değişmemiştir, yalnız ölçüsü yok edilmiştir. Bu, tehdit modelleme oturumunun sıfır kalemle
bitmesinin en yaygın sebebidir — çizge çizilmiştir ama üzerine sınır konmamıştır.

Kaba çizim — yalnız dış ve iç ayrımı — **7 geçiş** görür, yani gerçek geçişlerin %30,4'ünü ve 15
kalem doğurur, yani %25,9'unu. Ayrıntılı çizim 23 geçiş ve 58 kalem verir. Aradaki fark
**16 geçiş ve 43 kalemdir**; bu kalemlerin dokuzu bir veri deposuna giren akışlardan gelir.

Kaybın nerede olduğu açıktır. Kaba çizim iç ağı tek bir güvenli kutu sayar, dolayısıyla
`dogrulayici->olcum-deposu`, `faturalama->fatura-deposu` ya da `yonetim-konsolu->kimlik-servisi`
gibi akışlar hiç sınır geçmemiş olur. Bunlar sistemin en yüksek değerli akışlarıdır: kimlik ve
fatura verisinin depolara yazıldığı yerdir. **Sınır çözünürlüğü düştükçe kaybolan kalemler
rastgele seçilmez; iç bölgede kalanlar kaybolur ve iç bölgede duran şey deponun kendisidir.**

Buradan çıkan kural sadedir: bir tehdit modelleme oturumunun ilk çıktısı tehdit listesi değil,
**bölge listesidir**. Bölge sayısı ile bulunabilecek kalem sayısı aynı yönde hareket eder ve
bölgeler yanlış çizildiğinde sonraki bütün adımlar eksik bir küme üzerinde koşar.

#### Özet

- Tasarım aşamasında yüzeyin sayılabilir karşılığı **güven sınırını geçen akış sayısıdır**:
  17 düğüm ve 26 akışlık çizgede 23 akış sınır geçer, yalnız 3'ü aynı bölge içinde kalır.
- Sınır geçen 23 akış dört kuralla **58 kalem** doğurur; geçiş başına 2,52. Kalem sayısı akışın
  önemine değil, akışın kaç kuralı birden tetiklediğine bağlıdır.
- Kalemlerin %58,6'sı düşük güven düzeyinden yükseğe giden 17 akıştan gelir; çıktı süzme yalnız
  6 kalemle en küçük gruptur.
- Sınır hiç çizilmediğinde ölçüm **sıfır geçiş, sıfır kalem** verir; sistem değişmemiş, yalnız
  ölçüsü yok edilmiştir.
- Kaba bir dış/iç çizimi 23 geçişin 7'sini ve 58 kalemin 15'ini görür; görünmez kalan 16 geçiş
  43 kalem taşır ve bunların 9'u bir veri deposuna giren akıştır.

#### Sonraki Adım

Bu ders sayılabilir bir yüzey üretti: 23 geçiş ve 58 kalem. Ama 58 kalem bir tehdit listesi
değildir — kalemler denetim türleridir, yani "burada bir kimlik doğrulaması gerekir" der, "burada
şu şey olabilir" demez. İkisi arasındaki fark yöntemin ikinci adımıdır.

Bir çizge öğesine bakıp "burada ne ters gidebilir" sorusunu sormak kişiye ve o günkü dikkate
bağlıdır. Bunu kişiden bağımsız hale getiren şey, öğe türü başına **sabit bir kategori listesi**
uygulamaktır: her akışa, her sürece ve her depoya aynı soruların sorulması. Sonraki ders bu
sistematik üretimi koşturur ve iki sayıyı ayırır: yöntem kaç tehdit üretiyor ve bunların kaçı bu
sistem için gerçekten geçerli. Üretim ucuzdur; **eleme** pahalıdır ve dakikası ölçülür.

### Tehdit Sınıflandırma Yöntemleri

Source: https://academia.sh/tr/kurslar/guvenli-yasam-dongusu/tehdit-siniflandirma-yontemleri

Sistematik tehdit üretiminin iki sayısı: 43 çizge öğesine altı kategorinin uygulanmasıyla 156 ham tehdit üretilmesi, bunların 108'inin (%69,2) bu sistem için anlamlı, 48'inin geçersiz çıkması, elemenin 72 dakikayı karşılıksız harcaması, toplam oturum yükünün 666 dakika olması ve yalnız dışa açık öğelerle sınırlı üretimin anlamlı tehditlerin %92,6'sını 63,5 dakika daha ucuza bulması.

Önceki ders 23 sınır geçişinden 58 kalem çıkardı. O 58 kalem bir tehdit listesi değildi: her biri
bir **denetim türü** söylüyordu — "burada bir kaynak kimliği gerekir", "burada bir yetkilendirme
gerekir". Neyin ters gidebileceğini söylemiyordu.

Aradaki farkı kapatan adım, çizge öğesine bakıp "burada ne olabilir" diye sormaktır. Bu soru
kişiye ve o günkü dikkate bağlıdır; iki kişi iki ayrı liste üretir. Kişiden bağımsız hale getiren
şey, **her öğe türüne sabit bir kategori listesi uygulamaktır**. Bu ders o sistematik üretimi
koşturur ve iki sayıyı ayırır: yöntem kaç tehdit üretiyor, bunların kaçı bu sistem için gerçekten
geçerli.

#### Öğe Türü Başına Sabit Soru Listesi

Yaygın olarak kullanılan yöntem, her veri akış çizgesi öğesine sistematik tehdit üreten bir
**sınıflandırma yöntemidir**. Altı kategoriden oluşur ve kategoriler işleviyle anılır: **kimlik
taklidi**, **kurcalama**, **inkâr**, **bilgi ifşası**, **hizmet engelleme** ve **yetki
yükseltme**. Yöntemin tek kuralı vardır: her öğeye, türünde uygulanabilir olan kategorilerin
tamamı sorulur — biri atlanmaz, biri fazladan eklenmez.

Aşağıdaki envanter bir **modeldir**; önceki dersteki çizgenin aynı yapısıdır ve hiçbir saldırı
adımı taşımaz. Öğe özellikleri elle yazılmaz, çizgeden türetilir.

**TD9:** her öğenin beş özelliği çizgeden hesaplanır — dışa açıklık, gizli sınıf taşıma, iş
akışında olma, çok rollülük ve işlem üretme. **TD10:** üretim, öğe türüne uygulanabilir
kategorilerin çarpımıdır. **TD11:** üretilen tehdit, öğenin özelliği ilgili koşulu sağlamıyorsa
bu sistem için **geçersizdir**. **TD12:** her ham tehdit sabit bir eleme süresi, anlamlı bulunan
her tehdit ek bir yazım süresi harcar.

```js
// tehdit/oge.mjs — cizge ogelerinin envanteri (model): 02'deki cizgenin ayni yapisi, bu kez
// oge listesi olarak. Gercek bir sistem yoktur; hicbir saldiri adimi tasinmaz.

const BOLGE = { internet: 0, saha: 1, "dis-uc": 2, ic: 3, yonetim: 4, veri: 5 };
const DUGUM = Object.fromEntries(`
  abone D internet | denetim-kurumu D internet | sayac-cihazi D saha | saha-ekibi D saha
  abone-portali S dis-uc | toplama-ucu S dis-uc | saha-uygulamasi S saha
  dogrulayici S ic | faturalama S ic | is-emri S ic | rapor-ureteci S ic | kimlik-servisi S ic
  yonetim-konsolu S yonetim | olcum-deposu P veri | fatura-deposu P veri
  kimlik-deposu P veri | denetim-gunlugu P veri`
  .trim().split(/\s*[|\n]\s*/).map((r) => {
    const [ad, tur, bolge] = r.trim().split(/\s+/);
    return [ad, { ad, tur, bolge, duzey: BOLGE[bolge] }];
  }));
const AKIS = `
  abone            abone-portali    kimlik      | abone-portali   kimlik-servisi  kimlik
  kimlik-servisi   kimlik-deposu    kimlik      | abone-portali   faturalama      fatura
  faturalama       fatura-deposu    fatura      | faturalama      abone-portali   fatura
  sayac-cihazi     toplama-ucu      olcum       | toplama-ucu     dogrulayici     olcum
  dogrulayici      olcum-deposu     olcum       | dogrulayici     faturalama      olcum
  saha-ekibi       saha-uygulamasi  kimlik      | saha-uygulamasi is-emri         emir
  is-emri          saha-uygulamasi  emir        | is-emri         olcum-deposu    olcum
  saha-uygulamasi  toplama-ucu      olcum       | yonetim-konsolu dogrulayici     ayar
  yonetim-konsolu  toplama-ucu      ayar        | yonetim-konsolu kimlik-servisi  ayar
  rapor-ureteci    olcum-deposu     olcum       | rapor-ureteci   fatura-deposu   fatura
  denetim-kurumu   rapor-ureteci    kimlik      | rapor-ureteci   denetim-kurumu  fatura
  faturalama       denetim-gunlugu  kayit       | kimlik-servisi  denetim-gunlugu kayit
  is-emri          denetim-gunlugu  kayit       | faturalama      is-emri         emir`
  .trim().split(/\s*[|\n]\s*/).map((r) => {
    const [kaynak, hedef, sinif] = r.trim().split(/\s+/);
    return { kaynak, hedef, sinif, ad: `${kaynak}->${hedef}` };
  });

// TD9: her ogenin ozelligi cizgeden turetilir; elle yazilmaz.
const gelen = (d) => AKIS.filter((a) => a.hedef === d);
const giden = (d) => AKIS.filter((a) => a.kaynak === d);
const komsu = (d) => [...gelen(d), ...giden(d)];
const gizliSinif = (s) => s === "kimlik" || s === "fatura";
const isSinif = (s) => s === "olcum" || s === "fatura" || s === "emir";

export const OGE = [
  ...Object.values(DUGUM).map((d) => ({
    ad: d.ad, tur: d.tur,
    disaAcik: d.tur === "D" ? giden(d.ad).length > 0
      : gelen(d.ad).some((a) => DUGUM[a.kaynak].duzey < d.duzey),
    gizli: komsu(d.ad).some((a) => gizliSinif(a.sinif)),
    kritik: komsu(d.ad).some((a) => isSinif(a.sinif)),
    cokRol: new Set(gelen(d.ad).map((a) => DUGUM[a.kaynak].bolge)).size >= 2,
    islem: d.tur === "P" || (d.tur === "D" ? giden(d.ad).length > 0
      : giden(d.ad).some((a) => DUGUM[a.hedef].tur === "P")),
  })),
  ...AKIS.map((a) => ({
    ad: a.ad, tur: "A",
    disaAcik: DUGUM[a.kaynak].bolge !== DUGUM[a.hedef].bolge,
    gizli: gizliSinif(a.sinif), kritik: isSinif(a.sinif), cokRol: false, islem: false,
  })),
];

// TD10: sistematik uretim, her oge turune o turde uygulanabilir kategorileri uygular.
export const KATEGORI = ["kimlik-taklidi", "kurcalama", "inkar", "bilgi-ifsasi",
  "hizmet-engelleme", "yetki-yukseltme"];
export const UYGULANIR = {
  D: ["kimlik-taklidi", "inkar"],
  S: KATEGORI,
  P: ["kurcalama", "inkar", "bilgi-ifsasi", "hizmet-engelleme"],
  A: ["kurcalama", "bilgi-ifsasi", "hizmet-engelleme"],
};

// TD11: uretilen tehdit, ogenin ozelligi asagidaki kosulu saglamiyorsa gecersizdir.
export const GECERLI = {
  "kimlik-taklidi": (o) => o.disaAcik,
  "kurcalama": (o) => o.tur !== "A" || o.disaAcik,
  "inkar": (o) => o.islem,
  "bilgi-ifsasi": (o) => o.gizli,
  "hizmet-engelleme": (o) => o.kritik,
  "yetki-yukseltme": (o) => o.cokRol,
};

// TD12: her uretilen tehdit sabit bir eleme suresi, anlamli bulunan her tehdit ek bir
// yazim suresi harcar (kurgu dakika).
export const ELEME_DK = 1.5, YAZIM_DK = 4;
```

```js
// tehdit/uretim.mjs — sistematik uretim kac tehdit veriyor, kaci bu sistem icin gecersiz,
// eleme kac dakika aliyor.
import { OGE, KATEGORI, UYGULANIR, GECERLI, ELEME_DK, YAZIM_DK } from "./oge.mjs";

const yaz = (g, ...s) => console.log(s.map((v, i) =>
  (g[i] < 0 ? String(v).padEnd(-g[i]) : String(v).padStart(g[i]))).join(""));
const uret = (ler) => ler.flatMap((o) =>
  UYGULANIR[o.tur].map((k) => ({ oge: o, kategori: k, gecerli: GECERLI[k](o) })));
const HAM = uret(OGE), ANLAMLI = HAM.filter((t) => t.gecerli);
const TUR = { D: "dis varlik", S: "surec", P: "veri deposu", A: "veri akisi" };

console.log(`${OGE.length} oge, ${KATEGORI.length} kategori; ham uretim ${HAM.length} tehdit, ` +
  `anlamli ${ANLAMLI.length} (%${((ANLAMLI.length / HAM.length) * 100).toFixed(1)}), ` +
  `gecersiz ${HAM.length - ANLAMLI.length}`);

const A = [-13, 7, 10, 8, 9, 10, 11];
console.log("\n1. oge turu basina uretim");
yaz(A, "oge turu", "oge", "kategori", "ham", "anlamli", "gecersiz", "anlamli %");
for (const t of ["D", "S", "P", "A"]) {
  const o = OGE.filter((x) => x.tur === t), h = uret(o), g = h.filter((x) => x.gecerli);
  yaz(A, TUR[t], o.length, UYGULANIR[t].length, h.length, g.length, h.length - g.length,
    ((g.length / h.length) * 100).toFixed(1));
}

const B = [-18, 8, 9, 10, 11, 2, -22];
console.log("\n2. kategori basina uretim ve eleme");
yaz(B, "kategori", "ham", "anlamli", "gecersiz", "anlamli %", "", "gecerlilik kosulu");
const KOSUL = { "kimlik-taklidi": "disa acik", "kurcalama": "akis ise sinir gecen",
  "inkar": "islem uretiyor", "bilgi-ifsasi": "gizli sinif tasiyor",
  "hizmet-engelleme": "is akisinda", "yetki-yukseltme": "cok rollu surec" };
for (const k of KATEGORI) {
  const h = HAM.filter((t) => t.kategori === k), g = h.filter((t) => t.gecerli);
  yaz(B, k, h.length, g.length, h.length - g.length,
    ((g.length / h.length) * 100).toFixed(1), "", KOSUL[k]);
}

const C = [-26, 9, 10, 11, 12, 13];
console.log("\n3. uc uretim kumesi: hepsi, yalniz disa acik, yalniz surecler");
yaz(C, "sira", "oge", "ham", "anlamli", "toplam dk", "anlamli/dk");
const kume = { "butun ogeler": OGE, "yalniz disa acik ogeler": OGE.filter((o) => o.disaAcik),
  "yalniz surecler": OGE.filter((o) => o.tur === "S") };
for (const [ad, ler] of Object.entries(kume)) {
  const h = uret(ler), g = h.filter((x) => x.gecerli);
  const dk = h.length * ELEME_DK + g.length * YAZIM_DK;
  yaz(C, ad, ler.length, h.length, g.length, dk.toFixed(1), (g.length / dk).toFixed(3));
}
const disa = uret(OGE.filter((o) => o.disaAcik)).filter((x) => x.gecerli);
console.log(`disa acik ogelerle sinirli uretim, anlamli tehditlerin ` +
  `%${((disa.length / ANLAMLI.length) * 100).toFixed(1)}'ini buluyor; kacirdigi ` +
  `${ANLAMLI.length - disa.length} tehdit yalnizca ic ogelerde doguyor`);

const KOD = Object.fromEntries(KATEGORI.map((k) => [k, k.slice(0, 2).toUpperCase()]));
const D = [-32, -12, 6, 9, 2, -20];
console.log("\n4. en cok ve en az anlamli tehdit dogduran uc oge (" +
  KATEGORI.map((k) => `${KOD[k]}=${k}`).join(", ") + ")");
yaz(D, "oge", "tur", "ham", "anlamli", "", "anlamli kategoriler");
const sirali = OGE.map((o) => ({ o, h: UYGULANIR[o.tur],
  g: UYGULANIR[o.tur].filter((k) => GECERLI[k](o)) })).sort((x, y) => y.g.length - x.g.length);
for (const s of [...sirali.slice(0, 3), ...sirali.slice(-3)])
  yaz(D, s.o.ad, TUR[s.o.tur], s.h.length, s.g.length, "",
    s.g.map((k) => KOD[k]).join(" ") || "-");
for (const t of ["S", "A"]) {
  const g = ANLAMLI.filter((x) => x.oge.tur === t).length;
  console.log(`${TUR[t]} ogeleri: ogelerin ` +
    `%${((OGE.filter((o) => o.tur === t).length / OGE.length) * 100).toFixed(1)}'i, ` +
    `anlamli tehditlerin %${((g / ANLAMLI.length) * 100).toFixed(1)}'i`);
}
console.log(`gecersiz ${HAM.length - ANLAMLI.length} tehdidin elenmesi ` +
  `${((HAM.length - ANLAMLI.length) * ELEME_DK).toFixed(1)} dakika harcar ve karsiligi sifirdir`);
```

```
43 oge, 6 kategori; ham uretim 156 tehdit, anlamli 108 (%69.2), gecersiz 48

1. oge turu basina uretim
oge turu         oge  kategori     ham  anlamli  gecersiz  anlamli %
dis varlik         4         2       8        8         0      100.0
surec              9         6      54       40        14       74.1
veri deposu        4         4      16       12         4       75.0
veri akisi        26         3      78       48        30       61.5

2. kategori basina uretim ve eleme
kategori               ham  anlamli  gecersiz  anlamli %  gecerlilik kosulu
kimlik-taklidi          13       11         2       84.6  disa acik
kurcalama               39       36         3       92.3  akis ise sinir gecen
inkar                   17       13         4       76.5  islem uretiyor
bilgi-ifsasi            39       17        22       43.6  gizli sinif tasiyor
hizmet-engelleme        39       24        15       61.5  is akisinda
yetki-yukseltme          9        7         2       77.8  cok rollu surec

3. uc uretim kumesi: hepsi, yalniz disa acik, yalniz surecler
sira                            oge       ham    anlamli   toplam dk   anlamli/dk
butun ogeler                     43       156        108       666.0        0.162
yalniz disa acik ogeler          38       135        100       602.5        0.166
yalniz surecler                   9        54         40       241.0        0.166
disa acik ogelerle sinirli uretim, anlamli tehditlerin %92.6'ini buluyor; kacirdigi 8 tehdit yalnizca ic ogelerde doguyor

4. en cok ve en az anlamli tehdit dogduran uc oge (KI=kimlik-taklidi, KU=kurcalama, IN=inkar, BI=bilgi-ifsasi, HI=hizmet-engelleme, YE=yetki-yukseltme)
oge                             tur            ham  anlamli  anlamli kategoriler
faturalama                      surec            6        6  KI KU IN BI HI YE
abone-portali                   surec            6        5  KI KU BI HI YE
dogrulayici                     surec            6        5  KI KU IN HI YE
kimlik-servisi->denetim-gunlugu veri akisi       3        1  KU
is-emri->denetim-gunlugu        veri akisi       3        1  KU
faturalama->is-emri             veri akisi       3        1  HI
surec ogeleri: ogelerin %20.9'i, anlamli tehditlerin %37.0'i
veri akisi ogeleri: ogelerin %60.5'i, anlamli tehditlerin %44.4'i
gecersiz 48 tehdidin elenmesi 72.0 dakika harcar ve karsiligi sifirdir
```

Sayılar **ölçüm** sınıfındadır; girdileri TD9–TD12'dir.

#### Yüz Elli Altı Ham Tehdit

Kırk üç öğeye altı kategorinin uygulanabilir olanları sorulduğunda **156 ham tehdit** çıkar.
Üretim ucuzdur ve otomatiktir: kimse "burada ne olabilir" diye düşünmez, tablo doldurulur.
Yöntemin bütün değeri buradan gelir — hiçbir öğe atlanmaz ve liste kişiye göre değişmez.

Birinci tablo üretimin nereden geldiğini gösterir. Yirmi altı veri akışı öğesi üçer kategori
alarak **78 tehdit** üretir, yani ham üretimin yarısını. Dokuz süreç öğesi ise altışar kategori
alır ve 54 tehdit üretir. Dört dış varlık öğesi yalnız iki kategori alır: dış varlığa kurcalama ya
da yetki yükseltme sorulmaz, çünkü öğe sistemin dışındadır ve içeride bir yetkisi yoktur.

İkinci tabloda ham sayı kategori kategori dağılır. Kurcalama, bilgi ifşası ve hizmet engelleme
39'ar tehditle en kalabalık üçlüdür; üçü de hem süreçlerde hem depolarda hem akışlarda
uygulanabilir olduğu için toplam öğe sayısına yakın bir sayı üretirler. Yetki yükseltme yalnız
dokuz tehdit üretir, çünkü yalnız süreçlerde sorulur.

#### Yüz Sekizi Anlamlı

İkinci sayı elemeden sonra çıkar. Yüz elli altı ham tehdidin **108'i** bu sistem için anlamlıdır
(%69,2), **48'i geçersizdir**. Geçersizlik keyfi değildir: her kategorinin bir geçerlilik koşulu
vardır ve koşul öğenin çizgeden türetilen özelliğine bakar.

Ayrım kategoriden kategoriye çok değişir. Kurcalamanın %92,3'ü anlamlıdır; koşulu yalnız akışlar
için sınır geçmeyi ister ve akışların 26'sının 23'ü sınır geçer. Bilgi ifşasının ise yalnız
**%43,6'sı** anlamlıdır: koşul öğenin gizli sınıf — kimlik ya da fatura — taşımasıdır ve ölçüm,
ayar ve kayıt sınıfı taşıyan 22 öğede kategori boşa düşer. Hizmet engelleme ortadadır (%61,5):
iş akışında olmayan öğelerin kesintisi işi durdurmaz.

Dördüncü tablo aynı ayrımı öğe düzeyinde gösterir. `faturalama` altı kategorinin altısında da
anlamlı tehdit doğurur — dışa açıktır, gizli sınıf taşır, iş akışındadır, çok rollüdür ve bir
depoya yazar. Karşı uçta `is-emri->denetim-gunlugu` gibi akışlar üç kategoriden yalnız birinde
anlamlıdır. Yoğunlaşma dikkat çekicidir: dokuz süreç öğesi, öğelerin yalnız %20,9'u olmasına
karşın anlamlı tehditlerin **%37,0'sini** taşır; 26 veri akışı öğesi ise öğelerin %60,5'i olup
tehditlerin %44,4'ünü taşır.

#### Elemenin Dakikası

Üretimin ucuzluğu elemeyi pahalı hale getirir. Her ham tehdit değerlendirilmek zorundadır —
geçersiz olan da. Modelde bir tehdidin elenmesi 1,5 kurgu dakika, anlamlı bulunan bir tehdidin
yazılması ek 4 dakika sürer.

Toplam **666 dakikadır**, yani 11,1 saat. Bunun 234 dakikası eleme, 432 dakikası yazımdır.
Elemenin **72 dakikası geçersiz 48 tehdit için harcanır ve karşılığı sıfırdır** — hiçbir karşı
önleme dönüşmeyecek satırların okunup atılması. Tehdit modelleme oturumunun süresi bu yüzden
üretilen tehdit sayısıyla değil, **elenen** tehdit sayısıyla birlikte okunmalıdır.

Üçüncü tablo üç ayrı üretim kümesini karşılaştırır. Bütün öğeler: 156 ham, 108 anlamlı, 666
dakika, dakika başına 0,162 anlamlı tehdit. Yalnız dışa açık öğeler: 135 ham, 100 anlamlı, 602,5
dakika, dakika başına 0,166. Yalnız süreçler: 54 ham, 40 anlamlı, 241 dakika, yine 0,166.

Üç kümenin dakika verimliliği neredeyse aynıdır ve bu, beklenenin tersidir. Sınır geçen öğelere
öncelik vermek 63,5 dakika kazandırır ve 8 tehdit kaybettirir — kazanç toplamın onda birinden
azdır, çünkü öğelerin %88'i zaten dışa açıktır. Yalnız süreçlere bakmak ise 425 dakika kazandırır
ama anlamlı tehditlerin **%63'ünü** dışarıda bırakır.

Buradan çıkan karar şudur: bu yöntemde kısayol, verimliliği artırarak değil **kapsamayı
küçülterek** çalışır. Süreyi düşürmek isteyen bir ekip için tek dürüst yol, hangi öğe kümesinin
dışarıda bırakıldığını yazmaktır.

#### Özet

- Sistematik üretim, 43 çizge öğesine türlerinde uygulanabilir kategorileri sorarak **156 ham
  tehdit** çıkarır; üretim ucuzdur, kişiye göre değişmez ve hiçbir öğeyi atlamaz.
- Ham tehditlerin 108'i (%69,2) bu sistem için anlamlı, **48'i geçersizdir**; geçerlilik koşulu
  öğenin çizgeden türetilen özelliğine bakar.
- Anlamlılık kategoriye göre %43,6 ile %92,3 arasında değişir; bilgi ifşası 22 öğede boşa düşer,
  kurcalama neredeyse hiç düşmez.
- Oturumun süresi **666 dakikadır**; 72 dakikası geçersiz tehditlerin elenmesine gider ve karşılığı
  sıfırdır. Süre üretilen tehditle değil elenen tehditle birlikte okunur.
- Üç üretim kümesinin dakika verimliliği neredeyse aynıdır (0,162–0,166); kısayol verimlilikten
  değil kapsamadan tasarruf eder — yalnız süreçlere bakmak anlamlı tehditlerin %63'ünü kaçırır.

#### Sonraki Adım

Sistematik üretim öğeden başlar: her kutuya, her oka ve her depoya aynı sorular sorulur.
Bu yaklaşımın gücü de sınırı da aynı yerdedir — **öğeyi tek başına** ele alır. Yüz sekiz anlamlı
tehdidin her biri bir öğe ile bir kategorinin kesişimidir; hiçbiri iki öğenin birlikte
kullanılmasından doğmaz.

Oysa gerçek bir zarar çoğunlukla tek bir öğede değil, birkaç öğenin arka arkaya kullanılmasında
oluşur: bir yerde elde edilen bilgi başka bir yerde geçerli hale gelir. Bu tür kalemleri bulmanın
yolu öğeden değil **hedeften** başlamaktır — saldırgan ne elde etmek ister ve buraya hangi yoldan
gelir. Sonraki ders senaryo temelli modellemeyi aynı çizgede koşturur ve kapsama ekseninde ölçer:
senaryolar kaç tehdit buluyor, sistematik yöntemin bulduğunun kaçını kaçırıyor ve ikisinin
kesişimi ne.

### Risk Odaklı Modelleme

Source: https://academia.sh/tr/kurslar/guvenli-yasam-dongusu/risk-odakli-modelleme

Senaryo temelli modellemenin kapsama ölçümü: beş senaryonun 51 tehdit üretmesi, bunun 39'unun sistematik kümeyle kesişmesi ve 12'sinin hiçbir tek öğede tanımlı olmayan zincir tehdidi olması, senaryoların sistematik kümenin %63,9'unu kaçırması, kaçırılanın 24'ünün hizmet engelleme kategorisinde olması, senaryo yönteminin dakikada 0,234 tehditle sistematik üretimin 1,44 katı hızda çalışması ve iki yöntemin birleşiminin 120 tehdide çıkması.

Sistematik üretim öğeden başlar: her kutuya, her oka ve her depoya aynı sorular sorulur. Yüz sekiz
anlamlı tehdidin her biri **bir öğe ile bir kategorinin kesişimidir**; hiçbiri iki öğenin birlikte
kullanılmasından doğmaz.

Oysa gerçek zarar çoğunlukla tek bir öğede değil, birkaç öğenin arka arkaya kullanılmasında
oluşur. Bu kalemleri bulmanın yolu öğeden değil **hedeften** başlamaktır: saldıran taraf ne elde
etmek ister ve oraya hangi yoldan gider. Bu ders senaryo temelli modellemeyi aynı çizgede
koşturur ve tek soruyu sorar — senaryolar kaç tehdit buluyor, sistematik yöntemin bulduğunun
kaçını kaçırıyor, ikisinin kesişimi ne.

#### Senaryo Bir Düğüm Dizisidir

Senaryo, saldırgan bakışıyla kurulan bir yoldur; Güvenlik Gereksinimleri dersindeki **kötüye
kullanım senaryosu** ile aynı köktendir, ama orada gereksinim yazmak için kullanılırdı, burada
tehdit üretmek için kullanılıyor.

Aşağıdaki senaryolar **modeldir** ve yalnızca **hangi öğelerin kullanıldığını** yazar; hiçbir adım
nasıl yapıldığıyla anlatılmaz. Böyle bir senaryonun gerçek bir sistem üzerinde denenmesi, **yazılı
yetki ve tanımlı kapsam olmadan hem yasadışı hem meslek dışıdır**.

**TD13:** senaryo, bir saldırgan profilinden bir hedefe varan düğüm dizisidir. **TD14:**
senaryonun dokunduğu öğeler, dizideki düğümler ve aralarındaki akışlardır. **TD15:** senaryo iki
tür tehdit doğurur — dokunulan öğede senaryonun kategorisiyle örtüşen **öğe tehdidi** ve ardışık
iki düğümün birlikte kullanılmasından doğan **zincir tehdidi**; ikincisi tek öğe üzerinde tanımlı
olmadığı için sistematik üretimde karşılığı yoktur. **TD16:** senaryo kurmanın bedeli senaryo
başına sabit süre artı dokunulan öğe başına süredir.

```js
// tehdit/senaryo.mjs — ayni cizge, bu kez hedeften geriye kurulan senaryolarla (model).
// Senaryo yalnizca hangi ogelerin kullanildigini yazar; adimin nasil yapildigi yazilmaz.
// Gercek bir sistem, gercek bir uc ya da isleyen bir adim yoktur.

const BOLGE = { internet: 0, saha: 1, "dis-uc": 2, ic: 3, yonetim: 4, veri: 5 };
export const DUGUM = Object.fromEntries(`
  abone D internet | denetim-kurumu D internet | sayac-cihazi D saha | saha-ekibi D saha
  abone-portali S dis-uc | toplama-ucu S dis-uc | saha-uygulamasi S saha
  dogrulayici S ic | faturalama S ic | is-emri S ic | rapor-ureteci S ic | kimlik-servisi S ic
  yonetim-konsolu S yonetim | olcum-deposu P veri | fatura-deposu P veri
  kimlik-deposu P veri | denetim-gunlugu P veri`
  .trim().split(/\s*[|\n]\s*/).map((r) => {
    const [ad, tur, bolge] = r.trim().split(/\s+/);
    return [ad, { ad, tur, bolge, duzey: BOLGE[bolge] }];
  }));
export const AKIS = `
  abone            abone-portali    kimlik      | abone-portali   kimlik-servisi  kimlik
  kimlik-servisi   kimlik-deposu    kimlik      | abone-portali   faturalama      fatura
  faturalama       fatura-deposu    fatura      | faturalama      abone-portali   fatura
  sayac-cihazi     toplama-ucu      olcum       | toplama-ucu     dogrulayici     olcum
  dogrulayici      olcum-deposu     olcum       | dogrulayici     faturalama      olcum
  saha-ekibi       saha-uygulamasi  kimlik      | saha-uygulamasi is-emri         emir
  is-emri          saha-uygulamasi  emir        | is-emri         olcum-deposu    olcum
  saha-uygulamasi  toplama-ucu      olcum       | yonetim-konsolu dogrulayici     ayar
  yonetim-konsolu  toplama-ucu      ayar        | yonetim-konsolu kimlik-servisi  ayar
  rapor-ureteci    olcum-deposu     olcum       | rapor-ureteci   fatura-deposu   fatura
  denetim-kurumu   rapor-ureteci    kimlik      | rapor-ureteci   denetim-kurumu  fatura
  faturalama       denetim-gunlugu  kayit       | kimlik-servisi  denetim-gunlugu kayit
  is-emri          denetim-gunlugu  kayit       | faturalama      is-emri         emir`
  .trim().split(/\s*[|\n]\s*/).map((r) => {
    const [kaynak, hedef, sinif] = r.trim().split(/\s+/);
    return { kaynak, hedef, sinif, ad: `${kaynak}->${hedef}` };
  });

// Onceki dersin sistematik uretimi ayni kurallarla yeniden turetiliyor.
const gelen = (d) => AKIS.filter((a) => a.hedef === d);
const giden = (d) => AKIS.filter((a) => a.kaynak === d);
const komsu = (d) => [...gelen(d), ...giden(d)];
const gizliSinif = (s) => s === "kimlik" || s === "fatura";
const isSinif = (s) => s === "olcum" || s === "fatura" || s === "emir";
export const OGE = Object.fromEntries([
  ...Object.values(DUGUM).map((d) => [d.ad, { ad: d.ad, tur: d.tur,
    disaAcik: d.tur === "D" ? giden(d.ad).length > 0
      : gelen(d.ad).some((a) => DUGUM[a.kaynak].duzey < d.duzey),
    gizli: komsu(d.ad).some((a) => gizliSinif(a.sinif)),
    kritik: komsu(d.ad).some((a) => isSinif(a.sinif)),
    cokRol: new Set(gelen(d.ad).map((a) => DUGUM[a.kaynak].bolge)).size >= 2,
    islem: d.tur === "P" || (d.tur === "D" ? giden(d.ad).length > 0
      : giden(d.ad).some((a) => DUGUM[a.hedef].tur === "P")) }]),
  ...AKIS.map((a) => [a.ad, { ad: a.ad, tur: "A",
    disaAcik: DUGUM[a.kaynak].bolge !== DUGUM[a.hedef].bolge,
    gizli: gizliSinif(a.sinif), kritik: isSinif(a.sinif), cokRol: false, islem: false }]),
]);
export const KATEGORI = ["kimlik-taklidi", "kurcalama", "inkar", "bilgi-ifsasi",
  "hizmet-engelleme", "yetki-yukseltme"];
const UYGULANIR = { D: ["kimlik-taklidi", "inkar"], S: KATEGORI,
  P: ["kurcalama", "inkar", "bilgi-ifsasi", "hizmet-engelleme"],
  A: ["kurcalama", "bilgi-ifsasi", "hizmet-engelleme"] };
const GECERLI = { "kimlik-taklidi": (o) => o.disaAcik,
  "kurcalama": (o) => o.tur !== "A" || o.disaAcik,
  "inkar": (o) => o.islem, "bilgi-ifsasi": (o) => o.gizli,
  "hizmet-engelleme": (o) => o.kritik, "yetki-yukseltme": (o) => o.cokRol };
export const anlamli = (o, k) => UYGULANIR[o.tur].includes(k) && GECERLI[k](o);
export const SISTEMATIK = new Set(Object.values(OGE).flatMap((o) =>
  KATEGORI.filter((k) => anlamli(o, k)).map((k) => `${o.ad}|${k}`)));

// TD13: senaryo, bir saldirgan profilinden bir hedefe varan dugum dizisidir. Dizi yalnizca
// hangi ogenin kullanildigini soyler; adimin nasil yapildigi yazilmaz.
export const SENARYO = [
  { ad: "abone-hesabi-devralma", profil: "dis", hedef: "kimlik-deposu",
    dizi: ["abone", "abone-portali", "kimlik-servisi", "kimlik-deposu"],
    kategori: ["kimlik-taklidi", "bilgi-ifsasi"] },
  { ad: "fatura-tutarini-degistirme", profil: "abone", hedef: "fatura-deposu",
    dizi: ["abone", "abone-portali", "faturalama", "fatura-deposu"],
    kategori: ["kurcalama", "yetki-yukseltme"] },
  { ad: "sahte-olcum-kaydi", profil: "saha", hedef: "olcum-deposu",
    dizi: ["sayac-cihazi", "toplama-ucu", "dogrulayici", "olcum-deposu"],
    kategori: ["kimlik-taklidi", "kurcalama"] },
  { ad: "denetim-izini-bozma", profil: "ic-yetkili", hedef: "denetim-gunlugu",
    dizi: ["yonetim-konsolu", "kimlik-servisi", "denetim-gunlugu"],
    kategori: ["kurcalama", "inkar"] },
  { ad: "toplu-fatura-verisi-cikarma", profil: "dis-kurum", hedef: "fatura-deposu",
    dizi: ["denetim-kurumu", "rapor-ureteci", "fatura-deposu"],
    kategori: ["kimlik-taklidi", "bilgi-ifsasi"] },
];

// TD14: senaryonun dokundugu ogeler, dizideki dugumler ve aralarindaki akislardir.
export function dokunulan(s) {
  const ler = [...s.dizi];
  for (let i = 0; i + 1 < s.dizi.length; i++) ler.push(`${s.dizi[i]}->${s.dizi[i + 1]}`);
  return ler;
}

// TD15: senaryo iki tur tehdit dogurur. Oge tehdidi, dokunulan ogede senaryonun kategorisiyle
// ortusen ve orada anlamli olan tehdittir. Zincir tehdidi ardisik iki dugumun birlikte
// kullanilmasindan dogar; tek oge uzerinde tanimli olmadigi icin sistematik karsiligi yoktur.
export const ogeTehditleri = (s) => dokunulan(s)
  .flatMap((a) => s.kategori.filter((k) => anlamli(OGE[a], k)).map((k) => `${a}|${k}`));
export const zincirTehditleri = (s) => s.dizi.slice(0, -1)
  .map((d, i) => `${d}=>${s.dizi[i + 1]}|zincir`);

// TD16: senaryo kurmanin bedeli senaryo basina sabit sure arti dokunulan oge basina suredir.
export const SENARYO_DK = 25, OGE_DK = 3;

// Sistematik uretimin suresi de ayni girdilerden turetiliyor.
export const HAM_SAYI = Object.values(OGE).reduce((a, o) => a + UYGULANIR[o.tur].length, 0);
export const ELEME_DK = 1.5, YAZIM_DK = 4;
```

```js
// tehdit/kapsama.mjs — senaryo temelli uretim kac tehdit buluyor, sistematik uretimin
// bulduklarinin kacini kaciriyor, ikisinin kesisimi ne.
import { OGE, KATEGORI, SENARYO, SISTEMATIK, dokunulan, ogeTehditleri, zincirTehditleri,
  SENARYO_DK, OGE_DK, HAM_SAYI, ELEME_DK, YAZIM_DK } from "./senaryo.mjs";

const yaz = (g, ...s) => console.log(s.map((v, i) =>
  (g[i] < 0 ? String(v).padEnd(-g[i]) : String(v).padStart(g[i]))).join(""));
const OGE_T = new Set(SENARYO.flatMap(ogeTehditleri));
const ZINCIR = new Set(SENARYO.flatMap(zincirTehditleri));
const SENARYO_KUME = new Set([...OGE_T, ...ZINCIR]);
const KESISIM = [...OGE_T].filter((t) => SISTEMATIK.has(t));
const YALNIZ_S = [...SISTEMATIK].filter((t) => !OGE_T.has(t));
const SENARYO_DAKIKA = SENARYO.length * SENARYO_DK +
  SENARYO.reduce((a, s) => a + dokunulan(s).length, 0) * OGE_DK;

console.log(`${SENARYO.length} senaryo; senaryo kumesi ${SENARYO_KUME.size} tehdit ` +
  `(${OGE_T.size} oge tehdidi + ${ZINCIR.size} zincir tehdidi), sistematik kume ` +
  `${SISTEMATIK.size}; kesisim ${KESISIM.length}`);

const A = [-28, -12, -17, 6, 11, 8, 10, 8];
console.log("\n1. senaryolar ve urettikleri");
yaz(A, "senaryo", "profil", "hedef", "adim", "dokunulan", "oge t.", "zincir t.", "dakika");
for (const s of SENARYO) {
  const d = dokunulan(s);
  yaz(A, s.ad, s.profil, s.hedef, s.dizi.length, d.length, ogeTehditleri(s).length,
    zincirTehditleri(s).length, SENARYO_DK + d.length * OGE_DK);
}

const B = [-22, 10, 16, 18];
console.log("\n2. iki yontemin kapsamasi");
yaz(B, "kume", "tehdit", "sistematigin %", "sistematige oran");
for (const [ad, n, p] of [
  ["sistematik kume", SISTEMATIK.size, "-"],
  ["senaryo kumesi", SENARYO_KUME.size, "-"],
  ["kesisim", KESISIM.length, (KESISIM.length / SISTEMATIK.size * 100).toFixed(1)],
  ["yalniz senaryoda", SENARYO_KUME.size - KESISIM.length, "-"],
  ["yalniz sistematikte", YALNIZ_S.length, (YALNIZ_S.length / SISTEMATIK.size * 100).toFixed(1)],
  ["birlesim", SISTEMATIK.size + SENARYO_KUME.size - KESISIM.length, "-"],
]) yaz(B, ad, n, p === "-" ? "-" : p + " %", (n / SISTEMATIK.size).toFixed(2) + " x");

const C = [-20, 9, 10, 12, 12];
console.log("\n3. dakika basina bulunan tehdit");
yaz(C, "yontem", "tehdit", "dakika", "tehdit/dk", "kacirdigi");
const SISTEMATIK_DK = HAM_SAYI * ELEME_DK + SISTEMATIK.size * YAZIM_DK;
for (const [ad, n, dk, kacan] of [
  ["sistematik uretim", SISTEMATIK.size, SISTEMATIK_DK, ZINCIR.size],
  ["senaryo temelli", SENARYO_KUME.size, SENARYO_DAKIKA, YALNIZ_S.length],
  ["ikisi birlikte", SISTEMATIK.size + SENARYO_KUME.size - KESISIM.length,
    SISTEMATIK_DK + SENARYO_DAKIKA, 0],
]) yaz(C, ad, n, dk.toFixed(1), (n / dk).toFixed(3), kacan);

const D = [-13, 12, 10, 11, 13];
console.log("\n4. senaryolarin kacirdigi tehditler nerede duruyor");
yaz(D, "oge turu", "sistematik", "kesisim", "kacirilan", "kacirilan %");
const TUR = { D: "dis varlik", S: "surec", P: "veri deposu", A: "veri akisi" };
for (const t of ["D", "S", "P", "A"]) {
  const s = [...SISTEMATIK].filter((x) => OGE[x.split("|")[0]].tur === t);
  const k = s.filter((x) => !OGE_T.has(x));
  yaz(D, TUR[t], s.length, s.length - k.length, k.length,
    ((k.length / s.length) * 100).toFixed(1));
}
const kat = KATEGORI.map((k) => ({ k, n: YALNIZ_S.filter((x) => x.endsWith("|" + k)).length }))
  .sort((a, b) => b.n - a.n);
console.log(`kacirilan ${YALNIZ_S.length} tehdidin kategori dagilimi: ` +
  kat.map((x) => `${x.k} ${x.n}`).join(", "));
console.log(`${ZINCIR.size} zincir tehdidinin hicbiri sistematik uretimde yoktur; ` +
  `bunlar tek oge uzerinde tanimli degildir`);
```

```
5 senaryo; senaryo kumesi 51 tehdit (39 oge tehdidi + 12 zincir tehdidi), sistematik kume 108; kesisim 39

1. senaryolar ve urettikleri
senaryo                     profil      hedef              adim  dokunulan  oge t. zincir t.  dakika
abone-hesabi-devralma       dis         kimlik-deposu         4          7       9         3      46
fatura-tutarini-degistirme  abone       fatura-deposu         4          7       8         3      46
sahte-olcum-kaydi           saha        olcum-deposu          4          7       9         3      46
denetim-izini-bozma         ic-yetkili  denetim-gunlugu       3          5       7         2      40
toplu-fatura-verisi-cikarma dis-kurum   fatura-deposu         3          5       6         2      40

2. iki yontemin kapsamasi
kume                      tehdit  sistematigin %  sistematige oran
sistematik kume              108               -            1.00 x
senaryo kumesi                51               -            0.47 x
kesisim                       39          36.1 %            0.36 x
yalniz senaryoda              12               -            0.11 x
yalniz sistematikte           69          63.9 %            0.64 x
birlesim                     120               -            1.11 x

3. dakika basina bulunan tehdit
yontem                 tehdit    dakika   tehdit/dk   kacirdigi
sistematik uretim         108     666.0       0.162          12
senaryo temelli            51     218.0       0.234          69
ikisi birlikte            120     884.0       0.136           0

4. senaryolarin kacirdigi tehditler nerede duruyor
oge turu       sistematik   kesisim  kacirilan  kacirilan %
dis varlik              8         3          5         62.5
surec                  40        17         23         57.5
veri deposu            12         6          6         50.0
veri akisi             48        13         35         72.9
kacirilan 69 tehdidin kategori dagilimi: hizmet-engelleme 24, kurcalama 19, inkar 11, bilgi-ifsasi 7, yetki-yukseltme 5, kimlik-taklidi 3
12 zincir tehdidinin hicbiri sistematik uretimde yoktur; bunlar tek oge uzerinde tanimli degildir
```

Sayılar **ölçüm** sınıfındadır; girdileri TD13–TD16'dır.

#### Beş Senaryo, Elli Bir Tehdit

Birinci tablo senaryoların kendi ölçüsünü verir. Beş senaryonun üçü dört adımlık, ikisi üç
adımlıktır; dokunulan öğe sayısı yedi ile beş arasında değişir. Toplam **51 tehdit** çıkar ve bu
sayının bileşimi asıl bulgudur: **39 öğe tehdidi ve 12 zincir tehdidi**.

Kırk altı ile kırk dakika arasında değişen senaryo süreleri toplam 218 dakika eder. Sistematik
üretimin 666 dakikasıyla karşılaştırıldığında bu, yaklaşık üçte birdir. Senaryolar daha az öğeye
dokunur çünkü hedefe giden yol çizgenin tamamını dolaşmaz: beş senaryo birlikte 43 öğenin ancak
bir bölümünü kullanır.

#### Kesişim, Fark ve Birleşim

İkinci tablo bu dersin ana ölçümüdür. Sistematik küme 108, senaryo kümesi 51 tehdittir. Kesişim
**39'dur** — yani senaryoların bulduğu öğe tehditlerinin tamamı zaten sistematik kümededir.
Bu beklenen bir sonuçtur: senaryo bir öğeye dokunduğunda o öğede anlamlı olan kategoriyi üretir,
sistematik yöntem ise zaten bütün öğelerde bütün anlamlı kategorileri üretmiştir.

**Yalnız senaryoda olan 12 tehdidin hepsi zincir tehdididir.** Bunlar iki düğümün birlikte
kullanılmasından doğar ve tek öğe üzerinde tanımlı olmadıkları için sistematik üretimde hiçbir
satıra düşmezler. Yöntemin yapısı gereği düşemezler de: soru "bu öğede ne olabilir" olduğu sürece
"bu öğede elde edilenin şu öğede geçerli olması" hiç sorulmaz.

**Yalnız sistematikte olan 69 tehdit** ise senaryoların gördüğü kümenin dışındadır ve sistematik
kümenin **%63,9'unu** oluşturur. Beş senaryo 43 öğenin 26'sına dokunur, ama her öğede yalnız
kendi taşıdığı kategoriyi üretir; dokunulmayan 17 öğe hiç bakılmamış olarak kalır.

Birleşim 120 tehdittir — sistematik kümenin 1,11 katı. İki yöntem birbirinin yerine geçmez;
birleşimin sistematik kümeden büyük olmasının tek sebebi 12 zincir tehdididir.

#### Neyi Kaçırıyor

Dördüncü tablo kaçırılanın nerede durduğunu ayırır. Kaçırma oranı veri akışı öğelerinde en
yüksektir: 48 tehdidin **35'i** kaçar (%72,9). Veri depolarında en düşüktür (%50,0), çünkü beş
senaryonun beşi de bir depoda biter ve depolar senaryoların hedefidir.

Kategori dağılımı daha keskindir. Kaçırılan 69 tehdidin **24'ü hizmet engelleme**, 19'u kurcalama,
11'i inkârdır; kimlik taklidi yalnız üç tehditle en az kaçırılan kategoridir. Sebep senaryo
kurmanın kendi doğasındadır: senaryo bir hedefe **ulaşmayı** anlatır, hizmet engelleme ise hedefe
ulaşmayı değil hizmeti durdurmayı amaçlar. Saldırgan bakışıyla kurulan senaryolar erişim
peşindedir; erişim istemeyen tehdit sınıfı senaryo listesinde kendiliğinden yer almaz.

Bu, senaryo yönteminin ölçülebilir kör noktasıdır. "Saldırganın gözünden bakalım" cümlesi kulağa
kapsayıcı gelir, ama ölçüldüğünde bir kategoriyi neredeyse tamamen dışarıda bırakır.

#### Dakika Başına Bulunan Tehdit

Üçüncü tablo iki yöntemi aynı birimde karşılaştırır. Sistematik üretim 666 dakikada 108 tehdit
bulur: dakikada **0,162**. Senaryo temelli üretim 218 dakikada 51 tehdit bulur: dakikada
**0,234**, yani 1,44 kat daha hızlı.

Bu oran tek başına okunduğunda yanıltıcıdır. Senaryo yönteminin verimli görünmesinin sebebi eleme
yükünün olmamasıdır: senaryo hedeften geriye kurulduğu için ürettiği her tehdit zaten bir yolun
üstündedir ve atılacak satır çıkmaz. Sistematik üretim ise 48 geçersiz tehdit için 72 dakika
harcar. Verimliliği yaratan şey yöntemin zekâsı değil, **arama alanının küçüklüğüdür**.

Son sütun bunun bedelini yazar. Sistematik üretim tek başına kullanıldığında 12 zincir tehdidini
kaçırır; senaryo temelli üretim tek başına kullanıldığında **69** tehdit kaçırır. İkisi birlikte
884 dakikada 120 tehdit verir — dakikada 0,136, yani her iki yöntemden de yavaş. Kapsamanın
tamamlanması dakika verimliliğini düşürür ve bu, ölçümün kendisinin verdiği karardır: **hızlı olan
yöntem eksik olandır.**

#### Özet

- Senaryo, saldırgan profilinden hedefe uzanan bir düğüm dizisidir; beş senaryo 43 öğenin bir
  bölümüne dokunur ve 218 dakikada **51 tehdit** üretir.
- Elli bir tehdidin 39'u öğe tehdidi, **12'si zincir tehdididir**; zincir tehditleri iki düğümün
  birlikte kullanılmasından doğar ve sistematik üretimde hiçbir karşılığı yoktur.
- Kesişim 39'dur; senaryoların bulduğu öğe tehditlerinin tamamı sistematik kümenin içindedir.
  Senaryolar sistematik kümenin **%63,9'unu** (69 tehdit) kaçırır.
- Kaçırılanın kategori dağılımı düzgün değildir: 24'ü hizmet engellemedir, yalnız 3'ü kimlik
  taklididir. Senaryo erişim peşinde olduğu için erişim istemeyen tehdit sınıfını dışarıda bırakır.
- Senaryo yöntemi dakikada 0,234 tehditle sistematik üretimin 1,44 katı hızdadır, ama bu hız
  arama alanının küçüklüğünden gelir; ikisi birlikte 884 dakikada 120 tehdit verir.

#### Sonraki Adım

Zincir tehditleri bu dersin en dikkat çekici bulgusuydu: on iki kalem, hiçbir tek öğede tanımlı
değil ve yalnız yol üzerinde görünüyor. Ama bu ders yolları yalnız **saydı**, aralarında bir
sıralama yapmadı. Beş senaryonun beşi de listede eşit ağırlıkta durur.

Gerçekte yollar eşit değildir. Bir hedefe birden çok yoldan gidilebilir ve bu yolların bazıları
diğerlerinden ucuzdur; savunmanın ilgilendiği şey en pahalı yol değil, **en ucuz yoldur**. Bunu
sayabilmek için senaryoyu düz bir dizi olarak değil, hedeften geriye dallanan bir yapı olarak
yazmak gerekir: kök hedef, alt hedefler ve önkoşullarıyla maliyetleri yazılmış yaprak adımlar.
Sonraki ders bu yapıyı kurar, en ucuz yolun maliyetini hesaplar ve tek soruyu sorar: bir düğümü
kapatmak ağacın maliyetini kaç kat artırır.

### Saldırı Ağaçları

Source: https://academia.sh/tr/kurslar/guvenli-yasam-dongusu/saldiri-agaclari

Hedeften geriye çözümlemenin maliyet ölçümü: 12 yaprak ve üç alt hedeften oluşan ağaçta kök maliyetinin 9 kurgu birim ve en ucuz yolun iki adım olması, 12 yaprağın 10'unu kapatmanın kök maliyetini hiç değiştirmemesi, en verimli tek kapatmanın 2 önlem birimiyle 1,22 kat getirmesi, dört önlem birimlik bir VEYA düğümünün 1,89 kat vermesi, açgözlü sıranın kökü 28 birimde kapatması ve aynı sonucun dal başına bir VEYA düğümü seçilerek 16 birimde alınması.

Önceki dersin en dikkat çekici bulgusu zincir tehditleriydi: on iki kalem, hiçbir tek öğede tanımlı
değil, yalnız yol üzerinde görünüyor. Ama o ders yolları yalnız **saydı**; beş senaryonun beşi de
listede eşit ağırlıkta durdu.

Gerçekte yollar eşit değildir. Bir hedefe birden çok yoldan gidilebilir ve bunların bazıları
diğerlerinden ucuzdur; savunmanın ilgilendiği şey en pahalı yol değil **en ucuz yoldur**. Bunu
sayabilmek için senaryoyu düz bir dizi olarak değil, hedeften geriye dallanan bir yapı olarak
yazmak gerekir. **Saldırı ağacı** bu yapıdır: kök hedef, alt hedefler ve önkoşuluyla maliyeti
yazılmış yaprak adımlar.

#### Kök, Alt Hedef, Yaprak

Aşağıdaki ağaç bir **modeldir**. Yaprak düğümler yalnız **önkoşulu ve kurgu maliyetiyle** anılır;
hiçbir yerde bir adımın nasıl yapıldığı yazılmaz — ağacın savunma tarafındaki değeri zaten
adımın kendisinde değil, adımların **birleşim yapısındadır**. Böyle bir çözümlemenin gerçek bir
sistem üzerinde yürütülmesi, **yazılı yetki ve tanımlı kapsam olmadan hem yasadışı hem meslek
dışıdır**. Maliyet ve önlem sayıları kurgu birimdir; para birimi değildir.

**TD17:** her düğüm ya VEYA (çocuklardan biri yeter), ya VE (hepsi gerekir), ya da yapraktır;
yaprak bir önkoşul, bir maliyet ve bir **önlem bedeli** taşır. **TD18:** VEYA düğümün maliyeti
çocuklarının en küçüğü, VE düğümün maliyeti toplamıdır. **TD19:** kapatılan yaprağın maliyeti
sonsuzdur. **TD20:** en ucuz yol, her VEYA düğümünde en ucuz çocuğun seçildiği yaprak kümesidir.

```js
// tehdit/agac.mjs — saldiri agaci (model): kok hedef, alt hedefler ve yaprak adimlar.
// Yaprak adimlar YALNIZ onkosulu ve kurgu maliyetiyle yazilir; hicbir yerde bir adimin
// nasil yapildigi anlatilmaz. Maliyet ve onlem birimleri kurgudur, para birimi degildir.

// TD17: dugum ya VEYA (cocuklardan biri yeter) ya VE (hepsi gerekir) ya da yapraktir.
// Yaprak "ad onkosul maliyet onlem" tasir: onlem, o yapragi kapatmanin kurgu bedelidir.
export const AGAC = {
  ad: "fatura-kaydinin-degistirilmesi", tip: "VEYA", cocuk: [
    { ad: "depoya-dogrudan-yazma", tip: "VE", cocuk: [
      { ad: "veri-bolgesine-erisim", tip: "VEYA", cocuk: [
        { ad: "yonetim-agindan-erisim", onkosul: "ic-ag-erisimi", maliyet: 8, onlem: 4 },
        { ad: "yedek-kanalindan-erisim", onkosul: "yedek-ucu-acik", maliyet: 12, onlem: 3 }] },
      { ad: "depo-yazma-yetkisi", tip: "VEYA", cocuk: [
        { ad: "servis-kimligi-elde", onkosul: "kimlik-deposu-okunur", maliyet: 15, onlem: 6 },
        { ad: "yetki-atamasi-degisimi", onkosul: "yonetim-yetkisi", maliyet: 20, onlem: 5 }] }] },
    { ad: "faturalama-uzerinden", tip: "VE", cocuk: [
      { ad: "gecerli-abone-oturumu", tip: "VEYA", cocuk: [
        { ad: "abone-kimligini-elde", onkosul: "portal-disa-acik", maliyet: 6, onlem: 7 },
        { ad: "oturum-devralma", onkosul: "belirtec-gorunur", maliyet: 9, onlem: 5 }] },
      { ad: "yetki-denetimini-asma", tip: "VEYA", cocuk: [
        { ad: "nesne-kimligi-degisimi", onkosul: "yetki-karari-istemcide", maliyet: 3, onlem: 2 },
        { ad: "rol-alani-degisimi", onkosul: "rol-istemciden", maliyet: 5, onlem: 2 }] }] },
    { ad: "dogrulayici-cikisi-degisimi", tip: "VE", cocuk: [
      { ad: "olcum-akisina-girme", tip: "VEYA", cocuk: [
        { ad: "sayac-kimligi-taklidi", onkosul: "sayac-kimligi-dogrulanmiyor",
          maliyet: 10, onlem: 9 },
        { ad: "toplama-ucuna-erisim", onkosul: "toplama-ucu-disa-acik",
          maliyet: 14, onlem: 4 }] },
      { ad: "dogrulama-kuralini-asma", tip: "VEYA", cocuk: [
        { ad: "ayar-degisimi", onkosul: "yonetim-akisi-dogrulanmiyor", maliyet: 11, onlem: 3 },
        { ad: "esik-degerini-asma", onkosul: "esik-sabit", maliyet: 7, onlem: 2 }] }] }] };

export const YAPRAK = (d = AGAC) => d.cocuk ? d.cocuk.flatMap((c) => YAPRAK(c)) : [d];

// TD18: VEYA dugumun maliyeti cocuklarinin en kucugu, VE dugumun maliyeti toplamidir.
// TD19: kapatilan yapragin maliyeti sonsuzdur; kapatilan yapraktan gecen her yol kapanir.
export function maliyet(d = AGAC, kapali = []) {
  if (!d.cocuk) return kapali.includes(d.ad) ? Infinity : d.maliyet;
  const c = d.cocuk.map((x) => maliyet(x, kapali));
  return d.tip === "VEYA" ? Math.min(...c) : c.reduce((a, b) => a + b, 0);
}

// TD20: en ucuz yol, her VEYA dugumunde en ucuz cocugun secildigi yaprak kumesidir.
export function enUcuzYol(d = AGAC, kapali = []) {
  if (!d.cocuk) return maliyet(d, kapali) === Infinity ? [] : [d.ad];
  if (d.tip === "VEYA") {
    const en = d.cocuk.reduce((a, b) => maliyet(a, kapali) <= maliyet(b, kapali) ? a : b);
    return maliyet(en, kapali) === Infinity ? [] : enUcuzYol(en, kapali);
  }
  return d.cocuk.flatMap((c) => enUcuzYol(c, kapali));
}
```

```js
// tehdit/kapatma.mjs — en ucuz yolun maliyeti ve bir dugumu kapatmanin koku kac kat
// pahalilastirdigi.
import { AGAC, YAPRAK, maliyet, enUcuzYol } from "./agac.mjs";

const yaz = (g, ...s) => console.log(s.map((v, i) =>
  (g[i] < 0 ? String(v).padEnd(-g[i]) : String(v).padStart(g[i]))).join(""));
const bicim = (x) => (x === Infinity ? "kapali" : String(x));
const kat = (x) => (x === Infinity ? "kapali" : (x / TABAN).toFixed(2));
const yapraklar = YAPRAK();
const TABAN = maliyet();

console.log(`${yapraklar.length} yaprak, ${AGAC.cocuk.length} alt hedef; kok maliyeti ` +
  `${TABAN} birim, en ucuz yol ${enUcuzYol().join(" + ")}`);

const A = [-28, 7, 10, 10, 13];
console.log("\n1. alt hedefler ve maliyetleri");
yaz(A, "alt hedef", "tip", "maliyet", "yaprak", "en ucuz yol");
for (const c of AGAC.cocuk)
  yaz(A, c.ad, c.tip, maliyet(c), YAPRAK(c).length, enUcuzYol(c).length + " adim");

const B = [-24, -28, 9, 8, 10, 7, 11];
console.log("\n2. her yapragi tek tek kapatmak");
yaz(B, "yaprak", "onkosul", "maliyet", "onlem", "yeni kok", "kat", "kat/onlem");
const olcum = yapraklar.map((y) => ({ y, kok: maliyet(AGAC, [y.ad]) }))
  .sort((a, b) => b.kok - a.kok || a.y.onlem - b.y.onlem);
for (const { y, kok } of olcum)
  yaz(B, y.ad, y.onkosul, y.maliyet, y.onlem, kok, kat(kok),
    ((kok - TABAN) / y.onlem).toFixed(2));

const C = [-24, 8, 10, 10, 10, 12];
console.log("\n3. acgozlu kapatma: her turda koku en cok yukselten yaprak");
yaz(C, "kapatilan yaprak", "onlem", "biriken", "yeni kok", "adim kat", "toplam kat");
const kapali = [];
let onlem = 0;
while (maliyet(AGAC, kapali) !== Infinity) {
  const aday = yapraklar.filter((y) => !kapali.includes(y.ad))
    .map((y) => ({ y, kok: maliyet(AGAC, [...kapali, y.ad]) }))
    .sort((a, b) => b.kok - a.kok || a.y.onlem - b.y.onlem)[0];
  const onceki = maliyet(AGAC, kapali);
  kapali.push(aday.y.ad);
  onlem += aday.y.onlem;
  yaz(C, aday.y.ad, aday.y.onlem, onlem, bicim(aday.kok),
    aday.kok === Infinity ? "kapali" : (aday.kok / onceki).toFixed(2), kat(aday.kok));
}
console.log(`koku tamamen kapatmak ${kapali.length} yaprak ve ${onlem} onlem birimi istiyor; ` +
  `kalan ${yapraklar.length - kapali.length} yaprak hicbir acik yolun uzerinde degil`);

// Bir VEYA dugumunun butun yapraklarini kapatmak, o dugumu ve onu iceren VE dalini kapatir.
const veyaDugum = (d = AGAC) => (d.cocuk
  ? [...(d.tip === "VEYA" && d !== AGAC ? [d] : []), ...d.cocuk.flatMap((c) => veyaDugum(c))]
  : []);
const D = [-24, 8, 8, 10, 9, 14];
console.log("\n4. bir VEYA dugumunun tamamini kapatmak");
yaz(D, "VEYA dugumu", "yaprak", "onlem", "yeni kok", "kat", "birim basina");
for (const d of veyaDugum()) {
  const ler = YAPRAK(d), o = ler.reduce((a, y) => a + y.onlem, 0);
  const kok = maliyet(AGAC, ler.map((y) => y.ad));
  yaz(D, d.ad, ler.length, o, bicim(kok), kat(kok),
    kok === Infinity ? "-" : ((kok - TABAN) / o).toFixed(2));
}
const yol = yapraklar.filter((y) => enUcuzYol().includes(y.ad));
console.log(`karsilastirma: en ucuz yolun ${yol.length} yapragini kapatmak ` +
  `${yol.reduce((a, y) => a + y.onlem, 0)} onlem birimi harcar ve koku ` +
  `${maliyet(AGAC, yol.map((y) => y.ad))} birime cikarir`);

// Koku kapatmanin en ucuz yolu: her VE dalindan bir VEYA dugumu secilir, butun bilesimler
// denenir ve toplam onlemi en kucuk olan alinir.
const dalSecenek = AGAC.cocuk.map((dal) => veyaDugum(dal)
  .map((d) => ({ ad: d.ad, ler: YAPRAK(d) })));
let enUcuzKapatma = null;
const dolas = (i, secim) => {
  if (i === dalSecenek.length) {
    const ler = secim.flatMap((s) => s.ler), o = ler.reduce((a, y) => a + y.onlem, 0);
    if (maliyet(AGAC, ler.map((y) => y.ad)) === Infinity &&
      (!enUcuzKapatma || o < enUcuzKapatma.o)) enUcuzKapatma = { secim, o, n: ler.length };
    return;
  }
  for (const s of dalSecenek[i]) dolas(i + 1, [...secim, s]);
};
dolas(0, []);
console.log(`\nen ucuz tam kapatma ${enUcuzKapatma.n} yaprak ve ${enUcuzKapatma.o} onlem ` +
  `birimi (${enUcuzKapatma.secim.map((s) => s.ad).join(", ")}); acgozlu sira ayni sonucu ` +
  `${onlem} birimle veriyor, yani ${(onlem / enUcuzKapatma.o).toFixed(2)} kat pahaliya`);
```

```
12 yaprak, 3 alt hedef; kok maliyeti 9 birim, en ucuz yol abone-kimligini-elde + nesne-kimligi-degisimi

1. alt hedefler ve maliyetleri
alt hedef                       tip   maliyet    yaprak  en ucuz yol
depoya-dogrudan-yazma            VE        23         4       2 adim
faturalama-uzerinden             VE         9         4       2 adim
dogrulayici-cikisi-degisimi      VE        17         4       2 adim

2. her yapragi tek tek kapatmak
yaprak                  onkosul                       maliyet   onlem  yeni kok    kat  kat/onlem
abone-kimligini-elde    portal-disa-acik                    6       7        12   1.33       0.43
nesne-kimligi-degisimi  yetki-karari-istemcide              3       2        11   1.22       1.00
rol-alani-degisimi      rol-istemciden                      5       2         9   1.00       0.00
esik-degerini-asma      esik-sabit                          7       2         9   1.00       0.00
yedek-kanalindan-erisim yedek-ucu-acik                     12       3         9   1.00       0.00
ayar-degisimi           yonetim-akisi-dogrulanmiyor        11       3         9   1.00       0.00
yonetim-agindan-erisim  ic-ag-erisimi                       8       4         9   1.00       0.00
toplama-ucuna-erisim    toplama-ucu-disa-acik              14       4         9   1.00       0.00
yetki-atamasi-degisimi  yonetim-yetkisi                    20       5         9   1.00       0.00
oturum-devralma         belirtec-gorunur                    9       5         9   1.00       0.00
servis-kimligi-elde     kimlik-deposu-okunur               15       6         9   1.00       0.00
sayac-kimligi-taklidi   sayac-kimligi-dogrulanmiyor        10       9         9   1.00       0.00

3. acgozlu kapatma: her turda koku en cok yukselten yaprak
kapatilan yaprak           onlem   biriken  yeni kok  adim kat  toplam kat
abone-kimligini-elde           7         7        12      1.33        1.33
oturum-devralma                5        12        17      1.42        1.89
esik-degerini-asma             2        14        21      1.24        2.33
ayar-degisimi                  3        17        23      1.10        2.56
servis-kimligi-elde            6        23        28      1.22        3.11
yetki-atamasi-degisimi         5        28    kapali    kapali      kapali
koku tamamen kapatmak 6 yaprak ve 28 onlem birimi istiyor; kalan 6 yaprak hicbir acik yolun uzerinde degil

4. bir VEYA dugumunun tamamini kapatmak
VEYA dugumu               yaprak   onlem  yeni kok      kat  birim basina
veri-bolgesine-erisim          2       7         9     1.00          0.00
depo-yazma-yetkisi             2      11         9     1.00          0.00
gecerli-abone-oturumu          2      12        17     1.89          0.67
yetki-denetimini-asma          2       4        17     1.89          2.00
olcum-akisina-girme            2      13         9     1.00          0.00
dogrulama-kuralini-asma        2       5         9     1.00          0.00
karsilastirma: en ucuz yolun 2 yapragini kapatmak 9 onlem birimi harcar ve koku 14 birime cikarir

en ucuz tam kapatma 6 yaprak ve 16 onlem birimi (veri-bolgesine-erisim, yetki-denetimini-asma, dogrulama-kuralini-asma); acgozlu sira ayni sonucu 28 birimle veriyor, yani 1.75 kat pahaliya
```

Sayılar **ölçüm** sınıfındadır; girdileri TD17–TD20'dir.

#### Dokuz Birim

Kök maliyeti **9 birimdir** ve en ucuz yol iki adımdan oluşur. Bu tek sayı, on iki yaprağın
toplam 120 birimlik maliyetiyle hiç ilgili değildir: ağaç bir toplam değil, bir **en küçük
seçimdir**.

Birinci tablo bunu üç dala böler. Doğrudan depoya yazma 23 birim, doğrulayıcı çıkışını değiştirme
17 birim, faturalama üzerinden gitmek **9 birim**. Üç dalın da dört yaprağı ve iki adımlık en ucuz
yolu vardır; aradaki farkı üreten şey yaprak sayısı değil, yaprak maliyetleridir. Kök bir VEYA
düğümü olduğu için üçünün en küçüğünü alır — yani ağacın maliyetini **en zayıf dal belirler**.

Bu, savunma tarafında sık yapılan bir hesap hatasını doğrudan gösterir. Doğrudan depoya yazmayı
zorlaştırmak için harcanan çaba kök maliyetini hiç değiştirmez, çünkü o dal zaten en pahalı
daldır ve saldıran taraf onu seçmez. **Ağaç, hangi işin boşa gittiğini yazan bir yapıdır.**

#### On İki Yaprağın Onu Hiçbir Şey Değiştirmiyor

İkinci tablo her yaprağı tek tek kapatır. Sonuç serttir: **on iki yaprağın onunda kök maliyeti
9'da kalır**, kat 1,00'dır. Yalnız iki yaprak bir şey değiştirir —
`abone-kimligini-elde` kapatıldığında kök 12'ye çıkar (1,33 kat), `nesne-kimligi-degisimi`
kapatıldığında 11'e (1,22 kat). İkisi de en ucuz yolun üzerindedir; geri kalan on yaprak değildir.

Son sütun önlem birimi başına getiriyi verir ve sıralamayı tersine çevirir.
`abone-kimligini-elde` 7 önlem birimine karşılık 3 birimlik artış sağlar: birim başına 0,43.
`nesne-kimligi-degisimi` ise 2 önlem birimine karşılık 2 birimlik artış: birim başına **1,00**.
Daha küçük kat veren kapatma, ödenen birim başına iki buçuk kat daha verimlidir.

En pahalı önlemler en verimsizleridir. `sayac-kimligi-taklidi` 9 önlem birimi ister ve kök
maliyetini hiç değiştirmez; `servis-kimligi-elde` 6 birim ister ve yine hiçbir şey değiştirmez.
Bir tehdit modelleme çıktısında bu iki satır muhtemelen "yüksek öncelikli" görünürdü — ikisi de
gerçek bir açığa karşılık gelir. Ağaç üzerinde ölçüldüğünde ikisinin de kök maliyetine katkısı
sıfırdır, **çünkü ikisi de zaten en pahalı dalın üzerindedir**.

#### VEYA Düğümünü Kapatmak

Dördüncü tablo kapatmayı yaprak yerine düğüm düzeyinde yapar. Bir VEYA düğümünün bütün
yapraklarını kapatmak o düğümü kapatır ve onu içeren VE dalını tamamen ortadan kaldırır.

Altı VEYA düğümünden yalnız ikisi kök maliyetini değiştirir ve ikisi de faturalama dalındadır:
`gecerli-abone-oturumu` (12 önlem birimi) ve `yetki-denetimini-asma` (**4 önlem birimi**). İkisi
de kökü 17'ye çıkarır — **1,89 kat**. Aynı sonuç için biri ötekinin üç katı bedel
ister; birim başına getiri 0,67'ye karşılık **2,00**'dır.

Karşılaştırma satırı asıl kararı verir. En ucuz yolun iki yaprağını kapatmak 9 önlem birimi harcar
ve kökü 14'e çıkarır. `yetki-denetimini-asma` düğümünün iki yaprağını kapatmak **4 birim** harcar
ve kökü 17'ye çıkarır. Daha az harcayan seçim daha çok kazandırır, çünkü en ucuz yolun yaprakları
iki ayrı VEYA düğümüne dağılmıştır ve her birinin yerine geçecek bir kardeş yaprak vardır.
**Yaprak kapatmak yolu kaydırır; VEYA düğümü kapatmak dalı yok eder.**

#### Kökü Tamamen Kapatmak

Üçüncü tablo açgözlü sırayı yürütür: her turda kökü en çok yükselten yaprak kapatılır. Altı yaprak
ve **28 önlem birimi** sonunda kök kapanır; kalan altı yaprak hiçbir açık yolun üzerinde değildir.
Ara değerler 12, 17, 21, 23, 28 diye ilerler, ama adım katları düzgün azalmaz:
1,33 · 1,42 · 1,24 · 1,10 · 1,22. Bir kapatmanın getirisi bir öncekine değil, kalan açık yolların
yapısına bağlıdır.

Son satır bu sıranın verimsizliğini ölçer. Her VE dalından bir VEYA düğümü seçilerek yapılan tam
kapatma da altı yaprak kapatır, ama **16 önlem birimi** harcar. Açgözlü sıra aynı sonucu
**1,75 kat pahalıya** verir.

Sebep tablo 3'ün ilk satırındadır. Açgözlü seçim `abone-kimligini-elde` ile başlar çünkü kökü en
çok o yükseltir — ama o yaprağın önlem bedeli 7'dir ve aynı dalı `yetki-denetimini-asma` üzerinden
kapatmak 4 birim tutardı. **Her turda en çok kazandıran hamleyi seçmek, toplam bedeli en küçük
yapan seçimi vermez**; ağaçta seçimlerin bedeli birbirini etkiler ve kalem kalem sıralama bunu
göremez.

#### Özet

- Saldırı ağacında ölçülen sayı yaprak sayısı değil **kök maliyetidir**: 12 yaprak ve üç alt
  hedeften oluşan ağaçta kök 9 kurgu birim, en ucuz yol iki adımdır. Kök bir VEYA düğümüdür,
  yani maliyeti en zayıf dal belirler.
- On iki yaprağın **onu tek tek kapatıldığında kök maliyeti hiç değişmez**; yalnız en ucuz yolun
  üstündeki iki yaprak 1,33 ve 1,22 kat verir.
- Önlem birimi başına getiri sıralamayı tersine çevirir: 1,33 kat veren kapatma birim başına 0,43,
  1,22 kat veren kapatma birim başına 1,00 getirir.
- Bir VEYA düğümünün tamamını kapatmak dalı yok eder; 4 önlem birimlik bir düğüm kökü 1,89 kata
  çıkarırken en ucuz yolun iki yaprağı 9 birim harcayıp yalnız 1,56 kat verir.
- Kökü tamamen kapatmak açgözlü sırayla 28, dal başına bir VEYA düğümü seçilerek **16** önlem
  birimi tutar; her turda en çok kazandıran hamle toplamda 1,75 kat pahalıdır.

#### Sonraki Adım

Bu konu beş derste bir tehdit listesi ve bir öncelik sırası üretti: 23 sınır geçişi, 58 kalem, 108
sistematik tehdit, 12 zincir tehdidi ve kök maliyetini gerçekten değiştiren birkaç kapatma. Bütün
bu sayılar **modelin içinde** duruyor.

Modelin içinde durdukları sürece hiçbir şey değişmez. Bir karşı önlem ancak birinin üzerine
alındığı, bir kabul ölçütüne bağlandığı ve bir sürüme yazıldığı zaman koda dönüşür; bunlardan biri
eksikse iş öğesi hiç açılmaz ve kalem sessizce kaybolur. Sonraki ders model çıktısını iş öğesine
çevirir ve son ölçümü yapar: kaç tehdit kaç ayrı karşı önleme düşüyor, bunların kaçı gerçekten
planlanıyor, kaçı hangi eksikten kayboluyor ve geriye kalan artık riskin kaç kalemi **yazılı olarak
kabul ediliyor**.

### Model Çıktısının Kullanımı

Source: https://academia.sh/tr/kurslar/guvenli-yasam-dongusu/model-ciktisinin-kullanimi

Model çıktısının iş öğesine dönüşmesi ölçülür: 120 tehdit 24 karşı önleme düşer, bunların yalnız 11'i sahip, kabul ölçütü ve sürüm hedefinin üçünü birden taşıyıp iş öğesine döner ve 73 tehdidi (%60,8) kapatır; kaybolan 13 kalem 47 tehdit ve 97 efor günü taşır, 4'ü yazılı olarak kabul edilir, 9'u sessiz artık risk olarak kalır ve tek başına 33 tehdit taşır.

Önceki beş ders bir tehdit listesi ve bir öncelik sırası üretti: 23 sınır geçişi, 58 kalem, 108
sistematik tehdit, 12 zincir tehdidi ve kök maliyetini gerçekten değiştiren birkaç kapatma.
Bütün bu sayılar modelin içinde duruyor.

Modelin içinde durdukları sürece hiçbir şey değişmez. Bir karşı önlem ancak birinin üzerine
alındığı, bir kabul ölçütüne bağlandığı ve bir sürüme yazıldığı zaman koda dönüşür. Bu ders son
ölçümü yapar: kaç tehdit kaç ayrı karşı önleme düşüyor, bunların kaçı gerçekten planlanıyor,
kaçı hangi eksiklikten kayboluyor ve geriye kalan artık riskin kaç kalemi yazılı olarak kabul
ediliyor.

#### Yüz Yirmi Tehdit, Yirmi Dört Karşı Önlem

Aşağıdaki liste bir **modeldir** ve gerçek bir kayıt değildir. Karşı önlemler yalnız kapsadıkları
tehdit sayısı, efor günü ve üç alanın doluluğuyla anılır.

**TD21:** bir karşı önlem birden çok tehdidi birden kapatır; önceki iki dersin birleşim kümesi
120 tehditti ve bu sütunun toplamı onunla doğrulanır. **TD22:** bir karşı önlem iş öğesine ancak
üç alanı birden doluysa döner — **sahip**, **kabul ölçütü** ve **sürüm hedefi**; biri bile eksikse
kalem kaybolur. **TD23:** kaybolan kalem, taşıdığı **artık riskin (residual risk)** yazılı kabulü
varsa kayıtlıdır, yoksa sessizdir.

```js
// tehdit/onlem.mjs — model ciktisinin is ogesine cevrilmesi (model): kurgu olcum agi
// yaziliminin tehdit modelleme oturumundan cikan karsi onlem listesi. Gercek bir kayit
// degildir; hicbir saldiri adimi tasimaz.

// TD21: bir karsi onlem birden cok tehdidi birden kapatir; `tehdit` o sayidir. Onceki iki
// dersin birlesim kumesi 120 tehditti ve bu sutunun toplami onunla dogrulanir.
// TD22: bir karsi onlem is ogesine ancak uc alani birden doluysa doner: `sahip`, kabul
// `olcut`u ve `surum` hedefi. Biri bile eksikse kalem kaybolur.
// TD23: kaybolan kalem, artik riskin yazili `kabul`u varsa kayitlidir, yoksa sessizdir.
// `agac` sutunu, o onlemin saldiri agacinda kok maliyetini degistirip degistirmedigidir.
export const ONLEM = `
  sinir-gecisinde-girdi-dogrulama  17  8  E E E - H
  sinir-gecisinde-kaynak-kimligi   17 10  E E E - H
  depoya-yazmada-yetkilendirme      9  5  E E E - H
  gizli-sinifta-aktarim-korumasi    9  4  E E E - H
  disa-cikan-veride-suzme           6  6  E H E H H
  yetki-kararini-sunucuya-tasima    5  9  E E E - E
  rol-alanini-istemciden-almama     4  3  E E E - E
  oturum-belirtecini-gizleme        4  5  E E H E E
  sayac-kimligini-dogrulama         4 12  E H H E H
  toplama-ucunu-daraltma            4  6  E E H H H
  dogrulayici-ayarini-imzalama      3  7  H H H H H
  esik-degerini-veriye-baglama      3  4  E E E - H
  denetim-gunlugune-yazma-zorunlu   4  6  E E H E H
  gunlugu-degistirilemez-tutma      3  8  H H H H H
  yedek-ucunu-kapatma               2  2  E E E - H
  yonetim-agini-ayirma              4 11  H E H H H
  servis-kimligini-dondurme         3  7  E H H H H
  yetki-atamasini-onaya-baglama     2  5  E E E - H
  rapor-ucuna-kimlik-zorunlulugu    3  3  E E E - H
  abone-portalinda-hiz-siniri       2  2  E E E - E
  olcum-akisinda-butunluk-etiketi   4  9  H E H H H
  zincir-adiminda-yeniden-dogrulama 4 10  H H H H H
  saha-uygulamasinda-sir-tutmama    2  4  E E H E H
  kapasite-korumasi-toplama-ucunda  2  6  E H H H H`
  .trim().split("\n").map((r) => {
    const [ad, tehdit, efor, sahip, olcut, surum, kabul, agac] = r.trim().split(/\s+/);
    return { ad, tehdit: +tehdit, efor: +efor, sahip: sahip === "E", olcut: olcut === "E",
      surum: surum === "E", kabul: kabul === "E", agac: agac === "E" };
  });

export const ALAN = ["sahip", "olcut", "surum"];
export const isOgesi = (o) => ALAN.every((a) => o[a]);
export const TEHDIT = ONLEM.reduce((a, o) => a + o.tehdit, 0);
```

```js
// tehdit/isogesi.mjs — kac karsi onlem gercekten planlaniyor, kaci kayboluyor, artik riskin
// kac kalemi yazili olarak kabul ediliyor.
import { ONLEM, ALAN, isOgesi, TEHDIT } from "./onlem.mjs";

const yaz = (g, ...s) => console.log(s.map((v, i) =>
  (g[i] < 0 ? String(v).padEnd(-g[i]) : String(v).padStart(g[i]))).join(""));
const topla = (ler, f) => ler.reduce((a, o) => a + f(o), 0);
const donen = ONLEM.filter(isOgesi), kaybolan = ONLEM.filter((o) => !isOgesi(o));

console.log(`${TEHDIT} tehdit ${ONLEM.length} karsi onleme dusuyor (onlem basina ` +
  `${(TEHDIT / ONLEM.length).toFixed(2)} tehdit); is ogesine donen ${donen.length}, ` +
  `kaybolan ${kaybolan.length}`);

const A = [-10, 8, 8, 15, 13];
console.log("\n1. uc alanin doluluk denetimi");
yaz(A, "alan", "dolu", "eksik", "eksik tehdit", "eksik efor");
for (const a of ALAN) {
  const e = ONLEM.filter((o) => !o[a]);
  yaz(A, a, ONLEM.length - e.length, e.length, topla(e, (o) => o.tehdit),
    topla(e, (o) => o.efor));
}

const B = [-16, 8, 10, 11, 10, 11];
console.log("\n2. model ciktisi is ogesine donerken");
yaz(B, "kume", "onlem", "onlem %", "tehdit", "tehdit %", "efor gunu");
for (const [ad, ler] of [["is ogesine donen", donen], ["kaybolan", kaybolan],
  ["toplam", ONLEM]])
  yaz(B, ad, ler.length, ((ler.length / ONLEM.length) * 100).toFixed(1),
    topla(ler, (o) => o.tehdit), ((topla(ler, (o) => o.tehdit) / TEHDIT) * 100).toFixed(1),
    topla(ler, (o) => o.efor));

const C = [-22, 8, 10, 12];
console.log("\n3. kaybolan kalemler hangi alan eksikliginden kayboluyor");
yaz(C, "eksik alan bilesimi", "onlem", "tehdit", "efor gunu");
const bilesim = {};
for (const o of kaybolan) {
  const e = ALAN.filter((a) => !o[a]).join("+");
  (bilesim[e] ||= []).push(o);
}
for (const [e, ler] of Object.entries(bilesim).sort((x, y) => y[1].length - x[1].length))
  yaz(C, e, ler.length, topla(ler, (o) => o.tehdit), topla(ler, (o) => o.efor));

const D = [-22, 8, 10, 12, 15];
console.log("\n4. kaybolan kalemin artik risk karsiligi");
yaz(D, "kume", "onlem", "tehdit", "tehdit %", "tehdit/onlem");
for (const [ad, ler] of [["yazili kabul edilen", kaybolan.filter((o) => o.kabul)],
  ["sessiz artik risk", kaybolan.filter((o) => !o.kabul)]])
  yaz(D, ad, ler.length, topla(ler, (o) => o.tehdit),
    ((topla(ler, (o) => o.tehdit) / TEHDIT) * 100).toFixed(1),
    (topla(ler, (o) => o.tehdit) / ler.length).toFixed(2));

const agacli = ONLEM.filter((o) => o.agac);
console.log(`saldiri agacinda kok maliyetini degistiren ${agacli.length} onlemin ` +
  `${agacli.filter(isOgesi).length} tanesi is ogesine dondu, ` +
  `${agacli.filter((o) => !isOgesi(o)).length} tanesi kayboldu`);
const enBuyuk = [...kaybolan].sort((a, b) => b.tehdit - a.tehdit)[0];
console.log(`en cok tehdit tasiyan kaybolan kalem ${enBuyuk.ad} (${enBuyuk.tehdit} tehdit, ` +
  `${enBuyuk.efor} efor gunu); kaybolan ${kaybolan.length} kalemin ortalama eforu ` +
  `${(topla(kaybolan, (o) => o.efor) / kaybolan.length).toFixed(1)} gun, donen ` +
  `${donen.length} kalemin ${(topla(donen, (o) => o.efor) / donen.length).toFixed(1)} gun`);
```

```
120 tehdit 24 karsi onleme dusuyor (onlem basina 5.00 tehdit); is ogesine donen 11, kaybolan 13

1. uc alanin doluluk denetimi
alan          dolu   eksik   eksik tehdit   eksik efor
sahip           19       5             18           45
olcut           17       7             25           56
surum           12      12             41           91

2. model ciktisi is ogesine donerken
kume               onlem   onlem %     tehdit  tehdit %  efor gunu
is ogesine donen      11      45.8         73      60.8         55
kaybolan              13      54.2         47      39.2         97
toplam                24     100.0        120     100.0        152

3. kaybolan kalemler hangi alan eksikliginden kayboluyor
eksik alan bilesimi      onlem    tehdit   efor gunu
surum                        4        14          21
olcut+surum                  3         9          25
sahip+olcut+surum            3        10          25
sahip+surum                  2         8          20
olcut                        1         6           6

4. kaybolan kalemin artik risk karsiligi
kume                     onlem    tehdit    tehdit %   tehdit/onlem
yazili kabul edilen          4        14        11.7           3.50
sessiz artik risk            9        33        27.5           3.67
saldiri agacinda kok maliyetini degistiren 4 onlemin 3 tanesi is ogesine dondu, 1 tanesi kayboldu
en cok tehdit tasiyan kaybolan kalem disa-cikan-veride-suzme (6 tehdit, 6 efor gunu); kaybolan 13 kalemin ortalama eforu 7.5 gun, donen 11 kalemin 5.0 gun
```

Sayılar **ölçüm** sınıfındadır; girdileri TD21–TD23'tür.

#### Beşe Bir Birleşme

İlk sayı birleşme oranıdır. Yüz yirmi tehdit **24 karşı önleme** düşer; karşı önlem başına 5,00
tehdit. Bu, tehdit sayısının tek başına bir iş yükü ölçüsü olmadığını gösterir: `120 tehdit`
kulağa iki aylık bir yığın gibi gelir, karşılığı olan iş kalemi ise yirmi dörttür.

Birleşme düzgün dağılmaz. İlk iki karşı önlem — sınır geçişinde girdi doğrulama ve kaynak
kimliği — tek başlarına **34 tehdit** kapatır, yani listenin %28,3'ünü. Bunun sebebi ikinci
derste görülmüştü: kalemlerin %58,6'sı düşük güven düzeyinden yükseğe giden akışlardan geliyordu
ve bu akışların hepsi aynı iki denetimi istiyordu. Karşılık verilen soru "kaç tehdit var" değil,
"**kaç ayrı karar var**" sorusudur.

#### Sürüm Hedefi Olmayan Kalem

İkinci tablo dersin ana ölçümüdür. Yirmi dört karşı önlemin yalnız **11'i** üç alanı birden
taşır ve iş öğesine döner; 13'ü kaybolur. Kalem sayısı olarak dönüşüm oranı %45,8'dir.

Tehdit sayısıyla bakıldığında tablo daha iyi görünür: dönen 11 kalem **73 tehdit** kapatır, yani
%60,8'ini. Aradaki fark birleşme oranından gelir — dönen kalemler ortalama olarak daha çok tehdit
taşıyanlardır, çünkü en kalabalık iki karşı önlem de dönenler arasındadır.

Birinci tablo hangi alanın darboğaz olduğunu doğrudan yazar. Sahip alanı 24 kalemin 19'unda
doludur, kabul ölçütü 17'sinde, **sürüm hedefi yalnız 12'sinde**. Sürüm hedefi eksik olan 12 kalem
41 tehdit ve 91 efor günü taşır. Sahip bulmak kolaydır; ölçüt yazmak biraz daha zordur; kalemi bir
sürüme sokmak en zorudur, çünkü orada karşısına başka işler çıkar.

Üçüncü tablo aynı sonuca kalem düzeyinde varır. Kaybolan 13 kalemin **4'ü yalnız sürüm hedefi
eksik olduğu için** kaybolur — sahibi vardır, ölçütü yazılmıştır, tek eksiği takvimdir. Bu dört
kalem 14 tehdit taşır ve toplam 21 efor günüdür. Yalnız kabul ölçütü eksik olan tek bir kalem
vardır. Üç alanı birden boş olan üç kalem ise oturumda hiç sahiplenilmemiş kalemlerdir.

#### Kaybolan Kalem Nereye Gidiyor

Son satır kaybın yönünü verir ve beklenenin tersini söyler. Kaybolan 13 kalemin ortalama eforu
**7,5 gün**, iş öğesine dönen 11 kalemin ortalama eforu **5,0 gündür**. Yani pahalı kalemler daha
sık kaybolur.

Bu, üç alanın hangi sırayla dolduğuyla açıklanır. Bir kalemin sürüm hedefi alması için birinin onu
bir sprintin içine koyması gerekir; efor günü büyüdükçe bu karar zorlaşır ve kalem "sonraki
sürüme" kayar. Kayma bir kez olduğunda kalem tabloda hiçbir yerde bir sıfır olarak görünmez —
yalnızca hiçbir sürümde bulunmaz.

Ağaç ölçümüyle kesişim tek satırda görülür. Saldırı ağacında kök maliyetini gerçekten değiştiren
**4 karşı önlemin 3'ü** iş öğesine döndü, biri kayboldu. Bu iyi bir orandır, ama tesadüfidir:
o dört kalemin eforları 9, 3, 5 ve 2 gündür, yani listenin ucuz ucundadır. Aynı kalemler pahalı
olsaydı aynı süreç onları da eleyecekti. **Sürecin seçtiği ölçüt etki değil, efordur.**

#### Sessiz Artık Risk

Dördüncü tablo kursun son ayrımını yapar. Kaybolan 13 kalemin **4'ü yazılı olarak kabul
edilmiştir**: karşı önlem yapılmayacaktır, bunun taşıdığı artık risk bilinmekte ve kayda
geçirilmektedir. Bu dört kalem 14 tehdit taşır, yani toplamın %11,7'sini.

Kalan **9 kalem sessiz artık risktir**. Ne iş öğesine dönmüştür, ne de yapılmayacağı bir yere
yazılmıştır. Taşıdıkları **33 tehdit**, toplam kümenin %27,5'idir. Kalem başına taşınan tehdit
sayısı iki kümede neredeyse aynıdır (3,50 ve 3,67); yani sessiz kalanlar daha küçük kalemler
değildir, yalnız **hakkında karar verilmemiş** kalemlerdir.

Aradaki fark ölçüm açısından belirleyicidir. Yazılı kabul edilen artık risk bir karardır: bir
kalem, bir sahip, bir gerekçe ve bir tarih taşır; sonraki oturumda yeniden bakılabilir. Sessiz
artık risk bir karar değildir; kimsenin bilmediği bir eksikliktir ve bir sonraki tehdit modelleme
oturumu onu sıfırdan yeniden üretmek zorunda kalır. **Bir tehdit modelleme oturumunun çıktısı,
iş öğesine dönen kalemler ile yazılı olarak reddedilen kalemlerin toplamıdır; geri kalan
üretilmemiş sayılır.**

#### Özet

- 120 tehdit 24 karşı önleme düşer (önlem başına 5,00); en kalabalık iki karşı önlem tek başına
  34 tehdit kapatır. İş yükünün ölçüsü tehdit sayısı değil **ayrı karar sayısıdır**.
- Yirmi dört karşı önlemin yalnız 11'i sahip, kabul ölçütü ve sürüm hedefinin üçünü birden taşır;
  dönüşüm oranı kalem olarak %45,8, tehdit olarak %60,8'dir.
- Darboğaz sürüm hedefidir: 12 kalemde eksiktir ve 41 tehdit ile 91 efor günü taşır. Kaybolan 13
  kalemin dördü **yalnız** sürüm hedefi eksik olduğu için kaybolur.
- Kaybolan kalemlerin ortalama eforu 7,5 gün, dönenlerin 5,0 gündür; süreç etkiye göre değil
  **efora göre** eler. Kök maliyetini değiştiren dört karşı önlemin üçü dönmüştür, ama bu onların
  ucuz olmasındandır.
- Kaybolan 13 kalemin 4'ü yazılı olarak kabul edilir (14 tehdit), **9'u sessiz artık risktir** ve
  toplam kümenin %27,5'ini taşır; kalem başına taşıdıkları tehdit dönenlerle aynı büyüklüktedir.

#### Kurs Kapanışı

| Ders | Kalem hangi aşamada doğuyor | Hangi aşamada yakalanıyor | Yakalamanın bedeli |
|---|---|---|---|
| DevSecOps ve DevOps Farkı | 23 kalem, altı aşamada, en çok kod (7) | tek kapıda 10, dağıtık denetimde 23; gecikme 1,94→0,13 aşama | 200 uyarının 177'si yanlış pozitif |
| Sola Kaydırma | ortak 18 kalem, gereksinimden dağıtıma | geç akış 318 saat, erken akış 68 saat; kat 4,68 | 32,5 saat denetim yükü, net kazanç 217,5 saat |
| Güvenlik Gereksinimleri | gereksinim aşaması, senaryolarla 28 gereksinim | kodda 19 otomatik, dağıtımda 5 gözle, 4'ü hiç | 300 denetimde 40 saat gözle sınama |
| Güvenlik Şampiyonları | kod aşaması, haftada 35 inceleme | merkezde 16, dört şampiyonla 35 | 2,8 kişi eşdeğeri; derin kalem 2'den 1'e |
| Risk Temelli Önceliklendirme | 23 kalemlik yığın, 68 gün efor | 22 günde doğuş sırası 6, efor sırası 13 kalem | 5 kalem her ölçütte dışarıda, 110 saat |
| Tehdit Modellemenin Amacı | 18 kalem, 10'u gereksinim ve tasarımda | oturum 10 kalemi tasarımda, 8 kalem 1–3 aşama geç | 40 geliştirici saati, kalem başına 4,0 saat |
| Veri Akış Diyagramları | tasarım, 26 akışın 23'ü sınır geçiyor | 58 kalem tasarımda; kaba çizimde yalnız 15 | 16 geçiş görünmez, 43 kalem doğmuyor |
| Tehdit Sınıflandırma Yöntemleri | tasarım, 43 çizge öğesi | 156 ham üretimden 108 anlamlı, tasarımda | 666 dakika; 72'si geçersiz eleme |
| Risk Odaklı Modelleme | tasarım, 12 zincir tehdidi yol üzerinde | 51 tehdit; sistematiğin %63,9'u kaçıyor | 218 dakika; hizmet engellemede 24 kalem dışarıda |
| Saldırı Ağaçları | tasarım, 12 yaprak, kök 9 birim | 10 yaprak kökü hiç değiştirmiyor, 2'si 1,33 ve 1,22 kat | tam kapatma 16 önlem birimi, açgözlü sıra 28 |
| Model Çıktısının Kullanımı | tasarım, 120 tehdit, 24 karşı önlem | 11 iş öğesi, 73 tehdit (%60,8) | 13 kalem kayboldu, 9'u sessiz (33 tehdit) |

Kursun kuralı on bir satırın tamamında aynıdır: **güvenlik bir aşama değil, her aşamada farklı
fiyatı olan bir karardır.** Erken yakalamanın kazancı sayılabilir — 4,68 kat, 217,5 saat, 866
saat — ama aynı ölçüm her seferinde ikinci bir sayı üretti: tasarımda görülemeyecek bir kalem
sınıfı vardır ve o sınıf küçük değildir. Sola kaydırmanın hiç dokunamadığı 7 kalem, tasarım
oturumunun bulmadığı 8 kalem ve sistematik üretimin göremediği 12 zincir tehdidi aynı şeyi söyler.
**Bedeli yazılmayan denetim ölçülmemiş sayılır; kapsama sınırı yazılmayan yöntem de öyle.**

Son ders bir eşiği işaretledi. Tasarımda hangi tehdidin doğduğu yazıldı, hangi karşı önlemin
planlandığı sayıldı ve hangilerinin kaybolduğu ölçüldü. Ama planlanan 11 karşı önlemin **koda
dönüştüğü yer** hiç görülmedi: bir "sınır geçişinde girdi doğrulama" kalemi kod tabanında kaç
noktaya karşılık gelir, o noktaların kaçı gerçekten kapanır ve kaçı bu kararın tamamen dışında
kalır. **M25/K02 Güvenli Kodlama** bu soruyla başlar — bir savunma kalıbının kendiliğinden
kapattığı nokta sayısı ile hiç kimsenin bakmadığı noktaların sayısı.

