---
title: 'Çalışma Zamanı Güvenliği ve Sır Yönetimi'
source: 'https://academia.sh/tr/kurslar/calisma-zamani-guvenligi'
language: tr
updated: '2026-08-17T04:38:37+00:00'
license: 'CC BY-SA 4.0'
lessons: 15
outcomes:
    - 'Üretim ortamında uygulama düzeyi savunma katmanları kurar ve yanlış pozitifini birlikte ölçer'
    - 'Sır yaşam döngüsünü otomatik yönetir ve açık pencereyi sayıyla daraltır'
    - 'İş yükü kimliği ve ağ politikalarıyla yanal hareket yollarını sayarak sınırlar'
---

# Çalışma Zamanı Güvenliği ve Sır Yönetimi

Bir kalemi yakalamanın en pahalı olduğu aşamada kurulan savunma katmanları ve her katmanın daha erken nerede kapatılabileceği: uygulama katmanı güvenlik duvarının yakaladığı, kaçırdığı ve yanlış yere kestiği istek, hız sınırlama pencerelerinin meşru tepe yükünü kesmesi, kimlik bilgisi doldurma savunmasında eşik seçimi, güvenlik başlıklarının sunucudan yönetilmesiyle kapsanan uygulama sayısı, uygulama düzeyinde anormallik tespiti, sır deposu mimarisi ve erişim denetimi, kısa ömürlü kimlik bilgilerinin açık pencereyi daraltması, anahtar döndürmede iki sırrın birlikte geçerli olduğu süre, iş yükü kimliğinin ortadan kaldırdığı statik sır, sızıntı sonrası iptal akışı, servisler arası kimlik doğrulamayla yanal hareketin sınırlanması, konteyner çalışma zamanında anormal süreç davranışı, kabul denetleyicileri, sürekli yapılandırma denetimi ve yeniden inşa temelli güncelleme.

## Uygulama Savunması

Çalışma zamanında istek katmanına konan savunmaların yakaladığı, kaçırdığı ve yanlış yere kestiği isteğin aynı koşumda sayılması: hazır kural kümesinin puan eşiğine göre üç sayının birlikte hareketi, üç hız sınırı penceresinin meşru tepe yükünden kestiği istek, kimlik bilgisi doldurmaya karşı hesap ve adres eşiklerinin ayrı ayrı gördüğü saldırı biçimi, güvenlik başlıklarının sunucudan yönetilmesiyle kapsanan uygulama ve dışarıda kalan uç sayısı, uygulama düzeyinde anormallik puanlamasının taban çizgisinden sapan oturumu kaç dakika gecikmeyle işaretlediği ve her kalemin daha erken hangi aşamada kapatılabileceği.

### Web Uygulaması Güvenlik Duvarı

Source: https://academia.sh/tr/kurslar/calisma-zamani-guvenligi/web-uygulamasi-guvenlik-duvari

Hazır bir kural kümesinin kurgu bir günlük istek kümesinde koşturulması ve üç sayının ayrı ayrı yazılması: durdurulan kötü istek, kaçan kötü istek ve yanlış yere kesilen meşru istek; puan eşiği düşürüldüğünde üçünün nasıl birlikte hareket ettiği, muafiyet yazmanın aynı üç sayıyı hangi bedelle geri getirdiği ve durdurulan hacmin ne kadarının daha ucuz bir aşamada kapatılabileceği.

Önceki kurs kodu taradı, bileşenleri envanterledi ve yapı çıktısını imzaladı; bütün o denetimler
dağıtımdan önce durdu. Uygulama çalışmaya başladığı andan itibaren onu neyin koruduğu ise hiç
sorulmadı. Bu konu o soruyu istek katmanında yanıtlıyor ve ilk ders ölçünün kendisini kuruyor.

Çalışma zamanı, bir kalemi yakalamanın en pahalı olduğu aşamadır: kalem üretimdedir, isteği
gerçek bir abone göndermektedir ve savunma karar vermek için milisaniyeye sahiptir. Bu yüzden
"uygulama katmanı güvenlik duvarı konmalıdır" cümlesi tek başına karar taşımaz. Karar taşıyan
şey üç sayıdır ve üçü **aynı koşumdan** okunmalıdır: kaç kötü istek durduruldu, kaç kötü istek
geçti, kaç meşru istek yanlış yere kesildi. Üçüncüsü yazılmadığında ilk ikisi bir şey ölçmez.

#### Kural Kümesi Neye Bakıyor

Bölgesel ölçüm ağının abone portalı ile saha uygulaması aynı üretim ortamında duruyor. Önlerine
bir uygulama katmanı güvenlik duvarı konuyor ve hazır bir kural kümesiyle başlatılıyor: her kural
istekte belirli bir **belirtiyi** arar, eşleştiğinde bir puan yazar, isteğin toplam puanı eşiği
aşarsa istek durdurulur. Aşağıdaki her şey `node` ile kurulan bir modeldir; gerçek trafik
üretilmiyor, gerçek bir yük ya da atlatma dizgesi yazılmıyor.

- **US1.** On bir istek sınıfı, günlük sayıları, beş uç ve on kural kurgusal ölçüm ağına aittir.
- **US2.** Bir isteğin gerçek sınıfı (meşru ya da kötü) modelde bilinir. Üretimde bu sınıf ancak
  inceleme sonrası bilinir; modelde bilindiği varsayılıyor ki yanlış kesilen istek sayılabilsin.
- **US3.** Bir sınıfın taşıdığı belirti kümesi sabittir; aynı sınıftaki her istek aynı puanı alır.
  Gerçekte puan istek başına dağılır, bu dağılım eşik seçimini yumuşatır, yönünü değiştirmez.
- **US4.** Bir kural, aradığı etiketlerin **hepsi** varsa eşleşir. Belirti etiketleri bir söz
  dizimini değil, savunmanın gördüğü yüzeysel bir özelliği adlandırır.
- **US5.** "Daha erken kapatma aşaması" sütunu her kötü sınıf için elle işaretlendi: kalem
  tasarımda mı, kodda mı kapatılabilirdi, yoksa hiçbir erken aşamada kapatılamaz mı.

```js
// istek.mjs — bir gunluk istek kumesi ve hazir kural kumesi; model, gercek trafik degil
// [ad, gercek sinif, gunluk sayi, belirti etiketleri, uc, daha erken kapatma asamasi]
export const SINIF = [
  ['abone sorgu formu', 'mesru', 84000, [], '/portal/sorgu', '-'],
  ['saha uygulamasi toplu yukleme', 'mesru', 5400, ['uzun-govde', 'kodlanmis-alan'], '/saha/yukleme', '-'],
  ['rapor filtresi, serbest metin', 'mesru', 2600, ['tirnak', 'anahtar-sozcuk'], '/portal/rapor', '-'],
  ['fatura ekinde dosya adi', 'mesru', 900, ['yol-ayraci'], '/portal/fatura', '-'],
  ['ic izleme yoklamasi', 'mesru', 1440, ['arac-imzasi'], '/saglik', '-'],
  ['sorgu alaninda birlestirme', 'kotu', 320, ['tirnak', 'anahtar-sozcuk', 'yorum-imi'], '/portal/sorgu', 'kod'],
  ['form alaninda betik etiketi', 'kotu', 210, ['etiket-acilisi', 'olay-niteligi'], '/portal/sorgu', 'kod'],
  ['ek adinda dizin yukselme', 'kotu', 96, ['yol-ayraci', 'ust-dizin'], '/portal/fatura', 'kod'],
  ['ortu altinda tirnak dizisi', 'kotu', 260, ['tirnak', 'anahtar-sozcuk'], '/portal/rapor', 'kod'],
  ['bilesende yamasi cikmamis acik', 'kotu', 40, ['bicimsiz-govde'], '/saha/yukleme', 'yok'],
  ['is akisi disi toplu indirme', 'kotu', 1200, [], '/portal/rapor', 'tasarim'],
];

// [kural adi, aranan etiketler (hepsi bulunmali), puan]
export const KURAL = [
  ['tirnak ve anahtar sozcuk', ['tirnak', 'anahtar-sozcuk'], 3],
  ['yorum imi', ['yorum-imi'], 2],
  ['etiket acilisi', ['etiket-acilisi'], 3],
  ['olay niteligi', ['olay-niteligi'], 2],
  ['yol ayraci', ['yol-ayraci'], 2],
  ['ust dizin', ['ust-dizin'], 3],
  ['bicimsiz govde', ['bicimsiz-govde'], 4],
  ['bilinen arac imzasi', ['arac-imzasi'], 2],
  ['kodlanmis alan', ['kodlanmis-alan'], 2],
  ['uzun govde', ['uzun-govde'], 1],
];

// muaf = [uc, kural adi] ciftleri; o ucta o kural hic puan yazmaz
export const puan = (s, muaf = []) => KURAL.reduce((t, [ad, ara, p]) =>
  t + (ara.every((e) => s[3].includes(e)) && !muaf.some(([u, k]) => u === s[4] && k === ad) ? p : 0), 0);

export function olc(esik, muaf = []) {
  let yakalanan = 0, kacan = 0, yanlis = 0;
  for (const s of SINIF) {
    const durdu = puan(s, muaf) >= esik;
    if (s[1] === 'kotu') durdu ? (yakalanan += s[2]) : (kacan += s[2]);
    else if (durdu) yanlis += s[2];
  }
  return { yakalanan, kacan, yanlis };
}
```

Kural kümesinin hazır gelmesi, kuralların bu uygulamayı tanımadığı anlamına gelir. Kurallar söz
dizimi düzeyinde bir yüzeye bakar ve o yüzey meşru işin de geçtiği bir yüzeydir: rapor filtresine
serbest metin yazan bir abone ile sorgu alanına birleştirme deneyen bir istek aynı iki belirtiyi
taşıyabilir. Ayrımı kural yapamaz, çünkü ayrım isteğin biçiminde değil **niyetinde ve
bağlamındadır**; kuralın gördüğü tek şey biçimdir.

#### Üç Sayı Birlikte Hareket Eder

Eşik, kural kümesinin tek gerçek ayarıdır. Aşağıdaki koşumda kural kümesi, istek kümesi ve
puanlar sabit kalıyor; değişen tek şey eşiktir.

```js
// kosum.mjs — ayni gunluk kume, degisen tek sey esik
import { SINIF, KURAL, puan, olc } from './istek.mjs';

const s = (x, n) => String(x).padStart(n);
const kotu = SINIF.filter((k) => k[1] === 'kotu');
const T = (l) => l.reduce((t, k) => t + k[2], 0);
console.log(`${SINIF.length} istek sinifi, ${KURAL.length} kural; gunde ${T(SINIF)} istek` +
  ` (${T(kotu)} kotu / ${T(SINIF) - T(kotu)} mesru)\n`);
console.log(`${'istek sinifi'.padEnd(31)}${s('sinif', 6)}${s('gunluk', 7)}${s('puan', 5)}` +
  `${s('uc', 15)}${s('erken asama', 13)}`);
for (const k of SINIF)
  console.log(`${k[0].padEnd(31)}${s(k[1], 6)}${s(k[2], 7)}${s(puan(k), 5)}${s(k[4], 15)}${s(k[5], 13)}`);

console.log(`\n${'esik'.padEnd(6)}${s('yakalanan', 11)}${s('kacan', 8)}${s('yanlis kesilen', 16)}` +
  `${s('kesilen/yakalanan', 19)}`);
for (const e of [6, 5, 4, 3, 2]) {
  const r = olc(e);
  console.log(`${String(e).padEnd(6)}${s(r.yakalanan, 11)}${s(r.kacan, 8)}${s(r.yanlis, 16)}` +
    `${s(r.yakalanan ? (r.yanlis / r.yakalanan).toFixed(1) : '-', 19)}`);
}
```

```
11 istek sinifi, 10 kural; gunde 96466 istek (2126 kotu / 94340 mesru)

istek sinifi                    sinif gunluk puan             uc  erken asama
abone sorgu formu               mesru  84000    0  /portal/sorgu            -
saha uygulamasi toplu yukleme   mesru   5400    3  /saha/yukleme            -
rapor filtresi, serbest metin   mesru   2600    3  /portal/rapor            -
fatura ekinde dosya adi         mesru    900    2 /portal/fatura            -
ic izleme yoklamasi             mesru   1440    2        /saglik            -
sorgu alaninda birlestirme       kotu    320    5  /portal/sorgu          kod
form alaninda betik etiketi      kotu    210    5  /portal/sorgu          kod
ek adinda dizin yukselme         kotu     96    5 /portal/fatura          kod
ortu altinda tirnak dizisi       kotu    260    3  /portal/rapor          kod
bilesende yamasi cikmamis acik   kotu     40    4  /saha/yukleme          yok
is akisi disi toplu indirme      kotu   1200    0  /portal/rapor      tasarim

esik    yakalanan   kacan  yanlis kesilen  kesilen/yakalanan
6               0    2126               0                  -
5             626    1500               0                0.0
4             666    1460               0                0.0
3             926    1200            8000                8.6
2             926    1200           10340               11.2
```

Beş satır bir ayar eğrisidir ve her satırı ayrı okumak gerekir. Eşik altıda kural kümesi hiçbir
şey durdurmuyor: hiçbir sınıfın toplam puanı altıya ulaşmıyor, yani kurulmuş ama etkisiz bir
katman gündelik ölçümde sıfırdan ayırt edilemez. Eşik beşte üç sınıf durur ve altı yüz yirmi
altı kötü istek kesilir; yanlış kesilen istek sıfırdır. Eşik dörde inince yalnız kırk istek daha
eklenir ve yanlış kesilen yine sıfır kalır — dört, bu kümedeki karşılıksız ayardır.

Asıl karar üçüncü satırdadır. Eşiği üçe indirmek iki yüz altmış kötü isteği daha durdurur ve
karşılığında **sekiz bin meşru isteği** keser. Oran son sütunda yazılı: durdurulan her kötü
istek başına 8,6 kesilen meşru istek. Kesilenler de rastgele değildir; saha uygulamasının toplu
yüklemesi ile rapor filtresine yazılan serbest metindir, yani sistemin iki gerçek işlevi. Eşik
ikide ise durdurulan kötü istek hiç artmaz, kesilen istek iki bin üç yüz kırk artar: sıkılaştırma
belirli bir noktadan sonra yalnızca meşru işi kesmeye başlar.

Kaçan sütunu bütün ayarlarda bin iki yüzden aşağı inmiyor. Bunun nedeni bir eşik seçimi değil, bir
**görme sınırıdır**: iş akışı dışı toplu indirme hiçbir belirti taşımıyor. İstekler biçim olarak
kusursuzdur, kimliği doğrulanmıştır, yetkisi vardır; yanlış olan tek şey hacim ve bağlamdır.
Söz dizimine bakan bir kural kümesi bunu hiçbir eşikte göremez.

#### Muafiyet Yazmanın Bedeli

Eşiği üçte tutup yanlış kesmeyi ayrı ayrı kapatmak, üretimde en sık verilen yanıttır: kesilen
uç ile onu kesen kural bir muafiyet listesine yazılır ve o uçta o kural puan yazmaz. Üç muafiyet
yeterlidir — saha yükleme ucundaki iki kural ile rapor ucundaki tırnak kuralı.

```js
// muafiyet.mjs — esik 3'te yanlis kesmeyi muafiyetle kapatmanin bedeli
import { SINIF, puan, olc } from './istek.mjs';

const s = (x, n) => String(x).padStart(n);
const MUAF = [['/saha/yukleme', 'uzun govde'], ['/saha/yukleme', 'kodlanmis alan'],
  ['/portal/rapor', 'tirnak ve anahtar sozcuk']];

const AYAR = [['esik 4, muafiyet yok', 4, []], ['esik 3, muafiyet yok', 3, []],
  ['esik 3, 3 muafiyet', 3, MUAF]];
console.log(`${'ayar'.padEnd(22)}${s('yakalanan', 11)}${s('kacan', 8)}${s('yanlis kesilen', 16)}${s('bakilan kalem', 15)}`);
for (const [ad, e, m] of AYAR) {
  const r = olc(e, m);
  console.log(`${ad.padEnd(22)}${s(r.yakalanan, 11)}${s(r.kacan, 8)}${s(r.yanlis, 16)}${s(10 + m.length, 15)}`);
}

console.log(`\nmuafiyetin ucta actigi alan:`);
for (const [u, k] of MUAF) {
  const gecen = SINIF.filter((x) => x[4] === u && x[1] === 'kotu' && puan(x) >= 3 && puan(x, MUAF) < 3);
  console.log(`  ${u.padEnd(15)}${k.padEnd(26)}${gecen.length ? `gecen kotu: ${gecen[0][0]} (${gecen[0][2]})` : 'gecen kotu yok'}`);
}
```

```
ayar                    yakalanan   kacan  yanlis kesilen  bakilan kalem
esik 4, muafiyet yok          666    1460               0             10
esik 3, muafiyet yok          926    1200            8000             10
esik 3, 3 muafiyet            666    1460               0             13

muafiyetin ucta actigi alan:
  /saha/yukleme  uzun govde                gecen kotu yok
  /saha/yukleme  kodlanmis alan            gecen kotu yok
  /portal/rapor  tirnak ve anahtar sozcuk  gecen kotu: ortu altinda tirnak dizisi (260)
```

Birinci ve üçüncü satır üç sayının üçünde de aynıdır: 666, 1.460, 0. Yani üç muafiyetle
sıkılaştırılmış eşik, hiç muafiyet yazılmamış gevşek eşikle tam olarak aynı sonucu veriyor.
Fark yalnız son sütundadır — bakılan kalem sayısı ondan on üçe çıkmıştır. Üç kalem daha, üç ayrı
gerekçe, her uç değişikliğinde yeniden gözden geçirilecek üç satır.

Alt liste bunun nedenini veriyor. Muafiyet bir kuralı bir uçta kapatır ve o uçtan geçen **her
isteği** kapsar. Rapor ucundaki tırnak muafiyeti meşru filtre metnini kurtarırken aynı uçtan
geçen iki yüz altmış kötü isteği de birlikte kurtardı: üç puanlık kural o uçta artık hiç
yazmıyor. Saha yükleme ucundaki iki muafiyet bu yan etkiyi üretmedi, çünkü o uçtaki tek kötü
sınıf başka bir kuralla yakalanıyor. İkisi arasındaki fark önceden bilinmez; ancak muafiyetin
kapsadığı istek kümesi sayıldığında görülür. Muafiyet listesi bu yüzden bir ayar değil, bir
envanterdir: her satırın hangi uçta hangi kuralı susturduğu ve o uçtan başka nelerin geçtiği
ayrıca izlenmediği sürece liste zamanla kural kümesinin kendisinden daha belirleyici olur.

#### Durdurulanın Nereye Ait Olduğu

İlk iki sütun bu katmanın ne yaptığını söylüyor. Üçüncü sütun kursun asıl sorusudur: durdurulan
hacim, daha ucuz bir aşamada zaten kapatılabilir miydi.

```js
// asama.mjs — durdurulan kalemin kaci daha ucuz bir asamada kapatilabilirdi
import { SINIF, puan } from './istek.mjs';

const s = (x, n) => String(x).padStart(n);
const kotu = SINIF.filter((k) => k[1] === 'kotu');
const ASAMA = ['kod', 'tasarim', 'yok'];

console.log(`${'esik'.padEnd(6)}${ASAMA.map((a) => s(a, 10)).join('')}${s('yalniz burada %', 17)}`);
for (const e of [5, 4, 3]) {
  const d = kotu.filter((k) => puan(k) >= e);
  const t = d.reduce((x, k) => x + k[2], 0);
  const pay = ASAMA.map((a) => d.filter((k) => k[5] === a).reduce((x, k) => x + k[2], 0));
  console.log(`${String(e).padEnd(6)}${pay.map((p) => s(p, 10)).join('')}` +
    `${s(t ? (100 * pay[2] / t).toFixed(1) : '-', 17)}`);
}

console.log(`\nhicbir esikte durdurulmayan kotu sinif:`);
for (const k of kotu.filter((x) => puan(x) < 2))
  console.log(`  ${k[0].padEnd(31)}${s(k[2], 7)}  belirti yok, erken asama: ${k[5]}`);
console.log(`\nyalniz calisma zamaninda kapatilabilen sinif:`);
for (const k of kotu.filter((x) => x[5] === 'yok'))
  console.log(`  ${k[0].padEnd(31)}${s(k[2], 7)}  puan ${puan(k)}, esik 4'te durur`);
```

```
esik         kod   tasarim       yok  yalniz burada %
5            626         0         0              0.0
4            626         0        40              6.0
3            886         0        40              4.3

hicbir esikte durdurulmayan kotu sinif:
  is akisi disi toplu indirme       1200  belirti yok, erken asama: tasarim

yalniz calisma zamaninda kapatilabilen sinif:
  bilesende yamasi cikmamis acik      40  puan 4, esik 4'te durur
```

Tablo katmanın gerçek payını gösteriyor. Eşik dörtte durdurulan altı yüz altmış altı isteğin
altı yüz yirmi altısı — yüzde doksan dördü — kod aşamasında kapatılabilir sınıflardan geliyor:
sorgu birleştirme parametreli sorguyla, betik etiketi çıktı kodlamasıyla, dizin yükselme yol
doğrulamasıyla kapanır ve bunların üçü de bir defa yazılıp bütün istekler için geçerli olur.
Bu katman aynı kalemleri her gün, her istekte yeniden yakalıyor.

Yüzde altı ise başka bir şey. Bileşende yaması çıkmamış bir açık için erken aşama yoktur:
kalem ne tasarımda vardı ne kodda yazıldı, bağımlılık envanterinde göründüğü an da bir düzeltme
sürümü mevcut değildi. O kırk isteği durduran tek şey bu katmandır ve kural kümesinin varlık
nedeni tam olarak budur. Katmanın ölçüsü toplam durdurma sayısı değil, **yalnız burada
durdurulabilen** sayıdır.

Alt liste ise ters yönü söylüyor. İş akışı dışı toplu indirme hiçbir eşikte durmuyor; bu kalem
ne kurallarla ne eşikle yakalanır, çünkü yetkilendirme ve iş akışı kararıdır, yani tasarım
aşamasına aittir. Kural kümesi bu kalemi hiç görmediği hâlde günlük gösterge tablosunda altı yüz
altmış altı durdurma yazacaktır. Katmanın kurulu olması, kapsadığı kalem sınıfını genişletmez.

#### Özet

- Bir çalışma zamanı savunması üç sayıyla ölçülür ve üçü aynı koşumdan okunur: durdurulan kötü
  istek, kaçan kötü istek, yanlış yere kesilen meşru istek. Üçüncüsü yazılmadığında ilk ikisi
  bir şey ölçmez.
- Eşik 5'ten 4'e inince durdurulan istek 626'dan 666'ya çıktı ve yanlış kesilen sıfır kaldı;
  3'e inmek 260 istek daha durdurup 8.000 meşru isteği kesti (yakalanan başına 8,6 kesilen),
  2'ye inmek hiçbir kazanç eklemeden 2.340 kesme daha ekledi.
- Eşik 3 ile üç muafiyet, eşik 4 ile hiç muafiyetin verdiği üç sayının aynısını verdi (666,
  1.460, 0); tek fark bakılan kalemin 10'dan 13'e çıkmasıdır. Muafiyetlerden biri aynı uçtan
  geçen 260 kötü isteği de kapsadı.
- Kaçan istek hiçbir eşikte 1.200'ün altına inmedi: iş akışı dışı toplu indirme hiçbir belirti
  taşımıyor. Söz dizimine bakan kural biçimi görür, bağlamı görmez.
- Eşik 4'te durdurulan 666 isteğin 626'sı kod aşamasında bir kez kapatılabilecek sınıflardan
  geliyor. Yalnız çalışma zamanında kapatılabilen pay günde 40 istek, yani yüzde 6'dır — yaması
  çıkmamış bileşen açığı.

#### Sonraki Adım

Bu dersin kural kümesi tek bir isteğe bakıp karar verdi: belirti var mı, puan eşiği aşıyor mu.
Kaçan bin iki yüz istek ise tam olarak bu yüzden kaçtı — hiçbiri tek başına yanlış değildi.
İş akışı dışı toplu indirmenin yanlışlığı isteğin içinde değil, **aynı istemciden gelen istek
sayısında ve zamanlamasındadır**. Bunu görmek için savunmanın bir isteği değil bir sayacı
okuması gerekir: pencere başına kaç istek, hangi anahtara bağlı, hangi eşikle. Sonraki ders o
sayacı üç ayrı pencere biçiminde koşturuyor ve aynı üç sayıyı orada soruyor — özellikle
ikincisini, çünkü hız sınırının en pahalı yanı durdurduğu kötü istek değil, meşru tepe yükünden
kestiği istektir.

### Hız Sınırlama Pencereleri

Source: https://academia.sh/tr/kurslar/calisma-zamani-guvenligi/hiz-sinirlama-pencereleri

Aynı beş dakikalık yükün üç ayrı hız sınırı penceresinde koşturulması ve pencere biçiminin üç sayıyı nasıl kaydırdığı: sabit pencerenin sınır etkisi, kayan pencerenin meşru tepe yükünden kestiği istek, jeton kovasının tepe payını kurtarırken saldırı tepe yükünü de geçirmesi, meşru tepeyi kurtaran limitin kaç kötü isteği serbest bıraktığı ve kesilen hacmin hangi bölümünün daha erken bir aşamada kapatılabileceği.

Önceki ders bir kural kümesini tek tek isteklere baktırdı ve kaçan bin iki yüz isteğin tam olarak
bu yüzden kaçtığını gösterdi: hiçbiri tek başına yanlış değildi. Yanlışlık isteğin içinde değil,
aynı istemciden gelen istek **sayısında ve zamanlamasındaydı**. Hız sınırlama bu eksene bakan
savunmadır; ölçüsü ise durdurduğu kötü istek değil, meşru tepe yükünden kestiğidir.

Kısma algoritmaları daha önce ölçüldü ve burada tekrarlanmıyor. Bu dersin sorusu tektir: aynı
nominal sınır üç ayrı pencere biçiminde uygulandığında üç sayı nereye kayıyor. Pencere biçimi
bir uygulama ayrıntısı gibi görünür; ölçüldüğünde meşru işin kesilip kesilmediğini belirleyen
ana karar çıkar.

#### Aynı Yük, Üç Pencere Biçimi

Bölgesel ölçüm ağının üretim ortamında beş dakikalık bir dilim alınıyor. Aşağıdaki her şey `node`
ile kurulan bir modeldir; gerçek trafik üretilmiyor, hiçbir istek gövdesi yazılmıyor.

- **US6.** Yedi istemci sınıfı, varış serileri ve saniyedeki istek sayıları kurgusal ölçüm ağına
  aittir. Meşru sınıflardan ikisinin tepe yükü işin kendisidir: vardiya başlangıcında saha
  uygulamasının açtığı oturumlar ve fatura döneminde çalışan toplu sorgu.
- **US7.** Hız sınırı istemci başına tek bir anahtara bağlıdır ve bu derste anahtar sabittir.
  Anahtarın hesap mı adres mi olduğu ayrı bir eksendir; sonraki ders onu ölçüyor.
- **US8.** Varış hızı saniye içinde düzgün dağılıyor. Gerçekte saniye içi kümelenme kayan
  pencerenin kestiği miktarı bir miktar artırır, yönünü değiştirmez.
- **US9.** Üç biçim **aynı nominal sınırı** taşıyor: dakikada altı yüz istek. Jeton kovası
  saniyede on jeton ekliyor ve dokuz yüz jetonda doluyor; ortalama hız aynı, tepe payı farklı.
- **US10.** "Daha erken kapatma aşaması" sütunu her kötü istemci için elle işaretlendi.

```js
// yuk.mjs — bes dakikalik varis serisi ve uc pencere bicimi; model, gercek trafik degil
// [istemci, gercek sinif, [[t0, t1, saniyedeki istek], ...], daha erken kapatma asamasi]
export const SURE = 300;
export const ISTEMCI = [
  ['abone portali, surekli', 'mesru', [[0, 300, 4]], '-'],
  ['saha uygulamasi, vardiya baslangici', 'mesru', [[0, 110, 2], [110, 150, 30], [150, 300, 2]], '-'],
  ['fatura donemi toplu sorgu', 'mesru', [[0, 45, 1], [45, 65, 40], [65, 300, 1]], '-'],
  ['ic izleme yoklamasi', 'mesru', [[0, 300, 1]], '-'],
  ['is akisi disi toplu indirme', 'kotu', [[0, 300, 9]], 'tasarim'],
  ['sayfa gezinme kaziyicisi', 'kotu', [[0, 300, 26]], 'yok'],
  ['oturum acma denemesi dizisi', 'kotu', [[40, 100, 18], [160, 220, 18]], 'kod'],
];

export const seri = (prof) => {
  const a = new Array(SURE).fill(0);
  for (const [t0, t1, r] of prof) for (let t = t0; t < t1; t++) a[t] = r;
  return a;
};

// sabit pencere: sayac pencere sinirinda sifirlanir
export function sabit(a, limit, pen) {
  let gecen = 0, sayac = 0;
  for (let t = 0; t < a.length; t++) {
    if (t % pen === 0) sayac = 0;
    const izin = Math.min(a[t], Math.max(0, limit - sayac));
    sayac += izin; gecen += izin;
  }
  return gecen;
}

// kayan pencere: son `pen` saniyede kabul edilen istek sayilir
export function kayan(a, limit, pen) {
  let gecen = 0; const kabul = new Array(a.length).fill(0);
  for (let t = 0; t < a.length; t++) {
    let son = 0;
    for (let u = Math.max(0, t - pen + 1); u < t; u++) son += kabul[u];
    kabul[t] = Math.min(a[t], Math.max(0, limit - son));
    gecen += kabul[t];
  }
  return gecen;
}

// jeton kovasi: saniyede `hiz` jeton eklenir, kova `kap` jetonda dolar
export function kova(a, hiz, kap) {
  let gecen = 0, jeton = kap;
  for (let t = 0; t < a.length; t++) {
    jeton = Math.min(kap, jeton + hiz);
    const izin = Math.min(a[t], jeton);
    jeton -= izin; gecen += izin;
  }
  return gecen;
}

export const BICIM = [
  ['sabit pencere 60 s', (a) => sabit(a, 600, 60)],
  ['kayan pencere 60 s', (a) => kayan(a, 600, 60)],
  ['jeton kovasi 10/s', (a) => kova(a, 10, 900)],
];

export function olc(bicim) {
  let yakalanan = 0, kacan = 0, yanlis = 0, mesru = 0;
  for (const [, sinif, prof] of ISTEMCI) {
    const a = seri(prof);
    const toplam = a.reduce((x, y) => x + y, 0);
    const kesilen = toplam - bicim(a);
    if (sinif === 'kotu') { yakalanan += kesilen; kacan += toplam - kesilen; }
    else { yanlis += kesilen; mesru += toplam; }
  }
  return { yakalanan, kacan, yanlis, mesru };
}
```

Üç biçim arasındaki tek fark, sayacın geçmişi nasıl tuttuğudur. Sabit pencere sayacı dakika
başında sıfırlar; önceki dakikanın hiçbir isteğini hatırlamaz. Kayan pencere son altmış saniyede
kabul ettiği her isteği hatırlar. Jeton kovası hiç pencere tutmaz: kullanılmayan payı biriktirir
ve tek seferde harcamaya izin verir.

#### Meşru Tepe Yükünden Kesilen İstek

```js
// kosum.mjs — ayni bes dakikalik yuk, degisen tek sey pencere bicimi
import { ISTEMCI, BICIM, seri, olc } from './yuk.mjs';

const s = (x, n) => String(x).padStart(n);
const T = (f) => ISTEMCI.filter(f).reduce((t, k) => t + seri(k[2]).reduce((x, y) => x + y, 0), 0);
console.log(`${ISTEMCI.length} istemci, 300 saniye; toplam ${T(() => true)} istek` +
  ` (${T((k) => k[1] === 'kotu')} kotu / ${T((k) => k[1] === 'mesru')} mesru)\n`);

console.log(`${'istemci'.padEnd(36)}${s('sinif', 6)}${s('istek', 7)}` +
  BICIM.map(([ad]) => s(ad.split(' ')[0], 9)).join('') + s('erken asama', 13));
for (const [ad, sinif, prof, asama] of ISTEMCI) {
  const a = seri(prof), toplam = a.reduce((x, y) => x + y, 0);
  console.log(`${ad.padEnd(36)}${s(sinif, 6)}${s(toplam, 7)}` +
    BICIM.map(([, f]) => s(toplam - f(a), 9)).join('') + s(asama, 13));
}

console.log(`\n(uc sutun: o bicimin kestigi istek sayisi)\n`);
console.log(`${'pencere bicimi'.padEnd(20)}${s('yakalanan', 11)}${s('kacan', 8)}` +
  `${s('yanlis kesilen', 16)}${s('mesru kesme %', 15)}`);
for (const [ad, f] of BICIM) {
  const r = olc(f);
  console.log(`${ad.padEnd(20)}${s(r.yakalanan, 11)}${s(r.kacan, 8)}${s(r.yanlis, 16)}` +
    `${s((100 * r.yanlis / r.mesru).toFixed(1), 15)}`);
}
```

```
7 istemci, 300 saniye; toplam 16960 istek (12660 kotu / 4300 mesru)

istemci                              sinif  istek    sabit    kayan    jeton  erken asama
abone portali, surekli               mesru   1200        0        0        0            -
saha uygulamasi, vardiya baslangici  mesru   1720      360      640        0            -
fatura donemi toplu sorgu            mesru   1080       45      240        0            -
ic izleme yoklamasi                  mesru    300        0        0        0            -
is akisi disi toplu indirme           kotu   2700        0        0        0      tasarim
sayfa gezinme kaziyicisi              kotu   7800     4800     4800     3910          yok
oturum acma denemesi dizisi           kotu   2160      240      960        0          kod

(uc sutun: o bicimin kestigi istek sayisi)

pencere bicimi        yakalanan   kacan  yanlis kesilen  mesru kesme %
sabit pencere 60 s         5040    7620             405            9.4
kayan pencere 60 s         5760    6900             880           20.5
jeton kovasi 10/s          3910    8750               0            0.0
```

Üç satır aynı nominal sınırı taşıyor ve üçünde de üç sayı farklı. Kayan pencere en çok kötü
isteği durduruyor: beş bin yedi yüz altmış. Aynı satırda meşru yükün **yüzde 20,5'i** kesilmiş;
kesilenler de rastgele istekler değil, vardiya başlangıcında saha uygulamasının açtığı altı yüz
kırk oturum ile fatura döneminin iki yüz kırk sorgusudur. Sabit pencere daha az kesiyor, çünkü
sayacı dakika sınırında sıfırlıyor; vardiya tepesi iki pencereye bölündüğü için üç yüz altmış
istekle kurtuluyor. Aynı sıfırlama kötü tarafta da çalışıyor: oturum açma denemesi dizisinden
yalnız iki yüz kırk istek kesiliyor, çünkü altmış saniyelik iki tepe de sınırın iki yanına
dağılıyor. Sınır etkisi kimin lehine çalışacağını seçmez.

Jeton kovası satırı en dikkat çekici olanıdır. Meşru istekten **hiçbir şey kesilmiyor**: dokuz
yüz jetonluk birikim vardiya tepesini de fatura tepesini de bütünüyle karşılıyor. Aynı birikim
oturum açma denemesi dizisini de bütünüyle karşılıyor — iki bin yüz altmış isteğin tamamı
geçiyor. Kova bir tepenin meşru mu olduğunu sormaz; yalnızca birikmiş pay olup olmadığına bakar.
Tepe payı tanımak isteyen bir savunma, tepe biçimindeki saldırıyı da tanımak zorunda kalır.

İki bin yedi yüz isteklik iş akışı dışı toplu indirme ise üç biçimin hiçbirinde kesilmiyor.
Saniyede dokuz istek, dakikada altı yüzlük sınırın altındadır; istemci sınırın hemen altında
sabit hızla çalıştığı sürece hiçbir pencere biçimi onu görmez. Önceki dersin kural kümesinden
kaçan kalem, hız sınırından da kaçıyor.

#### Limiti Yükseltmenin Bedeli

Kayan pencerenin kestiği sekiz yüz seksen meşru istek üretimde bir aksama demektir: vardiya
başlangıcında saha ekibinin bir bölümü uygulamaya giremez. Verilen ilk yanıt limiti yükseltmektir.

```js
// limit.mjs — mesru tepe yukunu kurtarmak icin limiti yukseltmenin bedeli
import { ISTEMCI, seri, kayan, kova } from './yuk.mjs';

const s = (x, n) => String(x).padStart(n);
const KOTU = ISTEMCI.filter((k) => k[1] === 'kotu');
const MESRU = ISTEMCI.filter((k) => k[1] === 'mesru');
const dizi = ISTEMCI.find((k) => k[0].startsWith('oturum'));

const kes = (liste, f) => liste.reduce((t, k) => {
  const a = seri(k[2]); return t + a.reduce((x, y) => x + y, 0) - f(a);
}, 0);

console.log(`kayan pencere, 60 s; degisen tek sey limit`);
console.log(`${'limit'.padEnd(7)}${s('yanlis kesilen', 16)}${s('yakalanan', 11)}${s('kacan', 8)}` +
  `${s('gecen oturum denemesi', 23)}`);
for (const L of [600, 800, 1000, 1240, 1500]) {
  const f = (a) => kayan(a, L, 60);
  console.log(`${String(L).padEnd(7)}${s(kes(MESRU, f), 16)}${s(kes(KOTU, f), 11)}` +
    `${s(12660 - kes(KOTU, f), 8)}${s(f(seri(dizi[2])), 23)}`);
}

console.log(`\njeton kovasi, 10/s; degisen tek sey kova kapasitesi`);
console.log(`${'kapasite'.padEnd(10)}${s('yanlis kesilen', 16)}${s('yakalanan', 11)}${s('kacan', 8)}` +
  `${s('gecen oturum denemesi', 23)}`);
for (const K of [200, 400, 600, 900, 1200]) {
  const f = (a) => kova(a, 10, K);
  console.log(`${String(K).padEnd(10)}${s(kes(MESRU, f), 16)}${s(kes(KOTU, f), 11)}` +
    `${s(12660 - kes(KOTU, f), 8)}${s(f(seri(dizi[2])), 23)}`);
}
```

```
kayan pencere, 60 s; degisen tek sey limit
limit    yanlis kesilen  yakalanan   kacan  gecen oturum denemesi
600                 880       5760    6900                   1200
800                 480       4360    8300                   1600
1000                240       2960    9700                   2000
1240                  0       1600   11060                   2160
1500                  0        300   12360                   2160

jeton kovasi, 10/s; degisen tek sey kova kapasitesi
kapasite    yanlis kesilen  yakalanan   kacan  gecen oturum denemesi
200                   1020       5190    7470                   1580
400                    620       4590    8070                   1980
600                    220       4210    8450                   2160
900                      0       3910    8750                   2160
1200                     0       3610    9050                   2160
```

İki tablo aynı şeyi iki ayrı ayarla söylüyor. Kayan pencerede yanlış kesilen istek ancak limit
bin iki yüz kırka çıktığında sıfıra iner; vardiya tepesinin altmış saniyelik en yoğun dilimi
tam olarak o kadardır. Aynı satırda yakalanan istek beş bin yedi yüz altmıştan bin altı yüze
düşmüş, kaçan istek altı bin dokuz yüzden on bir bin altmışa çıkmıştır. Son sütun kararın asıl
bedelini yazıyor: oturum açma denemesi dizisinin **tamamı** geçmeye başlıyor.

Jeton kovası tablosu aynı eğriyi kapasite ekseninde tekrarlıyor. Meşru tepenin sıfır kesmeyle
geçtiği ilk kapasite dokuz yüzdür; oturum açma dizisinin tamamının geçtiği ilk kapasite ise altı
yüz. Yani kova, meşru tepeyi kurtaracak kadar gevşetilmeden **önce** saldırı tepesini kurtarmış
oluyor. Sıralama tersine çevrilemez, çünkü her iki tepe de aynı şeydir: kısa süreli yüksek hız.

Buradan çıkan bir ayar önerisi değil, bir sınırdır: tepe yükü işin kendisi olan bir sistemde tek
anahtara bağlı tek eşikli hız sınırı, meşru tepeyi geçirmek için saldırı tepesini de geçirmek
zorundadır. Ayrım hızda değil, isteğin **neye** yapıldığındadır; hız sayacı bunu görmez.

#### Kesilenin Nereye Ait Olduğu

```js
// asama.mjs — kesilen kotu istegin kaci daha ucuz bir asamada kapatilabilirdi
import { ISTEMCI, BICIM, seri, kayan } from './yuk.mjs';

const s = (x, n) => String(x).padStart(n);
const KOTU = ISTEMCI.filter((k) => k[1] === 'kotu');
const MESRU = ISTEMCI.filter((k) => k[1] === 'mesru');
const ASAMA = ['tasarim', 'kod', 'yok'];
const kesilen = (k, f) => { const a = seri(k[2]); return a.reduce((x, y) => x + y, 0) - f(a); };

console.log(`${'pencere bicimi'.padEnd(20)}${ASAMA.map((a) => s(a, 10)).join('')}${s('yalniz burada %', 17)}`);
for (const [ad, f] of BICIM) {
  const pay = ASAMA.map((a) => KOTU.filter((k) => k[3] === a).reduce((x, k) => x + kesilen(k, f), 0));
  const t = pay.reduce((x, y) => x + y, 0);
  console.log(`${ad.padEnd(20)}${pay.map((p) => s(p, 10)).join('')}${s((100 * pay[2] / t).toFixed(1), 17)}`);
}

console.log(`\nkayan pencere; is akisi disi toplu indirmeyi (9/s) yakalamak icin gereken limit`);
console.log(`${'limit'.padEnd(7)}${s('toplu indirmeden kesilen', 26)}${s('mesru kesilen', 15)}${s('mesru kesme %', 15)}`);
const indirme = KOTU.find((k) => k[3] === 'tasarim');
for (const L of [600, 540, 480, 360]) {
  const f = (a) => kayan(a, L, 60);
  const m = MESRU.reduce((x, k) => x + kesilen(k, f), 0);
  console.log(`${String(L).padEnd(7)}${s(kesilen(indirme, f), 26)}${s(m, 15)}${s((100 * m / 4300).toFixed(1), 15)}`);
}
```

```
pencere bicimi         tasarim       kod       yok  yalniz burada %
sabit pencere 60 s           0       240      4800             95.2
kayan pencere 60 s           0       960      4800             83.3
jeton kovasi 10/s            0         0      3910            100.0

kayan pencere; is akisi disi toplu indirmeyi (9/s) yakalamak icin gereken limit
limit    toplu indirmeden kesilen  mesru kesilen  mesru kesme %
600                             0            880           20.5
540                             0           1000           23.3
480                           300           1120           26.0
360                           900           1360           31.6
```

Üst tablo katmanın gerçek payını veriyor. Sayfa gezinme kazıyıcısı hiçbir erken aşamada
kapatılamaz: istekler tek tek meşrudur, kimliği doğrulanmıştır, yetkisi vardır ve yalnız birim
zamandaki sayıları anlamlıdır. Üç biçimde de kesilen dört bin sekiz yüz — kovada üç bin dokuz
yüz on — istek bu sınıftandır ve bu katmanın varlık nedeni tam olarak budur. Oturum açma denemesi
dizisi ise farklı bir yere aittir: kod aşamasında ikinci etken zorunlu kılındığında dizinin
değeri kalmaz, çünkü doğru parola bulunsa bile oturum açılmaz. Hız sınırının o dizide kestiği
iki yüz kırk ya da dokuz yüz altmış istek, kapatılabilir bir kalemi her gün yeniden yakalamaktır.

Alt tablo tasarım aşamasına ait kalemi gösteriyor. İş akışı dışı toplu indirmeyi hız sınırıyla
görmek için limitin dört yüz seksene indirilmesi gerekiyor; o ayarda bu istemciden kesilen istek
üç yüz, meşru yükten kesilen ise bin yüz yirmidir — meşru işin **dörtte biri**. Limit üç yüz
altmışa inince kesilen kötü istek dokuz yüze çıkıyor, meşru kesme yüzde 31,6'ya. Bu kalem hız
sınırıyla ancak sistemi kullanılamaz hâle getirerek kapatılabilir; doğru yeri tasarımdır. Toplu
indirme bir kuyruk işine alındığında uçta sınırın altında sabit hızla çalışma imkânı kalmaz.

#### Özet

- Aynı nominal sınır (dakikada 600 istek) üç pencere biçiminde üç ayrı sonuç verdi: sabit
  pencere 5.040 / 7.620 / 405, kayan pencere 5.760 / 6.900 / 880, jeton kovası 3.910 / 8.750 / 0
  (yakalanan / kaçan / yanlış kesilen).
- Kayan pencere meşru yükün yüzde 20,5'ini kesti ve kesilenler vardiya başlangıcı ile fatura
  dönemi tepesiydi. Sabit pencerenin daha az kesmesi bir üstünlük değil, sınır etkisinin
  yan ürünüdür: aynı sıfırlama oturum açma dizisini de 960 yerine 240 istekle kurtardı.
- Jeton kovası meşru tepeden hiçbir şey kesmedi ama oturum açma denemesi dizisinin 2.160
  isteğinin tamamını geçirdi. Kova kapasitesi meşru tepeyi kurtaracak kadar açıldığında (900)
  saldırı tepesi zaten 600 kapasitede kurtulmuştu.
- Kayan pencerede yanlış kesilen isteği sıfırlayan limit 1.240'tır; o ayarda yakalanan 5.760'tan
  1.600'e düşer, kaçan 11.060'a çıkar. Tepe yükü işin kendisi olan bir sistemde tek eşikli hız
  sınırı meşru tepeyi geçirmek için saldırı tepesini de geçirir.
- Kesilen hacmin yalnız burada kapatılabilen bölümü kazıyıcıdır (4.800 / 3.910). Oturum açma
  dizisi kod aşamasında ikinci etkenle, iş akışı dışı toplu indirme tasarımda kuyruk işiyle
  kapanır; ikincisini hız sınırıyla görmek limiti 480'e indirmeyi, yani meşru işin dörtte birini
  kesmeyi gerektirir.

#### Sonraki Adım

Bu dersin sayacı tek bir anahtara bağlıydı ve o anahtarın ne olduğu hiç sorulmadı. Oturum açma
denemesi dizisinin kesilen ya da kaçan bölümü de tam olarak bu yüzden belirsiz kaldı: dizinin
saniyedeki hızı biliniyordu, ama denemelerin **kaç hesaba** ve **kaç adrese** dağıldığı
bilinmiyordu. Aynı toplam hız, tek hesaba yüklendiğinde başka, on bin hesaba tek deneme olarak
dağıtıldığında bambaşka bir saldırı biçimidir ve ikincisi bu dersin hiçbir ayarında görünmez.
Sonraki ders eşiği hız ekseninden çıkarıp hesap ve adres eksenine taşıyor, hangi eşiğin hangi
saldırı biçimini durdurduğunu ayırıyor ve aynı üç sayıyı orada soruyor — özellikle kilitlenen
meşru hesabı.

### Kimlik Bilgisi Doldurma Savunması

Source: https://academia.sh/tr/kurslar/calisma-zamani-guvenligi/kimlik-bilgisi-doldurma-savunmasi

Bir saatlik oturum açma denemesi kaydında hesap ve adres eşiklerinin ayrı ayrı koşturulması ve hangi eşiğin hangi saldırı biçimini durdurduğunun ayrılması: kaba kuvveti hesap eşiği, yoğun kaynaklı püskürtmeyi adres eşiği durdururken hesap başına tek deneme yapan doldurmanın ikisinden de geçmesi, engellenen deneme sayısıyla önlenen hesap ele geçirme sayısı arasındaki fark, paylaşılan çıkış adresinin ve hedef alınan meşru hesabın kilitlenmesi.

Önceki ders hız sayacını tek bir anahtara bağladı ve o anahtarın ne olduğunu hiç sormadı. Oturum
açma denemesi dizisinin durumu da bu yüzden belirsiz kaldı: saniyedeki hız biliniyordu, ama
denemelerin kaç hesaba ve kaç adrese dağıldığı bilinmiyordu. Aynı toplam hız tek hesaba
yüklendiğinde başka, dört bin hesaba birer deneme olarak dağıtıldığında bambaşka bir saldırı
biçimidir. Bu ders eşiği hız ekseninden çıkarıp hesap ve adres eksenine taşıyor.

İki biçimin adı ayrı tutulur. **Kimlik bilgisi doldurma**, başka bir yerden sızmış hesap–parola
çiftlerinin bu sistemde denenmesidir; hesap başına genellikle tek deneme yapılır ve umut, aynı
parolanın burada da kullanılmış olmasıdır. **Püskürtme** ise az sayıda yaygın parolanın çok
hesapta denenmesidir; hesap başına birkaç deneme düşer. İkisi de hesap ekseninde seyrektir, ama
adres ekseninde farklı yoğunluk gösterirler ve savunma tam olarak bu farkı ölçebilir.

#### Üç Saldırı Biçimi, İki Eksen

Aşağıdaki her şey `node` ile kurulan bir modeldir. Hiçbir deneme gerçekten yapılmıyor, hiçbir
kimlik bilgisi listesi ya da deneme aracı yazılmıyor; saldırı yalnız bir kayıt satırı biçiminde,
hedef hesap ve kaynak adres alanlarıyla temsil ediliyor.

- **US11.** Bin dokuz yüz gerçek hesap, saldırı biçimleri ve sayıları kurgusal ölçüm ağına
  aittir. Kayıt görünür tohumla üretiliyor; üreteç kendi yazıldığı için koşum yinelenebilir.
- **US12.** Bir denemenin başarılı olması modelde hesabın özelliğinden türer: doldurma yalnız
  parolası sızmış çifte ait hesapta, püskürtme yalnız parolası yaygın olan hesapta başarılıdır.
- **US13.** Eşik, pencere içinde biriken **başarısız** deneme sayısına bakar; başarılı deneme
  sayacı artırmaz. Üretimdeki yaygın davranış budur ve bu dersin ana bulgusunun kaynağıdır.
- **US14.** Meşru başarısızlık oranı yüzde on ikidir ve saha ekibinin tamamı tek bir paylaşılan
  çıkış adresinden geliyor. Otuz abone de parolasını unutup art arda deniyor.
- **US15.** Eşik aşıldığında sonraki denemeler engelleniyor; hesap kilidi ile adres kısması aynı
  sonucu veriyor. Gerçekte ikisinin çözülme süresi farklıdır, sayıların yönünü değiştirmez.

```js
// giris.mjs — bir saatlik oturum acma denemesi kaydi; model, gercek deneme uretilmiyor
export const TOHUM = 20250804;
let s = TOHUM;
const rnd = () => (s = (s * 48271) % 2147483647) / 2147483647;
const tam = (n) => Math.floor(rnd() * n);

// gercek hesaplar: ikinci etken kayitli mi, parolasi sizmis cifte mi ait, parolasi yaygin mi
export const HESAP = [];
for (let i = 0; i < 1900; i++)
  HESAP.push({ ad: `hesap-${i}`, etken: rnd() < 0.86, tekrar: rnd() < 0.038, yaygin: rnd() < 0.009 });
export const HARITA = new Map(HESAP.map((h) => [h.ad, h]));

// [dakika, hesap, adres, sinif, basarili]
export function kayitUret() {
  const k = [];
  for (let i = 0; i < 500; i++)                      // saha ekibi: tek paylasilan cikis adresi
    k.push([tam(60), HESAP[tam(380)].ad, 'paylasilan-cikis', 'mesru', rnd() > 0.12]);
  for (let i = 0; i < 1900; i++)                     // portal aboneleri: dagitik adres
    k.push([tam(60), HESAP[380 + tam(1520)].ad, `abone-adres-${tam(900)}`, 'mesru', rnd() > 0.12]);
  for (let i = 0; i < 30; i++) {                     // parolasini unutan abone: ardisik deneme
    const n = 6 + tam(4), t0 = tam(50), ad = `abone-adres-${tam(900)}`, h = HESAP[380 + tam(1520)].ad;
    for (let j = 0; j < n; j++) k.push([t0 + j, h, ad, 'mesru', j === n - 1]);
  }
  for (let i = 0; i < 4000; i++) {                   // doldurma: hesap basina tek deneme, 400 adres
    const h = i < 1900 ? HESAP[i] : null;
    k.push([tam(60), h ? h.ad : `yok-${i}`, `doldurma-adres-${i % 400}`, 'doldurma', Boolean(h && h.tekrar)]);
  }
  for (let r = 0; r < 3; r++)                        // puskurtme: uc tur, hesap basina birer deneme
    for (let i = 0; i < 1900; i++)
      k.push([5 + r * 20 + tam(5), HESAP[i].ad, `puskurtme-adres-${i % 40}`, 'puskurtme',
        HESAP[i].yaygin && r === i % 3]);
  for (let i = 0; i < 600; i++)                      // kaba kuvvet: tek hesap, tek adres
    k.push([10 + Math.floor(i / 120), HESAP[7].ad, 'kaba-adres', 'kabakuvvet', false]);
  return k.sort((a, b) => a[0] - b[0]);
}

// esik: pencere icinde biriken basarisiz deneme sayisi; asilinca sonraki denemeler engellenir
export function olc(kayit, hesapEsigi, adresEsigi) {
  const hf = new Map(), af = new Map(), kilit = new Set();
  const tur = {}, gec = [];
  let engelMesru = 0, mesruHesapla = 0, mesruAdresle = 0, engelKotu = 0, gecenKotu = 0;
  for (const [, hesap, adres, sinif, basarili] of kayit) {
    const h = hf.get(hesap) || 0, a = af.get(adres) || 0;
    const engel = h >= hesapEsigi || a >= adresEsigi;
    if (sinif === 'mesru') {
      if (engel) { engelMesru++; kilit.add(hesap); h >= hesapEsigi ? mesruHesapla++ : mesruAdresle++; }
      else if (!basarili) { hf.set(hesap, h + 1); af.set(adres, a + 1); }
      continue;
    }
    tur[sinif] = tur[sinif] || { engellenen: 0, gecen: 0, eleGecen: 0 };
    if (engel) { engelKotu++; tur[sinif].engellenen++; continue; }
    gecenKotu++; tur[sinif].gecen++;
    if (basarili) { tur[sinif].eleGecen++; gec.push([hesap, sinif]); }
    else { hf.set(hesap, h + 1); af.set(adres, a + 1); }
  }
  return { engelMesru, mesruHesapla, mesruAdresle, kilitliHesap: kilit.size,
    engelKotu, gecenKotu, eleGecen: gec, tur };
}
```

#### Hangi Eşik Neyi Görüyor

```js
// kosum.mjs — ayni kayit, degisen tek sey hesap ve adres esikleri
import { TOHUM, kayitUret, olc } from './giris.mjs';

const s = (x, n) => String(x).padStart(n);
const K = kayitUret();
const say = (f) => K.filter(f).length;
const I = Infinity;
console.log(`tohum ${TOHUM}; 60 dakika, ${K.length} deneme` +
  ` (${say((r) => r[3] === 'mesru')} mesru / ${say((r) => r[3] !== 'mesru')} kotu)\n`);

console.log(`${'saldiri bicimi'.padEnd(14)}${s('deneme', 8)}${s('hesap', 7)}${s('adres', 7)}` +
  `${s('deneme/hesap', 14)}${s('deneme/adres', 14)}${s('ele gecen hesap', 17)}`);
for (const t of ['doldurma', 'puskurtme', 'kabakuvvet']) {
  const r = K.filter((x) => x[3] === t);
  const h = new Set(r.map((x) => x[1])).size, a = new Set(r.map((x) => x[2])).size;
  console.log(`${t.padEnd(14)}${s(r.length, 8)}${s(h, 7)}${s(a, 7)}` +
    `${s((r.length / h).toFixed(1), 14)}${s((r.length / a).toFixed(1), 14)}` +
    `${s(r.filter((x) => x[4]).length, 17)}`);
}

const AYAR = [['esik yok', I, I], ['hesap 5', 5, I], ['adres 50', I, 50],
  ['hesap 5 + adres 50', 5, 50], ['hesap 3 + adres 20', 3, 20]];
console.log(`\n${'ayar'.padEnd(20)}${s('engellenen kotu', 17)}${s('gecen kotu', 12)}` +
  `${s('ele gecen', 11)}${s('engellenen mesru', 18)}${s('kilitli hesap', 15)}`);
for (const [ad, he, ae] of AYAR) {
  const r = olc(K, he, ae);
  console.log(`${ad.padEnd(20)}${s(r.engelKotu, 17)}${s(r.gecenKotu, 12)}${s(r.eleGecen.length, 11)}` +
    `${s(r.engelMesru, 18)}${s(r.kilitliHesap, 15)}`);
}

console.log(`\nsaldiri bicimine gore engellenen deneme:`);
console.log(`${'ayar'.padEnd(20)}${['doldurma', 'puskurtme', 'kabakuvvet'].map((t) => s(t, 12)).join('')}`);
for (const [ad, he, ae] of AYAR.slice(1)) {
  const r = olc(K, he, ae);
  console.log(`${ad.padEnd(20)}` +
    ['doldurma', 'puskurtme', 'kabakuvvet'].map((t) => s(r.tur[t].engellenen, 12)).join(''));
}
```

```
tohum 20250804; 60 dakika, 12923 deneme (2623 mesru / 10300 kotu)

saldiri bicimi  deneme  hesap  adres  deneme/hesap  deneme/adres  ele gecen hesap
doldurma          4000   4000    400           1.0          10.0               57
puskurtme         5700   1900     40           3.0         142.5               13
kabakuvvet         600      1      1         600.0         600.0                0

ayar                  engellenen kotu  gecen kotu  ele gecen  engellenen mesru  kilitli hesap
esik yok                            0       10300         70                 0              0
hesap 5                           669        9631         69               220             91
adres 50                         4244        6056         63               227            164
hesap 5 + adres 50               4301        5999         62               364            194
hesap 3 + adres 20               5512        4788         57               613            315

saldiri bicimine gore engellenen deneme:
ayar                    doldurma   puskurtme  kabakuvvet
hesap 5                       18          55         596
adres 50                       0        3694         550
hesap 5 + adres 50            11        3694         596
hesap 3 + adres 20            15        4899         598
```

İlk tablo iki ekseni yan yana koyuyor ve ayrım orada okunuyor. Kaba kuvvet hesap ekseninde altı
yüz denemeyle uçtadır; hesap eşiği beşe kurulduğunda beş yüz doksan altı denemesi engellenir,
yani bu biçim tek bir eşikle bitirilmiş sayılır. Püskürtme hesap ekseninde seyrektir — hesap
başına üç deneme, eşiğin altında — ama kırk adrese sıkıştığı için adres başına yüz kırk iki
denemeye çıkar; adres eşiği elliye kurulduğunda üç bin altı yüz doksan dört denemesi engellenir.
Doldurma her iki eksende de eşiğin altındadır: hesap başına bir deneme, adres başına on. Adres
eşiği bu biçimden **sıfır** deneme engelliyor.

Alt tablodaki doldurma sütununda görünen on beş ile on sekiz, doldurmanın kendi yoğunluğundan
değil, aynı hesapların püskürtmeye de hedef olmasından geliyor: iki biçimin başarısızlıkları aynı
hesap sayacında toplanınca birkaç hesap eşiği aşıyor. Yani doldurma ancak yanında başka bir
biçim varsa dolaylı olarak görülüyor.

Orta tablonun son iki sütunu bedeli yazıyor. Hesap eşiği beşte doksan bir meşru hesap kilitleniyor
ve bunların yalnız otuzu parolasını unutan abonedir; kalanı **saldırının hedefi olduğu için**
kilitlendi. Hesabına yönelik başarısız denemeler sayacı doldurdu ve hesabın gerçek sahibi
giremez oldu. Adres eşiği ellide ise iki yüz yirmi yedi meşru deneme kesiliyor; hepsi paylaşılan
çıkış adresinden gelen saha ekibine ait, çünkü o adresten geçen beş yüz denemenin yüzde on ikilik
başarısız payı eşiği tek başına aşıyor. Adres eşiği bir hesabı değil, bir ekibi kesiyor.

#### Eşiğin Önlemediği Ele Geçirme

Yukarıdaki tabloda gözden kaçması en muhtemel sütun "ele geçen" sütunudur. Gösterge tablosunda
öne çıkan sayı engellenen denemedir ve o sayı ayar sıkılaştıkça yüzlerden binlere tırmanır.
Ele geçen sütunu ise neredeyse yerinde duruyor: eşiksiz koşumda yetmiş hesap ele geçiyor, en sıkı
ayarda elli yedi. Beş bin beş yüz on iki deneme engellendi ve ele geçirme yalnız on üç azaldı.
Bu iki sayının aynı tabloda bulunması gerekir, çünkü savunmanın amacı denemeyi azaltmak değil,
hesabın ele geçmesini önlemektir.

```js
// asama.mjs — ayni hesap ele gecirmeyi daha erken hangi asama kapatir
import { HESAP, HARITA, kayitUret, olc } from './giris.mjs';

const s = (x, n) => String(x).padStart(n);
const K = kayitUret(), I = Infinity;
const mesru = K.filter((r) => r[3] === 'mesru').length;
const taban = olc(K, I, I), siki = olc(K, 3, 20);
const etkensiz = (r) => r.eleGecen.filter(([ad]) => !HARITA.get(ad).etken).length;
const belirleme = HESAP.filter((h) => h.tekrar || h.yaygin).length;

console.log(`${'onlem'.padEnd(34)}${s('asama', 16)}${s('ele gecen', 11)}${s('mesru bedel', 28)}`);
for (const [a, b, c, d] of [
  ['onlem yok', '-', taban.eleGecen.length, '0'],
  ['hesap 3 + adres 20 esigi', 'calisma zamani', siki.eleGecen.length,
    `${siki.engelMesru} deneme, ${siki.kilitliHesap} hesap`],
  ['ikinci etken, kapsam %86', 'kod', etkensiz(taban), `${mesru} oturumda ek adim`],
  ['esik ve ikinci etken', 'ikisi', etkensiz(siki), `${siki.engelMesru} deneme, ek adim`],
  ['parola belirlemede cift denetimi', 'tasarim', 0, `${belirleme} hesapta parola degisir`],
]) console.log(`${a.padEnd(34)}${s(b, 16)}${s(c, 11)}${s(d, 28)}`);

console.log(`\nikinci etken kapsami ${HESAP.filter((h) => h.etken).length}/${HESAP.length};` +
  ` kapsam disindaki ${HESAP.filter((h) => !h.etken).length} hesap her ayarda savunmasiz kaliyor\n`);

console.log(`${'ayar'.padEnd(20)}${s('hesap esigi kesti', 19)}${s('adres esigi kesti', 19)}` +
  `${s('kilitli mesru hesap', 21)}`);
for (const [ad, he, ae] of [['hesap 5', 5, I], ['adres 50', I, 50],
  ['hesap 5 + adres 50', 5, 50], ['hesap 3 + adres 20', 3, 20]]) {
  const r = olc(K, he, ae);
  console.log(`${ad.padEnd(20)}${s(r.mesruHesapla, 19)}${s(r.mesruAdresle, 19)}${s(r.kilitliHesap, 21)}`);
}
console.log(`\npaylasilan cikis adresinden gelen mesru deneme: ` +
  `${K.filter((r) => r[3] === 'mesru' && r[2] === 'paylasilan-cikis').length}`);
```

```
onlem                                        asama  ele gecen                 mesru bedel
onlem yok                                        -         70                           0
hesap 3 + adres 20 esigi            calisma zamani         57       613 deneme, 315 hesap
ikinci etken, kapsam %86                       kod          5       2623 oturumda ek adim
esik ve ikinci etken                         ikisi          4         613 deneme, ek adim
parola belirlemede cift denetimi           tasarim          0   70 hesapta parola degisir

ikinci etken kapsami 1639/1900; kapsam disindaki 261 hesap her ayarda savunmasiz kaliyor

ayar                  hesap esigi kesti  adres esigi kesti  kilitli mesru hesap
hesap 5                             220                  0                   91
adres 50                              0                227                  164
hesap 5 + adres 50                  138                226                  194
hesap 3 + adres 20                  220                393                  315

paylasilan cikis adresinden gelen mesru deneme: 500
```

Üst tablo kursun ana sorusunu bu ders için yanıtlıyor. Çalışma zamanı eşiği kötü denemenin yüzde
elli üçünü engelledi ve ele geçirmeyi yetmişten elli yediye indirdi: önlenen ele geçirme oranı
yüzde on dokuz. Bunun nedeni eşiğin ayarında değil, tanımındadır. Eşik **başarısızlıkları** sayar;
doldurmada başarılı deneme hesabın gördüğü ilk denemedir ve o an sayaç boştur. Sayaç ancak
başarısızlıklar biriktikten sonra dolar, yani eşik geç kalmış olmayı yapısal olarak taşır.

Aynı ele geçirme kod aşamasında ikinci etkenle yetmişten beşe iniyor. Beşin sıfır olmamasının
nedeni de tabloda yazılı: ikinci etken kapsamı bin altı yüz otuz dokuz hesaptır ve kapsam dışında
kalan iki yüz altmış bir hesap hiçbir eşik ayarında korunmuyor. Kapsam, bu önlemin tek gerçek
ayarıdır. Bedeli ise iki bin altı yüz yirmi üç meşru oturumda ek bir adımdır; kesilen oturum
yoktur, geciken oturum vardır.

Tasarım aşamasındaki önlem daha da ucuza kapatıyor. Parola belirlenirken sızmış çift ve yaygın
parola denetimi yapıldığında doldurmanın da püskürtmenin de başarı koşulu ortadan kalkar: ele
geçen hesap sıfırdır. Bedeli yetmiş hesabın parola değiştirmesidir ve bu bir defalıktır. Çalışma
zamanı eşiği aynı kalem için her gün altı yüz on üç meşru denemeyi kesiyor ve üç yüz on beş
hesabı kilitliyor; tasarımdaki denetim kalemi bir kez kapatıyor.

Alt tablo yanlış kesmenin nereye düştüğünü ayırıyor. Hesap eşiği kesmeyi hesap sahibine, adres
eşiği ise bir ağ konumunun arkasındaki herkese yükler. Paylaşılan çıkış adresi arkasında beş yüz
meşru deneme duruyor ve adres eşiği yirmiye indirildiğinde bu adresten kesilen deneme üç yüz
doksan üçe çıkıyor. Adres eşiği, hedeflenen saldırgandan çok o adresin arkasındaki ekibin
büyüklüğüne göre ceza kesiyor.

#### Özet

- Üç saldırı biçimi iki eksende ayrışıyor: kaba kuvvet hesap başına 600 denemeyle hesap eşiğinde
  (596 engellendi), püskürtme adres başına 142,5 denemeyle adres eşiğinde (3.694 engellendi)
  durur; doldurma hesap başına 1,0 ve adres başına 10,0 denemeyle ikisinin de altındadır.
- Adres eşiği doldurmadan sıfır deneme engelledi. Alt tabloda görünen 15–18 deneme, aynı
  hesapların püskürtmeye de hedef olmasından gelen dolaylı bir yakalamadır.
- Eşiksiz koşumda 70 hesap ele geçti; en sıkı ayarda 57. Engellenen deneme 5.512'ye çıkarken
  önlenen ele geçirme yalnız 13'tür (yüzde 19), çünkü eşik başarısızlıkları sayar ve doldurmada
  başarılı deneme hesabın ilk denemesidir.
- Yanlış kesme iki ayrı yere düşüyor: hesap eşiği 5'te kilitlenen 91 hesabın yalnız 30'u
  parolasını unutan abonedir, kalanı saldırının hedefi olduğu için kilitlendi. Adres eşiği 50'de
  kesilen 227 denemenin tamamı paylaşılan çıkış adresindeki saha ekibine aittir.
- Aynı ele geçirme kod aşamasında ikinci etkenle 70'ten 5'e (kalan 5, kapsam dışındaki 261
  hesaptan), tasarımda parola belirleme denetimiyle 0'a iniyor. Tasarımdaki bedel 70 hesapta bir
  defalık parola değişimi; çalışma zamanı eşiğinin bedeli her gün 613 kesilen meşru denemedir.

#### Sonraki Adım

Bu dersin eşikleri de önceki iki dersin kuralları ve sayaçları da tek tek isteklere ya da
denemelere bakıyordu. Üçünün de ortak varsayımı, savunmanın istekle birlikte gelen bilgiye
bakmasıydı. Oysa çalışma zamanında sunucunun verdiği ve isteğin içeriğiyle hiç ilgisi olmayan
bir karar daha vardır: yanıtla birlikte gönderilen güvenlik başlıkları. Bunlar bir isteği
durdurmaz; tarayıcının ne yapmasına izin verildiğini belirler ve tek bir yerden yönetildiklerinde
arkalarındaki bütün uygulamaları aynı anda kapsarlar. Sonraki ders bu katmanı yakaladığı istekle
değil, **kapsadığı uygulama sayısıyla** ölçüyor ve asıl soruyu kapsamın dışında kalan uca
soruyor.

### Güvenlik Başlıkları Kapsamı

Source: https://academia.sh/tr/kurslar/calisma-zamani-guvenligi/guvenlik-basliklari-kapsami

Güvenlik başlıklarını uygulama içinden çıkarıp kenardan yönetmenin kapsadığı uç, uygulama ve istek sayısının dört ayrı sayımla ölçülmesi: kenardan geçmeyen tarayıcı yüzeyinin taşıdığı günlük istek, tarayıcı yüzeyi olmayan uçlarda yapılandırılmış ama etkisiz kalan hücre, sıkı bir kaynak kısıtlama politikasının kırdığı meşru sayfa sayısı ve politikanın sıkılaştırılabilmesi için kod aşamasında yapılması gereken iş.

Önceki üç ders isteğe bakan savunmaları ölçtü: kural kümesi isteğin biçimine, hız sayacı istek
sayısına, eşikler hesaba ve adrese baktı. Üçü de bir isteği durdurmaya ya da geçirmeye karar
veriyordu. Çalışma zamanında verilen bir karar daha vardır ve hiçbir isteği durdurmaz: yanıtla
birlikte gönderilen güvenlik başlıkları tarayıcının ne yapmasına izin verildiğini belirler.

Başlıkların ne yaptığı daha önceki bir kursta uygulama içinde ölçüldü ve burada tekrarlanmıyor.
Bu dersin ölçüsü başkadır: başlık yapılandırması uygulamadan çıkarılıp önlerindeki kenar
katmanına taşındığında **kaç uygulama ve kaç uç** aynı anda kapsanıyor, kapsamın dışında ne
kalıyor. Bu, "yakalanan istek" sayısı üretmeyen bir savunmadır; ölçüsü kapsamdır ve kapsam
sayılmadığında bir yapılandırma dosyası gerçek bir korumayla karıştırılır.

#### Başlık Nerede Yazılıyor

Bölgesel ölçüm ağının üretim ortamı `node` ile modelleniyor; gerçek bir sunucu ayağa
kaldırılmıyor ve hiçbir gerçek yanıt üretilmiyor.

- **US16.** On dört uç, dokuz uygulama, altı başlık ve günlük istek sayıları kurgusal ölçüm ağına
  aittir. Uçların bir bölümü ortak kenar katmanından geçiyor, bir bölümü doğrudan çağrılıyor.
- **US17.** "Tarayıcı yüzeyi" alanı, ucun bir tarayıcıya belge ya da tarayıcının yüklediği bir
  kaynak döndürüp döndürmediğini söyler. Güvenlik başlıkları yalnız tarayıcı yüzeyinde bir şey
  yapar; program arayüzünde yazılı olurlar ve hiçbir davranış değiştirmezler.
- **US18.** Kenardan yönetim, kenardan geçen her uca altı başlığın tamamını yazar. Kenardan
  geçmeyen uçta yalnız uygulamanın kendi yazdığı başlık kalır.
- **US19.** Kaynak kısıtlama politikası rapor kipinde koşturuluyor: engellenecek kaynak sayılıyor,
  gerçekten engellenmiyor. Kaynakların meşru olup olmadığı modelde biliniyor.
- **US20.** "Daha erken kapatma aşaması" sütunu her başlık için elle işaretlendi.

```js
// uc.mjs — uretim ortamindaki uc noktalari, alti guvenlik basligi ve sayfa kaynaklari; model
// [uc, uygulama, yol, tarayici yuzeyi mi, gunluk istek, uygulamanin kendi yazdigi baslik]
export const UC = [
  ['abone portali, sayfa', 'abone portali', 'kenar', true, 84000, 2],
  ['abone portali, program arayuzu', 'abone portali', 'kenar', false, 41000, 1],
  ['abone portali, kimlik dogrulama', 'abone portali', 'kenar', true, 6800, 2],
  ['saha uygulamasi, sayfa', 'saha uygulamasi', 'kenar', true, 12000, 0],
  ['saha uygulamasi, dosya yukleme', 'saha uygulamasi', 'kenar', false, 5400, 0],
  ['saha uygulamasi, mobil arka uc', 'saha uygulamasi', 'kenar', false, 22000, 0],
  ['fatura sayfasi', 'faturalama arayuzu', 'kenar', true, 9000, 3],
  ['rapor sayfasi', 'raporlama', 'kenar', true, 2600, 1],
  ['saglik yoklamasi', 'abone portali', 'kenar', false, 1440, 0],
  ['yonetim arayuzu', 'yonetim arayuzu', 'dogrudan', true, 900, 0],
  ['eski abone portali', 'eski portal', 'dogrudan', true, 3100, 1],
  ['duragan varlik konagi', 'varlik konagi', 'dogrudan', true, 62000, 0],
  ['sayac toplama arayuzu', 'sayac toplama', 'dogrudan', false, 150000, 0],
  ['faturalama servis arayuzu', 'faturalama servisi', 'dogrudan', false, 38000, 0],
];

// [baslik, durdurdugu kalem sinifi, daha erken kapatma asamasi]
export const BASLIK = [
  ['kaynak kisitlama politikasi', 'izinsiz betik yurutmesi', 'kod'],
  ['cerceveleme korumasi', 'sayfanin gomulmesi', 'yok'],
  ['tasima katmani zorlamasi', 'duz metin baglanti', 'yok'],
  ['icerik turu sabitlemesi', 'tur sezme', 'kod'],
  ['yonlendirici bilgisi politikasi', 'yolda sizan tanimlayici', 'kod'],
  ['tarayici yetenegi kisitlamasi', 'istenmeyen aygit erisimi', 'yok'],
];

// kenar yonetiminden sonra bir ucta yazili baslik sayisi
export const yazili = (u) => (u[2] === 'kenar' ? BASLIK.length : u[5]);
// bir baslik ancak tarayici yuzeyinde bir sey yapar
export const etkili = (u) => (u[3] ? yazili(u) : 0);

// [sayfa, kaynak, konum, mesru mu, gunluk yukleme]
export const KAYNAK = [
  ['abone portali, sayfa', 'uygulama betigi', 'ayni-koken', true, 84000],
  ['abone portali, sayfa', 'stil dosyasi', 'varlik-konagi', true, 84000],
  ['abone portali, sayfa', 'satir ici olcum betigi', 'satir-ici', true, 84000],
  ['abone portali, sayfa', 'bagimliliktan gelen ek betik', 'ucuncu-taraf', false, 84000],
  ['abone portali, kimlik dogrulama', 'form betigi', 'ayni-koken', true, 6800],
  ['abone portali, kimlik dogrulama', 'satir ici alan dogrulamasi', 'satir-ici', true, 6800],
  ['saha uygulamasi, sayfa', 'harita bileseni', 'varlik-konagi', true, 12000],
  ['saha uygulamasi, sayfa', 'satir ici durum betigi', 'satir-ici', true, 12000],
  ['fatura sayfasi', 'tablo betigi', 'ayni-koken', true, 9000],
  ['fatura sayfasi', 'yazi tipi', 'varlik-konagi', true, 9000],
  ['rapor sayfasi', 'cizim kitapligi', 'varlik-konagi', true, 2600],
  ['rapor sayfasi', 'enjekte satir ici betik', 'satir-ici', false, 2600],
];

export const POLITIKA = [
  ['yalniz ayni koken', (k) => k[2] === 'ayni-koken'],
  ['arti varlik konagi', (k) => ['ayni-koken', 'varlik-konagi'].includes(k[2])],
  ['arti satir ici toptan', (k) => ['ayni-koken', 'varlik-konagi', 'satir-ici'].includes(k[2])],
  ['arti satir ici karma', (k) => ['ayni-koken', 'varlik-konagi'].includes(k[2]) ||
    (k[2] === 'satir-ici' && k[3])],
];
```

#### Kapsama Nasıl Sayılırsa

```js
// kapsama.mjs — basligi kenardan yonetmenin kapsadigi uc, istek ve hucre
import { UC, BASLIK, yazili, etkili } from './uc.mjs';

const s = (x, n) => String(x).padStart(n);
const T = (f) => UC.filter(f).reduce((t, u) => t + u[4], 0);
const N = (f) => UC.filter(f).length;
console.log(`${UC.length} uc, ${new Set(UC.map((u) => u[1])).size} uygulama, ${BASLIK.length} baslik` +
  ` = ${UC.length * BASLIK.length} hucre; gunde ${T(() => true)} istek\n`);

console.log(`${'uc'.padEnd(33)}${s('yol', 10)}${s('tarayici', 10)}${s('gunluk', 8)}` +
  `${s('kendi yazdigi', 15)}${s('kenardan sonra', 16)}${s('etkili', 8)}`);
for (const u of UC)
  console.log(`${u[0].padEnd(33)}${s(u[2], 10)}${s(u[3] ? 'evet' : 'hayir', 10)}${s(u[4], 8)}` +
    `${s(u[5], 15)}${s(yazili(u), 16)}${s(etkili(u), 8)}`);

const sonra = UC.reduce((t, u) => t + yazili(u), 0), etk = UC.reduce((t, u) => t + etkili(u), 0);
console.log(`\n${'olcu'.padEnd(38)}${s('once', 8)}${s('kenardan sonra', 16)}`);
for (const [a, b, c] of [
  ['yazili baslik hucresi', UC.reduce((t, u) => t + u[5], 0), sonra],
  ['tarayici yuzeyinde etkili hucre', UC.reduce((t, u) => t + (u[3] ? u[5] : 0), 0), etk],
  ['baslik yazan uc sayisi', N((u) => u[5] > 0), N((u) => yazili(u) > 0)],
]) console.log(`${a.padEnd(38)}${s(b, 8)}${s(c, 16)}`);

console.log(`\n${'kapsama nasil sayilirsa'.padEnd(38)}${s('kapsanan', 10)}${s('toplam', 8)}${s('%', 8)}`);
for (const [a, b, c] of [
  ['uc sayisiyla', N((u) => u[2] === 'kenar'), UC.length],
  ['istek hacmiyle', T((u) => u[2] === 'kenar'), T(() => true)],
  ['tarayici yuzeyindeki istek hacmiyle', T((u) => u[2] === 'kenar' && u[3]), T((u) => u[3])],
  ['tarayici hucresiyle', etk, N((u) => u[3]) * BASLIK.length],
]) console.log(`${a.padEnd(38)}${s(b, 10)}${s(c, 8)}${s((100 * b / c).toFixed(1), 8)}`);

console.log(`\nkapsam disinda kalan tarayici yuzeyi (kenara alinsa kazanilan):`);
for (const u of UC.filter((x) => x[3] && x[2] !== 'kenar'))
  console.log(`  ${u[0].padEnd(24)}${s(u[4], 8)} istek/gun, ${s(BASLIK.length - u[5], 2)} hucre kazanilir`);
console.log(`\nyapilandirilmis ama etkisiz hucre (tarayici yuzeyi olmayan uclarda): ${sonra - etk}`);
```

```
14 uc, 9 uygulama, 6 baslik = 84 hucre; gunde 438240 istek

uc                                      yol  tarayici  gunluk  kendi yazdigi  kenardan sonra  etkili
abone portali, sayfa                  kenar      evet   84000              2               6       6
abone portali, program arayuzu        kenar     hayir   41000              1               6       0
abone portali, kimlik dogrulama       kenar      evet    6800              2               6       6
saha uygulamasi, sayfa                kenar      evet   12000              0               6       6
saha uygulamasi, dosya yukleme        kenar     hayir    5400              0               6       0
saha uygulamasi, mobil arka uc        kenar     hayir   22000              0               6       0
fatura sayfasi                        kenar      evet    9000              3               6       6
rapor sayfasi                         kenar      evet    2600              1               6       6
saglik yoklamasi                      kenar     hayir    1440              0               6       0
yonetim arayuzu                    dogrudan      evet     900              0               0       0
eski abone portali                 dogrudan      evet    3100              1               1       1
duragan varlik konagi              dogrudan      evet   62000              0               0       0
sayac toplama arayuzu              dogrudan     hayir  150000              0               0       0
faturalama servis arayuzu          dogrudan     hayir   38000              0               0       0

olcu                                      once  kenardan sonra
yazili baslik hucresi                       10              55
tarayici yuzeyinde etkili hucre              9              31
baslik yazan uc sayisi                       6              10

kapsama nasil sayilirsa                 kapsanan  toplam       %
uc sayisiyla                                   9      14    64.3
istek hacmiyle                            184240  438240    42.0
tarayici yuzeyindeki istek hacmiyle       114400  180400    63.4
tarayici hucresiyle                           31      48    64.6

kapsam disinda kalan tarayici yuzeyi (kenara alinsa kazanilan):
  yonetim arayuzu              900 istek/gun,  6 hucre kazanilir
  eski abone portali          3100 istek/gun,  5 hucre kazanilir
  duragan varlik konagi      62000 istek/gun,  6 hucre kazanilir

yapilandirilmis ama etkisiz hucre (tarayici yuzeyi olmayan uclarda): 24
```

Kenardan yönetimin kazancı ilk özet tablosunda yazılı ve küçük değildir: yazılı başlık hücresi
ondan elli beşe çıkıyor, yani tek bir yapılandırma değişikliği kırk beş hücreyi aynı anda
dolduruyor. Uygulama içinde bu iş dokuz ayrı kod tabanında dokuz kez yapılırdı ve beş uygulama
hiç yapmamıştı. Kenar katmanının gerçek üstünlüğü budur: kapsam, uygulama ekiplerinin ayrı ayrı
vereceği kararlardan çıkarılmıştır.

İkinci tablo aynı kapsamı dört ayrı sayımla veriyor ve dördü farklı sayı üretiyor: uç sayısıyla
yüzde 64,3, istek hacmiyle yüzde 42,0, tarayıcı yüzeyindeki istek hacmiyle yüzde 63,4, tarayıcı
hücresiyle yüzde 64,6. Aynı katman için dört farklı kapsama oranı yazılabiliyor ve hangisinin
raporlandığı bir tercihtir. İstek hacmi sayımının düşük çıkmasının nedeni sayaç toplama
arayüzünün günde yüz elli bin istek taşıması, ancak o ucun bir tarayıcıdan çağrılmamasıdır; o
uçta başlık olsa da olmasa da hiçbir şey değişmez. Bu yüzden anlamlı sayım üçüncüsüdür: tarayıcı
yüzeyindeki isteğin ne kadarı kapsanıyor.

Alt liste asıl bulguyu veriyor. Kapsam dışında kalan üç uç var ve bunlardan biri günde altmış iki
bin istek taşıyan durağan varlık konağıdır. Uygulama envanterinde bir "uygulama" olarak
görünmediği için kapsama tablolarında hiç sayılmaz; oysa tarayıcı ondan gelen kaynakları
yüklüyor ve o kaynaklar hiçbir başlık taşımıyor. Yönetim arayüzü ile eski abone portalı toplam
dört bin istek eder, yani kapsam dışı hacmin yüzde altısı. Kapsamı genişletme işinin sırasını bu
liste belirler ve envantere hiç girmemiş uç, sıradaki en büyük kalemdir.

Son satır ters yöndeki kusuru sayıyor: yirmi dört hücre yapılandırılmış ama etkisizdir. Program
arayüzü uçlarında altı başlık da yazılıdır, denetim listesinde yeşil görünürler ve hiçbir
davranış değiştirmezler. Yapılandırma sayısı bir koruma ölçüsü değildir.

#### Sıkı Politikanın Kırdığı Sayfa

Kapsam bir yanlış pozitif üretmez; başlığın **içeriği** üretir. Kaynak kısıtlama politikası
sıkılaştırıldığında engellenen şey yalnız izinsiz betik değil, sayfanın kendi kaynaklarıdır.

```js
// politika.mjs — kaynak kisitlama politikasini rapor kipinde kosturup kirilan mesru kaynagi saymak
import { UC, BASLIK, KAYNAK, POLITIKA, yazili } from './uc.mjs';

const s = (x, n) => String(x).padStart(n);
const kapsanan = new Set(UC.filter((u) => u[3] && yazili(u) === BASLIK.length).map((u) => u[0]));
const K = KAYNAK.filter((k) => kapsanan.has(k[0]));
console.log(`politika yalniz kenardan yonetilen ${kapsanan.size} tarayici ucunda gecerli;` +
  ` bu uclarda ${K.length} kaynak var\n`);

console.log(`${'politika'.padEnd(24)}${s('engellenen mesru', 18)}${s('kirilan sayfa', 15)}` +
  `${s('engellenen kotu', 17)}${s('gecen kotu', 12)}`);
for (const [ad, izin] of POLITIKA) {
  const eng = K.filter((k) => !izin(k)), m = eng.filter((k) => k[3]);
  console.log(`${ad.padEnd(24)}${s(m.length, 18)}${s(new Set(m.map((k) => k[0])).size, 15)}` +
    `${s(eng.filter((k) => !k[3]).length, 17)}${s(K.filter((k) => izin(k) && !k[3]).length, 12)}`);
}

const satirIci = K.filter((k) => k[2] === 'satir-ici' && k[3]);
const izin2 = POLITIKA[1][1], kodSonrasi = K.filter((k) => k[2] !== 'satir-ici' || !k[3]);
console.log(`\nkarma listesine yazilmasi gereken satir ici betik: ${satirIci.length}`);
console.log(`satir ici betikler kod asamasinda kaldirilirsa "arti varlik konagi" politikasi:` +
  ` engellenen mesru ${kodSonrasi.filter((k) => k[3] && !izin2(k)).length},` +
  ` gecen kotu ${kodSonrasi.filter((k) => !k[3] && izin2(k)).length}`);

console.log(`\n${'baslik'.padEnd(33)}${'durdurdugu kalem'.padEnd(26)}${s('erken asama', 13)}`);
for (const [ad, kalem, asama] of BASLIK)
  console.log(`${ad.padEnd(33)}${kalem.padEnd(26)}${s(asama, 13)}`);
const yok = BASLIK.filter((b) => b[2] === 'yok');
console.log(`\nyalniz bu katmanda kapatilabilen baslik ${yok.length}/${BASLIK.length};` +
  ` bunlarin etkili oldugu uc ${UC.filter((u) => u[3] && yazili(u) === BASLIK.length).length},` +
  ` gunde ${UC.filter((u) => u[3] && yazili(u) === BASLIK.length).reduce((t, u) => t + u[4], 0)} istek`);
```

```
politika yalniz kenardan yonetilen 5 tarayici ucunda gecerli; bu uclarda 12 kaynak var

politika                  engellenen mesru  kirilan sayfa  engellenen kotu  gecen kotu
yalniz ayni koken                        7              5                2           0
arti varlik konagi                       3              3                2           0
arti satir ici toptan                    0              0                1           1
arti satir ici karma                     0              0                2           0

karma listesine yazilmasi gereken satir ici betik: 3
satir ici betikler kod asamasinda kaldirilirsa "arti varlik konagi" politikasi: engellenen mesru 0, gecen kotu 0

baslik                           durdurdugu kalem            erken asama
kaynak kisitlama politikasi      izinsiz betik yurutmesi             kod
cerceveleme korumasi             sayfanin gomulmesi                  yok
tasima katmani zorlamasi         duz metin baglanti                  yok
icerik turu sabitlemesi          tur sezme                           kod
yonlendirici bilgisi politikasi  yolda sizan tanimlayici             kod
tarayici yetenegi kisitlamasi    istenmeyen aygit erisimi            yok

yalniz bu katmanda kapatilabilen baslik 3/6; bunlarin etkili oldugu uc 5, gunde 114400 istek
```

Dört satır bir sıkılık eğrisidir. En sıkı politika iki kötü kaynağı engelliyor ve yanında yedi
meşru kaynağı da engelleyerek beş sayfanın tamamını kırıyor; kapsanan her tarayıcı ucu bozulmuş
demektir. Varlık konağına izin verilince kırılan sayfa üçe iner, kötü kaynak yine ikidir. Üçüncü
satır üretimde en sık görülen kaçış yoludur: satır içi betiklere toptan izin verilir, kırılan
sayfa sıfıra iner — ve rapor sayfasındaki enjekte satır içi betik de aynı izinle geçer. Kırılan
sayfa sayısını sıfırlayan bu ayar, politikanın engellediği kötü kaynağı ikiden bire düşürür.

Dördüncü satır ikisini birden veriyor: satır içi betiklere karma listesiyle izin verildiğinde
kırılan sayfa sıfır, engellenen kötü kaynak ikidir. Bedeli listenin kendisidir. Üç satır içi
betik karma listesine yazılmalıdır ve bu betiklerden biri değiştiğinde liste güncellenmezse
sayfa kırılır. Politika artık bir başlık değeri değil, kodun her sürümünde bakılacak bir
envanterdir — birinci dersteki muafiyet listesiyle aynı türden bir yük.

Bir alt satır kursun sorusunu yanıtlıyor. Satır içi betikler kod aşamasında kaldırılırsa "artı
varlık konağı" politikası hem sıfır meşru kaynak engelliyor hem de sıfır kötü kaynak geçiriyor:
karma listesine gerek kalmıyor. Başlık aynı sonucu ancak sürekli bakım karşılığında veriyor.
Alt tablo bu ayrımı altı başlığa yayıyor: üçünün durdurduğu kalem kod aşamasında kapatılabilir,
üçünün aşaması yoktur. Bu üçü tarayıcının davranışını belirler ve uygulama kodundan söylenemez;
katmanın karşılıksız payı budur ve beş uçta, günde yüz on dört bin dört yüz istekte geçerlidir.

#### Özet

- Başlığı kenardan yönetmek yazılı hücreyi 10'dan 55'e, başlık yazan ucu 6'dan 10'a çıkardı; kapsam artık uygulama ekiplerinin ayrı kararlarına bağlı değildir.
- Aynı kapsam dört ayrı sayımla dört ayrı oran veriyor: uç sayısıyla yüzde 64,3, istek hacmiyle
  yüzde 42,0, tarayıcı yüzeyindeki istek hacmiyle yüzde 63,4, tarayıcı hücresiyle yüzde 64,6.
  Anlamlı olan üçüncüsüdür; ötekiler tarayıcının hiç görmediği uçları da sayar.
- Kapsam dışında üç tarayıcı ucu kaldı ve bunların 66.000 isteğinin 62.000'i envanterde
  "uygulama" olarak görünmeyen durağan varlık konağına aittir. Buna karşılık 24 hücre
  yapılandırılmış ama etkisizdir: program arayüzü uçlarında başlık yazılıdır, bir şey yapmaz.
- Kaynak kısıtlama politikası en sıkı ayarda 2 kötü kaynağı engellerken 7 meşru kaynağı da
  engelledi ve 5 sayfanın hepsini kırdı. Satır içi betiğe toptan izin kırılmayı sıfırladı ama
  engellenen kötü kaynağı 2'den 1'e düşürdü; karma listesi ikisini birden verdi (0 kırılan,
  2 engellenen) ve karşılığında 3 satırlık bir bakım envanteri getirdi.
- Satır içi betikler kod aşamasında kaldırılırsa politika karma listesi olmadan 0 kırılan ve
  0 geçen kötü kaynak veriyor. Altı başlığın üçünün durdurduğu kalem kod aşamasında kapanır;
  yalnız bu katmanda kapatılabilen üç başlık 5 uçta, günde 114.400 istekte geçerlidir.

#### Sonraki Adım

Bu dersin ölçüsü kapsamdı ve kapsam bir yanıtla birlikte gönderilen değerlerle sağlandı. Önceki
üç ders ise isteğin biçimine, sayısına ve kimliğine baktı. Dördünün de ortak sınırı aynıdır:
karar tek bir istek ya da tek bir yanıt üzerinde veriliyor. Oysa birinci dersten beri hiçbir
ayarda durdurulamayan kalem — iş akışı dışı toplu indirme — tek tek isteklerde kusursuz
görünüyordu; yanlış olan tek şey aynı oturumun isteklerinin **birlikte çizdiği şekildi**. Sonraki
ders savunmayı isteğin dışına çıkarıp oturumun davranışına bakıyor, taban çizgisinden sapan
oturumu anormallik puanıyla işaretliyor ve asıl soruyu oraya soruyor: sapma başladıktan kaç
dakika sonra.

### Uygulama Düzeyinde Anormallik Tespiti

Source: https://academia.sh/tr/kurslar/calisma-zamani-guvenligi/uygulama-duzeyinde-anormallik-tespiti

Rol taban çizgisine göre puanlanan yedi oturumun kırk beş dakikalık davranış kaydında koşturulması ve işaretleme eşiğinin dört ayarda karşılaştırılması: sapmanın başladığı dakika ile işaretin düştüğü dakika arasındaki gecikme, o gecikmede dışarı çıkan kayıt sayısı, yavaş sapan iç tehdit oturumu ile fatura dönemindeki meşru analist oturumunun puan farkı ve aynı sızıntının tasarım aşamasında kaç kayıt önce kapatıldığı.

Önceki dört ders isteğe baktı: kural kümesi biçime, hız sayacı sayıya, eşikler hesaba ve adrese,
başlıklar yanıta. Dördü de kararını tek bir istek ya da tek bir yanıt üzerinde verdi. Birinci
dersten beri hiçbir ayarda durdurulamayan kalem de tam bu yüzden kaçtı: iş akışı dışı toplu
indirmenin istekleri tek tek kusursuzdu, kimliği doğrulanmıştı, yetkisi vardı. Yanlış olan tek
şey aynı oturumun isteklerinin **birlikte çizdiği şekildi**.

Bu ders savunmayı isteğin dışına çıkarıp oturumun davranışına taşıyor. Ölçü de değişiyor:
durdurulan istek yerine **gecikme** sayılıyor — sapma başladıktan kaç dakika sonra işaret düşüyor
ve o dakikalarda ne kadar veri dışarı çıkıyor. Bu katman bir isteği engellemez; bir oturumu geç
ya da erken işaretler.

#### Taban Çizgisi ve Anormallik Puanı

Aşağıdaki her şey `node` ile kurulan bir modeldir; gerçek bir oturum kaydı okunmuyor ve hiçbir
oturum ele geçirme yöntemi yazılmıyor. Ele geçmiş oturumlar yalnız davranış vektörleriyle,
yani dakikadaki istek, benzersiz uç, kayıt ve ilk kez görülen uç sayısıyla temsil ediliyor.

- **US21.** Yedi oturum, üç rol taban çizgisi ve kırk beş dakikalık pencere kurgusal ölçüm ağına
  aittir. Taban çizgisi otuz günlük olağan davranışın ortalaması olarak veriliyor.
- **US22.** Puan, her özelliğin taban çizgisine oranından türer ve özellik başına sapma payı iki
  birimle sınırlanır. Tavan olmasaydı tek bir uç değer oturumu anında işaretlerdi; gerçek
  puanlama düzeneklerinde de böyle bir doyum vardır.
- **US23.** İşaret, son beş dakikanın puan toplamı eşiği aştığında düşer. Yığın penceresi
  sabittir; değişen tek şey eşiktir.
- **US24.** Meşru oturumlardan ikisi kasten olağan dışıdır: fatura dönemindeki analistin kayıt
  hacmi taban çizgisinin iki buçuk katına çıkıyor, yeni başlayan saha teknisyeninin ise ilk kez
  görülen uç sayısı yüksek. İkisi de yanlış işaret adayıdır.
- **US25.** "Daha erken kapatma aşaması" sütunu her kötü oturum için elle işaretlendi.

```js
// davranis.mjs — kirk bes dakikalik oturum davranis kaydi ve anormallik puanlamasi; model
export const SURE = 45;
export const OZELLIK = ['istek/dk', 'benzersiz uc', 'kayit/dk', 'ilk kez gorulen uc'];
export const AGIRLIK = [1, 1.5, 2, 2.5];
export const TAVAN = 2;   // ozellik basina sapma payi tavani

// rol taban cizgisi: otuz gunluk olagan davranistan cikarilmis ortalama
export const TABAN = {
  abone: [4, 3, 12, 0.2],
  saha: [9, 5, 40, 0.4],
  analist: [6, 7, 300, 0.3],
};

// [oturum, rol, gercek sinif, sapma dakikasi, sapma carpanlari, kac dakikada tam carpan, erken asama]
export const OTURUM = [
  ['abone-3391', 'abone', 'mesru', Infinity, [1, 1, 1, 1], 1, '-'],
  ['saha-12, vardiya', 'saha', 'mesru', Infinity, [1, 1, 1, 1], 1, '-'],
  ['analist-4, fatura donemi', 'analist', 'mesru', 0, [1.2, 1.1, 2.6, 1.3], 4, '-'],
  ['saha-58, yeni baslayan', 'saha', 'mesru', 0, [0.8, 1.8, 0.9, 6.0], 3, '-'],
  ['abone-8842, ele gecmis', 'abone', 'kotu', 12, [3.5, 2.5, 22, 5], 3, 'kod'],
  ['analist-9, ic tehdit', 'analist', 'kotu', 8, [1.4, 1.3, 2.2, 1.5], 12, 'tasarim'],
  ['saha-31, calinan jeton', 'saha', 'kotu', 20, [2.2, 4.4, 3.5, 9], 2, 'yok'],
];

// bir oturumun dakika dakika ozellik vektoru
export function kayit(o) {
  const [, rol, , sapma, carpan, ramp] = o, t0 = TABAN[rol], d = [];
  for (let t = 0; t < SURE; t++) {
    const f = t < sapma ? 0 : Math.min(1, (t - sapma + 1) / ramp);
    d.push(t0.map((b, i) => b * (1 + (carpan[i] - 1) * f)));
  }
  return d;
}

export const puan = (v, rol) =>
  v.reduce((t, x, i) => t + AGIRLIK[i] * Math.min(TAVAN, Math.max(0, x / TABAN[rol][i] - 1)), 0);

export const yigin = (o, pen = 5) => {
  const p = kayit(o).map((v) => puan(v, o[1]));
  return p.map((_, t) => p.slice(Math.max(0, t - pen + 1), t + 1).reduce((x, y) => x + y, 0));
};

// son `pen` dakikanin puan toplami esigi asinca oturum isaretlenir
export function isaretle(o, esik, pen = 5) {
  const d = kayit(o), p = d.map((v) => puan(v, o[1]));
  for (let t = 0; t < SURE; t++) {
    const yig = p.slice(Math.max(0, t - pen + 1), t + 1).reduce((x, y) => x + y, 0);
    if (yig >= esik) {
      const bas = Number.isFinite(o[3]) ? o[3] : 0;
      const kayitSayisi = d.slice(bas, t + 1).reduce((x, v) => x + v[2], 0);
      return { dakika: t, gecikme: t - bas, kayitSayisi: Math.round(kayitSayisi) };
    }
  }
  return null;
}
```

#### Kaç Dakika Gecikmeyle

```js
// kosum.mjs — ayni davranis kaydi, degisen tek sey isaretleme esigi
import { SURE, OTURUM, kayit, puan, yigin, isaretle } from './davranis.mjs';

const s = (x, n) => String(x).padStart(n);
console.log(`${OTURUM.length} oturum, ${SURE} dakika, 3 rol taban cizgisi\n`);
console.log(`${'oturum'.padEnd(26)}${s('rol', 9)}${s('sinif', 7)}${s('sapma dk', 10)}` +
  `${s('en yuksek dk puani', 20)}${s('en yuksek yigin', 17)}${s('toplam kayit', 14)}${s('erken asama', 13)}`);
for (const o of OTURUM) {
  const d = kayit(o), p = d.map((v) => puan(v, o[1]));
  console.log(`${o[0].padEnd(26)}${s(o[1], 9)}${s(o[2], 7)}` +
    `${s(Number.isFinite(o[3]) ? o[3] : '-', 10)}${s(Math.max(...p).toFixed(2), 20)}` +
    `${s(Math.max(...yigin(o)).toFixed(1), 17)}` +
    `${s(Math.round(d.reduce((x, v) => x + v[2], 0)), 14)}${s(o[6], 13)}`);
}

console.log(`\n${'esik'.padEnd(6)}${s('isaretlenen kotu', 18)}${s('kacirilan kotu', 16)}` +
  `${s('yanlis isaretlenen', 20)}${s('ortalama gecikme dk', 21)}${s('gecikmede inen kayit', 22)}`);
const K = OTURUM.filter((o) => o[2] === 'kotu'), M = OTURUM.filter((o) => o[2] === 'mesru');
for (const esik of [40, 30, 20, 12]) {
  const ik = K.filter((o) => isaretle(o, esik)), im = M.filter((o) => isaretle(o, esik));
  const g = ik.map((o) => isaretle(o, esik));
  console.log(`${String(esik).padEnd(6)}${s(`${ik.length}/${K.length}`, 18)}` +
    `${s(K.length - ik.length, 16)}${s(`${im.length}/${M.length}`, 20)}` +
    `${s((g.reduce((x, r) => x + r.gecikme, 0) / g.length).toFixed(1), 21)}` +
    `${s(g.reduce((x, r) => x + r.kayitSayisi, 0), 22)}`);
}

for (const esik of [30, 20]) {
  console.log(`\nesik ${esik}, oturum oturum:`);
  console.log(`  ${'oturum'.padEnd(26)}${s('sinif', 7)}${s('isaret dk', 15)}${s('gecikme dk', 12)}` +
    `${s('gecikmede inen kayit', 22)}`);
  for (const o of OTURUM) {
    const r = isaretle(o, esik);
    console.log(`  ${o[0].padEnd(26)}${s(o[2], 7)}${s(r ? r.dakika : 'isaretlenmedi', 15)}` +
      `${s(r ? r.gecikme : '-', 12)}${s(r && o[2] === 'kotu' ? r.kayitSayisi : '-', 22)}`);
  }
}
```

```
7 oturum, 45 dakika, 3 rol taban cizgisi

oturum                          rol  sinif  sapma dk  en yuksek dk puani  en yuksek yigin  toplam kayit  erken asama
abone-3391                    abone  mesru         -                0.00              0.0           540            -
saha-12, vardiya               saha  mesru         -                0.00              0.0          1800            -
analist-4, fatura donemi    analist  mesru         0                4.30             21.5         34380            -
saha-58, yeni baslayan         saha  mesru         0                6.20             31.0          1624            -
abone-8842, ele gecmis        abone   kotu        12               13.25             66.3          8604          kod
analist-9, ic tehdit        analist   kotu         8                4.50             22.5         24840      tasarim
saha-31, calinan jeton         saha   kotu        20               13.20             66.0          4250          yok

esik    isaretlenen kotu  kacirilan kotu  yanlis isaretlenen  ortalama gecikme dk  gecikmede inen kayit
40                   2/3               1                 0/4                  3.0                  1314
30                   2/3               1                 1/4                  2.0                   910
20                   3/3               0                 2/4                  4.7                  7106
12                   3/3               0                 2/4                  3.3                  4556

esik 30, oturum oturum:
  oturum                      sinif      isaret dk  gecikme dk  gecikmede inen kayit
  abone-3391                  mesru  isaretlenmedi           -                     -
  saha-12, vardiya            mesru  isaretlenmedi           -                     -
  analist-4, fatura donemi    mesru  isaretlenmedi           -                     -
  saha-58, yeni baslayan      mesru              5           5                     -
  abone-8842, ele gecmis       kotu             14           2                   540
  analist-9, ic tehdit         kotu  isaretlenmedi           -                     -
  saha-31, calinan jeton       kotu             22           2                   370

esik 20, oturum oturum:
  oturum                      sinif      isaret dk  gecikme dk  gecikmede inen kayit
  abone-3391                  mesru  isaretlenmedi           -                     -
  saha-12, vardiya            mesru  isaretlenmedi           -                     -
  analist-4, fatura donemi    mesru              6           6                     -
  saha-58, yeni baslayan      mesru              3           3                     -
  abone-8842, ele gecmis       kotu             13           1                   276
  analist-9, ic tehdit         kotu             20          12                  6600
  saha-31, calinan jeton       kotu             21           1                   230
```

İlk tablonun iki satırı yan yana okunmalıdır. Fatura dönemindeki meşru analistin en yüksek beş
dakikalık yığını 21,5, iç tehdit oturumunun 22,5. Aradaki fark bir birimdir ve puanlamanın gördüğü
her şey bu farktan ibarettir. İkisi de aynı rolde, taban çizgisinin birkaç katı
hacimle çalışıyor; birinin yaptığı dönem sonu raporu, ötekinin sızdırma. Puanlama bu iki
oturumu ayıramaz, çünkü ayrım davranışta değil **niyettedir** — birinci dersteki kural kümesinin
sınırının aynısı, bir katman yukarıda.

Eşik tablosu bunun sonucunu veriyor. Eşik kırkta hiçbir meşru oturum işaretlenmiyor, ortalama
gecikme üç dakika, ama iç tehdit hiç yakalanmıyor: yığını hiçbir zaman kırka ulaşmıyor. Eşik
otuzda tablo daha da iyi görünür — gecikme iki dakikaya, gecikmede inen kayıt dokuz yüz ona
düşer — ama iç tehdit yine kaçıyor ve yeni başlayan saha teknisyeni yanlış işaretleniyor. İç
tehdidin yakalandığı ilk ayar yirmidir ve orada dört sayının üçü birden kötüleşir: yanlış
işaretlenen oturum ikiye, ortalama gecikme 4,7 dakikaya, gecikmede inen kayıt yedi bin yüz altıya
çıkar.

Oturum bazlı iki liste gecikmenin nereden geldiğini gösteriyor. Ele geçmiş abone oturumu ile
çalınan jeton oturumu hızlı sapıyor ve bir ya da iki dakikada işaretleniyor; ikisinin gecikmede
çıkardığı kayıt iki yüz otuz ile beş yüz kırk arasındadır. İç tehdit ise on iki dakika sonra
işaretleniyor ve o sürede altı bin altı yüz kayıt indiriyor — üç kötü oturumun toplam
gecikme maliyetinin yüzde doksan üçü. Yavaş sapan oturum hem en geç yakalanandır hem de en çok
veri çıkarandır; gecikme ile zarar aynı yönde büyür.

#### Gecikmenin Nereye Ait Olduğu

```js
// asama.mjs — ayni sizintiyi daha erken hangi asama, kac kayit onceden kapatir
import { SURE, OTURUM, TABAN, kayit, isaretle } from './davranis.mjs';

const s = (x, n) => String(x).padStart(n);
const bul = (ad) => OTURUM.find((o) => o[0].startsWith(ad));
const tehdit = bul('analist-9'), donem = bul('analist-4'), T = TABAN.analist[2];
const kum = (o) => kayit(o).reduce((a, v) => (a.push((a.at(-1) || 0) + v[2]), a), []);
const fazla = (o, t) => Math.round(kum(o)[t] - T * (t + 1));
const tavanla = (o, tavan) => {
  const k = kum(o), t = k.findIndex((x) => x >= tavan);
  return t < 0 ? { dk: 'kesilmedi', t: SURE - 1 } : { dk: `${t}. dk`, t };
};

console.log(`analist rolunun taban cizgisi ${T} kayit/dk; ${SURE} dakikalik olagan is ${T * SURE} kayit`);
console.log(`ic tehdit oturumu toplam ${Math.round(kum(tehdit).at(-1))} kayit indirdi,` +
  ` taban ustu ${fazla(tehdit, SURE - 1)}\n`);

console.log(`${'onlem'.padEnd(32)}${s('asama', 16)}${s('taban ustu kayit', 18)}${s('mesru bedel', 30)}`);
const e20 = isaretle(tehdit, 20), e40 = isaretle(tehdit, 40);
for (const [a, b, c, d] of [
  ['onlem yok', '-', fazla(tehdit, SURE - 1), '0'],
  ['anormallik esigi 40', 'calisma zamani', e40 ? fazla(tehdit, e40.dakika) : fazla(tehdit, SURE - 1),
    'yanlis isaret yok'],
  ['anormallik esigi 20', 'calisma zamani', fazla(tehdit, e20.dakika),
    `donem analisti ${isaretle(donem, 20).dakika}. dk isaretli`],
  ['rol basina kayit tavani 18000', 'tasarim', fazla(tehdit, tavanla(tehdit, 18000).t),
    `donem analisti ${tavanla(donem, 18000).dk} kesilir`],
  ['toplu cikarma kuyruk isine alinir', 'tasarim', 0, 'toplu is onaya girer'],
]) console.log(`${a.padEnd(32)}${s(b, 16)}${s(c, 18)}${s(d, 30)}`);

console.log(`\n${'tavan'.padEnd(8)}${s('ic tehdit kesildi', 19)}${s('taban ustu kayit', 18)}` +
  `${s('donem analisti kesildi', 24)}${s('kesilen mesru kayit', 21)}`);
for (const tv of [13500, 18000, 25000]) {
  const a = tavanla(tehdit, tv), b = tavanla(donem, tv);
  console.log(`${String(tv).padEnd(8)}${s(a.dk, 19)}${s(fazla(tehdit, a.t), 18)}${s(b.dk, 24)}` +
    `${s(Math.round(kum(donem).at(-1) - kum(donem)[b.t]), 21)}`);
}

console.log(`\n${'kotu oturum'.padEnd(26)}${s('esik 20 gecikme', 17)}${s('erken asama', 13)}${s('orada kapanan', 16)}`);
const NE = { kod: 'ikinci etken', tasarim: 'is akisi', yok: 'yok' };
for (const o of OTURUM.filter((x) => x[2] === 'kotu'))
  console.log(`${o[0].padEnd(26)}${s(`${isaretle(o, 20).gecikme} dk`, 17)}${s(o[6], 13)}${s(NE[o[6]], 16)}`);
```

```
analist rolunun taban cizgisi 300 kayit/dk; 45 dakikalik olagan is 13500 kayit
ic tehdit oturumu toplam 24840 kayit indirdi, taban ustu 11340

onlem                                      asama  taban ustu kayit                   mesru bedel
onlem yok                                      -             11340                             0
anormallik esigi 40               calisma zamani             11340             yanlis isaret yok
anormallik esigi 20               calisma zamani              2700 donem analisti 6. dk isaretli
rol basina kayit tavani 18000            tasarim              7740 donem analisti 23. dk kesilir
toplu cikarma kuyruk isine alinir         tasarim                 0          toplu is onaya girer

tavan     ic tehdit kesildi  taban ustu kayit  donem analisti kesildi  kesilen mesru kayit
13500                27. dk              5220                  18. dk                20280
18000                34. dk              7740                  23. dk                16380
25000             kesilmedi             11340                  32. dk                 9360

kotu oturum                 esik 20 gecikme  erken asama   orada kapanan
abone-8842, ele gecmis                 1 dk          kod    ikinci etken
analist-9, ic tehdit                  12 dk      tasarim        is akisi
saha-31, calinan jeton                 1 dk          yok             yok
```

Üst tablo kaba bir tasarım önleminin çalışma zamanı puanlamasından **daha kötü** olabileceğini
gösteriyor. Rol başına on sekiz binlik bir kayıt tavanı iç tehdidin taban üstü çıkardığı kaydı
yalnız on bir bin üç yüz kırktan yedi bin yedi yüz kırka indiriyor; anormallik eşiği yirmi aynı
kalemi iki bin yedi yüzde durduruyor. Orta tablo tavanın neden bu kadar zayıf kaldığını yazıyor:
tavanı iç tehdidi erken kesecek kadar indirmek gerekir, ama on üç bin beş yüzlük tavan fatura
dönemi analistini on sekizinci dakikada kesip yirmi bin iki yüz seksen meşru kaydı dışarıda
bırakıyor. Sabit bir sayı, dönemsel iş yükü olan bir rolde ayarlanamaz.

Ayarlanabilen şey iş akışının kendisidir. Toplu çıkarma etkileşimli uçtan alınıp onaylı bir
kuyruk işine taşındığında oturumun taban üstü çıkarabileceği kayıt sıfırdır: iç tehdit oturumu o
hacmi üretemez, çünkü etkileşimli uçta o yetenek yoktur. Meşru bedel de daha küçüktür — dönem
analistinin toplu işi kesilmez, onaya girer ve gecikir. Bu, tasarımda bir kez verilen
karardır; her gün eşik ayarlamayı gerektirmez.

Alt tablo üç kötü oturumu ayırıyor. Ele geçmiş abone oturumu bir dakika gecikmeyle
yakalanıyor, ama zaten daha ucuzu vardı: aynı ele geçirmeyi üçüncü ders ikinci etkenle yetmişten
beşe indirmişti. İç tehdit on iki dakika gecikmeyle yakalanıyor ve doğru yeri iş akışıdır.
Çalınan jeton oturumu için ise erken aşama yoktur; jeton geçerlidir, kimlik doğrulaması
başarılıdır ve hiçbir tasarım ya da kod kararı geçerli bir kimlik bilgisini geçersiz kılmaz.
Bu katmanın karşılıksız payı o tek satırdır — ve o satır bile bir dakikalık gecikme taşır.

#### Özet

- Fatura dönemindeki meşru analistin en yüksek beş dakikalık yığını 21,5, iç tehdit oturumunun
  22,5. Puanlamanın iki oturum arasında gördüğü fark bir birimdir; ayrım davranışta değil
  niyettedir.
- Eşik 40 ve 30, hiçbir meşru oturumu ya da yalnız birini işaretleyip iç tehdidi kaçırıyor.
  İç tehdidin yakalandığı ilk ayar 20'dir ve orada yanlış işaretlenen oturum 2/4'e, ortalama
  gecikme 4,7 dakikaya, gecikmede inen kayıt 7.106'ya çıkar.
- Hızlı sapan iki oturum 1–2 dakikada işaretlendi ve gecikmede 230–540 kayıt çıkardı. Yavaş
  sapan iç tehdit 12 dakikada işaretlendi ve 6.600 kayıt çıkardı: toplam gecikme maliyetinin
  yüzde 93'ü. Gecikme ile zarar aynı yönde büyür.
- Kaba bir tasarım önlemi çalışma zamanından kötü olabilir: 18.000'lik kayıt tavanı taban üstü
  sızıntıyı 7.740'ta, anormallik eşiği 20 ise 2.700'de durdurdu. 13.500'lük tavan iç tehdidi 27.
  dakikada keserken dönem analistinin 20.280 meşru kaydını da kesiyor.
- Toplu çıkarmanın onaylı kuyruk işine alınması taban üstü kaydı sıfırlıyor ve meşru işi kesmiyor,
  yalnız geciktiriyor. Üç kötü oturumdan biri kod aşamasında (ikinci etken), biri tasarımda (iş
  akışı) kapanıyor; çalınan jeton oturumu için erken aşama yoktur.

#### Sonraki Adım

Bu konu istek katmanında ne yakalandığını ve neyin yanlış kesildiğini beş derste saydı: kural
kümesi, hız sınırı, hesap ve adres eşikleri, başlık kapsamı, oturum davranışı. Her derste bir
kalem sınıfı için "burada değil, daha erken kapanırdı" yazıldı ve her derste bir tane de tersi
çıktı — yalnız burada kapatılabilen bir sınıf.

Bu dersin çalınan jeton oturumu tam olarak o sınıftandır ve bıraktığı soru bütün konuyu aşıyor.
O oturum işaretlendi, ama işaretlenmesini gerektiren şey jetonun **hâlâ geçerli olmasıydı**. Beş
dersin savunmaları da aynı varsayıma dayanır: arkalarında duran anahtarlar, jetonlar ve kimlik
bilgileri geçerlidir ve geçerli kaldıkları sürece bu katmanlar davranışa bakmak zorundadır. O kimlik bilgilerinin nerede durduğu, kimin okuyabildiği ve ne kadar
süreyle geçerli kaldığı ise hiç sorulmadı. Sonraki konu bunu sorar ve ilk ölçüsü ömürdür: bir
sırrın geçerli kaldığı süre, açık bıraktığı pencerenin kendisidir.

## Sır Yönetimi

Uygulamanın taşıdığı anahtar ve kimlik bilgilerinin çalışma zamanında nasıl tutulduğu sayıyla ölçülür: sır deposunun erişim matrisi ve en az yetkinin kapattığı kalem, deponun tek nokta olarak açtığı başlatma bağımlılığı, kısa ömürlü kimlik bilgisinin açık pencereyi kaç kat daralttığı ve karşılığında getirdiği istek yükü, anahtar döndürmede iki sırrın birlikte geçerli olduğu asgari süre ve yanlış sıralamanın kestiği istek, iş yükü kimliğinin ortadan kaldırdığı statik sır ile geriye kalan dış sistem kalemi, sızıntı sonrası iptal akışında fark etmeden iptale geçen dakika ve o sürede sırla yapılan çağrı.

### Sır Deposu Mimarisi

Source: https://academia.sh/tr/kurslar/calisma-zamani-guvenligi/sir-deposu-mimarisi

Sır deposu erişim denetimi cinsinden ölçülür: yol öneki politikası dokuz uygulamaya 79 (uygulama, sır) kalemi açıyor, doksan günlük okuma kaydı 31 diyor ve 48 kalem hiç kullanılmadan duruyor. Üç sırrı hiçbir uygulama okumuyor; en geniş veri sırrına altı uygulama erişebiliyor. Merkezîleşmenin bedeli tek noktadır — dokuz uygulamanın hiçbiri depo olmadan başlayamıyor ve günde 41 başlatma denemesi bu tek noktadan geçiyor.

Önceki ders istek katmanını kapattı: uygulama katmanı güvenlik duvarının ve davranış puanlamasının
neyi yakaladığı, neyi kaçırdığı ve neyi yanlış yere kestiği sayıldı. Bütün o katmanların arkasında
tek bir sessiz varsayım duruyordu — uygulamanın veri deposuna, kuyruğa ve dış geçitlere bağlanmak
için taşıdığı anahtarların **yerli yerinde ve yalnız kendisinde** olduğu. Bu ders o varsayımı
kaldırır ve anahtarların durduğu yeri, yani **sır deposunu**, tek bir eksende ölçer: kim neye
erişebiliyor.

Sırrın nerede saklandığı, kaç kopya hâlinde durduğu ve merkezî bir deponun kopyayı nasıl azalttığı
daha önce ölçüldü ve burada tekrarlanmıyor. Buranın sorusu depo kurulduktan **sonra** başlıyor:
depo kurulmuş, sırlar içine konmuş ve her uygulamaya bir politika yazılmıştır. O politika kaç
kaleme izin veriyor, uygulamalar kaçını gerçekten okuyor ve aradaki fark ele geçen bir uygulamadan
ne kadar açıyor.

- **SR1.** Abone portalı ve saha uygulamasının üretim ortamı **kurgudur**: dokuz uygulama, yirmi
  sır ve bir sır deposu. Ölçülen şey `node` ile yazılmış bir **modeldir**.
- **SR2.** Modelde **gerçek sır değeri yoktur**; yalnız sır yolları, uygulama adları ve sayılar
  taşınır. Sır yolu `alan/kalem` biçimindedir ve politika **yol öneki** ile yazılır.
- **SR3.** Bir politika kuralı, kendisiyle başlayan her sır yolunu açar. `veri/` kuralı beş veri
  sırrının beşini birden verir; tam yol yazan kural tek sır verir.
- **SR4.** Okuma kaydı iki pencerede okunur: son otuz gün ve son doksan gün. Doksan günlük pencere
  bu modelde gerçek ihtiyaç sayılır; gerçekte hiçbir pencere ihtiyacın tamamını göstermez.
- **SR5.** Rastgelelik yok; bütün sayılar model tablolarından türetiliyor ve çıktı koşumdan koşuma
  aynı. Yeniden başlatma sayıları kurgu birimdir.
- **SR6.** Deponun kendi kesintisi tek değerli modellenir: depo ya vardır ya yoktur. Kısmi bozulma
  ve çoğaltılmış depo modellenmiyor; çoğaltma kesinti kalemini düşürür, erişim kalemini düşürmez.

#### Erişim Matrisi

```js
// depo.mjs — sir deposu envanteri, politika kurallari ve okuma kaydi. MODELDIR.
// Abone portali ve saha uygulamasinin uretim ortami KURGUDUR; dokuz uygulama, bir depo.
// GERCEK SIR YOKTUR: yalniz sir YOLLARI, uygulama adlari ve sayilar modellenir.
export const SIR = Object.entries({
  veri: ["portal-birincil", "portal-okuma", "saha-birincil", "fatura-birincil", "arsiv"],
  kuyruk: ["olcum-alim", "bildirim-kuyrugu", "is-emri-kuyrugu"],
  dis: ["odeme-gecidi", "harita-servisi", "kisa-mesaj-gecidi", "eposta-gecidi", "kimlik-saglayici"],
  imza: ["oturum-imzalama", "belge-imzalama", "ic-cagri-imzalama"],
  altyapi: ["nesne-deposu", "onbellek", "olcut-yazma", "gunluk-yazma"],
}).flatMap(([a, l]) => l.map((k) => `${a}/${k}`));

// kural: politikanin verdigi yol oneki. okur: son 30 gunun okuma kaydindaki sirlar.
// bicim/omur: sirrin nasil alindigi. yb: gunde kac yeniden baslatma (dagitim + olcek).
export const UYG = {
  "portal-onyuz": { kural: ["dis/kimlik-saglayici", "imza/"], bicim: "baslangicta", omur: 0, yb: 6,
    okur: ["imza/oturum-imzalama"] },
  "portal-api": { kural: ["veri/", "imza/", "altyapi/"], bicim: "onbellekli", omur: 60, yb: 12,
    okur: ["veri/portal-birincil", "veri/portal-okuma", "imza/oturum-imzalama",
      "imza/ic-cagri-imzalama", "altyapi/onbellek"] },
  "abone-kayit": { kural: ["veri/", "dis/"], bicim: "baslangicta", omur: 0, yb: 3,
    okur: ["veri/portal-birincil", "dis/eposta-gecidi", "dis/kisa-mesaj-gecidi"] },
  "fatura-servisi": { kural: ["veri/", "dis/", "imza/belge-imzalama"], bicim: "onbellekli",
    omur: 240, yb: 2,
    okur: ["veri/fatura-birincil", "veri/portal-okuma", "dis/odeme-gecidi", "imza/belge-imzalama"] },
  "odeme-koprusu": { kural: ["dis/"], bicim: "her-istekte", omur: -1, yb: 2,
    okur: ["dis/odeme-gecidi"] },
  "saha-api": { kural: ["veri/", "kuyruk/", "dis/harita-servisi", "imza/"], bicim: "onbellekli",
    omur: 60, yb: 8,
    okur: ["veri/saha-birincil", "kuyruk/is-emri-kuyrugu", "dis/harita-servisi",
      "imza/ic-cagri-imzalama"] },
  "is-emri": { kural: ["veri/", "kuyruk/"], bicim: "baslangicta", omur: 0, yb: 4,
    okur: ["veri/saha-birincil", "kuyruk/is-emri-kuyrugu", "kuyruk/bildirim-kuyrugu"] },
  "bildirim": { kural: ["kuyruk/", "dis/"], bicim: "onbellekli", omur: 15, yb: 3,
    okur: ["kuyruk/bildirim-kuyrugu", "dis/eposta-gecidi", "dis/kisa-mesaj-gecidi"] },
  "rapor-uretici": { kural: ["veri/", "altyapi/"], bicim: "baslangicta", omur: 0, yb: 1,
    okur: ["veri/portal-okuma", "veri/arsiv", "altyapi/nesne-deposu"] },
};
export const AD = Object.keys(UYG);
// 30 gunluk pencerede hic gorunmeyen, 90 gunde goruleni olan mesru okumalar.
export const NADIR = [["fatura-servisi", "veri/arsiv"], ["is-emri", "dis/harita-servisi"],
  ["portal-api", "altyapi/gunluk-yazma"], ["rapor-uretici", "dis/eposta-gecidi"]];

export const erisir = (a, s) => UYG[a].kural.some((k) => s.startsWith(k));
export const okur90 = (a) => [...UYG[a].okur, ...NADIR.filter((n) => n[0] === a).map((n) => n[1])];
export const topla = (f) => AD.reduce((t, a) => t + f(a), 0);
export const gen = (B) => (h) => h.map((v, j) => j ? String(v).padStart(B[j])
  : String(v).padEnd(B[0])).join("");

if (import.meta.url === `file://${process.argv[1]}`) {
  const yz = gen([16, 8, 14, 12, 12, 11]);
  console.log(`model: ${SIR.length} sir, ${AD.length} uygulama, 1 depo (kurgu uretim ortami)\n`);
  console.log(yz(["uygulama", "kural", "erisebildigi", "30 g okur", "90 g okur", "fazladan"]));
  for (const a of AD) {
    const e = SIR.filter((s) => erisir(a, s)).length;
    console.log(yz([a, UYG[a].kural.length, e, UYG[a].okur.length, okur90(a).length,
      e - okur90(a).length]));
  }
  const E = topla((a) => SIR.filter((s) => erisir(a, s)).length);
  const O30 = topla((a) => UYG[a].okur.length), O90 = topla((a) => okur90(a).length);
  console.log(yz(["toplam", topla((a) => UYG[a].kural.length), E, O30, O90, E - O90]));

  const ters = SIR.map((s) => [s, AD.filter((a) => erisir(a, s)).length,
    AD.filter((a) => okur90(a).includes(s)).length]).sort((x, y) => y[1] - x[1]);
  console.log("\nen genis dort sir (kac uygulama erisebiliyor / kaci gercekten okuyor):");
  for (const [s, e, o] of ters.slice(0, 4)) console.log(`  ${s.padEnd(24)} ${e} / ${o}`);
  const hic = ters.filter((t) => t[2] === 0), pay = ters.filter((t) => t[2] > 1);
  console.log(`hicbir uygulamanin okumadigi sir: ${hic.length} (${hic.map((t) => t[0]).join(", ")})`);
  console.log(`birden cok uygulamanin okudugu sir: ${pay.length} / ${SIR.length}; ` +
    `bu sirlarin biri degistiginde ortalama ` +
    `${(pay.reduce((t, x) => t + x[2], 0) / pay.length).toFixed(1)} uygulama etkilenir`);
  console.log(`\nele gecen bir uygulamadan acilan sir — politikayla ortalama ` +
    `${(E / AD.length).toFixed(1)}, en genis ${Math.max(...AD.map((a) =>
      SIR.filter((s) => erisir(a, s)).length))}; en az yetkiyle ortalama ` +
    `${(O90 / AD.length).toFixed(1)}, en genis ${Math.max(...AD.map((a) => okur90(a).length))}`);
  console.log(`en az yetki politikasi: ${O90} satir (bugun ${topla((a) => UYG[a].kural.length)}), ` +
    `kapanan kalem ${E - O90}; 30 gunluk gozlemle yazilsa ${O90 - O30} mesru okuma kesilirdi`);
}
```

```
model: 20 sir, 9 uygulama, 1 depo (kurgu uretim ortami)

uygulama           kural  erisebildigi   30 g okur   90 g okur   fazladan
portal-onyuz           2             4           1           1          3
portal-api             3            12           5           6          6
abone-kayit            2            10           3           3          7
fatura-servisi         3            11           4           5          6
odeme-koprusu          1             5           1           1          4
saha-api               4            12           4           4          8
is-emri                2             8           3           4          4
bildirim               2             8           3           3          5
rapor-uretici          2             9           3           4          5
toplam                21            79          27          31         48

en genis dort sir (kac uygulama erisebiliyor / kaci gercekten okuyor):
  veri/portal-birincil     6 / 2
  veri/portal-okuma        6 / 3
  veri/saha-birincil       6 / 2
  veri/fatura-birincil     6 / 1
hicbir uygulamanin okumadigi sir: 3 (dis/kimlik-saglayici, kuyruk/olcum-alim, altyapi/olcut-yazma)
birden cok uygulamanin okudugu sir: 12 / 20; bu sirlarin biri degistiginde ortalama 2.2 uygulama etkilenir

ele gecen bir uygulamadan acilan sir — politikayla ortalama 8.8, en genis 12; en az yetkiyle ortalama 3.4, en genis 6
en az yetki politikasi: 31 satir (bugun 21), kapanan kalem 48; 30 gunluk gozlemle yazilsa 4 mesru okuma kesilirdi
```

Yirmi bir kural satırı yetmiş dokuz `(uygulama, sır)` kalemi açıyor. Doksan günlük okuma kaydında
görünen kalem otuz bir. Aradaki **kırk sekiz kalem**, yani açılan erişimin yüzde altmış biri,
hiçbir uygulamanın hiç dokunmadığı sırlara verilmiş durumda. Bu fark bir tembellikten değil, kural
biçiminden geliyor: `veri/` yazmak bir satırdır, beş sır verir; beş sırrın hangisinin gerçekten
gerektiğini yazmak beş satırdır.

Satır satır bakıldığında en pahalı iki kalem iki ayrı uygulamadadır. `saha-api` dört kural
satırıyla on iki sırra erişebiliyor, dördünü okuyor; sekiz kalem karşılıksız. `portal-api` on iki
sırra erişip altısını okuyor. Karşılıksız kalemin en büyük tek kaynağı `veri/` önekidir: beş veri
sırrının her birine **altı uygulama** erişebiliyor, ama en çok okunanı üç uygulama, en az okunanı
tek uygulama okuyor. Fatura veri tabanının birincil kimlik bilgisine altı uygulama ulaşabiliyor;
onu okuyan tek uygulama var.

Üç sır listede hiç görünmüyor: kimlik sağlayıcı sırrı, ölçüm alım kuyruğunun anahtarı ve ölçüt
yazma anahtarı doksan gün boyunca hiçbir uygulama tarafından okunmamış. Bunlar erişim matrisinin
en ucuz kalemleridir — okuyanı olmayan sır, kimseyi kesmeden kapatılır.

Bir sonraki satır matrisi ters yönde okuyor ve bu dersin dışına taşan tek sayıyı veriyor: yirmi
sırrın on ikisi birden çok uygulama tarafından okunuyor, ortalama 2,2 uygulama tarafından. Erişim
matrisi daraltılsa bile bu paylaşım kalır — çünkü paylaşım politikadan değil, mimariden gelir; iki
uygulama aynı veri tabanına yazıyorsa aynı kimlik bilgisini okur. Bu on iki sırrın herhangi biri
değiştirildiğinde ortalama iki uygulama aynı anda yeni değere geçmek zorundadır ve o geçişin
nasıl yapılacağı erişim denetiminin çözebileceği bir soru değildir.

Son iki satır kararı veriyor. Ele geçen bir uygulama bugünkü politikayla ortalama 8,8 sır açıyor,
en kötü durumda on iki. En az yetkiye inildiğinde ortalama 3,4'e, en kötü durum altıya iniyor.
Bedel de aynı satırda: politika yirmi bir satırdan otuz bir satıra çıkıyor. **Daraltma politikayı
kısaltmaz, uzatır.** Ve daraltma otuz günlük gözlemle yazılırsa dört meşru okumayı keser — yıl sonu
arşiv okuması, toplu rota yeniden hesabı, tanı kipindeki günlük yazımı ve aylık özet gönderimi. Bu
dördü otuz günlük pencerede hiç görünmez; kesildiklerinde de dağıtım anında değil, ilk çalıştıkları
gün fark edilirler.

#### Merkezîleşmenin Tek Noktası

```js
// kesinti.mjs — merkezilesmenin tek nokta bedeli: depo dustugunde kim durur, kim baslayamaz
import { AD, UYG, topla, gen } from "./depo.mjs";

const yz = gen([14, 14, 17, 16, 20]);
const YB = topla((a) => UYG[a].yb);                       // gunluk yeniden baslatma (kurgu)
const derhal = AD.filter((a) => UYG[a].bicim === "her-istekte");
const biten = (D) => AD.filter((a) => UYG[a].bicim === "onbellekli" && UYG[a].omur < D);
console.log(`gunluk yeniden baslatma ${YB} (dagitim + olcek); depo olmadan baslayabilen ` +
  `uygulama 0 / ${AD.length}\n`);
console.log(yz(["kesinti(dk)", "derhal duran", "onbellegi biten", "duran uygulama",
  "basarisiz baslatma"]));
for (const D of [1, 15, 30, 60, 120, 240, 480, 1440])
  console.log(yz([D, derhal.length, biten(D).length, derhal.length + biten(D).length,
    Math.round((D / 1440) * YB)]));

console.log(`\nbicim dagilimi:`);
for (const b of ["her-istekte", "onbellekli", "baslangicta"]) {
  const l = AD.filter((a) => UYG[a].bicim === b);
  console.log(`  ${b.padEnd(13)} ${l.length}  ${l.join(", ")}`);
}
const ayakta = AD.filter((a) => UYG[a].bicim === "baslangicta");
console.log(`\n1440 dk kesintide: ${derhal.length + biten(1440).length} uygulama durur, ` +
  `${ayakta.length} uygulama calismaya devam eder ama ${YB} baslatma denemesi basarisiz olur`);
console.log(`kesintiden hic etkilenmeyen uygulama: 0 / ${AD.length}`);
```

```
gunluk yeniden baslatma 41 (dagitim + olcek); depo olmadan baslayabilen uygulama 0 / 9

kesinti(dk)     derhal duran  onbellegi biten  duran uygulama  basarisiz baslatma
1                          1                0               1                   0
15                         1                0               1                   0
30                         1                1               2                   1
60                         1                1               2                   2
120                        1                3               4                   3
240                        1                3               4                   7
480                        1                4               5                  14
1440                       1                4               5                  41

bicim dagilimi:
  her-istekte   1  odeme-koprusu
  onbellekli    4  portal-api, fatura-servisi, saha-api, bildirim
  baslangicta   4  portal-onyuz, abone-kayit, is-emri, rapor-uretici

1440 dk kesintide: 5 uygulama durur, 4 uygulama calismaya devam eder ama 41 baslatma denemesi basarisiz olur
kesintiden hic etkilenmeyen uygulama: 0 / 9
```

Kırk sekiz kalemi kapatmanın karşılığında ne alındığı bu tablodadır. Bir yerde toplanan sır, bir
yerde toplanan **bağımlılıktır**. Deponun bir dakikalık kesintisinde bile bir uygulama duruyor:
ödeme köprüsü sırrı her istekte okuyor, dolayısıyla depoya erişemediği anda ödeme almıyor. Bu, en
duyarlı sırrın en sıkı okunmasının doğal sonucudur — sıkı okuma, kesintiye en açık olma biçimidir.

Sonraki satırlar önbellek ömrünün gecikmeli bir tampon olduğunu gösteriyor. Otuz dakikalık
kesintide bildirim servisi düşüyor (önbellek ömrü on beş dakika), iki saatte portal ve saha
uygulama arayüzleri de düşüyor, sekiz saatte önbellekli dört uygulamanın dördü duruyor. Önbellek
kesintiyi engellemiyor, **erteliyor**; ertelediği süre tam olarak önbellek ömrü kadar.

Sağdaki sütun tablonun asıl bulgusudur. Başlangıçta okuyan dört uygulama kesinti boyunca çalışmaya
devam ediyor ve ilk bakışta bağışık görünüyorlar. Bağışık değiller: dokuz uygulamanın **hiçbiri**
depo olmadan başlayamıyor ve bu ortamda günde kırk bir yeniden başlatma var — dağıtım, ölçek
büyütme ve sağlıksız örneğin değiştirilmesi. Dört saatlik bir kesinti yedi başlatma denemesini,
bir günlük kesinti kırk birini düşürür. Yük artışıyla aynı saate denk gelen bir depo kesintisinde
ölçek büyütme çalışmaz; sistem, ayakta kalan örnekleriyle yükün altında kalır.

Tablonun son satırı merkezîleşmenin gerçek ifadesidir: kesintiden hiç etkilenmeyen uygulama
sıfırdır. Depoyu kurmak kırk sekiz karşılıksız erişim kalemini kapatılabilir hâle getirir; aynı
adım, dokuz uygulamanın tamamına **ortak bir başlatma bağımlılığı** yazar. İkinci kalem birincinin
faturasıdır ve çoğaltmayla küçültülebilir, sıfırlanamaz.

#### Daha Ucuz Aşama

Kırk sekiz karşılıksız kalem çalışma zamanında ölçüldü, ama çalışma zamanında **doğmadı**. Her
kalem, bir uygulamaya politika yazılırken doğdu: `veri/` öneki, o uygulamanın hangi veri sırrına
ihtiyaç duyduğu bilinmediği için yazıldı. Aynı kalem dağıtım aşamasında kapanabilirdi — her
uygulama ihtiyaç duyduğu sır yollarını dağıtım tanımında **açıkça bildirseydi**, politika o
bildirimden üretilir ve otuz bir kalem dışında hiçbir kalem hiç açılmazdı. İşin ölçüsü de farklı:
dokuz uygulama için dokuz bildirim yazmak ile yetmiş dokuz kalemlik matrisi elle gözden geçirip
hangisinin gereksiz olduğuna karar vermek arasında yaklaşık dokuz kat fark var — ve ikincisi her
yeni sır eklendiğinde yeniden yapılır, birincisi bir kez yazılır.

Çalışma zamanında ölçülmesi gereken tek kalem, bildirimin kendisinin doğru olup olmadığıdır: okuma
kaydı bildirilenden fazlasını gösteriyorsa bildirim eksiktir, azını gösteriyorsa fazladır. Bu
karşılaştırma bir denetimdir, bir savunma değil.

#### Özet

- Yirmi bir kural satırı dokuz uygulamaya 79 `(uygulama, sır)` kalemi açıyor; doksan günlük okuma
  kaydı 31 diyor. Kırk sekiz kalem, açılan erişimin %61'i, hiç kullanılmıyor.
- Karşılıksız kalemin kaynağı yol öneki kuralıdır: `veri/` bir satırdır ve beş sır verir; beş veri
  sırrının her birine altı uygulama erişebiliyor, en çok okunanını üç uygulama okuyor.
- Üç sırrı hiçbir uygulama okumuyor; bunlar kimseyi kesmeden kapatılabilecek en ucuz kalemlerdir.
- En az yetki ele geçen bir uygulamadan açılan sırrı ortalama 8,8'den 3,4'e, en kötü durumda
  12'den 6'ya indiriyor. Bedeli politikanın 21 satırdan 31 satıra uzamasıdır; otuz günlük gözlemle
  yazılırsa dört meşru okumayı keser ve kesinti ancak o iş ilk çalıştığında görünür.
- Merkezîleşmenin bedeli tek noktadır: bir dakikalık kesinti bir uygulamayı durduruyor, sekiz
  saatlik kesinti beşini; dokuz uygulamanın hiçbiri depo olmadan başlayamıyor ve günde 41 başlatma
  denemesi bu noktadan geçiyor.
- Kırk sekiz kalem çalışma zamanında ölçüldü ama dağıtım aşamasında doğdu; sır yolları dağıtım
  tanımında bildirilseydi hiç açılmayacaktı — dokuz bildirim ile 79 kalemlik matris incelemesi
  arasında yaklaşık dokuz kat fark var.

#### Sonraki Adım

Bu ders erişimi daralttı ama sırların kendisine hiç dokunmadı. Otuz bir kalemin her birinde duran
şey hâlâ **ömrü olmayan bir değerdir**: kurulum günü yazılmış, o gün bu gündür aynı. Erişim
matrisi daraltıldığında bir uygulamadan açılan sır altıya iner, ama o altı sır sızdığında ne kadar
süre çalışacağı sorusu hiç sorulmadı. Sonraki ders o süreyi ölçer: statik bir sır sızdığında açık
pencere kaç gün sürüyor, istek üzerine üretilen kısa ömürlü bir kimlik bilgisi aynı pencereyi kaç
kata indiriyor ve bu daralmanın karşılığında depoya günde kaç ek istek, sisteme kaç yeni bağımlılık
ekleniyor.

### Kısa Ömürlü Kimlik Bilgileri

Source: https://academia.sh/tr/kurslar/calisma-zamani-guvenligi/kisa-omurlu-kimlik-bilgileri

Bir sır sızdığı andan kendiliğinden geçersizleştiği ana kadar geçen süre ölçülür: 31 kalemin 16'sında açık pencere 90 günden 64 dakikaya, yani 2.033 kata iniyor; kalan 15 kalemde hiç kısalmıyor ve geçişten sonra toplam maruziyetin %99,96'sı orada toplanıyor. Bedeli depo isteğinin toplamı değil dağılımıdır — üç uygulamanın yükü 6,3 ile 14,5 kat artıyor, hedef sistemlerde günde 1.073 geçici kimlik bilgisi doğup ölüyor ve iki saatlik bir depo kesintisinde duran uygulama dörtten sekize çıkıyor.

Önceki ders erişim matrisini daralttı: yetmiş dokuz `(uygulama, sır)` kaleminden otuz biri
gerçekten okunuyordu, kırk sekizi karşılıksızdı. Kalan otuz bir kalemin her birinde duran şeye
ise hiç bakılmadı. O şey **ömrü olmayan bir değerdir**: kurulum günü yazılmış, o gün bu gündür
aynı. Bu ders o değeri tek bir eksende ölçer — sır sızarsa ne kadar süre çalışır.

Sır saklama servisinin mimarisi ve dinamik kimlik bilgisi üretecinin servis olarak nasıl
kurulduğu daha önceki kurslarda ölçüldü; burada tekrarlanmıyor. Buranın ölçüsü tek bir süredir:
**açık pencere**. Statik bir sır için bu süre bir sonraki planlı döndürmeye kadardır; istek
üzerine üretilen kısa ömürlü bir kimlik bilgisi için kalan jeton ömrüdür. İkisi arasındaki fark
bu dersin konusudur — ve o farkın hangi kalemlerde hiç oluşmadığı da.

- **SR7.** Önceki dersin modeli sürüyor: dokuz uygulama, bir sır deposu, otuz bir okunan kalem
  ve on yedi ayrı sır. Ortam **kurgudur**, ölçülen şey `node` ile yazılmış bir **modeldir** ve
  **gerçek sır değeri taşımaz**.
- **SR8.** Açık pencere sızıntının fark edilmesini içermez. Fark etme ve iptal akışı bu konunun
  son dersinde ayrıca ölçülür; burada sır **kendiliğinden** geçersizleşene kadar geçen süre
  sayılır.
- **SR9.** Statik sır için modelde planlı döndürme **zamanında yapılır**. Gecikmiş döndürme ve
  döndürme sırasında olan biten bir sonraki dersin konusudur.
- **SR10.** Sızıntı anı pencere içinde rastgele varsayılır: ortalama açık pencere döndürme
  periyodunun yarısı, en kötü durumda tamamıdır. Aynı kural jeton ömrü için de geçerlidir.
- **SR11.** Bir hedef sistemin istek üzerine kimlik bilgisi üretip üretemediği model tablosunda
  verilir. İmza anahtarı üretilebilir sayılmaz: imzayı doğrulayan tarafın da aynı anahtarı
  bilmesi gerekir, dolayısıyla anahtar istek başına değiştirilemez.
- **SR12.** Rastgelelik yok; bütün sayılar model tablolarından türetiliyor ve çıktı koşumdan
  koşuma aynı.

#### Pencere Kaç Kata İniyor

```js
// omur.mjs — 31 (uygulama, sir) kalemi ve her kalemin acik penceresi. MODELDIR.
// Bolgesel olcum aginin uretim ortami KURGUDUR: dokuz uygulama, bir sir deposu.
// GERCEK SIR DEGERI YOKTUR: yalniz sir yollari, dondurme periyodu ve jeton omru modellenir.
export const OKUR = {
  "portal-onyuz": ["imza/oturum-imzalama"],
  "portal-api": ["veri/portal-birincil", "veri/portal-okuma", "imza/oturum-imzalama",
    "imza/ic-cagri-imzalama", "altyapi/onbellek", "altyapi/gunluk-yazma"],
  "abone-kayit": ["veri/portal-birincil", "dis/eposta-gecidi", "dis/kisa-mesaj-gecidi"],
  "fatura-servisi": ["veri/fatura-birincil", "veri/portal-okuma", "veri/arsiv",
    "dis/odeme-gecidi", "imza/belge-imzalama"],
  "odeme-koprusu": ["dis/odeme-gecidi"],
  "saha-api": ["veri/saha-birincil", "kuyruk/is-emri-kuyrugu", "dis/harita-servisi",
    "imza/ic-cagri-imzalama"],
  "is-emri": ["veri/saha-birincil", "kuyruk/is-emri-kuyrugu", "kuyruk/bildirim-kuyrugu",
    "dis/harita-servisi"],
  "bildirim": ["kuyruk/bildirim-kuyrugu", "dis/eposta-gecidi", "dis/kisa-mesaj-gecidi"],
  "rapor-uretici": ["veri/portal-okuma", "veri/arsiv", "altyapi/nesne-deposu",
    "dis/eposta-gecidi"],
};
// alan varsayilani [dondurme(gun), uretir, jeton omru(dk)]; uretir = hedef sistem istek
// uzerine kisa omurlu kimlik bilgisi uretebiliyor mu. Istisnalar ayrica yaziliyor.
const ALANVAR = { veri: [180, true, 60], kuyruk: [180, true, 120], altyapi: [180, true, 240],
  imza: [90, false, 0], dis: [365, false, 0] };
const ISTISNA = { "altyapi/gunluk-yazma": [180, true, 720], "altyapi/onbellek": [180, false, 0],
  "dis/odeme-gecidi": [90, false, 0] };
export const SIR = Object.fromEntries([...new Set(Object.values(OKUR).flat())].map((s) => {
  const [dondurme, uretir, omur] = ISTISNA[s] || ALANVAR[s.split("/")[0]];
  return [s, { dondurme, uretir, omur }];
}));
// bicim/omur: sirrin bugun nasil alindigi. ornek: calisan ornek sayisi.
// yb: gunde kac yeniden baslatma. istek: gunluk istek (kurgu birim).
export const UYG = {
  "portal-onyuz": { bicim: "baslangicta", omur: 0, ornek: 4, yb: 6, istek: 84000 },
  "portal-api": { bicim: "onbellekli", omur: 60, ornek: 8, yb: 12, istek: 96000 },
  "abone-kayit": { bicim: "baslangicta", omur: 0, ornek: 2, yb: 3, istek: 1400 },
  "fatura-servisi": { bicim: "onbellekli", omur: 240, ornek: 2, yb: 2, istek: 6200 },
  "odeme-koprusu": { bicim: "her-istekte", omur: -1, ornek: 3, yb: 2, istek: 3400 },
  "saha-api": { bicim: "onbellekli", omur: 60, ornek: 5, yb: 8, istek: 42000 },
  "is-emri": { bicim: "baslangicta", omur: 0, ornek: 3, yb: 4, istek: 9600 },
  "bildirim": { bicim: "onbellekli", omur: 15, ornek: 2, yb: 3, istek: 12000 },
  "rapor-uretici": { bicim: "baslangicta", omur: 0, ornek: 1, yb: 1, istek: 320 },
};
export const AD = Object.keys(UYG);
export const KALEM = AD.flatMap((a) => OKUR[a].map((s) => [a, s]));
export const ALAN = ["veri", "kuyruk", "altyapi", "imza", "dis"];
// acik pencere: sir sizdiginda kendiliginden gecersizlesene kadar gecen sure (dk).
export const pencere = (s, kisa) => kisa && SIR[s].uretir ? SIR[s].omur : SIR[s].dondurme * 1440;
export const gen = (B) => (h) => h.map((v, j) => j ? String(v).padStart(B[j])
  : String(v).padEnd(B[0])).join("");
export const sure = (dk) => dk < 1440 ? `${Math.round(dk)} dk` : `${(dk / 1440).toFixed(1)} gun`;
export const ort = (k, kisa) => k.reduce((t, [, s]) => t + pencere(s, kisa) / 2, 0) / k.length;

if (import.meta.url === `file://${process.argv[1]}`) {
  const yz = gen([10, 8, 15, 16, 18, 7]);
  const D = KALEM.filter(([, s]) => SIR[s].uretir), S = KALEM.filter(([, s]) => !SIR[s].uretir);
  console.log(`model: ${KALEM.length} (uygulama, sir) kalemi, ${Object.keys(SIR).length} okunan ` +
    `sir, ${AD.length} uygulama (kurgu uretim ortami)\n`);
  console.log(yz(["alan", "kalem", "kisaltilabilir", "bugun pencere", "kisa omur pencere", "kat"]));
  for (const al of ALAN) {
    const k = KALEM.filter(([, s]) => s.startsWith(al + "/"));
    console.log(yz([al, k.length, k.filter(([, s]) => SIR[s].uretir).length,
      sure(ort(k, false)), sure(ort(k, true)), (ort(k, false) / ort(k, true)).toFixed(0)]));
  }
  console.log(yz(["toplam", KALEM.length, D.length, sure(ort(KALEM, false)),
    sure(ort(KALEM, true)), (ort(KALEM, false) / ort(KALEM, true)).toFixed(1)]));

  console.log(`\nyalniz kisaltilabilen ${D.length} kalem: ortalama pencere ` +
    `${sure(ort(D, false))} -> ${sure(ort(D, true))}, ` +
    `${Math.round(ort(D, false) / ort(D, true))} kat`);
  console.log(`geriye kalan ${S.length} kalem: ortalama pencere ${sure(ort(S, false))}, degismedi`);
  console.log(`kisa omre gecildikten sonra toplam maruziyet payi — ` +
    `${S.length} statik kalem: %${(100 * ort(S, true) * S.length /
      (ort(KALEM, true) * KALEM.length)).toFixed(2)}`);
  const kalan = [...new Set(S.map(([, s]) => s))].sort((x, y) => SIR[y].dondurme - SIR[x].dondurme);
  console.log(`kisa omre hic gecemeyen ${kalan.length} sir: ` +
    kalan.map((s) => `${s.split("/")[1]}(${SIR[s].dondurme}g)`).join(" "));
}
```

```
model: 31 (uygulama, sir) kalemi, 17 okunan sir, 9 uygulama (kurgu uretim ortami)

alan         kalem kisaltilabilir   bugun pencere kisa omur pencere    kat
veri            10             10        90.0 gun             30 dk   4320
kuyruk           4              4        90.0 gun             60 dk   2160
altyapi          3              2        90.0 gun          30.1 gun      3
imza             5              0        45.0 gun          45.0 gun      1
dis              9              0       151.9 gun         151.9 gun      1
toplam          31             16       100.7 gun          54.3 gun    1.9

yalniz kisaltilabilen 16 kalem: ortalama pencere 90.0 gun -> 64 dk, 2033 kat
geriye kalan 15 kalem: ortalama pencere 112.2 gun, degismedi
kisa omre gecildikten sonra toplam maruziyet payi — 15 statik kalem: %99.96
kisa omre hic gecemeyen 8 sir: eposta-gecidi(365g) kisa-mesaj-gecidi(365g) harita-servisi(365g) onbellek(180g) oturum-imzalama(90g) ic-cagri-imzalama(90g) odeme-gecidi(90g) belge-imzalama(90g)
```

Tablonun ilk iki satırı kısa ömürlü kimlik bilgisinin gerçek büyüklüğünü veriyor. Veri tabanı
kalemlerinde açık pencere doksan günden otuz dakikaya iniyor; oran dört bin üç yüz yirmi kat.
Kuyruk kalemlerinde iki bin yüz altmış kat. Çoğu savunma bir kalemi yüzde otuz, yüzde elli
iyileştirir; burada aynı kalem üç basamak birden değişiyor — doksan gün ile otuz dakika arasında
zaten dört basamak vardır.

Son satır aynı tabloyu bütün küme üzerinden okuyor ve rakam çöküyor. Otuz bir kalemin
ortalaması yüz virgül yedi günden elli dört virgül üç güne iniyor: **yalnız bir virgül dokuz
kat.** Aynı değişiklik, aynı koşumda, iki bin katla iki katı yan yana veriyor. Aradaki fark
tablonun üçüncü sütununda: otuz bir kalemin on altısı kısaltılabiliyor, on beşi kısaltılamıyor.

Kısaltılamayan on beş kalem üç sınıfa ayrılıyor. İmza anahtarları (beş kalem) istek başına
değiştirilemez, çünkü imzayı doğrulayan tarafın da aynı anahtarı bilmesi gerekir; anahtarın
ömrünü kısaltmak doğrulama tarafını kırar. Dış geçit anahtarları (dokuz kalem) sağlayıcının ne
verdiğine bağlıdır ve bu modelde dördü de sabit anahtar veriyor — ödeme, harita, e-posta ve kısa
mesaj geçitleri. Önbellek sunucusu (bir kalem) istek üzerine kullanıcı üretmiyor.

Dördüncü satırdan sonraki iki satır ise kararın kendisidir. Geçişten sonra toplam maruziyetin
**yüzde 99,96'sı** kısaltılamayan on beş kalemde toplanıyor. Yani kısa ömre geçmek, riskin
neredeyse tamamını taşıyan kalemleri hiç etkilemeden, riskin yüzde sıfır virgül sıfır dördünü
üç basamak küçültüyor. Bu, yapılan işin değersiz olduğu anlamına gelmez — veri tabanı kimlik
bilgisi sızdığında ele geçen şey abone verisidir ve pencerenin doksan günden otuz dakikaya
inmesi gerçek bir kazançtır. Anlamı şudur: **ortalama açık pencere yanlış göstergedir.** Doğru
gösterge, kısaltılamayan kalemin listesidir ve o liste sekiz sırdan oluşuyor.

#### Yenilemenin Bedeli

Jeton ömrü kısaldıkça yenileme sıklaşır; ve yenilemenin gittiği yer, önceki dersin ölçtüğü tek
noktadır.

```js
// yuk.mjs — kisa omre gecisin bedeli: depo istegi, hedef sistemde uretim, kesinti dayanikliligi
import { AD, OKUR, SIR, UYG, KALEM, gen } from "./omur.mjs";

// bir kalemin gunluk depo istegi. kisa omurlude kalem kendi jeton omruyle yenilenir;
// statik kalem uygulamanin bugunku okuma bicimini korur.
const istekSay = (a, s, kisa) => {
  const u = UYG[a];
  if (kisa && SIR[s].uretir) return Math.round(1440 / SIR[s].omur) * u.ornek + u.yb;
  if (u.bicim === "her-istekte") return u.istek;
  if (u.bicim === "onbellekli") return Math.round(1440 / u.omur) * u.ornek + u.yb;
  return u.yb;
};
// depo kesintisinde uygulamanin dayandigi sure: her istekte okuyan 0, onbellekli omru kadar,
// baslangicta okuyan sinirsiz. kisa omurlude en kisa jeton omru de tavan koyar.
const dayanma = (a, kisa) => Math.min(
  UYG[a].bicim === "her-istekte" ? 0 : UYG[a].bicim === "onbellekli" ? UYG[a].omur : Infinity,
  ...(kisa ? OKUR[a].filter((s) => SIR[s].uretir).map((s) => SIR[s].omur) : []));

const yz = gen([16, 8, 13, 13, 11, 6]);
console.log(yz(["uygulama", "kalem", "bugun istek", "kisa omurlu", "uretim", "kat"]));
for (const a of AD) {
  const b = OKUR[a].reduce((t, s) => t + istekSay(a, s, false), 0);
  const k = OKUR[a].reduce((t, s) => t + istekSay(a, s, true), 0);
  const u = OKUR[a].filter((s) => SIR[s].uretir).reduce((t, s) => t + istekSay(a, s, true), 0);
  console.log(yz([a, OKUR[a].length, b, k, u, (k / b).toFixed(1)]));
}
const T = (kisa, f = () => true) => KALEM.filter(([, s]) => f(s))
  .reduce((t, [a, s]) => t + istekSay(a, s, kisa), 0);
console.log(yz(["toplam", KALEM.length, T(false), T(true), T(true, (s) => SIR[s].uretir),
  (T(true) / T(false)).toFixed(1)]));

console.log(`\nhedef sistemde gunluk gecici kimlik bilgisi (olusturma, sonra suresi dolan):`);
for (const al of ["veri", "kuyruk", "altyapi"])
  console.log(`  ${al.padEnd(9)}${String(KALEM.filter(([, s]) => s.startsWith(al + "/") &&
    SIR[s].uretir).reduce((t, [a, s]) => t + istekSay(a, s, true), 0)).padStart(5)}`);

const yz2 = gen([13, 22, 20]);
console.log(`\n${yz2(["kesinti(dk)", "bugun duran uygulama", "kisa omurlu duran"])}`);
for (const D of [15, 60, 120, 240, 1440])
  console.log(yz2([D, AD.filter((a) => dayanma(a, false) < D).length,
    AD.filter((a) => dayanma(a, true) < D).length]));
const saglam = AD.filter((a) => dayanma(a, true) === Infinity);
console.log(`\ndepo kesintisinde suresiz calisabilen uygulama: bugun ` +
  `${AD.filter((a) => dayanma(a, false) === Infinity).length}, kisa omurlu ${saglam.length}` +
  `${saglam.length ? ` (${saglam.join(", ")})` : ""}`);
```

```
uygulama           kalem  bugun istek  kisa omurlu     uretim   kat
portal-onyuz           1            6            6          0   1.0
portal-api             6         1224         1048        436   0.9
abone-kayit            3            9           57         51   6.3
fatura-servisi         5           70          178        150   2.5
odeme-koprusu          1         3400         3400          0   1.0
saha-api               4          512          452        196   0.9
is-emri                4           16          160        156  10.0
bildirim               3          585          417         27   0.7
rapor-uretici          4            4           58         57  14.5
toplam                31         5826         5776       1073   1.0

hedef sistemde gunluk gecici kimlik bilgisi (olusturma, sonra suresi dolan):
  veri       863
  kuyruk     175
  altyapi     35

kesinti(dk)    bugun duran uygulama   kisa omurlu duran
15                                1                   1
60                                2                   2
120                               4                   8
240                               4                   8
1440                              5                   8

depo kesintisinde suresiz calisabilen uygulama: bugun 4, kisa omurlu 1 (portal-onyuz)
```

Toplam satırı ilk bakışta beklenenin tersini söylüyor: günlük depo isteği beş bin sekiz yüz yirmi
altıdan beş bin yedi yüz yetmiş altıya iniyor, yani hiç değişmiyor. Kısa ömre geçmenin depoya ek
yük getirmediği sonucu çıkarılamaz; toplam, birbirini götüren iki hareketi gizliyor.

Uygulama satırları o iki hareketi ayırıyor. Yükü artan dört uygulamanın üçü sırrını bugün
**yalnız başlangıçta** okuyanlardır: rapor üreticisi on dört buçuk kat, iş emri servisi on kat,
abone kaydı altı virgül üç kat. Bunlar bugün günde dört, on altı ve dokuz istek yapıyor; kısa
ömre geçtiklerinde elli sekiz, yüz altmış ve elli yedi. Ömrü olmayan bir değer bir kez okunur,
ömrü olan bir değer sürekli yenilenir. Yükü azalan üç uygulamada ise sebep terstir: portal ve
saha uygulama arayüzleri önbelleklerini zaten altmış dakikada bir tazeliyor, jeton ömrü de
altmış dakika; değişen tek şey günlük yazma anahtarının on iki saatlik ömre geçmesi ve o kalemin
isteğinin iki yüz dörtten yirmi sekize düşmesi.

İkinci tablo asıl yeni maliyeti gösteriyor. Bin yetmiş üç isteğin karşılığı bir okuma değil, bir
**üretimdir**: hedef sistemde günde sekiz yüz altmış üç veri tabanı kullanıcısı, yüz yetmiş beş
kuyruk ve otuz beş altyapı kimlik bilgisi yaratılıyor ve süresi dolduğunda temizleniyor. Bu, sır
deposunun değil veri tabanının yüküdür ve sır yönetimi hesabında sık sık unutulur; yaratmayı
beceren ama silmeyi beceremeyen bir akış günde sekiz yüz altmış üç kalemlik birikim üretir.

Üçüncü tablo bedelin en pahalı kalemidir ve önceki dersin bulgusunu doğrudan kötüleştiriyor.
Depo kesintisinde iki saat dayanabilen uygulama sayısı bugün dört; kısa ömre geçildiğinde bu sayı
sekize çıkıyor, yani dokuz uygulamanın sekizi iki saatlik bir depo kesintisinde duruyor.
Kesintiye süresiz dayanabilen uygulama dörtten bire iniyor ve o bir uygulama, hiç kısaltılabilir
kalemi olmayan portal ön yüzüdür. Açık pencereyi doksan günden otuz dakikaya indirmek,
uygulamanın depoya olan bağımlılığını da doksan günden otuz dakikaya indirmek demektir; ikisi
aynı ayarın iki yüzüdür ve ayrı ayrı seçilemez.

#### Daha Ucuz Aşama

Otuz dakikalık pencere çalışma zamanında kuruluyor, ama pencerenin **kısaltılabilir olup
olmadığı** çalışma zamanında kararlaşmıyor. Kısaltılamayan sekiz sırrın her biri daha erken bir
aşamada seçildi: e-posta ve kısa mesaj geçitleri tedarikçi seçimi aşamasında, imza anahtarları
tasarım aşamasında, önbellek sunucusu altyapı seçiminde. Bir dış sağlayıcı seçilirken "istek
üzerine kısa ömürlü kimlik bilgisi üretiyor mu" sorusu sorulmadıysa, o sağlayıcının anahtarı
sistemin ömrü boyunca statik kalır; bu ders o anahtarı ölçebilir, kısaltamaz. Dokuz dış kalemin
tamamı bu yolla doğdu ve bugün toplam maruziyetin en büyük payını taşıyor.

Çalışma zamanına gerçekten ait olan tek karar, kısaltılabilen on altı kalemde jeton ömrünün
seçilmesidir. O seçim de tek yönlü değildir: ömrü altmış dakikadan on beş dakikaya indirmek
pencereyi dörde böler, depo isteğini dörtle çarpar ve kesintiye dayanma süresini dörde böler.
Üçü aynı sayıdır.

#### Özet

- Açık pencere, sır sızdığı andan kendiliğinden geçersizleştiği ana kadar geçen süredir. Statik
  sırda bir sonraki planlı döndürmeye kadar, kısa ömürlü kimlik bilgisinde kalan jeton ömrü.
- Kısaltılabilen 16 kalemde pencere ortalama 90 günden 64 dakikaya, yani 2.033 kata iniyor; veri
  tabanı kalemlerinde oran 4.320 kat.
- Otuz bir kalemin tamamında ortalama yalnız 1,9 kat daralıyor. Geçişten sonra toplam maruziyetin
  %99,96'sı kısaltılamayan 15 kalemde toplanıyor. Ortalama açık pencere bu yüzden yanlış
  göstergedir; doğru gösterge sekiz sırlık kısaltılamayanlar listesidir.
- Depoya günlük istek 5.826'dan 5.776'ya, yani hiç değişmiyor; ama 1.073'ü artık okuma değil
  üretimdir ve hedef sistemlerde günde 863 veri tabanı kullanıcısı doğup ölüyor. Sırrını yalnız
  başlangıçta okuyan üç uygulamanın yükü 6,3, 10 ve 14,5 kat artıyor.
- Bedelin en pahalı kalemi kesinti dayanıklılığıdır: iki saatlik depo kesintisinde duran uygulama
  4'ten 8'e çıkıyor, süresiz dayanabilen 4'ten 1'e iniyor. Pencereyi kısaltmakla depo
  bağımlılığını sıkılaştırmak aynı ayardır.
- Kısaltılamayan sekiz sır tedarikçi ve tasarım seçimi aşamasında belirlendi; çalışma zamanı
  onları ölçer, kısaltamaz.

#### Sonraki Adım

Bu ders on beş kalemde ömrün kısaltılamadığını gösterdi. O kalemler için geriye tek bir araç
kalıyor: **döndürme**. Sır kısalmıyorsa belirli aralıklarla değiştirilir ve açık pencere döndürme
periyoduyla sınırlanır. Ama döndürme bir anda olan bir iş değildir. Yeni değeri okuyacak her
uygulamanın geçmesi gerekir ve uygulamalar aynı hızda geçmez: birisi altmış dakikada, birisi
ancak yeniden başladığında. O geçiş süresi boyunca **iki sır birlikte geçerli** kalmak
zorundadır, yoksa geçmemiş olan kesilir. Sonraki ders o süreyi hesaplar: on yedi sır için asgari
örtüşme kaç dakika, süre kısa tutulduğunda kaç istemci yeni değeri kaçırıyor ve kaç meşru istek
kesiliyor.

### Anahtar Döndürme

Source: https://academia.sh/tr/kurslar/calisma-zamani-guvenligi/anahtar-dondurme

Döndürme, iki sırrın birlikte geçerli kaldığı pencere cinsinden ölçülür: on yedi sırrın asgari örtüşmesi 60 ile 1.440 dakika arasında, ortalaması 815 dakika ve on birinde pencereyi tek başına başlangıçta okuyan dört uygulama belirliyor. Örtüşme kısa tutulduğunda hesap tersine döner — 60 dakikalık pencerede 36 istemci yeni değeri kaçırıyor ve 87.427 meşru istek kesiliyor, sıra ters çevrildiğinde her istekte okuyan tek uygulama bile kesiliyor. Aynı pencere, hata üzerine yeniden okuma eklendiğinde 1.440 dakikadan 240 dakikaya iniyor.

Önceki ders on beş kalemde açık pencerenin kısaltılamadığını gösterdi: imza anahtarları, dış
geçit anahtarları ve önbellek sunucusu istek üzerine kimlik bilgisi üretmiyor. O kalemler için
geriye tek araç kalıyor — sırrı belirli aralıklarla değiştirmek. Döndürme, açık pencereyi
periyoduyla sınırlar; doksan günde bir döndürülen bir anahtarın penceresi doksan günden uzun
olamaz.

Ama döndürme bir anda olmaz. Yeni değer depoya yazıldığı anda hiçbir uygulama ondan haberdar
değildir; her uygulama kendi okuma biçimine göre, kendi hızında geçer. O geçiş tamamlanana kadar
**iki değer de geçerli** kalmak zorundadır. Bu ders o zorunlu pencereyi ölçer: kaç dakika, neyin
belirlediği, kısa tutulduğunda ne kesildiği ve sıra ters çevrildiğinde ne olduğu.

- **SR13.** Önceki iki dersin modeli sürüyor: dokuz uygulama, on yedi okunan sır. Ortam
  **kurgudur**, ölçülen şey `node` ile yazılmış bir **modeldir** ve **gerçek sır değeri
  taşımaz**.
- **SR14.** Geçiş süresi okuma biçiminden türetilir. Her istekte okuyan uygulama derhal geçer;
  önbellekli uygulama en geç önbellek ömrü kadar sonra; yalnız başlangıçta okuyan uygulama ancak
  yeniden başladığında. Sonuncusu için modelde ortalama örnek yaşam süresi kullanılıyor:
  günlük yeniden başlatma sayısına bölünmüş örnek sayısı.
- **SR15.** Kesilen istek en kötü durum sayılır: bir uygulamanın bütün örnekleri geçiş süresinin
  sonunda geçer. Gerçekte geçişler örnekler arasına dağılır ve kesilen istek bu sayının altında
  kalır; sıralaması değişmez.
- **SR16.** On yedi sır **ayrı ayrı** döndürülür ve sonuçlar toplanır. Deponun eski değeri iptal
  etmesi anlık kabul ediliyor; iptalin kendi yayılma süresi modellenmiyor.
- **SR17.** Rastgelelik yok; bütün sayılar model tablolarından türetiliyor ve çıktı koşumdan
  koşuma aynı.

#### Pencereyi En Yavaş Okuyucu Belirler

```js
// gecis.mjs — dondurmede iki sirrin birlikte gecerli kalmasi gereken asgari sure. MODELDIR.
// Ortam KURGUDUR; GERCEK SIR DEGERI YOKTUR, yalniz sir yollari ve gecis sureleri modellenir.
export const OKUR = {
  "portal-onyuz": ["imza/oturum-imzalama"],
  "portal-api": ["veri/portal-birincil", "veri/portal-okuma", "imza/oturum-imzalama",
    "imza/ic-cagri-imzalama", "altyapi/onbellek", "altyapi/gunluk-yazma"],
  "abone-kayit": ["veri/portal-birincil", "dis/eposta-gecidi", "dis/kisa-mesaj-gecidi"],
  "fatura-servisi": ["veri/fatura-birincil", "veri/portal-okuma", "veri/arsiv",
    "dis/odeme-gecidi", "imza/belge-imzalama"],
  "odeme-koprusu": ["dis/odeme-gecidi"],
  "saha-api": ["veri/saha-birincil", "kuyruk/is-emri-kuyrugu", "dis/harita-servisi",
    "imza/ic-cagri-imzalama"],
  "is-emri": ["veri/saha-birincil", "kuyruk/is-emri-kuyrugu", "kuyruk/bildirim-kuyrugu",
    "dis/harita-servisi"],
  "bildirim": ["kuyruk/bildirim-kuyrugu", "dis/eposta-gecidi", "dis/kisa-mesaj-gecidi"],
  "rapor-uretici": ["veri/portal-okuma", "veri/arsiv", "altyapi/nesne-deposu",
    "dis/eposta-gecidi"],
};
// bicim/omur: sirrin okunma bicimi. ornek: calisan ornek. yb: gunluk yeniden baslatma.
// istek: gunluk istek (kurgu birim).
export const UYG = {
  "portal-onyuz": { bicim: "baslangicta", omur: 0, ornek: 4, yb: 6, istek: 84000 },
  "portal-api": { bicim: "onbellekli", omur: 60, ornek: 8, yb: 12, istek: 96000 },
  "abone-kayit": { bicim: "baslangicta", omur: 0, ornek: 2, yb: 3, istek: 1400 },
  "fatura-servisi": { bicim: "onbellekli", omur: 240, ornek: 2, yb: 2, istek: 6200 },
  "odeme-koprusu": { bicim: "her-istekte", omur: -1, ornek: 3, yb: 2, istek: 3400 },
  "saha-api": { bicim: "onbellekli", omur: 60, ornek: 5, yb: 8, istek: 42000 },
  "is-emri": { bicim: "baslangicta", omur: 0, ornek: 3, yb: 4, istek: 9600 },
  "bildirim": { bicim: "onbellekli", omur: 15, ornek: 2, yb: 3, istek: 12000 },
  "rapor-uretici": { bicim: "baslangicta", omur: 0, ornek: 1, yb: 1, istek: 320 },
};
export const AD = Object.keys(UYG);
export const SIR = [...new Set(Object.values(OKUR).flat())].sort();
export const okurlar = (s) => AD.filter((a) => OKUR[a].includes(s));
// gecis: yeni deger yazildiktan sonra uygulamanin ona gecmesi icin gereken en kotu sure (dk).
// her istekte okuyan derhal gecer; onbellekli en gec onbellek omru kadar sonra; baslangicta
// okuyan ancak yeniden baslayinca, yani ortalama ornek yasam suresi kadar sonra.
export const gecis = (a) => UYG[a].bicim === "her-istekte" ? 0
  : UYG[a].bicim === "onbellekli" ? UYG[a].omur : Math.round(1440 * UYG[a].ornek / UYG[a].yb);
export const ortusme = (s) => Math.max(...okurlar(s).map(gecis));
export const gen = (B) => (h) => h.map((v, j) => j ? String(v).padStart(B[j])
  : String(v).padEnd(B[0])).join("");

if (import.meta.url === `file://${process.argv[1]}`) {
  const yz = gen([19, 6, 10, 8, 24]), yz0 = gen([16, 14, 8, 6, 12]);
  console.log(`gecis suresi — yeni degere gecmek icin gereken en kotu sure (dk)`);
  console.log(yz0(["uygulama", "bicim", "ornek", "yb", "gecis(dk)"]));
  for (const a of AD) console.log(yz0([a, UYG[a].bicim, UYG[a].ornek, UYG[a].yb, gecis(a)]));

  console.log(`\n${yz(["sir", "okur", "ortusme", "= saat", "belirleyen uygulama"])}`);
  const sirali = [...SIR].sort((x, y) => ortusme(y) - ortusme(x) || x.localeCompare(y));
  for (const s of sirali)
    console.log(yz([s.split("/")[1], okurlar(s).length, ortusme(s), (ortusme(s) / 60).toFixed(1),
      okurlar(s).filter((a) => gecis(a) === ortusme(s)).join(",")]));
  const O = SIR.map(ortusme);
  console.log(`\n${SIR.length} sir; asgari ortusme en uzun ${Math.max(...O)} dk, en kisa ` +
    `${Math.min(...O)} dk, ortalama ${(O.reduce((t, x) => t + x, 0) / O.length).toFixed(0)} dk`);
  const yavas = AD.filter((a) => UYG[a].bicim === "baslangicta");
  console.log(`tek ortak pencerede dondurulurse gereken ortusme: ${Math.max(...O)} dk`);
  console.log(`ortusmeyi belirleyen: baslangicta okuyan ${yavas.length} uygulama, ` +
    `${SIR.filter((s) => okurlar(s).some((a) => UYG[a].bicim === "baslangicta" &&
      gecis(a) === ortusme(s))).length} / ${SIR.length} sirda tek basina`);
}
```

```
gecis suresi — yeni degere gecmek icin gereken en kotu sure (dk)
uygulama                 bicim   ornek    yb   gecis(dk)
portal-onyuz       baslangicta       4     6         960
portal-api          onbellekli       8    12          60
abone-kayit        baslangicta       2     3         960
fatura-servisi      onbellekli       2     2         240
odeme-koprusu      her-istekte       3     2           0
saha-api            onbellekli       5     8          60
is-emri            baslangicta       3     4        1080
bildirim            onbellekli       2     3          15
rapor-uretici      baslangicta       1     1        1440

sir                  okur   ortusme  = saat     belirleyen uygulama
nesne-deposu            1      1440    24.0           rapor-uretici
eposta-gecidi           3      1440    24.0           rapor-uretici
arsiv                   2      1440    24.0           rapor-uretici
portal-okuma            3      1440    24.0           rapor-uretici
harita-servisi          2      1080    18.0                 is-emri
bildirim-kuyrugu        2      1080    18.0                 is-emri
is-emri-kuyrugu         2      1080    18.0                 is-emri
saha-birincil           2      1080    18.0                 is-emri
kisa-mesaj-gecidi       2       960    16.0             abone-kayit
oturum-imzalama         2       960    16.0            portal-onyuz
portal-birincil         2       960    16.0             abone-kayit
odeme-gecidi            2       240     4.0          fatura-servisi
belge-imzalama          1       240     4.0          fatura-servisi
fatura-birincil         1       240     4.0          fatura-servisi
gunluk-yazma            1        60     1.0              portal-api
onbellek                1        60     1.0              portal-api
ic-cagri-imzalama       2        60     1.0     portal-api,saha-api

17 sir; asgari ortusme en uzun 1440 dk, en kisa 60 dk, ortalama 815 dk
tek ortak pencerede dondurulurse gereken ortusme: 1440 dk
ortusmeyi belirleyen: baslangicta okuyan 4 uygulama, 11 / 17 sirda tek basina
```

Üstteki tablo geçiş süresinin nereden geldiğini gösteriyor. Ödeme köprüsü sırrı her istekte
okuduğu için sıfır dakikada geçer; bildirim servisi on beş dakikalık önbelleğiyle en geç on beş
dakikada. Yalnız başlangıçta okuyan dört uygulamada ise geçiş süresi bir ayar değil, bir
**istatistiktir**: rapor üreticisi tek örnekle çalışıyor ve günde bir kez yeniden başlıyor,
dolayısıyla yeni değeri ortalama bin dört yüz kırk dakika sonra görüyor. Bu sayı sır yönetiminin
hiçbir ayarında yazmaz, dağıtım düzeninden gelir.

Alt tablo asıl ölçüyü veriyor. Bir sırrın asgari örtüşmesi, onu okuyanların **en yavaşının**
geçiş süresidir; başka bir ifadeyle örtüşme bir ortalama değil, bir azami değerdir. Bu yüzden
tek okuyucusu olan nesne deposu anahtarı ile üç okuyucusu olan e-posta geçidi anahtarı aynı
satırda: ikisinde de en yavaş okuyucu rapor üreticisidir ve ikisi de yirmi dört saat örtüşme
gerektirir. Okuyucu sayısı örtüşmeyi belirlemiyor; okuyucuların **en kötüsü** belirliyor.

En kısa örtüşme gerektiren üç sır, yalnız önbellekli uygulamalar tarafından okunanlardır: iç
çağrı imzalama anahtarı iki uygulama tarafından okunuyor ve altmış dakikada dönebiliyor. Bin
dört yüz kırk dakika ile altmış dakika arasında yirmi dört kat var ve bu farkın tamamı okuma
biçiminden geliyor — sırların duyarlılığında ya da politikalarında hiçbir fark yok.

Son satır bulguyu tek cümlede topluyor: başlangıçta okuyan dört uygulama, on yedi sırrın
on birinde örtüşmeyi **tek başına** belirliyor. Bunlar sistemin en küçük, en az istek alan
uygulamalarıdır — rapor üreticisi günde üç yüz yirmi istek görüyor. Döndürme takviminin tamamı
bu dört uygulamanın yeniden başlatma alışkanlığına bağlı.

#### Pencereyi Kısaltmanın Faturası

Yirmi dört saatlik örtüşme döndürmenin amacına ters düşer: sızmış eski değer o yirmi dört saat
boyunca da çalışır. Pencereyi kısaltmanın ölçülebilir bir karşılığı var.

```js
// sira.mjs — ortusme penceresi kisa tutuldugunda ve sira ters oldugunda ne kesiliyor
import { AD, OKUR, SIR, UYG, gecis, okurlar, ortusme, gen } from "./gecis.mjs";

// T dakikalik ortusmede bir uygulama gecis(a) - T dakika eski degerde kalir ve o sure boyunca
// o sirra bagli istekleri duser. On yedi sir ayri ayri dondurulur, sonuclar toplanir.
const kesilenIstek = (T, g = gecis) => SIR.reduce((t, s) => t + okurlar(s)
  .reduce((x, a) => x + UYG[a].istek * Math.max(0, g(a) - T) / 1440, 0), 0);
const kacanIstemci = (T, g = gecis) => SIR.reduce((t, s) => t + okurlar(s)
  .reduce((x, a) => x + (g(a) > T ? UYG[a].ornek : 0), 0), 0);

const yz = gen([14, 18, 16, 20]);
console.log(yz(["ortusme(dk)", "kacan istemci", "kesilen istek", "eski deger gecerli"]));
for (const T of [0, 15, 60, 240, 960, 1080, 1440])
  console.log(yz([T, kacanIstemci(T), Math.round(kesilenIstek(T)), `${T} dk`]));

const ORT = SIR.map(ortusme), toplamOrt = ORT.reduce((t, x) => t + x, 0);
console.log(`\nsir basina kendi asgari ortusmesi kullanilirsa: kacan istemci 0, kesilen istek 0,`);
console.log(`eski deger ortalama ${(toplamOrt / SIR.length).toFixed(0)} dk ` +
  `(${(toplamOrt / SIR.length / 60).toFixed(1)} saat) daha gecerli kalir`);

// ters sira: once eski deger iptal edilir, YAZ dakika sonra yenisi yazilir, sonra yayilir.
const YAZ = 5;
console.log(`\nters sira (once iptal, ${YAZ} dk sonra yeni deger): kacan istemci ` +
  `${kacanIstemci(-1)}, kesilen istek ${Math.round(kesilenIstek(0) +
    SIR.reduce((t, s) => t + okurlar(s).reduce((x, a) => x + UYG[a].istek * YAZ / 1440, 0), 0))}`);
console.log(`dogru sirada hic kesilmeyen tek uygulama her istekte okuyan odeme-koprusu; ` +
  `ters sirada o da ${Math.round(OKUR["odeme-koprusu"].length * UYG["odeme-koprusu"].istek *
    YAZ / 1440)} istek kaybeder`);

// hata uzerine yeniden okuma: baslangicta okuyan uygulama kimlik hatasinda sirri tazeler.
const HATA = 5;
const g2 = (a) => UYG[a].bicim === "baslangicta" ? HATA : gecis(a);
const ORT2 = SIR.map((s) => Math.max(...okurlar(s).map(g2)));
console.log(`\nhata uzerine yeniden okuma eklenirse (baslangicta okuyan ${AD.filter((a) =>
  UYG[a].bicim === "baslangicta").length} uygulama, gecis ${HATA} dk):`);
console.log(`  asgari ortusme en uzun ${Math.max(...ORT)} -> ${Math.max(...ORT2)} dk, ` +
  `ortalama ${(toplamOrt / SIR.length).toFixed(0)} -> ` +
  `${(ORT2.reduce((t, x) => t + x, 0) / SIR.length).toFixed(0)} dk`);
console.log(`  60 dk ortusmede kesilen istek ${Math.round(kesilenIstek(60))} -> ` +
  `${Math.round(kesilenIstek(60, g2))}, kacan istemci ${kacanIstemci(60)} -> ` +
  `${kacanIstemci(60, g2)}`);
```

```
ortusme(dk)        kacan istemci   kesilen istek  eski deger gecerli
0                            110          125422                0 dk
15                           104          115642               15 dk
60                            36           87427               60 dk
240                           26           67567              240 dk
960                           16            3627              960 dk
1080                           4             320             1080 dk
1440                           0               0             1440 dk

sir basina kendi asgari ortusmesi kullanilirsa: kacan istemci 0, kesilen istek 0,
eski deger ortalama 815 dk (13.6 saat) daha gecerli kalir

ters sira (once iptal, 5 dk sonra yeni deger): kacan istemci 113, kesilen istek 128693
dogru sirada hic kesilmeyen tek uygulama her istekte okuyan odeme-koprusu; ters sirada o da 12 istek kaybeder

hata uzerine yeniden okuma eklenirse (baslangicta okuyan 4 uygulama, gecis 5 dk):
  asgari ortusme en uzun 1440 -> 240 dk, ortalama 815 -> 102 dk
  60 dk ortusmede kesilen istek 87427 -> 3875, kacan istemci 36 -> 10
```

Tablo bir ayar eğrisidir ve iki uçtan okunmalıdır. En üstteki satır örtüşmenin sıfır olduğu
durumdur: yeni değer yazılır yazılmaz eski iptal edilir. Yüz on istemci — yani dokuz uygulamanın
çalışan otuz örneğinin okudukları sırlar üzerinden sayıldığında yüz on kalem — eski değerde
kalıyor ve on yedi döndürmenin toplamında yüz yirmi beş bin dört yüz yirmi iki meşru istek
kesiliyor. En alttaki satır tersidir: bin dört yüz kırk dakikalık örtüşmede hiçbir istemci
kaçmıyor, hiçbir istek kesilmiyor ve eski değer tam bir gün daha geçerli kalıyor.

Ortadaki satırlar dağılımın nasıl olduğunu gösteriyor. Altmış dakikalık örtüşme kaçan istemciyi
yüz ondan otuz altıya indiriyor, ama kesilen isteği yalnız yüz yirmi beş binden seksen yedi bine.
Oranların eşleşmemesi anlamlıdır: kaçan istemcilerin çoğu portal uygulama arayüzünün sekiz
örneğidir ve o örnekler altmış dakikada geçer; kesilen isteğin çoğu ise **tek bir uygulamadan**
gelir. Portal ön yüzü günde seksen dört bin istek görüyor ve dokuz yüz altmış dakika sonra
geçiyor; bu tek uygulama, altmış dakikalık örtüşmede kesilen seksen yedi bin isteğin elli iki
bin beş yüzünü tek başına üretiyor.

Sonraki iki satır doğru yordamı yazıyor. Her sır kendi asgari örtüşmesiyle döndürülürse kesilen
istek sıfırdır; bedel, eski değerin ortalama sekiz yüz on beş dakika daha geçerli kalmasıdır.
Yani örtüşme bir güvenlik ayarı değil, **açık pencereye eklenen sabit bir süredir**: doksan
günlük periyotla döndürülen bir anahtarın gerçek en kötü penceresi doksan gün değil, doksan gün
artı on üç buçuk saattir.

Ters sıra satırı ayrı bir sınıftır. Eski değer önce iptal edilip yenisi beş dakika sonra
yazıldığında kaçan istemci yüz on üçe, kesilen istek yüz yirmi sekiz bin altı yüz doksan üçe
çıkıyor. Aradaki fark büyük değil — üç istemci, üç bin istek — ama fark **kimde olduğu**
belirleyicidir: doğru sırada hiç etkilenmeyen ödeme köprüsü, ters sırada on iki ödeme isteği
kaybediyor. Sıfır dakikada geçen bir uygulamayı kesmenin tek yolu, geçilecek değeri henüz
yazmamış olmaktır. Ters sıranın belirtisi budur ve gösterge tablosunda yalnız bu on iki istek
görünür.

#### Pencere Nerede Kısalır

Son iki satır kursun asıl sorusunu yanıtlıyor. Yirmi dört saatlik örtüşme bir sır yönetimi
sorunu değildir; **başlangıçta okuyan bir uygulamanın sırrı bir daha hiç okumaması** sorunudur.
Uygulamalara kimlik hatası aldıklarında sırrı tazeleme davranışı eklendiğinde asgari örtüşme bin
dört yüz kırk dakikadan iki yüz kırk dakikaya, ortalama sekiz yüz on beş dakikadan yüz iki
dakikaya iniyor; altmış dakikalık örtüşmede kesilen istek seksen yedi bin dört yüz yirmi
yediden üç bin sekiz yüz yetmiş beşe düşüyor, yani yirmi üç kat.

Bu değişikliğin nerede yapıldığı önemlidir. Sır deposunda, döndürme takviminde ya da çalışma
zamanı savunmasında değil, **uygulama kodunda** yapılır: kimlik doğrulama hatası yakalanır, sır
yeniden okunur, istek bir kez daha denenir. Birkaç düzine satırlık bir davranış döndürme
penceresini yirmi dört kat kısaltıyor ve bir kez yazıldığında bütün sırlar için geçerli oluyor.
Aynı sonucu çalışma zamanında elde etmenin yolu her sır için ayrı örtüşme takvimi tutmak, her
döndürmede hangi uygulamanın geçtiğini izlemek ve geçmeyeni elle yeniden başlatmaktır.

Geriye kalan iki yüz kırk dakika ise gerçekten çalışma zamanına aittir: fatura servisinin dört
saatlik önbellek ömrü. O bir ayardır ve düşürülebilir; düşürüldüğünde önceki dersin ölçtüğü depo
isteği artar. Örtüşme, önbellek ömrü ve depo yükü tek bir sayının üç görünümüdür.

#### Özet

- Bir sırrın asgari örtüşmesi, onu okuyanların en yavaşının geçiş süresidir. On yedi sırda bu
  süre 60 ile 1.440 dakika arasında, ortalaması 815 dakika; tek ortak pencere kullanılırsa 1.440
  dakika.
- Örtüşmeyi belirleyen şey sırrın duyarlılığı ya da okuyucu sayısı değil, okuma biçimidir.
  Başlangıçta okuyan dört uygulama 17 sırrın 11'inde pencereyi tek başına belirliyor.
- Örtüşme sıfıra çekildiğinde 110 istemci eski değerde kalıyor ve 125.422 meşru istek kesiliyor;
  60 dakikada 36 istemci ve 87.427 istek, 1.440 dakikada sıfır ve sıfır. Kesilen isteğin
  52.500'ü tek bir uygulamadan, portal ön yüzünden geliyor.
- Her sır kendi asgari örtüşmesiyle döndürülürse kesme sıfırdır; bedel, eski değerin ortalama 815
  dakika daha geçerli kalmasıdır. Doksan günlük periyodun gerçek penceresi doksan gün artı on üç
  buçuk saattir.
- Ters sıra (önce iptal, sonra yazma) kesileni 128.693'e çıkarıyor. Asıl belirtisi hacim değil,
  doğru sırada hiç etkilenmeyen ödeme köprüsünün 12 istek kaybetmesidir.
- Örtüşmeyi kısaltan değişiklik kod aşamasındadır: hata üzerine yeniden okuma, asgari örtüşmeyi
  1.440'tan 240 dakikaya, 60 dakikalık pencerede kesileni 23 kat aşağı indiriyor.

#### Sonraki Adım

İki ders boyunca ölçülen şey aynı nesnenin iki özelliğiydi: sırrın ömrü ve sırrın değişme
maliyeti. İkisi de sırrın **var olduğunu** varsayıyordu. Bu varsayım kaldırılabilir. Bir
uygulamanın veri tabanına bağlanmak için taşıdığı değer, o uygulamanın kim olduğunu kanıtlamanın
bir yoludur; kanıt platform tarafından verilirse taşınacak bir değer kalmaz. Sonraki ders bunu
tek eksende sayar: iş yükü kimliği otuz bir kalemin kaçını ortadan kaldırıyor, geriye kaç kalem
ve hangi sistemler kalıyor, kaç uygulama hiçbir statik sır taşımaz hâle geliyor — ve sırrın
yerini alan güven ilişkisinin kendisi kaç satır.

### İş Yükü Kimliği

Source: https://academia.sh/tr/kurslar/calisma-zamani-guvenligi/is-yuku-kimligi

İş yükü kimliği tek bir sayıyla ölçülür: kaç statik sırrın yerini alıyor. Otuz bir kalemin yirmisi ortadan kalkıyor, on biri kalıyor ve kalanların tamamı altı sırda toplanıyor — imzayı doğrulayan tarafta duran anahtarlar ile federasyonu desteklemeyen dış sağlayıcılar. Dokuz uygulamanın yalnız ikisi hiçbir statik sır taşımaz hâle geliyor, yedisi en az bir tane taşımaya devam ediyor. Sırrın yerini alan güven ilişkisi kalem sayısını düşürmüyor; kalemin sızabilir olmasını düşürüyor — ve grup düzeyinde yazıldığında yirmi çift yerine otuz altı çift açıyor.

İki ders boyunca ölçülen şey aynı nesnenin iki özelliğiydi: sırrın ömrü ve sırrın değişme
maliyeti. İkisi de sırrın **var olduğunu** varsayıyordu. Bu ders o varsayımı kaldırır.

Bir uygulamanın veri tabanına bağlanmak için taşıdığı değer, aslında o uygulamanın kim olduğunu
kanıtlamanın bir yoludur. Kanıt uygulamanın kendi taşıdığı bir değerden değil, uygulamayı
çalıştıran platformdan gelirse, taşınacak bir değer kalmaz. İş yükü kimliğinin mekaniği —
kimliğin nasıl verildiği, nasıl doğrulandığı, hangi bileşenlerin işe karıştığı — daha önceki bir
kursta ölçüldü ve burada tekrarlanmıyor. Buranın ölçüsü tek bir sayıdır: **kaç statik sırrın
yerini alıyor, kaç tanesinin alamıyor.**

- **SR18.** Önceki üç dersin modeli sürüyor: dokuz uygulama, otuz bir kalem, on yedi sır. Ortam
  **kurgudur**, ölçülen şey `node` ile yazılmış bir **modeldir** ve **gerçek sır değeri
  taşımaz**.
- **SR19.** Bir hedef sistemin iş yükü kimliğini doğrudan doğrulayıp doğrulayamadığı model
  tablosunda verilir ve gerekçesiyle yazılır. İki gerekçe var: kanıtın doğrulayan tarafta durması
  gerekmesi ve sağlayıcının federasyonu desteklememesi.
- **SR20.** İmza anahtarları özel bir durumdur. Belge ve oturum imzasını doğrulayan taraf
  anahtarın kendisine ihtiyaç duyar; iş yükü kimliği bir çağrıyı yetkilendirir, bir imzayı
  doğrulatmaz. Buna karşılık **servisler arası çağrı** imzası yetkilendirmedir ve iş yükü
  kimliğiyle karşılanır.
- **SR21.** Jeton ömrü on beş dakika alınıyor; bu bir kurgu değerdir ve iş yükü kimliği
  jetonunun süresi dolmadan iptal edilemediği varsayılıyor.
- **SR22.** Rastgelelik yok; bütün sayılar model tablolarından türetiliyor ve çıktı koşumdan
  koşuma aynı.

#### Kaç Kalem Ortadan Kalkıyor

```js
// kimlik.mjs — is yuku kimliginin ortadan kaldirdigi statik sir ve geriye kalan kalem. MODELDIR.
// Ortam KURGUDUR; GERCEK SIR DEGERI YOKTUR, yalniz sir yollari ve kabul ozellikleri modellenir.
export const OKUR = {
  "portal-onyuz": ["imza/oturum-imzalama"],
  "portal-api": ["veri/portal-birincil", "veri/portal-okuma", "imza/oturum-imzalama",
    "imza/ic-cagri-imzalama", "altyapi/onbellek", "altyapi/gunluk-yazma"],
  "abone-kayit": ["veri/portal-birincil", "dis/eposta-gecidi", "dis/kisa-mesaj-gecidi"],
  "fatura-servisi": ["veri/fatura-birincil", "veri/portal-okuma", "veri/arsiv",
    "dis/odeme-gecidi", "imza/belge-imzalama"],
  "odeme-koprusu": ["dis/odeme-gecidi"],
  "saha-api": ["veri/saha-birincil", "kuyruk/is-emri-kuyrugu", "dis/harita-servisi",
    "imza/ic-cagri-imzalama"],
  "is-emri": ["veri/saha-birincil", "kuyruk/is-emri-kuyrugu", "kuyruk/bildirim-kuyrugu",
    "dis/harita-servisi"],
  "bildirim": ["kuyruk/bildirim-kuyrugu", "dis/eposta-gecidi", "dis/kisa-mesaj-gecidi"],
  "rapor-uretici": ["veri/portal-okuma", "veri/arsiv", "altyapi/nesne-deposu",
    "dis/eposta-gecidi"],
};
// kabul: hedef sistem is yuku kimligini dogrudan dogrulayabiliyor mu (evet/hayir + gerekce).
// dondurme: kimlik alamayan sirrin bugunku dondurme periyodu (gun).
const ALANVAR = { veri: [true, "-", 180], kuyruk: [true, "-", 180], altyapi: [true, "-", 180],
  imza: [false, "dogrulayan-tarafta", 90], dis: [false, "saglayici-desteklemiyor", 365] };
const ISTISNA = { "altyapi/onbellek": [false, "saglayici-desteklemiyor", 180],
  "imza/ic-cagri-imzalama": [true, "-", 90], "dis/harita-servisi": [true, "-", 365],
  "dis/odeme-gecidi": [false, "saglayici-desteklemiyor", 90] };
export const SIR = Object.fromEntries([...new Set(Object.values(OKUR).flat())].map((s) => {
  const [kabul, gerekce, dondurme] = ISTISNA[s] || ALANVAR[s.split("/")[0]];
  return [s, { kabul, gerekce, dondurme }];
}));
export const AD = Object.keys(OKUR);
export const KALEM = AD.flatMap((a) => OKUR[a].map((s) => [a, s]));
export const kalan = (a) => OKUR[a].filter((s) => !SIR[s].kabul);
export const gen = (B) => (h) => h.map((v, j) => j ? String(v).padStart(B[j])
  : String(v).padEnd(B[0])).join("");

if (import.meta.url === `file://${process.argv[1]}`) {
  const yz = gen([10, 8, 10, 8, 12, 26]);
  console.log(`model: ${KALEM.length} (uygulama, sir) kalemi, ${Object.keys(SIR).length} sir, ` +
    `${AD.length} uygulama (kurgu uretim ortami)\n`);
  console.log(yz(["alan", "sir", "kalkan", "kalan", "kalan sir", "kalma gerekcesi"]));
  for (const al of ["veri", "kuyruk", "altyapi", "imza", "dis"]) {
    const k = KALEM.filter(([, s]) => s.startsWith(al + "/"));
    const kl = k.filter(([, s]) => !SIR[s].kabul);
    const g = [...new Set(kl.map(([, s]) => SIR[s].gerekce))];
    console.log(yz([al, [...new Set(k.map(([, s]) => s))].length, k.length - kl.length, kl.length,
      [...new Set(kl.map(([, s]) => s))].length, g.length ? g.join(",") : "-"]));
  }
  const K = KALEM.filter(([, s]) => !SIR[s].kabul);
  console.log(yz(["toplam", Object.keys(SIR).length, KALEM.length - K.length, K.length,
    [...new Set(K.map(([, s]) => s))].length, ""]));

  const yz2 = gen([16, 10, 10, 34]);
  console.log(`\n${yz2(["uygulama", "kalem", "kalan", "kalan sirlar"])}`);
  for (const a of AD)
    console.log(yz2([a, OKUR[a].length, kalan(a).length,
      kalan(a).map((s) => s.split("/")[1]).join(",") || "yok"]));
  const temiz = AD.filter((a) => kalan(a).length === 0);
  console.log(`\nhic statik sir tasimayan uygulama: ${temiz.length} / ${AD.length} ` +
    `(${temiz.join(", ")})`);
  console.log(`en az bir statik sir tasiyan uygulama: ${AD.length - temiz.length} / ${AD.length}`);
  const G = K.reduce((t, [, s]) => t + SIR[s].dondurme, 0);
  const T = KALEM.reduce((t, [, s]) => t + SIR[s].dondurme, 0);
  console.log(`toplam acik pencere: ${Math.round(T / 2)} -> ${Math.round(G / 2)} kalem-gun ` +
    `(%${(100 - 100 * G / T).toFixed(0)} dusus); kalem basina ortalama ` +
    `${(T / KALEM.length / 2).toFixed(0)} -> ${(G / K.length / 2).toFixed(0)} gun`);
}
```

```
model: 31 (uygulama, sir) kalemi, 17 sir, 9 uygulama (kurgu uretim ortami)

alan           sir    kalkan   kalan   kalan sir           kalma gerekcesi
veri             5        10       0           0                         -
kuyruk           2         4       0           0                         -
altyapi          3         2       1           1   saglayici-desteklemiyor
imza             3         2       3           2        dogrulayan-tarafta
dis              4         2       7           3   saglayici-desteklemiyor
toplam          17        20      11           6                          

uygulama             kalem     kalan                      kalan sirlar
portal-onyuz             1         1                   oturum-imzalama
portal-api               6         2          oturum-imzalama,onbellek
abone-kayit              3         2   eposta-gecidi,kisa-mesaj-gecidi
fatura-servisi           5         2       odeme-gecidi,belge-imzalama
odeme-koprusu            1         1                      odeme-gecidi
saha-api                 4         0                               yok
is-emri                  4         0                               yok
bildirim                 3         2   eposta-gecidi,kisa-mesaj-gecidi
rapor-uretici            4         1                     eposta-gecidi

hic statik sir tasimayan uygulama: 2 / 9 (saha-api, is-emri)
en az bir statik sir tasiyan uygulama: 7 / 9
toplam acik pencere: 3123 -> 1228 kalem-gun (%61 dusus); kalem basina ortalama 101 -> 112 gun
```

Üst tablonun ilk iki satırı beklenen sonucu veriyor: veri tabanı ve kuyruk kalemlerinin tamamı,
on dört kalem, ortadan kalkıyor. Bunlar iç sistemlerdir ve iş yükünün kim olduğunu platformdan
öğrenip doğrudan yetkilendirebilirler. Sır yönetimi açısından bu kalemler artık yoktur — ne
saklanır, ne döndürülür, ne sızar.

İmza satırı ayrımı kuruyor. Üç imza sırrından biri, servisler arası çağrı imzası, kalkıyor;
çünkü o imza bir yetkilendirme kanıtıdır ve iş yükü kimliği aynı işi yapar. Diğer ikisi kalıyor:
oturum imzasını doğrulayan taraf ile belge imzasını doğrulayan taraf anahtarın **kendisine**
ihtiyaç duyar. Bu ayrım sık atlanır ve "iş yükü kimliği bütün anahtarları kaldırır" iddiasının
kırıldığı yerdir. İş yükü kimliği bir çağrıyı yetkilendirir; bir imzayı doğrulatmaz.

Dış satırı ise kalanın en büyük payıdır: dört dış geçitten yalnız harita servisi federasyonu
destekliyor, üçü sabit anahtar veriyor ve bu üç sır yedi kaleme yayılmış durumda. Önceki dersin
"kısaltılamayan sekiz sır" listesiyle kıyaslandığında tablo tutarlıdır — aynı sağlayıcı
kısıtları, aynı kalemlerde.

Alt tablo kararın kendisidir. Yirmi kalemin kalkması, dokuz uygulamanın yalnız **ikisini**
hiçbir statik sır taşımaz hâle getiriyor: saha uygulama arayüzü ve iş emri servisi. Diğer yedi
uygulama en az bir statik sır taşımaya devam ediyor ve çoğu yalnız bir ya da iki tane taşıyor.
Bu, ölçünün en önemli bulgusudur. **Kalem sayısı yüzde altmış beş azalırken, sır taşıyan uygulama
sayısı dokuzdan yediye iniyor.** Sır yönetimi işi, kalem sayısıyla değil, sır taşıyan uygulama
sayısıyla orantılıdır: her uygulamanın hâlâ bir sır dağıtım yolu, bir sahibi, bir döndürme
takvimi ve bir sızıntı yordamı olmak zorundadır. İki uygulamayı kurtarmak, o yedi yordamdan
hiçbirini ortadan kaldırmıyor.

Son satır aynı şeyi açık pencere cinsinden söylüyor. Toplam maruziyet üç bin yüz yirmi üç
kalem-günden bin iki yüz yirmi sekize, yüzde altmış bir aşağı iniyor. Ama kalem başına ortalama
pencere yüz bir günden yüz on iki güne **çıkıyor**: kalkan kalemler kısa döndürme periyoduna
sahip olan iç kalemlerdi, kalanlar ise üç yüz altmış beş günlük dış anahtarlardır. Kalanın
niteliği kötüleşiyor.

#### Sırrın Yerine Ne Geçiyor

Kalkan yirmi kalem hiçliğe gitmiyor; her birinin yerine bir **güven ilişkisi** yazılıyor: hedef
sistemin hangi iş yükü kimliğini kabul edeceğini söyleyen bir bağlama kuralı.

```js
// baglama.mjs — sirrin yerini alan guven iliskisi: kac kural, kac cift, kac tek nokta
import { AD, OKUR, SIR, KALEM, kalan, gen } from "./kimlik.mjs";

const JETON = 15;                      // is yuku kimligi jetonunun omru (dk, kurgu)
export const GRUP = { portal: ["portal-onyuz", "portal-api", "abone-kayit"],
  fatura: ["fatura-servisi", "odeme-koprusu"], saha: ["saha-api", "is-emri"],
  arka: ["bildirim", "rapor-uretici"] };
const kimlikli = (a) => OKUR[a].filter((s) => SIR[s].kabul);

const yz = gen([10, 9, 8, 13, 12, 16]);
console.log(yz(["grup", "is yuku", "hedef", "grup kural", "grup cift", "is yuku kural"]));
let GK = 0, GC = 0, IK = 0;
for (const [g, uyeler] of Object.entries(GRUP)) {
  const hedef = [...new Set(uyeler.flatMap(kimlikli))];
  const iy = uyeler.reduce((t, a) => t + kimlikli(a).length, 0);
  GK += hedef.length; GC += uyeler.length * hedef.length; IK += iy;
  console.log(yz([g, uyeler.length, hedef.length, hedef.length,
    uyeler.length * hedef.length, iy]));
}
console.log(yz(["toplam", AD.length, "", GK, GC, IK]));
console.log(`\ngrup duzeyinde baglama: ${GK} kural, ${GC} (is yuku, hedef) cifti acik`);
console.log(`is yuku duzeyinde baglama: ${IK} kural, ${IK} cift acik; ` +
  `karsiliksiz cift ${GC - IK}`);
console.log(`her iki durumda da sizabilir deger tasiyan kural sayisi: 0 ` +
  `(kural bir yetki kaydidir, bir sir degil)`);

const yz2 = gen([16, 10, 13, 25]);
console.log(`\n${yz2(["uygulama", "kimlikli", "statik sir", "bagli oldugu tek nokta"])}`);
for (const a of AD) {
  const k = kimlikli(a).length, st = kalan(a).length;
  console.log(yz2([a, k, st, k && st ? "depo+kimlik" : k ? "kimlik" : "depo"]));
}
const D = AD.filter((a) => kalan(a).length > 0), K = AD.filter((a) => kimlikli(a).length > 0);
console.log(`\nsir deposuna bagli ${D.length}, kimlik saglayiciya bagli ${K.length}, ` +
  `ikisine birden ${AD.filter((a) => kalan(a).length && kimlikli(a).length).length}, ` +
  `hicbirine bagli olmayan ${AD.filter((a) => !kalan(a).length && !kimlikli(a).length).length}`);
const kalkan = KALEM.filter(([, s]) => SIR[s].kabul);
console.log(`kalkan ${kalkan.length} kalemin bugunku maruziyeti ` +
  `${kalkan.reduce((t, [, s]) => t + SIR[s].dondurme / 2, 0)} kalem-gun; yerine gecen jetonun ` +
  `omru ${JETON} dk, yani ${(kalkan.length * JETON / 2 / 1440).toFixed(2)} kalem-gun`);
console.log(`kimlik saglayici kesintisinde ${JETON} dk sonra duran uygulama: ${K.length} / ` +
  `${AD.length}; kesintiden hic etkilenmeyen uygulama: 0 / ${AD.length}`);
```

```
grup        is yuku   hedef   grup kural   grup cift   is yuku kural
portal            3       4            4          12               5
fatura            2       3            3           6               3
saha              2       5            5          10               8
arka              2       4            4           8               4
toplam            9                   16          36              20

grup duzeyinde baglama: 16 kural, 36 (is yuku, hedef) cifti acik
is yuku duzeyinde baglama: 20 kural, 20 cift acik; karsiliksiz cift 16
her iki durumda da sizabilir deger tasiyan kural sayisi: 0 (kural bir yetki kaydidir, bir sir degil)

uygulama          kimlikli   statik sir   bagli oldugu tek nokta
portal-onyuz             0            1                     depo
portal-api               4            2              depo+kimlik
abone-kayit              1            2              depo+kimlik
fatura-servisi           3            2              depo+kimlik
odeme-koprusu            0            1                     depo
saha-api                 4            0                   kimlik
is-emri                  4            0                   kimlik
bildirim                 1            2              depo+kimlik
rapor-uretici            3            1              depo+kimlik

sir deposuna bagli 7, kimlik saglayiciya bagli 7, ikisine birden 5, hicbirine bagli olmayan 0
kalkan 20 kalemin bugunku maruziyeti 1895 kalem-gun; yerine gecen jetonun omru 15 dk, yani 0.10 kalem-gun
kimlik saglayici kesintisinde 15 dk sonra duran uygulama: 7 / 9; kesintiden hic etkilenmeyen uygulama: 0 / 9
```

Üst tablo bu konunun ilk dersindeki bulguyu aynen tekrar ediyor, yalnız nesne değişmiş. Bağlama
kuralı iş yükü grubuna yazıldığında on altı kural yetiyor ama otuz altı `(iş yükü, hedef)` çifti
açılıyor; iş yükü başına yazıldığında yirmi kural gerekiyor ve tam yirmi çift açılıyor.
Karşılıksız on altı çift, ilk dersteki kırk sekiz karşılıksız kalemin aynı biçimidir: **geniş
yazılan kural az satır, çok erişim demektir.** İş yükü kimliğine geçmek bu sorunu çözmüyor;
sorunu sır yolu önekinden iş yükü grubuna taşıyor.

Üçüncü satır ise farkın nerede olduğunu söylüyor. Bağlama kuralının sayısı yirmide kalsa bile
kural **sızabilir bir değer taşımıyor**. Kalkan yirmi kalemin bugünkü maruziyeti bin sekiz yüz
doksan beş kalem-gündü; yerine geçen jetonun ömrü on beş dakika, yani sıfır virgül bir kalem-gün.
Kazanç kalem sayısında değil, kalemin niteliğindedir: bir yetki kaydı çalınabilir bir şey
değildir, çünkü kopyalandığında hiçbir işe yaramaz — kimliği taşıyan iş yükünün kendisi
gerekir.

Alt tablo bedeli veriyor ve bedel tanıdıktır. İlk ders merkezî sır deposunun dokuz uygulamaya
ortak bir başlatma bağımlılığı yazdığını ölçmüştü. İş yükü kimliği bu bağımlılığı kaldırmıyor,
**ikinciye çıkarıyor**: yedi uygulama hâlâ sır deposuna, yedi uygulama kimlik sağlayıcıya, beşi
ikisine birden bağlı. Hiçbirine bağlı olmayan uygulama sayısı sıfır. Saha uygulama arayüzü ve iş
emri servisi sır deposundan tamamen kurtuldular, ama kimlik sağlayıcı on beş dakika erişilemez
olduğunda ikisi de duruyor. Bağımlılığın adı değişti, sayısı değişmedi.

#### Bu Karar Nereye Ait

Yirmi kalemin ortadan kalkması çalışma zamanında olan bir şey değildir. Hiçbir çalışma zamanı
savunması bir sırrı yakalamadı, durdurmadı ya da işaretlemedi; kalemler yok oldular çünkü
**dağıtım artık onları üretmiyor.** Bu, bu kursta ölçülen en ucuz kalem sınıfıdır: bir kalemi
yakalamak yerine hiç doğurmamak.

Bunun karşılığında yapılan iş de dağıtım aşamasındadır. Yirmi bağlama kuralı, hedef sistemlerin
yapılandırmasına yazılır ve iş yükü tanımına bağlanır; yazıldıktan sonra çalışma zamanında
izlenecek bir şey kalmaz. Çalışma zamanına düşen tek ölçüm, ilk derste yazılanın aynısıdır:
bağlama kurallarının açtığı çift kümesiyle gerçekten yapılan çağrıların karşılaştırılması. Otuz
altı çift açılıp yirmisi kullanılıyorsa, on altı çift karşılıksızdır ve bu ancak çağrı kaydından
görülür.

Kalan on bir kalem ise hiçbir aşamada kapatılamıyor. Üç dış sağlayıcı federasyonu
desteklemiyor, iki imza anahtarı doğrulayan tarafta duruyor, önbellek sunucusu kimlik kabul
etmiyor. Bu kalemlerin tamamı önceki iki dersin yordamlarına — döndürme takvimine, örtüşme
penceresine — geri düşüyor ve sonraki dersin konusu olan sızıntı akışına.

#### Özet

- İş yükü kimliği 31 kalemin 20'sini ortadan kaldırıyor, 11'i kalıyor. Kalanlar altı sırda
  toplanıyor: iki imza anahtarı, üç dış geçit anahtarı ve önbellek sunucusu.
- Ayrım gerekçelidir. Servisler arası çağrı imzası bir yetkilendirmedir ve kalkar; oturum ve
  belge imzası doğrulayan tarafta anahtarın kendisini gerektirir ve kalır. Dört dış geçitten
  yalnız biri federasyonu destekliyor.
- Kalem sayısı %65 azalırken sır taşıyan uygulama sayısı 9'dan 7'ye iniyor. Sır yönetimi işi
  kalem sayısıyla değil, sır taşıyan uygulama sayısıyla orantılıdır; yedi uygulamanın yordamı
  yerinde duruyor.
- Toplam açık pencere maruziyeti 3.123 kalem-günden 1.228'e (%61) iniyor, ama kalem başına
  ortalama pencere 101 günden 112 güne çıkıyor: kalkanlar iç kalemlerdi, kalanlar dış
  anahtarlardır.
- Sırrın yerine geçen bağlama kuralı sayıyı düşürmüyor, niteliği değiştiriyor: 1.895 kalem-günlük
  maruziyet 0,1 kalem-güne iniyor. Ama kural grup düzeyinde yazıldığında 16 satırla 36 çift
  açılıyor; iş yükü düzeyinde 20 satırla 20 çift. Karşılıksız 16 çift, ilk dersteki 48
  karşılıksız kalemin aynı biçimidir.
- Bağımlılık kalkmıyor, ikiye çıkıyor: 7 uygulama sır deposuna, 7 uygulama kimlik sağlayıcıya,
  5'i ikisine birden bağlı; hiçbirine bağlı olmayan uygulama sıfır.

#### Sonraki Adım

Bu ders sırların çoğunu ortadan kaldırdı, önceki iki ders kalanların ömrünü kısalttı ve döndürme
yordamını yazdı. Üçü de aynı soruyu yanıtsız bıraktı: **bir sır sızdığında ne oluyor.** Açık
pencere sırrın kendiliğinden geçersizleşme süresiydi; sızıntı fark edilip iptal edildiğinde
pencere daha erken kapanır. Ama fark etmek zaman alır, sahibini bulmak zaman alır, yenisini
üretmek zaman alır ve yeni değerin yayılması bir önceki dersin ölçtüğü örtüşme kadar sürer.
Sonraki ders bu akışı kalan altı sır üzerinde koşturur: sızıntı anından iptale kaç dakika
geçiyor, o dakikalarda sırdan kaç çağrı geçiyor, hangi aşamayı kısaltmak ne kazandırıyor ve
yayılmayı beklemeden iptal etmek kaç meşru isteği kesiyor.

### Sızıntı Müdahalesi

Source: https://academia.sh/tr/kurslar/calisma-zamani-guvenligi/sizinti-mudahalesi

Sızıntı müdahalesi iptal akışı olarak koşturulur: kalan altı statik sırda sızıntı anından iptale kadar ortalama 1.386 dakika, en kötü kalemde 4.650 dakika geçiyor ve o sürede sırlardan 224.171 çağrı geçiyor. Sahiplik kaydı 340, önceden üretilmiş yedek 465 dakika kazandırıyor; sürekli depo taraması hiçbir şey kazandırmıyor çünkü altı sızıntının yalnız ikisi depoya düşüyor. Yayılmayı beklemeden iptal 150.934 çağrıyı kurtarıyor ama 68.503 meşru isteği kesiyor — kurtarılan her 2,2 çağrı için bir kesilen istek.

Konunun ilk dört dersi sırların sayısını, ömrünü ve değişme maliyetini ölçtü ve aynı soruyu
yanıtsız bıraktı: bir sır sızdığında ne oluyor. Açık pencere, sırrın **kendiliğinden**
geçersizleşme süresiydi; sızıntı fark edilip iptal edilirse pencere daha erken kapanır. Bu ders
o "daha erken"i ölçer.

Ölçülen şey iptal akışıdır ve akış savunma tarafındadır. Sızmış bir sırla ne yapılabileceği ya da
o sırrın nasıl bulunacağı yazılmıyor; yazılan tek şey, sızıntının fark edilmesinden eski değerin
geçersiz kılınmasına kadar geçen dakikalar ve o dakikalarda sırdan geçen çağrı hacmidir. Ölçüm,
önceki dersten kalan **altı statik sır** üzerinde koşuyor.

- **SR23.** Önceki dört dersin modeli sürüyor. Ortam **kurgudur**, ölçülen şey `node` ile
  yazılmış bir **modeldir** ve **gerçek sır değeri taşımaz**; model yalnız sır yollarını ve akış
  sürelerini tutar.
- **SR24.** Her sırrın sızıntı kanalı modelde seçilmiştir ve tespit yolunu belirler: kod
  deposuna düşen sızıntı sürekli taramayla, günlük dosyasına düşen kullanım anormalliğiyle,
  üçüncü taraftaki sağlayıcı bildirimiyle, istemci paketindeki dış ihbarla fark edilir.
- **SR25.** Akış beş aşamalıdır: fark etme, teyit ve etki değerlendirmesi, sahibini bulma, yeni
  değeri üretme, yeni değerin yayılması. Yayılma süresi bir önceki dersin asgari örtüşmesidir.
- **SR26.** "Sırdan geçen çağrı", o sırrın açık pencere boyunca yetkilendirdiği toplam çağrı
  hacmidir; pencerenin **ölçeğini** gösteren üst sınırdır, kötüye kullanılan hacim değildir.
- **SR27.** Rastgelelik yok; bütün sayılar model tablolarından türetiliyor ve çıktı koşumdan
  koşuma aynı.

#### Fark Etmeden İptale Kaç Dakika

```js
// iptal.mjs — sizinti aninda iptale kadar gecen dakika ve o surede sirdan gecen cagri. MODELDIR.
// Ortam KURGUDUR; GERCEK SIR DEGERI YOKTUR, yalniz sir yollari ve akis sureleri modellenir.
// Sirrin nasil kullanilacagi yazilmaz; olculen sey savunma tarafindaki iptal akisidir.

// Onceki dersten kalan alti statik sir. kanal: sizintinin dustugu yer (modelde secilmis).
// sahip: sir kaydinda sahibi yazili mi. dis: yeni degeri dis saglayici uretiyor mu.
// cagri: sirrin yetkilendirdigi gunluk cagri. yayilma: onceki dersin asgari ortusmesi (dk).
export const SIR = {
  "altyapi/onbellek": { kanal: "depo", sahip: true, dis: false, cagri: 240000, yayilma: 60 },
  "imza/oturum-imzalama": { kanal: "gunluk", sahip: true, dis: false, cagri: 180000,
    yayilma: 960 },
  "imza/belge-imzalama": { kanal: "depo", sahip: true, dis: false, cagri: 6200, yayilma: 240 },
  "dis/odeme-gecidi": { kanal: "ucuncu-taraf", sahip: true, dis: true, cagri: 3400, yayilma: 240 },
  "dis/eposta-gecidi": { kanal: "istemci-paketi", sahip: false, dis: true, cagri: 13400,
    yayilma: 1440 },
  "dis/kisa-mesaj-gecidi": { kanal: "gunluk", sahip: false, dis: true, cagri: 8900,
    yayilma: 960 },
};
// tespit yolu kanala baglidir: yalniz kod deposuna dusen sizinti surekli taramayla yakalanir.
export const TESPIT = { depo: ["surekli tarama", 20], gunluk: ["kullanim anormalligi", 90],
  "ucuncu-taraf": ["saglayici bildirimi", 240], "istemci-paketi": ["dis ihbar", 2880] };
export const TEYIT = 30;                       // teyit ve etki degerlendirmesi (dk)
export const SAHIPLI = 10, SAHIPSIZ = 180;     // sahibini bulma (dk)
export const URETIM = 45, DISURETIM = 120;     // yeni deger uretme (dk)
export const AD = Object.keys(SIR);
export const asama = (s, o = {}) => {
  const k = SIR[s];
  return { tespit: o.tarama && k.kanal === "depo" ? 20 : TESPIT[k.kanal][1], teyit: TEYIT,
    sahip: k.sahip || o.kayit ? SAHIPLI : SAHIPSIZ,
    uretim: o.yedek ? 5 : k.dis ? DISURETIM : URETIM,
    yayilma: o.beklemez ? 0 : k.yayilma };
};
export const toplam = (s, o) => Object.values(asama(s, o)).reduce((t, x) => t + x, 0);
export const cagri = (s, o) => Math.round(SIR[s].cagri * toplam(s, o) / 1440);
export const gen = (B) => (h) => h.map((v, j) => j ? String(v).padStart(B[j])
  : String(v).padEnd(B[0])).join("");

if (import.meta.url === `file://${process.argv[1]}`) {
  const yz = gen([18, 22, 8, 7, 8, 9, 9, 8]);
  console.log(`iptal akisi — ${AD.length} statik sir (kurgu uretim ortami); sureler dakika\n`);
  console.log(yz(["sir", "tespit yolu", "tespit", "teyit", "sahip", "uretim", "yayilma",
    "toplam"]));
  for (const s of AD) {
    const a = asama(s);
    console.log(yz([s.split("/")[1], TESPIT[SIR[s].kanal][0], a.tespit, a.teyit, a.sahip,
      a.uretim, a.yayilma, toplam(s)]));
  }
  const T = AD.reduce((t, s) => t + toplam(s), 0), C = AD.reduce((t, s) => t + cagri(s), 0);
  console.log(yz(["toplam", "", "", "", "", "", "", T]));

  console.log(`\n${gen([18, 12, 12, 14, 16])(["sir", "toplam dk", "= saat",
    "gunluk cagri", "iptale kadar"])}`);
  for (const s of [...AD].sort((x, y) => cagri(y) - cagri(x)))
    console.log(gen([18, 12, 12, 14, 16])([s.split("/")[1], toplam(s),
      (toplam(s) / 60).toFixed(1), SIR[s].cagri, cagri(s)]));
  console.log(gen([18, 12, 12, 14, 16])(["toplam", T, (T / 60).toFixed(1), "", C]));
  console.log(`\nsir basina ortalama ${Math.round(T / AD.length)} dk ` +
    `(${(T / AD.length / 60).toFixed(1)} saat); en uzun ${Math.max(...AD.map((s) => toplam(s)))} dk`);
  console.log(`ayni sizinti kisa omurlu bir kimlik bilgisinde olsaydi iptal akisi hic islemez, ` +
    `pencere 60 dk kalirdi: ${Math.round(Math.max(...AD.map((s) => toplam(s))) / 60)} kat`);
}
```

```
iptal akisi — 6 statik sir (kurgu uretim ortami); sureler dakika

sir                          tespit yolu  tespit  teyit   sahip   uretim  yayilma  toplam
onbellek                  surekli tarama      20     30      10       45       60     165
oturum-imzalama     kullanim anormalligi      90     30      10       45      960    1135
belge-imzalama            surekli tarama      20     30      10       45      240     345
odeme-gecidi         saglayici bildirimi     240     30      10      120      240     640
eposta-gecidi                  dis ihbar    2880     30     180      120     1440    4650
kisa-mesaj-gecidi   kullanim anormalligi      90     30     180      120      960    1380
toplam                                                                               8315

sir                  toplam dk      = saat  gunluk cagri    iptale kadar
oturum-imzalama           1135        18.9        180000          141875
eposta-gecidi             4650        77.5         13400           43271
onbellek                   165         2.8        240000           27500
kisa-mesaj-gecidi         1380        23.0          8900            8529
odeme-gecidi               640        10.7          3400            1511
belge-imzalama             345         5.8          6200            1485
toplam                    8315       138.6                        224171

sir basina ortalama 1386 dk (23.1 saat); en uzun 4650 dk
ayni sizinti kisa omurlu bir kimlik bilgisinde olsaydi iptal akisi hic islemez, pencere 60 dk kalirdi: 78 kat
```

Üst tablo akışın nerede geçtiğini gösteriyor. Sır başına ortalama bin üç yüz seksen altı dakika,
yani yirmi üç saat; ama satırlar arasında yüz altmış beş ile dört bin altı yüz elli dakika
arasında yirmi sekiz kat fark var.

Sütunlara bakıldığında farkın tamamı iki aşamadan geliyor. Teyit her satırda otuz dakika, sahibini
bulma on ya da yüz seksen, üretme kırk beş ya da yüz yirmi. Tespit sütunu ise yirmiden iki bin
sekiz yüz seksene çıkıyor — yüz kırk dört kat — ve yayılma sütunu altmıştan bin dört yüz kırka.
**Akışın süresini belirleyen şey müdahale ekibinin hızı değil, sızıntının nasıl fark edildiği ve
yeni değerin ne kadar yavaş yayıldığıdır.** İkisi de sızıntıdan önce belirlenmiştir.

Alt tablo aynı satırları çağrı hacmine çeviriyor ve sıralamayı bozuyor. Süre olarak en kötü kalem
e-posta geçidi anahtarıdır, dört bin altı yüz elli dakikayla; ama iptale kadar en çok çağrı oturum
imzalama anahtarından geçiyor: yüz kırk bir bin sekiz yüz yetmiş beş. O anahtar günde yüz seksen
bin çağrı yetkilendiriyor ve bin yüz otuz beş dakika bu hacimde uzun bir süredir. Ters uçta belge
imzalama anahtarı var: üç yüz kırk beş dakikada yalnız bin dört yüz seksen beş çağrı. Aynı akış,
aynı yordam — sonuç iki kalemde doksan altı kat farklı, çünkü arkalarındaki trafik farklı.

Son satır bu konunun ikinci dersine bağlanıyor. Aynı sızıntı kısa ömürlü bir kimlik bilgisinde
olsaydı bu akışın hiçbir adımı işlemezdi: fark edilmesi, sahibinin bulunması, yenisinin üretilmesi
gerekmezdi; jeton altmış dakikada kendiliğinden geçersiz olurdu. En kötü kalemle arasındaki fark
yetmiş sekiz kat. İptal akışı, ömrü kısaltılamayan sırlar için ödenen bedeldir.

#### Hangi Aşamayı Kısaltmak Ne Kazandırıyor

```js
// hizlandirma.mjs — akisin hangi asamasini kisaltmak ne kazandiriyor, karsiliginda ne kesiyor
import { AD, SIR, TESPIT, asama, toplam, cagri, gen } from "./iptal.mjs";

// yeni degere gecmeyi bekleMEden iptal edilirse okuyucular gecis suresi boyunca kesilir.
// [uygulama, gecis(dk), gunluk istek] — onceki dersin gecis tablosundan.
const OKUR = {
  "altyapi/onbellek": [["portal-api", 60, 96000]],
  "imza/oturum-imzalama": [["portal-onyuz", 960, 84000], ["portal-api", 60, 96000]],
  "imza/belge-imzalama": [["fatura-servisi", 240, 6200]],
  "dis/odeme-gecidi": [["fatura-servisi", 240, 6200], ["odeme-koprusu", 0, 3400]],
  "dis/eposta-gecidi": [["abone-kayit", 960, 1400], ["bildirim", 15, 12000],
    ["rapor-uretici", 1440, 320]],
  "dis/kisa-mesaj-gecidi": [["abone-kayit", 960, 1400], ["bildirim", 15, 12000]],
};
const kesilen = (o) => o.beklemez ? Math.round(AD.reduce((t, s) => t + OKUR[s]
  .reduce((x, [, g, i]) => x + i * g / 1440, 0), 0)) : 0;

const AYAR = [["bugun", {}, "-"], ["+ sahiplik kaydi", { kayit: 1 }, "dagitim"],
  ["+ onceden uretilmis yedek", { kayit: 1, yedek: 1 }, "dagitim"],
  ["+ surekli depo taramasi", { kayit: 1, yedek: 1, tarama: 1 }, "yapi"],
  ["+ yayilmayi beklemeden iptal", { kayit: 1, yedek: 1, tarama: 1, beklemez: 1 },
    "calisma zamani"]];
const yz = gen([29, 11, 11, 15, 16]);
console.log(yz(["onlem", "toplam dk", "kazanc", "gecen cagri", "kesilen istek"]));
const T0 = AD.reduce((t, s) => t + toplam(s), 0);
for (const [ad, o] of AYAR) {
  const T = AD.reduce((t, s) => t + toplam(s, o), 0);
  console.log(yz([ad, T, T0 - T, AD.reduce((t, s) => t + cagri(s, o), 0), kesilen(o)]));
}
const son = AYAR[AYAR.length - 1][1], onceki = AYAR[AYAR.length - 2][1];
const dC = AD.reduce((t, s) => t + cagri(s, onceki) - cagri(s, son), 0);
console.log(`\nyayilmayi beklemeden iptal: ${dC} cagri kurtariyor, ${kesilen(son)} mesru istegi ` +
  `kesiyor (kurtarilan ${(dC / kesilen(son)).toFixed(1)} cagri basina 1 kesilen istek)`);
console.log(`surekli depo taramasinin kazanci 0: iki sirrin kanali zaten depo ve tespit 20 dk, ` +
  `diger dortunun sizintisi depoya hic dusmuyor`);

const yz2 = gen([18, 16, 9, 11, 27]);
console.log(`\n${yz2(["sir", "sizinti kanali", "tespit", "cagri", "daha erken kapatma"])}`);
const ERKEN = { depo: ["yapi", "hat sir taramasi"], gunluk: ["kod", "gunlukte maskeleme"],
  "istemci-paketi": ["yapi", "paket sir taramasi"], "ucuncu-taraf": ["yok", "-"] };
for (const s of AD)
  console.log(yz2([s.split("/")[1], SIR[s].kanal, asama(s).tespit, cagri(s),
    `${ERKEN[SIR[s].kanal][0]}: ${ERKEN[SIR[s].kanal][1]}`]));
const kapanir = AD.filter((s) => ERKEN[SIR[s].kanal][0] !== "yok");
console.log(`\nsizinti kanali daha erken kapatilabilen sir: ${kapanir.length} / ${AD.length}; ` +
  `bu kanallarin tespit gecikmesi toplam ` +
  `${kapanir.reduce((t, s) => t + asama(s).tespit, 0)} dk`);
const en = AD.reduce((x, s) => asama(s).tespit > asama(x).tespit ? s : x);
console.log(`tek kalemde en buyuk pay: ${en} — ${asama(en).tespit} dk tespit gecikmesi ve ` +
  `${Math.round(SIR[en].cagri * asama(en).tespit / 1440)} cagri, tamami yapi asamasindan geliyor`);
```

```
onlem                          toplam dk     kazanc    gecen cagri   kesilen istek
bugun                               8315          0         224171               0
+ sahiplik kaydi                    7975        340         221538               0
+ onceden uretilmis yedek           7510        805         207648               0
+ surekli depo taramasi             7510        805         207648               0
+ yayilmayi beklemeden iptal        3610       4705          56714           68503

yayilmayi beklemeden iptal: 150934 cagri kurtariyor, 68503 mesru istegi kesiyor (kurtarilan 2.2 cagri basina 1 kesilen istek)
surekli depo taramasinin kazanci 0: iki sirrin kanali zaten depo ve tespit 20 dk, diger dortunun sizintisi depoya hic dusmuyor

sir                 sizinti kanali   tespit      cagri         daha erken kapatma
onbellek                      depo       20      27500     yapi: hat sir taramasi
oturum-imzalama             gunluk       90     141875    kod: gunlukte maskeleme
belge-imzalama                depo       20       1485     yapi: hat sir taramasi
odeme-gecidi          ucuncu-taraf      240       1511                     yok: -
eposta-gecidi       istemci-paketi     2880      43271   yapi: paket sir taramasi
kisa-mesaj-gecidi           gunluk       90       8529    kod: gunlukte maskeleme

sizinti kanali daha erken kapatilabilen sir: 5 / 6; bu kanallarin tespit gecikmesi toplam 3100 dk
tek kalemde en buyuk pay: dis/eposta-gecidi — 2880 dk tespit gecikmesi ve 26800 cagri, tamami yapi asamasindan geliyor
```

İlk üç satır müdahale yordamına yazılan iki maddenin karşılığını veriyor. Her sır kaydına sahibini
yazmak üç yüz kırk dakika kazandırıyor; her sır için önceden bir yedek değer üretip hazır tutmak
dört yüz altmış beş dakika daha. İkisi birlikte sekiz bin üç yüz on beş dakikalık akışı yedi bin
beş yüz ona indiriyor — yüzde on. İkisi de ucuzdur ve sızıntı olmadan önce yazılır; ama toplam
kazanç akışın onda biridir.

Dördüncü satır bu kursun aradığı türden bir sonuçtur: **kazancı sıfır olan önlem.** Sürekli depo
taraması müdahale süresini bir dakika bile kısaltmıyor. Nedeni alt tabloda yazılı: altı sızıntının
yalnız ikisinin kanalı kod deposudur ve o ikisinde tespit zaten yirmi dakikadır. Diğer dördü depoya
hiç düşmüyor. Tarama gücünü artırmak, taramanın hiç bakmadığı yerlerdeki sızıntıyı görünür kılmaz;
bir savunmanın kapsadığı kalem kümesi sayılmadan yapılan her iyileştirme bu satırı üretir.

Beşinci satır asıl kararı içeriyor. Yeni değerin yayılmasını beklemeden eski değeri iptal etmek
akışı yedi bin beş yüz ondan üç bin altı yüz ona indiriyor ve geçen çağrıyı iki yüz yedi binden
elli altı bine düşürüyor — yüz elli bin dokuz yüz otuz dört çağrı kurtarılıyor. Karşılığında altmış
sekiz bin beş yüz üç meşru istek kesiliyor: kurtarılan her iki virgül iki çağrı için bir meşru
istek. Bu, sızıntı müdahalesinin gerçek kararıdır ve bir yordam maddesiyle çözülemez, çünkü doğru
cevap sırra göre değişir: ödeme geçidi anahtarında yayılmayı beklememek makul olabilir, oturum
imzalama anahtarında altmış bin isteği kesmek anlamına gelir.

Alt tablonun son sütunu kursun ekseni. Altı sızıntı kanalının beşi daha erken bir aşamada
kapatılabilir ve o beş kanalın tespit gecikmesi toplam üç bin yüz dakikadır. En büyük tek pay
e-posta geçidi anahtarındadır: saha uygulamasının istemci paketine gömülü olduğu için sızıntı
ancak dış ihbarla, iki gün sonra fark ediliyor ve o iki günde anahtardan yirmi altı bin sekiz yüz
çağrı geçiyor. Bu kalemin müdahale tarafında yapılacak hiçbir şeyi yoktur; anahtar paketin içine
yapı aşamasında girdi ve orada bir sır taramasıyla hiç girmemiş olurdu. Günlük dosyasına düşen iki
anahtar için de aynısı geçerli, bir aşama daha erken: günlük yazımında maskeleme bir kod kararıdır.

Geriye kalan tek kalem ödeme geçidi anahtarıdır. Sızıntı üçüncü tarafta oldu; ne yapı taraması ne
kod maskelemesi görürdü. Bu kalem için iptal akışı gerçekten tek yoldur — altı kalemden biri.

#### Özet

- İptal akışı beş aşamadır: fark etme, teyit, sahibini bulma, yeni değeri üretme, yayılma. Kalan
  altı statik sırda toplam 8.315 dakika, sır başına ortalama 1.386 dakika (23,1 saat), en kötü
  kalemde 4.650 dakika.
- Süreyi belirleyen şey müdahale hızı değil, tespit ve yayılma sütunlarıdır: teyit her satırda 30
  dakika iken tespit 20 ile 2.880 arasında, yayılma 60 ile 1.440 arasında değişiyor.
- İptale kadar sırlardan 224.171 çağrı geçiyor ve sıralama süre sıralamasıyla aynı değil: en uzun
  akış e-posta geçidinde (4.650 dk) ama en çok çağrı oturum imzalamada (141.875).
- Sahiplik kaydı 340, önceden üretilmiş yedek 465 dakika kazandırıyor — toplamın yüzde onu. Sürekli
  depo taramasının kazancı sıfırdır: altı sızıntının yalnız ikisi depoya düşüyor ve o ikisinde
  tespit zaten 20 dakika.
- Yayılmayı beklemeden iptal 150.934 çağrıyı kurtarıyor ve 68.503 meşru isteği kesiyor: kurtarılan
  her 2,2 çağrı için bir kesilen istek. Doğru cevap sırra göre değişir, yordama yazılamaz.
- Altı sızıntı kanalının beşi daha erken bir aşamada kapanabilirdi (toplam 3.100 dakika tespit
  gecikmesi); en büyük tek pay istemci paketine gömülü anahtardır — 2.880 dakika ve 26.800 çağrı,
  tamamı yapı aşamasından.

#### Sonraki Adım

Bu konu sırların ömrünü ölçtü ve kısalttı: erişim matrisi yetmiş dokuz kalemden otuz bire indi, on
altı kalemde açık pencere iki bin kat daraldı, yirmi kalem iş yükü kimliğiyle tamamen ortadan
kalktı ve kalan altı sır için iptal akışı dakika dakika yazıldı. Sırların artık bir sahibi, bir
ömrü, bir döndürme takvimi ve bir sızıntı yordamı var.

Bütün bunların altında bir varsayım duruyor ve o varsayıma hiç dokunulmadı. Bu konuda ölçülen her
şey bir servisin **kendini kanıtlamasıyla** ilgiliydi: doğru kimlik bilgisini taşıyan çağrı
geçiyor, taşımayan geçmiyor. Ama bir çağrı kimlik bilgisini taşıyorsa ne oluyor. Saha uygulama
arayüzü fatura servisini çağırdığında, fatura servisi o çağrının **fatura verisini okumaya yetkili
olup olmadığını** hiç sormuyor; çağrının bir yerden geldiğini görüyor ve karşılıyor. Sır doğru
yönetilse bile bu böyle kalırsa, tek bir servisin ele geçmesi ötekilere açılan bir kapıdır: dokuz
servisin arasındaki her güven ilişkisi, bir servisten diğerine geçilebilecek bir yoldur. Sonraki
konu o yolları sayar — kimlik doğrulaması olmayan servis çifti kaç, karşılıklı doğrulama bunların
kaçını kapatıyor ve kapanmayanlar hangi aşamada kapatılabilirdi.

## Altyapı Duruşu

Uygulamanın altında duran katmanın çalışma zamanındaki duruşu sayıyla ölçülür: servisler arası kimlik doğrulamanın kapattığı yanal hareket çifti ve sertifika yönetiminin getirdiği kalem, konteyner çalışma zamanında taban çizgisinden sapan süreç ile yanlış pozitif ve tespit gecikmesi, kabul denetleyicisi kurallarının reddettiği meşru dağıtım ve zorlama kipine geçişte etkilenen ekip sayısı, sürekli yapılandırma denetiminde uygulama ekibine dönen bulgu ile sahipsiz bulgu, yeniden inşa temelli güncellemenin yama gecikmesini kaç güne indirdiği ve karşılığında getirdiği kesinti.

### Ağ Bölütleme ve Servis Sıfır Güveni

Source: https://academia.sh/tr/kurslar/calisma-zamani-guvenligi/ag-bolutleme-ve-servis-sifir-guveni

Yanal hareket servis çifti cinsinden sayılır: dokuz servisin 72 yönlü çiftinden 52'si ağ politikasından geçiyor, yalnız 17'si bir meşru çağrıya karşılık geliyor. Tek yönlü taşıma doğrulaması ve izin listesiz karşılıklı doğrulama sıfır çift kapatıyor; çağıran başına izin listesi 35 çift kapatıyor ve ortalama erişimi 7,1'den 4,1'e indiriyor, ama kenar servisten sekizin sekizi hâlâ erişilebilir ve sır deposu en fazla iki sıçrama uzakta. Bedeli 31 sertifika, kısa ömürde yılda 11.315 yenileme ve servis başına düşen 3,8 meşru çift.

Önceki konu sırların ömrünü kısalttı ve sızıntı sonrası iptal akışını yazdı. Bütün o ölçüm tek bir
varsayıma yaslanıyordu: sırrı okuyan taraf, sırrı okuması gereken taraftır. Üretim ortamında bu
varsayımı sınayan bir şey yok. Servisler birbirine sorgusuz güveniyorsa, tek bir servisin ele
geçmesi ötekilere açılan bir kapıdır ve sırrın ömrünü kısaltmak o kapıyı kapatmaz — yalnızca
kapıdan geçenin elindeki anahtarın ne kadar süre işe yarayacağını sınırlar.

Bu konu uygulamanın altındaki katmanı ölçer ve ilk ders **yanal hareketi** sayar. Ölçü birimi
buradan sonra **servis çiftidir**: kaç yönlü çift var, kaçı bir meşru çağrıya karşılık geliyor,
hangi doğrulama düzeni kaçını kapatıyor. Ağ bölütlemesinin kural sayısı, etiket genişliği ve
matrisin büyüme hızı **Konteyner Orkestrasyonu** ve **Ağ Güvenliği** kurslarında ölçüldü; burada
tekrarlanmıyor, **girdi** olarak alınıyor.

- **AD1.** Ortam kurgusal bölgesel ölçüm ağının üretim ortamıdır: dokuz servis, bir sır deposu, bir
  küme. Gerçek bir küme koşturulmuyor; ölçülen şey `node` ile kurulan bir modeldir.
- **AD2.** Çağrı yönlüdür: `a->b` ile `b->a` ayrı çiftlerdir. Uç, kapı numarası ve protokol
  modellenmiyor; bunlar matrisi büyütür, sonucun yönünü değiştirmez.
- **AD3.** Meşru çağrı kümesi on yedidir ve çağrı sözleşmesinden okundu. Gerçekte bu liste ancak
  uzun bir izleme penceresiyle ya da tasarım belgesinden çıkarılır.
- **AD4.** Ağ politikası etiket düzeyinde yazılmıştır ve **verilmiş kabul edilir**; beş kuralı ve
  dört etiketi vardır.
- **AD5.** Ele geçme modeldir: bir serviste süreç denetimi saldırganın eline geçer ve o servisin
  açık olduğu her çift kullanılabilir hâle gelir. Hiçbir istismar adımı, çağrı dizisi ya da kaçış
  yöntemi yazılmaz.
- **AD6.** Sır deposu çağrı yapmayan bir düğümdür; dört servis onu meşru olarak okur, ağ politikası
  dokuzunun da ulaşmasına izin verir.

#### Çift Kümesi ve Dört Düzen

```js
// servis.mjs — dokuz servis, cift kumesi ve dogrulama duzenleri. MODELDIR, gercek ag degil.
const bol = (s) => s.trim().replace(/\s{2,}/g, "\n").split("\n").map((l) => l.trim().split("|"));

// Servis: ad|bolge etiketleri (bolutleme onceki kurslarda olculdu, burada GIRDIDIR).
export const SERVIS = Object.fromEntries(bol(`
  portal-onu|kenar             abone-servisi|uygulama
  faturalama|uygulama          is-emri|uygulama,toplayici-istemcisi
  bildirim|uygulama            rapor|uygulama,toplayici-istemcisi
  sayac-toplama|toplama        dogrulayici|toplama
  saha-senkron|toplama`).map(([a, e]) => [a, e.split(",")]));

// Mesru cagri cifti: cagiran|cagrilan. On yedi cift, cagri sozlesmesinden.
export const MESRU = bol(`
  portal-onu|abone-servisi     portal-onu|faturalama
  portal-onu|is-emri           portal-onu|rapor
  abone-servisi|bildirim       sayac-toplama|dogrulayici
  dogrulayici|faturalama       dogrulayici|sayac-toplama
  faturalama|abone-servisi     faturalama|bildirim
  is-emri|saha-senkron         is-emri|bildirim
  saha-senkron|sayac-toplama   saha-senkron|is-emri
  rapor|faturalama             rapor|sayac-toplama
  bildirim|abone-servisi`).map(([a, b]) => `${a}->${b}`);

// Ag politikasi etiket duzeyinde yazilmis: hedef etiketi <- kaynak etiketi.
export const AG_KURAL = [["uygulama", "kenar"], ["uygulama", "uygulama"],
  ["uygulama", "toplama"], ["toplama", "toplama"], ["toplama", "toplayici-istemcisi"]];

export const ADLAR = Object.keys(SERVIS);
export const tumCift = () => ADLAR.flatMap((a) => ADLAR.filter((b) => b !== a).map((b) => `${a}->${b}`));

export function agAcik(s = SERVIS) {
  const acik = new Set(), ad = Object.keys(s);
  for (const [h, k] of AG_KURAL)
    for (const hedef of ad) if (s[hedef].includes(h))
      for (const kaynak of ad) if (kaynak !== hedef && s[kaynak].includes(k))
        acik.add(`${kaynak}->${hedef}`);
  return acik;
}

// Duzen: cagrilan servis cagiranin kim oldugunu ne kadar dogruluyor.
// yok      : cagiran kimligi hic dogrulanmaz
// tek-yonlu: yalniz cagrilan kendini kanitlar, cagiran kimligi yine dogrulanmaz
// karsilikli: cagiran da kanitlar, ama ic yetkiliden gelen her kimlik kabul edilir
// yetkili  : karsilikli dogrulama + cagiran basina izin listesi
export function cift(duzen, ag = agAcik()) {
  if (duzen === "yetkili") return new Set(MESRU.filter((c) => ag.has(c)));
  return new Set(ag);
}

// Bir servis ele gectiginde ulasilan servis kumesi ve sicrama sayilari (enine arama).
export function yayilim(baslangic, kenar) {
  const uzaklik = { [baslangic]: 0 }, kuyruk = [baslangic];
  while (kuyruk.length) {
    const n = kuyruk.shift();
    for (const c of kenar) {
      const [k, h] = c.split("->");
      if (k === n && !(h in uzaklik)) { uzaklik[h] = uzaklik[n] + 1; kuyruk.push(h); }
    }
  }
  return uzaklik;
}

export const gen = (B) => (h) => h.map((v, j) => j ? String(v).padStart(B[j]) : String(v).padEnd(B[0])).join("");

// Sir deposu ayri bir dugumdur ve cagri yapmaz. Dort servis onu mesru olarak okur;
// ag politikasi dokuzunun da ulasmasina izin verir (depo etiketi uygulama ve toplama'ya acik).
export const SIR_OKUR = new Set(["abone-servisi", "faturalama", "sayac-toplama", "saha-senkron"]);

export function sirSicrama(baslangic, kenar, yetkili) {
  const u = yayilim(baslangic, kenar);
  const erisebilen = yetkili ? [...SIR_OKUR] : ADLAR;
  const d = erisebilen.filter((s) => s in u).map((s) => u[s] + 1);
  return d.length ? Math.min(...d) : Infinity;
}
```

`cift` işlevinin gövdesi kısa çünkü ölçülen şey kısa: dört düzenden üçü aynı kümeyi döndürür. Bu bir
eksiklik değil, dersin sonucudur.

#### Kapanan Çift

```js
// kosum1.mjs — dort dogrulama duzeni ayni cift kumesinde kosturulur
import { ADLAR, MESRU, tumCift, agAcik, cift, yayilim, sirSicrama, gen } from './servis.mjs';

const ag = agAcik();
console.log(`${ADLAR.length} servis -> ${tumCift().length} yonlu cift; ag politikasi ${ag.size} cifte izin veriyor`);
console.log(`cagri sozlesmesindeki mesru cift ${MESRU.length}, hepsi ag politikasindan geciyor: ` +
  `${MESRU.every((c) => ag.has(c)) ? 'evet' : 'hayir'}`);
console.log(`ag politikasindan gecen ama hicbir mesru cagriya karsilik gelmeyen cift: ${ag.size - MESRU.length}\n`);

const yz = gen([28, 11, 10, 15, 17, 15]);
console.log(yz(['duzen', 'acik cift', 'kapanan', 'ort. erisilen', 'en dusuk erisim', 'sir sicramasi']));
for (const [ad, duzen] of [['dogrulama yok', 'yok'], ['tek yonlu tasima', 'tek-yonlu'],
  ['karsilikli, izin listesiz', 'karsilikli'], ['karsilikli + izin listesi', 'yetkili']]) {
  const k = cift(duzen, ag), yetkili = duzen === 'yetkili';
  const ulasan = ADLAR.map((s) => Object.keys(yayilim(s, k)).length - 1);
  const sic = ADLAR.map((s) => sirSicrama(s, k, yetkili));
  console.log(yz([ad, k.size, ag.size - k.size, (ulasan.reduce((a, b) => a + b, 0) / ADLAR.length).toFixed(1),
    Math.min(...ulasan), `${Math.min(...sic)}-${Math.max(...sic)}`]));
}

const yetkiliKenar = cift('yetkili', ag);
console.log('\nizin listesi acikken servis basina yayilim:');
const ys = gen([16, 11, 9, 16]);
console.log(ys(['ele gecen servis', 'ulasilan', 'once', 'sir sicramasi']));
for (const s of ADLAR) {
  const sonra = Object.keys(yayilim(s, yetkiliKenar)).length - 1;
  const once = Object.keys(yayilim(s, ag)).length - 1;
  console.log(ys([s, sonra, once, `${sirSicrama(s, ag, false)} -> ${sirSicrama(s, yetkiliKenar, true)}`]));
}
```

```
9 servis -> 72 yonlu cift; ag politikasi 52 cifte izin veriyor
cagri sozlesmesindeki mesru cift 17, hepsi ag politikasindan geciyor: evet
ag politikasindan gecen ama hicbir mesru cagriya karsilik gelmeyen cift: 35

duzen                         acik cift   kapanan  ort. erisilen  en dusuk erisim  sir sicramasi
dogrulama yok                        52         0            7.1                7            1-1
tek yonlu tasima                     52         0            7.1                7            1-1
karsilikli, izin listesiz            52         0            7.1                7            1-1
karsilikli + izin listesi            17        35            4.1                1            1-2

izin listesi acikken servis basina yayilim:
ele gecen servis   ulasilan     once   sir sicramasi
portal-onu                8        8          1 -> 2
abone-servisi             1        7          1 -> 1
faturalama                2        7          1 -> 1
is-emri                   6        7          1 -> 2
bildirim                  1        7          1 -> 2
rapor                     5        7          1 -> 2
sayac-toplama             4        7          1 -> 1
dogrulayici               4        7          1 -> 2
saha-senkron              6        7          1 -> 1
```

İlk üç satır aynı sayıları taşıyor ve tablonun okunması gereken yeri burasıdır. **Tek yönlü taşıma
doğrulaması sıfır çift kapatıyor.** Çağrılan taraf kendini kanıtlar, çağıran hiçbir şey kanıtlamaz;
kimin aradığı bilinmediği için hiçbir çift reddedilemez. İkinci satırla üçüncü satır arasındaki fark
daha keskin: **karşılıklı doğrulama tek başına da sıfır çift kapatıyor.** Her servis geçerli bir iş
yükü kimliği taşır, dolayısıyla ele geçmiş bir servis de geçerli bir kimlik sunar. Doğrulama
sorusunu "geçerli bir iç kimlik mi" diye sorarsanız cevap her zaman evettir.

Kapatan tek satır dördüncüsü: çağıran başına izin listesi. Elli iki çiftten otuz beşi kapanıyor ve
ortalama erişilen servis 7,1'den 4,1'e iniyor. Bu, otuz beş çiftin **hiçbir meşru çağrıya karşılık
gelmediği** için ücretsiz sanılan bir kapanma değil; listenin kendisi on yedi satırdır ve o on yedi
satırı birinin yazması gerekir.

#### Kapanmayan Yol

Alt tablo kazancın nereye dağıldığını gösteriyor ve dağılım eşit değil. Bildirim servisi ele
geçtiğinde erişilen servis yediden **bire** iniyor; abone servisi de öyle. Bunlar çağrı çizgesinin
yapraklarıdır ve izin listesi onları gerçekten yalıtıyor. Portal önü ele geçtiğinde ise sayı
sekizden **sekize** iniyor: hiç değişmiyor. Kenar servis dört meşru çağrı yapar, o dördü ötekileri
çağırır ve zincir bütün kümeyi kapsar. İzin listesi yalnız çağrı çizgesinin **olmayan** kenarlarını
kapatır; var olan kenarlar üzerinden yürüyen bir yayılımı durdurmaz.

Sır sıçraması sütunu aynı sınırı sayıya bağlıyor. Doğrulama yokken sır deposu her servisten **bir**
sıçrama uzaktadır. İzin listesi açıkken dört servis için hâlâ bir sıçrama — onlar deposu meşru
olarak okuyor — kalan beşi için iki sıçrama. Yani en yüksek değer birden ikiye çıkıyor. Yanal
hareket kapanmıyor, **uzuyor**: saldırganın önce bir ara servisi kullanması gerekiyor ve o ara
servisin kullanımı bir kayıt satırı üretiyor. Kazanç budur ve bunun adını doğru koymak gerekir —
otuz beş çift kapandı, sır deposuna giden yol kapanmadı.

#### Doğrulamanın Getirdiği Kalem

```js
// kosum2.mjs — izin listesinin ve sertifika yonetiminin getirdigi kalem
import { ADLAR, MESRU, SERVIS, agAcik, gen } from './servis.mjs';

const KOPYA = { 'portal-onu': 6, 'abone-servisi': 4, 'faturalama': 3, 'is-emri': 3, 'bildirim': 2,
  'rapor': 2, 'sayac-toplama': 6, 'dogrulayici': 3, 'saha-senkron': 2 };
const ornek = Object.values(KOPYA).reduce((a, b) => a + b, 0);
console.log(`${ADLAR.length} servis, ${ornek} kopya; her kopya bir is yuku kimligi tasir`);
const yz = gen([18, 11, 17, 13, 14]);
console.log('\n' + yz(['sertifika omru', 'sertifika', 'yillik yenileme', 'elle kalem', 'acik pencere']));
for (const [ad, gun, elle] of [['90 gun', 90, ornek], ['24 saat', 1, 0], ['1 saat', 1 / 24, 0]])
  console.log(yz([ad, ornek, Math.round((365 / gun) * ornek), elle, `${(gun * 24).toFixed(0)} saat`]));
console.log(`izin listesi ${MESRU.length} satir; ag politikasi 5 kural ve ` +
  `${new Set(Object.values(SERVIS).flat()).size} etiket; kok guven cipasi 1 kalem, yilda 1 elle donduruluyor`);

console.log('\nbir servisin sertifikasi yenilenemezse dusen mesru cift:');
const yd = gen([18, 10, 11, 9]);
console.log(yd(['servis', 'cagiran', 'cagrilan', 'toplam']));
const dusen = ADLAR.map((s) => ({ s, c: MESRU.filter((x) => x.startsWith(`${s}->`)).length,
  h: MESRU.filter((x) => x.endsWith(`->${s}`)).length })).sort((a, b) => b.c + b.h - a.c - a.h);
for (const d of dusen.slice(0, 3)) console.log(yd([d.s, d.c, d.h, d.c + d.h]));
const son = dusen[dusen.length - 1];
console.log(`ortalama ${(dusen.reduce((a, b) => a + b.c + b.h, 0) / ADLAR.length).toFixed(1)} cift, ` +
  `en dusuk ${son.c + son.h} cift (${son.s})`);

const YENI = ['is-emri->arsiv', 'arsiv->faturalama'];
const once = agAcik().size, sonra = agAcik({ ...SERVIS, arsiv: ['uygulama'] }).size;
console.log('\nonuncu servis (arsiv, 2 kopya, uygulama etiketi) eklendiginde:');
console.log(`  ag kurali 5 -> 5, ag politikasinin actigi cift ${once} -> ${sonra}`);
console.log(`  izin listesi ${MESRU.length} -> ${MESRU.length + YENI.length} satir, sertifika ${ornek} -> ${ornek + 2}`);
console.log(`  yeni servisin gereksiz acik cifti: ag duzeninde ${sonra - once - YENI.length}, izin listesinde 0`);
```

```
9 servis, 31 kopya; her kopya bir is yuku kimligi tasir

sertifika omru      sertifika  yillik yenileme   elle kalem  acik pencere
90 gun                     31              126           31     2160 saat
24 saat                    31            11315            0       24 saat
1 saat                     31           271560            0        1 saat
izin listesi 17 satir; ag politikasi 5 kural ve 4 etiket; kok guven cipasi 1 kalem, yilda 1 elle donduruluyor

bir servisin sertifikasi yenilenemezse dusen mesru cift:
servis               cagiran   cagrilan   toplam
faturalama                 2          3        5
portal-onu                 4          0        4
abone-servisi              1          3        4
ortalama 3.8 cift, en dusuk 3 cift (saha-senkron)

onuncu servis (arsiv, 2 kopya, uygulama etiketi) eklendiginde:
  ag kurali 5 -> 5, ag politikasinin actigi cift 52 -> 66
  izin listesi 17 -> 19 satir, sertifika 31 -> 33
  yeni servisin gereksiz acik cifti: ag duzeninde 12, izin listesinde 0
```

Doksan günlük sertifika ömrü yılda yüz yirmi altı yenileme üretir ve bunlar elle yapılırsa otuz bir
kalem takvime girer. Ömrü yirmi dört saate indirmek elle kalemi sıfırlar çünkü bu sayıda yenileme
elle yapılamaz; karşılığında yıllık yenileme on bir bine çıkar ve bir dağıtım düzeneği zorunlu hâle
gelir. Bir saatlik ömür aynı düzenek üzerinde iki yüz yetmiş bin yenileme ister ve açık pencereyi
yirmi dört saatten bir saate indirir. Üç satır aynı ayarın üç değeridir; hangisinin seçileceği
kimliğin ne kadar süre kötüye kullanılabileceğine bakılarak belirlenir.

Orta tablo bu düzeneğin arıza yüzünü sayıyor. Faturalama servisinin sertifikası yenilenemezse beş
meşru çift düşer — iki çağrısı ve üç çağrılışı. Ortalama üç virgül sekiz çifttir ve en düşük değer
bile üçtür. Doğrulama açıkken bir yenileme arızası bir güvenlik olayı gibi görünmez; bir kesinti
gibi görünür ve nedeni ilk bakışta uygulama katmanında aranır. Kapatmanın meşru işe bedeli tam
olarak budur: kapatılan otuz beş çiftin karşılığında, kapatma düzeneğinin kendisi üç ile beş arası
meşru çifti düşürebilen yeni bir arıza kaynağıdır.

Son blok onuncu servisi ekliyor. Ağ politikası hiç değişmiyor — beş kural, beş kural — ama açtığı
çift elli ikiden altmış altıya çıkıyor: yeni servisin ihtiyacı iki çiftken on iki gereksiz çift
kendiliğinden açılıyor. İzin listesi düzeninde iki satır yazılır ve gereksiz açık çift sıfır kalır.
Etiketle yazılan politika büyümeye emek harcamadan uyum sağlar ve açıklığı biriktirir; çağıran
başına liste her serviste iki satır ister ve açıklığı biriktirmez.

#### Daha Erken Nerede Kapanırdı

İzin listesindeki on yedi satır bir çalışma zamanı yapılandırması gibi görünüyor ama içeriği
çalışma zamanına ait değil. O liste, hangi servisin hangi servisi çağırdığının listesidir ve bu
bilgi **tasarım aşamasında** doğar. Çağrı sözleşmesi yazıldığı anda on yedi çift bellidir; otuz beş
gereksiz çift, sözleşmenin hiçbir yere yazılmamış olmasından doğar.

Aynı kalemi iki aşamada kapatmanın fiyatı arasındaki fark tabloda okunuyor. Tasarım aşamasında
kapatmak bir belgedir ve bir gözden geçirmedir. Çalışma zamanında kapatmak on yedi politika satırı,
otuz bir sertifika, yılda on bir bin yenileme, bir kök güven çıpası, bir döndürme takvimi ve servis
başına üç ile beş arası meşru çifti düşürebilen bir arıza kaynağıdır. Çalışma zamanı katmanı bunu
yapmalıdır, çünkü sözleşmenin yazılmış olması onun uygulandığı anlamına gelmez — ama katmanın
kurulmasının nedeni sözleşmenin yokluğuysa, sayılan bedelin tamamı daha ucuza kapatılabilirdi.

#### Özet

- Dokuz servis 72 yönlü çift üretir; ağ politikası 52'sine izin verir, meşru çağrı çifti 17'dir ve
  35 çift hiçbir çağrıya karşılık gelmeden açık durur.
- Tek yönlü taşıma doğrulaması ve izin listesiz karşılıklı doğrulama **sıfır çift** kapatır; ele
  geçmiş bir servis de geçerli bir iç kimlik sunar.
- Çağıran başına izin listesi 35 çift kapatır ve ortalama erişilen servisi 7,1'den 4,1'e indirir;
  yaprak servislerde erişim yediden bire iner, kenar serviste sekizden sekize — hiç değişmez.
- Sır deposuna sıçrama sayısı 1'den en fazla 2'ye çıkar: yol kapanmaz, uzar ve ara servisin
  kullanımı bir kayıt satırı üretir.
- Bedel 31 sertifika, doksan günlük ömürde yılda 126 yenileme ve 31 elle kalem, yirmi dört saatlik
  ömürde 11.315 yenileme ve bir dağıtım düzeneğidir; bir yenilemenin düşmesi ortalama 3,8 meşru
  çifti keser.
- Onuncu servis eklendiğinde etiket politikası 12 gereksiz çift açar, izin listesi 2 satırla sıfır
  açar; listenin içeriği tasarım aşamasında doğan çağrı sözleşmesidir.

#### Sonraki Adım

Bu dersin bütün ölçümü servis sınırında durdu: kim kimi çağırabiliyor, çağrı reddedildiğinde ne
oluyor. Sınırın **içi** hiç açılmadı. İzin listesi eksiksiz yazılmış olsa bile, bir servisin kendi
kapsülünün içinde açılan bir kabuk, beklenmedik bir ikili ya da alışılmadık bir dosya erişimi
hiçbir çifti ihlal etmez — çünkü hiçbir çağrı yapmaz. Sonraki ders bu tarafı ölçer: dokuz servisin
süreç davranışı için bir taban çizgisi çıkarılır, bir haftalık kayıt üzerinde taban çizgisinden
sapan süreç sayılır ve sapmaların kaçının gerçek bir anormallik, kaçının meşru bir değişiklik
olduğu ayrılır. Tespitin kaç saniye gecikmeyle geldiği de aynı tabloda yazılır.

### Konteyner Çalışma Zamanı Tespiti

Source: https://academia.sh/tr/kurslar/calisma-zamani-guvenligi/konteyner-calisma-zamani-tespiti

Bir haftalık süreç başlatma kaydında dört taban çizgisi aynı kümede koşturulur: görüntü envanteri 21 anormal olayın 5'ini yakalar ve 16'sını kaçırır, yedi günlük öğrenme 12'sini yakalar ama 9 meşru olayı yanlış pozitife çevirir, izin listesi çift olarak yazılınca yanlış pozitif 4'e iner, ikili olarak yazılınca yakalanan 6'ya düşer. Tespit gecikmesi akış kipinde 17, toplu kipte 47 saniyedir ve yakalanan 12 olayın yalnız 8'i ile 6'sı süreç hâlâ koşarken gelir; hattın taşıdığı 68.746 olayın yüzde 90,9'u hiçbir tabanda sapmaz ve görüntüyü 342 ikiliden 41 çifte daraltmak aynı üç sayıyı öğrenme penceresi kurmadan verir.

Önceki ders servis sınırında durdu: çağıran başına izin listesi otuz beş çift kapattı ve sır
deposuna giden yol kapanmadan uzadı. Sınırın **içinde** ne olduğu ise hiç sorulmadı. Bir servisin
kendi kapsülü içinde açılan bir kabuk hiçbir çağrı çiftini ihlal etmez: ağ politikası da karşılıklı
doğrulama da onu görmez, çünkü ortada bir çağrı yoktur.

Bu ders o tarafı ölçer ve ölçü birimi **süreç başlatmadır**: bir haftalık kayıtta kaç süreç başladı,
kaçı taban çizgisinden sapıyor, sapanların kaçı gerçek bir anormallik ve kaçı meşru bir değişiklik.
Konteyner çalıştırma seçenekleri — düşürülen yetenek, salt okunur kök, kullanıcı kimliği —
**Konteynerler** kursunda ölçüldü ve burada girdi olarak alınıyor. Soru başkadır: koşan konteynerin
**davranışına** bakan bir düzenek kurulduğunda üç sayı ne oluyor.

- **AD7.** Ortam öncekiyle aynıdır: dokuz servis, otuz bir kopya, bir küme. Gerçek bir konteyner
  koşturulmuyor; ölçülen şey `node` ile kurulan bir modeldir.
- **AD8.** Kayıt yalnız süreç başlatma olaylarından oluşur; dosya erişimi ve ağ bağlantısı
  modellenmiyor. Süreç sınıfı ve haftalık sayısı sabittir, aynı sınıftaki her olay aynı ikiliyi ve
  aynı ömrü taşır; gerçekte ömür bir dağılımdır.
- **AD9.** Bir olayın gerçek sınıfı modelde bilinir. Üretimde bu sınıf ancak inceleme sonrası
  bilinir; modelde bilindiği varsayılıyor ki yanlış pozitif sayılabilsin.
- **AD10.** Anormal sınıflar **model** olarak yazıldı: hangi ikilinin hangi serviste beklenmediği ve
  sürecin kaç saniye koştuğu. Hiçbir istismar adımı ya da kaçırma yöntemi yazılmaz.
- **AD11.** Öğrenme penceresi yedi gündür ve o pencereye anormal davranış karışmadığı varsayılır.
  Tespit gecikmesi hattın aşama sürelerinin toplamıdır; duvar saati ölçülmüyor.

#### Kayıt ve Dört Taban Çizgisi

```js
// surec.mjs — bir haftalik surec baslatma kaydi ve dort taban cizgisi. MODELDIR, gercek kume degil.
export const KOPYA = { 'portal-onu': 6, 'abone-servisi': 4, 'faturalama': 3, 'is-emri': 3,
  'bildirim': 2, 'rapor': 2, 'sayac-toplama': 6, 'dogrulayici': 3, 'saha-senkron': 2 };
// Servis goruntusunde bulunan ikili sayisi (temel goruntu + uygulama katmani).
export const GORUNTU_IKILI = { 'portal-onu': 34, 'abone-servisi': 41, 'faturalama': 41,
  'is-emri': 38, 'bildirim': 29, 'rapor': 38, 'sayac-toplama': 44, 'dogrulayici': 29,
  'saha-senkron': 48 };
export const SERVIS = Object.keys(KOPYA);
export const kapsam = (s) => (s[1] === '*' ? SERVIS : [s[1]]);

// [ad, servis ('*' = dokuzunun hepsi), ikili, haftalik olay, gercek sinif, goruntude mi,
//  ogrenme penceresinde goruldu mu, surec omru (sn), daha erken kapatma asamasi]
export const SINIF = [
  ['uygulama girdi noktasi', '*', 'app', 620, 'mesru', 1, 1, 0, '-'],
  ['saglik yoklamasi', '*', 'saglik', 62496, 'mesru', 1, 1, 0.4, '-'],
  ['gunluk donusturucu', '*', 'gunluk', 5208, 'mesru', 1, 1, 1.2, '-'],
  ['sertifika yenileme istemcisi', '*', 'sertifika', 217, 'mesru', 1, 1, 2, '-'],
  ['gecelik yedek isi', 'sayac-toplama', 'yedek', 7, 'mesru', 1, 1, 340, '-'],
  ['zamanlanmis rapor uretimi', 'rapor', 'rapor-uret', 168, 'mesru', 1, 1, 26, '-'],
  ['aylik uzlastirma isi', 'faturalama', 'uzlastirma', 1, 'mesru', 1, 0, 880, '-'],
  ['ceyreklik arsiv isi', 'rapor', 'arsiv', 1, 'mesru', 1, 0, 410, '-'],
  ['operator tanilama kabugu', 'is-emri', 'kabuk', 4, 'mesru', 1, 0, 210, '-'],
  ['yeni surumun gecis adimi', 'abone-servisi', 'gecis', 3, 'mesru', 1, 0, 64, '-'],
  ['kapsul icinde kabuk acilisi', 'dogrulayici', 'kabuk', 6, 'anormal', 1, 0, 95, 'yapi'],
  ['goruntude olmayan ag araci', 'saha-senkron', 'ag-araci', 3, 'anormal', 0, 0, 12, 'yapi'],
  ['disaridan getirilen ikili', 'portal-onu', 'gecici-ikili', 2, 'anormal', 0, 0, 40, 'yok'],
  ['kisa omurlu zamanlayici kaydi', 'is-emri', 'zamanlayici', 1, 'anormal', 1, 0, 0.5, 'yok'],
  ['yorumlayici icinde calistirma', 'abone-servisi', 'app', 9, 'anormal', 1, 1, 6, 'kod'],
];

// Elle yazilan izin listesi iki bicimde: (servis, ikili) cifti ya da yalniz ikili adi.
export const CIFT_LISTE = new Set(['faturalama|uzlastirma', 'is-emri|kabuk']);
export const IKILI_LISTE = new Set(['uzlastirma', 'kabuk']);

export const TABAN = {
  'goruntu envanteri': (s) => !s[5],
  '7 gunluk ogrenme': (s) => !s[6],
  'ogrenme + cift listesi': (s) => !s[6] && !CIFT_LISTE.has(`${s[1]}|${s[2]}`),
  'ogrenme + ikili listesi': (s) => !s[6] && !IKILI_LISTE.has(s[2]),
};

export function olc(sapar) {
  let yakalanan = 0, kacan = 0, yanlis = 0, sapan = 0;
  const uyari = new Set(), gercek = new Set();
  for (const s of SINIF) {
    const d = sapar(s);
    if (d) { sapan += s[3]; uyari.add(`${s[1]}|${s[2]}`); if (s[4] === 'anormal') gercek.add(`${s[1]}|${s[2]}`); }
    if (s[4] === 'anormal') d ? (yakalanan += s[3]) : (kacan += s[3]);
    else if (d) yanlis += s[3];
  }
  return { sapan, yakalanan, kacan, yanlis, uyari: uyari.size, gercek: gercek.size };
}

export const gen = (B) => (h) => h.map((v, j) => j ? String(v).padStart(B[j]) : String(v).padEnd(B[0])).join('');
export const toplam = (f) => SINIF.filter(f).reduce((a, s) => a + s[3], 0);
```

Taban çizgisi bu modelde tek bir şeydir: hangi ikilinin hangi serviste meşru sayıldığı. Dört tanımın
farkı yalnız o listenin nereden geldiğidir — görüntüde bulunanlar, gözlemlenenler ve
gözlemlenenlerin üstüne iki farklı genişlikte yazılan izin listesi.

#### Aynı Hafta, Dört Taban

```js
// kosum1.mjs — ayni haftalik kayit, degisen tek sey taban cizgisinin nereden geldigi
import { SINIF, SERVIS, KOPYA, GORUNTU_IKILI, TABAN, olc, gen, toplam, kapsam } from './surec.mjs';

const top = (o) => Object.values(o).reduce((a, b) => a + b, 0);
const ogr = new Set(SINIF.filter((s) => s[6]).flatMap((s) => kapsam(s).map((v) => `${v}|${s[2]}`)));
console.log(`${SERVIS.length} servis, ${top(KOPYA)} kopya; bir haftada ${toplam(() => true)} surec baslatma ` +
  `(${toplam((s) => s[4] === 'mesru')} mesru / ${toplam((s) => s[4] === 'anormal')} anormal)`);
console.log(`taban genisligi: goruntu envanteri ${top(GORUNTU_IKILI)} cift, ogrenme penceresi ${ogr.size} cift\n`);

const yt = gen([26, 11, 7, 16, 7, 14]);
console.log(yt(['taban cizgisi', 'yakalanan', 'kacan', 'yanlis pozitif', 'uyari', 'gercek uyari']));
for (const [ad, sapar] of Object.entries(TABAN)) {
  const r = olc(sapar);
  console.log(yt([ad, r.yakalanan, r.kacan, r.yanlis, r.uyari, r.gercek]));
}
```

```
9 servis, 31 kopya; bir haftada 68746 surec baslatma (68725 mesru / 21 anormal)
taban genisligi: goruntu envanteri 342 cift, ogrenme penceresi 38 cift

taban cizgisi               yakalanan  kacan  yanlis pozitif  uyari  gercek uyari
goruntu envanteri                   5     16               0      2             2
7 gunluk ogrenme                   12      9               9      8             4
ogrenme + cift listesi             12      9               4      6             4
ogrenme + ikili listesi             6     15               4      5             3
```

Birinci satır tam olarak okunması gereken yerdir. Görüntü envanteri tabanı **hiç yanlış pozitif
üretmiyor** — sıfır — ve bu, gündelik gösterge tablosunda kusursuz bir katman gibi görünür. Aynı
satırda kaçan olay on altıdır, yani yirmi bir anormal olayın dörtte üçü. Nedeni dar bir tanım değil,
geniş bir tanım olmasıdır: taban çizgisi üç yüz kırk iki çifttir ve servis görüntüsünde duran her
ikili meşru sayıldığı için görüntüde zaten bulunan bir kabuğun açılması tabanı hiç ihlal etmez.
Sıfır yanlış pozitif burada bir başarı ölçüsü değil, tabanın genişliğinin işaretidir.

İkinci satır tabanı otuz sekiz çifte indiriyor ve yakalanan olay beşten on ikiye çıkıyor. Bedel aynı
satırda yazılı: dokuz meşru olay yanlış pozitife dönüşüyor ve bu dokuz olay rastgele değil, **dört
ayrı türden** geliyor. Aylık uzlaştırma ile çeyreklik arşiv işi öğrenme penceresine hiç girmedi;
operatör tanılama kabuğu bir mühendisin gerçekten yaptığı iştir; geçiş adımı bir dağıtımın normal
parçasıdır. Uyarı sütunu operatörün gördüğü sayıyı verir: sapan olaylar sekiz ayrı gruba düşer ve
dördü gerçektir, yani uyarıların yarısı incelemeden sonra kapatılacak kayıtlardır.

#### İzin Listesinin Genişliği

Üçüncü ve dördüncü satır aynı kusuru iki farklı genişlikte kapatıyor. Çift listesi `servis|ikili`
yazar, ikili listesi yalnız ikili adını; ikisi de aynı iki yanlış pozitifi kapatır ve yanlış pozitif
dokuzdan dörde iner.

Fark yakalanan sütunundadır. Çift listesinde yakalanan on iki kalır; ikili listesinde altıya düşer.
Kaybedilen altı olay, doğrulayıcı servisinde açılan kabuktur — listeye `kabuk` yazıldığı anda o
ikili **dokuz servisin dokuzunda** meşrulaşır. İki satır arasındaki fark bir sütundur ve bedeli
yakalanan olayın yarısıdır. Muafiyetin kapsadığı kümeyi saymadan yazmak, bu kursun ilk dersindeki uç
bazlı muafiyetle aynı hatadır: liste bir ayar değil, kapsamı ölçülmesi gereken bir envanterdir.

#### Gecikme ve Hattın Taşıdığı Olay

Tespit gecikmesi dört aşamanın toplamıdır: olay tamponu, gönderim penceresi, kural değerlendirme ve
bildirim. Gönderim penceresi akış kipinde sıfır, toplu kipte otuz saniyedir.

```js
// kosum2.mjs — tespit gecikmesi, hattin tasidigi olay ve tabani goruntuden daraltmak
import { SINIF, SERVIS, KOPYA, GORUNTU_IKILI, TABAN, olc, gen, toplam, kapsam } from './surec.mjs';

// Hat asamalari: olay tamponu 2 sn + gonderim penceresi 0/30 sn + degerlendirme 3 sn + bildirim 12 sn
const AKIS = 2 + 0 + 3 + 12, TOPLU = 2 + 30 + 3 + 12;
const sapar = TABAN['ogrenme + cift listesi'];
const yak = SINIF.filter((s) => s[4] === 'anormal' && sapar(s));
const yg = gen([32, 7, 8, 14, 15]);
console.log(yg(['yakalanan anormal sinif', 'olay', 'omur sn', `akis ${AKIS} sn`, `toplu ${TOPLU} sn`]));
for (const s of yak) console.log(yg([s[0], s[3], s[7], s[7] > AKIS ? 'evet' : 'hayir', s[7] > TOPLU ? 'evet' : 'hayir']));
const say = (b) => yak.filter((s) => s[7] > b).reduce((a, s) => a + s[3], 0);
const yt = yak.reduce((a, s) => a + s[3], 0);
console.log(`surec hala kosarken gelen tespit: akis ${say(AKIS)}/${yt} olay, toplu ${say(TOPLU)}/${yt} olay`);

const olay = toplam(() => true), kopya = Object.values(KOPYA).reduce((a, b) => a + b, 0);
const saglik = toplam((s) => s[2] === 'saglik'), r = olc(sapar);
const oran = olay / kopya / (7 * 24 * 3600 / 30), surum = 2 * SERVIS.length;
console.log(`\nhattin tasidigi olay ${olay}/hafta; saglik yoklamasinin payi ${saglik} olay ` +
  `(%${(100 * saglik / olay).toFixed(1)}) ve hicbir tabanda sapmiyor`);
console.log(`bu tabanda sapan olay ${r.sapan} (%${(100 * r.sapan / olay).toFixed(3)}); 30 sn pencerede kopya basina ` +
  `beklenen olay ${oran.toFixed(2)}, sikistirma katsayisi ${Math.max(1, oran).toFixed(2)} -> gecikme ${AKIS} yerine ${TOPLU} sn`);
console.log(`haftada ${surum} surum, servis basina dagitim araligi ${(7 * SERVIS.length / surum).toFixed(1)} gun: taban ` +
  `goruntu ozetine baglanirsa 7 gunluk ogrenme penceresi yarida kesilir, servise baglanirsa her ` +
  `yeni ikili haftada ${toplam((s) => s[2] === 'gecis')} yanlis pozitif uretir`);

const MINIMAL = new Set(SINIF.filter((s) => s[4] === 'mesru').flatMap((s) => kapsam(s).map((v) => `${v}|${s[2]}`)));
MINIMAL.delete('is-emri|kabuk');
const m = olc((s) => kapsam(s).some((v) => !MINIMAL.has(`${v}|${s[2]}`)));
const gt = Object.values(GORUNTU_IKILI).reduce((a, b) => a + b, 0);
console.log(`\ngoruntu ${gt} ikiliden ${MINIMAL.size} cifte daraltilirsa (tanilama kabugu cikarilir):`);
const yz = gen([26, 11, 7, 16, 7]);
console.log(yz(['taban cizgisi', 'yakalanan', 'kacan', 'yanlis pozitif', 'uyari']));
for (const [ad, o] of [['ogrenme + cift listesi', r], ['minimal goruntu envanteri', m]])
  console.log(yz([ad, o.yakalanan, o.kacan, o.yanlis, o.uyari]));
const asama = {};
for (const s of yak) asama[s[8]] = (asama[s[8]] || 0) + s[3];
console.log(`yakalanan ${yt} olayin erken kapatma asamasi: ${Object.entries(asama).map(([a, n]) => `${a} ${n}`).join(', ')}; ` +
  `kacan ${r.kacan} olay tek sinif: ${SINIF.find((s) => s[4] === 'anormal' && !sapar(s))[0]}, erken asama kod`);
```

```
yakalanan anormal sinif            olay omur sn    akis 17 sn    toplu 47 sn
kapsul icinde kabuk acilisi           6      95          evet           evet
goruntude olmayan ag araci            3      12         hayir          hayir
disaridan getirilen ikili             2      40          evet          hayir
kisa omurlu zamanlayici kaydi         1     0.5         hayir          hayir
surec hala kosarken gelen tespit: akis 8/12 olay, toplu 6/12 olay

hattin tasidigi olay 68746/hafta; saglik yoklamasinin payi 62496 olay (%90.9) ve hicbir tabanda sapmiyor
bu tabanda sapan olay 16 (%0.023); 30 sn pencerede kopya basina beklenen olay 0.11, sikistirma katsayisi 1.00 -> gecikme 17 yerine 47 sn
haftada 18 surum, servis basina dagitim araligi 3.5 gun: taban goruntu ozetine baglanirsa 7 gunluk ogrenme penceresi yarida kesilir, servise baglanirsa her yeni ikili haftada 3 yanlis pozitif uretir

goruntu 342 ikiliden 41 cifte daraltilirsa (tanilama kabugu cikarilir):
taban cizgisi               yakalanan  kacan  yanlis pozitif  uyari
ogrenme + cift listesi             12      9               4      6
minimal goruntu envanteri          12      9               4      5
yakalanan 12 olayin erken kapatma asamasi: yapi 9, yok 3; kacan 9 olay tek sinif: yorumlayici icinde calistirma, erken asama kod
```

Üst tablo tespitin ne işe yaradığını ayırıyor. Akış kipinde yakalanan on iki olayın sekizinde uyarı
süreç hâlâ koşarken gelir; toplu kipte bu sayı altıya iner. Kalanlarda uyarı gelmediği için değil,
**geç geldiği** için bir müdahale noktası yoktur: ağ aracı on iki saniye koşup çıkmıştır,
zamanlayıcı kaydı yarım saniye. Bu iki sınıf için tespit bir önleme değil, bir kayıttır.

Orta blok hattın fiyatını yazıyor. Haftada altmış sekiz bin yedi yüz kırk altı olay toplanıyor ve
bunun yüzde doksan virgül dokuzu sağlık yoklamasıdır: her kopyada beş dakikada bir koşan, hiçbir
tabanda sapmayan bir süreç. Sapan olay on altıdır, yani toplanan hacmin yüzde sıfır virgül sıfır iki
üçü. Otuz saniyelik toplu gönderim bu hacmi küçültmüyor: kopya başına pencereye düşen beklenen olay
sayısı birden küçük olduğu için sıkıştırma katsayısı birde kalır ve otuz saniyelik gecikme
karşılıksız kalır. Üçüncü satır tabanın ne kadar dayandığını söylüyor: haftada on sekiz sürüm
çıkarken taban görüntü özetine bağlanırsa hiçbir yedi günlük pencere kapanmaz, servise bağlanırsa
pencere kapanır ama her yeni ikili bir yanlış pozitif üretir. Taban çizgisi bir kez kurulup
bırakılan bir şey değil, dağıtım hızına bağlı bir bakım kalemidir.

#### Daha Erken Nerede Kapanırdı

Son tablonun iki satırı üç sayının üçünde de aynı: on iki yakalanan, dokuz kaçan, dört yanlış
pozitif. Üstteki satır bir öğrenme penceresi, bir izin listesi ve bir bakım takvimi gerektiriyor;
alttaki satır yalnızca görüntünün daraltılmasını — üç yüz kırk iki ikili yerine uygulamanın
gerçekten koşturduğu kırk bir çift. Aynı üç sayı, bir çalışma zamanı düzeneği olmadan, **yapı
aşamasında** ve kalıcı olarak elde ediliyor, üstelik bir uyarı grubu daha az.

Erken aşama dağılımı aynı sonucu ikinci kez söylüyor. Yakalanan on iki olayın dokuzu yapı aşamasında
kapatılabilir: doğrulayıcıda kabuk bulunmasaydı altı olay, saha senkronunda ağ aracı bulunmasaydı üç
olay hiç doğmayacaktı. Kalan üç olay için erken aşama yoktur — dışarıdan getirilen ikili ve
zamanlayıcı kaydı ancak koşan bir düzeneğin görebileceği kalemlerdir. **Katmanın ölçüsü on iki
değil, üçtür.**

Kaçan dokuz olay ters yönü söylüyor. Yorumlayıcı içinde çalıştırma yeni bir süreç başlatmaz;
uygulamanın kendi ikilisi zaten koşmaktadır. Süreç davranışına bakan bir düzenek, süreç doğurmayan
bir davranışı tanım gereği kaçırır; bu kalem kod aşamasına aittir.

#### Özet

- Bir haftalık kayıtta 68.746 süreç başlatma var; 21'i anormal. 342 çift genişliğindeki görüntü
  envanteri tabanı 5 olay yakalar, 16'sını kaçırır ve sıfır yanlış pozitif üretir — bu sıfır dar
  değil, **geniş** bir tanımın işaretidir.
- Yedi günlük öğrenme tabanı 38 çifte iner, yakalananı 12'ye çıkarır ve 9 meşru olayı yanlış
  pozitife çevirir: nadir işler, operatör tanılaması ve yeni sürümün geçiş adımı.
- İzin listesi `servis|ikili` çifti olarak yazılınca yanlış pozitif 4'e iner ve yakalanan 12 kalır;
  yalnız ikili adıyla yazılınca yanlış pozitif yine 4'tür ama yakalanan 6'ya düşer.
- Tespit gecikmesi akış kipinde 17, toplu kipte 47 saniyedir; yakalanan 12 olayın 8'i ile 6'sı süreç
  hâlâ koşarken gelir. Toplu gönderim bu olay yoğunluğunda hiçbir sıkıştırma sağlamaz.
- Hattın taşıdığı olayın yüzde 90,9'u sağlık yoklamasıdır; sapan pay yüzde 0,023'tür. Haftada 18
  sürüm çıkarken görüntü özetine bağlı bir taban hiç tamamlanmaz.
- Görüntüyü 41 çifte daraltmak aynı üç sayıyı yapı aşamasında verir. Yakalanan 12 olayın 9'u yapı
  aşamasında kapatılabilir; yalnız çalışma zamanında kapatılabilen pay 3 olaydır.

#### Sonraki Adım

Bu dersin bütün ölçümü konteyner **koşmaya başladıktan sonra** yapıldı: süreç başladı, olay
toplandı, kural değerlendirildi ve on yedi ya da kırk yedi saniye sonra bir uyarı üretildi.
Doğrulayıcıda kabuğun bulunması ve otuz bir kopyanın hangi ayrıcalıklarla koştuğu ise koşum
başlamadan önce belliydi; bunların hepsi kümeye bir nesne gönderildiği anda okunabilen alanlardır.
Sonraki ders o anı ölçer: kabul denetleyicisi kuralları yirmi iki küme nesnesi üzerinde koşturulur,
zorlama kipine geçildiğinde kaç dağıtımın reddedileceği ve bunların kaçının **meşru** olduğu
sayılır. Reddin kime ve ne zaman değdiği de aynı tabloda yazılır: kaç ekip etkileniyor ve aynı kural
hattın hangi aşamasında kimseyi bekletmeden koşabilirdi.

### Kabul Denetleyicisi

Source: https://academia.sh/tr/kurslar/calisma-zamani-guvenligi/kabul-denetleyicisi

On kabul kuralı 22 küme nesnesi üzerinde koşturulur: 35 ihlalin 22'si kusur, 8'i gerekçeli ihtiyaç, 5'i kuralın uymadığı nesne türüdür. Zorlama kipi hepsi birden açılırsa 21 nesne reddedilir, bunların 5'i meşru dağıtımdır ve beş ekibin beşi etkilenir; kurallar kusur oranına göre sıraya konduğunda ilk altı kural 22 kusurun 19'unu sıfır meşru retle kapatır, son üç kural hiç kusur kapatmadan dört meşru dağıtımı reddeder. Muafiyet nesne başına 13 satırdır, ad alanı başına 7 satırla 38 hücre kapsar ve bir kusuru sessizce muaf tutar; on kuralın onu da hat kapısında koşabilir ve yalnız kabul kapısında kapatılabilen kusur 3'tür.

Önceki ders koşan konteynerin davranışını ölçtü ve tespitin on yedi ya da kırk yedi saniye sonra
geldiğini yazdı. Yakalanan on iki olayın dokuzu için erken bir aşama vardı: görüntüde bulunmaması
gereken bir ikili, koşum başlamadan önce çıkarılabilirdi. O kararın alındığı yer bir kapıdır ve o
kapı henüz ölçülmedi.

Bu ders **kabul denetleyicisini** ölçer: kümeye bir nesne gönderildiğinde nesnenin bildirilen
alanlarına bakıp kabul ya da ret veren kapı. Küme nesnesi mekaniği — nesne türleri, ad alanı,
yetkilendirme — **Konteyner Orkestrasyonu** kursunda ölçüldü ve burada girdi olarak alınıyor.
Buradaki ölçü üç sütunludur: kaç kusur kapanıyor, kaç **meşru dağıtım** reddediliyor, kaç ekip
etkileniyor. Üçüncüsü yazılmadığında ilk ikisi bir şey ölçmez, çünkü zorlama kipine geçmek bir
yapılandırma değişikliği değil, beş ekibin dağıtım akışına dokunan bir karardır.

- **AD12.** Ortam aynı kurgusal bölgesel ölçüm ağıdır: bir küme, dokuz servisin nesneleri,
  zamanlanmış iş nesneleri ve platform iş yükleri; beş ekip. Nesne kümesi `node` ile kurulmuş bir
  modeldir.
- **AD13.** Modellenen tek şey bir nesnenin hangi kuralları ihlal ettiğidir. Nesnelerin alan yapısı,
  sürüm nesnesi ile kapsül ilişkisi ve ad alanı mekaniği modellenmiyor.
- **AD14.** İhlaller üç sınıfa ayrıldı: **kusur** (sahibinin düzeltmesi gereken kalem), **gerekçe**
  (belgelenmiş meşru ihtiyaç), **uyumsuz** (kuralın o nesne türüne uymaması). Üretimde bu ayrım bir
  inceleme sonucudur ve en pahalı adım odur; modelde verilmiş kabul ediliyor.
- **AD15.** Bir nesne, zorlanan kurallardan **birini** ihlal ediyorsa reddedilir; kısmi kabul yok.
- **AD16.** Haftalık dağıtım sayıları nesne başına sabittir. Ondalık değer daha seyrek bir sıklığı
  temsil eder: 0,2 beş haftada bir dağıtım demektir.
- **AD17.** Kapının kendi arızası — kapı düştüğünde dağıtımın açılması mı durması mı gerektiği —
  modellenmiyor; bu ayrı bir karardır.

#### Nesne Kümesi ve Kural Kümesi

```js
// nesne.mjs — yirmi iki kume nesnesi, on kabul kurali ve ihlallerin sinifi. MODELDIR.
export const KURAL = ['kaynak siniri yok', 'salt okunur kok degil', 'ayricalikli kip',
  'ana makine ag alani', 'kok kullanici', 'degisken goruntu etiketi', 'imzasiz goruntu',
  'saglik yoklamasi yok', 'sahip etiketi yok', 'sir ortam degiskeninde'];
export const K = Object.fromEntries(KURAL.map((a, i) => [`K${i + 1}`, a]));

// [ad, ekip, hattan geciyor mu, haftalik dagitim, {kural: ihlal sinifi}]
// ihlal sinifi: kusur = sahibinin duzeltmesi gereken kalem, gerekce = belgelenmis mesru
// ihtiyac, uyumsuz = kural bu nesne turune uymuyor (tek seferlik is nesnesi).
export const NESNE = [
  ['portal-onu', 'abone', 1, 2, { K6: 'kusur' }],
  ['abone-servisi', 'abone', 1, 2, { K1: 'kusur', K10: 'kusur' }],
  ['bildirim', 'abone', 1, 1, { K2: 'kusur' }],
  ['portal-toplu-is', 'abone', 1, 0.5, { K1: 'kusur', K8: 'uyumsuz' }],
  ['faturalama', 'faturalama', 1, 2, { K5: 'kusur', K10: 'kusur' }],
  ['rapor', 'faturalama', 1, 1, { K6: 'kusur' }],
  ['aylik-uzlastirma', 'faturalama', 1, 0.2, { K8: 'uyumsuz' }],
  ['ceyreklik-arsiv', 'faturalama', 1, 0.1, { K8: 'uyumsuz', K9: 'kusur' }],
  ['is-emri', 'saha', 1, 2, { K2: 'kusur' }],
  ['saha-senkron', 'saha', 1, 2, { K1: 'kusur', K2: 'kusur', K7: 'kusur' }],
  ['saha-yukleme-isi', 'saha', 1, 0.5, { K8: 'uyumsuz' }],
  ['sayac-toplama', 'olcum', 1, 2, {}],
  ['dogrulayici', 'olcum', 1, 2, { K5: 'kusur' }],
  ['sayac-yedek-isi', 'olcum', 1, 0.3, { K2: 'kusur', K8: 'uyumsuz' }],
  ['giris-denetleyici', 'platform', 1, 0.5, { K4: 'gerekce' }],
  ['gunluk-toplayici', 'platform', 1, 0.5, { K2: 'kusur', K3: 'gerekce' }],
  ['izleme-toplayici', 'platform', 1, 0.5, { K3: 'gerekce' }],
  ['sertifika-dagitici', 'platform', 1, 0.3, { K10: 'kusur' }],
  ['kayit-aynasi', 'platform', 1, 0.3, { K6: 'kusur', K7: 'kusur' }],
  ['yedek-surucusu', 'platform', 0, 0.2, { K1: 'kusur', K5: 'kusur' }],
  ['ag-eklentisi', 'platform', 0, 0.2, { K3: 'gerekce', K4: 'gerekce', K5: 'gerekce' }],
  ['dugum-aracisi', 'platform', 0, 0.1, { K3: 'gerekce', K5: 'gerekce', K9: 'kusur' }],
];

export const EKIP = [...new Set(NESNE.map((n) => n[1]))];
export const ihlal = (n, E) => Object.entries(n[4]).filter(([k]) => E.includes(k));

// Zorlama kipinde bir nesne, zorlanan kurallardan birini ihlal ediyorsa reddedilir.
// Reddedilen nesnede zorlanan kurallar arasinda hic kusur yoksa bu bir MESRU rettir.
export function zorla(E) {
  const ret = NESNE.filter((n) => ihlal(n, E).length);
  const mesru = ret.filter((n) => ihlal(n, E).every(([, s]) => s !== 'kusur'));
  return { ret, mesru, kusur: NESNE.reduce((a, n) => a + ihlal(n, E).filter(([, s]) => s === 'kusur').length, 0),
    ekip: new Set(ret.map((n) => n[1])).size, mekip: new Set(mesru.map((n) => n[1])).size,
    dagitim: ret.reduce((a, n) => a + n[3], 0), mdagitim: mesru.reduce((a, n) => a + n[3], 0) };
}

export const TUM = Object.keys(K);
export const gen = (B) => (h) => h.map((v, j) => j ? String(v).padStart(B[j]) : String(v).padEnd(B[0])).join('');
```

Kural kümesi bir nesnenin yalnız **bildirilen alanlarına** bakıyor; koşan bir şeye değil. Bu, dersin
sonundaki karşılaştırmanın da dayanağıdır.

#### Üç Kip ve Kural Başına Bilanço

```js
// kosum1.mjs — uc kip, kural basina bilanco ve kurallari siraya koyarak zorlama
import { NESNE, KURAL, K, TUM, EKIP, ihlal, zorla, gen } from './nesne.mjs';

const say = (s) => NESNE.reduce((a, n) => a + Object.values(n[4]).filter((x) => x === s).length, 0);
const z = zorla(TUM);
console.log(`${NESNE.length} nesne, ${EKIP.length} ekip, ${KURAL.length} kural; ihlal ${say('kusur') + say('gerekce') + say('uyumsuz')} ` +
  `(kusur ${say('kusur')} / gerekce ${say('gerekce')} / uyumsuz ${say('uyumsuz')})\n`);
const yk = gen([10, 12, 14, 13, 16, 13]);
console.log(yk(['kip', 'uyari kaydi', 'reddedilen', 'mesru ret', 'etkilenen ekip', 'ret/hafta']));
console.log(yk(['kapali', 0, 0, 0, 0, 0]));
console.log(yk(['uyari', z.ret.reduce((a, n) => a + ihlal(n, TUM).length, 0), 0, 0, 0, 0]));
console.log(yk(['zorlama', 0, z.ret.length, z.mesru.length, `${z.ekip}/${EKIP.length}`, z.dagitim.toFixed(1)]));

const bilanco = TUM.map((k) => ({ k, kusur: zorla([k]).kusur, mesru: zorla([k]).mesru.length }));
console.log('\n' + gen([6, 26, 8, 11])(['kural', 'ad', 'kusur', 'mesru ret']));
for (const b of bilanco) console.log(gen([6, 26, 8, 11])([b.k, K[b.k], b.kusur, b.mesru]));

const sira = [...bilanco].sort((a, b) => b.kusur / (1 + b.mesru) - a.kusur / (1 + a.mesru)).map((b) => b.k);
console.log(`\nkurallar kusur/(1+mesru ret) oranina gore siraya konup birer birer zorlaniyor:`);
const yz = gen([8, 26, 15, 13, 12, 15]);
console.log(yz(['adim', 'eklenen kural', 'kapanan kusur', 'reddedilen', 'mesru ret', 'mesru ret ekip']));
for (let i = 1; i <= sira.length; i++) {
  const r = zorla(sira.slice(0, i));
  console.log(yz([i, K[sira[i - 1]], r.kusur, r.ret.length, r.mesru.length, r.mekip]));
}
```

```
22 nesne, 5 ekip, 10 kural; ihlal 35 (kusur 22 / gerekce 8 / uyumsuz 5)

kip        uyari kaydi    reddedilen    mesru ret  etkilenen ekip    ret/hafta
kapali               0             0            0               0            0
uyari               35             0            0               0            0
zorlama              0            21            5             5/5         18.2

kural                         ad   kusur  mesru ret
K1             kaynak siniri yok       4          0
K2         salt okunur kok degil       5          0
K3               ayricalikli kip       0          4
K4           ana makine ag alani       0          2
K5                 kok kullanici       3          2
K6      degisken goruntu etiketi       3          0
K7               imzasiz goruntu       2          0
K8          saglik yoklamasi yok       0          5
K9             sahip etiketi yok       2          0
K10       sir ortam degiskeninde       3          0

kurallar kusur/(1+mesru ret) oranina gore siraya konup birer birer zorlaniyor:
adim                 eklenen kural  kapanan kusur   reddedilen   mesru ret mesru ret ekip
1            salt okunur kok degil              5            5           0              0
2                kaynak siniri yok              9            8           0              0
3         degisken goruntu etiketi             12           11           0              0
4           sir ortam degiskeninde             15           13           0              0
5                  imzasiz goruntu             17           13           0              0
6                sahip etiketi yok             19           15           0              0
7                    kok kullanici             22           17           1              1
8                  ayricalikli kip             22           18           2              1
9              ana makine ag alani             22           19           3              1
10            saglik yoklamasi yok             22           21           5              3
```

Üst tablo zorlama kipine hepsi birden geçmenin fiyatını veriyor. Uyarı kipi otuz beş kayıt üretir ve
hiçbir dağıtımı durdurmaz; bu, kapının kurulduğu ama hiçbir şeyi değiştirmediği evredir. Zorlama
açıldığında yirmi bir nesne reddedilir, haftada on sekiz virgül iki dağıtım düşer ve **beş ekibin
beşi** etkilenir. Reddedilenlerin beşinde ise kapının şikâyet ettiği tek bir kusur yoktur: ihlal
ettikleri kuralların hepsi ya belgelenmiş bir gerekçedir ya da o nesne türüne uymayan bir kuraldır.

Orta tablo bu beş meşru reddin nereden geldiğini tek tek gösteriyor. Üç kural — ayrıcalıklı kip, ana
makine ağ alanı ve sağlık yoklaması — **hiçbir kusur kapatmıyor** ve meşru reddin tamamını üretiyor.
Sağlık yoklaması kuralı tek başına beş meşru ret verir, çünkü beş nesnenin beşi de tek seferlik iş
nesnesidir ve kural onlara hiç uygulanmamalıydı. Kök kullanıcı kuralı ikisinin arasında durur: üç
kusur kapatır, iki meşru ret verir. Bir kuralı zorlamaya almanın kararı bu iki sütunun oranıdır,
kuralın adı değil.

#### Kademeli Zorlama Nereye Kadar Bedavadır

Alt tablo kuralları o orana göre sıraya koyup birer birer zorluyor. İlk altı adımda **meşru ret
sıfırdır** ve kapanan kusur on dokuza çıkar: yirmi iki kusurun yüzde seksen altısı, hiçbir meşru
dağıtımı durdurmadan kapanıyor. Yedinci adım kök kullanıcı kuralını ekler, üç kusur daha kapatarak
yirmi ikiyi tamamlar ve bedeli tek bir meşru rettir.

Son üç adım sıfır kusur kapatıyor. Sekizinci, dokuzuncu ve onuncu satırda kapanan kusur sütunu yirmi
ikide sabit kalırken meşru ret birden beşe, meşru redde uğrayan ekip birden üçe çıkıyor. Kapının bir
hafta içinde üç ekibin dağıtımını gerekçesiz durdurmasının kaynağı bu üç kuraldır ve üçünün de
kazancı sıfırdır. Zorlama kipine hepsi birden geçmenin yanlışlığı burada sayıya bağlanır: aynı yirmi
iki kusur, sıralı bir açılışla ve tek bir meşru retle kapanabiliyordu.

#### Muafiyetin Genişliği ve Hat Kapısı

```js
// kosum2.mjs — muafiyetin genisligi ve ayni kuralin hat kapisinda kosmasi
import { NESNE, KURAL, EKIP, gen } from './nesne.mjs';

// Muafiyet iki granuluk: nesne basina (ad|kural) ya da ad alani basina (ekip|kural).
const anahtar = (i) => NESNE.flatMap((n) => Object.entries(n[4])
  .filter(([, s]) => s !== 'kusur').map(([k]) => `${n[i]}|${k}`));
const NESNE_MUAF = new Set(anahtar(0)), EKIP_MUAF = new Set(anahtar(1));
const hucre = (M, i) => NESNE.reduce((a, n) => a + KURAL.filter((_, j) => M.has(`${n[i]}|K${j + 1}`)).length, 0);

const olc = (muaf) => {
  const acik = (n) => Object.entries(n[4]).filter(([k]) => !muaf(n, k));
  const ret = NESNE.filter((n) => acik(n).length);
  return { ret: ret.length, mesru: ret.filter((n) => acik(n).every(([, s]) => s !== 'kusur')).length,
    kusur: NESNE.reduce((a, n) => a + acik(n).filter(([, s]) => s === 'kusur').length, 0),
    dagitim: ret.reduce((a, n) => a + n[3], 0) };
};

const AYAR = [['muafiyet yok', () => false, 0, 0],
  ['nesne basina', (n, k) => NESNE_MUAF.has(`${n[0]}|${k}`), NESNE_MUAF.size, hucre(NESNE_MUAF, 0)],
  ['ad alani basina', (n, k) => EKIP_MUAF.has(`${n[1]}|${k}`), EKIP_MUAF.size, hucre(EKIP_MUAF, 1)]];
const ym = gen([18, 8, 12, 13, 13, 11, 12]);
console.log(ym(['muafiyet bicimi', 'satir', 'kapsanan', 'acik kusur', 'reddedilen', 'mesru ret', 'ret/hafta']));
for (const [ad, f, satir, kaps] of AYAR) {
  const r = olc(f);
  console.log(ym([ad, satir, kaps, r.kusur, r.ret, r.mesru, r.dagitim.toFixed(1)]));
}

const hatta = NESNE.filter((n) => n[2]), disi = NESNE.filter((n) => !n[2]);
const kusur = (l) => l.reduce((a, n) => a + Object.values(n[4]).filter((s) => s === 'kusur').length, 0);
console.log(`\non kuralin onu da nesnenin bildirilen alanlarina bakiyor: ayni kural hat kapisinda kosabilir`);
console.log(`  hattan gecen nesne ${hatta.length}/${NESNE.length}, tasidiklari kusur ${kusur(hatta)}/${kusur(NESNE)}`);
console.log(`  hat disinda olusturulan nesne ${disi.length} (${disi.map((n) => n[0]).join(', ')}), kusur ${kusur(disi)}`);

const mesruN = NESNE.filter((n) => Object.values(n[4]).length && Object.values(n[4]).every((s) => s !== 'kusur'));
const toplam = NESNE.reduce((a, n) => a + n[3], 0), kalici = mesruN.reduce((a, n) => a + n[3], 0);
console.log(`\nhaftalik dagitim ${toplam.toFixed(1)}; zorlama acildigi hafta reddedilen ${olc(() => false).dagitim.toFixed(1)}`);
console.log(`  ${kusur(NESNE)} kusur duzeltildikten sonra kalici mesru ret ${kalici.toFixed(1)}/hafta, ` +
  `${EKIP.length} ekibin ${new Set(mesruN.map((n) => n[1])).size}'unde; kalici olmasinin nedeni kusur degil kural kapsamidir`);
```

```
muafiyet bicimi      satir    kapsanan   acik kusur   reddedilen  mesru ret   ret/hafta
muafiyet yok             0           0           22           21          5        18.2
nesne basina            13          13           22           16          0        16.3
ad alani basina          7          38           21           16          0        16.3

on kuralin onu da nesnenin bildirilen alanlarina bakiyor: ayni kural hat kapisinda kosabilir
  hattan gecen nesne 19/22, tasidiklari kusur 19/22
  hat disinda olusturulan nesne 3 (yedek-surucusu, ag-eklentisi, dugum-aracisi), kusur 3

haftalik dagitim 20.2; zorlama acildigi hafta reddedilen 18.2
  22 kusur duzeltildikten sonra kalici mesru ret 1.9/hafta, 5 ekibin 3'unde; kalici olmasinin nedeni kusur degil kural kapsamidir
```

Üst tablonun ikinci ve üçüncü satırı meşru reddi ikisi de sıfırlıyor, reddedilen nesneyi ikisi de on
altıya indiriyor. Fark iki sütundadır. Nesne başına muafiyet on üç satırdır ve tam olarak on üç
hücreyi kapsar; ad alanı başına muafiyet yedi satırdır ve otuz sekiz hücreyi kapsar — yarı yarıya az
satır, üç kata yakın kapsam. Bedeli üçüncü sütunda: açık kusur yirmi ikiden yirmi bire iniyor.
Yedek sürücüsünün kök kullanıcı olarak koşması, ağ eklentisi ile düğüm aracısı için yazılmış olan
platform muafiyetinin altında sessizce meşrulaşıyor.

Kapsanan hücre sayısı gelecekteki nesneleri de içerir: o ad alanında sonradan oluşturulan her nesne
muafiyeti hazır bulur. Muafiyet listesi bu yüzden önceki iki derste ölçülen listelerle aynı
türdendir — bir ayar değil, kapsamı sayılmadığında kural kümesinden daha belirleyici olan bir
envanter.

#### Daha Erken Nerede Kapanırdı

On kuralın onu da nesnenin bildirilen alanlarına bakıyor; hiçbiri koşan bir şeyi okumuyor. Bu,
kuralların tamamının **hat kapısında**, nesne kümeye gönderilmeden önce koşabileceği anlamına gelir.
Fark kuralın kendisinde değil, reddin kime ve ne zaman değdiğindedir: hat kapısında ret değişikliği
yazan kişiye birleştirme anında gelir; kabul kapısında dağıtım sırasında, çoğu zaman o anda nöbette
olan başka birine gelir ve bir sürüm penceresini bloke eder.

Yirmi iki nesnenin on dokuzu hattan geçiyor ve yirmi iki kusurun on dokuzu bu nesnelerde. Yani
kusurların yüzde seksen altısı, hiç kimsenin dağıtımını durdurmadan, sahibinin masasında
kapatılabilirdi. Kalan üç kusur hat dışında elle oluşturulan üç platform nesnesindedir ve hat kapısı
onları tanım gereği hiç görmez. **Kabul kapısının yalnız kendisine ait payı bu üçtür**; kalan on
dokuz için kapı ikinci savunma hattıdır, birinci değil.

Son satır kalıcı bir kalemi yazıyor. Yirmi iki kusur düzeltildikten sonra bile haftada bir virgül
dokuz dağıtım reddedilmeye devam eder ve bu üç ekibi ilgilendirir. Nedeni bir kusur değil, kural
kapsamının nesne türüyle uyuşmamasıdır. Bu kalem muafiyetle kapatılabilir ve kapatıldığında on üç ya
da yedi satırlık bir envanter doğar — ya da kural nesne türünü okuyacak biçimde yeniden yazılır ve
envanter hiç doğmaz.

#### Özet

- 22 nesnede 35 ihlal var: 22 kusur, 8 belgelenmiş gerekçe, 5 kuralın uymadığı nesne. Uyarı kipi 35
  kayıt üretir ve hiçbir dağıtımı durdurmaz.
- Zorlama kipine hepsi birden geçmek 21 nesneyi reddeder, haftada 18,2 dağıtımı düşürür ve 5 ekibin
  5'ini etkiler; reddedilenlerin 5'i hiçbir kusur taşımayan **meşru dağıtımdır**.
- Üç kural (ayrıcalıklı kip, ana makine ağ alanı, sağlık yoklaması) hiç kusur kapatmadan meşru
  reddin tamamını üretir; sağlık yoklaması tek başına 5 meşru ret verir.
- Kurallar kusur oranına göre sıraya konduğunda ilk 6 adım 22 kusurun 19'unu **sıfır meşru retle**
  kapatır, 7. adım kalan 3 kusuru tek bir meşru retle kapatır; son 3 adım sıfır kusur kapatıp meşru
  reddi 5'e, etkilenen ekibi 3'e çıkarır.
- Muafiyet nesne başına 13 satırla 13 hücre, ad alanı başına 7 satırla 38 hücre kapsar; ikincisi bir
  gerçek kusuru sessizce muaf tutar ve ad alanındaki gelecek nesneleri de kapsar.
- On kuralın onu da hat kapısında koşabilir; 22 kusurun 19'u hattan geçen nesnelerdedir. Yalnız
  kabul kapısında kapatılabilen kusur 3'tür ve üçü de elle oluşturulan platform nesnelerindedir.

#### Sonraki Adım

Bu dersin kapısı yalnız **gönderilen** nesneyi gördü. Kümede hâlihazırda koşan nesneler kapıdan bir
daha geçmez; kural kümesi bugün sıkılaştırılsa bile dün kabul edilmiş yirmi iki nesne yerinde durur.
Kümenin dışındaki altyapı kaynakları — depolama, ağ, kayıt defteri, kimlik tanımları — zaten hiçbir
kabul kapısından geçmiyor. Bunları ancak sürekli koşan bir denetim tarar ve o denetim bir bulgu
listesi üretir. Sonraki ders o listeyi ölçer, ama bulgu sayısını değil: her bulgunun **kimin işine
düştüğünü**, kaçının hiçbir sahibi olmadığını ve sahipsiz bulguların hangi hızda biriktiğini.

### Sürekli Yapılandırma Denetimi

Source: https://academia.sh/tr/kurslar/calisma-zamani-guvenligi/surekli-yapilandirma-denetimi

Sürekli denetimin 147 açık bulgusu sahiplik zincirinden geçirilir: sahip etiketi 65'ini, ad alanı sahipliği 24'ünü, depo yolu eşlemesi 18'ini çözer ve 40'ı (yüzde 27,2) sahipsiz kalır. Bulguların 81'i uygulama ekiplerine düşer, 26'sı platformda kalır; sahipsiz 40 bulgunun kapasitesi sıfır olduğu için kuyruk on iki haftada 112'ye çıkarken düzelten ekiplerin yığını erir. Sahipsizliğin 31'i küme dışındaki kaynaktadır ve hiçbir küme düzeneği onu çözemez; 147 bulgunun 122'si daha erken bir aşamada kapatılabilirdi ama sahipsiz 40 bulgunun 25'i için erken aşama yoktur.

Önceki dersin kapısı yalnız gönderilen nesneyi gördü ve on kuralın onu da nesnenin bildirilen
alanlarını okudu. Kapı bugün sıkılaştırılsa bile dün kabul edilmiş nesneler yerinde durur; küme
dışındaki depolama, ağ ve kimlik tanımları ise hiçbir kabul kapısından geçmez. O alanı ancak sürekli
koşan bir denetim tarar.

Bu ders o denetimi ölçer, ama bulgu sayısını değil. Hangi yanlış yapılandırmanın hangi kapıda
kapandığı **Bulut ve Sanallaştırma Güvenliği** kursunda ölçüldü ve burada tekrarlanmıyor. Buradaki
ölçü tek bir sorudur: **bulgu kimin işine düşüyor.** Kaç bulgu bir uygulama ekibine dönüyor, kaçı
platform ekibinde kalıyor ve kaçının hiçbir sahibi yok. Sahipsiz bulgu, ölçülmemiş bulgudan
farklıdır: gösterge tablosunda görünür, sayıya girer, raporlanır ve kimse kapatmaz.

- **AD18.** Denetim kurgusal bölgesel ölçüm ağının tamamını tarar: küme nesneleri ve küme dışındaki
  depolama, ağ, kimlik ve kayıt defteri kaynakları. Bulgu envanteri `node` ile kurulmuş bir
  modeldir.
- **AD19.** Kural kümesinin içeriği ölçülmüyor; sayılar açık bulgu envanterinden okunur. Aynı kaynak
  aynı kuralı ihlal ettiği sürece tek bir bulgu sayılır.
- **AD20.** Sahiplik zinciri üç adımlıdır ve sırayla denenir: kaynağın sahip etiketi, ad alanı
  sahiplik tablosu, depo yolu eşlemesi. İlk eşleşen adım kazanır; hiçbiri eşleşmezse bulgu
  sahipsizdir.
- **AD21.** Bir bulgunun hangi adımda çözüldüğü ve hangi ekibe düştüğü modelde verilmiştir. Üretimde
  bu, envanterin o günkü gerçek durumundan okunur ve zaman içinde değişir.
- **AD22.** Kapasite haftalık sabittir ve yalnız bu bulgular için ayrılan kalemi sayar. Kuyruk
  `max(0, kuyruk + yeni - kapasite)` ile yürür; bulguların kapanma zorluğu farkı modellenmiyor.

#### Bulgu Envanteri ve Sahiplik Zinciri

```js
// bulgu.mjs — surekli denetimin acik bulgu envanteri ve sahiplik zinciri. MODELDIR.
// [ad, kaynak turu, acik bulgu, siddet, sahipligin cozuldugu adim, ekip, erken kapatma asamasi]
export const BULGU = [
  ['kapsul kaynak siniri yok', 'kume', 18, 'orta', 'etiket', 'abone', 'dagitim'],
  ['salt okunur kok degil', 'kume', 14, 'orta', 'etiket', 'saha', 'dagitim'],
  ['sir ortam degiskeninde', 'kume', 6, 'yuksek', 'etiket', 'faturalama', 'kod'],
  ['degisken goruntu etiketi', 'kume', 9, 'dusuk', 'adalani', 'abone', 'yapi'],
  ['imzasiz goruntu', 'kayit', 7, 'yuksek', 'adalani', 'saha', 'yapi'],
  ['genis erisimli depolama kovasi', 'depolama', 11, 'yuksek', 'etiket', 'olcum', 'tasarim'],
  ['sifrelenmemis yedek birimi', 'depolama', 5, 'yuksek', 'depo', 'platform', 'tasarim'],
  ['acik yonetim kapisi', 'ag', 9, 'yuksek', 'yok', '-', 'tasarim'],
  ['kullanilmayan kimlik tanimi', 'kimlik', 16, 'dusuk', 'yok', '-', 'yok'],
  ['genis yetkili rol baglantisi', 'kimlik', 8, 'yuksek', 'adalani', 'platform', 'tasarim'],
  ['gunlugu kapali kaynak', 'ag', 13, 'dusuk', 'depo', 'platform', 'dagitim'],
  ['eski calisma zamani surumu', 'kume', 16, 'orta', 'etiket', 'olcum', 'yapi'],
  ['sahipsiz kalan eski ad alani', 'kume', 9, 'orta', 'yok', '-', 'yok'],
  ['elle olusturulmus ag kurali', 'ag', 6, 'orta', 'yok', '-', 'dagitim'],
];

export const ZINCIR = ['etiket', 'adalani', 'depo'];
export const ADIM_ADI = { etiket: 'sahip etiketi', adalani: 'ad alani sahipligi', depo: 'depo yolu esleme' };
// Ekibin haftada guvenlik bulgusu icin ayirdigi kalem; sahipsiz bulgunun kapasitesi yoktur.
export const KAPASITE = { abone: 4, faturalama: 2, saha: 3, olcum: 5, platform: 3, sahipsiz: 0 };
export const YENI = 22; // haftalik yeni bulgu; dagitim hizina bagli, modelde verilmis

export const taraf = (b) => (b[4] === 'yok' ? 'sahipsiz' : b[5] === 'platform' ? 'platform' : 'uygulama');
export const kova = (b) => (b[4] === 'yok' ? 'sahipsiz' : b[5]);
export const top = (f) => BULGU.filter(f).reduce((a, b) => a + b[2], 0);
export const gen = (B) => (h) => h.map((v, j) => j ? String(v).padStart(B[j]) : String(v).padEnd(B[0])).join('');
```

Zincirin üç adımı üç ayrı yerden okur ve üçü de bir **envanter** kararıdır: kaynağa bir etiket
konmuş mu, ad alanı bir ekibe bağlanmış mı, kaynağı tanımlayan dosya bir depo yolunda mı duruyor.
Hiçbiri denetimin kendi kararı değildir.

#### Bulgu Kimin İşine Düşüyor

```js
// kosum1.mjs — sahiplik zinciri kosturulur: bulgu kimin isine dusuyor
import { BULGU, ZINCIR, ADIM_ADI, taraf, top, gen } from './bulgu.mjs';

const SID = ['yuksek', 'orta', 'dusuk'];
const T = top(() => true);
console.log(`${BULGU.length} bulgu sinifi; acik bulgu ${T} ` +
  `(${SID.map((s) => `${s} ${top((b) => b[3] === s)}`).join(' / ')})\n`);

const yz = gen([22, 8, 12, 9]);
console.log(yz(['cozum adimi', 'bulgu', 'kumulatif', 'pay']));
let k = 0;
for (const a of ZINCIR) {
  k += top((b) => b[4] === a);
  console.log(yz([ADIM_ADI[a], top((b) => b[4] === a), k, `%${(100 * k / T).toFixed(1)}`]));
}
console.log(yz(['cozulemeyen', T - k, T, `%${(100 * (T - k) / T).toFixed(1)}`]));

const yt = gen([20, 8, 9, 8, 9]);
console.log('\n' + yt(['bulgu kime dusuyor', 'bulgu', ...SID]));
for (const [ad, t] of [['uygulama ekipleri', 'uygulama'], ['platform ekibi', 'platform'], ['sahipsiz', 'sahipsiz']])
  console.log(yt([ad, top((b) => taraf(b) === t), ...SID.map((s) => top((b) => taraf(b) === t && b[3] === s))]));
const sz = BULGU.filter((b) => taraf(b) === 'sahipsiz');
console.log(`sahipsiz bulgu ${sz.length} sinifta: ` + sz.map((b) => `${b[0]} (${b[2]})`).join(', '));
```

```
14 bulgu sinifi; acik bulgu 147 (yuksek 46 / orta 63 / dusuk 38)

cozum adimi              bulgu   kumulatif      pay
sahip etiketi               65          65    %44.2
ad alani sahipligi          24          89    %60.5
depo yolu esleme            18         107    %72.8
cozulemeyen                 40         147    %27.2

bulgu kime dusuyor     bulgu   yuksek    orta    dusuk
uygulama ekipleri         81       24      48        9
platform ekibi            26       13       0       13
sahipsiz                  40        9      15       16
sahipsiz bulgu 4 sinifta: acik yonetim kapisi (9), kullanilmayan kimlik tanimi (16), sahipsiz kalan eski ad alani (9), elle olusturulmus ag kurali (6)
```

Zincirin ilk adımı en güçlü olanıdır: sahip etiketi tek başına altmış beş bulgunun sahibini bulur,
yani envanterin yüzde kırk dördünü. İkinci ve üçüncü adımlar yirmi dört ve on sekiz bulgu daha
çözer. Üç adım birlikte yüzde yetmiş üçe ulaşır ve orada durur. Kalan kırk bulgu, denetimin gördüğü
ama kimseye gönderemediği kalemlerdir.

Alt tablo asıl dağılımı veriyor. Seksen bir bulgu uygulama ekiplerine dönüyor, yirmi altısı platform
ekibinde kalıyor ve kırkı sahipsiz. Şiddet sütunları bu üç kovayı birbirinden ayırıyor: platform
ekibinin bulgularının yarısı yüksek şiddetli, uygulama ekiplerinin bulgularının çoğunluğu orta.
Sahipsiz kovada dokuz yüksek şiddetli bulgu var ve dokuzu da açık yönetim kapısıdır. Bu,
sahipsizliğin düşük şiddetli kalemlerle sınırlı olmadığını gösteriyor — sahipsiz olmanın nedeni
bulgunun önemsizliği değil, kaynağın envanterde kimseye bağlanmamış olmasıdır.

#### Kuyruk On İki Hafta Yürütülürse

```js
// kosum2.mjs — kuyrugun on iki haftalik seyri, sahipsizligin kaynagi ve erken asama
import { BULGU, KAPASITE, YENI, kova, top, gen } from './bulgu.mjs';

const T = top(() => true), HAFTA = 12;
const yk = gen([12, 7, 15, 10, 14, 11]);
console.log(yk(['kova', 'acik', 'haftalik yeni', 'kapasite', 'haftalik net', `${HAFTA}. hafta`]));
const son = {};
for (const kv of Object.keys(KAPASITE)) {
  const acik = top((b) => kova(b) === kv), yeni = YENI * acik / T, net = yeni - KAPASITE[kv];
  let q = acik;
  for (let h = 0; h < HAFTA; h++) q = Math.max(0, q + net);
  son[kv] = Math.round(q);
  console.log(yk([kv, acik, yeni.toFixed(1), KAPASITE[kv], net.toFixed(1), son[kv]]));
}
const sahipli = Object.keys(KAPASITE).filter((k) => k !== 'sahipsiz');
const kap = sahipli.reduce((a, k) => a + KAPASITE[k], 0);
const szAcik = top((b) => kova(b) === 'sahipsiz'), gerek = YENI * szAcik / T + szAcik / HAFTA;
console.log(`toplam yigin ${T} -> ${Object.values(son).reduce((a, b) => a + b, 0)}; sahipli kovalar ` +
  `${T - szAcik} -> ${sahipli.reduce((a, k) => a + son[k], 0)}, sahipsiz kova ${szAcik} -> ${son.sahipsiz}`);
console.log(`sahipsiz kovayi ${HAFTA} haftada eritmek haftada ${gerek.toFixed(1)} kalem ister: ` +
  `en buyuk tek ekip kapasitesinin ${(gerek / Math.max(...sahipli.map((k) => KAPASITE[k]))).toFixed(1)} kati, ` +
  `bes ekibin toplam kapasitesinin (${kap}) %${(100 * gerek / kap).toFixed(0)}'i`);

const sz = (f) => top((b) => kova(b) === 'sahipsiz' && f(b));
const ici = sz((b) => b[1] === 'kume'), tumSz = sz(() => true), yuksek = sz((b) => b[3] === 'yuksek');
console.log(`\nsahipsiz ${tumSz} bulgunun ${ici}'u kume nesnesinde, ${tumSz - ici}'i kume disindaki kaynakta ` +
  `(${[...new Set(BULGU.filter((b) => kova(b) === 'sahipsiz' && b[1] !== 'kume').map((b) => b[1]))].join(', ')})`);

const KALDIRAC = [['ad alani sahipligi satiri', ici, yuksek - sz((b) => b[1] === 'kume' && b[3] === 'yuksek'), 'yalniz kume nesnesi'],
  ['kaynak envanterinde sahip alani', tumSz, 0, 'butun kaynaklar'],
  ['dusuk siddetli sinifi susturma', sz((b) => b[3] === 'dusuk'), yuksek, 'bulgu kaybolur, kaynak kalir'],
  ['kabul kapisinda sahip etiketi', 0, yuksek, 'yalniz yeni olusturulan kaynak']];
const yl = gen([34, 10, 8, 15, 32]);
console.log('\n' + yl(['kaldirac', 'cozulen', 'kalan', 'kalan yuksek', 'kapsam']));
for (const [ad, c, y, kap] of KALDIRAC) console.log(yl([ad, c, tumSz - c, y, kap]));
console.log(`kabul kapisi mevcut ${tumSz} bulguya dokunmaz; haftalik yeni sahipsizin kume payini ` +
  `${(YENI * ici / T).toFixed(1)}'ten 0'a indirir`);

const ASAMA = ['tasarim', 'yapi', 'kod', 'dagitim', 'yok'];
const ya = gen([12, 8, 11]);
console.log('\n' + ya(['erken asama', 'bulgu', 'sahipsiz']));
for (const a of ASAMA) console.log(ya([a, top((b) => b[6] === a), sz((b) => b[6] === a)]));
const erken = top((b) => b[6] !== 'yok');
console.log(`${erken} bulgu (%${(100 * erken / T).toFixed(0)}) daha erken bir asamada kapatilabilirdi; ` +
  `sahipsiz ${tumSz} bulgunun ${sz((b) => b[6] === 'yok')}'i icin erken asama yok`);
```

```
kova           acik  haftalik yeni  kapasite  haftalik net  12. hafta
abone            27            4.0         4           0.0         27
faturalama        6            0.9         2          -1.1          0
saha             21            3.1         3           0.1         23
olcum            27            4.0         5          -1.0         15
platform         26            3.9         3           0.9         37
sahipsiz         40            6.0         0           6.0        112
toplam yigin 147 -> 214; sahipli kovalar 107 -> 102, sahipsiz kova 40 -> 112
sahipsiz kovayi 12 haftada eritmek haftada 9.3 kalem ister: en buyuk tek ekip kapasitesinin 1.9 kati, bes ekibin toplam kapasitesinin (17) %55'i

sahipsiz 40 bulgunun 9'u kume nesnesinde, 31'i kume disindaki kaynakta (ag, kimlik)

kaldirac                             cozulen   kalan   kalan yuksek                          kapsam
ad alani sahipligi satiri                  9      31              9             yalniz kume nesnesi
kaynak envanterinde sahip alani           40       0              0                 butun kaynaklar
dusuk siddetli sinifi susturma            16      24              9    bulgu kaybolur, kaynak kalir
kabul kapisinda sahip etiketi              0      40              9  yalniz yeni olusturulan kaynak
kabul kapisi mevcut 40 bulguya dokunmaz; haftalik yeni sahipsizin kume payini 1.3'ten 0'a indirir

erken asama    bulgu   sahipsiz
tasarim           33          9
yapi              32          0
kod                6          0
dagitim           51          6
yok               25         25
122 bulgu (%83) daha erken bir asamada kapatilabilirdi; sahipsiz 40 bulgunun 25'i icin erken asama yok
```

Üst tablo altı kovanın altısını farklı yönlere gönderiyor. Faturalama ve ölçüm ekiplerinin
kapasitesi gelen yükün üstünde olduğu için yığınları eriyor: faturalama on iki haftada sıfırlanıyor,
ölçüm yirmi yediden on beşe iniyor. Abone ekibi tam dengede duruyor. Saha ve platform ekipleri her
hafta biraz geriye düşüyor ve platformun yığını yirmi altıdan otuz yediye çıkıyor. Bunların hepsi
yönetilebilir sayılardır ve hepsinin ortak yanı bir sahibinin olmasıdır.

Altıncı satır başka bir şey. Sahipsiz kovada kapasite sıfırdır, çünkü kapasite bir ekibe ait bir
kavramdır ve bu kovanın ekibi yoktur. Kırk bulgu her hafta altı yeni bulgu alıyor, hiç kapanmıyor ve
on iki haftada yüz on ikiye çıkıyor. Sahibi olan beş kovanın toplam yığını aynı sürede yüz yediden
yüz ikiye inerken toplam envanter yüz kırk yediden iki yüz on dörde çıkıyor: artışın tamamı tek bir
kovadan geliyor ve o kova hiçbir düzeltme çabasına yanıt vermiyor.

Son satır bunun fiyatını yazıyor. Sahipsiz kovayı on iki haftada eritmek haftada dokuz virgül üç
kalemlik bir kapasite ister. Bu sayı en büyük tek ekip kapasitesinin bir virgül dokuz katı ve beş
ekibin **toplam** kapasitesinin yüzde elli beşidir. Yani sahipsiz bulgular bir ekibe toptan
verilseydi o ekibin bütün kapasitesi yetmezdi; en büyük iki ekibin kapasitesi bile yetmez, üçüncü
bir ekibin payı gerekirdi ve o ekipler kendi bulgularını bırakmak zorunda kalırdı. Sahipsizliğin bedeli, kimsenin bakmaması değil, bakacak
birinin bulunması hâlinde ödenmesi gereken sayının bu kadar büyük olmasıdır.

#### Sahipliği Kim Verecek

Orta blok sahipsizliğin nereden geldiğini ayırıyor: kırk bulgunun yalnız dokuzu bir küme
nesnesindedir, otuz biri ağ ve kimlik kaynaklarındadır. Bu ayrım kaldıraç tablosunun tamamını
belirliyor. Ad alanı sahipliği tablosuna bir satır yazmak dokuz bulguyu çözer ve otuz biri yerinde
bırakır — çünkü o kaynaklar bir ad alanında değildir. Bir önceki dersin kabul kapısına eklenen sahip
etiketi kuralı mevcut kırk bulgunun **hiçbirine** dokunmaz; yalnız yeni oluşturulan küme nesnelerini
etkiler ve haftalık yeni sahipsizin küme payını bir virgül üçten sıfıra indirir. Düşük şiddetli
sınıfı susturmak envanteri kırktan yirmi dörde indirir ama kalan yüksek şiddetli dokuz bulguya hiç
dokunmaz; kaynak yerinde durur, yalnız görünmez olur.

Kırk bulgunun kırkını çözen tek satır ikincisidir: kaynak envanterinde bir sahip alanı. O alan
kümenin bir düzeneği değildir, denetimin bir çıktısı da değildir — kaynak oluşturulurken doldurulan
bir metadır. Sürekli denetim sahipliği **üretemez**; yalnız yokluğunu raporlar.

#### Daha Erken Nerede Kapanırdı

Son tablo iki sütunla bakıldığında dersin sonucunu veriyor. Yüz kırk yedi bulgunun yüz yirmi ikisi —
yüzde seksen üçü — daha erken bir aşamada kapatılabilirdi: elli biri dağıtım aşamasında bir manifest
denetimiyle, otuz üçü tasarımda bir erişim kararıyla, otuz ikisi yapı aşamasında bir yeniden
inşayla, altısı kodda. Sürekli denetim bu yüz yirmi ikiyi her taramada yeniden bulur ve her taramada
yeniden raporlar.

İkinci sütun ise ters yönde okunur. Sahipsiz kırk bulgunun yirmi beşi için erken aşama **yoktur** ve
bu bir rastlantı değildir: kullanılmayan kimlik tanımları ile sahipsiz kalan eski ad alanı, bir
aşamada doğup unutulmuş kaynaklardır. Onları üreten karar bir aşamaya ait değil, bir kaydın hiç
tutulmamış olmasına aittir. Bu kursun ölçüsü — bir kalemi daha erken kapatmanın kaç kat ucuz olduğu
— burada başka bir biçim alır: sahiplik bir aşamada kapatılabilecek bir kalem değil, kaynağın var
olduğu ilk andan itibaren taşıması gereken bir alandır. Alan boş bırakıldığında ortaya çıkan bulgu
hiçbir aşamada ucuzlamaz; yalnızca kimsenin bakmadığı bir listede birikir.

#### Özet

- 147 açık bulgunun sahipliği üç adımlı bir zincirle çözülüyor: sahip etiketi 65, ad alanı sahipliği
  24, depo yolu eşlemesi 18. Zincir yüzde 72,8'de duruyor ve 40 bulgu (yüzde 27,2) sahipsiz kalıyor.
- Bulguların 81'i uygulama ekiplerine düşüyor, 26'sı platform ekibinde kalıyor. Sahipsiz kovada 9
  yüksek şiddetli bulgu var; sahipsizlik düşük şiddetle sınırlı değil.
- Sahipsiz kovanın kapasitesi sıfırdır: 40 bulgu on iki haftada 112'ye çıkarken sahibi olan beş
  kovanın toplam yığını 107'den 102'ye iniyor. Bu kovayı aynı sürede eritmek haftada 9,3 kalem, yani
  beş ekibin toplam kapasitesinin yüzde 55'i kadar bir pay ister.
- Sahipsiz 40 bulgunun 31'i küme dışındaki ağ ve kimlik kaynaklarındadır; ad alanı sahipliği yalnız
  9'unu çözer, kabul kapısı mevcut hiçbirine dokunmaz, susturma 16'sını görünmez yapar ve kaynağı
  yerinde bırakır. Kırkını çözen tek şey kaynak envanterindeki bir sahip alanıdır.
- 147 bulgunun 122'si (yüzde 83) daha erken bir aşamada kapatılabilirdi; sahipsiz 40 bulgunun 25'i
  için erken aşama yoktur, çünkü sahiplik bir aşamanın değil kaynak oluşturmanın kararıdır.

#### Sonraki Adım

Erken aşama sütununda otuz iki bulgu **yapı** yazıyor: değişken görüntü etiketi, imzasız görüntü ve
eski çalışma zamanı sürümü. Bu üç sınıfın ortak yanı, hiçbirinin yerinde düzeltilememesidir —
kapanmaları için yeni bir görüntü inşa edilip otuz bir kopyanın yeniden dağıtılması gerekir. Denetim
onları her taramada yeniden bulur, çünkü tarama ile düzeltme arasındaki mesafe bir yapılandırma
değişikliği değil, bir sürüm döngüsüdür. Sonraki ders o döngüyü ölçer: bir düzeltme yayımlandıktan
sonra kopyalara ulaşması kaç gün alıyor, yerinde yama ile yeniden inşa arasındaki gün farkı nedir ve
yeniden inşanın karşılığında getirdiği kesinti kaç kopyaya değiyor.

### Yeniden İnşa Temelli Güncelleme

Source: https://academia.sh/tr/kurslar/calisma-zamani-guvenligi/yeniden-insa-temelli-guncelleme

Aynı temel görüntü düzeltmesi otuz bir kopyada üç yolla koşturulur ve yama gecikmesi gün cinsinden ölçülür: yerinde yama bütün filoyu 5,25 günde kapatır ama koruma kopya ağırlıklı ortalama 2,61 gün sonra kaybolur ve otuz günün yüzde 72,8'i açık geçer; kod değişikliğiyle yeniden inşa son kopyayı 14,25 günde kapatır, açık pay yüzde 19,4'tür; zamanlanmış yeniden inşa dokuz servisi de 1,75 günde kapatır ve açık payı yüzde 5,8'e indirir. Bedeli haftalık kopya yeniden başlatmasının 73,5'ten 96,75'e, yani yüzde 31,6 artmasıdır; iki kopyalı servisler her turda doksan saniye boyunca kapasitelerinin yarısını yitirir.

Önceki ders sürekli denetimin bulgularını sahibine göre ayırdı ve erken aşama sütununda otuz iki
bulgu **yapı** yazdı: değişken görüntü etiketi, imzasız görüntü ve eski çalışma zamanı sürümü.
Üçü de yerinde düzeltilemez; kapanmaları için yeni bir görüntü inşa edilip otuz bir kopyanın yeniden
dağıtılması gerekir.

Bu ders o mesafeyi ölçer ve ölçü birimi **gündür**: bir düzeltme yayımlandıktan sonra filonun son
kopyasında koşmaya başlaması kaç gün alıyor ve o süre boyunca kaç kopya açık kalıyor. Değişmez
altyapının gerekçesi — makinelerin ayrışması, geri alma turu, taşınamayan yerel durum — **Kod Olarak
Altyapı** kursunda ölçüldü ve burada girdi olarak alınıyor. Soru başkadır: yama gecikmesi kaç güne
iniyor ve karşılığında kaç yeniden başlatma isteniyor.

- **AD23.** Ortam aynıdır: dokuz servis, otuz bir kopya, bir küme. Gerçek bir yapı ya da dağıtım
  koşturulmuyor; ölçülen şey `node` ile kurulan bir modeldir. Bütün aşama süreleri gün cinsinden
  modelde verilmiştir ve sayılar bunlardan türetilir; duvar saati ölçülmüyor.
- **AD24.** Servis başına dağıtımlar eşit aralıklıdır ve haftalık sürüm toplamı konunun ikinci
  dersinde kullanılan on sekizdir. Gerçekte aralık dağılır; dağılım kuyruğu uzatır, sıralamayı değiştirmez.
- **AD25.** Yerinde yama koşan kapsülün dosya sistemine uygulanır, görüntüye yazılmaz; bir sonraki
  dağıtım yamasız görüntüyü geri getirir. Modelin belirleyici varsayımı budur.
- **AD26.** Kademeli dağıtımda aynı anda en fazla bir kopya kapalıdır ve hazır olma süresi kopya
  başına sabittir; yeniden başlatmanın kendi arıza olasılığı modellenmiyor.

#### Üç Yol ve Yama Gecikmesi

```js
// guncelleme.mjs — otuz bir kopya, uc guncelleme yolu ve otuz gunluk pencere. MODELDIR.
// [servis, kopya, haftalik surum]; surum toplami 18, konunun ikinci dersindeki degerin dagilimi.
export const SERVIS = [
  ['portal-onu', 6, 5], ['abone-servisi', 4, 4], ['faturalama', 3, 3], ['is-emri', 3, 2],
  ['bildirim', 2, 1], ['rapor', 2, 1], ['sayac-toplama', 6, 1], ['dogrulayici', 3, 0.5],
  ['saha-senkron', 2, 0.5],
];
export const PENCERE = 30, HAZIR = 45; // gun; kopya basina hazir olma suresi (sn)
export const aralik = (s) => 7 / s[2];
export const kopya = SERVIS.reduce((a, s) => a + s[1], 0);

// Asama sureleri (gun): yerinde yama = paket deposu 0.5 + onay 1 + bakim penceresi 3.5 +
// uygulama 0.25; yeniden insa = kayit defterine yansima 0.5 + yapi ve hat 0.25; zamanlanmis
// bunlara gecelik tetikleyiciyi (1) ekler.
const YAMA = 0.5 + 1 + 3.5 + 0.25, INSA = 0.25, KAYIT = 0.5, TETIK = 1;
const sonraki = (s, t) => Math.ceil((t + 1e-9) / aralik(s)) * aralik(s);

// Yerinde yama goruntuye yazilmaz: bir sonraki dagitim yamasiz goruntuyu geri getirir.
export function korumali(yol, s) {
  const ara = [];
  if (yol === 'yerinde yama')
    for (let w = YAMA; w < PENCERE; w += 7) ara.push([w, Math.min(sonraki(s, w), PENCERE)]);
  else if (yol === 'kod degisikligiyle yeniden insa')
    ara.push([Math.min(sonraki(s, KAYIT) + INSA, PENCERE), PENCERE]);
  else ara.push([Math.min(KAYIT + TETIK + INSA, PENCERE), PENCERE]);
  return ara.filter(([b, e]) => e > b);
}

export const YOLLAR = ['yerinde yama', 'kod degisikligiyle yeniden insa', 'zamanlanmis yeniden insa'];
export const koruma = (yol, s) => korumali(yol, s).reduce((a, [b, e]) => a + e - b, 0);
export const ilk = (yol, s) => korumali(yol, s)[0] ?? [PENCERE, PENCERE];
export const acik = (yol) => SERVIS.reduce((a, s) => a + s[1] * (PENCERE - koruma(yol, s)), 0);
export const gen = (B) => (h) => h.map((v, j) => j ? String(v).padStart(B[j]) : String(v).padEnd(B[0])).join('');
```

```js
// kosum1.mjs — ayni yama, uc yol: son kopyanin kapanma gunu ve acik kopya-gun
import { SERVIS, YOLLAR, PENCERE, kopya, aralik, koruma, ilk, acik, gen } from './guncelleme.mjs';

console.log(`${SERVIS.length} servis, ${kopya} kopya, haftada ${SERVIS.reduce((a, s) => a + s[2], 0)} surum; ` +
  `dagitim araligi ${Math.min(...SERVIS.map(aralik)).toFixed(2)} ile ${Math.max(...SERVIS.map(aralik))} gun arasinda\n`);

const yy = gen([32, 12, 12, 17, 11]);
console.log(yy(['yol', 'ilk kopya', 'son kopya', 'acik kopya-gun', 'acik pay']));
for (const y of YOLLAR) {
  const g = SERVIS.map((s) => ilk(y, s)[0]);
  console.log(yy([y, Math.min(...g).toFixed(2), Math.max(...g).toFixed(2), acik(y).toFixed(1),
    `%${(100 * acik(y) / (kopya * PENCERE)).toFixed(1)}`]));
}

const ys = gen([16, 8, 10, 14, 15]);
console.log('\n' + ys(['servis', 'kopya', 'aralik', 'yama dayanir', 'insa ilk gun']));
for (const s of SERVIS) {
  const [b, e] = ilk('yerinde yama', s);
  console.log(ys([s[0], s[1], aralik(s).toFixed(2), (e - b).toFixed(2),
    ilk('kod degisikligiyle yeniden insa', s)[0].toFixed(2)]));
}
const dayan = SERVIS.reduce((a, s) => { const [b, e] = ilk('yerinde yama', s); return a + s[1] * (e - b); }, 0) / kopya;
console.log(`yerinde yama kopya agirlikli ortalama ${dayan.toFixed(2)} gun dayaniyor; ${PENCERE} gunde ` +
  `korumali gecen sure %${(100 * SERVIS.reduce((a, s) => a + s[1] * koruma('yerinde yama', s), 0) / (kopya * PENCERE)).toFixed(1)}`);
```

```
9 servis, 31 kopya, haftada 18 surum; dagitim araligi 1.40 ile 14 gun arasinda

yol                                ilk kopya   son kopya   acik kopya-gun   acik pay
yerinde yama                            5.25        5.25            676.6      %72.8
kod degisikligiyle yeniden insa         1.65       14.25            180.6      %19.4
zamanlanmis yeniden insa                1.75        1.75             54.3       %5.8

servis             kopya    aralik  yama dayanir   insa ilk gun
portal-onu             6      1.40          0.35           1.65
abone-servisi          4      1.75          1.75           2.00
faturalama             3      2.33          1.75           2.58
is-emri                3      3.50          1.75           3.75
bildirim               2      7.00          1.75           7.25
rapor                  2      7.00          1.75           7.25
sayac-toplama          6      7.00          1.75           7.25
dogrulayici            3     14.00          8.75          14.25
saha-senkron           2     14.00          8.75          14.25
yerinde yama kopya agirlikli ortalama 2.61 gun dayaniyor; 30 gunde korumali gecen sure %27.2
```

Üst tablonun ilk iki sütunu yerinde yamayı en iyi seçenek gibi gösteriyor: filonun tamamı beş virgül
iki beş günde kapanıyor, çünkü yama bütün kopyalara aynı bakım penceresinde uygulanıyor. Kod
değişikliğine bağlı yeniden inşanın son kopyası ise on dört virgül iki beş günde kapanıyor.

Üçüncü sütun kararı tersine çeviriyor. Otuz günlük pencerede yerinde yama altı yüz yetmiş altı
virgül altı kopya-gün açık bırakıyor (filonun yüzde yetmiş iki virgül sekizi), yeniden inşa yüz
seksen virgül altı kopya-gün (yüzde on dokuz virgül dört). Aynı yama, aynı filo, aynı otuz gün:
**ilk kapatmayı üç kat hızlı yapan yol, açık kalan süreyi dört kat büyütüyor.**

#### Yamanın Dayanmadığı Yer

Alt tablo bunun nedenini servis servis yazıyor. Yerinde yama görüntüye yazılmadığı için bir sonraki
dağıtım yamasız görüntüyü geri getiriyor; yamanın ne kadar dayanacağı bu yüzden yamanın kendisine
değil, **servisin dağıtım sıklığına** bağlı.

Sıralama beklenenin tersidir. Portal önü iki günde birden sık dağıtılıyor ve yaması sıfır virgül
otuz beş gün, yani dokuz saatten kısa dayanıyor: altı kopyalı ve kenarda duran servis, filonun
yamayı en çabuk kaybeden servisidir. Doğrulayıcı ile saha senkronu iki haftada bir dağıtıldığı için
yamayı sekiz virgül yetmiş beş gün taşıyor. Yerinde yamanın en iyi çalıştığı yer, en az dağıtılan ve
genellikle en az açık trafiğe bakan servistir.

Kopya ağırlıklı ortalama iki virgül altı bir gündür; otuz günün yalnız yüzde yirmi yedi virgül ikisi
korumalı geçiyor ve haftalık bakım penceresi tekrarlansa da tablo değişmiyor, çünkü pencere haftada
bir, dağıtım bazı servislerde günde birden sık. Zamanlanmış yeniden inşa sütunu ise dokuz servis
için de aynı sayıyı taşıyor: bir virgül yetmiş beş gün. Tetikleyici temel görüntünün değişmesidir,
servisin kod değişikliği değil; dağıtım sıklığı denklemden çıkıyor.

#### Kesintinin Fiyatı

```js
// kosum2.mjs — yeniden insanin getirdigi kesinti ve calisma zamani katmaninin tuttugu pencere
import { SERVIS, YOLLAR, PENCERE, HAZIR, kopya, acik, gen } from './guncelleme.mjs';

const yk = gen([8, 9, 15, 17, 18]);
console.log(yk(['kopya', 'servis', 'pencere (sn)', 'kapasite kaybi', 'haftalik yeniden']));
for (const k of [...new Set(SERVIS.map((s) => s[1]))].sort((a, b) => b - a)) {
  const g = SERVIS.filter((s) => s[1] === k);
  console.log(yk([k, g.length, k * HAZIR, `%${(100 / k).toFixed(1)}`, g.reduce((a, s) => a + s[1] * s[2], 0).toFixed(1)]));
}
const mevcut = SERVIS.reduce((a, s) => a + s[1] * s[2], 0), ek = (3 / 4) * kopya;
const sirali = SERVIS.map((s) => [s[0], s[1] * s[2]]).sort((a, b) => b[1] - a[1]);
console.log(`filo penceresi: dokuz servis paralel ${(Math.max(...SERVIS.map((s) => s[1])) * HAZIR / 60).toFixed(2)} dk, ` +
  `sirayla ${(kopya * HAZIR / 60).toFixed(2)} dk; en cok yeniden baslayan ${sirali[0][0]} (${sirali[0][1]}/hafta), ` +
  `en az ${sirali[8][0]} (${sirali[8][1]}/hafta)`);
console.log(`haftalik kopya yeniden baslatmasi ${mevcut.toFixed(1)}; zamanlanmis yeniden insa (ayda 3 temel ` +
  `goruntu) ${ek.toFixed(2)} ekler: %${(100 * ek / mevcut).toFixed(1)} artis. Yerinde yama sifir yeniden ` +
  `baslatma ekler, karsiliginda ayda 4 bakim penceresi ve ${4 * kopya} kopya dokunusu ister`);

// Yalniz calisma zamaninda durdurulabilen sinif: yamasi cikmamis bilesen acigi, gunde 40 istek
// (bu kursun ilk dersinden). Yama gecikmesi, o sinifi tutan agin genisligidir.
const GUNLUK = 40, ya = gen([32, 16, 22, 15]);
console.log('\n' + ya(['yol', 'acik filo-gun', 'aginin tuttugu istek', 'en iyiye kat']));
const enIyi = acik('zamanlanmis yeniden insa') / kopya;
for (const y of YOLLAR) {
  const g = acik(y) / kopya;
  console.log(ya([y, g.toFixed(2), Math.round(g * GUNLUK), `${(g / enIyi).toFixed(1)}x`]));
}
console.log(`otuz gunluk pencerede toplam ${PENCERE * GUNLUK} istek gelir`);
```

```
kopya      servis   pencere (sn)   kapasite kaybi  haftalik yeniden
6               2            270            %16.7              36.0
4               1            180            %25.0              16.0
3               3            135            %33.3              16.5
2               3             90            %50.0               5.0
filo penceresi: dokuz servis paralel 4.50 dk, sirayla 23.25 dk; en cok yeniden baslayan portal-onu (30/hafta), en az saha-senkron (1/hafta)
haftalik kopya yeniden baslatmasi 73.5; zamanlanmis yeniden insa (ayda 3 temel goruntu) 23.25 ekler: %31.6 artis. Yerinde yama sifir yeniden baslatma ekler, karsiliginda ayda 4 bakim penceresi ve 124 kopya dokunusu ister

yol                                acik filo-gun  aginin tuttugu istek   en iyiye kat
yerinde yama                               21.83                   873          12.5x
kod degisikligiyle yeniden insa             5.83                   233           3.3x
zamanlanmis yeniden insa                    1.75                    70           1.0x
otuz gunluk pencerede toplam 1200 istek gelir
```

Zamanlanmış yeniden inşanın bedeli haftalık kopya yeniden başlatmasının yetmiş üç virgül beşten
doksan altı virgül yetmiş beşe çıkmasıdır: yüzde otuz bir virgül altı artış. Bu artış eşit
dağılmıyor. Portal önü zaten haftada otuz kez yeniden başlıyor ve ek yükü fark etmez; saha senkronu
haftada bir kez yeniden başlarken üstüne bir buçuk kat ekleniyor. Yük **en az dağıtılan servislere**
biniyor ve o servisler yamayı en uzun taşıyan servislerdi.

Kapasite kaybı sütunu ikinci bedeli veriyor. Kademeli dağıtımda aynı anda bir kopya kapalıysa altı
kopyalı serviste kayıp yüzde on altı virgül yedi, iki kopyalı serviste yüzde ellidir. Üç servis her
turda doksan saniye boyunca kapasitesinin yarısıyla koşuyor; dokuz servis paralel dağıtılırsa filo
dört buçuk dakikada dönüyor. Asıl karar bu dakikaların kabul edilebilir olup olmadığıdır ve bu soru
yama gecikmesinden ayrı sorulamaz.

#### Ağın Genişliği

Alt tablo kursun bütün ölçümünü tek bir sayıya bağlıyor. İlk derste, uygulama katmanı güvenlik
duvarının durdurduğu altı yüz altmış altı isteğin yalnız kırkı — yüzde altısı — daha erken bir
aşamada kapatılamayan sınıftı: bileşende yaması çıkmamış bir açık, günde kırk istek, yamanın
gelmesini bekliyor.

Yama gecikmesi tam olarak o ağın gerilmek zorunda olduğu süredir. Zamanlanmış yeniden inşada çalışma
zamanı katmanı yetmiş isteği tek başına tutuyor; kod değişikliğine bağlı yeniden inşada iki yüz otuz
üç, yerinde yamada sekiz yüz yetmiş üç — on iki buçuk kat. Aynı kural kümesi, aynı eşik; değişen tek
şey arkasındaki güncelleme yolu. Çalışma zamanı savunmasının değeri kural kümesinin kalitesiyle
değil, **arkasındaki kalemin ne kadar süre açık kaldığıyla** ölçülür.

#### Özet

- Üç yolda son kopyanın kapanma günü 5,25 / 14,25 / 1,75'tir; otuz günlük açık kopya-gün 676,6 /
  180,6 / 54,3, yani yüzde 72,8 / 19,4 / 5,8.
- Yerinde yama ilk kapatmayı en hızlı yapar ama görüntüye yazılmadığı için bir sonraki dağıtımda
  düşer; koruma kopya ağırlıklı ortalama 2,61 gün dayanır. En sık dağıtılan servis yamayı 0,35
  günde kaybeder, en seyrek dağıtılan 8,75 gün taşır.
- Zamanlanmış yeniden inşa dokuz servisi de 1,75 günde kapatır: tetikleyici temel görüntünün
  değişmesidir ve dağıtım sıklığı denklemden çıkar.
- Bedeli haftalık kopya yeniden başlatmasının 73,5'ten 96,75'e çıkmasıdır (yüzde 31,6) ve yük en az
  dağıtılan servislere biner; iki kopyalı üç servis her turda 90 saniye boyunca kapasitesinin
  yarısıyla koşar.
- Yalnız çalışma zamanında durdurulabilen sınıf günde 40 istektir; katmanın tek başına tuttuğu istek
  70 / 233 / 873'tür. Yama gecikmesini kısaltmak katmanın yükünü kural yazmadan 12,5 kat azaltır.

#### Kurs Kapanışı

| Ders | Katmanın yakaladığı | Kaçırdığı / yanlış kestiği | Daha erken kapatma aşaması |
|---|---|---|---|
| Güvenlik duvarı | 666 kötü istek/gün | 1.460 kaçan, eşik 3'te 8.000 kesilen | 626 kod, yalnız burada 40 |
| Hız sınırlama | 5.760 istek (kayan pencere) | 6.900 kaçan, 880 meşru tepe | 3.910 burada, gerisi kod ve tasarım |
| Doldurma savunması | 5.512 deneme, 13 ele geçirme | doldurmada 0 engel, 91 hesap kilidi | kod 70'ten 5'e, tasarım 0 |
| Güvenlik başlıkları | 55 hücre, isteğin %63,4'ü | 3 uç dışarıda, 24 hücre etkisiz | 3 başlık kod, 3 başlık burada |
| Anormallik tespiti | 3 kötü oturum (eşik 20) | 2/4 meşru işaret, 7.106 kayıt | 1 kod, 1 tasarım, 1'i için yok |
| Sır deposu | 31 kullanılan kalem | 48 karşılıksız kalem (%61) | dağıtım bildirimi, 9 kat ucuz |
| Kısa ömürlü kimlik | 16 kalemde 2.033 kat | 15 kalem sabit, maruziyetin %99,96'sı | tasarım, 8 sır |
| Anahtar döndürme | asgari örtüşmede 0 kesme | 60 dakikada 87.427 kesilen istek | kod, 1.440'tan 240 dakikaya |
| İş yükü kimliği | 20 statik sır kalkıyor | 11 kalem kalıyor, 7 uygulama sırlı | tasarım, 4 geçidin 3'ü |
| Sızıntı müdahalesi | erken iptal 150.934 çağrı | 224.171 çağrı, 68.503 kesilen istek | yapı, 2.880 dakika gecikme |
| Ağ bölütleme | 35 çift kapanır, 7,1'den 4,1'e | depoya 1'den 2 sıçrama, 3,8 çift kesinti | tasarım, çağrı sözleşmesi |
| Çalışma zamanı tespiti | 21 olayın 12'si | 9 kaçan, 4 yanlış pozitif | 9 olay yapı, yalnız burada 3 |
| Kabul denetleyicisi | 22 kusur, ilk 6 kural 19'u | 5 meşru ret, 5/5 ekip | 19 hat kapısı, yalnız burada 3 |
| Yapılandırma denetimi | 107 bulguya sahip bulunur | 40 sahipsiz, 12 haftada 112 | 122 daha erken, 25'i için yok |
| Yeniden inşa | son kopya 1,75 günde | %5,8 açık, +%31,6 yeniden başlatma | yapı, temel görüntü |

Üçüncü sütun bu kursun kuralıdır. On beş dersin hiçbirinde çalışma zamanı katmanı yakaladığı hacmin
tamamına sahip çıkamadı: güvenlik duvarının durdurduğu her yüz istekten doksan dördü kodda, kabul
denetleyicisinin kapattığı yirmi iki kusurun on dokuzu hat kapısında, sürekli denetimin bulduğu yüz
kırk yedi bulgunun yüz yirmi ikisi daha erken bir aşamada kapatılabilirdi. Katmanın kendi payı her
derste küçük ve her derste gerçektir — kırk istek, üç olay, üç kusur, yirmi beş sahipsiz bulgu.
**Çalışma zamanı savunması bir yama değil, daha erken kapatılamayan kalem için gerilen bir ağdır.**
Her kalem için "bu daha ucuza nerede kapanırdı" sorusu sorulmadığında katman bir savunma olmaktan
çıkıp bir bahaneye dönüşür: gösterge tablosundaki büyük sayı, kapatılmamış bir kod kusurunun her gün
yeniden yakalanmasından başka bir şey olmaz.

İkinci sütun da aynı ısrarla okunmalıdır. Yanlış kesilen sekiz bin istek, kilitlenen doksan bir
hesap, reddedilen beş meşru dağıtım, döndürmede kesilen seksen yedi bin dört yüz yirmi yedi istek —
bunlar katmanın yan etkisi değil, fiyatıdır. Yanlış pozitifi yazılmayan bir çalışma zamanı savunması
ölçülmemiş sayılır.

Bir sonraki kurs — **M25/K05 Tespit, Müdahale ve Uyumluluk** — bu tablonun cevaplamadığı soruyu
alıyor. Katmanlar kuruldu ve neyi kaçırdıkları tek tek yazıldı; ama kaçırılanın kaçırıldığını
**hangi kaydın** göstereceği hiç sorulmadı. İhlal gerçekleştiğinde kimin ne yapacağı ve bütün bu
pratiğin bir denetimde nasıl kanıtlanacağı da sorulmadı. Ölçülmüş bir savunma, olay anında
okunabilir bir kayıt ve dışarıdan doğrulanabilir bir kanıt bırakmadığı sürece yalnızca kendi
tablosunda doğrudur.

