---
title: 'Bulut Yönetişimi, Güvenlik ve Maliyet'
source: 'https://academia.sh/tr/kurslar/bulut-yonetisimi'
language: tr
updated: '2026-08-17T04:38:57+00:00'
license: 'CC BY-SA 4.0'
lessons: 21
outcomes:
    - 'Politika yapısını izin, kaynak ve koşul cinsinden okur ve daraltır'
    - 'Şifreleme, denetim ve yalıtım kararlarını yüzey cinsinden ölçer'
    - 'Maliyeti sahipliğe bağlar ve sınırları ölçek planına katar'
---

# Bulut Yönetişimi, Güvenlik ve Maliyet

Kiralanan her şeyin kime ait olduğu ve faturanın kime çıktığı: kullanıcı, grup ve rol kimlik türleri, izin, kaynak ve koşul ifadelerinden oluşan politika yapısı, kimlik ve kaynak temelli politikaların iki değerlendirme yönü, geçici kimlik bilgisiyle rol üstlenme, uygulamaya kimlik verme, aşırı yetkinin tespiti ve daraltılması, hesap ve kuruluş yapısıyla iş yükü ayrımı, beklemede ve aktarımda şifreleme, sır saklama ve döndürme, denetim günlükleri, yapılandırma uyum denetimi, ağ yalıtımı ve özel uç noktalar, tehdit tespiti, uyumluluk gereksinimlerinin buluta yansıması, maliyet modeli, etiketleme ve maliyet dağıtımı, bütçe uyarıları, kaynak boyutlandırma, kota ve servis sınırları ile satıcı bağımlılığı.

## Kimlik ve Erişim

Kimin neye erişebildiğinin yazılması: kullanıcı, grup ve rol kimlik türlerinin ayrımı, izin, kaynak ve koşul ifadelerinden oluşan politika yapısı, kimlik temelli ile kaynak temelli politikaların iki yönden değerlendirilmesi, geçici kimlik bilgisiyle rol üstlenme, uygulamaya kimlik verme, kullanılmayan iznin tespiti ve en az yetkiye daraltma ile hesap ve kuruluş yapısıyla iş yükü ve ortam ayrımı.

### Kullanıcılar, Gruplar ve Roller

Source: https://academia.sh/tr/kurslar/bulut-yonetisimi/kullanicilar-gruplar-ve-roller

Beş ekibin kurgu ölçüm ağı üzerindeki ihtiyacı üç kimlik türüyle kurulur ve karşılaştırılır: doğrudan kullanıcıya, gruba ve role verilen iznin bağlantı sayısı, aşırı yetkisi, yeni üye maliyeti ve biri ayrıldığında geride kalan izni sayılır.

Dört kurs boyunca her katman kiralandı: makine, ağ, depo, işlev ve kenar. Her kiralama bir kararı
sağlayıcıya devretti ve karşılığında bir kalem geri geldi. Sorulmayan tek şey, bütün bu kiralamaları
kimin adına yaptığımızdı. Bu dersin sorusu şudur: kiralanan şeyin sahibi kim ve o sahiplik kaç
bağlantıyla yazılıyor.

Üç yol var: izin doğrudan kişiye, kişilerin toplandığı bir gruba ya da kişiden bağımsız bir role
yazılabilir. Üçü de aynı erişimi kurar; farkları sayıdadır — kaç bağlantı yazılıyor, kaç kişi
ihtiyacından fazlasını alıyor, yeni biri geldiğinde nereye dokunuluyor ve biri ayrıldığında geride
ne kalıyor.

- **BI1.** Model, kurgusal bölgesel ölçüm ağının beş ekibini, üç ortamını ve yedi kaynak türünü
  taşır. Gerçek bir hesap koşturulmuyor; ölçülen şey `node` ile kurulan modeldir.
- **BI2.** İhtiyaç tablosu elle yazıldı ve kişiden değil, (ekip, görev) çiftinden türetiliyor.
  Gerçekte ihtiyaç kişi başına ayrışır; burada görev başına tek olduğu için ölçülen aşırı yetki
  bir alt sınırdır.
- **BI3.** İzin bağlantısı bu derste yalnız (kim, ne) çiftidir; hangi işlemin yapılabildiği
  sayılmıyor. İşlem ayrımı sonraki derste politika belgesine girer.
- **BI4.** Uzun ömürlü kimlik bilgisi yaşları kendi ürettiğimiz sayı dizisinden geliyor; tohum
  `20260802` olarak koda yazılıdır. Dağılım kurgudur.
- **BI5.** Sınırlar kurgudur ve ders içinde tanımlıdır: hesap başına altmış grup, kırk rol,
  kimlik başına on politika belgesi.
- **BI6.** Ayrılan kişiler, otomasyonların hangi kimlikle koştuğu ve günlük işlem sayıları elle
  yazıldı.

Aynı biçimde bir yetki matrisi daha önce küme nesneleri üzerinde ölçülmüştü; buradaki nesne küme
nesnesi değil, kiralanan hesabın kaynağıdır ve oradaki sayılar buraya taşınmaz.

#### Ekip, Kaynak ve İhtiyaç

```js
// kimlik.mjs — kurgusal bolgesel olcum aginin kimlik modeli; gercek bir hesap degil, modeldir
export const ORTAM = ['gelistirme', 'hazirlik', 'uretim'];
export const EKIP_TUR = {                                // ekip -> dokundugu kaynak turleri
  toplama: ['kenar-dugum-grubu', 'olcum-deposu', 'islev-paketi', 'kayit-akisi'],
  dogrulama: ['makine-kumesi', 'islev-paketi', 'olcum-deposu', 'kayit-akisi'],
  faturalama: ['nesne-deposu', 'olcum-deposu', 'kayit-akisi'],
  saha: ['kenar-dugum-grubu', 'ag-yapilandirmasi', 'makine-kumesi'],
  pano: ['olcum-deposu', 'kayit-akisi'],
};
export const GOREV_ORTAM = {                             // gorev -> calistigi ortamlar
  gelistirici: ['gelistirme', 'hazirlik'], nobetci: ['hazirlik', 'uretim'],
  analist: ['uretim'], sorumlu: ORTAM,
};
const KADRO = {                                          // yirmi uc kisi; elle yazildi
  toplama: ['gelistirici', 'gelistirici', 'gelistirici', 'nobetci', 'analist', 'sorumlu'],
  dogrulama: ['gelistirici', 'gelistirici', 'nobetci', 'analist', 'sorumlu'],
  faturalama: ['gelistirici', 'gelistirici', 'analist', 'sorumlu'],
  saha: ['gelistirici', 'gelistirici', 'nobetci', 'nobetci', 'sorumlu'],
  pano: ['gelistirici', 'analist', 'sorumlu'],
};
export const KISI = Object.entries(KADRO).flatMap(([e, gs]) =>
  gs.map((g, i) => ({ ad: `${e}-${i + 1}`, ekip: e, gorev: g })));

export const capraz = (turler, ortamlar) =>              // (kim, ne) ciftinin "ne" tarafi
  new Set(turler.flatMap((t) => ortamlar.map((o) => `${t}@${o}`)));
export const ihtiyac = (k) => capraz(EKIP_TUR[k.ekip], GOREV_ORTAM[k.gorev]);
export const kabaGrup = (k) => capraz(EKIP_TUR[k.ekip], ORTAM);

export const OTOMASYON = [                               // ad, kimlik, kisisel mi, gunluk islem
  ['olcum-sikistirma', 'toplama-1', true, 2450], ['kenar-saglik-taramasi', 'saha-4', true, 720],
  ['gece-fatura-aktarimi', 'faturalama-1', true, 1840], ['pano-yenileme', 'pano-2', true, 96],
  ['surum-dagitimi', 'is-kimligi-1', false, 310], ['yedek-dogrulama', 'is-kimligi-2', false, 144],
].map(([ad, kimlik, kisisel, gunluk]) => ({ ad, kimlik, kisisel, gunluk }));
export const AYRILAN = ['toplama-1', 'saha-4', 'faturalama-3', 'pano-2'];
export const KISI_GUNLUK = 40;                           // kisi basina gunluk islem, kurgu
export const SINIR = { grup: 60, rol: 40, belge: 10 };   // kurgu sinirlar, ders icinde tanimli

export function* uretec(tohum) {                         // kendi uretecimiz; tohum gorunur
  let x = tohum % 2147483647;
  for (;;) { x = (x * 48271) % 2147483647; yield x; }
}
```

İhtiyaç iki kalemin çarpımıdır: ekip hangi kaynak türlerine dokunuyor, görev hangi ortamlarda
çalışıyor. Kaba grup aynı türleri taşır ama ortam ayrımını taşımaz — bir ekibe üye olmak, o ekibin
bütün kaynaklarına üç ortamda birden erişmek demektir.

#### Üç Kimlik Türü

```js
// kosum1.mjs — ayni ihtiyac uc kimlik turuyle kurulur ve baglanti sayisi karsilastirilir
import { KISI, EKIP_TUR, ORTAM, ihtiyac, kabaGrup } from './kimlik.mjs';

const rolAdi = (k) => `${k.ekip}-${k.gorev}`;
const ROL = new Map(), GRUP = new Map();
for (const k of KISI) {
  if (!ROL.has(rolAdi(k))) ROL.set(rolAdi(k), ihtiyac(k));
  if (!GRUP.has(k.ekip)) GRUP.set(k.ekip, kabaGrup(k));
}
const topla = (f) => KISI.reduce((a, k) => a + f(k), 0);
const kume = (m) => [...m.values()].reduce((a, s) => a + s.size, 0);
const yeni = { ekip: 'toplama', gorev: 'gelistirici' };  // yeni gelen bir ekip uyesi

const MODEL = [
  { ad: 'dogrudan kullanici', tanim: KISI.length, ustBag: 0, kaynakBag: topla((k) => ihtiyac(k).size),
    verilen: ihtiyac, yeniYazim: ihtiyac(yeni).size },
  { ad: 'grup', tanim: GRUP.size, ustBag: KISI.length, kaynakBag: kume(GRUP),
    verilen: kabaGrup, yeniYazim: 1 },
  { ad: 'rol', tanim: ROL.size, ustBag: KISI.length, kaynakBag: kume(ROL),
    verilen: ihtiyac, yeniYazim: 1 },
];
console.log(`${KISI.length} kisi, ${Object.keys(EKIP_TUR).length} ekip, ${ORTAM.length} ortam, ` +
  `${new Set(Object.values(EKIP_TUR).flat()).size} kaynak turu`);
console.log(`gorevden turetilen ihtiyac: ${topla((k) => ihtiyac(k).size)} (kim, ne) cifti\n`);
console.log('model               tanim  kimlik bagi  kaynak bagi  toplam  etkin izin  asiri  yeni uye');
for (const m of MODEL) {
  const etkin = topla((k) => m.verilen(k).size);
  const asiri = topla((k) => [...m.verilen(k)].filter((x) => !ihtiyac(k).has(x)).length);
  console.log(`${m.ad.padEnd(19)} ${String(m.tanim).padEnd(6)} ${String(m.ustBag).padEnd(12)} ` +
    `${String(m.kaynakBag).padEnd(12)} ${String(m.ustBag + m.kaynakBag).padEnd(7)} ` +
    `${String(etkin).padEnd(11)} ${String(asiri).padEnd(6)} ${m.yeniYazim}`);
}
```

```
23 kisi, 5 ekip, 3 ortam, 7 kaynak turu
gorevden turetilen ihtiyac: 157 (kim, ne) cifti

model               tanim  kimlik bagi  kaynak bagi  toplam  etkin izin  asiri  yeni uye
dogrudan kullanici  23     0            157          157     157         0      8
grup                5      23           48           71      231         74     1
rol                 17     23           115          138     157         0      1
```

Yirmi üç kişinin görevlerinden çıkan ihtiyaç yüz elli yedi çifttir ve modelden bağımsızdır; değişen,
o çiftlerin kaç bağlantıyla kurulduğudur. Doğrudan yazımda birebir: yüz elli yedi ihtiyaç, yüz elli
yedi bağlantı. Grup yetmiş bire iniyor — seksen altı bağlantı daha az — ama etkin izin iki yüz
otuz bire çıkıyor. Yetmiş dört izin, kimsenin istemediği hâlde açık duruyor.

Grubun ucuzluğu buradan geliyor: beş grup tanımı ortam ayrımını hiç yazmıyor ve ortamı yazmamanın
karşılığı her üyeye üç ortamı birden vermektir. Yalnız üretimde çalışan bir analist, ekibinin bütün
kaynak türlerine üç ortamda birden eriştiği için ihtiyacının tam üç katını alır.

Rol iki taraf arasında duruyor: on yedi tanım, yüz on beş kaynak bağı, yirmi üç kimlik bağı; toplam
yüz otuz sekiz. Doğrudan yazımdan on dokuz bağlantı ucuz, gruptan altmış yedi bağlantı pahalı, ama
aşırı yetkisi sıfır. Asıl kazancı son sütunda: yeni bir ekip üyesi geldiğinde doğrudan yazımda sekiz
ayrı bağlantı kurulur, grupta ve rolde bir tane. Doğrudan yazımın maliyeti kurulumda bir kez değil,
her gelişte yeniden ödenir.

#### Gelen, Giden ve Geride Kalan

```js
// kosum2.mjs — ayrilan kisi, geride kalan izin ve denetim kaydinda gorunen ozne
import { KISI, AYRILAN, OTOMASYON, KISI_GUNLUK, ihtiyac, kabaGrup, uretec } from './kimlik.mjs';

const bul = (ad) => KISI.find((k) => k.ad === ad);
const kisisel = OTOMASYON.filter((o) => o.kisisel);
const bagli = new Map(kisisel.map((o) => [o.kimlik, o]));

console.log('ayrilan       gorev        ihtiyac  kaba grup izni  uzerinde kosan otomasyon');
for (const ad of AYRILAN) {
  const k = bul(ad), o = bagli.get(ad);
  console.log(`${ad.padEnd(13)} ${k.gorev.padEnd(12)} ${String(ihtiyac(k).size).padEnd(8)} ` +
    `${String(kabaGrup(k).size).padEnd(15)} ${o ? `${o.ad} (${o.gunluk} islem/gun)` : '-'}`);
}
const kapanamaz = AYRILAN.filter((a) => bagli.has(a));
const duran = kapanamaz.reduce((a, x) => a + bagli.get(x).gunluk, 0);
const kalan = (f) => kapanamaz.reduce((a, x) => a + f(bul(x)).size, 0);
console.log(`\nkimligi kapatilamayan ${kapanamaz.length} kisi, ustunde ${duran} islem/gun kosuyor`);
console.log('model               silinecek baglanti  acik kalirsa canli izin  kapatilirsa duran islem/gun');
const satir = (ad, sil, izin) => console.log(`${ad.padEnd(19)} ${String(sil).padEnd(19)} ${String(izin).padEnd(24)} ${duran}`);
satir('dogrudan kullanici', AYRILAN.reduce((a, x) => a + ihtiyac(bul(x)).size, 0), kalan(ihtiyac));
satir('grup', AYRILAN.length, kalan(kabaGrup));
satir('rol', AYRILAN.length, kalan(ihtiyac));

// Uzun omurlu kimlik bilgisi: her kimligin bir anahtari var, kisisel anahtarlar kopyalanmis
const kimlikSayisi = KISI.length + OTOMASYON.filter((o) => !o.kisisel).length;
const g = uretec(20260802);
const yas = Array.from({ length: kimlikSayisi }, () => 45 + (g.next().value % 856));
console.log(`\nuzun omurlu anahtar: ${kimlikSayisi} kimlik + ${kisisel.length} kopya = ` +
  `${kimlikSayisi + kisisel.length} saklama yeri; en eski ${Math.max(...yas)} gun, ` +
  `365 gunden eski ${yas.filter((y) => y > 365).length}`);

// Denetim kaydi: hangi satir kimin adiyla yaziliyor
const otoToplam = OTOMASYON.reduce((a, o) => a + o.gunluk, 0);
const kisiselToplam = kisisel.reduce((a, o) => a + o.gunluk, 0);
const insanToplam = KISI.length * KISI_GUNLUK;
const adTasiyan = kisiselToplam + insanToplam;
console.log(`\ngunluk denetim kaydi ${otoToplam + insanToplam} satir: insan ${insanToplam}, otomasyon ${otoToplam}`);
console.log(`kisi adiyla yazilan ${adTasiyan} satirin ${kisiselToplam} tanesini otomasyon uretti ` +
  `(%${((100 * kisiselToplam) / adTasiyan).toFixed(1)})`);
console.log(`ayrilan ${kapanamaz.length} kisinin adi otuz gunde ${30 * duran} satirda gorunmeye devam eder`);
```

```
ayrilan       gorev        ihtiyac  kaba grup izni  uzerinde kosan otomasyon
toplama-1     gelistirici  8        12              olcum-sikistirma (2450 islem/gun)
saha-4        nobetci      6        9               kenar-saglik-taramasi (720 islem/gun)
faturalama-3  analist      3        9               -
pano-2        analist      2        6               pano-yenileme (96 islem/gun)

kimligi kapatilamayan 3 kisi, ustunde 3266 islem/gun kosuyor
model               silinecek baglanti  acik kalirsa canli izin  kapatilirsa duran islem/gun
dogrudan kullanici  19                  16                       3266
grup                4                   27                       3266
rol                 4                   16                       3266

uzun omurlu anahtar: 25 kimlik + 4 kopya = 29 saklama yeri; en eski 880 gun, 365 gunden eski 16

gunluk denetim kaydi 6480 satir: insan 920, otomasyon 5560
kisi adiyla yazilan 6026 satirin 5106 tanesini otomasyon uretti (%84.7)
ayrilan 3 kisinin adi otuz gunde 97980 satirda gorunmeye devam eder
```

Dört kişi ayrıldı. Doğrudan yazımda on dokuz bağlantı silinmeli, grupta ve rolde dört. İkinci sütun
beklenmedik olanı veriyor: dördünden üçünün kimliği kapatılamıyor, çünkü üzerinde otomasyon koşuyor.
Bu üç kişinin kimliği açık kaldığı sürece doğrudan yazımda on altı, grupta yirmi yedi izin canlı
kalır.

Üçüncü sütun kararın öbür yüzünü veriyor. Kimlikler kapatılırsa günde üç bin iki yüz altmış altı
meşru işlem durur ve bu işlerin hiçbiri ayrılan kişilerle ilgili değil. Üç modelin hiçbiri ikilemi
çözmüyor, üçünde de aynı sayı durur: kimlik türünü seçmek temizlik maliyetini ve geride kalan iznin
genişliğini değiştiriyor, ama bir insanın kimliğine bağlanmış makine işini yerinden oynatmıyor.

Anahtar satırı yüzeyin boyunu veriyor. Yirmi beş kimliğin her birinde bir uzun ömürlü anahtar var,
dördü otomasyon makinelerine kopyalanmış; toplam yirmi dokuz saklama yeri. On altı anahtar bir
yıldan eski, en eskisi sekiz yüz seksen günlük — bir anahtarın ömrü, sızdığı anda ne kadar süre
geçerli kalacağının üst sınırıdır.

Son üç satır "kim görebiliyor" sütununu kapatıyor. Kişi adı taşıyan altı bin yirmi altı denetim
satırının yüzde seksen dördünü bir insan üretmedi ve ayrılan üç kişinin adı otuz gün boyunca doksan
yedi bin dokuz yüz seksen satırda görünmeye devam eder. Denetim kaydı burada yanlış cevap vermiyor;
sorulan soruyu yanıtlıyor ve soru yanlış.

#### Sınır, Kalan ve Daraltmanın Bedeli

```js
// kosum3.mjs — sinir, kalan ve kaba grubu daraltmanin bedeli
import { KISI, EKIP_TUR, GOREV_ORTAM, ORTAM, SINIR, ihtiyac, kabaGrup, capraz } from './kimlik.mjs';

const rolAdi = (k) => `${k.ekip}-${k.gorev}`;
const rol = new Set(KISI.map(rolAdi));
const bolunmus = KISI.reduce((s, k) => {                 // her rol kendi ortamina bolunurse
  for (const o of GOREV_ORTAM[k.gorev]) s.add(`${rolAdi(k)}@${o}`);
  return s;
}, new Set());
const enCokBelge = Math.max(...KISI.map((k) => EKIP_TUR[k.ekip].length));
console.log(`kurgu sinirlar: hesap basina ${SINIR.grup} grup, ${SINIR.rol} rol; kimlik basina ${SINIR.belge} politika belgesi`);
console.log('tanim                     kullanilan  kalan');
const kal = (ad, k, s) => console.log(`${ad.padEnd(25)} ${String(k).padEnd(11)} ${s - k}`);
kal('grup (ekip basina bir)', new Set(KISI.map((k) => k.ekip)).size, SINIR.grup);
kal('rol (ekip x gorev)', rol.size, SINIR.rol);
kal('rol (ortama bolunmus)', bolunmus.size, SINIR.rol);
kal('belge (en genis kimlik)', enCokBelge, SINIR.belge);
const rolBasinaEkip = rol.size / new Set(KISI.map((k) => k.ekip)).size;
console.log(`ekip basina ${rolBasinaEkip} rol dusuyor; rol sinirina ` +
  `${Math.floor((SINIR.rol - rol.size) / rolBasinaEkip)} ekip kaldi, ortama bolunmus tanimda ` +
  `${Math.floor((SINIR.rol - bolunmus.size) / (bolunmus.size / 5))} ekip`);

// Kaba grubu en dar uyeye gore kismak: ortam kesisimi alinir
console.log('\nekip        uye  ortak ortam  uye basina kaba izin  uye basina dar izin  duran mesru izin');
let toplamDusen = 0, toplamKorunan = 0, toplamIhtiyac = 0;
for (const e of Object.keys(EKIP_TUR)) {
  const uye = KISI.filter((k) => k.ekip === e);
  const kesisim = ORTAM.filter((o) => uye.every((k) => GOREV_ORTAM[k.gorev].includes(o)));
  const dar = capraz(EKIP_TUR[e], kesisim);
  const ist = uye.reduce((a, k) => a + ihtiyac(k).size, 0);
  const kor = uye.reduce((a, k) => a + [...ihtiyac(k)].filter((x) => dar.has(x)).length, 0);
  toplamDusen += ist - kor; toplamKorunan += kor; toplamIhtiyac += ist;
  console.log(`${e.padEnd(11)} ${String(uye.length).padEnd(4)} ${String(kesisim.length || '-').padEnd(12)} ` +
    `${String(kabaGrup(uye[0]).size).padEnd(21)} ${String(dar.size).padEnd(20)} ${ist - kor}`);
}
console.log(`\ntoplam: kaba grup ${KISI.reduce((a, k) => a + kabaGrup(k).size, 0)} izin veriyor, ` +
  `daraltilmis grup ${toplamKorunan}; ${toplamIhtiyac} mesru izinden ${toplamDusen} tanesi dusuyor ` +
  `(%${((100 * toplamDusen) / toplamIhtiyac).toFixed(1)})`);
```

```
kurgu sinirlar: hesap basina 60 grup, 40 rol; kimlik basina 10 politika belgesi
tanim                     kullanilan  kalan
grup (ekip basina bir)    5           55
rol (ekip x gorev)        17          23
rol (ortama bolunmus)     35          5
belge (en genis kimlik)   4           6
ekip basina 3.4 rol dusuyor; rol sinirina 6 ekip kaldi, ortama bolunmus tanimda 0 ekip

ekip        uye  ortak ortam  uye basina kaba izin  uye basina dar izin  duran mesru izin
toplama     6    -            12                    0                    48
dogrulama   5    -            12                    0                    40
faturalama  4    -            9                     0                    24
saha        5    1            9                     3                    18
pano        3    -            6                     0                    12

toplam: kaba grup 231 izin veriyor, daraltilmis grup 15; 157 mesru izinden 142 tanesi dusuyor (%90.4)
```

Sınır tablosu iki ayrı hikâye anlatıyor. Grup tarafında sıkıntı yok: beş grup, elli beş yer boş.
Rol tarafında on yedi rol var ve yirmi üç yer kaldı; ekip başına üç virgül dört rol düştüğüne göre
altı ekip daha eklenebilir. Rolleri ortam başına bölmek — üretim yetkisini ayrı bir role koymak —
tanım sayısını otuz beşe çıkarıyor ve kalan yeri beşe düşürüyor: tek başına makul görünen bir
daraltma, hesabı büyümeye kapatıyor.

Alt tablo daraltmanın öbür bedelini sayıyor. Kaba grubun aşırı yetkisini gruba dokunarak kapatmak,
grubu en dar üyesine göre kısmak demektir; üyelerin ortak ortamı alınır. Beş ekibin dördünde ortak
ortam yok — bir geliştirici geliştirme ve hazırlıkta, bir analist yalnız üretimde çalıştığı için
kesişim boş kalıyor. Kaba grubun verdiği iki yüz otuz bir izin on beşe düşüyor, ama düşenlerin yüz
kırk ikisi meşru ihtiyaçtı: yüzde doksan.

Yetmiş dört aşırı izin grup tanımına dokunarak temizlenemez. Aşırı yetki grubun içinde değil, kaba
oluşundadır; kapatmanın tek yolu grubu bölmektir ve grubu görev ekseninde böldüğümüzde elde
ettiğimiz şey zaten rol modelidir. Grup ucuzdur çünkü ayrım yapmaz, rol pahalıdır çünkü ayrımı
yazar, doğrudan yazım ise aynı ayrımı her kişi için yeniden yazar.

#### Özet

- Yirmi üç kişinin görevlerinden çıkan 157 (kim, ne) çiftini doğrudan yazım 157, kaba grup 71, rol
  138 bağlantıyla kurar; yeni bir üye doğrudan yazımda 8, grupta ve rolde 1 bağlantı ister.
- Grubun 86 bağlantılık ucuzluğunun karşılığı 74 aşırı izindir: etkin izin 157'den 231'e çıkar,
  çünkü grup ortam ayrımını hiç yazmaz.
- Ayrılan dört kişiden üçünün kimliği kapatılamıyor çünkü üstünde günde 3266 işlemlik otomasyon
  koşuyor; kimlik açık kalırsa grupta 27, doğrudan yazımda ve rolde 16 izin canlı kalır.
- Denetim kaydında kişi adı taşıyan 6026 satırın 5106'sı bir insan tarafından üretilmedi; 25
  kimliğin uzun ömürlü anahtarı 29 yerde duruyor ve 16 tanesi bir yıldan eski.
- Kaba grubu en dar üyesine göre kısmak aşırı yetkiyi kapatır ama 157 meşru izinden 142'sini
  düşürür; aşırı yetki grubun içeriğinde değil, kaba oluşundadır.

#### Sonraki Adım

Bu dersin bağlantıları yalnız (kim, ne) çiftini taşıyor: toplama ekibinin ölçüm deposuna erişimi
var. Hangi erişim olduğu yazılmadı — okumak mı, yazmak mı, deponun kendisini kaldırmak mı. O küme
yazılmadığı sürece "erişimi var" cümlesi bir şey ölçmüyor. Sonraki ders bağlantının içini açar:
etki, işlem, kaynak deseni ve koşul. Aynı niyetin farklı yazımlarının gerçekte kaç işlemi kapsadığı
sayılır, joker karakterin genişlettiği kapsam kalem kalem çıkarılır ve açık retin neden her zaman
kazandığı gösterilir.

### Politika Yapısı

Source: https://academia.sh/tr/kurslar/bulut-yonetisimi/politika-yapisi

Bir politika belgesi değerlendiricisi yazılır ve aynı niyet dört ayrı yazımla ifade edilerek gerçekte kaç işlemi kapsadığı sayılır: joker karakterin açtığı kapsam kalem kalem çıkarılır, açık retin her zaman kazandığı gösterilir ve koşul ifadesinin kapsamı ne kadar daralttığı ölçülür.

Önceki dersin bağlantıları "toplama ekibinin ölçüm deposuna erişimi var" diyordu ve hangi erişim
olduğunu söylemiyordu. Bir bağlantı gerçekte bir işlem kümesini temsil eder, o küme yazılmadıkça
bağlantı sayısı bir şey ölçmez. Politika belgesi bu kümeyi dört alanla yazar: **etki** (izin ya da
ret), **işlem**, **kaynak** ve **koşul**. Bu dersin ölçüsü, yazımın gerçekte neyi kapsadığıdır.

Aradaki fark yazan kişinin niyetiyle değerlendiricinin okuduğu şey arasındadır. Niyet dar olabilir;
yazım geniş kalabilir ve fark hiçbir yerde uyarı üretmez, çünkü fazladan verilen izinlerin
kullanılmaması bir hata değildir. Bu yüzden fark ancak sayılarak görülür.

- **BI7.** Model kurgusal bölgesel ölçüm ağının yedi kaynak türünü, kırk dört işlem türünü ve kırk
  iki kaynak örneğini taşır. Gerçek bir servis koşturulmuyor; ölçülen şey `node` ile kurulan
  değerlendiricidir.
- **BI8.** Politika belgesi dört alan taşır. Alan kümesi ders içinde tanımlıdır; daha zengin
  yazımlarda alan sayısı artar, ölçüm biçimi değişmez.
- **BI9.** Joker karakter yalnız `*` ve eşleşme kuralı kod içinde tanımlıdır. Desen dili büyüdükçe
  kapsam da büyür; buradaki sayılar bu tek karakterin açtığı kapsamdır.
- **BI10.** Yıkıcı işlem kümesi elle işaretlendi: silme fiilleri ile saklama, erişim ve ortam
  ayarını değiştiren fiiller. İşaretleme tartışmaya açıktır, sayılan değer ona bağlıdır.
- **BI11.** Bağlam dört profile indirgendi — iç ve dış ağ, taze ve eski doğrulama. Koşul ölçümü bu
  dört profil üzerinden okunur.
- **BI12.** Belge sırası karıştırması kendi ürettiğimiz diziyle yapıldı; tohum `31071923` koda
  yazılıdır ve yüz yirmi sıra denendi.

#### Değerlendirici

```js
// politika.mjs — politika belgesi degerlendiricisi; gercek bir servis degil, modeldir
export const TUR_FIIL = {                                // kaynak turu -> uzerinde tanimli fiiller
  'makine-kumesi': ['listele', 'oku', 'olustur', 'baslat', 'durdur', 'boyutlandir', 'sil', 'etiket-yaz'],
  'ag-yapilandirmasi': ['listele', 'oku', 'kural-ekle', 'kural-sil', 'yol-yaz', 'uc-nokta-ac'],
  'nesne-deposu': ['listele', 'oku', 'yaz', 'sil', 'surum-oku', 'yasam-dongusu-yaz', 'erisim-yaz'],
  'olcum-deposu': ['listele', 'oku', 'yaz', 'sil', 'sorgula', 'saklama-yaz'],
  'islev-paketi': ['listele', 'oku', 'yayinla', 'calistir', 'surum-sil', 'ortam-degiskeni-yaz'],
  'kenar-dugum-grubu': ['listele', 'oku', 'kayit-ekle', 'kayit-sil', 'yazilim-guncelle'],
  'kayit-akisi': ['listele', 'oku', 'yaz', 'tuket', 'saklama-yaz', 'sil'],
};
export const ORTAM = ['gelistirme', 'hazirlik', 'uretim'];
const ORNEK = ['bolge-1', 'bolge-2'];                    // her tur ve ortamda iki ornek
export const YIKICI = new Set(['sil', 'kural-sil', 'kayit-sil', 'surum-sil', 'erisim-yaz',
  'ortam-degiskeni-yaz', 'saklama-yaz', 'yasam-dongusu-yaz', 'durdur']);

export const ISLEM = Object.entries(TUR_FIIL).flatMap(([t, fs]) => fs.map((f) => `${t}:${f}`));
export const KAYNAK = Object.keys(TUR_FIIL).flatMap((t) =>
  ORTAM.flatMap((o) => ORNEK.map((a) => ({ ad: `${t}/${o}/${a}`, tur: t, ortam: o }))));
export const CIFT = ISLEM.flatMap((i) =>                 // (islem, kaynak) evreni
  KAYNAK.filter((k) => k.tur === i.split(':')[0]).map((k) => ({ islem: i, kaynak: k })));
export const BAGLAM = [                                  // istegin baglami; elle yazildi
  { ad: 'ic-taze', ag: 'ic', dogrulamaYasi: 5 }, { ad: 'ic-eski', ag: 'ic', dogrulamaYasi: 240 },
  { ad: 'dis-taze', ag: 'dis', dogrulamaYasi: 5 }, { ad: 'dis-eski', ag: 'dis', dogrulamaYasi: 240 },
];
export const ISTEK = CIFT.flatMap((c) => BAGLAM.map((b) => ({ ...c, baglam: b })));

export const desen = (p, s) =>                           // joker karakter yalnizca *
  new RegExp(`^${p.split('*').map((x) => x.replace(/[.+?^${}()|[\]\\]/g, '\\$&')).join('.*')}$`).test(s);
const kosulTut = (k, i) => (k.ag === undefined || k.ag === i.baglam.ag) &&
  (k.yasEnCok === undefined || i.baglam.dogrulamaYasi <= k.yasEnCok) &&
  (k.ortam === undefined || k.ortam === i.kaynak.ortam);
export const uyar = (b, i) => b.islem.some((p) => desen(p, i.islem)) &&
  b.kaynak.some((p) => desen(p, i.kaynak.ad)) && (!b.kosul || kosulTut(b.kosul, i));

// Kural: acik ret her zaman kazanir; belge sirasi sonucu degistirmez
export function degerlendir(belgeler, istek) {
  const uyan = belgeler.filter((b) => uyar(b, istek));
  if (uyan.some((b) => b.etki === 'ret')) return 'acik-ret';
  return uyan.some((b) => b.etki === 'izin') ? 'izin' : 'ortuk-ret';
}
// Karsilastirma icin: ilk eslesen kazanir
export function ilkEslesen(belgeler, istek) {
  for (const b of belgeler) if (uyar(b, istek)) return b.etki === 'ret' ? 'acik-ret' : 'izin';
  return 'ortuk-ret';
}
export function* uretec(tohum) {                         // kendi uretecimiz; tohum gorunur
  let x = tohum % 2147483647;
  for (;;) { x = (x * 48271) % 2147483647; yield x; }
}
```

Değerlendirici üç sonuç üretiyor. **İzin**, eşleşen bir izin belgesi var ve eşleşen ret belgesi yok
demektir. **Açık ret**, bir ret belgesinin eşleşmesidir ve eşleşen izin belgesi sayısına
bakılmaksızın kazanır. **Örtük ret**, hiçbir belgenin eşleşmemesidir — yazılmamış olan yasaktır.
İkinci değerlendirici karşılaştırma için duruyor: ilk eşleşen belgenin kazandığı bir kural.

#### Aynı Niyetin Dört Yazımı

```js
// kosum1.mjs — ayni niyet dort yazimla ifade edilir ve gercekte kac islemi kapsadigi sayilir
import { ISLEM, KAYNAK, CIFT, YIKICI, uyar, BAGLAM } from './politika.mjs';

const niyet = (c) => ['oku', 'listele', 'sorgula'].includes(c.islem.split(':')[1]) &&
  c.kaynak.tur === 'olcum-deposu' && c.kaynak.ortam === 'uretim';
const YAZIM = [
  ['A  islem *, kaynak *', { etki: 'izin', islem: ['*'], kaynak: ['*'] }],
  ['B  islem olcum-deposu:*', { etki: 'izin', islem: ['olcum-deposu:*'], kaynak: ['*'] }],
  ['C  islem *:oku *:listele *:sorgula', { etki: 'izin', islem: ['*:oku', '*:listele', '*:sorgula'],
    kaynak: ['olcum-deposu/*'] }],
  ['D  islem ve kaynak tam yazilmis', { etki: 'izin',
    islem: ['olcum-deposu:oku', 'olcum-deposu:listele', 'olcum-deposu:sorgula'],
    kaynak: ['olcum-deposu/uretim/*'] }],
];
console.log(`islem turu ${ISLEM.length}, kaynak ${KAYNAK.length}, (islem, kaynak) evreni ${CIFT.length}`);
console.log(`baglam ${BAGLAM.length}; niyetin gerektirdigi cift ${CIFT.filter(niyet).length}\n`);
console.log('yazim                              kapsanan  fazla  yikici islem  dokunulan tur');
for (const [ad, b] of YAZIM) {
  const k = CIFT.filter((c) => uyar(b, { ...c, baglam: BAGLAM[0] }));
  const fazla = k.filter((c) => !niyet(c)).length;
  const yikici = k.filter((c) => YIKICI.has(c.islem.split(':')[1])).length;
  const tur = new Set(k.map((c) => c.kaynak.tur)).size;
  console.log(`${ad.padEnd(34)} ${String(k.length).padEnd(9)} ${String(fazla).padEnd(6)} ` +
    `${String(yikici).padEnd(13)} ${tur}`);
}
```

```
islem turu 44, kaynak 42, (islem, kaynak) evreni 264
baglam 4; niyetin gerektirdigi cift 6

yazim                              kapsanan  fazla  yikici islem  dokunulan tur
A  islem *, kaynak *               264       258    78            7
B  islem olcum-deposu:*            36        30     12            1
C  islem *:oku *:listele *:sorgula 18        12     0             1
D  islem ve kaynak tam yazilmis    6         0      0             1
```

Dördü de aynı niyeti karşılıyor: toplama ekibi üretimdeki ölçüm depolarını okuyabilsin. Niyetin
gerektirdiği çift altı tanedir. A yazımı iki yüz altmış dördünü açıyor — evrenin tamamını — ve
fazladan verilen iki yüz elli sekiz çiftin yetmiş sekizi yıkıcı bir fiile denk geliyor. Yazan kişi
bunu istemedi; yalnızca alanları doldurmadı.

B ile C arasındaki fark hangi alanın gevşetildiğini gösteriyor. B işlem alanını açık bırakıyor ve
otuz altı çift kapsıyor; on ikisi yıkıcı, çünkü ölçüm deposunun altı fiilinden ikisi silme ve
saklama ayarı yazma. C işlem alanını yazıp kaynak alanını gevşetiyor: on sekiz çift, hiç yıkıcı
yok, ama üç ortamın hepsi içeride. C ile D arasındaki tek fark kaynak deseninin bir basamağıdır ve
kapsam üç kat değişiyor. Sayı şunu söylüyor: işlem alanını gevşetmek yıkıcı fiil getirir, kaynak
alanını gevşetmek ortam sınırını kaldırır. İkisi ayrı riskler ve ikisi ayrı yazılır.

#### Joker Karakterin Açtığı Kapsam

```js
// kosum2.mjs — joker karakterin actigi kapsam kalem kalem cikarilir
import { ISLEM, KAYNAK, CIFT, YIKICI, desen } from './politika.mjs';

const cift = (ip, kp) => CIFT.filter((c) => desen(ip, c.islem) && desen(kp, c.kaynak.ad)).length;
console.log('islem deseni      eslesen islem turu  bunlarin yikicisi  her kaynakla cift');
for (const p of ['*', 'olcum-deposu:*', '*:oku', '*:sil', '*:*-yaz', 'olcum-deposu:oku']) {
  const e = ISLEM.filter((i) => desen(p, i));
  console.log(`${p.padEnd(17)} ${String(e.length).padEnd(14)} ` +
    `${String(e.filter((i) => YIKICI.has(i.split(':')[1])).length).padEnd(18)} ${cift(p, '*')}`);
}
console.log('\nkaynak deseni          eslesen kaynak  ortam  islem deseni olcum-deposu:* ile cift');
for (const p of ['*', '*/uretim/*', 'olcum-deposu/*', 'olcum-deposu/uretim/*']) {
  const e = KAYNAK.filter((k) => desen(p, k.ad));
  console.log(`${p.padEnd(22)} ${String(e.length).padEnd(15)} ${String(new Set(e.map((k) => k.ortam)).size).padEnd(6)} ` +
    `${cift('olcum-deposu:*', p)}`);
}
console.log('\n"olcum-deposu:*" kalem kalem:');
console.log('  ' + ISLEM.filter((i) => desen('olcum-deposu:*', i))
  .map((i) => `${i.split(':')[1]}${YIKICI.has(i.split(':')[1]) ? ' (yikici)' : ''}`).join(', '));
const tam = cift('olcum-deposu:oku', 'olcum-deposu/uretim/*');
console.log('\ntam yazima gore kat:');
for (const [ip, kp] of [['olcum-deposu:oku', 'olcum-deposu/uretim/*'], ['olcum-deposu:oku', 'olcum-deposu/*'],
  ['olcum-deposu:*', 'olcum-deposu/uretim/*'], ['olcum-deposu:*', 'olcum-deposu/*'], ['*', '*']]) {
  console.log(`  ${ip.padEnd(17)} ${kp.padEnd(22)} cift ${String(cift(ip, kp)).padEnd(4)} kat ${cift(ip, kp) / tam}`);
}
```

```
islem deseni      eslesen islem turu  bunlarin yikicisi  her kaynakla cift
*                 44             13                 264
olcum-deposu:*    6              2                  36
*:oku             7              0                  42
*:sil             4              4                  24
*:*-yaz           7              5                  42
olcum-deposu:oku  1              0                  6

kaynak deseni          eslesen kaynak  ortam  islem deseni olcum-deposu:* ile cift
*                      42              3      36
*/uretim/*             14              1      12
olcum-deposu/*         6               3      36
olcum-deposu/uretim/*  2               1      12

"olcum-deposu:*" kalem kalem:
  listele, oku, yaz, sil (yikici), sorgula, saklama-yaz (yikici)

tam yazima gore kat:
  olcum-deposu:oku  olcum-deposu/uretim/*  cift 2    kat 1
  olcum-deposu:oku  olcum-deposu/*         cift 6    kat 3
  olcum-deposu:*    olcum-deposu/uretim/*  cift 12   kat 6
  olcum-deposu:*    olcum-deposu/*         cift 36   kat 18
  *                 *                      cift 264  kat 132
```

Tek başına yazılan bir yıldız kırk dört işlem türüne denk geliyor ve bunların on üçü yıkıcı.
`olcum-deposu:*` altı fiil demek ve kalem kalem açılınca ikisinin silme ile saklama ayarı yazma
olduğu görünüyor — ikisi de "okuma izni veriyorum" diyen birinin aklında olmayan fiiller. Desen
metni beş karakter uzunluğunda, açtığı kapsam altı kat.

Son tablo iki alanın çarpım gibi davrandığını gösteriyor. Tam yazılmış bir izin iki çift kapsıyor.
Kaynak desenindeki ortam basamağını yıldıza çevirmek üç kat, işlem desenindeki fiili yıldıza
çevirmek altı kat, ikisi birden on sekiz kat açıyor. Her iki alanı da tek yıldıza indirmek yüz otuz
iki kat. Bu, bir politika belgesini okurken kaç yıldız olduğunu saymanın neden yeterli olmadığını
söylüyor: yıldızın hangi basamakta durduğu, kaç tane olduğundan daha belirleyici.

#### Açık Ret ve Koşul

```js
// kosum3.mjs — acik ret her zaman kazanir; kosul kapsami ne kadar daraltiyor
import { ISTEK, degerlendir, ilkEslesen, uyar, uretec } from './politika.mjs';

const BELGE = [
  { ad: 'p1-okuma', etki: 'izin', islem: ['*:oku', '*:listele', '*:sorgula'], kaynak: ['*'] },
  { ad: 'p2-yazma', etki: 'izin', islem: ['olcum-deposu:yaz', 'kayit-akisi:yaz'],
    kaynak: ['*/hazirlik/*', '*/gelistirme/*'] },
  { ad: 'p3-bakim', etki: 'izin', islem: ['*'], kaynak: ['makine-kumesi/*'] },
  { ad: 'p4-silme-yasak', etki: 'ret', islem: ['*:sil', '*:kural-sil', '*:kayit-sil', '*:surum-sil'],
    kaynak: ['*/uretim/*'] },
  { ad: 'p5-dis-ag-yasak', etki: 'ret', islem: ['*'], kaynak: ['*/uretim/*'], kosul: { ag: 'dis' } },
];
const say = (bs, f = degerlendir) => ISTEK.reduce((a, i) => (a[f(bs, i)]++, a),
  { izin: 0, 'acik-ret': 0, 'ortuk-ret': 0 });
console.log(`istek evreni ${ISTEK.length} = 264 (islem, kaynak) x 4 baglam\n`);
console.log('belge kumesi                 izin   acik ret  ortuk ret');
const temel = say(BELGE);
console.log(`${'bes belge (tam kume)'.padEnd(28)} ${String(temel.izin).padEnd(6)} ` +
  `${String(temel['acik-ret']).padEnd(9)} ${temel['ortuk-ret']}`);
const cakisan = ISTEK.filter((i) => BELGE.some((b) => b.etki === 'izin' && uyar(b, i)) &&
  BELGE.some((b) => b.etki === 'ret' && uyar(b, i))).length;
console.log(`hem izin hem ret belgesine uyan istek: ${cakisan} — hepsinde ret kazaniyor`);

console.log('\nbelge cikarilinca                izin   acik ret  ortuk ret');
for (const ad of ['p4-silme-yasak', 'p5-dis-ag-yasak']) {
  const s = say(BELGE.filter((b) => b.ad !== ad));
  console.log(`${(ad + ' yok').padEnd(32)} ${String(s.izin).padEnd(6)} ${String(s['acik-ret']).padEnd(9)} ${s['ortuk-ret']}`);
}
const dar = BELGE.map((b) => (b.ad === 'p1-okuma' ? { ...b, kosul: { yasEnCok: 60 } } : b));
const duran = ISTEK.filter((i) => degerlendir(BELGE, i) === 'izin' && degerlendir(dar, i) !== 'izin');
console.log(`p1'e "dogrulama yasi en cok 60 dk" kosulu eklenince izin ${say(dar).izin}; duran ${duran.length} istek, ` +
  `fiilleri: ${[...new Set(duran.map((i) => i.islem.split(':')[1]))].join(', ')}`);

const g = uretec(31071923);                              // belge sirasi kendi uretecimizle karistirilir
const karistir = (a) => { const c = [...a];
  for (let i = c.length - 1; i > 0; i--) { const j = g.next().value % (i + 1); [c[i], c[j]] = [c[j], c[i]]; }
  return c; };
const temelIlk = ISTEK.map((i) => ilkEslesen(BELGE, i));
let farkA = 0, farkB = 0;
for (let n = 0; n < 120; n++) {
  const s = karistir(BELGE);
  ISTEK.forEach((i, x) => {
    if (degerlendir(s, i) !== degerlendir(BELGE, i)) farkA++;
    if (ilkEslesen(s, i) !== temelIlk[x]) farkB++;
  });
}
console.log(`\n120 karisik sirada, ${ISTEK.length} istek:`);
console.log(`  acik ret kazanir kurali   sonucu degisen ${farkA}`);
console.log(`  ilk eslesen kazanir       sonucu degisen ${farkB}`);
```

```
istek evreni 1056 = 264 (islem, kaynak) x 4 baglam

belge kumesi                 izin   acik ret  ortuk ret
bes belge (tam kume)         448    204       404
hem izin hem ret belgesine uyan istek: 88 — hepsinde ret kazaniyor

belge cikarilinca                izin   acik ret  ortuk ret
p4-silme-yasak yok               452    176       428
p5-dis-ag-yasak yok              528    56        472
p1'e "dogrulama yasi en cok 60 dk" kosulu eklenince izin 318; duran 130 istek, fiilleri: listele, oku, sorgula

120 karisik sirada, 1056 istek:
  acik ret kazanir kurali   sonucu degisen 0
  ilk eslesen kazanir       sonucu degisen 5588
```

Bin elli altı isteğin dört yüz kırk sekizi izinli, iki yüz dördü açıkça reddedilmiş, dört yüz dördü
hiçbir belgeye uymadığı için örtük olarak reddedilmiş. Seksen sekiz istek hem bir izin hem bir ret
belgesine uyuyor ve hepsinde ret kazanıyor. Açık retin anlamı budur: izin belgesi kaç tane olursa
olsun, kaç yıldız taşırsa taşısın, tek bir ret belgesi onu geçersiz kılar.

Belge çıkarma satırları açık retin ne kadarının gerçekten iş gördüğünü ayırıyor. `p4` kaldırılınca
açık ret iki yüz dörtten yüz yetmiş altıya iniyor — yirmi sekiz istek — ama izin yalnız dört
artıyor. Kalan yirmi dört istek zaten örtük rete düşüyordu, çünkü onları açan bir izin belgesi
yoktu. `p4` yirmi sekiz isteği reddediyor görünse de gerçekte dört isteği durduruyor. `p5` için
tablo başka türlü: yüz kırk sekiz açık retin seksen tanesi kaldırıldığında izne dönüşüyor. İki ret
belgesi aynı görünüyor, taşıdıkları yük beş kat farklı.

Koşul satırı daraltmanın bedelini veriyor. `p1`'e doğrulama yaşı koşulu eklenince izinli istek dört
yüz kırk sekizden üç yüz on sekize iniyor; duran yüz otuz isteğin fiilleri okuma, listeleme ve
sorgulama — hiçbiri yıkıcı değil. Koşul yıkıcı bir işlemi durdurmadı; eski doğrulamayla gelen meşru
okumaları durdurdu. Koşulun kazancı başka bir sütunda aranmalı, çünkü bu sütunda yalnız maliyeti
görünüyor.

Son iki satır sıranın önemini ölçüyor. Yüz yirmi karışık sırada bin elli altı istek yeniden
değerlendirildi: açık ret kuralında sonucu değişen istek sıfır. İlk eşleşen kuralında beş bin beş
yüz seksen sekiz — yüz yirmi altı bin yedi yüz yirmi değerlendirmenin yaklaşık yüzde dördü. Açık
retin bir üstünlüğü de buradadır: sonuç belgelerin yazılma sırasına bağlı değildir, dolayısıyla iki
ekip birbirinden habersiz belge yazdığında sonuç ikisinin de öngörebileceği şeydir.

#### Özet

- 44 işlem türü ve 42 kaynak 264 (işlem, kaynak) çifti kuruyor; altı çiftlik bir niyet dört ayrı
  yazımla 264, 36, 18 ve 6 çift kapsıyor.
- İşlem alanını gevşetmek yıkıcı fiil getiriyor (B yazımında 12 çift), kaynak alanını gevşetmek
  ortam sınırını kaldırıyor (C ile D arasında üç kat); ikisi ayrı risktir.
- Yıldızın hangi basamakta durduğu sayısından belirleyici: ortam basamağı üç kat, fiil basamağı
  altı kat, ikisi birden 18 kat, tek yıldız 132 kat açıyor.
- 88 istek hem izin hem ret belgesine uyuyor ve hepsinde ret kazanıyor; 120 karışık sırada açık ret
  kuralında değişen sonuç 0, ilk eşleşen kuralında 5588.
- İki ret belgesi aynı görünse de yükü farklı: `p4` 28 isteği reddediyor ama yalnız 4'ünü
  durduruyor, `p5`'in 148 retinin 80'i gerçek engeldir.
- `p1`'e eklenen koşul izinli isteği 448'den 318'e indiriyor; duran 130 isteğin hepsi meşru okuma,
  hiçbiri yıkıcı değil.

#### Sonraki Adım

Bu dersin beş belgesi tek yerde duruyordu ve hepsi bir özneye bağlıydı. Kaynağın kendisi de politika
taşıyabilir: deponun üstüne yazılan bir belge, ona kimin erişebileceğini kaynak tarafından söyler.
O zaman bir istek iki ayrı belge kümesinden geçer ve sonuç ikisinin kesişimidir. Sonraki ders bu iki
yönü birlikte değerlendirir: kaç istek yalnız birinde izinli olduğu için reddediliyor, hesap sınırı
aşıldığında kaynak temelli politikanın neden zorunlu hâle geldiği ve bir erişimin neden
reddedildiğini bulmanın kaç belgeye bakmayı gerektirdiği sayılır.

### Kimlik ve Kaynak Temelli Politikalar

Source: https://academia.sh/tr/kurslar/bulut-yonetisimi/kimlik-ve-kaynak-temelli-politikalar

Aynı erişim isteği iki ayrı politika kümesinden geçirilir ve kesişimi hesaplanır: kaç istek yalnız bir yönde izinli olduğu için reddediliyor, hesap sınırı aşıldığında kaynak temelli politikanın neden zorunlu olduğu ve bir retin nedenini bulmanın kaç belge okumayı gerektirdiği sayılır.

Önceki dersin beş belgesi tek bir yerde duruyordu ve hepsi bir özneye bağlıydı. Kaynağın kendisi de
politika taşıyabilir: deponun üstüne yazılan bir belge, ona kimin erişebileceğini kaynak tarafından
söyler. İki yön aynı soruya iki ayrı yerden cevap verir — biri "bu özne nereye erişebilir", öbürü
"bu kaynağa kimler erişebilir" — ve bir istek ikisinden birden geçer.

İki yönün var olma nedeni farklıdır. Kimlik temelli belge özneyi yöneten ekibin elindedir, kaynak
temelli belge kaynağı işletenin. Aynı hesabın içinde ikisi birbirinin yerine geçebilir, hesap sınırı
aşıldığında geçemez. Bu dersin ölçüsü kesişimin boyu ve o kesişimi okumanın maliyetidir.

- **BI13.** Model sekiz özne, beş fiil, yirmi bir kaynak ve üç hesap taşır. Gerçek bir hesap
  koşturulmuyor; ölçülen şey `node` ile kurulan modeldir.
- **BI14.** Değerlendirme kuralı ders içinde tanımlıdır: aynı hesapta bir yönün izin vermesi
  yeterli, hesap sınırı aşıldığında iki yönün de izin vermesi gerekli, açık ret her iki yönde de
  kazanır.
- **BI15.** On bir kimlik temelli, altı kaynak temelli belge elle yazıldı. Sayılar bu kümeye
  bağlıdır; ölçüm biçimi değildir.
- **BI16.** Otuz günlük kullanım izi elle yazıldı ve ortam ayrımı taşımaz — izde görünen bir üçlü
  üç ortamda da meşru sayılır. Kullanılmayan izin sayısı bu yüzden bir alt sınırdır.
- **BI17.** "Bakılacak belge" sayısı özneye bağlı belge, kaynağa uyan belge ve hesap kuralının
  toplamıdır. Gerçekte devralınan belgeler sayıyı büyütür; ölçülen değer alt sınırdır.
- **BI18.** Kuruluş yapısı üç hesaba indirgendi; hesapların birbirini kapsaması modele girmedi.

#### İki Yön

```js
// yon.mjs — iki degerlendirme yonu; gercek bir hesap degil, node ile kurulan modeldir
export const FIIL = ['oku', 'listele', 'yaz', 'sil', 'yapilandir'];
const ORTAM = ['gelistirme', 'hazirlik', 'uretim'];
export const TUR_HESAP = {                               // kaynak turu hangi hesapta duruyor
  'olcum-deposu': 'hesap-olcum', 'kayit-akisi': 'hesap-olcum', 'kenar-dugum-grubu': 'hesap-olcum',
  'nesne-deposu': 'hesap-analitik', 'islev-paketi': 'hesap-analitik',
  'makine-kumesi': 'hesap-ortak', 'ag-yapilandirmasi': 'hesap-ortak',
};
export const OZNE_HESAP = {
  'toplama-hizmeti': 'hesap-olcum', 'dogrulama-hizmeti': 'hesap-olcum', 'kenar-toplayici': 'hesap-olcum',
  'analitik-is': 'hesap-analitik', 'pano-okuyucu': 'hesap-analitik',
  'faturalama-is': 'hesap-ortak', 'saha-bakim': 'hesap-ortak', 'yedek-dogrulama': 'hesap-ortak',
};
export const OZNE = Object.keys(OZNE_HESAP);
export const KAYNAK = Object.keys(TUR_HESAP).flatMap((t) =>
  ORTAM.map((o) => ({ ad: `${t}/${o}`, tur: t, hesap: TUR_HESAP[t] })));
export const ISTEK = OZNE.flatMap((o) => FIIL.flatMap((f) => KAYNAK.map((k) => ({ ozne: o, fiil: f, kaynak: k }))));

const OKU = ['oku', 'listele'], OKU_YAZ = ['oku', 'listele', 'yaz'];
const K = (ad, ozne, etki, fiil, kaynak) => ({ ad, ozne, etki, fiil, kaynak });
const R = (ad, kaynak, etki, ozne, fiil) => ({ ad, kaynak, etki, ozne, fiil });
export const KIMLIK_BELGE = [                            // ozneye bagli: nerede ne yapabilir
  K('k1', 'toplama-hizmeti', 'izin', OKU_YAZ, ['olcum-deposu/*', 'kayit-akisi/*']),
  K('k2', 'toplama-hizmeti', 'ret', ['sil'], ['*']),
  K('k3', 'dogrulama-hizmeti', 'izin', OKU, ['*']),
  K('k4', 'kenar-toplayici', 'izin', OKU_YAZ, ['kenar-dugum-grubu/*', 'kayit-akisi/*']),
  K('k5', 'analitik-is', 'izin', OKU, ['olcum-deposu/*', 'nesne-deposu/*']),
  K('k6', 'analitik-is', 'izin', ['yaz'], ['nesne-deposu/hazirlik', 'nesne-deposu/gelistirme']),
  K('k7', 'pano-okuyucu', 'izin', OKU, ['olcum-deposu/*', 'kayit-akisi/*']),
  K('k8', 'faturalama-is', 'izin', OKU, ['olcum-deposu/*', 'nesne-deposu/*', 'kayit-akisi/*']),
  K('k9', 'saha-bakim', 'izin', [...OKU_YAZ, 'yapilandir'], ['makine-kumesi/*', 'ag-yapilandirmasi/*', 'kenar-dugum-grubu/*']),
  K('k10', 'saha-bakim', 'ret', ['sil'], ['*/uretim']),
  K('k11', 'yedek-dogrulama', 'izin', OKU, ['nesne-deposu/*', 'olcum-deposu/*']),
];
export const KAYNAK_BELGE = [                            // kaynaga bagli: kim ne yapabilir
  R('r1', ['olcum-deposu/*'], 'izin', ['analitik-is', 'faturalama-is'], OKU),
  R('r2', ['nesne-deposu/*'], 'izin', ['*'], OKU),
  R('r3', ['kayit-akisi/*'], 'izin', ['toplama-hizmeti', 'kenar-toplayici'], OKU_YAZ),
  R('r4', ['makine-kumesi/*', 'ag-yapilandirmasi/*'], 'izin', ['saha-bakim'], [...OKU_YAZ, 'yapilandir']),
  R('r5', ['*/uretim'], 'ret', ['pano-okuyucu'], ['yaz', 'sil', 'yapilandir']),
  R('r6', ['kenar-dugum-grubu/*'], 'izin', ['kenar-toplayici', 'saha-bakim'], OKU_YAZ),
];
// Otuz gunluk kullanim izi: (ozne, fiil, kaynak turu); elle yazildi, ortam ayrimi tasimaz
export const IZ = new Set([
  ['toplama-hizmeti', OKU_YAZ, ['olcum-deposu', 'kayit-akisi']],
  ['dogrulama-hizmeti', ['oku'], ['olcum-deposu', 'kayit-akisi', 'makine-kumesi']],
  ['kenar-toplayici', ['oku', 'yaz'], ['kenar-dugum-grubu', 'kayit-akisi']],
  ['analitik-is', OKU, ['olcum-deposu', 'nesne-deposu']],
  ['pano-okuyucu', OKU, ['olcum-deposu', 'kayit-akisi']],
  ['faturalama-is', ['oku'], ['olcum-deposu', 'nesne-deposu', 'kayit-akisi']],
  ['saha-bakim', ['oku', 'yaz', 'yapilandir'], ['makine-kumesi', 'ag-yapilandirmasi']],
  ['yedek-dogrulama', ['oku'], ['nesne-deposu', 'olcum-deposu']],
].flatMap(([o, fs, ts]) => fs.flatMap((f) => ts.map((t) => `${o}|${f}|${t}`))));
export const izde = (i) => IZ.has(`${i.ozne}|${i.fiil}|${i.kaynak.tur}`);

export const desen = (p, s) =>
  new RegExp(`^${p.split('*').map((x) => x.replace(/[.+?^${}()|[\]\\]/g, '\\$&')).join('.*')}$`).test(s);
export const kimlikBelgeleri = (i, kb = KIMLIK_BELGE) => kb.filter((b) => b.ozne === i.ozne);
export const kaynakBelgeleri = (i, rb = KAYNAK_BELGE) => rb.filter((b) => b.kaynak.some((p) => desen(p, i.kaynak.ad)));
const uyar = (b, i) => b.fiil.includes(i.fiil) && b.kaynak.some((p) => desen(p, i.kaynak.ad)) &&
  (typeof b.ozne === 'string' ? b.ozne === i.ozne : b.ozne.includes('*') || b.ozne.includes(i.ozne));
export function yon(belgeler, i) {                       // bir yonun sonucu
  const u = belgeler.filter((b) => uyar(b, i));
  if (u.some((b) => b.etki === 'ret')) return 'acik-ret';
  return u.some((b) => b.etki === 'izin') ? 'izin' : 'yok';
}
// Model kurali: ayni hesapta bir yon yeter, hesap sinirinda iki yon de izin vermeli
export function degerlendir(i, kb = KIMLIK_BELGE, rb = KAYNAK_BELGE) {
  const a = yon(kimlikBelgeleri(i, kb), i), b = yon(kaynakBelgeleri(i, rb), i);
  if (a === 'acik-ret' || b === 'acik-ret') return 'acik-ret';
  const ayni = OZNE_HESAP[i.ozne] === i.kaynak.hesap;
  return (ayni ? a === 'izin' || b === 'izin' : a === 'izin' && b === 'izin') ? 'izin' : 'ortuk-ret';
}
```

İki belge türünün alanları aynı, taşıdıkları liste farklı: kimlik temelli belge bir özneye bağlıdır
ve kaynak deseni taşır, kaynak temelli belge bir kaynağa bağlıdır ve özne listesi taşır. `r2`
belgesindeki `*` özne listesi bu farkın en görünür yeri — kaynak, kendisine kimin erişebileceğini
adıyla saymak yerine hepsini açabiliyor.

#### Kesişim

```js
// kosum1.mjs — ayni istek iki yonden gecirilir ve kesisim hesaplanir
import { ISTEK, OZNE, KAYNAK, FIIL, OZNE_HESAP, KIMLIK_BELGE, KAYNAK_BELGE,
  kimlikBelgeleri, kaynakBelgeleri, yon, degerlendir } from './yon.mjs';

const ayniHesap = (i) => OZNE_HESAP[i.ozne] === i.kaynak.hesap;
const yonler = ISTEK.map((i) => ({ i, a: yon(kimlikBelgeleri(i), i), b: yon(kaynakBelgeleri(i), i),
  ayni: ayniHesap(i), sonuc: degerlendir(i) }));
console.log(`${OZNE.length} ozne x ${FIIL.length} fiil x ${KAYNAK.length} kaynak = ${ISTEK.length} istek`);
console.log(`kimlik temelli belge ${KIMLIK_BELGE.length}, kaynak temelli belge ${KAYNAK_BELGE.length}`);
console.log(`ayni hesap ${yonler.filter((y) => y.ayni).length}, hesap sinirini asan ${yonler.filter((y) => !y.ayni).length}\n`);

const say = (f) => yonler.filter(f).length;
console.log('iki yonun kesisimi        ayni hesap  hesap siniri  izinli sonuc');
const satir = (ad, f) => console.log(`${ad.padEnd(25)} ${String(say((y) => y.ayni && f(y))).padEnd(11)} ` +
  `${String(say((y) => !y.ayni && f(y))).padEnd(13)} ${say((y) => f(y) && y.sonuc === 'izin')}`);
satir('yalniz kimlik yonu izin', (y) => y.a === 'izin' && y.b !== 'izin' && y.b !== 'acik-ret');
satir('yalniz kaynak yonu izin', (y) => y.b === 'izin' && y.a !== 'izin' && y.a !== 'acik-ret');
satir('iki yon de izin', (y) => y.a === 'izin' && y.b === 'izin');
satir('hicbir yon izin vermiyor', (y) => y.a !== 'izin' && y.b !== 'izin');
satir('en az bir yonde acik ret', (y) => y.a === 'acik-ret' || y.b === 'acik-ret');

const s = { izin: 0, 'acik-ret': 0, 'ortuk-ret': 0 };
for (const y of yonler) s[y.sonuc]++;
console.log(`\nsonuc: izin ${s.izin}, acik ret ${s['acik-ret']}, ortuk ret ${s['ortuk-ret']}`);
const tekYonYeterdi = say((y) => y.sonuc !== 'izin' && (y.a === 'izin' || y.b === 'izin') &&
  y.a !== 'acik-ret' && y.b !== 'acik-ret');
console.log(`bir yonde izinli oldugu halde reddedilen: ${tekYonYeterdi} istek — hepsi hesap sinirini asiyor`);
```

```
8 ozne x 5 fiil x 21 kaynak = 840 istek
kimlik temelli belge 11, kaynak temelli belge 6
ayni hesap 285, hesap sinirini asan 555

iki yonun kesisimi        ayni hesap  hesap siniri  izinli sonuc
yalniz kimlik yonu izin   29          45            29
yalniz kaynak yonu izin   6           18            6
iki yon de izin           57          39            96
hicbir yon izin vermiyor  193         453           0
en az bir yonde acik ret  17          32            0

sonuc: izin 131, acik ret 49, ortuk ret 660
bir yonde izinli oldugu halde reddedilen: 63 istek — hepsi hesap sinirini asiyor
```

Sekiz yüz kırk isteğin yüz otuz biri izinli. İlk iki satır aynı hesapla hesap sınırının neden ayrı
sütun olduğunu gösteriyor: aynı hesapta yalnız kimlik yönünde izinli yirmi dokuz istek var ve
yirmi dokuzu izinli sonuçlanıyor, yalnız kaynak yönünde izinli altı istek de öyle. Hesap sınırında
aynı satırlar kırk beş ve on sekiz, ama izinli sonuç sıfır.

Son satır bunu tek sayıya indiriyor: altmış üç istek bir yönde açıkça izinli olduğu hâlde
reddediliyor. Birileri gerçekten bir belge yazdı, belge eşleşiyor, ama karşı yön yazılmadığı için
erişim olmuyor. Hesap sınırının yaptığı iş budur — bir yönün yazılmasını yeterli olmaktan çıkarıp
iki tarafın anlaşmasını zorunlu kılar.

#### Hesap Sınırı

```js
// kosum2.mjs — hesap siniri: kaynak temelli belge ne zaman zorunlu oluyor
import { ISTEK, KAYNAK_BELGE, KIMLIK_BELGE, TUR_HESAP, OZNE_HESAP, OZNE, desen,
  kimlikBelgeleri, yon, degerlendir, izde, IZ } from './yon.mjs';

const disHesap = ISTEK.filter((i) => OZNE_HESAP[i.ozne] !== i.kaynak.hesap);
console.log('kaynak turu        hesap           izin veren belge  sinir asan istek  izin  kimlik izinli ama ret');
for (const t of Object.keys(TUR_HESAP)) {
  const d = disHesap.filter((i) => i.kaynak.tur === t);
  const belge = KAYNAK_BELGE.filter((b) => b.etki === 'izin' && b.kaynak.some((p) => desen(p, `${t}/uretim`))).length;
  const izin = d.filter((i) => degerlendir(i) === 'izin').length;
  const kesik = d.filter((i) => degerlendir(i) !== 'izin' && yon(kimlikBelgeleri(i), i) === 'izin').length;
  console.log(`${t.padEnd(18)} ${TUR_HESAP[t].padEnd(15)} ${String(belge).padEnd(17)} ${String(d.length).padEnd(17)} ` +
    `${String(izin).padEnd(5)} ${kesik}`);
}
const kesim = (kb, rb) => ISTEK.filter((i) => degerlendir(i, kb, rb) === 'izin');
const mesru = (l) => l.filter(izde).length;
const tam = kesim(KIMLIK_BELGE, KAYNAK_BELGE);
console.log(`\nizinli istek ${tam.length}; izde gorunen ${mesru(tam)}, kullanilmayan izin ${tam.length - mesru(tam)}`);
console.log(`iz ${IZ.size} (ozne, fiil, tur) uclusu tasiyor\n`);

// Kaynak temelli belgeyi daraltmanin uc kademesi
const r2Dar = KAYNAK_BELGE.map((b) => (b.ad === 'r2'
  ? { ...b, ozne: OZNE.filter((o) => [...IZ].some((k) => k.startsWith(`${o}|`) && k.endsWith('|nesne-deposu'))) } : b));
console.log('kaynak temelli belge kumesi        izin  izde gorunen  duran mesru is');
for (const [ad, rb] of [['degismeden (r2 ozne *)', KAYNAK_BELGE], ['r2 ozne listesi ize gore', r2Dar],
  ['r2 kaldirildi', KAYNAK_BELGE.filter((b) => b.ad !== 'r2')], ['hicbiri yok', []]]) {
  const k = kesim(KIMLIK_BELGE, rb);
  console.log(`${ad.padEnd(34)} ${String(k.length).padEnd(5)} ${String(mesru(k)).padEnd(13)} ${mesru(tam) - mesru(k)}`);
}
```

```
kaynak turu        hesap           izin veren belge  sinir asan istek  izin  kimlik izinli ama ret
olcum-deposu       hesap-olcum     1                 75                12    12
kayit-akisi        hesap-olcum     1                 75                0     12
kenar-dugum-grubu  hesap-olcum     1                 75                9     3
nesne-deposu       hesap-analitik  1                 90                18    0
islev-paketi       hesap-analitik  0                 90                0     6
makine-kumesi      hesap-ortak     1                 75                0     6
ag-yapilandirmasi  hesap-ortak     1                 75                0     6

izinli istek 131; izde gorunen 75, kullanilmayan izin 56
iz 32 (ozne, fiil, tur) uclusu tasiyor

kaynak temelli belge kumesi        izin  izde gorunen  duran mesru is
degismeden (r2 ozne *)             131   75            0
r2 ozne listesi ize gore           119   75            0
r2 kaldirildi                      107   69            6
hicbiri yok                        86    60            15
```

`islev-paketi` satırı kuralı en yalın biçimde gösteriyor: bu türe bağlı izin veren bir kaynak
belgesi yok, dolayısıyla hesap sınırını aşan doksan isteğin hepsi reddediliyor ve altısı kimlik
tarafında yazılmış izinlere sahip. O altı izin bir yerde duruyor, bakımı yapılıyor, denetimde
görünüyor ve hiçbir işe yaramıyor. `kayit-akisi` satırında bir izin belgesi var ama saydığı iki
özne aynı hesapta olduğu için sınır aşan yetmiş beş isteğin hiçbirine yaramıyor.

Alt tablo daraltmanın kademelerini veriyor. `r2` belgesinin `*` özne listesi otuz günlük izde
görünen öznelerle değiştirilince izinli istek yüz otuz birden yüz on dokuza iniyor ve duran meşru
iş sıfır: on iki iznin tamamı kullanılmayan izindi. `r2` tamamen kaldırılınca izin yüz yediye
düşüyor ve altı meşru iş duruyor; bütün kaynak temelli belgeler kaldırılırsa izin seksen altıya,
duran meşru iş on beşe çıkıyor. Daraltmanın ilk kademesi bedava, ikincisi değil.

#### Neden Reddedildi

```js
// kosum3.mjs — bir erisimin neden reddedildigini bulmak kac belgeye bakmayi gerektiriyor
import { ISTEK, OZNE_HESAP, kimlikBelgeleri, kaynakBelgeleri, yon, degerlendir } from './yon.mjs';

const neden = (i) => {
  const a = yon(kimlikBelgeleri(i), i), b = yon(kaynakBelgeleri(i), i);
  if (a === 'acik-ret') return 'kimlik yonunde acik ret';
  if (b === 'acik-ret') return 'kaynak yonunde acik ret';
  if (a === 'izin' || b === 'izin') return 'hesap siniri: tek yon izin veriyor';
  return 'iki yonde de izin yok';
};
const ret = ISTEK.filter((i) => degerlendir(i) !== 'izin');
const belge = (i) => kimlikBelgeleri(i).length + kaynakBelgeleri(i).length + 1;  // +1: hesap kurali
const ort = (l, f) => (l.reduce((a, x) => a + f(x), 0) / l.length).toFixed(1);

console.log(`reddedilen ${ret.length} istek; bakilacak belge = ozneye bagli + kaynaga uyan + hesap kurali\n`);
console.log('ret nedeni                          istek  belge ortalama  en cok');
for (const n of ['kimlik yonunde acik ret', 'kaynak yonunde acik ret',
  'hesap siniri: tek yon izin veriyor', 'iki yonde de izin yok']) {
  const l = ret.filter((i) => neden(i) === n);
  console.log(`${n.padEnd(35)} ${String(l.length).padEnd(6)} ${String(ort(l, belge)).padEnd(15)} ` +
    `${Math.max(...l.map(belge))}`);
}
console.log(`${'toplam'.padEnd(35)} ${String(ret.length).padEnd(6)} ${String(ort(ret, belge)).padEnd(15)} ` +
  `${Math.max(...ret.map(belge))}`);
console.log(`tek yon okunsaydi (yalniz kimlik): ortalama ${ort(ret, (i) => kimlikBelgeleri(i).length)} belge`);

// Tek yone bakan bir okuyucu kac istekte yanlis cevap verir
const yalniz = (i) => (yon(kimlikBelgeleri(i), i) === 'izin' ? 'izin' : 'ret');
const gercek = (i) => (degerlendir(i) === 'izin' ? 'izin' : 'ret');
const yanlis = ISTEK.filter((i) => yalniz(i) !== gercek(i));
console.log(`\nyalniz kimlik yonune bakan okuyucu ${ISTEK.length} istegin ${yanlis.length} tanesinde yanilir`);
console.log(`bunlarin ${yanlis.filter((i) => OZNE_HESAP[i.ozne] !== i.kaynak.hesap).length} tanesi hesap sinirini asiyor`);
const aralik = (f) => { const v = ISTEK.map(f); return `${Math.min(...v)}-${Math.max(...v)}`; };
console.log(`ozneye bagli belge ${aralik((i) => kimlikBelgeleri(i).length)}, ` +
  `kaynaga uyan belge ${aralik((i) => kaynakBelgeleri(i).length)}`);
```

```
reddedilen 709 istek; bakilacak belge = ozneye bagli + kaynaga uyan + hesap kurali

ret nedeni                          istek  belge ortalama  en cok
kimlik yonunde acik ret             28     4.4             5
kaynak yonunde acik ret             21     3.9             4
hesap siniri: tek yon izin veriyor  63     3.5             5
iki yonde de izin yok               597    3.5             5
toplam                              709    3.5             5
tek yon okunsaydi (yalniz kimlik): ortalama 1.4 belge

yalniz kimlik yonune bakan okuyucu 840 istegin 51 tanesinde yanilir
bunlarin 45 tanesi hesap sinirini asiyor
ozneye bagli belge 1-2, kaynaga uyan belge 0-2
```

Bir retin nedenini bulmak ortalama üç buçuk belge okumayı gerektiriyor, en kötü durumda beş. Sayının
küçük olmasının nedeni modelin küçük olmasıdır; asıl bilgi oranda. Tek yön okunsaydı ortalama bir
virgül dört belgeye bakılacaktı: ikinci yönü eklemek okunacak belgeyi iki buçuk kat artırıyor ve bu
artış her ret sorgusunda ödenir.

Bedelin karşılığı son iki satırda. Yalnız kimlik yönüne bakan bir okuyucu sekiz yüz kırk isteğin
elli birinde yanlış cevap verir — hepsinde "izinli" der, oysa istek reddedilir. Kırk beşinin nedeni
hesap sınırıdır, kalan altısında kaynak yönünde bir açık ret vardır. Belge doğru okunmuştur; yanlış
olan tek belgeye bakmaktır.

#### Özet

- 840 isteğin 131'i izinli; 285 istek aynı hesapta, 555'i hesap sınırını aşıyor.
- 63 istek bir yönde açıkça izinli olduğu hâlde reddediliyor ve hepsi hesap sınırını aşıyor; aynı
  hesapta bu sayı sıfırdır, çünkü orada bir yön yeter.
- `islev-paketi` türünde izin veren kaynak belgesi yok: sınır aşan 90 isteğin tamamı reddediliyor
  ve 6 kimlik temelli izin hiçbir işe yaramadan duruyor.
- İzinli 131 isteğin 75'i izde görünüyor; `r2`'nin `*` özne listesini ize göre yazmak 12 kullanılmayan
  izni kapatıyor ve hiçbir meşru işi durdurmuyor.
- İkinci kademe bedava değil: `r2` kaldırılınca 6, bütün kaynak temelli belgeler kaldırılınca 15
  meşru iş duruyor.
- Bir retin nedenini bulmak ortalama 3,5 belge ister, tek yön okunsaydı 1,4; yalnız kimlik yönüne
  bakan okuyucu 840 isteğin 51'inde yanılır.

#### Sonraki Adım

Bu dersin sekiz öznesi kalıcı kimliklerdi ve her birinin uzun ömürlü bir kimlik bilgisi vardı. İlk
derste sayılan yüzey buydu: yirmi dokuz saklama yeri ve sekiz yüz seksen günlük bir anahtar. İzin
bağlantısı ne kadar dar yazılırsa yazılsın, anahtar sızdığında bütün belgeler onu taşıyanın lehine
çalışır. Sonraki ders erişimi kalıcı kimlikten ayırır: bir özne başka bir kimliği geçici olarak
üstlenir. Ölçülen kalemler sızıntı penceresi, üstlenme zincirinin uzunluğu, güven ilişkisinin kimin
üstlenebileceğini belirlemesi ve denetim kaydında asıl öznenin kaç adım sonra kaybolduğudur.

### Rol Üstlenme

Source: https://academia.sh/tr/kurslar/bulut-yonetisimi/rol-ustlenme

Geçici kimlik bilgisiyle erişim, uzun ömürlü anahtarla karşılaştırılır: sızıntı penceresi, üstlenme zincirinin uzunluğu, güven ilişkisinin kimin üstlenebileceğini belirlemesi ve denetim kaydında asıl öznenin kaç adım sonra kaybolduğu sayılır.

Önceki üç ders izni daralttı ve iki yönü birlikte okumayı öğretti, ama her özne hâlâ kalıcı bir
kimlikti ve her kalıcı kimliğin uzun ömürlü bir kimlik bilgisi vardı. İlk derste bu yüzeyin boyu
sayılmıştı: yirmi dokuz saklama yeri, en eskisi sekiz yüz seksen günlük. Politika belgesi ne kadar
dar yazılırsa yazılsın, anahtarı ele geçiren o belgenin verdiği her şeyi alır.

Rol üstlenme erişimi kalıcı kimlikten ayırır. Özne kendi kimliğiyle doğrulanır, sonra bir rolü
üstlenir ve o rolün yetkisiyle çalışan **geçici bir kimlik bilgisi** alır. Kimlik bilgisinin
dinamik üretilmesi ve ömrünün kısalması daha önce sır yönetimi ekseninde ölçülmüştü; buradaki
ölçüm o değil. Burada sayılan üç şey var: pencerenin ne kadar daraldığı, üstlenmenin zincirlenmesi
ve zincirin denetim kaydında bıraktığı iz.

- **BI19.** Model beş kalıcı kimlik, altı rol ve dokuz üstlenme zinciri taşır. Gerçek bir hesap
  koşturulmuyor; ölçülen şey `node` ile kurulan güven grafiğidir.
- **BI20.** Kimlik bilgisi ömürleri ve saatlik üstlenme sınırı kurgudur, ders içinde tanımlıdır.
  Bir sağlayıcının değerleri değildir.
- **BI21.** Sızıntının fark edilme süresi yirmi bir gün kabul edildi. Uzun ömürlü anahtarın
  penceresi bu süreyle sınırlandı; gerçekte fark edilmeyen sızıntıda pencere daha uzundur, bu
  yüzden ölçülen kat bir alt sınırdır.
- **BI22.** Sızıntının kimlik bilgisinin geçerlilik aralığında düzgün dağıldığı varsayıldı;
  beklenen pencere bu yüzden ömrün yarısıdır.
- **BI23.** Otuz günlük iz elle yazıldı ve dokuz zincirden oluşuyor. Zincirlerin güven ilişkisine
  uyduğu kod içinde denetleniyor.
- **BI24.** Denetim kaydı iki kalem taşıyor sayılır: son rol ve oturum adı. Üstlenme kaydı ayrıca
  çağıranın oturum adını taşır. Kayıt saklama süresi modele girmedi.

#### Güven Grafiği ve Ömürler

```js
// ustlenme.mjs — guven iliskisi ve ustlenme zinciri; gercek bir hesap degil, node ile kurulan modeldir
export const KIMLIK = ['toplama-hizmeti', 'analitik-is', 'saha-bakim', 'yayin-hatti', 'nobetci-insan'];
export const GUVEN = {                                   // rol -> onu ustlenebilecekler (kimlik ya da rol)
  'rol-okuma': ['toplama-hizmeti', 'analitik-is', 'rol-koprusu'],
  'rol-yayin': ['yayin-hatti'],
  'rol-bakim': ['saha-bakim', 'rol-yayin'],
  'rol-yonetim': ['nobetci-insan', 'rol-bakim'],
  'rol-denetim': ['*'],
  'rol-koprusu': ['nobetci-insan', 'yayin-hatti'],
};
export const ROL = Object.keys(GUVEN);
// Otuz gunluk iz: hangi zincir kac islem uretti; elle yazildi
export const IZ = [
  ['toplama-hizmeti', ['rol-okuma'], 1200], ['analitik-is', ['rol-okuma'], 800],
  ['saha-bakim', ['rol-bakim'], 260], ['yayin-hatti', ['rol-yayin', 'rol-bakim'], 340],
  ['nobetci-insan', ['rol-koprusu', 'rol-okuma'], 90], ['nobetci-insan', ['rol-yonetim'], 40],
  ['yayin-hatti', ['rol-yayin', 'rol-bakim', 'rol-yonetim'], 25],
  ['saha-bakim', ['rol-denetim'], 60], ['analitik-is', ['rol-denetim'], 30],
];
export const guvenir = (rol, ustlenen, g = GUVEN) => g[rol].includes('*') || g[rol].includes(ustlenen);
export function zincirGecerli(basla, adimlar, g = GUVEN) {
  let su = basla;
  for (const r of adimlar) { if (!guvenir(r, su, g)) return false; su = r; }
  return true;
}
// Bir kimlikten ulasilan roller ve en kisa zincir uzunlugu (genislik oncelikli arama)
export function ulasim(basla, g = GUVEN) {
  const uzaklik = new Map(); let sinir = [basla];
  for (let d = 1; sinir.length; d++) {
    const yeni = [];
    for (const r of Object.keys(g)) {
      if (uzaklik.has(r)) continue;
      if (sinir.some((s) => guvenir(r, s, g))) { uzaklik.set(r, d); yeni.push(r); }
    }
    sinir = yeni;
  }
  return uzaklik;
}
export const OMUR = [                                    // ad, gecerlilik suresi (dakika)
  ['uzun omurlu anahtar', null], ['rol ustlenme 12 saat', 720],
  ['rol ustlenme 1 saat', 60], ['rol ustlenme 15 dk', 15],
];
export const TESPIT_DK = 21 * 24 * 60;                   // sizintinin fark edilme suresi, kurgu
export const SINIR_SAAT = 500;                           // saatte en cok ustlenme cagrisi, kurgu
```

Güven ilişkisi rolün kendi üstünde durur ve bir liste taşır: bu rolü kim üstlenebilir. Listede
kalıcı bir kimlik olabileceği gibi başka bir rol de olabilir — zincir buradan doğar. `rol-denetim`
satırındaki `*` bu listenin en geniş hâlidir ve kendi başına bir ölçüm konusudur.

#### Sızıntı Penceresi

```js
// kosum1.mjs — sizinti penceresi: uzun omurlu anahtar ile rol ustlenme
import { KIMLIK, OMUR, TESPIT_DK, SINIR_SAAT } from './ustlenme.mjs';

const AY = 30 * 24 * 60;                                 // otuz gunluk pencere, dakika
const uzun = TESPIT_DK;                                  // uzun omurlude pencere = fark edilme suresi
console.log(`otuz gun ${AY} dk; sizintinin fark edilme suresi ${TESPIT_DK} dk (kurgu)`);
console.log(`${KIMLIK.length} kalici kimlik, saatlik ustlenme siniri ${SINIR_SAAT} cagri (kurgu)\n`);
console.log('kimlik bilgisi        omur (dk)  otuz gunde adet  beklenen pencere  en kotu pencere  kat');
for (const [ad, t] of OMUR) {
  const adet = t ? AY / t : 1;
  const beklenen = t ? Math.min(t / 2, uzun) : uzun;
  const enKotu = t ? Math.min(t, uzun) : uzun;
  console.log(`${ad.padEnd(21)} ${String(t ?? 'sinirsiz').padEnd(10)} ${String(adet).padEnd(16)} ` +
    `${String(beklenen).padEnd(17)} ${String(enKotu).padEnd(16)} ${Math.round(uzun / beklenen)}`);
}
console.log('\nyenileme maliyeti ve sinir:');
for (const [ad, t] of OMUR.filter(([, t]) => t)) {
  const saatlik = (60 / t) * KIMLIK.length;
  console.log(`  ${ad.padEnd(21)} saatlik cagri ${saatlik.toFixed(2).padEnd(6)} ` +
    `sinira kalan ${(SINIR_SAAT - saatlik).toFixed(2).padEnd(7)} ayni hizda sigan kimlik ${Math.floor(SINIR_SAAT / (60 / t))}`);
}
```

```
otuz gun 43200 dk; sizintinin fark edilme suresi 30240 dk (kurgu)
5 kalici kimlik, saatlik ustlenme siniri 500 cagri (kurgu)

kimlik bilgisi        omur (dk)  otuz gunde adet  beklenen pencere  en kotu pencere  kat
uzun omurlu anahtar   sinirsiz   1                30240             30240            1
rol ustlenme 12 saat  720        60               360               720              84
rol ustlenme 1 saat   60         720              30                60               1008
rol ustlenme 15 dk    15         2880             7.5               15               4032

yenileme maliyeti ve sinir:
  rol ustlenme 12 saat  saatlik cagri 0.42   sinira kalan 499.58  ayni hizda sigan kimlik 6000
  rol ustlenme 1 saat   saatlik cagri 5.00   sinira kalan 495.00  ayni hizda sigan kimlik 500
  rol ustlenme 15 dk    saatlik cagri 20.00  sinira kalan 480.00  ayni hizda sigan kimlik 125
```

Uzun ömürlü anahtarın penceresi ömründen değil, sızıntının fark edilmesinden gelir: otuz bin iki
yüz kırk dakika, yani üç haftadır. Bu sürede anahtar hâlâ geçerlidir ve kimse durumu bilmez. Bir
saatlik geçici kimlik bilgisinde beklenen pencere otuz dakikaya iner — bin sekiz kat daha kısa —
çünkü sızan şeyin ömrü, fark edilmeye kadar geçen süreden bağımsızdır. Kimse bir şey yapmasa bile
kimlik bilgisi kendiliğinden geçersizleşir.

Maliyet ikinci sütunda. Bir saatlik ömür otuz günde yedi yüz yirmi ayrı kimlik bilgisi demektir;
on beş dakikalık ömürde iki bin sekiz yüz seksen. Bunların her biri bir üstlenme çağrısıdır ve
çağrı sayısı kotaya çarpar. Beş kalıcı kimlikle on beş dakikalık ömür saatte yirmi çağrı ediyor ve
kurgu beş yüzlük sınıra dört yüz seksen çağrı kalıyor; aynı hızda çalışan yüz yirmi beş kimlik
sığar. Pencereyi dört kat daraltmanın bedeli, sığan kimlik sayısının dörtte bire inmesidir.

#### Zincir ve Güven Listesi

```js
// kosum2.mjs — guven iliskisi kimin ustlenebilecegini belirler; zincir ne kadar uzuyor
import { KIMLIK, ROL, GUVEN, IZ, ulasim, zincirGecerli } from './ustlenme.mjs';

console.log(`${KIMLIK.length} kalici kimlik, ${ROL.length} rol; izdeki zincir ${IZ.length}`);
console.log(`izdeki zincirlerin hepsi guven iliskisine uyuyor: ${IZ.every(([b, a]) => zincirGecerli(b, a))}\n`);
console.log('kalici kimlik      dogrudan  zincirle  toplam  en uzun zincir  izde kullandigi');
let dogrudanT = 0, toplamT = 0;
for (const k of KIMLIK) {
  const u = ulasim(k);
  const d = [...u.values()].filter((x) => x === 1).length;
  const kullanilan = new Set(IZ.filter(([b]) => b === k).flatMap(([, a]) => a)).size;
  dogrudanT += d; toplamT += u.size;
  console.log(`${k.padEnd(18)} ${String(d).padEnd(9)} ${String(u.size - d).padEnd(9)} ${String(u.size).padEnd(7)} ` +
    `${String(Math.max(...u.values())).padEnd(15)} ${kullanilan}`);
}
console.log(`toplam             ${String(dogrudanT).padEnd(9)} ${String(toplamT - dogrudanT).padEnd(9)} ${toplamT}`);

// rol-denetim'in genis guveni ize gore daraltilirsa
const izdeUstlenen = (rol) => KIMLIK.filter((k) => IZ.some(([b, a]) => b === k && a.includes(rol)));
const dar = { ...GUVEN, 'rol-denetim': izdeUstlenen('rol-denetim') };
const cift = (g) => KIMLIK.reduce((a, k) => a + ulasim(k, g).size, 0);
const mesru = (g) => IZ.filter(([b, a]) => zincirGecerli(b, a, g)).reduce((s, [, , n]) => s + n, 0);
console.log('\n' + 'guven listesi'.padEnd(36) + ' (kimlik, rol) cifti  duran zincir  duran islem/gun');
for (const [ad, g] of [['rol-denetim: *', GUVEN], [`rol-denetim: ${dar['rol-denetim'].join(', ')}`, dar],
  ['rol-denetim kaldirildi', { ...GUVEN, 'rol-denetim': [] }]]) {
  const kalan = IZ.filter(([b, a]) => !zincirGecerli(b, a, g)).length;
  console.log(`${ad.padEnd(36)} ${String(cift(g)).padEnd(20)} ${String(kalan).padEnd(13)} ${mesru(GUVEN) - mesru(g)}`);
}
```

```
5 kalici kimlik, 6 rol; izdeki zincir 9
izdeki zincirlerin hepsi guven iliskisine uyuyor: true

kalici kimlik      dogrudan  zincirle  toplam  en uzun zincir  izde kullandigi
toplama-hizmeti    2         0         2       1               1
analitik-is        2         0         2       1               2
saha-bakim         2         1         3       2               2
yayin-hatti        3         3         6       3               3
nobetci-insan      3         1         4       2               3
toplam             12        5         17

guven listesi                        (kimlik, rol) cifti  duran zincir  duran islem/gun
rol-denetim: *                       17                   0             0
rol-denetim: analitik-is, saha-bakim 14                   0             0
rol-denetim kaldirildi               12                   2             90
```

Beş kimlik ve altı rol otuz olası çift kurar; güven listeleri bunun on yedisini açıyor. On ikisi
doğrudan üstlenme, beşi zincir üzerinden. Zincir en çok `yayin-hatti` için iş görüyor: doğrudan üç
role üstlenebiliyor, zincirle üç role daha ulaşıyor ve en uzun zinciri üç adım. Bu kimliğe
`rol-yonetim` yetkisi hiçbir yerde verilmemiştir; `rol-yayin` üzerinden `rol-bakim`a, oradan
`rol-yonetim`e ulaşıyor. Güven listelerine tek tek bakan biri bunu göremez, çünkü hiçbir listede
`yayin-hatti` ile `rol-yonetim` yan yana yazılı değil.

Alt tablo geniş güven listesinin bedelini ölçüyor. `rol-denetim` her özneye açık olduğu için beş
çift buradan geliyor; listeyi izde gerçekten üstlenen iki adla değiştirmek çifti on yediden on
dörde indiriyor ve duran meşru iş sıfır. Üç çift, hiç kullanılmadığı hâlde açık duran üstlenme
hakkıydı. Bir kademe ileri gidip rolü tamamen kapatmak iki zinciri durduruyor ve günde doksan
işlem kaybediyor. Daraltmanın ilk kademesi bedava, ikincisi değil — önceki derste kaynak temelli
belge için çıkan sonucun aynısı, başka bir eksende.

#### Denetim Kaydında Asıl Özne

```js
// kosum3.mjs — denetim kaydinda asil ozne gorunuyor mu, kac adim sonra kayboluyor
import { ROL, IZ } from './ustlenme.mjs';

function kayitlar(adlandir) {                            // otuz gunluk izden kayit uretilir
  const ustlenme = [], islem = [];
  for (const [asil, adimlar, gunluk] of IZ) {
    let su = asil, onceki = null, oturum = null;
    for (const [n, r] of adimlar.entries()) {
      oturum = adlandir(asil, r, n);
      ustlenme.push({ ustlenen: su, rol: r, oturum, cagiran: onceki });
      onceki = oturum; su = r;
    }
    islem.push({ rol: adimlar.at(-1), oturum, gunluk, asil, uzunluk: adimlar.length });
  }
  return { ustlenme, islem };
}
// Geri izleme: (rol, oturum) anahtarindan olasi asil ozneler
function olasiAsil(ustlenme, rol, oturum) {
  const kume = new Set();
  for (const u of ustlenme.filter((x) => x.rol === rol && x.oturum === oturum)) {
    if (!ROL.includes(u.ustlenen)) kume.add(u.ustlenen);
    else for (const a of olasiAsil(ustlenme, u.ustlenen, u.cagiran)) kume.add(a);
  }
  return kume;
}
const ADLANDIRMA = [                                     // ad, son kayittan okunur mu, uretici
  ['rol adina gore', false, (a, r) => `${r}-oturum`],
  ['yalniz ilk adimda asil', false, (a, r, n) => (n === 0 ? `${a}@${r}` : `${r}-oturum`)],
  ['her adimda asil', true, (a, r) => `${a}@${r}`],
];
const toplamIslem = IZ.reduce((a, [, , n]) => a + n, 0);
console.log(`otuz gunluk izde ${IZ.length} zincir, gunde ${toplamIslem} islem kaydi\n`);
console.log('oturum adlandirmasi     son kayitta asil  cozulen islem/gun  yuzde   okunacak kayit  en cok aday');
const sonuc = new Map();
for (const [ad, okunur, f] of ADLANDIRMA) {
  const { ustlenme, islem } = kayitlar(f);
  const adayi = islem.map((k) => ({ ...k, aday: olasiAsil(ustlenme, k.rol, k.oturum).size }));
  sonuc.set(ad, adayi);
  const tek = adayi.filter((k) => k.aday === 1);
  const cozulen = tek.reduce((a, k) => a + k.gunluk, 0);
  const derinlik = okunur ? '0' : (cozulen ? (tek.reduce((a, k) => a + k.gunluk * k.uzunluk, 0) / cozulen).toFixed(2) : '-');
  console.log(`${ad.padEnd(23)} ${(okunur ? 'evet' : 'hayir').padEnd(17)} ${String(cozulen).padEnd(18)} ` +
    `%${((100 * cozulen) / toplamIslem).toFixed(1).padEnd(6)} ${derinlik.padEnd(15)} ${Math.max(...adayi.map((k) => k.aday))}`);
}
console.log('\nzincir uzunlugu  zincir  islem/gun  rol adina gore cozulen  ilk adimda asil ile cozulen');
for (const u of [1, 2, 3]) {
  const secili = (ad) => sonuc.get(ad).filter((k) => k.uzunluk === u);
  const c = (ad) => secili(ad).filter((k) => k.aday === 1).reduce((a, k) => a + k.gunluk, 0);
  console.log(`${String(u).padEnd(16)} ${String(secili('rol adina gore').length).padEnd(7)} ` +
    `${String(secili('rol adina gore').reduce((a, k) => a + k.gunluk, 0)).padEnd(10)} ` +
    `${String(c('rol adina gore')).padEnd(23)} ${c('yalniz ilk adimda asil')}`);
}
const adim = IZ.reduce((a, [, ad]) => a + ad.length, 0);
console.log(`\nustlenme adimi ${adim}; bir saatlik gecici kimlik bilgisiyle gunde ${adim * 24} ustlenme kaydi`);
```

```
otuz gunluk izde 9 zincir, gunde 2845 islem kaydi

oturum adlandirmasi     son kayitta asil  cozulen islem/gun  yuzde   okunacak kayit  en cok aday
rol adina gore          hayir             0                  %0.0    -               3
yalniz ilk adimda asil  hayir             2845               %100.0  1.17            1
her adimda asil         evet              2845               %100.0  0               1

zincir uzunlugu  zincir  islem/gun  rol adina gore cozulen  ilk adimda asil ile cozulen
1                6       2390       0                       2390
2                2       430        0                       430
3                1       25         0                       25

ustlenme adimi 13; bir saatlik gecici kimlik bilgisiyle gunde 312 ustlenme kaydi
```

İşlem kaydı iki kalem taşıyor: hangi rol ve hangi oturum. Rol adına göre isimlendirilmiş bir
oturumda asıl özne hiçbir yerde görünmüyor ve geri izleme de kurtarmıyor — günde iki bin sekiz yüz
kırk beş kaydın sıfırı tek bir asıl özneye bağlanabiliyor. Nedeni ikinci tabloda: bir adımlık
zincirlerde bile sonuç sıfır. `rol-okuma` rolüne üç ayrı kimlik ulaşıyor ve üçü de aynı oturum
adını kullandığı için bir okuma kaydının hangisinden geldiği ayırt edilemiyor. En kötü durumda üç
aday var.

Oturum adı yalnız ilk adımda asıl özneyi taşıdığında bütün kayıtlar çözülüyor, ama kaydın kendisi
hâlâ asıl özneyi göstermiyor: ortalama bir virgül on yedi üstlenme kaydını birleştirmek gerekiyor
ve üç adımlık zincirde bu sayı üçe çıkıyor. Asıl özne her adımda taşındığında birleştirme sıfıra
iniyor — soru doğrudan kaydın kendisinden cevaplanıyor.

Aradaki fark bir arıza sırasında ölçülür. Üç kayıt kümesini birleştirmek, ilgili kayıtların üçünün
de elde olmasını ve zaman aralıklarının örtüşmesini gerektirir; oturum adı seçimi ise üstlenmeyi
yapan tarafın elindedir. Son satır hacmi veriyor: on üç üstlenme adımı, bir saatlik ömürle günde
üç yüz on iki üstlenme kaydı. Pencereyi daraltmak denetim kaydını da büyütüyor.

#### Özet

- Uzun ömürlü anahtarın sızıntı penceresi fark edilme süresine eşittir (30240 dk); bir saatlik
  geçici kimlik bilgisinde beklenen pencere 30 dk, yani 1008 kat kısa.
- Pencerenin bedeli üretim hacmidir: 15 dakikalık ömür otuz günde 2880 kimlik bilgisi ve saatte 20
  çağrı ister; kurgu 500'lük sınıra 480 çağrı kalıyor, aynı hızda 125 kimlik sığar.
- Beş kimlik ve altı rol 30 çift kurar, güven listeleri 17'sini açar: 12 doğrudan, 5 zincirle.
  `yayin-hatti` hiçbir listede yazmadığı hâlde üç adımda `rol-yonetim`e ulaşıyor.
- `rol-denetim`in `*` güven listesini ize göre yazmak çifti 17'den 14'e indiriyor ve hiçbir meşru
  işi durdurmuyor; rolü kapatmak 2 zinciri ve günde 90 işlemi durduruyor.
- Oturum adı role göre verildiğinde günde 2845 işlem kaydının sıfırı tek bir asıl özneye
  bağlanabiliyor; bir adımlık zincirlerde bile sonuç sıfır, en kötü durumda 3 aday var.
- Asıl özne yalnız ilk adımda taşındığında bütün kayıtlar çözülür ama ortalama 1,17 üstlenme
  kaydını birleştirmek gerekir; her adımda taşındığında birleştirme sıfıra iner.

#### Sonraki Adım

Bu dersin beş öznesinden dördü bir program, biri insandı ve hepsi aynı biçimde ele alındı. Kalıcı
kimlik ile geçici kimlik bilgisi arasındaki fark ölçüldü, ama bir sorunun cevabı verilmedi: bir
program ilk kimliğini nereden alıyor. Rol üstlenmek için önce bir kimlikle doğrulanmak gerekiyor
ve o ilk kimlik bir yerde duruyorsa zincirin başında yine uzun ömürlü bir sır var demektir.
Sonraki ders bu ilk adımı ölçer: bir iş yüküne kimlik verilmesinin kaç ayrı yolu var, her yol
kaç sır saklamayı gerektiriyor ve saklanan sır sayısı sıfıra indiğinde yerine hangi kalem geçiyor.

### İş Yükü Kimlikleri

Source: https://academia.sh/tr/kurslar/bulut-yonetisimi/is-yuku-kimlikleri

Uygulamaya kimlik vermenin üç yolu yan yana ölçülür: dosyada duran uzun ömürlü anahtar, ortam değişkenindeki sır ve çalışma ortamının verdiği kimlik. Sızıntı yüzeyi, döndürme işi ve kimliğin kapsamı sayılır; kenar ile işlev katmanında kimliğin nasıl verildiği ayrı çıkarılır.

Önceki ders insan kimliklerini geçici hâle getirdi: yetki üstlenilerek alınıyor, iş bitince
düşüyor. Kod için aynı şey söylenemez. Ölçüm ağının iş yükü örnekleri gece boyunca veri deposuna
yazıyor ve bunu yaparken bir yerde duran bir anahtarı okuyor. O anahtar kurulum günü
yazıldı; ne zaman değişeceği hiçbir yerde yazmıyor. Sırrın ömrü ve sızıntı penceresi M22/K07'de
ölçüldü, burada tekrarlanmıyor. Bu dersin sorusu ömür değil, **yer** ve **kapsam**: kimlik kaç ayrı
yerde duruyor, değiştirmek kaç yere dokunmayı gerektiriyor ve bir işlem ele geçirildiğinde o
kimlikle kaç iş daha açılıyor. Üç yol yan yana konuyor — dosyada duran uzun ömürlü anahtar, ortam
değişkenine konmuş sır ve çalışma ortamının verdiği kimlik.

- **BI25.** On iş yükü, üç konak, üç ortam ve on iki kenar noktası kurgusal bölgesel ölçüm ağına
  aittir. Gerçek anahtar, sır ya da kimlik bilgisi yazılmadı; adlar uydurmadır. Ölçülen şey `node`
  ile yazılan modeldir.
- **BI26.** Rastgelelik yok; sayılar model tablolarından türetiliyor ve çıktı koşumdan koşuma aynı.
- **BI27.** Kimliğin ömrü ve sızıntı penceresi ölçülmüyor. Sayılan üç şey var: kimliğin durduğu
  yer, döndürmenin dokunduğu yer ve kimliğin kapsamı.
- **BI28.** Bir yer ya kalıcıdır ya geçici, ya erişim kaydı tutar ya tutmaz; kısmi kayıt
  modellenmiyor.
- **BI29.** Konak kapsamlı kimlikte konaktaki her işlem konağın kimliğini okuyabiliyor; işlemler
  arası yalıtım modellenmiyor. Gerçekte yalıtım kalemi düşürür, sıfırlamaz.
- **BI30.** Kenar katmanında çalışma ortamının verdiği kimlik yok; kimlik dağıtım paketiyle gidiyor.
  Bu bir model kararıdır — kenar noktalarının yerel kimlik uç noktası taşımadığı varsayıldı.

#### Kimliğin Durduğu Yer

Model on iş yükünü, hangi konakta koştuklarını ve her birinin ihtiyaç duyduğu izinleri tutuyor. Kap
ve makine katmanındaki yedi iş yükü üç konağa dağılmış; işlev ve kenar katmanındaki üçünün konağı
yok. `YER` tablosu her yol için kimliğin durduğu yerleri, her yerin sistemde kaç kez var olduğunu,
kalıcı olup olmadığını ve erişim kaydı tutup tutmadığını veriyor.

```js
// kimlik.mjs — is yuku, konak ve kimlik verme yolu modeli
// Kurgusal bolgesel olcum agi; gercek anahtar, sir ya da kimlik bilgisi yok, adlar uydurma.
export const ORTAM = ['gelistirme', 'hazirlik', 'uretim'];
export const IS_YUKU = {
  'okuma-toplayici':   { katman: 'kap',    konak: 'k1', izin: ['olcum-yaz', 'kuyruk-yaz'] },
  'dogrulayici':       { katman: 'kap',    konak: 'k1', izin: ['olcum-oku', 'kuyruk-oku', 'olcum-yaz'] },
  'gunluk-tasiyici':   { katman: 'kap',    konak: 'k1', izin: ['gunluk-yaz', 'yapilandirma-oku'] },
  'faturalama':        { katman: 'kap',    konak: 'k2', izin: ['fatura-oku', 'fatura-yaz', 'posta-gonder'] },
  'is-emri':           { katman: 'kap',    konak: 'k2', izin: ['is-emri-yaz', 'kuyruk-oku', 'posta-gonder'] },
  'gecelik-toplu-is':  { katman: 'makine', konak: 'm1', izin: ['olcum-oku', 'arsiv-yaz', 'fatura-oku'] },
  'arsivleyici':       { katman: 'makine', konak: 'm1', izin: ['arsiv-oku', 'arsiv-yaz'] },
  'olcut-ozeti':       { katman: 'islev',  konak: null, izin: ['olcum-oku'] },
  'rapor-uretici':     { katman: 'islev',  konak: null, izin: ['fatura-oku', 'arsiv-oku'] },
  'kenar-dogrulayici': { katman: 'kenar',  konak: null, izin: ['olcum-yaz'] },
};
export const AD = Object.keys(IS_YUKU);
export const KONAK = ['k1', 'k2', 'm1'];
export const KENAR_NOKTA = 12;                     // kenar katmaninin dagitildigi nokta
// Olcek adlari: bir yerin sistemde kac kez var oldugu.
export const OLCEK = {
  ornek: AD.length * ORTAM.length,                 // (is yuku, ortam) cifti
  konak: KONAK.length * ORTAM.length,
  tek: 1,
};
// Kimligin durdugu yer: [ad, olcek, kalici mi, erisim kaydi tutuyor mu, dondurme nasil ulasiyor]
export const YER = {
  'dosyada-anahtar': [
    ['ornek-diski', 'ornek', true, false, 'elle'], ['makine-goruntusu', 'konak', true, false, 'elle'],
    ['yapilandirma-deposu', 'ornek', true, true, 'elle'], ['yedek', 'konak', true, false, 'ulasilmaz'],
    ['gelistirici-dizustu', 'tek', true, false, 'ulasilmaz']],
  'ortam-degiskeni': [
    ['dagitim-tanimi', 'ornek', true, true, 'elle'], ['surec-ortami', 'ornek', false, false, 'yeniden-baslatma'],
    ['cokme-dokumu', 'konak', true, false, 'ulasilmaz']],
  'ortamin-verdigi': [
    ['surec-bellegi', 'ornek', false, true, 'kendiliginden']],
};
export const YOL = Object.keys(YER);
// Kimlik surec baslarken mi okunuyor: oyleyse dondurme yeniden baslatma istiyor.
export const BASLANGICTA_OKUNUR = { 'dosyada-anahtar': true, 'ortam-degiskeni': true, 'ortamin-verdigi': false };
export const adet = (y) => OLCEK[y[1]];
export const topla = (yol, sec) => YER[yol].filter(sec).reduce((a, y) => a + adet(y), 0);
// Konak kapsamli kimlikte bir konagin tasidigi izin, uzerindeki is yuklerinin birlesimidir.
export const konakIzni = (k) =>
  [...new Set(AD.filter((a) => IS_YUKU[a].konak === k).flatMap((a) => IS_YUKU[a].izin))];
export const konakta = (k) => AD.filter((a) => IS_YUKU[a].konak === k);
// Katman basina ortamin verdigi kimligin var olup olmadigi ve en dar kapsami.
export const KATMAN = {
  makine: [true, 'konak'], kap: [true, 'ornek'], islev: [true, 'cagri'], kenar: [false, 'dagitim'],
};
```

```js
// kosum1.mjs — uc yolun sizinti yuzeyi ve dondurme isi tek tabloda
import { AD, ORTAM, OLCEK, YER, YOL, topla, BASLANGICTA_OKUNUR } from './kimlik.mjs';

const G = [5, 7, 8, 10, 7, 10, 13];                // sutun genislikleri
const satir = (ad, v) => ad.padEnd(18) + v.map((x, i) => String(x).padStart(G[i])).join('');
const say = (yol, mod) => topla(yol, (y) => y[4] === mod);
console.log(`is yuku ${AD.length}, ortam ${ORTAM.length}, ornek ${OLCEK.ornek}, konak kalemi ${OLCEK.konak}\n`);
console.log(satir('', ['', '', '', '', 'elle', 'yeniden', 'ulasilmayan']));
console.log(satir('yol', ['yer', 'kopya', 'kalici', 'kayitsiz', 'dokun', 'baslatma', 'kopya']));
for (const yol of YOL)
  console.log(satir(yol, [YER[yol].length, topla(yol, () => true), topla(yol, (y) => y[2]),
    topla(yol, (y) => !y[3]), say(yol, 'elle'), BASLANGICTA_OKUNUR[yol] ? OLCEK.ornek : 0,
    say(yol, 'ulasilmaz')]));
```

```
is yuku 10, ortam 3, ornek 30, konak kalemi 9

                                                   elle   yeniden  ulasilmayan
yol                 yer  kopya  kalici  kayitsiz  dokun  baslatma        kopya
dosyada-anahtar       5     79      79        49     69        30           10
ortam-degiskeni       3     69      39        39     30        30            9
ortamin-verdigi       1     30       0         0      0         0            0
```

Dosyada duran anahtar beş ayrı yerde, toplam yetmiş dokuz kopya hâlinde duruyor ve hepsi kalıcı.
Kırk dokuz kopya erişim kaydı tutmayan yerlerde. Ortam değişkeni yolu yer sayısını üçe indiriyor
ama toplam kopyayı yalnız altmış dokuza düşürüyor; asıl fark kalıcı ve kayıtsız sütunlarında, her
ikisi de otuz dokuza iniyor.

Üçüncü satır ölçüyü yerine oturtuyor. Çalışma ortamının verdiği kimlikte kalıcı kopya
sıfır, kayıtsız kopya sıfır. Otuz kopya var — her örneğin belleğinde bir tane — ama hepsi kimlik uç
noktasından alınırken kaydediliyor. Kazanç kopyanın azalması değil; kalıcı kopyanın yetmiş dokuzdan
sıfıra inmesi ve kırk dokuz sessiz okumanın kaydedilir hâle gelmesidir.

#### Döndürme İşi

Tablonun sağ üç sütunu maliyet tarafıdır. Bu sütunların nereden geldiğini görmek için yerlerin tek
tek dökülmesi gerekiyor.

```js
// kosum2.mjs — kimligin durdugu yerler ve dondurmenin oralara nasil ulastigi
import { YER, YOL, adet } from './kimlik.mjs';

for (const yol of YOL) {
  console.log(yol);
  for (const y of YER[yol])
    console.log(`  ${y[0].padEnd(21)}${String(adet(y)).padStart(3)}  ${(y[2] ? 'kalici' : 'gecici')}` +
      `  kayit ${(y[3] ? 'var' : 'yok').padEnd(4)} dondurme: ${y[4]}`);
}
```

```
dosyada-anahtar
  ornek-diski           30  kalici  kayit yok  dondurme: elle
  makine-goruntusu       9  kalici  kayit yok  dondurme: elle
  yapilandirma-deposu   30  kalici  kayit var  dondurme: elle
  yedek                  9  kalici  kayit yok  dondurme: ulasilmaz
  gelistirici-dizustu    1  kalici  kayit yok  dondurme: ulasilmaz
ortam-degiskeni
  dagitim-tanimi        30  kalici  kayit var  dondurme: elle
  surec-ortami          30  gecici  kayit yok  dondurme: yeniden-baslatma
  cokme-dokumu           9  kalici  kayit yok  dondurme: ulasilmaz
ortamin-verdigi
  surec-bellegi         30  gecici  kayit var  dondurme: kendiliginden
```

Dosyadaki anahtarı değiştirmek altmış dokuz yere elle dokunmayı ve otuz örneği yeniden başlatmayı
gerektiriyor; toplam doksan dokuz dokunuş. Ortam değişkeninde elle dokunuş otuza iniyor, çünkü süreç
ortamı yeniden başlatmayla kendiliğinden yenileniyor. Üçüncü yolda iki sütun da sıfır — döndürme
diye ayrı bir iş yok.

Asıl bulgu son sütundadır. Dosya yolunda döndürme on kopyaya hiç ulaşmıyor: dokuz yedek ve bir
geliştirici dizüstü. Ortam değişkeninde dokuz çökme dökümü aynı durumda ve üçünün de kaydı yok.
Eskisini iptal etmek ayrı bir adımdır ve ulaşılamayan kopya varken iptalin güvenle yapılıp
yapılamayacağı bilinmiyor: bir yedekten dönen makine iptal edilmiş anahtarla açılır. Doksan dokuz
dokunuşluk işin sonunda kapanmayan kalem sıfır değil, on.

#### Kimliğin Kapsamı

Üçüncü ölçü kapsamdır: kimlik bir örneğe mi verilmiş, yoksa o örneğin koştuğu konağa mı. Konak
kapsamlı kimlikte konaktaki her işlem aynı kimliği okuyabiliyor, dolayısıyla kimliğin izni konaktaki
bütün iş yüklerinin izinlerinin birleşimidir.

```js
// kosum3.mjs — kimligin kapsami: konak kapsamli kimlik kac izni ve kac isi fazladan aciyor
import { AD, ORTAM, IS_YUKU, KONAK, konakIzni, konakta } from './kimlik.mjs';

console.log('konak  is yuku  birlesim izni  izinler');
for (const k of KONAK) {
  const u = konakIzni(k);
  console.log(`${k.padEnd(7)}${String(konakta(k).length).padStart(7)}${String(u.length).padStart(15)}  ${u.join(', ')}`);
}
console.log('\nis yuku            kapsam   kendi  konak  fazladan  fazladan');
console.log('                            izni   izni    izin      is yuku');
let kendi = 0, konakli = 0, fazlaIs = 0;
for (const a of AD) {
  const w = IS_YUKU[a], k = w.konak;
  const konakN = k ? konakIzni(k).length : w.izin.length;
  const fazlaIsY = k ? konakta(k).length - 1 : 0;
  kendi += w.izin.length; konakli += konakN; fazlaIs += fazlaIsY;
  console.log(`${a.padEnd(19)}${(k ?? 'konaksiz').padEnd(9)}${String(w.izin.length).padStart(5)}` +
    `${String(konakN).padStart(7)}${String(konakN - w.izin.length).padStart(9)}${String(fazlaIsY).padStart(10)}`);
}
const O = ORTAM.length;
console.log('');
for (const [ad, v] of [
  ['ornek kapsamli kimlikte (ornek, izin)', kendi * O],
  ['konak kapsamli kimlikte (ornek, izin)', konakli * O],
  ['fazladan verilen izin kalemi', `${(konakli - kendi) * O}  (%${Math.round(((konakli - kendi) / kendi) * 100)})`],
  ['fazladan erisilen (ornek, is yuku) kalemi', fazlaIs * O],
  ['tek ornekten en cok fazladan acilan is', Math.max(...KONAK.map((k) => konakta(k).length - 1))],
  ['fazladan hicbir sey acmayan ornek', `${AD.filter((a) => !IS_YUKU[a].konak).length * O} / ${AD.length * O}`],
]) console.log(`${ad.padEnd(42)}${v}`);
```

```
konak  is yuku  birlesim izni  izinler
k1           3              6  olcum-yaz, kuyruk-yaz, olcum-oku, kuyruk-oku, gunluk-yaz, yapilandirma-oku
k2           2              5  fatura-oku, fatura-yaz, posta-gonder, is-emri-yaz, kuyruk-oku
m1           2              4  olcum-oku, arsiv-yaz, fatura-oku, arsiv-oku

is yuku            kapsam   kendi  konak  fazladan  fazladan
                            izni   izni    izin      is yuku
okuma-toplayici    k1           2      6        4         2
dogrulayici        k1           3      6        3         2
gunluk-tasiyici    k1           2      6        4         2
faturalama         k2           3      5        2         1
is-emri            k2           3      5        2         1
gecelik-toplu-is   m1           3      4        1         1
arsivleyici        m1           2      4        2         1
olcut-ozeti        konaksiz     1      1        0         0
rapor-uretici      konaksiz     2      2        0         0
kenar-dogrulayici  konaksiz     1      1        0         0

ornek kapsamli kimlikte (ornek, izin)     66
konak kapsamli kimlikte (ornek, izin)     120
fazladan verilen izin kalemi              54  (%82)
fazladan erisilen (ornek, is yuku) kalemi 30
tek ornekten en cok fazladan acilan is    2
fazladan hicbir sey acmayan ornek         9 / 30
```

Üst blok birleşimin ne kadar büyüdüğünü gösteriyor. `k1` üzerinde üç iş yükü var, hiçbirinin
ihtiyacı üçten fazla izin değil, konağın birleşim izni altı. Günlük taşıyıcı iki izne ihtiyaç
duyuyor ama konak kimliğiyle altı izin taşıyor; fazladan gelen dördün ikisi ölçüm ve kuyruk
yazmadır — günlük taşıyıcının hiç dokunmadığı iki veri yolu.

Alt blok sistem toplamıdır. Örnek kapsamlı kimlikte altmış altı `(örnek, izin)` kalemi var, konak
kapsamlı kimlikte yüz yirmi. Fazladan verilen elli dört kalem, gerçek ihtiyacın yüzde seksen ikisi
kadar. Bir örneğin ele geçirilmesi otuz `(örnek, iş yükü)` kaleminde fazladan erişim açıyor; en kötü
durumda tek bir işlemden iki iş yükü daha açılıyor.

Son satır kapsam ölçüsünün sınırını söylüyor: otuz örneğin dokuzu konak paylaşmıyor, kapsam sorusu
onlarda hiç doğmuyor. Kapsam kalemi, konak paylaşımının kalemidir. Kimliği dosyadan çalışma ortamına
taşımak yer ve döndürme sütunlarını sıfırlıyor ama bu sütunu sıfırlamıyor — çalışma ortamının
verdiği kimlik de konak kapsamlı olabilir.

#### Kenar ve İşlev Katmanı

Kapsam katmana göre değişiyor: çalışma ortamı kimliği her katmanda aynı biçimde vermiyor,
bazılarında hiç vermiyor.

```js
// kosum4.mjs — kenar ve islev katmaninda kimlik nasil veriliyor: kapsam ve kalici kopya ayri sayilir
import { AD, ORTAM, IS_YUKU, KATMAN, KENAR_NOKTA } from './kimlik.mjs';

const O = ORTAM.length;
const katmanda = (kt) => AD.filter((a) => IS_YUKU[a].katman === kt);
const kalici = (kt) => (KATMAN[kt][0] ? 0 : katmanda(kt).length * KENAR_NOKTA * O);
console.log('katman  is yuku  ornek  ortamin verdigi  en dar    kalici  dondurmede');
console.log('                        kimlik           kapsam    kopya   dokunus');
for (const kt of Object.keys(KATMAN)) {
  const n = katmanda(kt).length;
  console.log(`${kt.padEnd(8)}${String(n).padStart(7)}${String(n * O).padStart(7)}  ` +
    `${(KATMAN[kt][0] ? 'var' : 'yok').padEnd(17)}${KATMAN[kt][1].padEnd(10)}` +
    `${String(kalici(kt)).padStart(6)}${String(kalici(kt)).padStart(10)}`);
}
const alan = Object.keys(KATMAN).filter((k) => KATMAN[k][0]);
const dar = alan.filter((k) => KATMAN[k][1] !== 'konak');
const say = (ks) => ks.reduce((a, k) => a + katmanda(k).length * O, 0);
console.log('');
for (const [ad, v] of [
  ['ortamin verdigi kimligi alabilen ornek', `${say(alan)} / ${AD.length * O}`],
  ['ornek ya da daha dar kapsam alabilen', `${say(dar)} / ${AD.length * O}`],
  ['konak kapsaminda kalan ornek', `${say(alan.filter((k) => KATMAN[k][1] === 'konak'))} / ${AD.length * O}`],
  ['hic alamayan ornek', `${say(Object.keys(KATMAN).filter((k) => !KATMAN[k][0]))} / ${AD.length * O}`],
  ['en iyi yolda sistemde kalan kalici kopya', Object.keys(KATMAN).reduce((a, k) => a + kalici(k), 0)],
]) console.log(`${ad.padEnd(42)}${v}`);
```

```
katman  is yuku  ornek  ortamin verdigi  en dar    kalici  dondurmede
                        kimlik           kapsam    kopya   dokunus
makine        2      6  var              konak          0         0
kap           5     15  var              ornek          0         0
islev         2      6  var              cagri          0         0
kenar         1      3  yok              dagitim       36        36

ortamin verdigi kimligi alabilen ornek    27 / 30
ornek ya da daha dar kapsam alabilen      21 / 30
konak kapsaminda kalan ornek              6 / 30
hic alamayan ornek                        3 / 30
en iyi yolda sistemde kalan kalici kopya  36
```

Makine katmanında kimlik var ama en dar kapsam konaktır: makineye verilen kimliği o makinede koşan
her şey okuyabiliyor. Kap katmanında örnek kapsamı mümkün, her iş yükü kendi kimliğini alabiliyor.
İşlev katmanı en darıdır — kimlik çağrı başına veriliyor, çağrı bitince ortadan kalkıyor, kalıcı
kopya sıfır.

Kenar satırı ötekilerden ayrı duruyor. Kenar noktalarında yerel bir kimlik uç noktası yok; kimlik
dağıtım paketinin içinde gidiyor ve on iki nokta çarpı üç ortam otuz altı kalıcı kopya ediyor.
Döndürme de aynı otuz altı yere dokunuyor. Kimliği en kötü koşullarda taşıyan katman, dışarıya bakan
katmandır.

Alt blok toplamı veriyor. Otuz örneğin yirmi yedisi çalışma ortamının verdiği kimliği alabiliyor ama
yalnız yirmi biri örnek ya da daha dar kapsam alabiliyor; altısı konak kapsamında kalıyor, üçü hiç
alamıyor. En iyi yol seçildiğinde bile sistemde otuz altı kalıcı kopya kalıyor, hepsi tek bir
katmanda. Yetmiş dokuzdan otuz altıya inmek gerçek bir kazançtır ama sıfır olmuyor; kalan kalem
katmanın verdiği imkânsızlıktan kalıyor.

#### Özet

- Dosyada duran anahtar 5 yerde 79 kopya hâlinde ve hepsi kalıcı; 49'u erişim kaydı tutmayan bir
  yerde. Ortam değişkeni kalıcı kopyayı 39'a indiriyor. Çalışma ortamının verdiği kimlikte 30 kopya
  var ama kalıcı kopya 0, kayıtsız kopya 0 — kazanç kopya sayısında değil, kopyanın kalıcılığında
  ve kaydedilebilirliğindedir.
- Döndürme dosya yolunda 69 elle dokunuş ve 30 yeniden başlatma, ortam değişkeninde 30 dokunuş ve
  30 yeniden başlatma, çalışma ortamı kimliğinde 0 istiyor.
- Döndürmenin hiç ulaşamadığı kopya dosya yolunda 10 (9 yedek, 1 dizüstü), ortam değişkeninde 9
  (çökme dökümü); bunlar iptalin güvenle yapılıp yapılamayacağını belirsiz bırakıyor.
- Konak kapsamlı kimlik `(örnek, izin)` kalemini 66'dan 120'ye çıkarıyor: 54 fazladan izin, gerçek
  ihtiyacın %82'si. Ele geçen bir örnek 30 `(örnek, iş yükü)` kaleminde fazladan erişim açıyor; 30
  örneğin 9'unda konak paylaşımı olmadığı için bu kalem hiç doğmuyor.
- Katman kimliği belirliyor: 30 örneğin 27'si çalışma ortamının kimliğini alabiliyor ama yalnız
  21'i örnek ya da daha dar kapsam alabiliyor, 6'sı konak kapsamında kalıyor, 3'ü hiç alamıyor.
- En iyi yolda bile 36 kalıcı kopya kalıyor ve hepsi kenar katmanında; orada yerel kimlik uç noktası
  olmadığı için kimlik dağıtım paketiyle 12 noktaya çoğalıyor.

#### Sonraki Adım

Bu ders kimliğin nereden geldiğini değiştirdi ama o kimliğin ne yapabildiğine hiç bakmadı. Kapsam
ölçülürken çıkan sayı bunu zaten söylüyor: `k1` kimliği altı izin taşıyor ve üstündeki üç iş
yükünün hiçbiri altısını birden kullanmıyor. Örnek kapsamına inildiğinde bile aynı soru duruyor —
bir iş yüküne yazılan izin kümesi, o iş yükünün gerçekten kullandığı kümeyle aynı mı? Sonraki dersin
sorusu budur. Kullanım geçmişi ile verilmiş politika yan yana konduğunda kullanılmayan izin oranı
kaç çıkıyor, daraltılmış politika kaç satır ediyor ve daraltma kaç meşru işi durduruyor — geçmişte
hiç görünmemiş ama gerekli olan nadir yol, daraltmanın bedelidir.

### En Az Yetki Uygulaması

Source: https://academia.sh/tr/kurslar/bulut-yonetisimi/en-az-yetki-uygulamasi

Verilen izin ile kullanılan izin yan yana konur: kullanılmayan izin oranı, daraltılmış politikanın satır sayısı ve daraltmanın durdurduğu meşru iş sayılır. Gözlem penceresi taranır ve güvenli daraltma eşiği sayıyla verilir.

Önceki ders kimliğin nereden geldiğini değiştirdi; ne yapabildiği açık kaldı. Politika belgeleri
yazılırken izinler çoğunlukla tek tek değil aile düzeyinde verilir: bir satır ölçüm ailesinin bütün
izinlerini açar, çünkü satır yazmak pahalı, izin saymak ucuzdur. Bu dersin sorusu o satırların ne
kadarının gerçekten kullanıldığıdır. Verilen izin kümesi ile kullanım geçmişi yan yana konuyor ve
üç şey sayılıyor: **kullanılmayan izin oranı**, daraltılmış politikanın kaç satır ettiği ve
**daraltmanın kaç meşru işi durdurduğu**. Üçüncüsü ilk ikisi kadar önemlidir: geçmişte hiç görünmemiş
bir yol, gerekli olmadığı anlamına gelmez.

- **BI31.** Sekiz iş yükü, sekiz kaynak ailesi ve on sekiz izin kurgusal bölgesel ölçüm ağına
  aittir; ölçülen şey `node` ile yazılan modeldir.
- **BI32.** Gerçek ihtiyaç listesi ölçülmedi, seçildi; her yolun ortalama kullanım aralığı bir model
  kararıdır. Gerçekte bu liste bilinmez — dersin noktası zaten onun bilinmemesidir.
- **BI33.** Kullanım geçmişi kendi yazılan doğrusal eşlemeli üreteçle üretildi. Tohum görünür ve
  sabittir; çıktı koşumdan koşuma aynı kalır.
- **BI34.** Bir izin ya kullanıldı ya kullanılmadı. Koşul ifadesi ve kaynak düzeyinde daraltma
  modellenmiyor; bunlar daraltmayı derinleştirir, yönünü değiştirmez.
- **BI35.** Verilen politika aile düzeyinde yazıldı, daraltılmış politika izin düzeyinde yazılıyor.
  Satır sayısı bu yüzden ayrı bir ölçüdür.
- **BI36.** Sınama dönemi ikinci doksan gündür ve aynı üreteç akışından gelir. Daraltılmış
  politikanın kaç meşru işi durdurduğu orada sayılıyor.

#### Verilen İzin ile Gerçek İhtiyaç

Model üç şeyi ayrı tutuyor: aile düzeyinde yazılmış politika, onun açtığı izin kümesi ve her iş
yükünün gerçekten ihtiyaç duyduğu yollar. Üçüncüsü gerçek bir sistemde bilinmez; burada bilinir
kılınıyor ki daraltmanın isabeti ölçülebilsin.

```js
// yetki.mjs — verilen izin, gercek ihtiyac ve kullanim gecmisi modeli
// Kurgusal bolgesel olcum agi; sekiz is yuku, sekiz kaynak ailesi. Olculen sey bu modeldir.
export const AILE = {
  olcum: ['oku', 'yaz', 'sil'], kuyruk: ['oku', 'yaz', 'yonet'], arsiv: ['oku', 'yaz', 'sil'],
  fatura: ['oku', 'yaz'], 'is-emri': ['oku', 'yaz'], gunluk: ['oku', 'yaz'],
  yapilandirma: ['oku', 'yaz'], posta: ['gonder'],
};
export const IZIN = Object.entries(AILE).flatMap(([a, e]) => e.map((x) => `${a}-${x}`));
// Verilen politika aile duzeyinde yazildi: bir satir bir ailenin butun izinlerini veriyor.
export const VERILEN = {
  'okuma-toplayici': ['olcum', 'kuyruk'], 'dogrulayici': ['olcum', 'kuyruk'],
  'gunluk-tasiyici': ['gunluk', 'yapilandirma'], 'faturalama': ['fatura', 'posta', 'arsiv'],
  'is-emri': ['is-emri', 'kuyruk', 'posta'], 'gecelik-toplu-is': ['olcum', 'arsiv', 'fatura'],
  'arsivleyici': ['arsiv'], 'rapor-uretici': ['fatura', 'arsiv', 'gunluk'],
};
export const OZNE = Object.keys(VERILEN);
// Gercek ihtiyac: izin -> ortalama kullanim araligi (gun). Model karari; olculmedi, secildi.
export const GERCEK = {
  'okuma-toplayici': { 'olcum-yaz': 1, 'kuyruk-yaz': 1, 'olcum-oku': 3 },
  'dogrulayici': { 'olcum-oku': 1, 'kuyruk-oku': 1, 'olcum-yaz': 2, 'olcum-sil': 30 },
  'gunluk-tasiyici': { 'gunluk-yaz': 1, 'yapilandirma-oku': 7 },
  'faturalama': { 'fatura-oku': 1, 'fatura-yaz': 1, 'posta-gonder': 2, 'arsiv-oku': 45 },
  'is-emri': { 'is-emri-yaz': 1, 'is-emri-oku': 1, 'kuyruk-oku': 1, 'posta-gonder': 5 },
  'gecelik-toplu-is': { 'olcum-oku': 1, 'arsiv-yaz': 1, 'fatura-oku': 7, 'olcum-sil': 20 },
  'arsivleyici': { 'arsiv-oku': 1, 'arsiv-yaz': 1, 'arsiv-sil': 60 },
  'rapor-uretici': { 'fatura-oku': 1, 'arsiv-oku': 7, 'gunluk-oku': 30 },
};
export const DONEM = 90;                             // gozlenen gun sayisi
export const TOHUM = 20260802;                       // uretecin tohumu; gorunur ve sabit
export const PENCERE = [1, 7, 14, 30, 60, 90];
export const verilenIzin = (o) => VERILEN[o].flatMap((a) => AILE[a].map((x) => `${a}-${x}`));
export const verilenCift = OZNE.flatMap((o) => verilenIzin(o).map((i) => `${o}|${i}`));
export const gercekCift = OZNE.flatMap((o) => Object.keys(GERCEK[o]).map((i) => `${o}|${i}`));
export const araligi = (c) => GERCEK[c.split('|')[0]][c.split('|')[1]];
// Kendi uretecimiz: dogrusal eslesmeli uretec; tohumdan baslar, kosumdan kosuma ayni diziyi verir.
export function uretec(tohum) {
  let s = tohum >>> 0;
  return () => { s = (Math.imul(s, 1664525) + 1013904223) >>> 0; return s / 4294967296; };
}
// Gecmis: her gun her gercek cift 1/aralik olasilikla kullanilir.
export function gecmisUret(gun, tohum) {
  const r = uretec(tohum), g = [];
  for (let d = 0; d < gun; d++)
    for (const c of gercekCift) if (r() < 1 / araligi(c)) g.push([d, c]);
  return g;
}
```

```js
// kosum1.mjs — verilen izin ile gercek ihtiyac yan yana: kullanilmayan izin orani
import { OZNE, VERILEN, GERCEK, IZIN, verilenIzin, verilenCift, gercekCift } from './yetki.mjs';

console.log('ozne              satir  verilen  gercek  kullanilmayan');
let satir = 0;
for (const o of OZNE) {
  const v = verilenIzin(o), g = Object.keys(GERCEK[o]);
  satir += VERILEN[o].length;
  console.log(`${o.padEnd(18)}${String(VERILEN[o].length).padStart(5)}${String(v.length).padStart(9)}` +
    `${String(g.length).padStart(8)}${String(v.length - g.length).padStart(15)}`);
}
const kullanilmayan = verilenCift.length - gercekCift.length;
console.log('');
for (const [ad, v] of [
  ['izin katalogu', IZIN.length],
  ['verilen politika satiri (ozne, aile)', satir],
  ['verilen (ozne, izin) kalemi', verilenCift.length],
  ['gercekten gereken kalem', gercekCift.length],
  ['kullanilmayan izin kalemi', `${kullanilmayan}  (%${Math.round((kullanilmayan / verilenCift.length) * 100)})`],
]) console.log(`${ad.padEnd(38)}${v}`);
```

```
ozne              satir  verilen  gercek  kullanilmayan
okuma-toplayici       2        6       3              3
dogrulayici           2        6       4              2
gunluk-tasiyici       2        4       2              2
faturalama            3        6       4              2
is-emri               3        6       4              2
gecelik-toplu-is      3        8       4              4
arsivleyici           1        3       3              0
rapor-uretici         3        7       3              4

izin katalogu                         18
verilen politika satiri (ozne, aile)  19
verilen (ozne, izin) kalemi           46
gercekten gereken kalem               27
kullanilmayan izin kalemi             19  (%41)
```

On dokuz satırlık politika kırk altı `(özne, izin)` kalemi açıyor; gerçekten gereken yirmi yedi.
On dokuz kalem, yani verilen iznin yüzde kırk biri hiç kullanılmıyor. Bu kalemler yanlışlıkla
eklenmedi — hiçbiri tek tek yazılmadı. Aile düzeyinde yazılan bir satır, ailenin bütün izinlerini
birlikte getirdi.

Satır sütunu farkın nereden geldiğini gösteriyor. Arşivleyici tek satırla üç izin alıyor ve üçünü
de kullanıyor; kullanılmayan izni sıfır. Rapor üretici üç satırla yedi izin alıyor ve üçünü
kullanıyor; dördü boşta. Gecelik toplu iş üç satırla sekiz izin alıyor, dördü boşta. Bir satır ne
kadar geniş bir aileye dokunuyorsa fazlalık o kadar büyüyor; ölçüm ve arşiv aileleri üçer izin
taşıyor ve fazlalığın çoğu bu iki ailenin silme izninde birikiyor.

#### Kullanım Geçmişi

Kullanılmayan izni gerçek bir sistemde bulmanın tek yolu geçmişe bakmaktır. Model doksan günlük bir
kullanım geçmişi üretiyor; ardından gelen doksan gün sınama dönemi olarak ayrılıyor.

```js
// kosum2.mjs — 90 gunluk kullanim gecmisi uretilir; nadir yollar ayri sayilir
import { DONEM, TOHUM, gercekCift, araligi, gecmisUret } from './yetki.mjs';

const tam = gecmisUret(2 * DONEM, TOHUM);            // ilk donem gozlem, ikincisi sinama
const gecmis = tam.filter(([d]) => d < DONEM);
const sayim = new Map(gercekCift.map((c) => [c, 0]));
for (const [, c] of gecmis) sayim.set(c, sayim.get(c) + 1);
console.log(`tohum ${TOHUM}, donem ${DONEM} gun, olay ${gecmis.length}, sinama donemi ${tam.length - gecmis.length} olay\n`);
console.log('araligi 7 gun ve uzeri olan gercek yollar:');
console.log('cift                              aralik  90 gunde  ilk gorulme');
for (const c of gercekCift.filter((x) => araligi(x) >= 7)) {
  const ilk = gecmis.find(([, x]) => x === c);
  console.log(`${c.padEnd(34)}${String(araligi(c)).padStart(6)}${String(sayim.get(c)).padStart(10)}` +
    `${(ilk ? `${ilk[0] + 1}. gun` : 'gorulmedi').padStart(13)}`);
}
const gorulen = new Set(gecmis.map(([, c]) => c));
console.log('');
for (const [ad, v] of [
  ['gercek yol', gercekCift.length],
  ['90 gunde en az bir kez gorulen', gorulen.size],
  ['90 gunde hic gorulmeyen gercek yol', gercekCift.filter((c) => !gorulen.has(c)).join(', ') || 'yok'],
]) console.log(`${ad.padEnd(36)}${v}`);
```

```
tohum 20260802, donem 90 gun, olay 1545, sinama donemi 1521 olay

araligi 7 gun ve uzeri olan gercek yollar:
cift                              aralik  90 gunde  ilk gorulme
dogrulayici|olcum-sil                 30         1       8. gun
gunluk-tasiyici|yapilandirma-oku       7        12       1. gun
faturalama|arsiv-oku                  45         2      25. gun
gecelik-toplu-is|fatura-oku            7        15       3. gun
gecelik-toplu-is|olcum-sil            20         7       5. gun
arsivleyici|arsiv-sil                 60         0    gorulmedi
rapor-uretici|arsiv-oku                7         9       6. gun
rapor-uretici|gunluk-oku              30         3      25. gun

gercek yol                          27
90 gunde en az bir kez gorulen      26
90 gunde hic gorulmeyen gercek yol  arsivleyici|arsiv-sil
```

Doksan günde bin beş yüz kırk beş olay birikiyor ama bu sayı yanıltıcıdır: olayların ezici çoğunluğu
günlük koşan on beş yoldan geliyor. Tablo yalnız aralığı bir haftadan uzun olanları listeliyor.
Doğrulayıcının silme izni doksan günde bir kez kullanıldı, sekizinci gün; faturalama arşivi iki kez
okudu, ilki yirmi beşinci gün.

Son satır bu dersin sert bulgusudur. Arşivleyicinin silme izni doksan günün hiçbir gününde
kullanılmadı. Yirmi yedi gerçek yoldan yirmi altısı görüldü, biri görülmedi — ve görülmeyen o yol
gerçek bir yoldur. Geçmişe bakan bir daraltma onu kullanılmayan izin sayar ve keser. Kesildikten
sonra ne olacağı, o yolun ne zaman koşacağına bağlıdır; altmış günde bir koşan bir yol için bu,
kesmeden sonraki herhangi bir gün olabilir.

#### Gözlem Penceresi Taraması

Gözlem penceresi bir seçimdir: kısa pencere daha çok keser, uzun pencere daha az yanılır. İkisi
arasındaki değiş tokuş sayıyla çıkarılabilir.

```js
// kosum3.mjs — gozlem penceresi taranir: ne kadar kesiyor, ne kadar yanlis kesiyor
import { DONEM, TOHUM, PENCERE, verilenCift, gercekCift, gecmisUret } from './yetki.mjs';

const tam = gecmisUret(2 * DONEM, TOHUM);
const gecmis = tam.filter(([d]) => d < DONEM), sinama = tam.filter(([d]) => d >= DONEM);
console.log('pencere  daraltilmis  kullanilmayan  yanlis   sinamada    engellenen');
console.log('(gun)    satir        izin orani     kesme    engellenen  is yuku');
for (const p of PENCERE) {
  const gor = new Set(gecmis.filter(([d]) => d >= DONEM - p).map(([, c]) => c));
  const yanlis = gercekCift.filter((c) => !gor.has(c));
  const engel = sinama.filter(([, c]) => !gor.has(c));
  const oran = Math.round(((verilenCift.length - gor.size) / verilenCift.length) * 100);
  console.log(`${String(p).padEnd(9)}${String(gor.size).padEnd(13)}${`%${oran}`.padEnd(15)}` +
    `${String(yanlis.length).padEnd(9)}${String(engel.length).padEnd(12)}` +
    `${new Set(engel.map(([, c]) => c.split('|')[0])).size}`);
}
console.log('\npencere daraldikca hangi gercek yollar kesiliyor:');
for (const p of PENCERE) {
  const gor = new Set(gecmis.filter(([d]) => d >= DONEM - p).map(([, c]) => c));
  const y = gercekCift.filter((c) => !gor.has(c));
  console.log(`  ${String(p).padStart(2)} gun  ${y.length ? y.slice(0, 4).join(', ') + (y.length > 4 ? ` (+${y.length - 4})` : '') : 'yok'}`);
}
```

```
pencere  daraltilmis  kullanilmayan  yanlis   sinamada    engellenen
(gun)    satir        izin orani     kesme    engellenen  is yuku
1        19           %59            8        69          7
7        22           %52            5        12          4
14       23           %50            4        10          3
30       24           %48            3        5           2
60       25           %46            2        4           1
90       26           %43            1        0           0

pencere daraldikca hangi gercek yollar kesiliyor:
   1 gun  okuma-toplayici|olcum-oku, dogrulayici|olcum-sil, gunluk-tasiyici|yapilandirma-oku, faturalama|arsiv-oku (+4)
   7 gun  dogrulayici|olcum-sil, faturalama|arsiv-oku, gecelik-toplu-is|olcum-sil, arsivleyici|arsiv-sil (+1)
  14 gun  dogrulayici|olcum-sil, faturalama|arsiv-oku, gecelik-toplu-is|olcum-sil, arsivleyici|arsiv-sil
  30 gun  dogrulayici|olcum-sil, faturalama|arsiv-oku, arsivleyici|arsiv-sil
  60 gun  dogrulayici|olcum-sil, arsivleyici|arsiv-sil
  90 gun  arsivleyici|arsiv-sil
```

Tablo tek bir seçimin iki sonucunu yan yana koyuyor. Tek günlük pencere kırk altı kalemin yüzde
elli dokuzunu kesiyor ve daraltılmış politika on dokuz satıra iniyor — verilen politikayla aynı
sayı, ama bu kez izin düzeyinde ve çok daha dar. Bedeli sağdaki iki sütunda: sekiz meşru yol
kesiliyor ve sınama döneminde altmış dokuz iş yedi ayrı iş yükünde duruyor.

Pencere büyüdükçe her iki taraf da yumuşuyor. Otuz günlük pencerede kesme oranı yüzde kırk sekize
düşüyor, yanlış kesme üçe, engellenen iş beşe iniyor. Doksan günlük pencerede yanlış kesme bire,
engellenen iş sıfıra iniyor. Kesilen izin oranı yüzde elli dokuzdan yüzde kırk üçe geriledi; yani
uzun pencerenin bedeli, kesilebilecek on altı puanlık izni kesmemektir.

Son iki satır arasındaki fark dikkat ister. Doksan günlük pencerede yanlış kesme bir, engellenen iş
sıfır. Kesilen yol arşivleyicinin silme iznidir ve sınama döneminde de hiç koşmamıştır. Yanlış
kesmenin faturası kesildiği gün gelmiyor — yol koştuğu gün geliyor. Alt blok sırayı veriyor: pencere
daraldıkça önce nadir yollar, sonra haftalık yollar, en sonunda günlük olmayan her şey
kesiliyor.

#### Güvenli Daraltma Eşiği

Gözlenen doksan gün bir yolu kaçırmaya yetiyorsa, kaç gün yetmez? Bu soru geçmişe değil aralığa
bakarak yanıtlanır: aralığı `d` gün olan bir yolun `p` günlük pencerede hiç görünmeme olasılığı
`(1 − 1/d)^p` değeridir.

```js
// kosum4.mjs — guvenli daraltma esigi: bir yolun kacirilma olasiligi pencereyle nasil dusuyor
import { DONEM, gercekCift, araligi } from './yetki.mjs';

const RISK = 0.01;                                   // kabul edilen kacirma olasiligi
const kacirma = (d, p) => Math.pow(1 - 1 / d, p);
const gereken = (d) => (d === 1 ? 1 : Math.ceil(Math.log(RISK) / Math.log(1 - 1 / d)));
const araliklar = [...new Set(gercekCift.map(araligi))].sort((a, b) => a - b);
console.log('aralik  yol  90 gunde kacirma  %1 risk icin pencere');
for (const d of araliklar) {
  const n = gercekCift.filter((c) => araligi(c) === d).length;
  console.log(`${String(d).padStart(6)}${String(n).padStart(5)}` +
    `${`%${(kacirma(d, DONEM) * 100).toFixed(1)}`.padStart(18)}${String(gereken(d)).padStart(18)} gun`);
}
console.log('');
for (const [ad, v] of [
  ['en nadir gercek yolun araligi', `${Math.max(...araliklar)} gun`],
  ['guvenli daraltma esigi (%1 risk)', `${Math.max(...araliklar.map(gereken))} gun`],
  ['gozlenen pencere', `${DONEM} gun`],
  ['90 gunde beklenen yanlis kesme', gercekCift.reduce((a, c) => a + kacirma(araligi(c), DONEM), 0).toFixed(2)],
]) console.log(`${ad.padEnd(34)}${v}`);
```

```
aralik  yol  90 gunde kacirma  %1 risk icin pencere
     1   15              %0.0                 1 gun
     2    2              %0.0                 7 gun
     3    1              %0.0                12 gun
     5    1              %0.0                21 gun
     7    3              %0.0                30 gun
    20    1              %1.0                90 gun
    30    2              %4.7               136 gun
    45    1             %13.2               205 gun
    60    1             %22.0               275 gun

en nadir gercek yolun araligi     60 gun
guvenli daraltma esigi (%1 risk)  275 gun
gozlenen pencere                  90 gun
90 gunde beklenen yanlis kesme    0.46
```

Tablo eşiği aralık aralık veriyor. Günlük koşan on beş yol için bir gün yetiyor; haftalık koşan üç
yol için otuz gün. Yirmi günlük aralıkta gereken pencere doksan güne çıkıyor — gözlenen dönemin
tamamı, tek bir yol için. Altmış günlük aralıkta gereken pencere iki yüz yetmiş beş gün, yani
gözlenenin üç katı.

Sağdan ikinci sütun doksan günlük pencerede kalan riski veriyor. Altmış günlük yolun kaçırılma
olasılığı yüzde yirmi iki, kırk beş günlük yolun yüzde on üç, otuz günlük iki yolun her biri için
yüzde beş. Toplandığında doksan günde beklenen yanlış kesme sayısı sıfır virgül kırk altı yol;
koşumda gerçekleşen bir yol. Model ile koşum aynı büyüklük mertebesindedir.

Güvenli daraltma eşiği bu tablonun tek satırlık cevabıdır: iki yüz yetmiş beş gün. Bu sayı bir
sistem özelliği değil, en nadir meşru yolun aralığının bir fonksiyonudur; aralığı bilinmeyen bir
sistemde eşik de bilinmez. Doksan günlük pencereyle daraltmak yüzde kırk üç kesme ve yarım yanlış
kesme demektir — kabul edilebilir olup olmadığı, o yarımın hangi iş yükünde çıkacağına bağlıdır.

#### Özet

- Aile düzeyinde yazılmış 19 satırlık politika 46 `(özne, izin)` kalemi açıyor; gerçekten gereken
  27. Kullanılmayan izin 19 kalem, verilen iznin %41'i — ve hiçbiri tek tek yazılmadı, hepsi
  satırın genişliğinden geldi.
- 90 günlük geçmişte 1.545 olay birikiyor ama 27 gerçek yoldan yalnız 26'sı görünüyor. Görünmeyen
  yol arşivleyicinin silme iznidir; aralığı 60 gün ve geçmişe bakan bir daraltma onu keser.
- Pencere taraması değiş tokuşu veriyor: 1 günlük pencere %59 kesiyor ama 8 meşru yolu durduruyor
  ve sınama döneminde 7 iş yükünde 69 iş engelleniyor; 90 günlük pencere %43 kesiyor, 1 yanlış
  kesme yapıyor, 0 iş engelliyor.
- Yanlış kesmenin faturası kesildiği gün gelmiyor: 90 günlük pencerede kesilen tek yol sınama
  döneminde de koşmadı, engellenen iş 0 göründü.
- Daraltma satır sayısını düşürmüyor: 19 satırlık aile düzeyi politika, 90 günlük pencerede 26
  satırlık izin düzeyi politikaya dönüşüyor. Dar politika daha uzun politikadır.
- Güvenli daraltma eşiği %1 kaçırma riski için 275 gündür — en nadir yolun 60 günlük aralığının
  yaklaşık 4,6 katı. Gözlenen 90 günde o yolun kaçırılma olasılığı %22 ve beklenen yanlış kesme
  0,46 yoldur.

#### Sonraki Adım

Bu ders bir politika kümesini daraltmayı ölçtü ve daraltmanın nerede durduğunu gösterdi. Ama
tabloların hepsi tek bir varsayım üzerinde duruyor: bütün bu iş yükleri aynı yerde, aynı sınırın
içinde. Kırk altı kalemin hepsi tek bir hesapta yazılıysa bir kimliğin ele geçirilmesi o hesabın
tamamına açılan bir kapıdır ve daraltma yalnız anahtarın şeklini değiştirir, kapının genişliğini
değil. Sonraki dersin sorusu bu yüzden sınırın kendisidir: aynı iş yükü kümesi tek hesapta,
ortama göre ayrılmış hesaplarda ve iş yüküne göre ayrılmış hesaplarda kurulduğunda patlama yarıçapı
kaç kaynak ediyor, kota nasıl paylaşılıyor, fatura ayrışıyor mu ve kaç hesap ile kaç politika
kopyası yönetmek gerekiyor.

### Hesap ve Kuruluş Yapısı

Source: https://academia.sh/tr/kurslar/bulut-yonetisimi/hesap-ve-kurulus-yapisi

Aynı iş yükü kümesi üç yapıda kurulur — tek hesap, ortama göre hesap, iş yüküne göre hesap. Patlama yarıçapı, kota paylaşımı, faturanın ayrışması ve yönetim yükü sayılır; kuruluş düzeyi koruma bandının ne kesip ne kesemediği ölçülür.

Önceki iki ders kimliğin nereden geldiğini ve ne yapabildiğini ölçtü; ikisi de tek bir sınırın
içinde kaldı. Politika daraltıldıktan sonra bile bir soru yanıtsız duruyor: bu iş yükleri hangi
sınırın içinde? Aynı sekiz iş yükü ve üç ortam üç ayrı yapıda kurulabilir — hepsi tek hesapta,
ortama göre ayrılmış hesaplarda ya da iş yüküne göre ayrılmış hesaplarda. Bu ders üçünü yan yana
kuruyor ve dört şey sayıyor: patlama yarıçapı, kotanın kaç iş yükü arasında paylaşıldığı, faturanın
kaç kaleme ayrıştığı ve kaç hesapla kaç politika kopyasının yönetildiği. Sonda kuruluş düzeyi
koruma bandının ne kesip ne kesemediği ölçülüyor.

- **BI37.** Sekiz iş yükü, üç ortam, sekiz kaynak ailesi ve yirmi dört kaynak kurgusal bölgesel
  ölçüm ağına aittir; ölçülen şey `node` ile yazılan modeldir.
- **BI38.** Patlama yarıçapı iki kümenin birleşimidir: kimliğin politikayla eriştiği kaynaklar ve
  hesabının içindeki kaynaklar. Hesap içinde yükselme mümkün, hesap sınırı geçilmez varsayıldı.
- **BI39.** Kota hesap başına verildi ve tek bir sayı olarak modellendi. Kurgu birimdir; gerçek bir
  fiyat ya da sınır listesi değildir.
- **BI40.** Talep sabittir; ani yük, geri çekilme ve kuyruklanma modellenmiyor. Bunlar sınıra çarpma
  anını değiştirir, hangi hesabın çarptığını değiştirmez.
- **BI41.** Bir iş yükünün fatura payı ancak hesabında tek başınaysa doğrudan okunabilir sayıldı;
  etiketleme yoluyla dağıtım bu derste ölçülmüyor.
- **BI42.** Kuruluş düzeyi koruma bandı hesaba iliştirilir ve hesabın içini ayıramaz. Bu bir model
  kararıdır; bandın ortama göre kesebilmesi hesap sınırının ortamı ayırmasına bağlıdır.

#### Aynı Küme, Üç Yapı

Model kaynakları aile ve ortam çiftiyle adlandırıyor, her ailenin bir sahip iş yükü var ve üç yapı
tek bir soruya farklı yanıt veriyor: bir iş yükü hangi hesaba düşüyor. Geri kalanı — politika,
kaynak, talep — üç yapıda aynı.

```js
// hesap.mjs — ayni is yuku kumesi uc hesap yapisinda kurulur; kurgusal olcum agi modeli
export const ORTAM = ['gelistirme', 'hazirlik', 'uretim'];
export const AILE = ['olcum', 'kuyruk', 'arsiv', 'fatura', 'is-emri', 'gunluk', 'yapilandirma', 'posta'];
export const IZIN = {                                // aile -> ailenin acilan izinleri
  olcum: ['oku', 'yaz', 'sil'], kuyruk: ['oku', 'yaz', 'yonet'], arsiv: ['oku', 'yaz', 'sil'],
  fatura: ['oku', 'yaz'], 'is-emri': ['oku', 'yaz'], gunluk: ['oku', 'yaz'],
  yapilandirma: ['oku', 'yaz'], posta: ['gonder'],
};
export const VERILEN = {                             // is yuku -> erisimi olan aileler
  'okuma-toplayici': ['olcum', 'kuyruk'], 'dogrulayici': ['olcum', 'kuyruk'],
  'gunluk-tasiyici': ['gunluk', 'yapilandirma'], 'faturalama': ['fatura', 'posta', 'arsiv'],
  'is-emri': ['is-emri', 'kuyruk', 'posta'], 'gecelik-toplu-is': ['olcum', 'arsiv', 'fatura'],
  'arsivleyici': ['arsiv'], 'rapor-uretici': ['fatura', 'arsiv', 'gunluk'],
};
export const SAHIP = {                               // kaynak ailesinin sahibi is yuku
  olcum: 'okuma-toplayici', kuyruk: 'dogrulayici', arsiv: 'arsivleyici', fatura: 'faturalama',
  'is-emri': 'is-emri', gunluk: 'gunluk-tasiyici', yapilandirma: 'gunluk-tasiyici', posta: 'faturalama',
};
export const GERCEK = {                              // gercekten kullanilan yollar
  'okuma-toplayici': ['olcum-yaz', 'kuyruk-yaz', 'olcum-oku'],
  'dogrulayici': ['olcum-oku', 'kuyruk-oku', 'olcum-yaz', 'olcum-sil'],
  'gunluk-tasiyici': ['gunluk-yaz', 'yapilandirma-oku'],
  'faturalama': ['fatura-oku', 'fatura-yaz', 'posta-gonder', 'arsiv-oku'],
  'is-emri': ['is-emri-yaz', 'is-emri-oku', 'kuyruk-oku', 'posta-gonder'],
  'gecelik-toplu-is': ['olcum-oku', 'arsiv-yaz', 'fatura-oku', 'olcum-sil'],
  'arsivleyici': ['arsiv-oku', 'arsiv-yaz', 'arsiv-sil'],
  'rapor-uretici': ['fatura-oku', 'arsiv-oku', 'gunluk-oku'],
};
export const OZNE = Object.keys(VERILEN);
export const TALEP = {                               // kurgu birim: dakikada istek, uretim olceginde
  'okuma-toplayici': 420, 'dogrulayici': 260, 'gunluk-tasiyici': 90, 'faturalama': 140,
  'is-emri': 110, 'gecelik-toplu-is': 380, 'arsivleyici': 70, 'rapor-uretici': 60,
};
export const ORTAM_OLCEK = { gelistirme: 0.1, hazirlik: 0.3, uretim: 1 };
export const KOTA = 1000;                            // hesap basina kota, kurgu birim
export const KAYNAK = AILE.flatMap((a) => ORTAM.map((o) => `${a}@${o}`));
export const KIMLIK = OZNE.flatMap((s) => ORTAM.map((o) => `${s}@${o}`));
// Uc yapi: bir is yukunun hangi hesaba dustugu.
export const YAPI = {
  'tek-hesap': () => 'tek', 'ortama-gore': (s, o) => o, 'is-yukune-gore': (s, o) => `${s}@${o}`,
};
export const kimlikHesap = (y, k) => YAPI[y](k.split('@')[0], k.split('@')[1]);
export const kaynakHesap = (y, r) => YAPI[y](SAHIP[r.split('@')[0]], r.split('@')[1]);
// Politikayla erisilen kaynaklar: kimligin kendi ortamindaki verilen aileler.
export const politikaKaynak = (k) => VERILEN[k.split('@')[0]].map((a) => `${a}@${k.split('@')[1]}`);
// Hesabindaki kaynaklar: ele gecen kimlik hesap icinde yukselirse acilan kume.
export const hesapKaynak = (y, k) => KAYNAK.filter((r) => kaynakHesap(y, r) === kimlikHesap(y, k));
export const patlama = (y, k) => new Set([...hesapKaynak(y, k), ...politikaKaynak(k)]).size;
// Kurulus duzeyi koruma bandi: [izin, hangi ortamda kesilir]
export const UST_SINIR = [
  ['olcum-sil', (o) => o !== 'uretim'], ['arsiv-sil', (o) => o !== 'uretim'],
  ['yapilandirma-yaz', () => true],
];
export const verilenIzin = (s) => VERILEN[s].flatMap((a) => IZIN[a].map((x) => `${a}-${x}`));
```

```js
// kosum1.mjs — patlama yaricapi: bir kimlik ele gecerse kac kaynak aciliyor
import { KAYNAK, KIMLIK, YAPI, kimlikHesap, hesapKaynak, patlama, politikaKaynak } from './hesap.mjs';

console.log(`kaynak ${KAYNAK.length}, kimlik ${KIMLIK.length}\n`);
console.log('yapi              hesap  en genis  ortalama  (kimlik, kaynak)  politika');
console.log('                         patlama   patlama   kalemi            kadari');
for (const y of Object.keys(YAPI)) {
  const p = KIMLIK.map((k) => patlama(y, k));
  const hesap = new Set(KIMLIK.map((k) => kimlikHesap(y, k))).size;
  const pol = KIMLIK.reduce((a, k) => a + politikaKaynak(k).length, 0);
  console.log(`${y.padEnd(18)}${String(hesap).padStart(5)}${String(Math.max(...p)).padStart(10)}` +
    `${(p.reduce((a, x) => a + x, 0) / p.length).toFixed(1).padStart(10)}` +
    `${String(p.reduce((a, x) => a + x, 0)).padStart(18)}${String(pol).padStart(10)}`);
}
console.log('\nis yukune gore yapida uretim kimlikleri  hesabinda  politikayla  patlama');
for (const k of KIMLIK.filter((x) => x.endsWith('uretim')))
  console.log(`  ${k.padEnd(38)}${String(hesapKaynak('is-yukune-gore', k).length).padStart(9)}` +
    `${String(politikaKaynak(k).length).padStart(13)}${String(patlama('is-yukune-gore', k)).padStart(9)}`);
```

```
kaynak 24, kimlik 24

yapi              hesap  en genis  ortalama  (kimlik, kaynak)  politika
                         patlama   patlama   kalemi            kadari
tek-hesap             1        24      24.0               576        57
ortama-gore           3         8       8.0               192        57
is-yukune-gore       24         3       2.4                57        57

is yukune gore yapida uretim kimlikleri  hesabinda  politikayla  patlama
  okuma-toplayici@uretim                        1            2        2
  dogrulayici@uretim                            1            2        2
  gunluk-tasiyici@uretim                        2            2        2
  faturalama@uretim                             2            3        3
  is-emri@uretim                                1            3        3
  gecelik-toplu-is@uretim                       0            3        3
  arsivleyici@uretim                            1            1        1
  rapor-uretici@uretim                          0            3        3
```

Tek hesapta yirmi dört kimliğin her biri, ele geçirildiğinde yirmi dört kaynağın hepsini açıyor.
Ortama göre ayrıldığında bu sayı sekize, iş yüküne göre ayrıldığında en fazla üçe iniyor. Toplam
`(kimlik, kaynak)` kalemi beş yüz yetmiş altıdan elli yediye düşüyor — on kat.

Son sütun yapının nerede durduğunu söylüyor. Politikanın tek başına verdiği erişim üç yapıda da
elli yedi kalemdir; hesap yapısı bu sayıyı değiştirmiyor, yalnız üstüne ne eklendiğini belirliyor.
Tek hesapta beş yüz on dokuz kalem hesap sınırından geliyor; iş yüküne göre ayrılmış yapıda ekleme
sıfırdır. Daraltılmış bir politika ancak hesap sınırı onu destekliyorsa gerçekten dar demektir.

Alt blok nedenini gösteriyor. Gecelik toplu iş ve rapor üretici hiçbir kaynağa sahip değil;
hesaplarında sıfır kaynak var, yarıçapları tamamen politikadan geliyor. Arşivleyici tek aileye
sahip ve tek aileye erişiyor, yarıçapı bir. Yapının ne kadar sıkabileceğini sahiplik dağılımı
belirliyor.

#### Kota Paylaşımı ve Kalan

Hesap yalnız bir güvenlik sınırı değil, aynı zamanda bir kota kabıdır.

```js
// kosum2.mjs — kota paylasimi: hangi hesap sinira carpiyor, sinira kac birim kaliyor
import { KIMLIK, YAPI, KOTA, TALEP, ORTAM_OLCEK, kimlikHesap } from './hesap.mjs';

const talep = (k) => Math.round(TALEP[k.split('@')[0]] * ORTAM_OLCEK[k.split('@')[1]]);
console.log(`hesap basina kota ${KOTA} kurgu birim; toplam talep ${KIMLIK.reduce((a, k) => a + talep(k), 0)}\n`);
console.log('yapi              hesap  kotayi paylasan  en dolu   sinira  asan');
console.log('                         en cok kimlik    hesap     kalan   hesap');
for (const y of Object.keys(YAPI)) {
  const h = new Map();
  for (const k of KIMLIK) {
    const a = kimlikHesap(y, k);
    h.set(a, [(h.get(a)?.[0] ?? 0) + talep(k), (h.get(a)?.[1] ?? 0) + 1]);
  }
  const yuk = [...h.values()], enDolu = Math.max(...yuk.map((v) => v[0]));
  console.log(`${y.padEnd(18)}${String(h.size).padStart(5)}${String(Math.max(...yuk.map((v) => v[1]))).padStart(17)}` +
    `${String(enDolu).padStart(10)}${String(KOTA - enDolu).padStart(9)}` +
    `${String(yuk.filter((v) => v[0] > KOTA).length).padStart(6)}`);
}
console.log('\nortama gore yapida hesap yuku:');
for (const o of ['gelistirme', 'hazirlik', 'uretim']) {
  const t = KIMLIK.filter((k) => k.endsWith(o)).reduce((a, k) => a + talep(k), 0);
  console.log(`  ${o.padEnd(12)}talep ${String(t).padStart(4)}  kalan ${String(KOTA - t).padStart(5)}`);
}
```

```
hesap basina kota 1000 kurgu birim; toplam talep 2142

yapi              hesap  kotayi paylasan  en dolu   sinira  asan
                         en cok kimlik    hesap     kalan   hesap
tek-hesap             1               24      2142    -1142     1
ortama-gore           3                8      1530     -530     1
is-yukune-gore       24                1       420      580     0

ortama gore yapida hesap yuku:
  gelistirme  talep  153  kalan   847
  hazirlik    talep  459  kalan   541
  uretim      talep 1530  kalan  -530
```

Tek hesapta yirmi dört kimlik aynı bin birimlik kotayı paylaşıyor ve toplam talep iki bin yüz kırk
iki. Sınıra kalan eksi bin yüz kırk iki birim; yani hesap kotayı iki kattan fazla aşıyor. Aşmanın
sonucu bir iş yükünün değil hepsinin yavaşlamasıdır — geliştirme ortamında koşan bir sınama, üretim
ortamındaki toplayıcıyla aynı kabın içindedir.

Ortama göre ayrıldığında kap üçe bölünüyor ve asıl bilgi alt blokta. Geliştirmede sekiz yüz kırk
yedi, hazırlıkta beş yüz kırk bir birim boşta duruyor; üretim ise beş yüz otuz birim aşıyor. Toplam
talep değişmedi, yalnız nereye düştüğü değişti — ve boşta duran bin üç yüz seksen sekiz birim
üretimin eksiğini kapatmıyor, çünkü kotalar devredilemiyor.

İş yüküne göre ayrılmış yapıda hiçbir hesap sınıra çarpmıyor; en dolu hesapta beş yüz seksen birim
kalıyor. Bedeli yirmi dört ayrı kotadır — her biri ayrı izlenmesi, artırılması ve unutulması
gereken bir sınır. Kota paylaşımı azaldıkça çarpma riski düşüyor, sınır sayısı artıyor.

#### Fatura ve Yönetim Yükü

Hesap sınırı üçüncü bir şeyi daha belirliyor: faturanın kaç kaleme ayrıldığını ve kaç politika
belgesinin bakımını.

```js
// kosum3.mjs — faturanin ayrismasi ve yonetim yuku: kac hesap, kac politika kopyasi
import { KIMLIK, YAPI, kimlikHesap, kaynakHesap, politikaKaynak } from './hesap.mjs';

console.log('yapi              fatura  dogrudan  kimlik    kaynak    toplam');
console.log('                  kalemi  okunan    temelli   temelli   politika');
for (const y of Object.keys(YAPI)) {
  const h = new Map();
  for (const k of KIMLIK) h.set(kimlikHesap(y, k), (h.get(kimlikHesap(y, k)) ?? 0) + 1);
  const yalniz = KIMLIK.filter((k) => h.get(kimlikHesap(y, k)) === 1).length;
  const capraz = KIMLIK.reduce((a, k) =>
    a + politikaKaynak(k).filter((r) => kaynakHesap(y, r) !== kimlikHesap(y, k)).length, 0);
  console.log(`${y.padEnd(18)}${String(h.size).padStart(6)}${`${yalniz}/${KIMLIK.length}`.padStart(10)}` +
    `${String(KIMLIK.length).padStart(10)}${String(capraz).padStart(10)}${String(KIMLIK.length + capraz).padStart(10)}`);
}
console.log('\nis yukune gore yapida capraz hesap erisimi:');
for (const k of KIMLIK.filter((x) => x.endsWith('uretim'))) {
  const c = politikaKaynak(k).filter((r) => kaynakHesap('is-yukune-gore', r) !== kimlikHesap('is-yukune-gore', k));
  console.log(`  ${k.padEnd(26)}${String(c.length).padStart(2)}  ${c.map((r) => r.split('@')[0]).join(', ') || '-'}`);
}
```

```
yapi              fatura  dogrudan  kimlik    kaynak    toplam
                  kalemi  okunan    temelli   temelli   politika
tek-hesap              1      0/24        24         0        24
ortama-gore            3      0/24        24         0        24
is-yukune-gore        24     24/24        24        33        57

is yukune gore yapida capraz hesap erisimi:
  okuma-toplayici@uretim     1  kuyruk
  dogrulayici@uretim         1  olcum
  gunluk-tasiyici@uretim     0  -
  faturalama@uretim          1  arsiv
  is-emri@uretim             2  kuyruk, posta
  gecelik-toplu-is@uretim    3  olcum, arsiv, fatura
  arsivleyici@uretim         0  -
  rapor-uretici@uretim       3  fatura, arsiv, gunluk
```

Fatura kalemi hesap sayısıdır: bir, üç, yirmi dört. İlk iki yapıda hiçbir iş yükünün payı hesap
düzeyinde okunamıyor; ortama göre ayrılmış yapıda ortam toplamı okunuyor ama iş yükü payı
okunmuyor. Üçüncü yapıda yirmi dördün yirmi dördü okunuyor.

Sağdaki üç sütun bedeli veriyor. Kimlik temelli politika sayısı üç yapıda da yirmi dörttür. Değişen
kaynak temelli politikadır: iş yüküne göre ayrılmış yapıda otuz üç çapraz hesap erişimi doğuyor ve
her biri kaynağın hesabında ayrıca yazılması gereken bir belge. Toplam politika belgesi yirmi
dörtten elli yediye çıkıyor.

Alt blok çapraz erişimin nerede biriktiğini gösteriyor. Hiçbir kaynağa sahip olmayan iki iş yükü
üçer çapraz erişim taşıyor; günlük taşıyıcı ve arşivleyici hiç taşımıyor, çünkü eriştiği her aileye
sahipler. Yapıyı bölmenin maliyeti tam olarak sahiplikle erişimin örtüşmediği kadardır.

#### Kuruluş Düzeyi Koruma Bandı

Hesapların üstüne bir üst sınır politikası konabilir: hesap içinde ne yazılırsa yazılsın, bandın
kestiği izin geçmez. Bandın gücü hesap sınırına bağlıdır, çünkü band hesaba iliştirilir.

```js
// kosum4.mjs — kurulus duzeyi koruma bandi: ne kesiyor, ne kesemiyor
import { ORTAM, KIMLIK, YAPI, UST_SINIR, GERCEK, verilenIzin, kimlikHesap, patlama } from './hesap.mjs';

const ayirir = (y) => {                              // hesap sinirlari ortami ayiriyor mu
  const h = new Map();
  for (const k of KIMLIK) {
    const a = kimlikHesap(y, k);
    h.set(a, new Set([...(h.get(a) ?? []), k.split('@')[1]]));
  }
  return [...h.values()].every((s) => s.size === 1);
};
const uygula = (y) => UST_SINIR.filter(([, ko]) => ayirir(y) || ORTAM.every(ko));
const verilenToplam = KIMLIK.reduce((a, k) => a + verilenIzin(k.split('@')[0]).length, 0);
console.log(`verilen (kimlik, izin) kalemi ${verilenToplam}\n`);
console.log('yapi              ortam      kesilen  verilenin  durdurulan  banttan sonra');
console.log('                  ayriliyor  kalem    yuzdesi    mesru yol   en genis patlama');
for (const y of Object.keys(YAPI)) {
  let kes = 0, dur = 0;
  for (const [izin, ko] of uygula(y))
    for (const k of KIMLIK) {
      const [s, o] = k.split('@');
      if (!ko(o) || !verilenIzin(s).includes(izin)) continue;
      kes++; if (GERCEK[s].includes(izin)) dur++;
    }
  console.log(`${y.padEnd(18)}${(ayirir(y) ? 'evet' : 'hayir').padEnd(11)}${String(kes).padStart(5)}` +
    `${`%${Math.round((kes / verilenToplam) * 100)}`.padStart(11)}${String(dur).padStart(11)}` +
    `${String(Math.max(...KIMLIK.map((k) => patlama(y, k)))).padStart(18)}`);
}
console.log('\nbant kurallarinin tek tek kestigi kalem (ortam ayrilan yapida):');
for (const [izin, ko] of UST_SINIR) {
  const k = KIMLIK.filter((x) => ko(x.split('@')[1]) && verilenIzin(x.split('@')[0]).includes(izin));
  console.log(`  ${izin.padEnd(18)}${String(k.length).padStart(3)} kalem, mesru ` +
    `${k.filter((x) => GERCEK[x.split('@')[0]].includes(izin)).length}`);
}
```

```
verilen (kimlik, izin) kalemi 138

yapi              ortam      kesilen  verilenin  durdurulan  banttan sonra
                  ayriliyor  kalem    yuzdesi    mesru yol   en genis patlama
tek-hesap         hayir          3         %2          0                24
ortama-gore       evet          17        %12          6                 8
is-yukune-gore    evet          17        %12          6                 3

bant kurallarinin tek tek kestigi kalem (ortam ayrilan yapida):
  olcum-sil           6 kalem, mesru 4
  arsiv-sil           8 kalem, mesru 2
  yapilandirma-yaz    3 kalem, mesru 0
```

Band üç kural taşıyor: üretim dışında ölçüm silme, üretim dışında arşiv silme ve her yerde
yapılandırma yazma. Ortamı ayıran iki yapıda üçü de uygulanabiliyor ve yüz otuz sekiz kalemin on
yedisini, yani yüzde on ikisini kesiyor. Tek hesapta yalnız üçüncü kural uygulanabiliyor: hesap
sınırı ortamı ayırmadığı için "üretim dışında" koşulu bir yere iliştirilemiyor ve kesilen kalem
üçte kalıyor.

Dördüncü sütun bandın bedelini veriyor: kesilen on yedi kalemin altısı meşru bir yolu durduruyor.
Alt blok bunu kural kural ayırıyor — ölçüm silme altı kalem kesiyor, dördü meşru; arşiv silme sekiz
kesiyor, ikisi meşru; yapılandırma yazma üç kesiyor, hiçbiri meşru değil. Üçüncü kural bedelsiz,
ilk ikisi değil.

Son sütun bandın kesemediğini gösteriyor. Band uygulandıktan sonra da en geniş patlama yarıçapı
yirmi dört, sekiz ve üç kalıyor. Band izinleri keser, sınırları kurmaz: silme iznini kaldırmak ele
geçen bir kimliğin kaç kaynağa dokunabildiğini değiştirmiyor. Onu değiştiren tek şey kaynakların
hangi hesapta durduğudur.

#### Özet

- Aynı 24 kaynak ve 24 kimlik üç yapıda kurulduğunda en geniş patlama yarıçapı 24 → 8 → 3;
  toplam `(kimlik, kaynak)` kalemi 576'dan 57'ye düşüyor.
- Politikanın tek başına verdiği erişim üç yapıda da 57 kalemdir; tek hesapta üstüne 519 kalem
  ekleniyor, iş yüküne göre ayrılmış yapıda ekleme 0. Daraltılmış politika ancak hesap sınırı
  destekliyorsa gerçekten dardır.
- Kota hesap başına 1.000 kurgu birim: tek hesapta sınır 1.142 birim aşılıyor; ortama göre üretim
  hesabı 530 aşarken geliştirme ve hazırlıkta 1.388 birim boşta kalıyor ve devredilemiyor; iş
  yüküne göre hiçbir hesap aşmıyor, en dolusunda 580 birim kalıyor.
- Fatura kalemi 1 → 3 → 24; iş yükü payı ilk iki yapıda 0/24, üçüncüde 24/24 doğrudan okunuyor.
  Bedeli politika sayısıdır: 24 belge 57'ye çıkıyor, çünkü 33 çapraz hesap erişimi doğuyor.
- Kuruluş düzeyi koruma bandı ortamı ayıran yapılarda 138 kalemin 17'sini (%12) kesiyor ve 6 meşru
  yolu durduruyor; tek hesapta ortam koşulu iliştirilemediği için yalnız 3 kalem kesiyor. Gücü kendi
  metninden değil hesap yapısından geliyor — ve kesemediği şey patlama yarıçapıdır: banttan sonra da
  en geniş yarıçap 24 / 8 / 3 kalıyor.

#### Sonraki Adım

Bu konu bir soruyu sonuna kadar götürdü: kim ne yapabiliyor. Kullanıcılar ve roller yazıldı,
politikalar iki yönden değerlendirildi, yetki geçici hâle geldi, iş yüküne kimlik verildi, verilen
izin kullanılan izinle karşılaştırıldı ve hesaplar ayrıldı. Ama bütün bu ölçümler tek bir fiile
bakıyordu: yapmak. Erişim daraltıldıktan sonra bile listede kalan özneler var — patlama yarıçapı
sıfır olmadı, üç oldu. Sorulmayan soru şudur: o üç kaynağa erişebilen bir özne veriyi okuduğunda ne
görecek? Diskte duran kayıt açık mı, kablodan geçen istek okunabilir mi, kaydı çözen anahtar kimde
duruyor? Sonraki ders erişimi değil, erişilenin kendisini ölçüyor.

## Güvenlik ve Uyumluluk

Kiralanan katmanda verinin ve erişimin korunması: anahtar yönetimi servisi ve müşteri anahtarlarıyla beklemede şifreleme, aktarımda uçtan uca şifreleme zorunluluğu, sır saklama servislerinde döndürme ve erişim denetimi, API çağrılarını izleyen denetim günlükleri, sapmayı otomatik yakalayan yapılandırma uyum denetimi, özel uç noktalarla genel internetten çıkarma, anormal etkinlik uyarılarıyla tehdit tespiti ve denetim gereksinimlerinin buluta yansıması.

### Beklemede Şifreleme

Source: https://academia.sh/tr/kurslar/bulut-yonetisimi/beklemede-sifreleme

Beklemede duran veri üç seçenekle karşılaştırılır: şifreleme yok, sağlayıcı anahtarı, müşteri anahtarı. Kaç öznenin çözebildiği, anahtar kullanımının denetim kaydına düşüp düşmediği ve müşteri anahtarının getirdiği yük gerçek zarf şifrelemesiyle sayılır; anahtar kaybında 14 kümenin 3.973 GB'ı kalıcı olarak okunamaz hale gelir.

Önceki konu kimin neyi yapabildiğini yazdı: özne–işlem–kaynak matrisi çıkarıldı, politika belgeleri
değerlendirildi, hesap sınırları çizildi. O defterin atladığı bir soru var — erişebilen biri veriyi
açtığında **ne görüyor?** Erişim listesi kapının kimlere açıldığını söyler, ardındaki kutunun içini
söylemez. Bu ders beklemede duran veri için üç seçeneği tek ölçüyle karşılaştırır: şifreleme yok,
sağlayıcı anahtarı, **müşteri anahtarı**. Ölçü **kaç öznenin kaç veri kümesini çözebildiğidir**;
yanına iki sütun konur — anahtar kullanımının kiracının denetim kaydında görünmesi ve müşteri
anahtarının getirdiği yük. Şifreli sırların depoda tutulması ve oradaki anahtar yerleşimi depo
tabanlı dağıtım konusunda ölçüldü; burada ölçülen, anahtar **kiralanan bir servisin içinde**
durduğunda kimin elinde olduğudur.

Ölçüm **bölgesel ölçüm ağı** üzerindedir ve **kurgudur**. Veri kümeleri, özne kataloğu ve okuma
sayıları `node` ile yazılmış bir **modeldir**; şifreleme `node:crypto` ile gerçekten koşar,
anahtar türetme tohumları ve içerik değerleri uydurmadır.

**BG1.** Beklemede duran veri 14 veri kümesindedir: üç ortam, yedi tür (ham ölçüm, özet, fatura,
arşiv, yedek, anlık görüntü, günlük arşivi). Hacimler kurgudur.
**BG2.** Özne kataloğu 23 birimdir: beş ekipte 20 kişi ve üç iş yükü kimliği.
**BG3.** Veri erişimi ile **anahtar kullanma izni ayrı iki eksendir**; müşteri anahtarı seçeneğinde
çözme bu iki kümenin kesişimidir. Anahtar ortam başına birdir.
**BG4.** Her öznenin işini yapmak için düz metne ihtiyaç duyup duymadığı yazılıdır: yedekleme işi ve
platform ekibi şifreli baytı taşır, açmaz.
**BG5.** Şifreleme zarf biçimindedir: her kümenin bir veri anahtarı vardır, veri anahtarı ana
anahtarla sarılır. Sarma ve çözme gerçekten koşar.
**BG6.** Müşteri anahtarında her çözme bir denetim kaydı satırı üretir; sağlayıcı anahtarında anahtar
kullanımı kiracının kaydına düşmez. Anahtar döndürme dönemi 365 gündür (kurgu politika).

#### Üç Seçenek, Tek Soru: Kim Çözebiliyor

```js
// depo.mjs — beklemede duran veri kumeleri, ozneler ve uc sifreleme secenegi. MODELDIR.
// Bolgesel olcum agi KURGUDUR: ekip adlari, kume adlari ve okuma sayilari uydurmadir.
export const ORTAM = ["gelistirme", "hazirlik", "uretim"];
const TEMEL = ["ham-olcum", "ozet", "fatura"];
const EK = { gelistirme: [], hazirlik: ["yedek"],
  uretim: ["arsiv", "yedek", "anlik-goruntu", "gunluk-arsivi"] };
const GB = { "ham-olcum": 420, ozet: 18, fatura: 6, arsiv: 900, yedek: 1340,
  "anlik-goruntu": 760, "gunluk-arsivi": 210 };
const OKUMA = { "ham-olcum": 4, ozet: 9, fatura: 6, arsiv: 1, yedek: 0,
  "anlik-goruntu": 0, "gunluk-arsivi": 2 };   // ozne basina gunluk duz metin okumasi

export const KUME = ORTAM.flatMap((o) => [...TEMEL, ...EK[o]].map((t) => ({
  ad: `${o}/${t}`, ortam: o, tur: t,
  gb: o === "uretim" ? GB[t] : Math.round(GB[t] / (o === "hazirlik" ? 6 : 20)) })));

// duzMetin: isini yapmak icin cozulmus veriye ihtiyaci var mi. Yedekleme sifreli bayti kopyalar.
export const OZNE = [
  { ad: "olcum ekibi", n: 6, duzMetin: true, anahtar: ["gelistirme", "hazirlik"],
    erisim: [["*", "ham-olcum"], ["*", "ozet"]] },
  { ad: "fatura ekibi", n: 4, duzMetin: true, anahtar: ["gelistirme", "hazirlik"],
    erisim: [["*", "fatura"]] },
  { ad: "veri ekibi", n: 5, duzMetin: true, anahtar: ["uretim"], erisim: [["uretim", "*"]] },
  { ad: "platform ekibi", n: 3, duzMetin: false, anahtar: [], erisim: [["*", "*"]] },
  { ad: "uretim nobeti", n: 2, duzMetin: true, anahtar: ["uretim"],
    erisim: [["uretim", "ozet"], ["uretim", "fatura"]] },
  { ad: "toplayici kimligi", n: 1, duzMetin: true, anahtar: ORTAM, erisim: [["*", "ham-olcum"]] },
  { ad: "raporlama kimligi", n: 1, duzMetin: true, anahtar: ["uretim"],
    erisim: [["*", "ozet"], ["*", "fatura"]] },
  { ad: "yedekleme isi", n: 1, duzMetin: false, anahtar: [],
    erisim: [["*", "yedek"], ["*", "arsiv"], ["*", "anlik-goruntu"]] },
];

export const YAS = { gelistirme: 288, hazirlik: 141, uretim: 322 };  // musteri anahtarinin yasi
export const OMUR = 365;                                  // kurgu dondurme donemi, gun

const uyar = (k, [o, t]) => (o === "*" || k.ortam === o) && (t === "*" || k.tur === t);
export const erisir = (z, k) => z.erisim.some((c) => uyar(k, c));
export const anahtarVar = (z, k) => z.anahtar.includes(k.ortam);
export const OZNE_SAYISI = OZNE.reduce((a, z) => a + z.n, 0);
export const okuma = (z, k) => (z.duzMetin ? z.n * OKUMA[k.tur] : 0);

// Uc secenek: cozmeyi hangi kosul belirliyor. "tam" = eksik anahtar izinleri tamamlanmis hali.
export const SECENEK = {
  "sifreleme yok": (z, k) => erisir(z, k),
  "saglayici anahtari": (z, k) => erisir(z, k),
  "musteri anahtari": (z, k) => erisir(z, k) && anahtarVar(z, k),
  "musteri anahtari (tam)": (z, k) => erisir(z, k) && (anahtarVar(z, k) || z.duzMetin),
};

export const cift = (f) => OZNE.flatMap((z) => KUME.filter((k) => f(z, k)).map((k) => ({ z, k })));
export const cozer = (f) => OZNE.filter((z) => KUME.some((k) => f(z, k)))
  .reduce((a, z) => a + z.n, 0);

if (import.meta.url === `file://${process.argv[1]}`) {
  const toplamGb = KUME.reduce((a, k) => a + k.gb, 0);
  console.log(`model: ${KUME.length} veri kumesi (${toplamGb} GB, kurgu), ` +
    `${OZNE_SAYISI} ozne / ${OZNE.length} grup, ${OZNE_SAYISI * KUME.length} olasi cift`);
  const B = [23, 15, 13, 10, 11, 17];
  const yz = (h) => h.map((v, j) => j ? String(v).padStart(B[j]) : String(v).padEnd(B[0])).join("");
  console.log("\n" + yz(["secenek", "cozebilen ozne", "cozme cifti", "en genis",
    "kayit/gun", "altyapi yolu"]));
  for (const [ad, f] of Object.entries(SECENEK)) {
    const c = cift(f);
    const kayit = ad === "sifreleme yok" || ad === "saglayici anahtari" ? 0
      : c.reduce((a, x) => a + okuma(x.z, x.k), 0);
    console.log(yz([ad, cozer(f), c.length,
      Math.max(...OZNE.map((z) => KUME.filter((k) => f(z, k)).length)), kayit,
      ad === "sifreleme yok" ? "acik, sayilamaz" : "kapali"]));
  }
  const acik = cift(SECENEK["sifreleme yok"]);
  const musteri = new Set(cift(SECENEK["musteri anahtari"]).map((x) => `${x.z.ad}|${x.k.ad}`));
  const kirik = acik.filter((x) => !musteri.has(`${x.z.ad}|${x.k.ad}`));
  console.log(`\nmusteri anahtarina gecince kapanan cift: ${kirik.length}; ` +
    `bunlarin ${kirik.filter((x) => x.z.duzMetin).length} tanesi duz metin isteyen mesru is`);
  for (const z of OZNE) {
    const d = kirik.filter((x) => x.z.ad === z.ad);
    if (d.length) console.log(`  ${z.ad.padEnd(20)} ${String(d.length).padStart(3)} cift, ` +
      `${String(d.reduce((a, x) => a + okuma(x.z, x.k), 0)).padStart(3)} gunluk okuma, ` +
      `duz metin gerek: ${z.duzMetin}`);
  }
  const her = cift(SECENEK["musteri anahtari"]).length;
  console.log(`\nsifrelemenin hicbir secenekte kapatmadigi cift: ${her} ` +
    `(yetkili kimlik zaten okuyor); izinler tamamlaninca ${cift(SECENEK["musteri anahtari (tam)"]).length}`);

  const tam = cift(SECENEK["musteri anahtari (tam)"]);
  console.log("\n" + yz(["anahtar (ortam)", "yas (gun)", "kalan gun", "kume", "cozme/gun"]));
  for (const o of ORTAM) {
    const k = tam.filter((x) => x.k.ortam === o);
    console.log(yz([o, YAS[o], OMUR - YAS[o], KUME.filter((x) => x.ortam === o).length,
      k.reduce((a, x) => a + okuma(x.z, x.k), 0)]));
  }
}
```

```
model: 14 veri kumesi (3973 GB, kurgu), 23 ozne / 8 grup, 322 olasi cift

secenek                 cozebilen ozne  cozme cifti  en genis  kayit/gun     altyapi yolu
sifreleme yok                       23           45        14          0  acik, sayilamaz
saglayici anahtari                  23           45        14          0           kapali
musteri anahtari                    19           20         7        371           kapali
musteri anahtari (tam)              19           27         7        503           kapali

musteri anahtarina gecince kapanan cift: 25; bunlarin 7 tanesi duz metin isteyen mesru is
  olcum ekibi            2 cift,  78 gunluk okuma, duz metin gerek: true
  fatura ekibi           1 cift,  24 gunluk okuma, duz metin gerek: true
  platform ekibi        14 cift,   0 gunluk okuma, duz metin gerek: false
  raporlama kimligi      4 cift,  30 gunluk okuma, duz metin gerek: true
  yedekleme isi          4 cift,   0 gunluk okuma, duz metin gerek: false

sifrelemenin hicbir secenekte kapatmadigi cift: 20 (yetkili kimlik zaten okuyor); izinler tamamlaninca 27

anahtar (ortam)              yas (gun)    kalan gun      kume  cozme/gun
gelistirme                         288           77         3        121
hazirlik                           141          224         4        121
uretim                             322           43         7        261
```

Tablonun ilk iki satırı birbirinin aynısıdır ve dersin ilk kararı oradadır. Sağlayıcı anahtarına
geçmek **çözebilen özne sayısını bir tane bile azaltmıyor**: 23 özne, 45 çift, en geniş öznenin
elinde 14 kümenin hepsi. Sağlayıcı anahtarında çözme veri erişimiyle birlikte otomatik gerçekleşir;
okuma isteğini yapan özne için şifreleme görünmez bir katmandır. Değiştirdiği tek sütun altyapı
yoludur: disk, yedek ortamı, elden çıkarılan donanım ve sağlayıcı tarafındaki işletim erişimi
kapanır. O sütunun "açık, sayılamaz" değeri kendi başına bir kalemdir; kaç öznenin bu yoldan
okuyabildiği **kiracının defterinde yazmaz**.

Müşteri anahtarı satırı ölçüyü ilk kez oynatıyor: 23 özne 19'a, 45 çift 20'ye, en geniş yetki 14
kümeden 7'ye iner. Bunun bedeli aşağıdaki dökümdedir. Kapanan 25 çiftin **7 tanesi düz metne
gerçekten ihtiyaç duyan meşru iştir**: ölçüm ekibinin üretim ham ölçümü ve özeti, fatura ekibinin
üretim faturası, raporlama kimliğinin geliştirme ve hazırlık kümeleri — günde 132 okuma durur. Eksik
anahtar izinleri verildiğinde bu işler geri açılır ve çift sayısı 20'den 27'ye çıkar. Kalan fark
45'e göre 18 çifttir ve tamamı düz metne ihtiyacı olmayan öznelerdir: platform ekibinin 14 çifti ve
yedekleme işinin 4 çifti. **Müşteri anahtarının gerçek kazancı bu 18 çifttir** — 45'ten 27'ye, yüzde
kırk. Geri kalanı anahtar iznini erişim izninin kopyası haline getirmekle biter.

Son sütun ikinci kazancı veriyor: aynı 503 çözme sağlayıcı anahtarında 0 kayıt satırı üretiyor,
müşteri anahtarında 503. Anahtar kullanımının görünürlüğü, çözme yetkisinin daralmasından bağımsız
bir kalemdir. Sınır tablosu anahtar ömrünü sayıyor: üretim anahtarı 322 günlük, 365 günlük döneme
**43 gün kaldı** ve o döndürme 7 kümeyi ilgilendiriyor.

#### Anahtarın Kendi Yükü: Döndürme, Yedek ve Kayıp

```js
// zarf.mjs — zarf sifreleme gercekten kosar: veri anahtari sarilir, dondurulur, kaybedilir.
// ANAHTAR VE ICERIK DEGERLERI KURGUDUR. Turetme tohumu gorunur ki cikti yeniden uretilebilsin.
import { scryptSync, createCipheriv, createDecipheriv, createHash } from "node:crypto";
import { KUME, cift, okuma, SECENEK } from "./depo.mjs";

const anaAnahtar = (s) => scryptSync(`kurgu-ana-parola-s${s}`, "kurgu-tuz-0001", 32, { N: 16384 });
const veriAnahtari = (k) => createHash("sha256").update(`kurgu-veri-anahtari|${k.ad}`).digest();
const iv = (etiket) => createHash("sha256").update(`iv|${etiket}`).digest().subarray(0, 12);
const icerik = (k) => Buffer.from(`kurgu-kayit|${k.ad}|`.repeat(Math.max(4, k.gb)));

const sar = (k, s) => {                                   // veri anahtarini ana anahtarla sarar
  const c = createCipheriv("aes-256-gcm", anaAnahtar(s), iv(`${k.ad}#${s}`));
  const g = Buffer.concat([c.update(veriAnahtari(k)), c.final()]);
  return { kume: k.ad, surum: s, govde: g, etiket: c.getAuthTag() };
};
const ac = (sarili, s) => {                               // sarili anahtari acar; yanlis anahtar atar
  const d = createDecipheriv("aes-256-gcm", anaAnahtar(s), iv(`${sarili.kume}#${sarili.surum}`));
  d.setAuthTag(sarili.etiket);
  return Buffer.concat([d.update(sarili.govde), d.final()]);
};
const sifrele = (k, va) => {
  const c = createCipheriv("aes-256-gcm", va, iv(k.ad));
  return { govde: Buffer.concat([c.update(icerik(k)), c.final()]), etiket: c.getAuthTag() };
};
const coz = (k, va, kutu) => {
  const d = createDecipheriv("aes-256-gcm", va, iv(k.ad));
  d.setAuthTag(kutu.etiket);
  return Buffer.concat([d.update(kutu.govde), d.final()]);
};

const sarili = KUME.map((k) => sar(k, 1));
const kutu = KUME.map((k, i) => sifrele(k, ac(sarili[i], 1)));
const nesneBayt = kutu.reduce((a, x) => a + x.govde.length, 0);
const sariliBayt = sarili.reduce((a, x) => a + x.govde.length + x.etiket.length, 0);
const dogru = KUME.every((k, i) => coz(k, ac(sarili[i], 1), kutu[i]).equals(icerik(k)));
console.log(`${KUME.length} kume sifrelendi: ${nesneBayt} bayt nesne, ${sariliBayt} bayt ` +
  `sarili anahtar; hepsi geri cozuldu: ${dogru}`);
console.log(`ornek sarili anahtar ${sarili[0].kume} -> ${sarili[0].govde.toString("base64")}`);

const B = [36, 8, 8, 16];
const yz = (h) => h.map((v, j) => j ? String(v).padStart(B[j]) : String(v).padEnd(B[0])).join("");
console.log("\n" + yz(["dondurme bicimi", "sarma", "nesne", "dokunulan bayt"]));
const yeniSarili = KUME.map((k) => sar(k, 2));             // ana anahtar 1 -> 2
const acilan = KUME.map((k, i) => coz(k, ac(yeniSarili[i], 2), kutu[i]).equals(icerik(k)));
console.log(yz(["ana anahtar (yalniz sarma)", KUME.length, 0, sariliBayt]));
console.log(yz(["veri anahtari (yeniden sifreleme)", KUME.length, KUME.length,
  nesneBayt + sariliBayt]));
console.log(`ana anahtar dondurulduktan sonra nesneler bozulmadan aciliyor: ` +
  `${acilan.every(Boolean)} (${acilan.filter(Boolean).length}/${KUME.length})`);

// anahtar kaybi: sarili anahtarlar duruyor, ana anahtar surum 2 elde yok. Sahte surumle denenir.
let kayipKume = 0, kayipGb = 0;
for (const [i, s] of yeniSarili.entries()) {
  try { coz(KUME[i], ac(s, 9), kutu[i]); } catch { kayipKume++; kayipGb += KUME[i].gb; }
}
console.log(`\nana anahtar kaybi: sarili anahtar acilmiyor, ${kayipKume}/${KUME.length} kume ` +
  `okunamiyor, ${kayipGb} GB kalici kayip`);
const geri = yeniSarili.map((s, i) => coz(KUME[i], ac(s, 2), kutu[i]).equals(icerik(KUME[i])));
console.log(`anahtar yedeginden geri getirilince: ${geri.filter(Boolean).length}/` +
  `${KUME.length} kume dogru cozuluyor — sifreli bayt yedegi tek basina yetmiyor`);

const gunluk = cift(SECENEK["musteri anahtari (tam)"]).reduce((a, x) => a + okuma(x.z, x.k), 0);
console.log(`\ndenetim kaydi: musteri anahtarinda ${gunluk} anahtar kullanimi/gun, ` +
  `30 gunde ${gunluk * 30} satir; saglayici anahtarinda ayni ${gunluk} cozme icin 0 satir`);
```

```
14 kume sifrelendi: 110110 bayt nesne, 672 bayt sarili anahtar; hepsi geri cozuldu: true
ornek sarili anahtar gelistirme/ham-olcum -> ZlpDt4j6C7N+EAH7PufTZiBJ2rlZSinVP8dhgHFvKic=

dondurme bicimi                        sarma   nesne  dokunulan bayt
ana anahtar (yalniz sarma)                14       0             672
veri anahtari (yeniden sifreleme)         14      14          110782
ana anahtar dondurulduktan sonra nesneler bozulmadan aciliyor: true (14/14)

ana anahtar kaybi: sarili anahtar acilmiyor, 14/14 kume okunamiyor, 3973 GB kalici kayip
anahtar yedeginden geri getirilince: 14/14 kume dogru cozuluyor — sifreli bayt yedegi tek basina yetmiyor

denetim kaydi: musteri anahtarinda 503 anahtar kullanimi/gun, 30 gunde 15090 satir; saglayici anahtarinda ayni 503 cozme icin 0 satir
```

Şifreleme gerçekten koştu: 14 küme şifrelendi, sarılı anahtarlar açıldı ve içerik bire bir geri
geldi. Ana anahtarı döndürmek 14 sarma işlemi ve 672 bayta dokunur; **nesne baytına hiç dokunmaz.**
Veri anahtarını döndürmek aynı 14 sarmaya ek olarak 14 nesnenin tamamını yeniden şifreler: 110.782
bayt, yüz altmış kat. Sarma katmanının varlık sebebi budur — sık döndürülen anahtar veriye değil,
anahtara dokunur.

Karşılığında şu doğar: ana anahtar döndürüldükten sonra da **veri anahtarı aynı veri anahtarıdır.**
Sarılı hali değişti, sardığı şey değişmedi. Veri anahtarı bir yerde açık kalmışsa döndürme onu
kapatmaz; kapatmak için 110.782 baytlık satıra geçmek gerekir. Ucuz döndürme ile kapatıcı döndürme
aynı işlem değildir ve tabloda ayrı satırlarda durur.

Kayıp satırı müşteri anahtarının en sert kalemidir ve çalıştırılmış bir denemedir: ana anahtar sürüm
2 elde yokken 14 kümenin **hiçbiri** açılmıyor, 3.973 GB kalıcı olarak okunamaz. Şifreli baytların
yedeği duruyordu ve işe yaramadı; anahtar yedeğinden gelen sürüm 2 ile aynı 14 küme doğru çözüldü.
Müşteri anahtarına geçmek, **yedekleme planının kapsamına veriyi değil anahtarı** eklemek demektir.

#### Şifrelemenin Kapatmadığı Yol

Üç seçenekte de açık kalan 20 çift — izinler tamamlandığında 27 — bu dersin adı konması gereken
kalemidir. Bunlar **yetkili kimliklerin okumasıdır**. Veri ekibinin 5 üyesi üretim ortamının yedi
kümesini açar, çünkü hem veri erişimi hem anahtar izni onda toplanmıştır. Beklemede şifreleme bu
yola karşı hiçbir şey yapmaz ve yapması da beklenmez: özne kimlik doğrulamasından geçmiş, politika
belgesi izin vermiş, anahtar servisi çözmüştür.

Şifrelemenin kapattığı yol tek bir sütundur: kiracının okuyamadığı, sayamadığı ve denetleyemediği
altyapı tarafı. Sağlayıcı anahtarı o sütunu kapatır ve karşılığında hiçbir şey istemez. Müşteri
anahtarı iki şey daha ekler — çözme yetkisini erişim yetkisinden ayırır (45 çiftten 27'ye) ve anahtar
kullanımını kiracının kendi kaydına düşürür (0 satırdan günde 503'e) — istediği bedel de sayılıdır:
7 meşru işin durması, yedeklenmesi gereken yeni bir sır ve kaybedildiğinde 3.973 GB'ı geri
getirilemez bir anahtar.

#### Özet

- Sağlayıcı anahtarı çözebilen özneyi 23'ten indirmiyor, çifti 45'te bırakıyor; kapattığı tek şey
  kiracının sayamadığı altyapı yoludur.
- Müşteri anahtarı çiftleri 45'ten 20'ye indiriyor; eksik izinler tamamlanınca 27'ye çıkıyor ve
  kalıcı kazanç, düz metne ihtiyacı olmayan öznelerin 18 çiftidir.
- Daraltmanın bedeli: kapanan 25 çiftin 7'si düz metin isteyen meşru iştir, günde 132 okuma durur;
  en geniş öznenin yetkisi 14 kümeden 7'ye iner.
- Ana anahtar döndürme 14 sarma ve 672 bayt, veri anahtarı döndürme 14 nesne ve 110.782 bayttır;
  ucuz döndürme veri anahtarını değiştirmediği için açık kalmış bir veri anahtarını kapatmaz.
- Anahtar kaybı çalıştırılarak gösterildi: 14/14 küme açılmıyor, 3.973 GB kalıcı kayıp; şifreli bayt
  yedeği yetmiyor, anahtar yedeği 14/14 kümeyi geri getiriyor.
- Anahtar kullanımı yalnız müşteri anahtarında görünüyor: aynı 503 çözme için 0 satıra karşı günde
  503, 30 günde 15.090 satır; üretim anahtarının 365 günlük dönemine 43 gün kaldı.

#### Sonraki Adım

Beklemede duran veri için soru yanıtlandı. Ama veri yalnız beklemede durmuyor — kümeler, ortamlar ve
ölçüm uçlarıyla toplayıcı arasında sürekli **hareket ediyor**. Bir sonraki ders o hareketi ölçer:
bağlantı bacaklarının kaçı şifreli, kaçı "iç ağ" gerekçesiyle açık bırakılmış, şifreleme politikayla
zorunlu kılındığında kaç bağlantı kırılıyor ve kaç kalem yapılandırma değişiyor.

### Aktarımda Şifreleme

Source: https://academia.sh/tr/kurslar/bulut-yonetisimi/aktarimda-sifreleme

Aktarım şifrelemesi zorunlu kılındığında ne oluyor sayılır: 16 bağlantı bacağının 9'u açık, 4'ünün durumu bilinmiyor. Üç aşamalı zorlama 23 yapılandırma kalemi değiştiriyor ve 79 bağlantı kırıyor; 34'ü yükseltilemiyor. Altı yolun ancak biri uçtan uca kanıtlı hale geliyor, hepsi için kendi katmanında şifreleme gerekiyor.

Beklemede duran veri için soru yanıtlandı. Veri hareket ettiğinde ise ortada bir kutu değil, bir
**zincir** var: ölçüm ağının bir kaydı kenar cihazdan alım ucuna, oradan ağ geçidine, toplayıcıya ve
veritabanına gidiyor; her sıçrama ayrı bir bacak ve her bacağın kendi durumu var. Bu dersin sorusu el
sıkışmanın maliyeti değil — o ölçüm daha önce yapıldı — şifrelemenin hangi noktada sonlandığı da
değil; o da ölçüldü. Buranın sorusu **zorunlu kılmaktır**: hangi bacaklar şifreli, hangileri "iç ağ"
gerekçesiyle açık bırakılmış, politikayla zorunlu kılınınca **kaç bağlantı kırılıyor** ve kaç kalem
yapılandırma değişiyor.

Üçüncü bir durum daha var: sağlayıcının kendi ağı içindeki taşımanın şifreli olup olmadığı **kiracı
tarafından doğrulanamaz**. O bacaklar "bilinmiyor" olarak durur, sağlayıcının varsayılanı bir
**varsayım** olarak yazılır ve bilinmiyor olmanın kendisi bir kalem sayılır. Ölçüm **bölgesel ölçüm
ağı** üzerindedir, **kurgudur** ve `node` ile yazılmış bir **modeldir**.

**BG7.** Veri yolu 16 bağlantı bacağına ayrılır; bacak kataloğu, istemci sayıları, yapılandırma
kalemleri ve istek hacimleri kurgudur.
**BG8.** Her bacak üç ağ türünden birindedir: genel ağ, özel hat, sağlayıcı içi ağ.
**BG9.** Bacağın durumu üç değerlidir — şifreli, açık, **bilinmiyor**. Üçüncü değer yalnız sağlayıcı
içi taşıma için kullanılır ve doğrulanamaz.
**BG10.** Her açık bacakta şifrelemeyi desteklemeyen istemci sayısı ve bunların kaçının
yükseltilebildiği yazılıdır; yükseltilemeyen istemci zorlamada kalıcı olarak kırılır.
**BG11.** Zorlama üç aşamadadır: önce genel ağ, sonra özel hat, sonra sağlayıcı içi ağ. Geçiş
penceresi 90 gündür (kurgu) ve uyarı modunda 61 gün geçmiştir.
**BG12.** "Bilinmiyor" bacakların şifreli olduğu ancak kiracının kendi katmanında şifreleme
yapmasıyla kanıtlanabilir; bunun yapılandırma bedeli bacak başına yazılıdır.

#### Bacaklar, Yollar ve Aşamalı Zorlama

```js
// bacak.mjs — aktarim bacaklari, yollar ve asamali zorlama. MODELDIR.
// Bolgesel olcum agi KURGUDUR: bacak katalogu, istemci sayilari ve istek hacimleri uydurmadir.
// durum "bilinmiyor" = saglayici ici tasima; kiraci dogrulayamaz, VARSAYIM olarak durur.
export const BACAK = [
  // id, ad, ag, durum, istemci, destekmeyen, yapKalemi, istekBin, kanitKalemi, yukseltilebilir
  ["b1", "kenar cihaz -> alim ucu", "genel", "acik", 340, 54, 3, 4820, 0, 38],
  ["b2", "alim ucu -> ag gecidi", "saglayici-ici", "sifreli", 6, 0, 1, 4820, 0, 0],
  ["b3", "ag gecidi -> toplayici", "saglayici-ici", "bilinmiyor", 12, 0, 2, 4820, 4, 0],
  ["b4", "toplayici -> veritabani", "saglayici-ici", "acik", 12, 0, 4, 1960, 0, 0],
  ["b5", "toplayici -> kuyruk", "saglayici-ici", "acik", 12, 2, 2, 3100, 0, 2],
  ["b6", "isleyici -> kuyruk", "saglayici-ici", "acik", 9, 0, 2, 3100, 0, 0],
  ["b7", "isleyici -> nesne deposu", "saglayici-ici", "bilinmiyor", 9, 0, 1, 640, 3, 0],
  ["b8", "isleyici -> onbellek", "saglayici-ici", "acik", 9, 9, 2, 5400, 0, 0],
  ["b9", "servis -> gunluk toplayici", "saglayici-ici", "acik", 21, 0, 3, 8900, 0, 0],
  ["b10", "gunluk toplayici -> arsiv", "saglayici-ici", "bilinmiyor", 2, 0, 1, 190, 2, 0],
  ["b11", "arsiv -> ikincil bolge", "saglayici-ici", "bilinmiyor", 2, 0, 1, 190, 2, 0],
  ["b12", "fatura ihraci -> mutabakat", "genel", "sifreli", 1, 0, 1, 12, 0, 0],
  ["b13", "is ortagi beslemesi -> alim", "genel", "acik", 7, 3, 2, 260, 0, 1],
  ["b14", "operator -> yonetim ucu", "genel", "sifreli", 20, 0, 1, 45, 0, 0],
  ["b15", "yonetim ucu -> servis", "saglayici-ici", "acik", 20, 0, 3, 45, 0, 0],
  ["b16", "olcum agi bakim kanali", "ozel-hat", "acik", 28, 11, 2, 70, 0, 4],
].map(([id, ad, ag, durum, istemci, kirilan, yap, istek, kanit, yuk]) =>
  ({ id, ad, ag, durum, istemci, kirilan, yap, istek, kanit, yuk }));

export const YOL = {                                      // bir istegin gectigi bacak dizisi
  "olcum alimi": ["b1", "b2", "b3", "b4"],
  "ozet uretimi": ["b5", "b6", "b7"],
  "gunluk akisi": ["b9", "b10", "b11"],
  "fatura ihraci": ["b4", "b7", "b12"],
  "yonetim erisimi": ["b14", "b15"],
  "is ortagi alimi": ["b13", "b3", "b4"],
};
export const bul = (id) => BACAK.find((b) => b.id === id);
export const AG = ["genel", "ozel-hat", "saglayici-ici"];  // zorlama asamalarinin sirasi
export const PENCERE = 90, GECEN = 61;                     // kurgu gecis penceresi, gun

const top = (l, f) => l.reduce((a, b) => a + f(b), 0);
const B = [26, 7, 9, 10, 12, 13, 15];
export const yz = (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]}`) {
  console.log(`model: ${BACAK.length} bacak, ${Object.keys(YOL).length} yol, ` +
    `${top(BACAK, (b) => b.istek)} bin istek/gun (kurgu)`);
  console.log("\n" + yz(["ag turu", "bacak", "sifreli", "acik", "bilinmiyor", "istemci",
    "istek(bin)"]));
  for (const a of AG) {
    const l = BACAK.filter((b) => b.ag === a);
    const s = (d) => l.filter((b) => b.durum === d).length;
    console.log(yz([a, l.length, s("sifreli"), s("acik"), s("bilinmiyor"),
      top(l, (b) => b.istemci), top(l, (b) => b.istek)]));
  }

  // asamali zorlama: her asamada o ag turundeki acik bacaklar sifreye cekilir.
  const durum = new Map(BACAK.map((b) => [b.id, b.durum]));
  console.log("\n" + yz(["asama", "bacak", "yap.kal.", "kirilan", "istek(bin)", "kalan acik",
    "bilinmiyor"]));
  const satir = (ad, l) => {
    for (const b of l) durum.set(b.id, "sifreli");
    console.log(yz([ad, l.length, top(l, (b) => b.yap), top(l, (b) => b.kirilan),
      top(l, (b) => b.istek), [...durum.values()].filter((d) => d === "acik").length,
      [...durum.values()].filter((d) => d === "bilinmiyor").length]));
  };
  satir("0. uyari modu", []);
  for (const a of AG) satir(`${AG.indexOf(a) + 1}. ${a}`,
    BACAK.filter((b) => b.ag === a && durum.get(b.id) === "acik"));

  // yol basina uctan uca: bir yolun her bacagi sifreliyse yol kanitli sayilir.
  const yolSatir = (ad, d) => {
    const l = YOL[ad].map(bul);
    const say = (x) => l.filter((b) => d(b) === x).length;
    console.log(yz([ad, l.length, say("sifreli"), say("acik"), say("bilinmiyor"),
      say("bilinmiyor") === 0 && say("acik") === 0 ? "kanitli" : "hayir",
      top(l.filter((b) => d(b) !== "sifreli"), (b) => b.istek)]));
  };
  console.log("\n" + yz(["yol (zorlamadan once)", "bacak", "sifreli", "acik", "bilinmiyor",
    "uctan uca", "kanitsiz(bin)"]));
  for (const ad of Object.keys(YOL)) yolSatir(ad, (b) => b.durum);
  console.log("\n" + yz(["yol (uc asama sonrasi)", "bacak", "sifreli", "acik", "bilinmiyor",
    "uctan uca", "kanitsiz(bin)"]));
  for (const ad of Object.keys(YOL)) yolSatir(ad, (b) => durum.get(b.id));
}
```

```
model: 16 bacak, 6 yol, 38372 bin istek/gun (kurgu)

ag turu                     bacak  sifreli      acik  bilinmiyor      istemci     istek(bin)
genel                           4        2         2           0          368           5137
ozel-hat                        1        0         1           0           28             70
saglayici-ici                  11        1         6           4          114          33165

asama                       bacak yap.kal.   kirilan  istek(bin)   kalan acik     bilinmiyor
0. uyari modu                   0        0         0           0            9              4
1. genel                        2        5        57        5080            7              4
2. ozel-hat                     1        2        11          70            6              4
3. saglayici-ici                6       16        11       22505            0              4

yol (zorlamadan once)       bacak  sifreli      acik  bilinmiyor    uctan uca  kanitsiz(bin)
olcum alimi                     4        1         2           1        hayir          11600
ozet uretimi                    3        0         2           1        hayir           6840
gunluk akisi                    3        0         1           2        hayir           9280
fatura ihraci                   3        1         1           1        hayir           2600
yonetim erisimi                 2        1         1           0        hayir             45
is ortagi alimi                 3        0         2           1        hayir           7040

yol (uc asama sonrasi)      bacak  sifreli      acik  bilinmiyor    uctan uca  kanitsiz(bin)
olcum alimi                     4        3         0           1        hayir           4820
ozet uretimi                    3        2         0           1        hayir            640
gunluk akisi                    3        1         0           2        hayir            380
fatura ihraci                   3        2         0           1        hayir            640
yonetim erisimi                 2        2         0           0      kanitli              0
is ortagi alimi                 3        2         0           1        hayir           4820
```

İlk tablo bir kalıbı hemen ele veriyor: genel ağdaki 4 bacağın 2'si şifreli, sağlayıcı içi 11 bacağın
yalnız 1'i. Şifreleme dışarıya bakan yüzde uygulanmış, içeride uygulanmamıştır — gerekçe yazılıdır:
"iç ağ". O gerekçenin taşıdığı hacim sayılıdır: sağlayıcı içi bacaklardan günde 33.165 bin istek
geçiyor, toplamın yüzde seksen altısı.

Aşama tablosu faturayı üçe bölüyor. Genel ağ aşaması ucuzdur — 2 bacak, 5 yapılandırma kalemi — ama
**57 bağlantı kırar**, çünkü kenar cihazların 54'ü ve iş ortağı beslemesinin 3 istemcisi şifreli
aktarımı desteklemiyor. Özel hat aşaması 1 bacak, 2 kalem, 11 kırık. Sağlayıcı içi aşama en
pahalısıdır: 6 bacak, 16 kalem ve günde 22.505 bin isteğin yolu; kırdığı bağlantı ise yalnız 11'dir.
Dağılım sezgiye ters çıkıyor — en çok yapılandırma değiştiren aşama, en az bağlantı kıran aşamadır.

Yol tabloları asıl cümleyi kuruyor. Zorlamadan önce **altı yolun hiçbiri uçtan uca şifreli değil.**
Üç aşamadan sonra da yalnız biri kanıtlı hale geliyor: yönetim erişimi, çünkü geçtiği iki bacak da
doğrulanabilir. Kalan beş yol en az bir "bilinmiyor" bacak taşıdığı için kanıtlanamıyor. Kanıtsız
hacim 11.600'den 4.820 bin isteğe düşüyor ama sıfırlanmıyor; sebebi tek bir bacaktır — ağ geçidiyle
toplayıcı arasındaki sıçrama, ölçüm alımının ve iş ortağı alımının ortak parçası.

#### Zorunlu Kılmanın Defteri

```js
// kirilan.mjs — zorunlu kilmanin defteri: kirilan baglanti, kalici kirik, istisna ve kanit bedeli.
import { BACAK, YOL, PENCERE, GECEN } from "./bacak.mjs";

const gen = (B) => (h) => h.map((v, j) => j ? String(v).padStart(B[j]) : String(v).padEnd(B[0]))
  .join("");
const yz = gen([28, 9, 11, 10, 8, 10, 12]);               // kirilan baglanti tablosu
const yk = gen([27, 10, 14, 11, 13, 13, 15]);              // karar tablosu
const SINIR = 2;                                          // kurgu politika: kalici istisna tavani

const top = (l, f) => l.reduce((a, b) => a + f(b), 0);
const ACIK = BACAK.filter((b) => b.durum === "acik");
const BILINMIYOR = BACAK.filter((b) => b.durum === "bilinmiyor");
const kalici = (b) => b.kirilan - b.yuk;

console.log(yz(["kirilan bacak", "istemci", "destekmez", "yukselir", "kalici", "yap.kal.",
  "istek(bin)"]));
for (const b of ACIK.filter((x) => x.kirilan > 0))
  console.log(yz([b.ad, b.istemci, b.kirilan, b.yuk, kalici(b), b.yap, b.istek]));
console.log(yz(["toplam", top(ACIK, (b) => b.istemci), top(ACIK, (b) => b.kirilan),
  top(ACIK, (b) => b.yuk), top(ACIK, kalici), top(ACIK, (b) => b.yap), top(ACIK, (b) => b.istek)]));

// Bir karar: hangi bacaklar zorlanir, hangileri kendi katmaninda sifrelenir, vekil kurulur mu.
const degerlendir = (zorlanan, kendi, vekil) => {
  const d = new Map(BACAK.map((b) => [b.id, b.durum]));
  let kirik = 0, yap = 0;
  for (const b of BACAK) {
    if (zorlanan.has(b.id)) { d.set(b.id, "sifreli"); yap += b.yap; kirik += vekil ? 0 : kalici(b); }
    if (kendi.has(b.id)) { d.set(b.id, "sifreli"); yap += b.kanit; }
  }
  if (vekil) yap += 3 * BACAK.filter((b) => zorlanan.has(b.id) && kalici(b) > 0).length;
  const kanitli = Object.values(YOL)
    .filter((y) => y.every((id) => d.get(id) === "sifreli")).length;
  const kanitsiz = top(BACAK.filter((b) => d.get(b.id) !== "sifreli"), (b) => b.istek);
  return { kirik, yap, kanitli, kanitsiz,
    istisna: BACAK.filter((b) => b.durum === "acik" && !zorlanan.has(b.id)).length };
};

const id = (l) => new Set(l.map((b) => b.id));
const bos = new Set();
const muaf = ACIK.filter((b) => kalici(b) > 0);            // kalici kirik ureten bacaklar
const KARAR = {
  "0 uyari modu": [bos, bos, false],
  "1 zorlama, istisnasiz": [id(ACIK), bos, false],
  "2 zorlama + vekil katman": [id(ACIK), bos, true],
  "3 vekil + kendi sifrelemen": [id(ACIK), id(BILINMIYOR), true],
  "4 zorlama + istisna": [id(ACIK.filter((b) => kalici(b) === 0)), bos, false],
};
console.log("\n" + yk(["karar", "zorlanan", "kalici kirik", "muaf acik", "kanitli yol", "ek yap.kal.",
  "kanitsiz(bin)"]));
for (const [ad, [z, k, v]] of Object.entries(KARAR)) {
  const s = degerlendir(z, k, v);
  console.log(yk([ad, z.size, s.kirik, s.istisna, `${s.kanitli}/${Object.keys(YOL).length}`,
    s.yap, s.kanitsiz]));
}

const acikIstek = top(ACIK, (b) => b.istek);
console.log(`\ngecis penceresi: ${PENCERE} gun, ${GECEN} gun gecti, ${PENCERE - GECEN} gun kaldi; ` +
  `uyari modunda gecen surede ${acikIstek * GECEN} bin istek acik bacaktan gecti`);
console.log(`kalici istisna siniri ${SINIR} bacak (kurgu politika); istenen ${muaf.length}, ` +
  `${muaf.length - SINIR} bacak sinirin disinda`);
console.log(`istemci yukseltmesi: ${top(ACIK, (b) => b.yuk)} istemci, ` +
  `${ACIK.filter((b) => b.yuk > 0).length} bacakta; geri kalan ${top(ACIK, kalici)} istemci ` +
  `yukseltilemiyor`);
console.log(`\nbilinmiyor kalemi: ${BILINMIYOR.length} bacak, ` +
  `${top(BILINMIYOR, (b) => b.istek)} bin istek/gun, kanit bedeli ` +
  `${top(BILINMIYOR, (b) => b.kanit)} yapilandirma kalemi`);
for (const b of BILINMIYOR)
  console.log(`  ${b.ad.padEnd(26)} ${String(b.istek).padStart(6)} bin/gun, ` +
    `kanit ${b.kanit} kalem, varsayim: saglayici ici tasima sifreli`);
```

```
kirilan bacak                 istemci  destekmez  yukselir  kalici  yap.kal.  istek(bin)
kenar cihaz -> alim ucu           340         54        38      16         3        4820
toplayici -> kuyruk                12          2         2       0         2        3100
isleyici -> onbellek                9          9         0       9         2        5400
is ortagi beslemesi -> alim         7          3         1       2         2         260
olcum agi bakim kanali             28         11         4       7         2          70
toplam                            458         79        45      34        23       27655

karar                        zorlanan  kalici kirik  muaf acik  kanitli yol  ek yap.kal.  kanitsiz(bin)
0 uyari modu                        0             0          9          0/6            0          33495
1 zorlama, istisnasiz               9            34          0          1/6           23           5840
2 zorlama + vekil katman            9             0          0          1/6           35           5840
3 vekil + kendi sifrelemen          9             0          0          6/6           46              0
4 zorlama + istisna                 5             0          4          1/6           14          16390

gecis penceresi: 90 gun, 61 gun gecti, 29 gun kaldi; uyari modunda gecen surede 1686955 bin istek acik bacaktan gecti
kalici istisna siniri 2 bacak (kurgu politika); istenen 4, 2 bacak sinirin disinda
istemci yukseltmesi: 45 istemci, 4 bacakta; geri kalan 34 istemci yukseltilemiyor

bilinmiyor kalemi: 4 bacak, 5840 bin istek/gun, kanit bedeli 11 yapilandirma kalemi
  ag gecidi -> toplayici       4820 bin/gun, kanit 4 kalem, varsayim: saglayici ici tasima sifreli
  isleyici -> nesne deposu      640 bin/gun, kanit 3 kalem, varsayim: saglayici ici tasima sifreli
  gunluk toplayici -> arsiv     190 bin/gun, kanit 2 kalem, varsayim: saglayici ici tasima sifreli
  arsiv -> ikincil bolge        190 bin/gun, kanit 2 kalem, varsayim: saglayici ici tasima sifreli
```

Kırılan bağlantı tablosu tek bir sayıyı ayırıyor: 79 istemci şifreli aktarımı desteklemiyor, 45'i
yükseltilebiliyor ve **34'ü yükseltilemiyor**. En sert satır önbellek bacağıdır: 9 istemcinin 9'u da
desteklemiyor, hiçbiri yükseltilemiyor ve o bacak günde 5.400 bin istek taşıyor. İkincisi kenar
cihazlarıdır: 54 cihazın 16'sı sahada duran, yazılımı değişmeyen donanım.

Karar tablosu beş yolu yan yana koyuyor. Uyarı modu hiçbir şey kırmaz ve hiçbir şeyi kanıtlamaz; 61
günde açık bacaklardan 1.686.955 bin istek geçmiştir ve bu geriye dönük kapatılamaz. İstisnasız
zorlama 23 kalem değiştirir ve 34 bağlantıyı kalıcı koparır. Vekil katman kırığı sıfırlar, 12 kalem
ekler: 35. Bu üç kararın hiçbiri kanıtlı yolu 1/6'nın üstüne çıkarmaz; çıkaran tek satır
dördüncüsüdür — "bilinmiyor" bacakları kendi katmanında şifrelemek 11 kalem daha ekler, toplam 46
olur ve **6/6 yol kanıtlı** hale gelir.

Son karar tersini gösteriyor: kalıcı kırık üreten 4 bacağı muaf tutmak yükü 14 kaleme indirir ve
hiçbir bağlantı kırmaz, ama kanıtsız hacim 16.390 bin istek/güne çıkar. Kurgu politika 2 kalıcı
istisna tanıyor; istenen 4'tür ve **2 bacak sınırın dışındadır.** Geçiş penceresinin 90 gününün 61'i
geçti, **29 gün kaldı.**

Dört "bilinmiyor" bacağın her birinin yanında aynı cümle var: varsayım, sağlayıcı içi taşımanın
şifreli olduğudur. Günde 5.840 bin istek taşıyorlar ve durumları kiracının hiçbir yapılandırmasından
okunmuyor. Bilinmemek, açık olmakla aynı şey değildir ama **kanıtlanabilir olmakla da aynı şey
değildir.**

#### Özet

- 16 bacağın 3'ü şifreli, 9'u açık, 4'ünün durumu bilinmiyor; sağlayıcı içi 11 bacağın yalnız 1'i
  şifreli ve o bacaklardan günde 33.165 bin istek geçiyor.
- Üç aşamalı zorlama 23 kalem değiştiriyor; en pahalı aşama (sağlayıcı içi, 16 kalem) en az bağlantı
  kırandır (11), en ucuz aşama 57 bağlantı kırar.
- 79 istemci şifreli aktarımı desteklemiyor; 45'i yükseltilebiliyor, 34'ü yükseltilemiyor ve vekil
  katman bu 34'ü kurtarırken 12 kalem ekliyor.
- Zorlamadan önce hiçbir yol uçtan uca şifreli değil; üç aşamadan sonra 1/6, kendi katmanında
  şifreleme eklenince 6/6 ve kanıtsız hacim 33.495'ten sıfıra iner.
- Muafiyet yolu yükü 14 kaleme indiriyor, kanıtsız hacmi 16.390 bin istek/güne çıkarıyor; kurgu
  politika 2 istisna tanıyor, 2 bacak sınırın dışında. Geçiş penceresinden 29 gün kaldı.

#### Sonraki Adım

Veri beklemede ve aktarımda şifreli hale getirildi. İkisi de aynı şeye dayanıyor: bir anahtar ya da
kimlik bilgisi bir yerde saklanıyor ve servisler onu okuyor. Bir sonraki ders o saklama katmanına
döner ve tek bir soruyu ölçer: sır döndürüldüğünde eski ile yeni değerin birlikte geçerli olduğu
**pencere** ne kadar olmalı — kısa pencere kaç istemciyi kaçırıyor, uzun pencere sızıntı süresini ne
kadar uzatıyor.

### Sır Saklama Servisleri

Source: https://academia.sh/tr/kurslar/bulut-yonetisimi/sir-saklama-servisleri

Sır döndürmenin ölçüsü penceredir: eski ile yeni değerin birlikte geçerli olduğu süre taranır. Kısa pencere 44 istemciyi kaçırıyor, sıfır kaçıran pencere 3.624 dakika ve yılda 601.584 dakika eski sır bırakıyor. Yalnız başlangıçta okuyan 18 istemciyi düzeltmek pencereyi 227 dakikaya indiriyor; 41 sırrın 17'si hiç döndürülmemiş.

Beklemede ve aktarımda şifreleme kurulduğunda ikisi de aynı şeye dayanıyordu: bir anahtar ya da
kimlik bilgisi bir yerde duruyor ve servisler onu okuyor. O yer bir **sır saklama servisidir** ve
kiralanan her katman gibi bir karar devreder. Bu dersin ölçtüğü karar tek bir sayıda toplanır:
**döndürme penceresi.** Sır döndürüldüğünde eski değer bir anda geçersiz olmaz; bir süre eski ve
yeni değer birlikte kabul edilir, istemciler bu sürede yeni değeri alır. Pencere kapandığında eski
değer reddedilir ve o ana kadar yeni değeri okumamış her istemci kırılır.

Pencere iki yönde birden ölçülür ve iki yön ters işaretlidir. **Kısa pencere kaçırılan istemci
üretir**; uzun pencere eski sırrın geçerli kaldığı süreyi uzatır — sızmış bir değer o süre boyunca
çalışmaya devam eder. Sırların hangi yollardan sızdığı — kayıt satırları, ortam değişkenleri, yapı
çıktısı katmanları — daha önce tarandı ve burada tekrarlanmaz; buranın konusu döndürmenin kendisidir.

Ölçüm **bölgesel ölçüm ağı** üzerindedir, **kurgudur** ve `node` ile yazılmış bir **modeldir**.
Modelde **gerçek sır değeri yoktur**: yalnız sır adları, istemci sayıları ve zamanlar taşınır.

**BG13.** Sır saklama servisinde 41 sır vardır: üç ortam, beş servis, beş sır türü ve üç kuruluş
çapında sır.
**BG14.** Sırları okuyan 83 istemci örneği vardır. Okuma biçimi üç değerlidir: her istekte okur,
önbellekli okur (önbellek ömrü 240 dakika), yalnız başlangıçta okur (dağıtım aralığı 4.320 dakika).
**BG15.** Döndürme penceresi eski ve yeni sırrın birlikte geçerli olduğu süredir; pencere bitmeden
yeni değeri almamış istemci **kaçırılmış** sayılır ve kırılır.
**BG16.** Her istemci örneği dakikada 12 istek yapar (kurgu birim).
**BG17.** Döndürme dönemi 90 gündür (kurgu politika). Sırların bir kısmı otomatik, bir kısmı elle
döndürülür, bir kısmı hiç döndürülmemiştir.
**BG18.** Rastgelelik kendi yazılan doğrusal üreteçten gelir; tohum 20260415'tir ve çıktıda görünür.
Son 90 gündeki insan okumaları modelde sayılıdır.

#### Pencereyi Taramak

```js
// sir.mjs — sir saklama servisi, istemci envanteri ve dondurme penceresi taramasi. MODELDIR.
// Bolgesel olcum agi KURGUDUR. GERCEK SIR YOKTUR: yalniz sir ADLARI ve sayilar modellenir.
// Rastgelelik kendi yazilmis dogrusal uretecten gelir; tohum asagida gorunur.
export const TOHUM = 20260415;
export const uretec = (t) => { let s = t >>> 0;
  return () => (s = (s * 1664525 + 1013904223) >>> 0) / 4294967296; };

const ORTAM = ["gelistirme", "hazirlik", "uretim"];
const KATALOG = [
  ["toplayici", ["veritabani-parolasi", "alim-anahtari"]],
  ["dogrulayici", ["veritabani-parolasi", "imzalama-anahtari"]],
  ["faturalama", ["veritabani-parolasi", "dis-uc-jetonu", "imzalama-anahtari"]],
  ["isemri", ["veritabani-parolasi", "dis-uc-jetonu"]],
  ["arsivci", ["veritabani-parolasi", "bakim-kimligi"]],
];
export const SIR = [
  ...ORTAM.flatMap((o) => KATALOG.flatMap(([s, tl]) => tl.map((t) =>
    ({ ad: `${o}/${s}/${t}`, ortam: o, servis: s, tur: t })))),
  ...KATALOG.map(([s]) => ({ ad: `uretim/${s}/bakim-kimligi`, ortam: "uretim", servis: s,
    tur: "bakim-kimligi" })),
  ...["olcum-agi-bakim", "ikincil-bolge-kopya", "is-ortagi-besleme"].map((a) =>
    ({ ad: `kurulus/${a}`, ortam: "kurulus", servis: "paylasilan", tur: "dis-uc-jetonu" })),
];

// Istemci ornekleri: her sirri okuyan surecler. Okuma bicimi alis zamanini belirler.
const r = uretec(TOHUM);
export const ISTEMCI = [];
for (const s of SIR) {
  const n = 1 + Math.floor(r() * ({ uretim: 6, kurulus: 3, hazirlik: 2, gelistirme: 2 })[s.ortam]);
  for (let i = 0; i < n; i++) {
    const u = r();
    ISTEMCI.push({ sir: s.ad, ortam: s.ortam, faz: r(),
      bicim: u < 0.45 ? "onbellek" : u < 0.75 ? "her-istek" : "baslangic" });
  }
}
for (const s of SIR) {                                    // dondurme gecmisi ve insan okumasi
  s.otomatik = r() < 0.55;
  s.yas = 40 + Math.floor(r() * 860);                     // sirrin olusturulmasindan bu yana, gun
  s.son = s.otomatik ? Math.floor(r() * 90) : (r() < 0.45 ? Math.floor(r() * 420) : null);
  s.insan = Math.floor(r() * 4);                          // son 90 gunde insan okumasi sayisi
}

export const ISTEK_DK = 12;                               // istemci basina dakikadaki istek (kurgu)
export const PROFIL = {                                   // istemci tarafinin alis davranisi
  "bugunku hal": { onbellek: 240, dagitim: 4320, degisen: [] },
  "onbellek 60 dk": { onbellek: 60, dagitim: 4320, degisen: ["onbellek"] },
  "baslangic okurlari": { onbellek: 240, dagitim: 60, degisen: ["baslangic"] },
  "hepsi yeniden okur": { onbellek: 60, dagitim: 60, degisen: ["onbellek", "baslangic"] },
};
export const alis = (c, p) => c.bicim === "her-istek" ? 1
  : Math.ceil(c.faz * (c.bicim === "onbellek" ? p.onbellek : p.dagitim));
export const kaciran = (p, W) => ISTEMCI.filter((c) => alis(c, p) > W);
export const DONEM = 90, YIL = 365;                       // kurgu dondurme donemi, gun

const B = [13, 20, 15, 18, 20];
export const yz = (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 bicimSay = (b) => ISTEMCI.filter((c) => c.bicim === b).length;
  console.log(`model (tohum ${TOHUM}): ${SIR.length} sir, ${ISTEMCI.length} istemci ornegi — ` +
    `${bicimSay("her-istek")} her istekte okur, ${bicimSay("onbellek")} onbellekli, ` +
    `${bicimSay("baslangic")} yalniz baslangicta okur`);
  const p = PROFIL["bugunku hal"];
  console.log(`\nbugunku hal: onbellek omru ${p.onbellek} dk, dagitim araligi ${p.dagitim} dk; ` +
    `en gec alis ${Math.max(...ISTEMCI.map((c) => alis(c, p)))} dk`);
  console.log("\n" + yz(["pencere(dk)", "kacirilan istemci", "etkilenen sir", "kirilan istek/dk",
    "yillik acik (dk)"]));
  const yillik = Math.round((YIL / DONEM) * SIR.length);   // yilda toplam dondurme sayisi
  for (const W of [0, 1, 30, 60, 120, 240, 720, 1440, 2880, 3624]) {
    const k = kaciran(p, W);
    console.log(yz([W, k.length, new Set(k.map((c) => c.sir)).size, k.length * ISTEK_DK,
      W * yillik]));
  }
}
```

```
model (tohum 20260415): 41 sir, 83 istemci ornegi — 27 her istekte okur, 38 onbellekli, 18 yalniz baslangicta okur

bugunku hal: onbellek omru 240 dk, dagitim araligi 4320 dk; en gec alis 3624 dk

pencere(dk)     kacirilan istemci  etkilenen sir  kirilan istek/dk    yillik acik (dk)
0                              83             40               996                   0
1                              56             34               672                 166
30                             53             32               636                4980
60                             44             30               528                9960
120                            38             29               456               19920
240                            18             17               216               39840
720                            14             14               168              119520
1440                           10             10               120              239040
2880                            3              3                36              478080
3624                            0              0                 0              601584
```

Tablonun iki ucu kararı çerçeveliyor. Üstte pencere sıfırdır: eski değer aynı anda reddedilir, 83
istemci örneğinin **hepsi** kaçırır ve dakikada 996 istek düşer. Altta pencere 3.624 dakikadır —
altmış saat — ve hiçbir istemci kaçırmaz. İkisinin arası bir seçim değil, bir takas eğrisidir.

Ortadaki satırlar takasın şeklini gösteriyor. Bir saatlik pencere 44 istemciyi kaçırıyor: 30 sırrı
etkiliyor ve dakikada 528 isteği kesiyor. Dört saat (240 dakika) kaçıranı 18'e düşürüyor, çünkü
önbellek ömrü 240 dakikadır ve o sınırda bütün önbellekli istemciler değeri yenilemiş oluyor.
Kalan 18, yalnız başlangıçta okuyan istemcilerdir ve onlar dört saatte değil, ancak bir sonraki
dağıtımda okur. Bir günlük pencere bile 10'unu kaçırıyor.

Son sütun ters yöndeki bedeli sayıyor. 41 sır 90 günlük dönemle yılda 166 kez döndürülüyor; her
döndürmede pencere boyunca eski değer geçerli kalıyor. Sıfır kaçıran pencerede yıllık toplam
**601.584 dakika** eder — 417 güne denk, yani yılın her anında ortalama 1,14 sır eski değeriyle de
çalışıyor demektir. Sızmış bir sır, sızıntının fark edilmesinden bağımsız olarak o süre boyunca
kabul edilir. Bir saatlik pencerede aynı toplam 9.960 dakikaya, altmışta bire iner.

İki sayı da kabul edilebilir değildir: 44 kırık istemci de, yılda 417 gün açık kalan eski sır da.
Pencere tek başına ayarlanacak bir düğme değildir; **istemci tarafı değişmeden hiçbir pencere
değeri iyi değildir.**

#### İstemci Tarafı ve Hiç Döndürülmeyen Sırlar

```js
// dondurme.mjs — otomatik dondurmenin istemci tarafi, dondurulmemis sirlar ve okuma yuzeyi.
import { SIR, ISTEMCI, PROFIL, alis, kaciran, ISTEK_DK, DONEM } from "./sir.mjs";

const gen = (B) => (h) => h.map((v, j) => j ? String(v).padStart(B[j]) : String(v).padEnd(B[0]))
  .join("");
const yp = gen([21, 10, 14, 18, 14, 16]);
const ortanca = (l) => l.length ? [...l].sort((a, b) => a - b)[Math.floor(l.length / 2)] : 0;

console.log(yp(["profil", "degisen", "pencere(dk)", "yillik acik (dk)", "60 dk kacan",
  "60 dk istek/dk"]));
for (const [ad, p] of Object.entries(PROFIL)) {
  const enGec = Math.max(...ISTEMCI.map((c) => alis(c, p)));
  const degisen = ISTEMCI.filter((c) => p.degisen.includes(c.bicim)).length;
  const k60 = kaciran(p, 60).length;
  console.log(yp([ad, degisen, enGec, enGec * Math.round((365 / DONEM) * SIR.length), k60,
    k60 * ISTEK_DK]));
}

const hic = SIR.filter((s) => s.son === null);
const oto = SIR.filter((s) => s.otomatik);
const elle = SIR.filter((s) => s.son !== null && !s.otomatik);
const ys = gen([24, 8, 14, 12, 20]);
console.log("\n" + ys(["dondurme sinifi", "sir", "en gec (gun)", "ortanca", "doneme kalan/asan"]));
const satir = (ad, l, alan) => {
  const v = l.map((s) => s[alan]);
  const enGec = Math.max(...v, 0);
  console.log(ys([ad, l.length, enGec, ortanca(v),
    enGec <= DONEM ? `${DONEM - enGec} gun kaldi` : `${enGec - DONEM} gun asildi`]));
};
satir("otomatik dondurulen", oto, "son");
satir("elle dondurulen", elle, "son");
satir("hic dondurulmemis", hic, "yas");
for (const s of [...hic].sort((a, b) => b.yas - a.yas).slice(0, 4))
  console.log(`  ${s.ad.padEnd(38)} ${String(s.yas).padStart(4)} gun, ` +
    `${ISTEMCI.filter((c) => c.sir === s.ad).length} istemci, ` +
    `son 90 gunde ${s.insan} insan okumasi`);

const insanli = SIR.filter((s) => s.insan > 0);
const kesisim = insanli.filter((s) => s.son === null);
console.log(`\nokuma yuzeyi: ${insanli.length}/${SIR.length} sir son 90 gunde bir insan tarafindan ` +
  `okundu (${SIR.reduce((a, s) => a + s.insan, 0)} okuma, hepsi denetim kaydinda)`);
console.log(`bunlarin ${kesisim.length} tanesi hic dondurulmemis sirdir; ` +
  `bu ${kesisim.length} sirri ${ISTEMCI.filter((c) => kesisim.some((s) => s.ad === c.sir)).length} ` +
  `istemci ornegi okuyor`);
const enGenis = SIR.map((s) => [s.ad, ISTEMCI.filter((c) => c.sir === s.ad).length])
  .sort((a, b) => b[1] - a[1])[0];
console.log(`en genis sir: ${enGenis[0]} — ${enGenis[1]} istemci ornegi; ` +
  `dondurulunce bu ${enGenis[1]} ornegin hepsi yeni degeri almak zorunda`);
```

```
profil                  degisen   pencere(dk)  yillik acik (dk)   60 dk kacan  60 dk istek/dk
bugunku hal                   0          3624            601584            44             528
onbellek 60 dk               38          3624            601584            18             216
baslangic okurlari           18           227             37682            26             312
hepsi yeniden okur           56            57              9462             0               0

dondurme sinifi              sir  en gec (gun)     ortanca   doneme kalan/asan
otomatik dondurulen           16            88          64         2 gun kaldi
elle dondurulen                8           371         209      281 gun asildi
hic dondurulmemis             17           826         442      736 gun asildi
  uretim/isemri/bakim-kimligi             826 gun, 5 istemci, son 90 gunde 1 insan okumasi
  hazirlik/arsivci/bakim-kimligi          789 gun, 1 istemci, son 90 gunde 1 insan okumasi
  kurulus/is-ortagi-besleme               760 gun, 1 istemci, son 90 gunde 0 insan okumasi
  uretim/dogrulayici/imzalama-anahtari    748 gun, 6 istemci, son 90 gunde 2 insan okumasi

okuma yuzeyi: 34/41 sir son 90 gunde bir insan tarafindan okundu (68 okuma, hepsi denetim kaydinda)
bunlarin 15 tanesi hic dondurulmemis sirdir; bu 15 sirri 34 istemci ornegi okuyor
en genis sir: uretim/toplayici/veritabani-parolasi — 6 istemci ornegi; dondurulunce bu 6 ornegin hepsi yeni degeri almak zorunda
```

Profil tablosu bu dersin en ters sonucunu veriyor. Önbellek ömrünü 240 dakikadan 60'a çekmek **38
istemciye dokunur ve pencereyi hiç kısaltmaz**: sıfır kaçıran pencere 3.624 dakikada kalır, yıllık
açık süre 601.584 dakikada kalır. Kazandığı tek şey bir saatlik pencerede kaçıranın 44'ten 18'e
inmesidir. Sebep açıktır: bağlayıcı kısıt önbellek değil, **yalnız başlangıçta okuyan 18
istemcidir**; onlar önbellek ömrünü hiç dinlemez.

Üçüncü satır bunu doğruluyor. Yalnız o 18 istemciyi yeniden okur hale getirmek — yarısından az
dokunuşla — pencereyi 3.624 dakikadan **227 dakikaya**, yıllık açık süreyi 601.584'ten 37.682
dakikaya indirir: on altıda bir. Dördüncü satır ikisini birleştirir: 56 istemci değişir, pencere 57
dakikaya iner, yıllık açık süre 9.462 dakika olur ve bir saatlik pencerede kaçıran **sıfırdır**.
Otomatik döndürmenin istemci tarafında gerektirdiği şey budur — sırrı yeniden okuma yeteneği
birinci, önbellek ömrü ikincidir. Yeniden okuma yoksa döndürme her seferinde bir dağıtım bekler.

Değişikliğin kendisi de bir kalemdir ve tabloda ilk sütunda duruyor. Yeniden okuma yeteneği eklemek
18 istemcide kod değişikliği ister; önbellek ömrünü kısaltmak 38 istemcide yapılandırma değişikliği.
İkisi birden 56 örnek eder ve o 56 örneğin her biri ayrı bir dağıtım kalemidir. Sıralama bu yüzden
önemlidir: 18 istemcilik iş, 38 istemcilik işten on altı kat fazla kazandırıyor ve tek başına
yapıldığında pencereyi dört saatin altına indiriyor. Hiçbir şey yapılmazsa döndürme dönemi işlemez —
17 sırrın hiç döndürülmemiş olmasının teknik karşılığı da budur.

Alt tablo aynı sorunun envanter yüzüdür. 41 sırrın 16'sı otomatik döndürülüyor ve en gecikmişine 90
günlük döneme **2 gün kalmış**. 8 sır elle döndürülüyor ve en gecikmişi dönemi 281 gün aşmış.
Geriye kalan **17 sır hiç döndürülmemiş** — envanterin yüzde kırkı — ve en yaşlısı 826 günlük. Bunu
ölçmek için ayrı bir tarama gerekmedi: son döndürme alanı boş olan kayıtlar sayıldı.

Son üç satır sırayı belirliyor. 41 sırrın 34'ü son 90 günde en az bir kez bir insan tarafından
okundu — toplam 68 okuma ve hepsi denetim kaydında duruyor. Bu 34 sırrın **15'i hiç döndürülmemiş
sırlardır** ve o 15 sırrı 34 istemci örneği okuyor. Kesişim döndürme sırasını verir: insan eli
değmiş ve hiç döndürülmemiş sır, envanterin geri kalanından önce gelir. En geniş sır üretim
toplayıcısının veritabanı parolasıdır; 6 istemci örneği okuyor ve döndürüldüğünde altısının da yeni
değeri alması gerekir — pencere kararı tam olarak bu altı örnek için verilir.

#### Özet

- Döndürme penceresi iki yönde ölçüldü: sıfır pencerede 83 istemcinin hepsi kaçırıyor, 3.624
  dakikalık pencerede hiçbiri kaçırmıyor; bir saatlik pencerede 44 istemci ve dakikada 528 istek.
- Uzun pencerenin bedeli sayıldı: 41 sır yılda 166 kez döndürülüyor ve 3.624 dakikalık pencere
  yılda 601.584 dakika eski sır bırakıyor; bir saatlik pencerede aynı toplam 9.960 dakikadır.
- Önbellek ömrünü dörtte bire indirmek 38 istemciye dokunuyor ve sıfır kaçıran pencereyi hiç
  kısaltmıyor; bağlayıcı kısıt yalnız başlangıçta okuyan 18 istemcidir.
- O 18 istemciyi yeniden okur hale getirmek pencereyi 227 dakikaya, ikisi birden 57 dakikaya
  indiriyor; ikinci durumda bir saatlik pencerede kaçıran sıfırdır.
- 41 sırrın 16'sı otomatik döndürülüyor (döneme 2 gün kaldı), 8'i elle (281 gün aşıldı) ve **17'si
  hiç döndürülmemiş**; en yaşlısı 826 günlük.
- Son 90 günde 34 sır bir insan tarafından okundu (68 okuma, hepsi kayıtta) ve bunların 15'i hiç
  döndürülmemiş sırlardır; döndürme sırası bu kesişimden çıkar.

#### Sonraki Adım

Şifreleme kuruldu, sırlar döndürülebilir hale geldi ve her ölçümde aynı cümle geçti: "hepsi denetim
kaydında". O cümle şimdiye kadar sınanmadı. Bir sonraki ders kaydın kendisini ölçer: bir olay
kümesi denetim günlüğüne düşürülür ve **kaç soru yanıtlanabiliyor** sayılır — kim, ne zaman, hangi
kaynak, hangi kimlikten. Kaydın kapsamadığı işlem türü adıyla yazılır, kaydı kimin silebildiği
sayılır ve saklama süresiyle maliyet birlikte taranır.

### Denetim Günlükleri

Source: https://academia.sh/tr/kurslar/bulut-yonetisimi/denetim-gunlukleri

Bir olay kümesi denetim kaydına düşürülür ve kaç sorunun yanıtlandığı sayılır: 480 olayın 273'ü dört soruyu birden yanıtlıyor, varsayılan yapılandırmada 88'i. Sekiz soruşturmanın 3'ü yanıtlanıyor. Kaydı 11 özne silebiliyor; ayrı hesaba taşımak 6 meşru işi durduruyor ve veri düzlemi kaydı yönetim düzleminin 772 katına mal oluyor.

Önceki üç derste aynı cümle defalarca geçti: "hepsi denetim kaydında". Anahtar kullanımı kayda
düşüyordu, sır okumaları kayda düşüyordu, politika değişiklikleri kayda düşüyordu. O cümle şimdiye
kadar hiç sınanmadı. Bu ders onu sınar ve ölçüyü tek bir biçime indirir: bir olay kümesi denetim
kaydına düşürülür ve **kaç soru yanıtlanabiliyor** sayılır. Sorular dörttür — kim, ne zaman, hangi
kaynak, hangi kimlikten.

Kaydın kapsamadığı bir işlem türü var ve adı yazılmalıdır: **veri düzlemi okumaları ve yazmaları.**
Yönetim düzlemi çağrıları (politika değişikliği, anahtar kullanımı, kaynak oluşturma) varsayılan
olarak kaydedilir; nesne okuma, nesne yazma ve kuyruk tüketimi kaydedilmez. Bu kayıt ayrı açılır ve
**ayrıca ücretlendirilir**. İkinci konu kaydın kendisidir: bir denetim günlüğü de bir yüzeydir — kim
silebiliyor, nereye yazılıyor, değiştirilemezliği nasıl sağlanıyor.

Ölçüm **bölgesel ölçüm ağı** üzerindedir, **kurgudur** ve `node` ile yazılmış bir **modeldir**.
Para birimi de kurgudur: "b" birimi uydurmadır, gerçek bir fiyat değildir.

**BG19.** Olay örneklemi 480 işlemdir; günlük hacim yönetim düzleminde 2.400, veri düzleminde
1.860.000 olaydır (kurgu).
**BG20.** Yönetim düzlemi kaydı varsayılan olarak açıktır; veri düzlemi kaydı ayrı açılır ve ayrıca
ücretlendirilir.
**BG21.** Olayın kimliği dört türdendir: kullanıcı, rol üstlenmiş kullanıcı, iş yükü kimliği,
otomatik servis. Rol üstlenmede tekil özne ancak **oturum etiketi** varsa okunur.
**BG22.** Toplu işlemler kaynağı tek tek adlandırmaz; kaynak alanı kapsayıcı adıyla dolar ve "hangi
kaynak" sorusu yanıtsız kalır.
**BG23.** Kaydın yazıldığı hedef için silebilen, değiştirebilen ve okuyan özne sayıları ile
değiştirilemezlik kilidi modelde yazılıdır.
**BG24.** Maliyet kurgu birimle hesaplanır: bin olay alımı 0,4 b, GB-ay saklama 12 b, olay boyutu
1,4 KB. Örneklemli kayıt tekil kaynak sorularını yanıtlamaz. Üreteç kendi yazılmıştır; tohum
20260722'dir.

#### Kaç Soru Yanıtlanabiliyor

```js
// olay.mjs — denetim kaydina dusen olaylar ve yanitlanabilen sorular. MODELDIR.
// Bolgesel olcum agi KURGUDUR. Uretec kendi yazilmistir; tohum asagida gorunur.
export const TOHUM = 20260722;
const uretec = (t) => { let s = t >>> 0;
  return () => (s = (s * 1664525 + 1013904223) >>> 0) / 4294967296; };

export const YONETIM = ["politika-degisikligi", "anahtar-kullanma", "rol-ustlenme",
  "ag-kurali-degisikligi", "sir-okuma", "kaynak-olusturma"];
export const VERI = ["nesne-okuma", "nesne-yazma", "nesne-silme", "kuyruk-tuketimi"];
export const GUNLUK = { yonetim: 2400, veri: 1860000 };    // gunluk olay hacmi (kurgu)

const r = uretec(TOHUM);
export const OLAY = Array.from({ length: 480 }, () => {
  const veriMi = r() < 0.72;
  const islem = veriMi ? VERI[Math.floor(r() * VERI.length)]
    : YONETIM[Math.floor(r() * YONETIM.length)];
  const u = r();
  const kimlik = u < 0.18 ? "kullanici" : u < 0.52 ? "rol-ustlenme"
    : u < 0.86 ? "is-yuku" : "otomatik-servis";
  return { duzlem: veriMi ? "veri" : "yonetim", islem, kimlik,
    etiket: kimlik === "rol-ustlenme" ? r() < 0.38 : true,   // oturum etiketi tekil ozneyi verir
    ayrinti: r() > (veriMi ? 0.34 : 0.12) };                 // toplu islem kaynagi adlandirmaz
});

// Dort soru: kayitta duran bir olay hangilerini yanitliyor.
export const SORU = {
  "ne zaman": () => true,
  "hangi kimlikten": () => true,
  "hangi kaynak": (o) => o.ayrinti,
  "kim (tekil ozne)": (o) => o.kimlik !== "rol-ustlenme" || o.etiket,
};
export const kayitta = (o, veriAcik) => o.duzlem === "yonetim" || veriAcik;

// Sorusturma: bir soru bir isleme, bir alana ve geriye bakis suresine baglidir.
export const SORUSTURMA = [
  ["uretim politika belgesini kim degistirdi", "politika-degisikligi", "kim (tekil ozne)", 12],
  ["arsivden hangi nesneler okundu", "nesne-okuma", "hangi kaynak", 5],
  ["musteri anahtarini hangi kimlik kullandi", "anahtar-kullanma", "hangi kimlikten", 40],
  ["olcum kaydini kim sildi", "nesne-silme", "kim (tekil ozne)", 3],
  ["ag kurali ne zaman gevsetildi", "ag-kurali-degisikligi", "ne zaman", 210],
  ["bakim kimligi hangi sirri okudu", "sir-okuma", "hangi kaynak", 60],
  ["is ortagi jetonunu kim okudu", "sir-okuma", "kim (tekil ozne)", 150],
  ["yedek hangi kaynaga yazildi", "nesne-yazma", "hangi kaynak", 400],
];
export const yanit = (s, veriAcik, saklama) => {
  const [, islem, alan, gun] = s;
  const l = OLAY.filter((o) => o.islem === islem && kayitta(o, veriAcik) && SORU[alan](o));
  if (gun > saklama) return ["hayir", `saklama ${saklama} gun < ${gun}`];
  if (l.length === 0) {
    const kapali = OLAY.some((o) => o.islem === islem) && VERI.includes(islem) && !veriAcik;
    return ["hayir", kapali ? "veri duzlemi kaydi kapali" : `${alan} alani bos`];
  }
  return ["evet", `${l.length} olay`];
};

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

if (import.meta.url === `file://${process.argv[1]}`) {
  const y = OLAY.filter((o) => o.duzlem === "yonetim").length;
  console.log(`model (tohum ${TOHUM}): ${OLAY.length} olay orneklemi — ${y} yonetim duzlemi, ` +
    `${OLAY.length - y} veri duzlemi; gunluk hacim ${GUNLUK.yonetim} / ${GUNLUK.veri} (kurgu)`);
  console.log("\n" + yz(["soru", "varsayilan", "veri de acik", "kayit disi kalan", "oran"]));
  for (const [ad, f] of Object.entries(SORU)) {
    const v = OLAY.filter((o) => kayitta(o, false) && f(o)).length;
    const t = OLAY.filter((o) => kayitta(o, true) && f(o)).length;
    console.log(yz([ad, v, t, OLAY.length - t, `${Math.round(100 * t / OLAY.length)}%`]));
  }
  const dort = (va) => OLAY.filter((o) => kayitta(o, va) &&
    Object.values(SORU).every((f) => f(o))).length;
  console.log(yz(["dordu birden", dort(false), dort(true), OLAY.length - dort(true),
    `${Math.round(100 * dort(true) / OLAY.length)}%`]));

  for (const [va, sk, ad] of [[false, 90, "varsayilan (yonetim, 90 gun)"],
    [true, 90, "veri duzlemi acik (90 gun)"], [true, 365, "veri duzlemi acik (365 gun)"]]) {
    const s = SORUSTURMA.map((x) => yanit(x, va, sk));
    console.log(`\n${ad}: ${s.filter((x) => x[0] === "evet").length}/${SORUSTURMA.length} soru ` +
      `yanitlaniyor`);
    if (ad.startsWith("varsayilan")) for (const [i, x] of SORUSTURMA.entries())
      console.log(`  ${x[0].padEnd(42)} ${s[i][0].padEnd(6)} ${s[i][1]}`);
  }
}
```

```
model (tohum 20260722): 480 olay orneklemi — 132 yonetim duzlemi, 348 veri duzlemi; gunluk hacim 2400 / 1860000 (kurgu)

soru                  varsayilan  veri de acik  kayit disi kalan        oran
ne zaman                     132           480                 0        100%
hangi kimlikten              132           480                 0        100%
hangi kaynak                 119           352               128         73%
kim (tekil ozne)              99           374               106         78%
dordu birden                  88           273               207         57%

varsayilan (yonetim, 90 gun): 3/8 soru yanitlaniyor
  uretim politika belgesini kim degistirdi   evet   16 olay
  arsivden hangi nesneler okundu             hayir  veri duzlemi kaydi kapali
  musteri anahtarini hangi kimlik kullandi   evet   17 olay
  olcum kaydini kim sildi                    hayir  veri duzlemi kaydi kapali
  ag kurali ne zaman gevsetildi              hayir  saklama 90 gun < 210
  bakim kimligi hangi sirri okudu            evet   15 olay
  is ortagi jetonunu kim okudu               hayir  saklama 90 gun < 150
  yedek hangi kaynaga yazildi                hayir  saklama 90 gun < 400

veri duzlemi acik (90 gun): 5/8 soru yanitlaniyor

veri duzlemi acik (365 gun): 7/8 soru yanitlaniyor
```

İlk sütun varsayılan yapılandırmanın kapsamıdır ve 480 olayın 348'i o sütunda hiç yoktur — veri
düzlemi kaydı kapalıdır. "Ne zaman" ve "hangi kimlikten" soruları kalan 132 olayın hepsinde
yanıtlanıyor; kayıt bu iki alanı her zaman taşır.

Diğer iki soru taşımıyor. Veri düzlemi de açıldığında "hangi kaynak" 480 olayın 352'sinde
yanıtlanıyor: kalan 128 olay **toplu işlemdir** ve kaynak alanı tek tek nesneleri değil kapsayıcıyı
adlandırır. "Kim" sorusu 374'te yanıtlanıyor; eksik 106 olay rol üstlenmiş çağrılardır ve oturum
etiketi taşımıyorlar. Kayıtta rolün adı var, o rolü üstlenen insanın adı yok — rol paylaşımlıysa
soru orada biter.

Dört soruyu **birden** yanıtlayan olay sayısı 273'tür, yani %57. Varsayılan yapılandırmada aynı sayı
88'dir: 480 olayın %18'i. Bu, "hepsi denetim kaydında" cümlesinin ölçülmüş karşılığıdır.

Soruşturma listesi aynı sonucu somut sorularla veriyor: sekiz sorunun **üçü** yanıtlanıyor.
Başarısızlıklar iki sınıfta toplanıyor ve ikisi ayrı kararlara bakıyor. İki soru veri düzlemi kaydı
kapalı olduğu için, üç soru saklama süresi yetmediği için yanıtsız. Veri düzlemi açılınca 5/8, üstüne
saklama 365 güne çıkınca 7/8 olur. Hangisinin önce yapılacağı bir maliyet sorusudur ve sonraki
bölümde sayılıdır.

#### Kaydın Kendi Yüzeyi ve Saklamanın Faturası

```js
// kayit.mjs — kaydin kendi yuzeyi (silme, degistirilemezlik) ve saklama-maliyet taramasi.
// Para birimi KURGUDUR: "b" birimi uydurmadir, gercek fiyat degildir.
import { GUNLUK, SORUSTURMA, yanit } from "./olay.mjs";

const HEDEF = [                                           // kayit nereye yaziliyor. MODEL.
  ["ayni hesap, ayni kova", 11, 11, 14, "yok", 0, 0],
  ["ayni hesap, kilitli kova", 3, 0, 14, "saklama kilidi", 4, 2],
  ["ayri hesap, kilitli kova", 1, 0, 5, "saklama kilidi", 9, 6],
  ["ayri hesap + ikinci kopya", 0, 0, 5, "kilit + kopya", 14, 6],
].map(([ad, sil, degis, oku, kilit, ek, duran]) => ({ ad, sil, degis, oku, kilit, ek, duran }));

const OLAY_KB = 1.4, ALIM_BIN = 0.4, SAKLAMA_GB = 12;     // kurgu birim (b)
const gb = (n, gun) => (n * gun * OLAY_KB) / (1024 * 1024);
const aylik = (n, gun) => Math.round((n * 30 / 1000) * ALIM_BIN + gb(n, gun) * SAKLAMA_GB);

const gen = (B) => (h) => h.map((v, j) => j ? String(v).padStart(B[j]) : String(v).padEnd(B[0]))
  .join("");
const yh = gen([27, 11, 16, 9, 19, 10, 12]);
const ym = gen([14, 12, 14, 14, 14, 13, 13]);

console.log(yh(["kayit hedefi", "silebilen", "degistirebilen", "okuyan", "degistirilemezlik",
  "ek kalem", "duran is"]));
for (const h of HEDEF)
  console.log(yh([h.ad, h.sil, h.degis, h.oku, h.kilit, h.ek, h.duran]));

console.log("\n" + ym(["saklama(gun)", "yonetim GB", "yonetim(b/ay)", "veri GB", "veri(b/ay)",
  "%5 orneklem", "kapsanan"]));
for (const gun of [30, 90, 180, 365, 730]) {
  const t = SORUSTURMA.map((x) => yanit(x, true, gun)).filter((x) => x[0] === "evet").length;
  console.log(ym([gun, gb(GUNLUK.yonetim, gun).toFixed(2), aylik(GUNLUK.yonetim, gun),
    Math.round(gb(GUNLUK.veri, gun)), aylik(GUNLUK.veri, gun),
    aylik(GUNLUK.veri * 0.05, gun), `${t}/${SORUSTURMA.length}`]));
}

const kapsam = (va, gun) => SORUSTURMA.map((x) => yanit(x, va, gun))
  .filter((x) => x[0] === "evet").length;
const tut = (va, gun) => aylik(GUNLUK.yonetim, gun) + (va ? aylik(GUNLUK.veri, gun) : 0);
console.log(`\nkapsam ve maliyet (kurgu birim b): varsayilan ${kapsam(false, 90)}/8 -> ` +
  `${tut(false, 90)} b/ay; veri duzlemi acik 90 gun ${kapsam(true, 90)}/8 -> ${tut(true, 90)} b/ay; ` +
  `365 gun ${kapsam(true, 365)}/8 -> ${tut(true, 365)} b/ay`);
console.log(`veri duzlemi kaydini acmak: +${tut(true, 90) - tut(false, 90)} b/ay ve ` +
  `+${kapsam(true, 90) - kapsam(false, 90)} soru. Saklamayi 90 -> 365 gun: ` +
  `+${tut(true, 365) - tut(true, 90)} b/ay ve +${kapsam(true, 365) - kapsam(true, 90)} soru`);
console.log(`ayni kapsamin iki yolu: yalniz yonetim duzlemi 365 gun ${kapsam(false, 365)}/8 -> ` +
  `${tut(false, 365)} b/ay; veri duzlemi acik 90 gun ${kapsam(true, 90)}/8 -> ${tut(true, 90)} b/ay`);
console.log(`veri duzlemi kaydi yonetim duzlemi kaydinin ` +
  `${(aylik(GUNLUK.veri, 365) / aylik(GUNLUK.yonetim, 365)).toFixed(0)} katidir; %5 orneklem bu ` +
  `farki 20'ye boler ama tekil kaynak sorularini yanitlamaz`);
```

```
kayit hedefi                 silebilen  degistirebilen   okuyan  degistirilemezlik  ek kalem    duran is
ayni hesap, ayni kova               11              11       14                yok         0           0
ayni hesap, kilitli kova             3               0       14     saklama kilidi         4           2
ayri hesap, kilitli kova             1               0        5     saklama kilidi         9           6
ayri hesap + ikinci kopya            0               0        5      kilit + kopya        14           6

saklama(gun)    yonetim GB yonetim(b/ay)       veri GB    veri(b/ay)  %5 orneklem     kapsanan
30                    0.10            30            75         23214         1161          3/8
90                    0.29            32           224         25002         1250          5/8
180                   0.58            36           447         27684         1384          6/8
365                   1.17            43           906         33197         1660          7/8
730                   2.34            57          1813         44074         2204          8/8

kapsam ve maliyet (kurgu birim b): varsayilan 3/8 -> 32 b/ay; veri duzlemi acik 90 gun 5/8 -> 25034 b/ay; 365 gun 7/8 -> 33240 b/ay
veri duzlemi kaydini acmak: +25002 b/ay ve +2 soru. Saklamayi 90 -> 365 gun: +8206 b/ay ve +2 soru
ayni kapsamin iki yolu: yalniz yonetim duzlemi 365 gun 5/8 -> 43 b/ay; veri duzlemi acik 90 gun 5/8 -> 25034 b/ay
veri duzlemi kaydi yonetim duzlemi kaydinin 772 katidir; %5 orneklem bu farki 20'ye boler ama tekil kaynak sorularini yanitlamaz
```

Üstteki tablo dersin en rahatsız edici satırıyla başlıyor. Varsayılan yerleşimde denetim kaydı,
kaydettiği olayların gerçekleştiği hesabın içinde duruyor ve **11 özne onu silebiliyor, 11'i
değiştirebiliyor.** Kaydın anlamı buradan gelir: bir olayı yapabilen özne, o olayın kaydını da
kaldırabiliyorsa kayıt bir kanıt değil, bir kolaylıktır. Saklama kilidi değiştirebileni sıfıra,
silebileni 3'e indiriyor; bedeli 4 kalem yapılandırma ve **2 meşru işin durmasıdır** — kova üzerinde
doğrudan çalışan iki iş kilitle uyuşmuyor.

Ayrı hesaba taşımak silebileni 1'e indirir, ama okuyan özne sayısını 14'ten 5'e düşürür ve **6 meşru
iş durur**: kaydı doğrudan sorgulayan ekipler erişimlerini kaybeder ve hesaplar arası okuma ayrıca
kurulmadan geri gelmez. Daraltmanın bedeli budur ve 9 yapılandırma kalemiyle birlikte gelir. Son
satır silebileni sıfırlar: kilit ve ikinci kopya, 14 kalem. Değiştirilemezlik ücretsiz bir özellik
değil, 14 kalemlik bir yapılandırma ve 6 durmuş iştir.

Alt tablo saklama ile maliyeti aynı satırda tutuyor. Yönetim düzlemi kaydı ucuzdur: 365 günde ayda
43 b, 1,17 GB. Veri düzlemi kaydı aynı sürede 33.197 b ve 906 GB — **772 kat**. "Kaydın kapsamadığı
işlem türü" ücretsiz olduğu için kapsam dışında değildir; kapsam dışıdır çünkü açıldığında fatura
üç basamak büyür. Yüzde beşlik örneklem bu farkı yirmiye böler, ama tekil kaynak sorularını
yanıtlamaz: "arşivden hangi nesneler okundu" sorusu örneklemli bir kayıtta yanıtsızdır.

Marjinal hesap sıralamayı belirliyor. Veri düzlemini açmak ayda 25.002 b ekliyor ve 2 soru
kazandırıyor: soru başına 12.501 b. Saklamayı 90 günden 365 güne çıkarmak 8.206 b ekliyor ve yine 2
soru kazandırıyor: soru başına 4.103 b. Son satır kararı kesinleştiriyor — **yalnız yönetim düzlemi
kaydını 365 gün saklamak 5/8 soruyu ayda 43 b'ye yanıtlıyor**, veri düzlemini açıp 90 gün saklamak
aynı 5/8 için 25.034 b istiyor. Beş yüz seksen kat fark, tek bir yapılandırma sırasından doğuyor.

#### Özet

- 480 olayın 273'ü dört soruyu birden yanıtlıyor (%57); varsayılan yapılandırmada bu sayı 88'dir
  (%18), çünkü 348 olay veri düzlemindedir ve hiç kaydedilmez.
- "Ne zaman" ve "hangi kimlikten" kayıtlı her olayda yanıtlanıyor; "hangi kaynak" 128 toplu işlemde,
  "kim" ise oturum etiketi taşımayan 106 rol üstlenme çağrısında yanıtsız kalıyor.
- Sekiz soruşturmanın 3'ü varsayılan yapılandırmada yanıtlanıyor; iki soru veri düzlemi kapalı
  olduğu, üç soru saklama süresi yetmediği için düşüyor.
- Kaydı varsayılan yerleşimde 11 özne silebiliyor ve 11'i değiştirebiliyor; kilit ve ayrı hesap bunu
  0'a indiriyor, karşılığında 14 yapılandırma kalemi ve **6 meşru işin durması** geliyor.
- Veri düzlemi kaydı yönetim düzlemi kaydının 772 katına mal oluyor (365 gün, kurgu birim);
  yüzde beşlik örneklem farkı yirmiye böler ama tekil kaynak sorularını yanıtlamaz.
- Marjinal bedel sırayı veriyor: soru başına saklama uzatması 4.103 b, veri düzlemi açması 12.501 b;
  yalnız yönetim düzlemini 365 gün saklamak 5/8 soruyu ayda 43 b'ye yanıtlıyor.

#### Sonraki Adım

Şifreleme, döndürme ve kayıt kurulduğunda ortaya bir sorun çıkıyor: bunların hepsi **yapılandırma**
olarak duruyor ve yapılandırma zamanla kayıyor. Bir kova kilidi kaldırılıyor, bir kayıt hedefi
değiştiriliyor, bir bacak muafiyeti kalıcı hale geliyor. Bir sonraki ders bu kaymayı kural kümesiyle
ölçer: kaç kaynak uyum kurallarından geçiyor, kaç tanesi geçmiyor ve otomatik düzeltme devreye
girdiğinde kaç meşru yapılandırma bozuluyor.

### Yapılandırma Uyum Denetimi

Source: https://academia.sh/tr/kurslar/bulut-yonetisimi/yapilandirma-uyum-denetimi

Sapmanın otomatik tespiti: 22 kiralanmış kaynakta 6 kuralın koşturulması, 46 ateşleyen çiftin 40'ının işaretlenmesi, 38 gerçek uyumsuzluğun 32'sinin yakalanıp 6'sının kaçması, üç düzeltme kipinde açıkta kalan kaynağın 16'dan 6'ya inerken 8 meşru yapılandırmanın bozulması ve 6 meşru değişiklikten 5'inin durdurulması.

Önceki ders kimin ne yaptığını kayda geçirdi: denetim günlüğü, geçmiş kipinde bir kayıttır ve
sorusu "bu işlem oldu mu" sorusudur. Bu dersin sorusu şimdiki kiptedir — kaynağın **şu anki
yapılandırması** kurala uyuyor mu? Kayıt, yanlış olanı gösterip göstermediği konusunda sessizdir;
bir depoyu genel erişime açan işlem kayda düzgünce düşer ve kayıt o işlemin yanlış olduğunu
söylemez.

**Yapılandırma uyum denetimi** (configuration compliance), kaynak kümesinin üzerinde bir kural
kümesi koşturup uyumsuz olanı işaretlemektir. Yapılandırma sapması M22/K01'de, sapmayı kapatan
uzlaştırıcı döngü M22/K05'te ölçüldü; ikisi de burada tekrarlanmaz. Ayrım şudur: orada istenen
durumu yazan da, sapmayı kapatan da aynı taraftı. Burada kaynak kiralanmıştır, kural kümesini
başkası yazar ve düzeltme, kiralanan katmana **yazma yetkisi** ister — düzeltmenin kendisi bir
erişim kalemi hâline gelir.

#### Kural Kümesi ve Uyumsuz Kaynak

Örnek kursun kurgu **bölgesel ölçüm ağı**dır: beş ekip, üç ortam. **BG25 — kaynak çizelgesi:**
yirmi iki kaynak; her satır bir kaynağın sahibi ekibi, ortamını ve altı yapılandırma alanını
taşır. **BG26 — kural kümesi:** altı kural; her kural bir yüklem, düzeltmenin değiştireceği alan
ve düzeltilmiş değerden oluşur. **BG27 — istisna kayıtları:** dört kayıt; üçü kaynak, biri **ekip
düzeyinde** yazılmıştır. **BG28 — gerçek uyumsuzluk etiketi:** otuz sekiz
kaynak-kural çifti elle uyumsuz etiketlenmiştir; ikisi kural kümesinde karşılığı olmayan bir
türdedir. **BG29 — değişiklik akışı:** yirmi değişiklik, altısı meşru etiketli. **BG30 — birim
girdiler:** elle düzeltme kalem başına 25 dakika, denetleyicinin tarama başına değerlendirme
kotası 240 (kurgu birim).

Aşağıdaki dosya çizelgeleri, kuralları ve üç kipi kurar. Süreç içi bir **modeldir**; gerçek bulut
kaynağı, denetleyici ya da düzeltme yoktur.

```js
// uyum/denetim.mjs — kiralanan katmanda yapilandirma uyum denetimi. Surec ici model: bolgesel
// olcum agi (kurgu); gercek bulut kaynagi, denetleyici ya da duzeltme yoktur.

const satir = (s) => s.trim().split("\n").map((l) => l.trim().split("|"));
const yaz = (g, ...s) => console.log(s.map((v, i) =>
  (g[i] < 0 ? String(v).padEnd(-g[i]) : String(v).padStart(g[i]))).join(""));

// Kaynak: ad|ekip|ortam|genel erisim|beklemede sifreleme|denetim gunlugu|yonetim portu genis|sahip etiketi|anahtar yasi (gun)
const KAYNAK = satir(`
  olcum-depo|olcum|uretim|0|1|1|0|1|120
  olcum-arsiv|olcum|uretim|0|0|1|0|1|900
  olcum-sinama|olcum|sinama|1|0|0|1|0|500
  akis-kuyruk|akis|uretim|0|1|1|0|1|200
  akis-depo|akis|uretim|1|1|0|0|1|410
  akis-gelistirme|akis|gelistirme|1|0|0|1|0|730
  katalog-depo|katalog|uretim|0|1|1|0|1|90
  katalog-kapi|katalog|uretim|1|1|1|0|1|150
  katalog-sinama|katalog|sinama|0|0|1|1|1|380
  kapi-genel|kapi|uretim|1|1|1|0|1|60
  kapi-yonetim|kapi|uretim|0|1|1|1|1|340
  kapi-gelistirme|kapi|gelistirme|1|1|0|1|0|620
  isletim-gunluk|isletim|uretim|0|1|1|0|1|280
  isletim-yedek|isletim|uretim|0|0|1|0|1|1100
  isletim-arac|isletim|sinama|0|1|0|1|1|450
  isletim-gelistirme|isletim|gelistirme|1|1|0|0|0|800
  olcum-kenar|olcum|uretim|1|1|1|0|1|170
  akis-arsiv|akis|uretim|0|0|1|0|0|960
  katalog-yedek|katalog|uretim|0|1|0|0|1|520
  kapi-sinama|kapi|sinama|0|1|1|1|1|300
  isletim-kota|isletim|uretim|0|1|1|0|1|110
  olcum-rapor|olcum|sinama|0|1|0|0|0|240`)
  .map(([ad, ekip, ortam, genel, sifre, gunluk, port, etiket, yas]) =>
    ({ ad, ekip, ortam, genel: +genel, sifre: +sifre, gunluk: +gunluk,
       port: +port, etiket: +etiket, yas: +yas }));

// Kural kumesi: kural kimligi -> [yuklem, duzeltmenin degistirdigi alan, duzeltilmis deger]
const KURAL = {
  Y1: [(k) => k.genel === 1, "genel", 0],
  Y2: [(k) => k.sifre === 0, "sifre", 1],
  Y3: [(k) => k.gunluk === 0, "gunluk", 1],
  Y4: [(k) => k.port === 1, "port", 0],
  Y5: [(k) => k.etiket === 0, "etiket", 1],
  Y6: [(k) => k.yas > 365, "yas", 90],
};
const AD = { Y1: "genel erisim kapali", Y2: "beklemede sifreleme", Y3: "denetim gunlugu",
  Y4: "yonetim portu dar", Y5: "sahip etiketi", Y6: "anahtar yasi <= 365",
  Y7: "aktarimda sifreleme" };

// Bildirilmis istisna kayitlari (model girdisi). Ucu kaynak, biri ekip duzeyinde yazilmistir.
const ISTISNA = satir(`
  kapi-genel|Y1
  olcum-kenar|Y1
  isletim-yedek|Y6
  ekip:akis|Y6`).map((x) => x.join("|"));

const istisnali = (k, r) =>
  ISTISNA.includes(`${k.ad}|${r}`) || ISTISNA.includes(`ekip:${k.ekip}|${r}`);

// Elle etiketli gercek uyumsuzluk (model girdisi): sapmanin mesru olmadigi kaynak-kural ciftleri.
// Y7 kural kumesinde yoktur; iki gercek uyumsuzluk bu turdedir.
const GERCEK = satir(`
  olcum-sinama|Y1 Y2 Y3 Y4 Y5 Y6
  akis-depo|Y1 Y3 Y6
  akis-gelistirme|Y1 Y2 Y6
  kapi-gelistirme|Y1 Y3 Y6
  isletim-gelistirme|Y1 Y3 Y5 Y6
  olcum-arsiv|Y2
  katalog-sinama|Y2 Y4 Y6
  isletim-yedek|Y2 Y6
  akis-arsiv|Y2 Y5 Y6
  isletim-arac|Y3 Y6
  katalog-yedek|Y3 Y6
  olcum-rapor|Y3 Y5
  kapi-yonetim|Y4
  kapi-sinama|Y4
  akis-kuyruk|Y7
  katalog-depo|Y7`).flatMap(([ad, r]) => r.split(" ").map((x) => `${ad}|${x}`));

const KURALLAR = Object.keys(KURAL);
const TUM = [...KURALLAR, "Y7"];

// Atesleyen: yuklem dogru. Isaretlenen: atesleyen ve istisna kaydi yok.
const atesle = (kume) => {
  const a = [], i = [];
  for (const k of kume) for (const r of KURALLAR) if (KURAL[r][0](k)) {
    a.push(`${k.ad}|${r}`);
    if (!istisnali(k, r)) i.push(`${k.ad}|${r}`);
  }
  return { atesleyen: a, isaretli: i };
};

const taban = atesle(KAYNAK);
const yak = taban.isaretli.filter((x) => GERCEK.includes(x));
const yanlis = taban.isaretli.filter((x) => !GERCEK.includes(x));
const kacan = GERCEK.filter((x) => !taban.isaretli.includes(x));
const uyumsuzKaynak = new Set(taban.isaretli.map((x) => x.split("|")[0]));

console.log(`${KAYNAK.length} kaynak, ${KURALLAR.length} kural, ${ISTISNA.length} istisna kaydi, ` +
  `${GERCEK.length} elle etiketli gercek uyumsuzluk`);
console.log(`isaretlenen kaynak: ${uyumsuzKaynak.size}/${KAYNAK.length}, ` +
  `isaretlenen cift: ${taban.isaretli.length} (atesleyen ${taban.atesleyen.length})`);

const K = [-8, -22, 11, 12, 11, 8, 15];
console.log();
yaz(K, "kural", "ne bakiyor", "atesleyen", "isaretlenen", "yakalanan", "kacan", "yanlis isaret");
for (const r of TUM) {
  const at = taban.atesleyen.filter((x) => x.endsWith(`|${r}`)).length;
  const is = taban.isaretli.filter((x) => x.endsWith(`|${r}`));
  const y = is.filter((x) => GERCEK.includes(x)).length;
  const kc = GERCEK.filter((x) => x.endsWith(`|${r}`) && !is.includes(x)).length;
  yaz(K, r, AD[r], at, is.length, y, kc, is.length - y);
}
yaz(K, "toplam", "", taban.atesleyen.length, taban.isaretli.length, yak.length, kacan.length,
  yanlis.length);

// Degisiklik akisi: kaynak|alan|yeni deger|mesru mu (model girdisi)
const DEGISIKLIK = satir(`
  katalog-depo|genel|1|1
  katalog-depo|gunluk|0|0
  olcum-depo|port|1|0
  olcum-depo|yas|900|0
  akis-kuyruk|genel|1|1
  akis-kuyruk|sifre|0|0
  isletim-kota|port|1|1
  isletim-kota|etiket|0|0
  kapi-genel|gunluk|0|0
  kapi-genel|yas|700|0
  olcum-kenar|port|1|1
  katalog-kapi|sifre|0|0
  katalog-kapi|yas|800|0
  isletim-gunluk|genel|1|1
  isletim-gunluk|port|1|0
  olcum-depo|etiket|0|0
  akis-kuyruk|yas|900|1
  kapi-yonetim|gunluk|0|0
  isletim-kota|yas|600|0
  katalog-depo|etiket|0|0`)
  .map(([ad, alan, deger, mesru]) => ({ ad, alan, deger: +deger, mesru: mesru === "1" }));

// Uc kip: yalniz bildir, engelle, duzelt. Her kip ayni akisi ayni sirayla gorur.
const kipKos = (kip) => {
  const durum = KAYNAK.map((k) => ({ ...k }));
  const bul = (ad) => durum.find((k) => k.ad === ad);
  let durdurulan = 0, geriAlinan = 0, bozulan = 0, duzeltilen = 0;

  if (kip === "duzelt") for (const k of durum) for (const r of KURALLAR)
    if (KURAL[r][0](k) && !istisnali(k, r)) {
      if (!GERCEK.includes(`${k.ad}|${r}`)) bozulan++;
      k[KURAL[r][1]] = KURAL[r][2];
      duzeltilen++;
    }

  for (const d of DEGISIKLIK) {
    const k = bul(d.ad);
    const once = { ...k };
    k[d.alan] = d.deger;
    const yeni = KURALLAR.filter((r) => KURAL[r][0](k) && !KURAL[r][0](once) && !istisnali(k, r));
    if (yeni.length === 0) continue;
    if (kip === "engelle") { Object.assign(k, once); if (d.mesru) durdurulan++; }
    else if (kip === "duzelt") {
      for (const r of yeni) { k[KURAL[r][1]] = KURAL[r][2]; duzeltilen++; }
      if (d.mesru) geriAlinan++;
    }
  }

  // Pencere sonunda acikta kalan: hala gercek uyumsuzluk tasiyan kaynak ve cift
  const acik = new Set(), cift = [];
  for (const k of durum) {
    for (const r of KURALLAR) if (KURAL[r][0](k) && GERCEK.includes(`${k.ad}|${r}`))
      { acik.add(k.ad); cift.push(`${k.ad}|${r}`); }
    if (GERCEK.includes(`${k.ad}|Y7`)) { acik.add(k.ad); cift.push(`${k.ad}|Y7`); }
  }
  // Denetleyicinin yazma yetkisi: yalnizca duzelt kipi alan yazar
  const alan = kip === "duzelt" ? KAYNAK.length * KURALLAR.length : 0;
  return { acik: acik.size, cift: cift.length, durdurulan, geriAlinan, bozulan, duzeltilen, alan };
};

const KIP = ["bildir", "engelle", "duzelt"], SONUC = {};
for (const kip of KIP) SONUC[kip] = kipKos(kip);

const D = [-10, 15, 13, 11, 23, 20, 15];
console.log();
yaz(D, "kip", "acikta kaynak", "acikta cift", "duzeltme", "durdurulan/geri alinan",
  "bozulan mesru yap.", "yazma yetkisi");
for (const kip of KIP) {
  const s = SONUC[kip];
  yaz(D, kip, s.acik, s.cift, s.duzeltilen, s.durdurulan + s.geriAlinan, s.bozulan,
    `${s.alan} alan`);
}

// Elle duzeltme yuku (kurgu birim): bildir kipinde her isaretli cift bir is kalemidir
const DAKIKA = 25, KISI_SAAT = (n) => ((n * DAKIKA) / 60).toFixed(1);
const mesruDeg = DEGISIKLIK.filter((d) => d.mesru).length;
console.log(`\nbildir kipi kuyrugu: ${taban.isaretli.length} cift x ${DAKIKA} dk = ` +
  `${KISI_SAAT(taban.isaretli.length)} kisi-saat; akistaki ${DEGISIKLIK.length} degisikligin ` +
  `${mesruDeg} tanesi mesru etiketli`);
console.log(`engelle: mesru degisikligin ${SONUC.engelle.durdurulan}/${mesruDeg} tanesi ` +
  `durduruldu; duzelt: ${SONUC.duzelt.geriAlinan}/${mesruDeg} tanesi geri alindi`);
console.log(`kacan ${kacan.length} ciftin ${kacan.filter((x) => x.endsWith("|Y7")).length} tanesi ` +
  `kural kumesinde karsiligi olmayan tur, ` +
  `${kacan.filter((x) => !x.endsWith("|Y7")).length} tanesi istisna kaydinin kapsadigi cift`);
const ekipIstisna = GERCEK.filter((x) => {
  const [ad, r] = x.split("|");
  const k = KAYNAK.find((z) => z.ad === ad);
  return ISTISNA.includes(`ekip:${k.ekip}|${r}`);
}).length;
console.log(`ekip duzeyinde yazilmis tek istisna kaydi ${ekipIstisna} gercek uyumsuzlugu ortuyor`);

// Sinir ve kalan (kurgu): denetleyicinin tarama basina degerlendirme kotasi
const KOTA = 240, kullanilan = KAYNAK.length * KURALLAR.length;
console.log(`\ndegerlendirme kotasi ${KOTA}/tarama; kullanilan ${KAYNAK.length} x ` +
  `${KURALLAR.length} = ${kullanilan}, kalan ${KOTA - kullanilan} -> ayni kural kumesiyle ` +
  `${Math.floor((KOTA - kullanilan) / KURALLAR.length)} kaynak daha, ya da ayni kaynak ` +
  `kumesiyle ${Math.floor(KOTA / KAYNAK.length) - KURALLAR.length} kural daha`);
```

```
22 kaynak, 6 kural, 4 istisna kaydi, 38 elle etiketli gercek uyumsuzluk
isaretlenen kaynak: 15/22, isaretlenen cift: 40 (atesleyen 46)

kural   ne bakiyor              atesleyen isaretlenen  yakalanan   kacan  yanlis isaret
Y1      genel erisim kapali             8           6          5       0              1
Y2      beklemede sifreleme             6           6          6       0              0
Y3      denetim gunlugu                 8           8          7       0              1
Y4      yonetim portu dar               7           7          4       0              3
Y5      sahip etiketi                   6           6          4       0              2
Y6      anahtar yasi <= 365            11           7          6       4              1
Y7      aktarimda sifreleme             0           0          0       2              0
toplam                                 46          40         32       6              8

kip         acikta kaynak  acikta cift   duzeltme durdurulan/geri alinan  bozulan mesru yap.  yazma yetkisi
bildir                 16           38          0                      0                   0         0 alan
engelle                16           38          0                      5                   0         0 alan
duzelt                  6            6         59                      5                   8       132 alan

bildir kipi kuyrugu: 40 cift x 25 dk = 16.7 kisi-saat; akistaki 20 degisikligin 6 tanesi mesru etiketli
engelle: mesru degisikligin 5/6 tanesi durduruldu; duzelt: 5/6 tanesi geri alindi
kacan 6 ciftin 2 tanesi kural kumesinde karsiligi olmayan tur, 4 tanesi istisna kaydinin kapsadigi cift
ekip duzeyinde yazilmis tek istisna kaydi 3 gercek uyumsuzlugu ortuyor

degerlendirme kotasi 240/tarama; kullanilan 22 x 6 = 132, kalan 108 -> ayni kural kumesiyle 18 kaynak daha, ya da ayni kaynak kumesiyle 4 kural daha
```

Sayılar **ölçüm** sınıfındadır; girdileri yukarıdaki varsayımlardır. Yirmi iki kaynak üzerinde
altı kural kırk altı yerde ateşliyor, istisna kayıtları altısını süzüyor ve geriye kırk işaretli
çift kalıyor. Kaynak düzeyinde bakıldığında yirmi ikinin on beşi uyumsuz görünüyor — bu, ilk
taramada okunacak sayıdır ve tek başına yanıltıcıdır, çünkü işaretlenen her çift gerçekten
uyumsuz değildir.

#### Kural Başına Yakalanan ve Kaçan

Alt tablo kuralları ayırıyor ve kuralların birbirine benzemediğini gösteriyor. Y2 temiz çalışıyor:
altı yerde ateşliyor, altısı da gerçekten uyumsuz, yanlış işareti yok — çünkü yüklemi bir kaynağın
niyetinden bağımsızdır, beklemede şifrelemenin kapalı olmasının meşru bir okuması yoktur. Y4 aynı
biçimde yazılmış ama başka türlü davranıyor: yedi ateşlemenin dördü gerçek, üçü meşru bir
yapılandırmayı işaretliyor; geliştirme ortamındaki bir yönetim aracının portunun açık olması o
ortamın kendi düzenidir. Y5 de aynı: altı ateşlemenin ikisi geçici geliştirme kaynağına ait ve
sahip etiketi bilerek boştur.

Kırk işaretli çiftin otuz ikisi gerçek uyumsuzluk, sekizi **yanlış işaret**. Kaçan altı çift ise
iki ayrı yerden geliyor ve ikisi de kuralın eşiğiyle ilgili değildir. Dördü istisna kayıtlarının
altında duruyor: Y6 on bir yerde ateşliyor ama yalnız yedisi işaretleniyor, çünkü bir istisna
kaydı **ekip düzeyinde** yazılmıştır ve tek başına üç gerçek uyumsuzluğu örtüyor. İstisnanın
kapsamı, uyumsuzluğun kendisinden daha belirleyicidir — istisna kaydı yazma yetkisi bir denetim
kalemidir ve kimin yazabildiği sayılmalıdır. Kalan iki kaçan çift kural kümesinde karşılığı
olmayan bir türdedir: aktarımda şifreleme için yazılmış bir kural yoktur, dolayısıyla o iki
kaynak için üretilen sayı da yoktur. Kuralları sıkılaştırmak bu boşluğu kapatmaz; boşluk eşikte
değil, kural kümesinin kapsamındadır.

#### Üç Düzeltme Kipi

Yirmi değişiklikten oluşan akış üç kipte de aynı sırayla koşuyor. **Yalnız bildir** kipi hiçbir
şeye dokunmaz: açıkta kalan otuz sekiz çift ve on altı kaynak duruyor, denetleyicinin kiralanan
katmanda yazma yetkisi sıfır alandır, karşılığında kırk kalemlik bir elle düzeltme kuyruğu doğuyor
— kalem başına 25 dakikayla 16,7 kişi-saat. **Engelle** kipi yeni değişikliği reddeder ama var
olana dokunmaz; açıkta kalan sayı değişmiyor, on altı kaynak ve otuz sekiz çift aynen duruyor.
Engellemenin bedeli ise başka bir sütunda: akıştaki altı meşru değişikliğin beşi durduruldu.

Kaçan tek meşru değişikliğin nasıl geçtiği söylenmeye değer. Akış kuyruğunun anahtar yaşını
uzatan değişikliği reddedilmedi, çünkü o ekibin Y6 için ekip düzeyinde bir istisna kaydı var —
yani meşru işi geçiren kayıt ile üç gerçek uyumsuzluğu örten kayıt **aynı kayıttır**. İstisnayı
daraltmak kaçanı dörtten bire indirir ve durdurulan meşru değişikliği beşten altıya çıkarır; iki
sütun aynı düğmeye bağlıdır.

**Düzelt** kipi açıkta kalanı on altı kaynaktan altıya, otuz sekiz çiftten altıya indiriyor. Kalan
altı çift zaten kaçanlardır: dördü istisna kaydının örttüğü, ikisi kural kümesinde karşılığı
olmayan tür. Denetleyici bunun için elli dokuz düzeltme yazıyor ve yirmi iki kaynağın altı alanına,
yani yüz otuz iki alana yazma yetkisi istiyor. Kiralanan katmanda bu, hiçbir insanın sahip olmadığı
genişlikte bir yetkidir: bir kaynağı ağa açan, şifrelemeyi çeviren ve anahtarı değiştiren tek
özne, denetim aracının kendisi olur.

#### Yanlış Düzeltmenin Bedeli

Düzelt kipinin ikinci sütunu asıl ölçüdür: sekiz meşru yapılandırma bozuldu. Bunlar yanlış
işaretlenen sekiz çiftin tamamıdır — kamuya açık olması gereken katalog kapısı kapatıldı, üç
yönetim portu daraltıldı, iki geçici kaynağa sahip etiketi yazıldı, bir arşiv anahtarının ömrü
kısaltıldı, bir sınama kaynağının günlüğü açıldı. Denetleyici bunların meşru olduğunu bilmiyor,
çünkü meşruluk bilgisinin tek taşıyıcısı istisna kaydıdır ve bu sekiz çift için yazılmamıştır.

Oran adıyla anılmalı: taban taramasındaki kırk düzeltmenin sekizi, yani her beş düzeltmeden
biri meşru bir yapılandırmayı bozuyor. Üstüne akıştan gelen beş meşru değişiklik uygulandıktan sonra geri
alınıyor. Kip seçimi bu yüzden bir kural sıkılığı seçimi değil, iki sütun arasında bir seçimdir:
bildir kipi hiçbir meşru işi durdurmaz ve on altı kaynağı açıkta bırakır; düzelt kipi on kaynağı
kapatır ve on üç meşru işlemi bozar ya da geri alır. Ortadaki engelle kipi ikisini de yapmaz —
yeni uyumsuzluğu içeri sokmaz ama eskisini de kapatmaz; var olan on altı kaynak için hâlâ bir
elle düzeltme kuyruğu gerekir.

#### Sınır ve Kalan

Denetleyicinin kendi sınırı da sayılır. Tarama başına değerlendirme kotası 240 birimdir; yirmi iki
kaynak çarpı altı kural, 132 birim kullanıyor ve 108 kalıyor. Aynı kural kümesiyle on sekiz kaynak
daha eklenebilir ya da aynı kaynak kümesiyle dört kural daha yazılabilir; ikisi birden yapılamaz.
Kapsam boşluğunu kapatmak için yazılacak aktarımda şifreleme kuralı yirmi iki değerlendirme yer
kaplar, yani kalan bütçenin beşte birini. Kota, kural yazmayı ücretsiz olmaktan çıkarır: kural
kümesini büyütmek ile kaynak sayısını büyütmek aynı sınıra çarpar.

#### Özet

- Yirmi iki kaynak üzerinde altı kural kırk altı yerde ateşliyor, dört istisna kaydı altısını
  süzüyor; kırk işaretli çiftin otuz ikisi gerçek uyumsuzluk, sekizi yanlış işarettir.
- Kaçan altı çiftin dördü istisna kayıtlarının altındadır ve tek bir ekip düzeyinde kayıt üç
  gerçek uyumsuzluğu örtüyor; ikisi kural kümesinde karşılığı olmayan türdür ve eşik
  sıkılaştırmakla kapanmaz.
- Yalnız bildir kipi on altı kaynağı açıkta bırakır, hiçbir meşru işi durdurmaz ve kırk kalemlik
  bir kuyruk üretir (16,7 kişi-saat, kurgu birim).
- Engelle kipi açıkta kalanı değiştirmez ama altı meşru değişikliğin beşini durdurur; geçen tek
  meşru değişiklik, üç gerçek uyumsuzluğu örten istisna kaydı sayesinde geçiyor.
- Düzelt kipi açıkta kalanı on altı kaynaktan altıya indirir; karşılığında sekiz meşru
  yapılandırmayı bozar, beş meşru değişikliği geri alır ve yüz otuz iki alanda yazma yetkisi ister.
- Denetleyicinin tarama başına 240 değerlendirmelik kotasının 132'si kullanılıyor; kalan 108 birim
  on sekiz kaynağa ya da dört kurala yeter, ikisine birden değil.

#### Sonraki Adım

Uyum denetimi kaynağın yapılandırmasını okudu ve ilk kuralı genel erişimle ilgiliydi: Y1 sekiz
yerde ateşledi, altısı işaretlendi. Ama bu kural bir kaynağın açık olup olmadığına bakan tek bir
bayrağı okuyor. Bayrak kapatıldığında o kaynağa gerçekten kaç yol kaldığı, hizmete hangi uçtan
gidildiği ve adın nasıl çözümlendiği hiç sorulmadı. Sonraki ders yönetilen bir hizmete erişimin
kaç yoldan sağlandığını sayar ve genel uç kapatıldığında kaç meşru erişimin kırıldığını ölçer.

### Ağ Yalıtımı ve Özel Uç Noktalar

Source: https://academia.sh/tr/kurslar/bulut-yonetisimi/ag-yalitimi-ve-ozel-uc-noktalar

Yönetilen hizmete genel uçtan mı özel uçtan mı gidildiğinin ölçümü: 25 erişimde genel uç kapatılınca 12 meşru erişimin kırılması, 12 erişimin sıfır yola düşmesi, aynı adın 11 yerine 14 yerde özel adrese çözülmesi ve eksiklerin kapatılmasının 12 yeni özel uç ile ayda 180 kurgu birim tutması.

Önceki ders bir kaynağın genel erişime açık olup olmadığını tek bir bayrakla okudu: Y1 sekiz yerde
ateşledi, altısı işaretlendi. O bayrak bir kaynağın kendi ayarıdır. Bu dersin sorusu bir aşama
öncesindedir — bir iş yükü **yönetilen bir hizmete** gittiğinde paketi hangi yoldan gidiyor? Ağ
yalıtımının ve özel bağlantının kendisi M23/K02'de ölçüldü; burada tekrarlanmaz. Buranın nesnesi
tek tek kiralanmış hizmetlerdir: bir nesne deposuna, bir kuyruğa ya da bir sır saklama servisine
erişim, hizmetin **genel ucundan** mı yoksa özel ağın içine yerleştirilmiş bir **özel uç
noktadan** mı geçiyor?

Ayrımın ölçülebilir olmasının nedeni şudur: yönetilen hizmet varsayılan olarak genel bir adla ve
genel bir adresle gelir. Özel uç nokta iki şeyi birden değiştirir — ağa yeni bir yol ekler ve
adın **çözümlendiği adresi** değiştirir. İkisi ayrı ayrı bozulabilir ve bu ders ikisini ayrı ayrı
sayar.

#### Hizmet, Ağ ve Erişim Çizelgesi

Örnek kursun kurgu **bölgesel ölçüm ağı**dır. **BG31 — yönetilen hizmet kataloğu:** yedi hizmet;
altısı özel uç noktayı destekler, biri yalnız genel uç sunar. Her destekli hizmetin aylık bir özel
uç kirası vardır (kurgu birim). **BG32 — üç özel ağ ve tek eşleme kaydı:** üretim ile sınama ağı
eşlenmiştir, ortak ağ eşlenmemiştir. **BG33 — kurulu özel uç noktalar:** altı hizmetin altısı da
yalnız üretim ağında kuruludur. **BG34 — ad çözümleme bölgesi:** özel kayıtları taşıyan bölge
üretim ve ortak ağa bağlıdır, sınama ağına bağlı değildir. **BG35 — erişim çizelgesi:** yirmi beş
erişim; yirmi ikisi meşru, üçü meşru değil, üçü bir atlama noktasına çevrilebilir. **BG36 — üç
senaryo:** A genel uç açık, B genel uç kapalı, C genel uç kapalı ve eksikler kapatılmış.

Aşağıdaki dosya bu çizelgeleri kurar ve üç senaryoyu koşturur. Süreç içi bir **modeldir**; gerçek
ağ, ad kaydı ya da hizmet yoktur.

```js
// yalitim/uc.mjs — yonetilen hizmete genel uctan mi ozel uctan mi gidildiginin olcumu.
// Surec ici model: bolgesel olcum agi (kurgu); gercek ag, ad kaydi ya da hizmet yoktur.

const satir = (s) => s.trim().split("\n").map((l) => l.trim().split("|"));
const yaz = (g, ...s) => console.log(s.map((v, i) =>
  (g[i] < 0 ? String(v).padEnd(-g[i]) : String(v).padStart(g[i]))).join(""));

// Yonetilen hizmet: ad|ozel uc destegi|ozel uc aylik kirasi (kurgu birim)
const HIZMET = Object.fromEntries(satir(`
  nesne-deposu|1|18
  iliskisel-depo|1|18
  kuyruk|1|14
  sir-saklama|1|12
  anahtar-yonetimi|1|12
  gunluk-toplama|1|16
  bildirim-hizmeti|0|0`).map(([ad, d, k]) => [ad, { destek: d === "1", kira: +k }]));

// Ozel aglar ve esleme (model girdisi). ortak-ag eslenmemistir.
const AG = ["uretim-ag", "sinama-ag", "ortak-ag"];
const ESLEME = [["uretim-ag", "sinama-ag"]];
const eslesik = (a, b) => a === b || ESLEME.some(([x, y]) =>
  (x === a && y === b) || (x === b && y === a));

// Kurulu ozel uc noktalar: hizmet|ag. Alti hizmetin altisi da yalniz uretim aginda.
const KURULU_A = satir(`
  nesne-deposu|uretim-ag
  iliskisel-depo|uretim-ag
  kuyruk|uretim-ag
  sir-saklama|uretim-ag
  anahtar-yonetimi|uretim-ag
  gunluk-toplama|uretim-ag`).map((x) => x.join("|"));

// Ad cozumleme bolgesinin bagli oldugu aglar: sinama-ag baglanmamistir.
const ZONA_A = ["uretim-ag", "ortak-ag"];

// Erisim: istemci|hizmet|konum (ag ya da dis)|mesru mu|atlama noktasina cevrilebilir mi
const ERISIM = satir(`
  olcum-toplayici|nesne-deposu|uretim-ag|1|0
  olcum-toplayici|kuyruk|uretim-ag|1|0
  akis-isleyici|kuyruk|uretim-ag|1|0
  akis-isleyici|iliskisel-depo|uretim-ag|1|0
  akis-isleyici|anahtar-yonetimi|uretim-ag|1|0
  katalog-servisi|iliskisel-depo|uretim-ag|1|0
  katalog-servisi|sir-saklama|uretim-ag|1|0
  kapi-servisi|gunluk-toplama|uretim-ag|1|0
  kapi-servisi|bildirim-hizmeti|uretim-ag|1|0
  sinama-kosucu|nesne-deposu|sinama-ag|1|0
  sinama-kosucu|iliskisel-depo|sinama-ag|1|0
  sinama-kosucu|kuyruk|sinama-ag|1|0
  ortak-rapor|nesne-deposu|ortak-ag|1|0
  ortak-rapor|iliskisel-depo|ortak-ag|1|0
  ortak-rapor|gunluk-toplama|ortak-ag|1|0
  yonetim-araci|iliskisel-depo|dis|1|1
  yonetim-araci|sir-saklama|dis|1|1
  yonetim-araci|anahtar-yonetimi|dis|1|1
  gece-isi|nesne-deposu|dis|1|0
  gece-isi|kuyruk|dis|1|0
  kenar-yukleyici|nesne-deposu|dis|1|0
  kenar-yukleyici|bildirim-hizmeti|dis|1|0
  gelistirici-dizustu|nesne-deposu|dis|0|0
  gelistirici-dizustu|iliskisel-depo|dis|0|0
  bilinmeyen-istemci|nesne-deposu|dis|0|0`)
  .map(([istemci, hizmet, konum, mesru, atlama]) =>
    ({ istemci, hizmet, konum, mesru: mesru === "1", atlama: atlama === "1" }));

// Bir erisimin yollari ve ad cozumlemesi. genelAcik: hizmetin genel ucu hala aciksa.
const olc = (e, { kurulu, zona, genelAcik, atlamaVar }) => {
  const ozelVar = (ag) => kurulu.includes(`${e.hizmet}|${ag}`);
  const ozelYol = e.konum !== "dis" && AG.some((a) => ozelVar(a) && eslesik(a, e.konum));
  const genelYol = genelAcik(e.hizmet);
  // Ad cozumlemesi: ic bolgeye bagli bir agdan bakiliyorsa ve o hizmetin kaydi varsa ozel adres
  const kayitVar = AG.some((a) => ozelVar(a));
  const cozum = e.konum !== "dis" && zona.includes(e.konum) && kayitVar ? "ozel" : "genel";
  // Atlama noktasi: dis istemci ic ag uzerinden gecer, ad ic bolgeden cozulur
  const atlamaYolu = atlamaVar && e.atlama && kayitVar;
  const yollar = [];
  if (ozelYol) yollar.push("ozel");
  if (genelYol) yollar.push("genel");
  if (atlamaYolu) yollar.push("atlama");
  const calisiyor = (cozum === "ozel" && ozelYol) || (cozum === "genel" && genelYol) || atlamaYolu;
  const durum = calisiyor
    ? (atlamaYolu && !(cozum === "ozel" && ozelYol) && !(cozum === "genel" && genelYol)
        ? "atlama" : cozum === "ozel" ? "ozel uc" : "genel uc")
    : (cozum === "ozel" ? "ad ozel, yol yok" : "ad genel, uc kapali");
  return { yol: yollar.length, cozum, calisiyor, durum };
};

// Uc senaryo
const hepsiDestekli = (h) => HIZMET[h].destek;
const KURULU_C = AG.flatMap((a) => Object.keys(HIZMET).filter(hepsiDestekli).map((h) => `${h}|${a}`));
const SENARYO = {
  "A genel uc acik": { kurulu: KURULU_A, zona: ZONA_A, atlamaVar: false,
    genelAcik: () => true },
  "B genel uc kapali": { kurulu: KURULU_A, zona: ZONA_A, atlamaVar: false,
    genelAcik: (h) => !HIZMET[h].destek },
  "C eksikler kapatildi": { kurulu: KURULU_C, zona: AG, atlamaVar: true,
    genelAcik: (h) => !HIZMET[h].destek },
};

const S = [-22, 10, 12, 10, 16, 10, 14];
yaz(S, "senaryo", "ozel uc", "genel uc", "atlama", "kirilan mesru", "kesilen", "internetten");
const R = {};
for (const [ad, s] of Object.entries(SENARYO)) {
  const c = ERISIM.map((e) => ({ e, ...olc(e, s) }));
  const say = (d) => c.filter((x) => x.durum === d).length;
  R[ad] = {
    ozel: say("ozel uc"), genel: say("genel uc"), atlama: say("atlama"),
    kirilan: c.filter((x) => !x.calisiyor && x.e.mesru).length,
    kesilen: c.filter((x) => !x.calisiyor && !x.e.mesru).length,
    internet: c.filter((x) => x.calisiyor && x.durum === "genel uc").length,
    c,
  };
  yaz(S, ad, R[ad].ozel, R[ad].genel, R[ad].atlama, R[ad].kirilan, R[ad].kesilen, R[ad].internet);
}

// Ad cozumlemesi: ayni ad hangi senaryoda hangi adrese cozuluyor
const C = [-22, 14, 15];
console.log();
yaz(C, "senaryo", "ozel adrese", "genel adrese");
for (const ad of Object.keys(SENARYO))
  yaz(C, ad, R[ad].c.filter((x) => x.cozum === "ozel").length,
    R[ad].c.filter((x) => x.cozum === "genel").length);

// Genel uc kapatilinca kac yol kaliyor: erisim basina yol sayisi dagilimi
const Y = [-22, 9, 9, 9, 14];
console.log();
yaz(Y, "senaryo", "0 yol", "1 yol", "2 yol", "toplam erisim");
for (const ad of Object.keys(SENARYO)) {
  const d = [0, 1, 2].map((n) => R[ad].c.filter((x) => x.yol === n).length);
  yaz(Y, ad, ...d, ERISIM.length);
}

// B senaryosunda kirilan mesru erisimlerin nedeni
const B = [-24, 10];
console.log();
yaz(B, "B: kirilma nedeni", "erisim");
for (const n of ["ad ozel, yol yok", "ad genel, uc kapali"])
  yaz(B, n, R["B genel uc kapali"].c.filter((x) => !x.calisiyor && x.e.mesru
    && x.durum === n).length);
const konumlar = [...new Set(ERISIM.map((e) => e.konum))];
const KN = [-24, 10];
console.log();
yaz(KN, "B: kirilan mesru, konum", "erisim");
for (const k of konumlar) {
  const n = R["B genel uc kapali"].c.filter((x) => !x.calisiyor && x.e.mesru && x.e.konum === k);
  if (n.length) yaz(KN, k, n.length);
}

// Ozel uc noktanin maliyeti: her hizmet ve her ag icin ayri (kurgu birim)
const kira = (kurulu) => kurulu.reduce((t, x) => t + HIZMET[x.split("|")[0]].kira, 0);
const destekli = Object.keys(HIZMET).filter(hepsiDestekli).length;
console.log(`\nozel uc: A/B ${KURULU_A.length} adet, aylik ${kira(KURULU_A)} birim; ` +
  `C ${KURULU_C.length} adet (${destekli} hizmet x ${AG.length} ag), aylik ${kira(KURULU_C)} birim`);
console.log(`C, B'ye gore ${KURULU_C.length - KURULU_A.length} yeni ozel uc ve ` +
  `${kira(KURULU_C) - kira(KURULU_A)} birim/ay ekliyor; ` +
  `kirilan mesru erisim ${R["B genel uc kapali"].kirilan} -> ${R["C eksikler kapatildi"].kirilan}`);
const kapatilamaz = Object.keys(HIZMET).filter((h) => !HIZMET[h].destek);
console.log(`ozel uc desteklemeyen ${kapatilamaz.length} hizmet: ` +
  `${ERISIM.filter((e) => !HIZMET[e.hizmet].destek).length} erisim her senaryoda ` +
  `genel uctan geciyor; birim basina ${(kira(KURULU_C) / KURULU_C.length).toFixed(1)} birim ` +
  `ortalama kira`);

// Kurulan her ozel uc bir hizmet ve bir ag icindir; kaci gercekten kullaniliyor
const GEREKLI = [...new Set(ERISIM.filter((e) => e.mesru && e.konum !== "dis"
  && HIZMET[e.hizmet].destek).map((e) => `${e.hizmet}|${e.konum}`))];
const bosta = KURULU_C.filter((x) => !GEREKLI.includes(x));
console.log(`C'deki ${KURULU_C.length} ozel ucun ${GEREKLI.length} tanesi bir mesru erisim ` +
  `tarafindan kullaniliyor; ${bosta.length} tanesi bosta ve ayda ${kira(bosta)} birim yiyor`);
console.log(`yalnizca gerekli ${GEREKLI.length} ozel uc kurulsa ayda ${kira(GEREKLI)} birim: ` +
  `ust sinir ${destekli} hizmet x ${AG.length} ag = ${destekli * AG.length}, kalan ` +
  `${destekli * AG.length - GEREKLI.length} kurulum`);
```

```
senaryo                  ozel uc    genel uc    atlama   kirilan mesru   kesilen   internetten
A genel uc acik                8          14         0               3         0            14
B genel uc kapali              8           2         0              12         3             2
C eksikler kapatildi          14           2         3               3         3             2

senaryo                  ozel adrese   genel adrese
A genel uc acik                   11             14
B genel uc kapali                 11             14
C eksikler kapatildi              14             11

senaryo                   0 yol    1 yol    2 yol toplam erisim
A genel uc acik               0       14       11            25
B genel uc kapali            12       13        0            25
C eksikler kapatildi          6       19        0            25

B: kirilma nedeni           erisim
ad ozel, yol yok                 3
ad genel, uc kapali              9

B: kirilan mesru, konum     erisim
sinama-ag                        3
ortak-ag                         3
dis                              6

ozel uc: A/B 6 adet, aylik 90 birim; C 18 adet (6 hizmet x 3 ag), aylik 270 birim
C, B'ye gore 12 yeni ozel uc ve 180 birim/ay ekliyor; kirilan mesru erisim 12 -> 3
ozel uc desteklemeyen 1 hizmet: 2 erisim her senaryoda genel uctan geciyor; birim basina 15.0 birim ortalama kira
C'deki 18 ozel ucun 12 tanesi bir mesru erisim tarafindan kullaniliyor; 6 tanesi bosta ve ayda 78 birim yiyor
yalnizca gerekli 12 ozel uc kurulsa ayda 192 birim: ust sinir 6 hizmet x 3 ag = 18, kalan 6 kurulum
```

Sayılar **ölçüm** sınıfındadır; girdileri yukarıdaki varsayımlardır. İlk okunacak satır A
senaryosudur ve rahatsız edicidir: özel uç noktalar kurulmuş, genel uç hâlâ açık ve yirmi beş
erişimin **on dördü genel internetten geçiyor**. Özel uç kurulmuş olması trafiğin oradan geçtiği
anlamına gelmiyor. Aynı satırda A senaryosunda bile üç meşru erişim kırık duruyor.

#### Yol Sayısı ile Erişimin Ayrılması

Yol dağılımı tablosu bu ayrımı taşıyor. A senaryosunda hiçbir erişim sıfır yolda değil: on dördü
tek yolda, on biri iki yolda. Yani üretim ve sınama ağındaki on bir erişim için hem özel uç hem
genel uç açıktır. Buna rağmen sınama ağındaki üç erişim genel uçtan gidiyor, çünkü **ad çözümleme
bölgesi sınama ağına bağlı değil**. Yol vardır, ad onu göstermez. Ölçünün ayırdığı şey budur:
özel uç noktayı kurmak bir yol açar, ad kaydını bağlamak o yolu kullanılır kılar ve ikisi ayrı
işlerdir.

Ortak ağdaki üç erişim ters tarafta durur. Ad bölgesi ortak ağa bağlıdır, dolayısıyla ad özel
adrese çözülür; ama ortak ağ üretim ağıyla eşlenmemiştir ve özel adrese giden bir yol yoktur. A
senaryosunda bile bu üç erişim kırıktır ve kırılma nedeni genel ucun kapatılması değildir. Ad
çözümlemesi yönlendirmeden önce sonuç verir; adres yanlış tarafa çözüldüğünde açık duran genel uç
bile kurtarmaz.

#### Genel Uç Kapatıldığında Kalan

B senaryosunda destekli altı hizmetin genel ucu kapatılıyor. Yirmi beş erişimin **on ikisi sıfır
yola düşüyor**, on üçü tek yolda kalıyor ve iki yollu erişim kalmıyor. Kırılan meşru erişim üçten
on ikiye çıkıyor; buna karşılık meşru olmayan üç erişim — geliştirici dizüstünün üretim deposuna
iki doğrudan okuması ve kaynağı bilinmeyen bir istemci — kesiliyor. Kazanç sütunu budur ve üç
kalemdir.

Kırılan on ikinin nedenleri iki gruba ayrılıyor. Üçü "ad özel, yol yok" durumundadır ve zaten
A'da da kırıktı; dokuzu "ad genel, uç kapalı" durumundadır ve doğrudan kapatmanın sonucudur.
Konuma göre bakıldığında sınama ağından üç, ortak ağdan üç ve **dışarıdan altı** erişim kırılıyor.
Dışarıdan gelen altısı bu dersin asıl uyarısıdır: gece toplu işi, kenar yükleyicisi ve yönetim
aracı özel ağın içinde değildir, hiçbir zaman da olmamıştı. Genel ucun kapatılması bunları
görmeden keser, çünkü kapatma kararı hizmet tarafında verilir ve hizmet tarafı istemcinin nerede
olduğunu bilmez.

#### Eksikleri Kapatmanın Faturası

C senaryosunda üç şey birden yapılıyor: her destekli hizmet için her ağda özel uç kuruluyor, ad
bölgesi üç ağa da bağlanıyor ve yönetim aracı için bir atlama noktası ekleniyor. Sonuç, kırılan
meşru erişimi on ikiden üçe indiriyor; özel uçtan geçen erişim sekizden on dörde çıkıyor, üç
erişim atlama noktası üzerinden geçiyor ve genel adrese çözülen ad sayısı on dörtten on bire
iniyor.

Kalan üç kırık erişim kapatılamayanlardır: gece toplu işinin iki erişimi ve kenar yükleyicisinin
depo erişimi. Bunlar dışarıdan çalışır, atlama noktasına çevrilemez ve özel uç noktanın tanımı
gereği erişemez. Bir özel uç nokta, ağın içinden erişimi çözer; ağın dışında kalan bir istemci
için çözecek bir şeyi yoktur. Bu üç iş ya ağın içine taşınacak ya da genel uç açık kalacaktır.

Faturanın kendisi ayrı bir kalemdir ve tek seferlik değildir. **Özel uç nokta hizmet başına ve ağ
başına ayrı gerekir:** altı destekli hizmet çarpı üç ağ, on sekiz kurulum ve ayda 270 kurgu birim.
B'ye göre on iki yeni özel uç ve 180 birim/ay eklenmiş oluyor — dokuz meşru erişimi kurtarmanın
bedeli budur. On sekiz kurulumun yalnız on ikisi bir meşru erişim tarafından kullanılıyor; kalan
altısı boştadır ve ayda 78 birim yiyor. Yalnız gerekli on ikisi kurulsaydı fatura 192 birim
olurdu. Üst sınır on sekizdir ve on ikisi doludur; her yeni hizmet ya da yeni ağ bu çarpımı
büyütür, çünkü tek bir özel uç birden çok hizmete hizmet etmez.

Bir kalem hiçbir senaryoda kapanmıyor. Bildirim hizmeti özel uç noktayı desteklemez; ona giden
iki erişim üç senaryoda da genel uçtan geçer. Kiralanan katmanın sınırı burada görünür hâle
geliyor: yalıtımı ne kadar ileri götürebileceğine sağlayıcının hizmet başına verdiği yetenek
karar veriyor ve bu kalem müzakere edilemez.

#### Özet

- Özel uç noktaların kurulu olması trafiğin oradan geçtiği anlamına gelmiyor: A senaryosunda
  yirmi beş erişimin on dördü genel internetten geçiyor ve üçü zaten kırık.
- Yol ile ad çözümlemesi ayrı ölçülür. Sınama ağında iki yol açıktır ama ad bölgesi bağlı olmadığı
  için üç erişim genel uçtan gider; ortak ağda ad özele çözülür ama eşleme olmadığı için yol yoktur.
- Genel uç kapatılınca yirmi beş erişimin on ikisi sıfır yola düşüyor; kırılan meşru erişim üçten
  on ikiye çıkıyor (sınama 3, ortak 3, dışarıdan 6) ve meşru olmayan üç erişim kesiliyor.
- Eksikleri kapatmak kırılanı on ikiden üçe indiriyor; bedeli on iki yeni özel uç ve ayda 180
  kurgu birimdir. Kalan üç erişim ağın dışındadır ve özel uç noktayla çözülemez.
- Özel uç nokta hizmet başına ve ağ başına ayrı gerekir: altı hizmet çarpı üç ağ, on sekizlik üst
  sınırın on ikisi kullanılıyor, altısı boşta ayda 78 birim yiyor.
- Bir hizmet özel uç noktayı desteklemiyor; ona giden iki erişim her senaryoda genel uçtan geçer
  ve bu sınıra kiracının verebileceği bir karar yoktur.

#### Sonraki Adım

Genel uç kapatıldı, yollar sayıldı ve dışarıda kalan üç erişim adıyla yazıldı. Ama kapanan yol
yalnız beklenen istemcileri değil, beklenmeyenleri de dışarıda bırakmayı amaçlıyordu; kesilen üç
meşru olmayan erişim bunu gösterdi. Sorun şu ki o üçü, çizelgede yazılı oldukları için sayılabildi.
Çizelgede olmayan, özel ağın içinden gelen ve geçerli kimlik bilgisi taşıyan bir etkinlik hiçbir
tabloda görünmedi. Sonraki ders anormal etkinliği ölçer: bilinen bir olay kümesinde tespit
kurallarının kaçını yakaladığını, kaçını kaçırdığını ve kaç yanlış alarm ürettiğini sayar.

### Tehdit Tespiti

Source: https://academia.sh/tr/kurslar/bulut-yonetisimi/tehdit-tespiti

Anormal etkinlik uyarılarının bilinen olay kümesinde ölçülmesi: 30 olayda 9 tespit kuralının 11 zararlının 9'unu yakalaması, 13 yanlış alarm üretmesi, 8 olayın yalnız tek bir sinyal kaynağıyla yakalanması, üç kaynağın ayda 612 kurgu birim tutması ve yanlış alarm eşiği aşılınca iki kural kapanınca yakalananın 7'ye inmesi.

Önceki ders genel ucu kapattı ve çizelgede yazılı üç meşru olmayan erişimi kesti. O üçü
kesilebildi, çünkü çizelgede vardılar. Özel ağın içinden gelen, geçerli kimlik bilgisi taşıyan ve
izin verilmiş bir işlemi yapan bir etkinlik hiçbir erişim tablosunda görünmez; erişim denetimi onu
meşru sayar, çünkü tanımı gereği meşrudur. **Tehdit tespiti** (threat detection) bu boşluğu
hedefler: yetki kontrolünün geçirdiği etkinliğin **olağandışı** olup olmadığını sorar.

Sorunun biçimi bu yüzden başkadır. Erişim kararı ikili bir yüklemdir ve doğru yanıtı tanımlıdır;
tespit ise bir tahmindir ve üç sayıyla ölçülür: yakalanan, kaçan, yanlış alarm. Bu ders bilinen bir
olay kümesi üzerinde tespit kurallarını koşturup üç sayıyı çıkarır, sonra iki bedeli sayar — sinyal
toplamanın ücreti ve yanlış alarmın ekipte ürettiği davranış.

#### Olay Kümesi, Sinyal Kaynakları ve Kurallar

Örnek kursun kurgu **bölgesel ölçüm ağı**dır. **BG37 — bilinen olay kümesi:** otuz olay, on biri
zararlı etiketli. Zararsız on dokuzu bilerek **zor benzerler** seçilmiştir; her biri bir zararlı
olayın bir yüzeyini paylaşır, dolayısıyla yanlış alarm oranı kolay bir kümedekinden yüksek
olacaktır. **BG38 — üç sinyal kaynağı:** denetim kaydı (işlem, işlem sayısı, saat), ağ akışı
(dışarı çıkan hacim, daha önce görülmemiş hedef, olağandışı port) ve kimlik davranışı (yeni konum,
başarısız deneme, ilk kez görülen özne). **BG39 — dokuz tespit kuralı:** her kural **tek bir
kaynağa** bakar, kaynak başına üç kural. **BG40 — toplama ücreti:** kaynak başına günlük hacim ve
GB başına birim (kurgu birim). **BG41 — yanlış alarm eşiği:** üç ve üzeri yanlış alarm üreten kural
kapatılır. **BG42 — toplama sınırı:** günde 60 GB (kurgu birim).

Aşağıdaki dosya kümeyi, kuralları ve iki bedeli kurar. Süreç içi bir **modeldir**; gerçek olay,
sinyal akışı ya da ücret yoktur.

```js
// tespit/kural.mjs — bilinen olay kumesinde tespit kurallarinin kosturulmasi. Surec ici model:
// bolgesel olcum agi (kurgu); gercek olay, sinyal akisi ya da ucret yoktur.

const satir = (s) => s.trim().split("\n").map((l) => l.trim().split("|"));
const yaz = (g, ...s) => console.log(s.map((v, i) =>
  (g[i] < 0 ? String(v).padEnd(-g[i]) : String(v).padStart(g[i]))).join(""));

// Olay: ad|zararli|D islem|D sayi|D saat|A cikis MB|A yeni hedef|A olagandisi port|
//       K yeni konum|K basarisiz deneme|K yeni ozne
const OLAY = satir(`
  toplu-arsiv-silme|1|sil|40|3|20|0|0|0|0|0
  politika-genisletme|1|politika-degistir|2|4|5|0|0|1|0|0
  gece-rol-zinciri|1|rol-ustlen|9|2|10|0|0|1|2|0
  depo-disari-kopya|1|oku|60|14|900|1|0|0|0|0
  yeni-hedefe-sizinti|1|oku|12|11|120|1|0|0|0|0
  anahtar-cikarma|1|anahtar-olustur|3|1|8|0|0|1|0|1
  kaba-kuvvet-girisi|1|oku|4|22|3|0|0|1|18|0
  sessiz-yan-kanal|1|oku|6|13|40|0|1|0|0|0
  ortak-hesap-devri|1|rol-ustlen|2|10|15|0|0|1|1|1
  gunluk-kapatma|1|politika-degistir|1|13|4|0|0|0|0|0
  yavas-sizdirma|1|oku|9|15|45|0|0|0|0|0
  gece-yedek-donusu|0|sil|30|3|400|0|0|0|0|0
  toplu-temizlik|0|sil|25|11|10|0|0|0|0|0
  surum-yayimi|0|politika-degistir|1|10|6|0|0|0|0|0
  olcum-alimi|0|yaz|80|9|650|0|0|0|0|0
  gece-rapor-cekimi|0|oku|20|4|300|1|0|0|0|0
  yeni-ekip-uyesi|0|oku|5|9|12|0|0|1|1|1
  seyahatten-giris|0|oku|7|8|9|0|0|1|2|0
  ortak-agdan-rapor|0|oku|11|16|80|1|0|0|0|0
  kenar-yukleme|0|yaz|14|20|140|1|0|0|0|0
  sinama-kosumu|0|rol-ustlen|6|13|20|0|0|0|0|0
  arac-guncellemesi|0|yaz|3|2|18|0|1|0|0|0
  parola-unutma|0|oku|2|9|2|0|0|0|11|0
  bakim-penceresi|0|sil|22|1|30|0|0|0|0|0
  yedek-dogrulama|0|oku|18|5|520|0|0|0|0|0
  kurulum-isi|0|anahtar-olustur|2|14|7|0|0|0|0|1
  katalog-yenileme|0|oku|15|10|60|0|0|0|0|0
  sinama-verisi-silme|0|sil|8|14|5|0|0|0|0|0
  gunluk-arsivleme|0|yaz|19|12|210|0|0|0|0|0
  plan-isi|0|oku|10|7|25|0|0|0|0|0`)
  .map(([ad, z, di, ds, dh, ac, ay, ap, kk, kb, ko]) => ({ ad, zararli: z === "1",
    dIslem: di, dSayi: +ds, dSaat: +dh, aCikis: +ac, aYeniHedef: +ay, aPort: +ap,
    kKonum: +kk, kBasarisiz: +kb, kOzne: +ko }));

// Tespit kurali: kimlik|sinyal kaynagi|yuklem. Her kural tek bir kaynaga bakar.
const KURAL = {
  T1: ["denetim kaydi", (o) => o.dIslem === "politika-degistir" && o.dSaat < 6],
  T2: ["denetim kaydi", (o) => o.dIslem === "sil" && o.dSayi >= 20],
  T3: ["denetim kaydi", (o) => o.dIslem === "rol-ustlen" && o.dSayi >= 5],
  T4: ["ag akisi", (o) => o.aCikis >= 500],
  T5: ["ag akisi", (o) => o.aYeniHedef === 1 && o.aCikis >= 50],
  T6: ["ag akisi", (o) => o.aPort === 1],
  T7: ["kimlik davranisi", (o) => o.kKonum === 1 && o.kBasarisiz >= 1],
  T8: ["kimlik davranisi", (o) => o.kBasarisiz >= 10],
  T9: ["kimlik davranisi", (o) => o.kOzne === 1 && o.kKonum === 1],
};
const KAYNAK = ["denetim kaydi", "ag akisi", "kimlik davranisi"];
const KURALLAR = Object.keys(KURAL);

const alarm = (kurallar) => OLAY.map((o) => ({ o,
  kural: kurallar.filter((t) => KURAL[t][1](o)) }));

const ozet = (kurallar) => {
  const a = alarm(kurallar);
  const zararli = a.filter((x) => x.o.zararli);
  return {
    yakalanan: zararli.filter((x) => x.kural.length > 0).length,
    kacan: zararli.filter((x) => x.kural.length === 0).length,
    yanlis: a.filter((x) => !x.o.zararli && x.kural.length > 0).length,
    sessiz: a.filter((x) => !x.o.zararli && x.kural.length === 0).length,
  };
};

const zararliSayi = OLAY.filter((o) => o.zararli).length;
console.log(`${OLAY.length} bilinen olay (${zararliSayi} zararli etiketli), ` +
  `${KURALLAR.length} tespit kurali, ${KAYNAK.length} sinyal kaynagi`);

// Kural basina
const K = [-6, -18, 9, 11, 14];
console.log();
yaz(K, "kural", "sinyal kaynagi", "alarm", "yakalanan", "yanlis alarm");
for (const t of KURALLAR) {
  const a = alarm([t]).filter((x) => x.kural.length > 0);
  const y = a.filter((x) => x.o.zararli).length;
  yaz(K, t, KURAL[t][0], a.length, y, a.length - y);
}
const T = ozet(KURALLAR);
yaz(K, "toplam", "", T.yakalanan + T.yanlis, `${T.yakalanan}/${zararliSayi}`, T.yanlis);

// Sinyal kaynagi basina: kaynak tek basina ve kaynak cikarilinca
const S = [-18, 13, 14, 14, 18];
console.log();
yaz(S, "sinyal kaynagi", "tek basina", "yanlis alarm", "cikarilinca", "yalniz bu kaynak");
for (const s of KAYNAK) {
  const kendi = KURALLAR.filter((t) => KURAL[t][0] === s);
  const digeri = KURALLAR.filter((t) => KURAL[t][0] !== s);
  const tek = ozet(kendi), yok = ozet(digeri);
  yaz(S, s, `${tek.yakalanan}/${zararliSayi}`, tek.yanlis, `${yok.yakalanan}/${zararliSayi}`,
    T.yakalanan - yok.yakalanan);
}

// Yalniz tek bir kaynakla yakalanan olaylar adiyla yazilir
console.log();
for (const x of alarm(KURALLAR).filter((x) => x.o.zararli && x.kural.length > 0)) {
  const kaynaklar = [...new Set(x.kural.map((t) => KURAL[t][0]))];
  if (kaynaklar.length === 1) console.log(`yalniz "${kaynaklar[0]}" ile: ${x.o.ad}`);
}
for (const x of alarm(KURALLAR).filter((x) => x.o.zararli && x.kural.length === 0))
  console.log(`hicbir kaynak yakalamiyor: ${x.o.ad}`);

// Toplama ucreti (kurgu birim): kaynak|gunluk GB|GB basina birim
const UCRET = Object.fromEntries(satir(`
  denetim kaydi|12|0.5
  ag akisi|40|0.3
  kimlik davranisi|3|0.8`).map(([s, gb, b]) => [s, { gb: +gb, birim: +b }]));
const U = [-18, 10, 12, 13, 18];
console.log();
yaz(U, "sinyal kaynagi", "GB/gun", "birim/GB", "birim/ay", "yalniz-bu basina");
let toplamAy = 0, toplamGb = 0;
for (const s of KAYNAK) {
  const ay = UCRET[s].gb * UCRET[s].birim * 30;
  const digeri = KURALLAR.filter((t) => KURAL[t][0] !== s);
  const yalniz = T.yakalanan - ozet(digeri).yakalanan;
  toplamAy += ay; toplamGb += UCRET[s].gb;
  yaz(U, s, UCRET[s].gb, UCRET[s].birim.toFixed(1), ay.toFixed(0),
    yalniz ? (ay / yalniz).toFixed(0) : "-");
}
yaz(U, "toplam", toplamGb, "", toplamAy.toFixed(0), "");

// Yanlis alarmin urettigi davranis: esigi asan kural kapatiliyor (M20/K04 ile ayni olcu)
const ESIK = 3;
const kapali = KURALLAR.filter((t) => {
  const a = alarm([t]).filter((x) => x.kural.length > 0);
  return a.length - a.filter((x) => x.o.zararli).length >= ESIK;
});
const A = ozet(KURALLAR.filter((t) => !kapali.includes(t)));
console.log(`\nyanlis alarm esigi ${ESIK}: kapatilan kural ${kapali.join(", ")} ` +
  `(${kapali.length}/${KURALLAR.length}); kapatildiktan sonra yakalanan ` +
  `${T.yakalanan} -> ${A.yakalanan}, kacan ${T.kacan} -> ${A.kacan}, ` +
  `yanlis alarm ${T.yanlis} -> ${A.yanlis}`);
const acik = KURALLAR.filter((t) => !kapali.includes(t));
const yeniKacan = alarm(KURALLAR).filter((x) => x.o.zararli && x.kural.length > 0
  && !x.kural.some((t) => acik.includes(t))).map((x) => x.o.ad);
console.log(`kapatma sonrasi kacana eklenen: ${yeniKacan.join(", ")}; ` +
  `kapatilan kurallarin baktigi kaynaklarin ucreti (${[...new Set(kapali.map((t) =>
    KURAL[t][0]))].join(", ")}) odenmeye devam ediyor`);

// Sinir ve kalan (kurgu): gunluk toplama siniri
const SINIR = 60;
console.log(`toplama siniri ${SINIR} GB/gun; kullanilan ${toplamGb}, kalan ${SINIR - toplamGb} -> ` +
  `dorduncu bir kaynak icin ${SINIR - toplamGb} GB/gun yer var, ag akisi ikiye katlansa sinir asilir`);
```

```
30 bilinen olay (11 zararli etiketli), 9 tespit kurali, 3 sinyal kaynagi

kural sinyal kaynagi        alarm  yakalanan  yanlis alarm
T1    denetim kaydi             1          1             0
T2    denetim kaydi             4          1             3
T3    denetim kaydi             2          1             1
T4    ag akisi                  3          1             2
T5    ag akisi                  5          2             3
T6    ag akisi                  2          1             1
T7    kimlik davranisi          5          3             2
T8    kimlik davranisi          2          1             1
T9    kimlik davranisi          3          2             1
toplam                         22       9/11            13

sinyal kaynagi       tek basina  yanlis alarm   cikarilinca  yalniz bu kaynak
denetim kaydi              3/11             4          7/11                 2
ag akisi                   3/11             6          6/11                 3
kimlik davranisi           4/11             3          6/11                 3

yalniz "denetim kaydi" ile: toplu-arsiv-silme
yalniz "denetim kaydi" ile: politika-genisletme
yalniz "ag akisi" ile: depo-disari-kopya
yalniz "ag akisi" ile: yeni-hedefe-sizinti
yalniz "kimlik davranisi" ile: anahtar-cikarma
yalniz "kimlik davranisi" ile: kaba-kuvvet-girisi
yalniz "ag akisi" ile: sessiz-yan-kanal
yalniz "kimlik davranisi" ile: ortak-hesap-devri
hicbir kaynak yakalamiyor: gunluk-kapatma
hicbir kaynak yakalamiyor: yavas-sizdirma

sinyal kaynagi        GB/gun    birim/GB     birim/ay  yalniz-bu basina
denetim kaydi             12         0.5          180                90
ag akisi                  40         0.3          360               120
kimlik davranisi           3         0.8           72                24
toplam                    55                      612                  

yanlis alarm esigi 3: kapatilan kural T2, T5 (2/9); kapatildiktan sonra yakalanan 9 -> 7, kacan 2 -> 4, yanlis alarm 13 -> 7
kapatma sonrasi kacana eklenen: toplu-arsiv-silme, yeni-hedefe-sizinti; kapatilan kurallarin baktigi kaynaklarin ucreti (denetim kaydi, ag akisi) odenmeye devam ediyor
toplama siniri 60 GB/gun; kullanilan 55, kalan 5 -> dorduncu bir kaynak icin 5 GB/gun yer var, ag akisi ikiye katlansa sinir asilir
```

Sayılar **ölçüm** sınıfındadır; girdileri yukarıdaki varsayımlardır. Dokuz kural otuz olay üzerinde
yirmi iki alarm üretiyor: on bir zararlının dokuzu yakalanıyor, ikisi kaçıyor, on üç zararsız olay
işaretleniyor. Yanlış alarm sayısının yakalanandan büyük olması bu kümenin seçiminden gelir —
zararsız olaylar zararlıların yüzeylerini paylaşacak biçimde seçildi — ama oranın yönü gerçektir:
tespit kuralları meşru işi işaretlemeden çalışmaz.

Kural başına bakıldığında dağılım eşit değil. T1 tek bir alarm üretiyor ve hiç yanlışı yok; dar
yazılmış bir kuraldır ve karşılığında yalnız bir olay görüyor. T7 beş alarmın üçünü doğru veriyor.
T2 ve T5 ise üçer yanlış alarmla en gürültülü ikilidir ve bu iki sayı dersin son bölümünde geri
gelecektir.

#### Sinyal Kaynakları Ayrı Ayrı

Asıl ayrım kaynak tablosundadır ve iki farklı soruyu ayırır. Birinci sütun kaynağın **tek başına**
ne yakaladığını söyler: denetim kaydı üç, ağ akışı üç, kimlik davranışı dört. Üçünün toplamı ondur
ama birlikte yakalanan dokuzdur; örtüşme vardır. Üçüncü sütun daha yararlıdır — kaynak
**çıkarıldığında** ne kalıyor. Denetim kaydı çıkarılırsa yakalanan dokuzdan yediye, ağ akışı ya da
kimlik davranışı çıkarılırsa altıya iner.

Son sütun kararı taşıyan sayıdır: **yalnız bu kaynakla yakalanan olay.** Denetim kaydında iki, ağ
akışında üç, kimlik davranışında üç. Sekiz zararlı olay tek bir kaynağın omzunda duruyor ve
adlarıyla yazılıyor. Toplu arşiv silme ile politika genişletmesini yalnız denetim kaydı görüyor;
ikisi de ağda iz bırakmıyor, çünkü dışarı veri çıkmıyor. Depoya yapılan dışarı kopyayı, yeni bir
hedefe akan sızıntıyı ve sessiz yan kanalı yalnız ağ akışı görüyor; üçü de yetkili bir öznenin
izin verilmiş okuma işlemidir ve denetim kaydında olağan görünür. Anahtar çıkarmayı, kaba kuvvet
girişini ve ortak hesap devrini yalnız kimlik davranışı görüyor. Dokuz yakalanandan yalnız biri —
gece rol zinciri — iki kaynakta birden görünüyor.

Kaçan ikisi de tabloların altında adıyla duruyor ve neden kaçtıkları birbirine benziyor. Günlük
kapatma, mesai saatinde yapılmış tek bir politika değişikliğidir; T1 bunu yakalayabilirdi ama
yüklemi saati de arıyor, gece dışında ateşlemiyor. Yavaş sızdırma 45 MB'lık bir okumadır; T4'ün
eşiğinin çok altında, T5 için hedef yeni değil. İkisi de kural kümesinin **eşiğinin** öbür
yanındadır, kapsamının değil — yani gevşetilerek yakalanabilirler. T1'den saat koşulunu kaldırmak
günlük kapatmayı yakalar ve sürüm yayımını yanlış alarma çevirir; T4'ün eşiğini 40 MB'a indirmek
yavaş sızdırmayı yakalar ve o kuralın yanlış alarmını ikiden sekize çıkarır. Eşiği gevşetmek kaçanı yakalanana
taşır, ama taşıdığı her olay için yanlış alarm sütununa birden fazla kalem yazar; bir sonraki
bölüm bu kalemlerin ne yaptığını sayacaktır.

Buradan çıkan cümle şudur: **üç kaynak birbirinin yedeği değildir.** Bir kaynağı ücreti yüzünden
kesmek, o kaynağın tek başına gördüğü olayları doğrudan kaçana çevirir. Hangi kaynağın kesilebilir
olduğu, ücretine değil bu sütuna bakılarak söylenir.

#### Tespitin İki Bedeli

Birinci bedel ücret tablosudur. Üç kaynak günde 55 GB üretiyor ve ayda 612 kurgu birim tutuyor.
Kalemler eşit değil: ağ akışı hacmin dörtte üçünü ve ücretin 360 birimini alıyor, kimlik davranışı
üç GB ile 72 birim. Son sütun ikisini karşılaştırılabilir kılar — yalnız o kaynakla yakalanan olay
başına düşen aylık ücret: kimlik davranışı 24 birim, denetim kaydı 90, ağ akışı 120. Ağ akışı en
pahalı kaynaktır ve üç olayı tek başına gören tek şeydir; ikisi aynı anda doğrudur ve karar bu iki
sayının arasında verilir.

İkinci bedel ücretle ödenmez. Yanlış alarm eşiği üçe konduğunda T2 ve T5 kapanıyor; ikisi de üçer
yanlış alarm üretmişti. Kapatmadan sonra yakalanan dokuzdan yediye, kaçan ikiden dörde gidiyor,
yanlış alarm on üçten yediye iniyor. Kaçana eklenen iki olay adıyla bellidir: toplu arşiv silme ve
yeni hedefe sızıntı. İkisi de **yalnız kapatılan kuralın gördüğü** olaylardı. Bu ölçü M20/K04'ün
uygunluk işlevlerinde kullandığı ölçüyle aynı biçimdedir — yakalamayı artıran her ayar yanlış
alarmı da artırır ve yanlış alarmın ürettiği davranış kuralın kapatılmasıdır — ilişki bir cümleyle
söylenip geçilir.

Bu ikinci bedelin altı çizilmeli: kural kapandığında toplama durmaz. Denetim kaydı ve ağ akışı
ücreti aynen ödenmeye devam eder; kesilen şey ücret değil, ücretin satın aldığı görüştür. Kapatma
kararını veren de alarmı okuyan ekiptir, dolayısıyla tespitin gerçek kapsamı yazılı kural kümesi
değil, **açık bırakılmış kural kümesidir** ve ikisi arasındaki fark hiçbir faturada görünmez.

Sınır tarafında kalan az: günlük toplama sınırı 60 GB, kullanılan 55, kalan 5. Dördüncü bir sinyal
kaynağı için beş GB'lık yer vardır ve ağ akışı ikiye katlanırsa sınır aşılır. Kaynak eklemek de,
var olan kaynağın hacminin büyümesi de aynı sınıra çarpar.

#### Özet

- Dokuz kural otuz olayda yirmi iki alarm üretiyor: on bir zararlının dokuzu yakalanıyor, ikisi
  hiçbir kaynakta iz bırakmıyor, on üç zararsız olay işaretleniyor.
- Yakalanan dokuz olayın sekizi **yalnız tek bir sinyal kaynağıyla** yakalanıyor; yalnızca biri iki
  kaynakta birden görünüyor. Üç kaynak birbirinin yedeği değildir.
- Bir kaynağı çıkarmanın bedeli tablodadır: denetim kaydı çıkarılırsa yakalanan dokuzdan yediye,
  ağ akışı ya da kimlik davranışı çıkarılırsa altıya iner.
- Toplama ücreti ayda 612 kurgu birimdir; yalnız o kaynakla yakalanan olay başına kimlik davranışı
  24, denetim kaydı 90, ağ akışı 120 birim eder.
- Yanlış alarm eşiği üç olduğunda iki kural kapanıyor: yakalanan 9'dan 7'ye, kaçan 2'den 4'e
  gidiyor, yanlış alarm 13'ten 7'ye iniyor; kapanan kuralların kaynaklarının ücreti ödenmeye devam
  ediyor.
- Toplama sınırı 60 GB/gün, kullanılan 55, kalan 5; dördüncü bir kaynak ya da ağ akışının büyümesi
  aynı sınıra çarpar.

#### Sonraki Adım

Tespit kuralları koştu, yakalanan ve kaçan sayıldı, iki kuralın kapatıldığı da yazıldı. Bu
sayıların hepsi içeriye bakan sayılardır: ekibin kendi ölçüsü, kendi eşiği, kendi kararı. Dışarıdan
biri "erişimin kısıtlandığını ve olağandışı etkinliğin izlendiğini gösterin" dediğinde ise
istenen şey ölçü değil **kanıttır** ve kanıtın bir kısmı kiracının elinde bile değildir. Sonraki
ders uyumluluk gereksinimlerini tür olarak alır ve her gereksinim için kanıtın kimden geldiğini —
sağlayıcının belgesi ile kendi kaydın — ayırır, hangi gereksinimde kanıtın boşlukta kaldığını
sayar.

### Uyumluluk Gereksinimlerinin Buluta Yansıması

Source: https://academia.sh/tr/kurslar/bulut-yonetisimi/uyumluluk-cerceveleri

Uyumluluk gereksinimlerinin kiralanan katmanda kanıta çevrilmesi: 12 gereksinim türü ve 26 kanıt kaleminde 7 kalemin sağlayıcının belgesinden, 16'sının kendi kaydından gelmesi, 3 gereksinimde kanıtın boşlukta kalması, kiracının katmanı dışında geçen 14 kalemin 7'sinin kanıtının sağlayıcıdan gelmemesi ve kanıt üretmenin yılda 139 kurgu birim ile 160 kişi-saate mal olması.

Önceki ders tespit kurallarını koşturdu ve üç sayı üretti: yakalanan, kaçan, yanlış alarm. Üçü de
ekibin kendi ölçüsüydü — eşiği de, kapatma kararını da aynı taraf veriyordu. Dışarıdan biri
"erişimin kısıtlandığını ve olağandışı etkinliğin izlendiğini gösterin" dediğinde istenen şey bu
sayılar değildir. İstenen **kanıttır**: bir yükümlülüğün karşılandığını, o yükümlülüğü koymayan
birine gösterilebilir biçimde ortaya koyan kayıt ya da belge.

Dış kısıtların koşturulabilir denetime çevrilmesi M20/K04'te ölçüldü; orada gevşetmenin yerini
kanıt alıyordu ve kanıtın tamamı mimarinin kendi çıktısıydı. Kiralanan katmanda bu bölünür.
Gereksinimlerin bir kısmı sağlayıcının makinesinde, tesisinde ya da personelinde karşılanır;
kiracının orada üretebileceği bir kayıt yoktur ve kanıt olarak **sağlayıcının belgesi** geçer. Bu
dersin ölçüsü o ayrımdır. Gereksinimler burada **tür olarak** anılır — veri yerleşimi kısıtı,
saklama zorunluluğu, silme hakkı, erişim kaydı yükümlülüğü, ayrıcalıklı erişim kanıtı — ve hiçbir
düzenleme, standart, sertifika ya da çerçeve adı yazılmaz.

#### Gereksinimler ve Kanıt Kalemleri

Örnek kursun kurgu **bölgesel ölçüm ağı**dır. **BG43 — gereksinim kataloğu:** on iki gereksinim
türü. **BG44 — kanıt kalemi çizelgesi:** yirmi altı kalem; her kalem hangi katmanda geçtiğini
(sağlayıcı, paylaşılan, kiracı), kanıtının kim tarafından üretildiğini (sağlayıcının belgesi,
kendi kaydın, hiçbiri), tazeliğini gün olarak, günlük satır sayısını ve saklama süresini taşır.
**BG45 — gereksinim-kalem eşlemesi:** otuz iki bağ; bir kalem birden çok gereksinime hizmet
edebilir. **BG46 — kayıt birimleri:** satır başına 200 bayt, GB başına aylık 1,5 kurgu birim.
**BG47 — rapor üretimi:** her gereksinim çeyrekte bir derlenir, gereksinim başına 2 kişi-saat sabit
ve kalem başına 0,5 kişi-saat. **BG48 — kanıt deposu üst sınırı:** 12 GB (kurgu birim).

Aşağıdaki dosya çizelgeleri kurar ve kanıtı üreticisine göre ayırır. Süreç içi bir **modeldir**;
gerçek belge, kayıt ya da ücret yoktur.

```js
// uyum/kanit.mjs — uyumluluk gereksinimlerinin kiralanan katmanda kanita cevrilmesi.
// Surec ici model: bolgesel olcum agi (kurgu); gercek belge, kayit ya da ucret yoktur.

const satir = (s) => s.trim().split("\n").map((l) => l.trim().split("|"));
const yaz = (g, ...s) => console.log(s.map((v, i) =>
  (g[i] < 0 ? String(v).padEnd(-g[i]) : String(v).padStart(g[i]))).join(""));

// Kanit kalemi: ad|katman|uretici (saglayici|kendi|yok)|tazelik (gun)|gunluk satir|saklama (gun)
const KALEM = Object.fromEntries(satir(`
  kaynak-envanteri|kiraci|kendi|1|400|1095
  bolge-etiketi|kiraci|kendi|1|400|1095
  veri-akis-haritasi|kiraci|yok|0|0|0
  tesis-bolge-beyani|saglayici|saglayici|365|0|0
  saklama-politikasi-kaydi|kiraci|kendi|1|150|1095
  yasam-dongusu-kosum-kaydi|kiraci|kendi|1|900|1095
  yedek-kopya-envanteri|paylasilan|kendi|7|60|1095
  silme-istegi-kaydi|kiraci|kendi|1|30|2555
  silme-yayin-kaydi|kiraci|kendi|1|120|2555
  yedekten-silme-onayi|paylasilan|yok|0|0|0
  denetim-gunlugu|paylasilan|kendi|1|9000|2555
  veri-duzlemi-erisim-kaydi|saglayici|kendi|1|4000|2555
  saglayici-personel-erisim-beyani|saglayici|saglayici|365|0|0
  ayricalikli-oturum-kaydi|kiraci|kendi|1|200|2555
  rol-ustlenme-kaydi|kiraci|kendi|1|600|2555
  sifreleme-yapilandirma-taramasi|paylasilan|kendi|1|300|1095
  anahtar-sahipligi-beyani|saglayici|saglayici|365|0|0
  aktarim-uc-taramasi|kiraci|kendi|1|250|1095
  istemci-dogrulama-kaydi|kiraci|yok|0|0|0
  anahtar-dondurme-kaydi|paylasilan|kendi|1|20|2555
  anahtar-materyali-imha-beyani|saglayici|saglayici|365|0|0
  tesis-erisim-denetimi-beyani|saglayici|saglayici|365|0|0
  donanim-imha-beyani|saglayici|saglayici|365|0|0
  geri-yukleme-tatbikat-kaydi|kiraci|kendi|90|10|1095
  olay-zaman-cizelgesi|paylasilan|kendi|1|80|2555
  saglayici-olay-bildirimi|saglayici|saglayici|30|0|0`)
  .map(([ad, katman, uretici, taze, satirSay, sakla]) => [ad,
    { katman, uretici, taze: +taze, satirSay: +satirSay, sakla: +sakla }]));

// Gereksinim turu -> kanit kalemleri. Duzenleme, standart ya da cerceve adi yoktur.
const GEREKSINIM = satir(`
  G01 veri yerlesimi kisiti|kaynak-envanteri bolge-etiketi veri-akis-haritasi tesis-bolge-beyani
  G02 saklama alt siniri|saklama-politikasi-kaydi yasam-dongusu-kosum-kaydi yedek-kopya-envanteri
  G03 saklama ust siniri|saklama-politikasi-kaydi yasam-dongusu-kosum-kaydi
  G04 silme hakki|silme-istegi-kaydi silme-yayin-kaydi yedekten-silme-onayi
  G05 erisim kaydi yukumlulugu|denetim-gunlugu veri-duzlemi-erisim-kaydi
  G06 ayricalikli erisim kaniti|ayricalikli-oturum-kaydi rol-ustlenme-kaydi saglayici-personel-erisim-beyani denetim-gunlugu
  G07 beklemede sifreleme kaniti|sifreleme-yapilandirma-taramasi anahtar-sahipligi-beyani
  G08 aktarimda sifreleme kaniti|aktarim-uc-taramasi istemci-dogrulama-kaydi
  G09 anahtar dondurme kaniti|anahtar-dondurme-kaydi anahtar-sahipligi-beyani anahtar-materyali-imha-beyani
  G10 fiziksel erisim ve imha kaniti|tesis-erisim-denetimi-beyani donanim-imha-beyani
  G11 geri yuklenebilirlik kaniti|geri-yukleme-tatbikat-kaydi yedek-kopya-envanteri
  G12 olay bildirimi kaniti|olay-zaman-cizelgesi saglayici-olay-bildirimi denetim-gunlugu`)
  .map(([ad, k]) => ({ ad, kalem: k.split(" ") }));

const KATMAN = ["saglayici", "paylasilan", "kiraci"];
const URETICI = ["saglayici", "kendi", "yok"];

console.log(`${GEREKSINIM.length} gereksinim turu, ${Object.keys(KALEM).length} kanit kalemi, ` +
  `${GEREKSINIM.reduce((t, g) => t + g.kalem.length, 0)} gereksinim-kalem bagi`);

// Gereksinim basina: kanit kimden geliyor, bosta kalan var mi, en eski kanit kac gunluk
const G = [-36, 8, 14, 8, 8, 15];
console.log();
yaz(G, "gereksinim turu", "kalem", "saglayicidan", "kendi", "bosta", "en eski (gun)");
const durum = {};
for (const g of GEREKSINIM) {
  const say = (u) => g.kalem.filter((k) => KALEM[k].uretici === u).length;
  const uretilen = g.kalem.filter((k) => KALEM[k].uretici !== "yok");
  const taze = Math.max(...uretilen.map((k) => KALEM[k].taze));
  durum[g.ad] = { bosta: say("yok"), taze };
  yaz(G, g.ad, g.kalem.length, say("saglayici"), say("kendi"), say("yok"), taze);
}
const bosluklu = GEREKSINIM.filter((g) => durum[g.ad].bosta > 0);
console.log(`\nkaniti boslukta kalan gereksinim: ${bosluklu.length}/${GEREKSINIM.length} -> ` +
  bosluklu.map((g) => `${g.ad.split(" ")[0]} (${g.kalem.filter((k) =>
    KALEM[k].uretici === "yok").join(", ")})`).join("; "));

// Paylasilan sorumluluk siniri kanit tarafinda yeniden cizilir: katman x uretici
const C = [-14, 12, 10, 8, 9];
console.log();
yaz(C, "katman \\ uretici", "saglayici", "kendi", "yok", "toplam");
for (const kt of KATMAN) {
  const kume = Object.values(KALEM).filter((k) => k.katman === kt);
  yaz(C, kt, ...URETICI.map((u) => kume.filter((k) => k.uretici === u).length), kume.length);
}
yaz(C, "toplam", ...URETICI.map((u) =>
  Object.values(KALEM).filter((k) => k.uretici === u).length), Object.keys(KALEM).length);
const disKatman = Object.entries(KALEM).filter(([, k]) => k.katman !== "kiraci");
const disAmaKendi = disKatman.filter(([, k]) => k.uretici !== "saglayici");
console.log(`kiracinin katmani disinda gecen ${disKatman.length} kalemin ` +
  `${disAmaKendi.length} tanesinin kaniti saglayicidan gelmiyor: ` +
  `${disAmaKendi.map(([a]) => a).join(", ")}`);

// Kanit uretmenin surekli maliyeti (kurgu birim)
const SATIR_BAYT = 200, GB = 1e9, GB_BIRIM = 1.5;
const kendi = Object.entries(KALEM).filter(([, k]) => k.uretici === "kendi");
const hacim = kendi.reduce((t, [, k]) => t + (k.satirSay * k.sakla * SATIR_BAYT) / GB, 0);
const gunlukSatir = kendi.reduce((t, [, k]) => t + k.satirSay, 0);
console.log(`\nkendi kaydindan gelen ${kendi.length} kalem: gunde ` +
  `${gunlukSatir.toLocaleString("tr-TR")} satir; saklama suresi sonunda ` +
  `${hacim.toFixed(2)} GB, ayda ${(hacim * GB_BIRIM).toFixed(2)} birim, ` +
  `yilda ${(hacim * GB_BIRIM * 12).toFixed(0)} birim depolama`);

// Rapor uretimi: her gereksinim ceyrekte bir derlenir
const [CEYREK, SABIT, KALEM_SAAT] = [4, 2, 0.5];
const kisiSaat = GEREKSINIM.reduce((t, g) =>
  t + CEYREK * (SABIT + g.kalem.length * KALEM_SAAT), 0);
console.log(`rapor uretimi: ${GEREKSINIM.length} gereksinim x ${CEYREK} ceyrek x ` +
  `(${SABIT} + kalem x ${KALEM_SAAT}) = ${kisiSaat} kisi-saat/yil`);
const beyan = Object.values(KALEM).filter((k) => k.uretici === "saglayici");
console.log(`saglayicidan gelen ${beyan.length} belgenin tazeligi ` +
  `${Math.min(...beyan.map((k) => k.taze))}-${Math.max(...beyan.map((k) => k.taze))} gun; ` +
  `kendi kaydinin tazeligi 1-90 gun`);

// Sinir ve kalan (kurgu): kanit deposu ust siniri
const SINIR = 12;
console.log(`kanit deposu ust siniri ${SINIR} GB; kullanilan ${hacim.toFixed(2)}, kalan ` +
  `${(SINIR - hacim).toFixed(2)} -> denetim gunlugunun gunluk satiri ` +
  `${Math.floor(((SINIR - hacim) * GB) / (SATIR_BAYT * KALEM["denetim-gunlugu"].sakla))
    .toLocaleString("tr-TR")} satir daha buyuyebilir`);
```

```
12 gereksinim turu, 26 kanit kalemi, 32 gereksinim-kalem bagi

gereksinim turu                        kalem  saglayicidan   kendi   bosta  en eski (gun)
G01 veri yerlesimi kisiti                  4             1       2       1            365
G02 saklama alt siniri                     3             0       3       0              7
G03 saklama ust siniri                     2             0       2       0              1
G04 silme hakki                            3             0       2       1              1
G05 erisim kaydi yukumlulugu               2             0       2       0              1
G06 ayricalikli erisim kaniti              4             1       3       0            365
G07 beklemede sifreleme kaniti             2             1       1       0            365
G08 aktarimda sifreleme kaniti             2             0       1       1              1
G09 anahtar dondurme kaniti                3             2       1       0            365
G10 fiziksel erisim ve imha kaniti         2             2       0       0            365
G11 geri yuklenebilirlik kaniti            2             0       2       0             90
G12 olay bildirimi kaniti                  3             1       2       0             30

kaniti boslukta kalan gereksinim: 3/12 -> G01 (veri-akis-haritasi); G04 (yedekten-silme-onayi); G08 (istemci-dogrulama-kaydi)

katman \ uretici   saglayici     kendi     yok   toplam
saglayici                7         1       0        8
paylasilan               0         5       1        6
kiraci                   0        10       2       12
toplam                   7        16       3       26
kiracinin katmani disinda gecen 14 kalemin 7 tanesinin kaniti saglayicidan gelmiyor: yedek-kopya-envanteri, yedekten-silme-onayi, denetim-gunlugu, veri-duzlemi-erisim-kaydi, sifreleme-yapilandirma-taramasi, anahtar-dondurme-kaydi, olay-zaman-cizelgesi

kendi kaydindan gelen 16 kalem: gunde 16.520 satir; saklama suresi sonunda 7.72 GB, ayda 11.58 birim, yilda 139 birim depolama
rapor uretimi: 12 gereksinim x 4 ceyrek x (2 + kalem x 0.5) = 160 kisi-saat/yil
saglayicidan gelen 7 belgenin tazeligi 30-365 gun; kendi kaydinin tazeligi 1-90 gun
kanit deposu ust siniri 12 GB; kullanilan 7.72, kalan 4.28 -> denetim gunlugunun gunluk satiri 8.374 satir daha buyuyebilir
```

Sayılar **ölçüm** sınıfındadır; girdileri yukarıdaki varsayımlardır. On iki gereksinim yirmi altı
kanıt kalemine ve otuz iki bağa çözülüyor. Yirmi altı kalemin yedisi sağlayıcının belgesinden, on
altısı kendi kaydından geliyor, üçünün üreticisi yok. Kalem sayısı gereksinim sayısından fazladır
ve bağ sayısı kalem sayısından fazladır; tek bir kalem birden çok yükümlülüğe hizmet eder — denetim
günlüğü üç ayrı gereksinimde geçiyor, anahtar sahipliği beyanı ikisinde.

#### Kanıtın İki Üreticisi

Gereksinim tablosunun ilk okunacak yeri ikinci ve üçüncü sütunlardır. G10 tamamen sağlayıcının
tarafındadır: iki kaleminin ikisi de belgedir, kiracının orada üreteceği hiçbir kayıt yoktur. G03
ve G05 tamamen kiracının tarafındadır. Kalan dokuz gereksinim karışıktır ve kanıt dosyası iki
farklı türden parça içerir. Bu, uyum çalışmasının pratik biçimini belirler: bir gereksinimi
karşılamak tek bir sorumlunun işi değil, iki üreticiden gelen parçaların birleştirilmesidir.

Son sütun bu birleştirmenin zayıf halkasını gösteriyor. **Bir gereksinimin kanıtı, en eski
parçasının yaşı kadar tazedir.** G05 için tazelik bir gündür, çünkü her iki kalem de günlük tutulan
kayıtlardır. G01, G06, G07, G09 ve G10 için tazelik 365 gündür; bu beş gereksinimin her birinde
yılda bir yenilenen bir sağlayıcı belgesi vardır ve kiracının günlük tuttuğu kayıtlar dosyanın
yaşını düşürmez. Bir olay ile onu kapsayan belgenin yenilenmesi arasında bir yıla kadar boşluk
kalabilir; yenileme takvimini de sağlayıcı belirler, dolayısıyla bu bir devredilmiş karardır ve
kiracının hızlandıramayacağı bir kalemdir.

İki üreticinin ürettiği şey aynı türden değildir ve bu ayrım sayılardan sonra gelir. Kendi kaydın
sorgulanabilir: bir tarih aralığı verilir, bir özne süzülür, aynı kayıttan başka bir soruya yanıt
çıkarılır ve gerekirse geriye dönük yeniden derlenir. Sağlayıcının belgesi ise kapalı bir
çıktıdır — verilen biçimiyle kabul edilir, içine sorgu yazılamaz, kapsamı dışına çıkarılamaz ve
kapsamadığı bir kaynak için ikinci bir sürümü istenemez. On altı kalem birinci türden, yedisi
ikinci türdendir. Pratik sonucu şudur: bir denetçi tabloda olmayan bir soru sorduğunda kiracının
on altı kalemde yanıt üretme şansı vardır, yedi kalemde yoktur; o yedide verilecek yanıt belgede
yazılı olanla sınırlıdır.

Üç gereksinimde kanıt boşlukta kalıyor ve üçü de adıyla yazılıyor. G01'de veri akış haritası
eksiktir: hangi verinin hangi bölgeye aktığını gösteren bir kayıt yok, dolayısıyla envanterdeki
etiket ile tesis beyanı arasındaki bağ kurulamıyor. G04'te yedekten silme onayı eksiktir: silme
isteği kaydediliyor ve yayınlanıyor ama silmenin yedek kopyalarda gerçekleştiğini gösteren bir
kayıt üretilmiyor. G08'de istemci doğrulama kaydı eksiktir: uç taraması sunucu tarafını gösteriyor,
istemcinin doğrulamayı gerçekten yaptığına dair kanıt yok. Üçünün ortak yanı şudur: eksik olan bir
belge değil, hiç kurulmamış bir kayıt akışıdır. Kimse reddetmedi, kimse vermedi — kimse istemedi.

#### Sınır Kanıt Tarafında Yeniden Çizilir

Çapraz tablo dersin ana ölçüsüdür. Katman sütunları sorumluluğun nerede olduğunu, satırlar kanıtın
kimden geldiğini söylüyor ve ikisi çakışmıyor. Sağlayıcının katmanında geçen sekiz kalemin yedisi
belge ile karşılanıyor, biri karşılanmıyor: veri düzlemi erişim kaydı sağlayıcının içinde olup
biter ama kanıtını üreten, o kaydı açık tutan kiracıdır. Paylaşılan katmandaki altı kalemin
**hiçbiri** sağlayıcının belgesinden gelmiyor; beşi kiracının kaydından, biri hiç gelmiyor.

Toplam sayı bunu tek satıra indiriyor: kiracının katmanı dışında geçen on dört kalemin yedisinin
kanıtı sağlayıcıdan gelmiyor. Yani sorumluluk paylaşımı kanıt tarafına aynen geçmiyor; **kanıt
sınırı katman sınırının kiracı tarafına doğru kaymış durumdadır.** Yedek kopya envanteri, denetim
günlüğü, şifreleme yapılandırma taraması, anahtar döndürme kaydı ve olay zaman çizelgesi ortak
katmanda geçen işlerdir, ama gösterilmesi gerektiğinde gösterecek olan kiracıdır. Bu ayrım
sözleşmede değil, kanıt dosyasının kim tarafından derlendiğinde görünür — ve derleme yükü tam da
buradan doğar.

#### Kanıt Üretmenin Sürekli Maliyeti

Kanıt bir defa üretilip bitmez; sürekli bir kalemdir ve iki başlıkta sayılır. Kendi kaydından gelen
on altı kalem günde 16.520 satır üretiyor; kendi saklama süreleri sonunda 7,72 GB tutuyor, ayda
11,58 ve yılda 139 kurgu birim depolama ediyor. İkinci başlık daha ağırdır: on iki gereksinimin her
biri çeyrekte bir derleniyor ve yılda 160 kişi-saat tutuyor. İki kalemi yan yana koymak dersin
sonucudur — kanıtın sürekli maliyeti ağırlıklı olarak depolama değil, **derleme emeğidir** ve
gereksinim başına değil kalem başına büyür.

M20/K04'ün kapalı halkası burada da geçerlidir ve bir sözcük ekler: kanıt da bir veri sınıfıdır,
kendi saklama süresine ve kendi yerleşim kısıtına tabidir. Eklenen sözcük şudur: bu veri sınıfının
yarısını kiracı üretmez. Sağlayıcıdan gelen yedi belgenin tazeliği 30–365 gün arasındadır ve bu
aralık kiracının seçimi değildir; kendi kaydının tazeliği 1–90 gündür ve bu aralık kiracının
seçimidir. Kanıt dosyasının ne kadar taze olabileceğine iki taraf birden karar verir.

Sınır tarafında da kalan sayılıyor. Kanıt deposunun üst sınırı 12 GB, kullanılan 7,72, kalan 4,28.
Bu, denetim günlüğünün günlük satır sayısının 8.374 satır daha büyümesine yeter; ondan sonrası ya
saklama süresini kısaltmayı gerektirir — ki saklama süresi bir gereksinimin kendisidir — ya da
sınırı büyütmeyi, ki bu da faturaya yazılır.

#### Özet

- On iki gereksinim türü yirmi altı kanıt kalemine ve otuz iki bağa çözüldü; kalemlerin yedisi
  sağlayıcının belgesinden, on altısı kendi kaydından geliyor, üçünün üreticisi yok.
- Üç gereksinimde kanıt boşlukta kalıyor (veri akış haritası, yedekten silme onayı, istemci
  doğrulama kaydı); üçünde de eksik olan bir belge değil, hiç kurulmamış bir kayıt akışıdır.
- Bir gereksinimin kanıtı en eski parçası kadar tazedir: beş gereksinimde tazelik 365 gündür,
  çünkü içlerinde yılda bir yenilenen bir sağlayıcı belgesi vardır ve yenileme takvimi kiracının
  değildir.
- Paylaşılan sorumluluk sınırı kanıt tarafında aynı yerde durmuyor: kiracının katmanı dışında geçen
  on dört kalemin yedisinin kanıtı sağlayıcıdan gelmiyor, paylaşılan katmandaki altı kalemin
  hiçbiri belgeyle karşılanmıyor.
- Kanıt üretmenin sürekli maliyeti iki kalemdir: 16.520 satır/gün ve 7,72 GB ile yılda 139 kurgu
  birim depolama, artı yılda 160 kişi-saat rapor derleme. Ağır olan ikincisidir.
- Kanıt deposunun 12 GB'lık sınırının 7,72'si dolu; kalan 4,28 GB denetim günlüğüne günde 8.374
  satırlık büyüme yeri bırakıyor.

#### Sonraki Adım

Konu burada kapanıyor ve bıraktığı tablo tek bir cümleye sığar: kiralanan katmanda güvenlik, kimin
neyi yapabildiğini daraltmak, verinin okunduğunda ne göstereceğini değiştirmek ve ikisinin de
yapıldığını gösterebilmektir. Üçünün de sayısı çıkarıldı — daraltmanın kaç meşru işi durdurduğu,
yalıtımın kaç erişimi kırdığı, tespitin kaçını kaçırdığı ve kanıtın hangi gereksinimde boşlukta
kaldığı.

Çıkarılmayan tek şey bunların toplamıdır. Uyum denetimi bir kotayı, özel uç noktalar hizmet ve ağ
başına aylık bir kirayı, sinyal toplama GB başına bir ücreti, kanıt saklama bir depo sınırını
tüketiyor; her biri kendi bölümünde kurgu birimle yazıldı ama hiçbiri diğerinin yanına konmadı.
Erişim daraltıldı, veri şifrelendi ve kanıt üretildi — bunların hepsinin bir **faturası** var ve o
fatura bu konu boyunca hiç okunmadı. Sonraki konu faturayı kalem kalem açar: hangi kalemin neye
ait olduğu, hangi ekibe düştüğü ve hangi payın hiçbir ekibe atanamadığı.

## Maliyet ve Sınırlar

Faturanın okunması ve sınırların planlanması: hesaplama, depolama, aktarım ve istek ücretlerinden oluşan maliyet modeli, etiketleme ile sahiplik bazlı maliyet dağıtımı, beklenmedik harcamayı erken yakalayan bütçe ve uyarılar, aşırı sağlamanın azaltılması için kaynak boyutlandırma, ölçek planlamasında kota ve servis sınırları ile taşınabilirlik ve çıkış maliyetiyle satıcı bağımlılığının değerlendirilmesi.

### Maliyet Modeli

Source: https://academia.sh/tr/kurslar/bulut-yonetisimi/maliyet-modeli

Kiralanan katmanın faturası dört kaleme ayrılır: aylık 1.542 kurgu birimin %37,7'si hesaplama, %31,8'i aktarım, %20,2'si istek ve yalnız %10,3'ü depolamadır; istek ücreti depolamanın 1,95 katıdır. Aynı fatura on bir tasarım kararına eşlendiğinde kararların yarısından fazlası (%50,8) platformun, dördü birden çok kaleme dağılıyor. Ham ölçüm akışında istek ücretinin depolamayı geçtiği nokta 693.370 kalem/ay (11.364 bayt) çıkıyor; ağ kalem başına 152 bayt yazarak bu noktanın 74,8 katı ötesinde duruyor ve 6,48 birimlik depolamaya karşılık 299,43 birim istek ücreti ödüyor.

Önceki konu erişimi daralttı, veriyi şifreledi ve kanıtı üretti. Üçü de bir kaynak tüketti:
anahtar yönetimi servisi çağrıldı, denetim günlüğü yazıldı, özel uç noktalar açıldı, sır
döndürüldü. Bunların hiçbiri bedava değildi ve hiçbirinin bedeli sayılmadı.

Bu konu faturayı okur. İlk soru en yalın olanıdır: aylık tutar hangi kalemlerden oluşuyor, her
kalem hangi tasarım kararından doğuyor ve fatura o kararı adlandırıyor mu.

#### Dört Kalem ve Ardındaki Karar

Örnek kurgu **bölgesel ölçüm ağı**dır: beş ekip, üç ortam, kiralanmış makine, ağ, depo, işlev ve
kenar katmanı. Kalemler, miktarlar ve birim fiyatlar kurgudur; **para birimi de kurgudur** ve
`br` diye anılır, gerçek bir fiyat listesine karşılık gelmez.

**BM1:** fatura dört kalem türü taşır — hesaplama, depolama, aktarım, istek — ve on dört satır
verir. **BM2:** her satırın bir birimi, aylık miktarı ve birim fiyatı vardır. **BM3:** her satır
bir **tasarım kararından** doğar ve o kararın bir sahibi vardır; fatura bu iki alanı taşımaz,
modelde tutulur. **BM4:** ham ölçüm akışının gövde hacmi sabittir — akışın kaç **kaleme**
bölündüğü hacmi değiştirmez, yalnız kalem üstverisini ve istek sayısını değiştirir. **BM5:** bir
ayda yazılan veri saklama süresi boyunca ödenir. **BM6:** fatura ay ve kalem satırı bazında
gelir; kaynak, ekip ve ortam ayrımı taşımaz.

Fatura, kalemler ve akış süreç içi bir **modeldir**; gerçek bir fatura yoktur.

```js
// maliyet/fatura.mjs — aylik fatura modeli: gercek bir fatura yok. Kalemler, miktarlar ve birim
// fiyatlar bir veri yapisidir; para birimi kurgudur ve `br` diye anilir, gercek bir fiyat
// listesine karsilik gelmez. Her satir bir *fatura kalemine* bagli, ayrica onu doguran *tasarim
// kararina* ve karari veren tarafa bagli tutulur; fatura bu ikinci baglantiyi hic tasimaz.

// [kalem turu, satir adi, birim, aylik miktar, birim fiyat (br), karar, karari veren]
export const FATURA = [
  ["hesaplama", "kiralanmis makine",      "makine-saat",     8640,  0.062,
    "uc ortamin ucu de surekli acik", "platform"],
  ["hesaplama", "islev cagri suresi",     "bin GB-saniye",     41.6, 0.850,
    "olay basina islev", "uygulama"],
  ["hesaplama", "kenar katmani islem",    "bin cagri",        930,   0.011,
    "on isleme kenarda", "uygulama"],
  ["depolama",  "ham olcum govdesi",      "GB-ay",            189.1, 0.021,
    "ham olcum 24 ay saklanir", "yonetisim"],
  ["depolama",  "kalem ustverisi",        "GB-ay",            119.4, 0.021,
    "her okuma ayri kalem yazilir", "uygulama"],
  ["depolama",  "islenmis seri",          "GB-ay",           1420,   0.019,
    "her toplam onceden hesaplanir", "raporlama"],
  ["depolama",  "anlik goruntu ve yedek", "GB-ay",           2140,   0.048,
    "gunluk anlik goruntu, 35 gun", "yonetisim"],
  ["depolama",  "kayit deposu",           "GB-ay",           1360,   0.017,
    "her istek kaydedilir", "yonetisim"],
  ["aktarim",   "bolge disina cikis",     "GB",              2960,   0.082,
    "rapor bolge disindan cekilir", "raporlama"],
  ["aktarim",   "bolgeler arasi kopya",   "GB",              4400,   0.019,
    "ikinci bolgeye surekli kopya", "platform"],
  ["aktarim",   "bolge ici bolgeler arasi", "GB",           18200,   0.009,
    "her yazma uc bolgeye dagilir", "platform"],
  ["istek",     "nesne yazma",            "milyon istek",      51.84,  4.300,
    "her okuma ayri kalem yazilir", "uygulama"],
  ["istek",     "nesne okuma",            "milyon istek",     212.544, 0.360,
    "rapor bolge disindan cekilir", "raporlama"],
  ["istek",     "islev cagrisi",          "milyon istek",      62.1,   0.190,
    "olay basina islev", "uygulama"],
];

export const TUR = ["hesaplama", "depolama", "aktarim", "istek"];
export const br = (r) => r[3] * r[4];
export const topla = (v) => v.reduce((a, b) => a + b, 0);

// ham olcum akisi: hacim sabit, degisen tek sey kac *kaleme* bolundugu (BM5)
export const AKIS = {
  sayac: 18000, okumaGun: 96, gun: 30,     // aylik okuma sayisi bundan turer
  govdeBayt: 152, ustveriBayt: 96,         // her kalem bir ustveri de tasir
  saklamaAy: 24, depoBr: 0.021,            // bu ayin verisi 24 ay boyunca odenir
  yazmaBr: 4.30, okumaBr: 0.36, okumaKati: 4.1,
};

export const govdeGB = () =>
  AKIS.sayac * AKIS.okumaGun * AKIS.gun * AKIS.govdeBayt / 1e9;

// M: aylik kalem sayisi. Govde hacmi M'den bagimsiz; ustveri M ile buyur.
export const depolamaBr = (M) =>
  (govdeGB() + M * AKIS.ustveriBayt / 1e9) * AKIS.saklamaAy * AKIS.depoBr;
export const istekBr = (M) =>
  M / 1e6 * (AKIS.yazmaBr + AKIS.okumaKati * AKIS.okumaBr);

// iki dogru da M'de dogrusal: kesisim kapali bicimde cikar
export const kesisim = () => {
  const a = (AKIS.yazmaBr + AKIS.okumaKati * AKIS.okumaBr) / 1e6;
  const b = AKIS.ustveriBayt / 1e9 * AKIS.saklamaAy * AKIS.depoBr;
  return govdeGB() * AKIS.saklamaAy * AKIS.depoBr / (a - b);
};
```

```js
// maliyet/olc.mjs — dort kaleme ayirma, kalemin doguran karara eslenmesi ve istek ucretinin
// depolama ucretini gectigi nokta. Tum sayilar yukaridaki modelden turer; olculen sey fatura
// degil, faturanin *cozunurlugudur*.
import { FATURA, TUR, AKIS, br, topla, govdeGB, depolamaBr, istekBr,
  kesisim } from "./fatura.mjs";

const yaz = (g, ...s) => console.log(s.map((v, i) =>
  (g[i] < 0 ? String(v).padEnd(-g[i]) : String(v).padStart(g[i]))).join(""));
const t0 = process.hrtime.bigint();

const T = topla(FATURA.map(br)), pay = (x) => `%${(100 * x / T).toFixed(1)}`;
console.log(`${FATURA.length} fatura satiri, aylik ${T.toFixed(0)} br (kurgu para birimi)`);

console.log("\n1. dort kalem: fatura neyi soyluyor");
const A = [-26, -15, 11, 9, 11, 8];
yaz(A, "satir", "birim", "miktar", "birim br", "aylik br", "pay");
for (const t of TUR) {
  const s = FATURA.filter((r) => r[0] === t);
  for (const r of s) yaz(A, r[1], r[2], r[3], r[4].toFixed(3), br(r).toFixed(1), pay(br(r)));
  const alt = topla(s.map(br));
  yaz(A, `  ${t} toplam`, "-", "-", "-", alt.toFixed(1), pay(alt));
}
const T4 = TUR.map((t) => topla(FATURA.filter((r) => r[0] === t).map(br)));
console.log(`  istek ${T4[3].toFixed(1)} br, depolama ${T4[1].toFixed(1)} br: ` +
  `oran ${(T4[3] / T4[1]).toFixed(2)}`);

console.log("\n2. ayni fatura karara eslenince: kalem satiri bir karari adlandirmiyor");
const K = new Map();
for (const r of FATURA) {
  const k = K.get(r[5]) ?? { br: 0, tur: new Set(), sahip: r[6] };
  k.br += br(r); k.tur.add(r[0]); K.set(r[5], k);
}
const B = [-32, -11, 22, 11, 7];
yaz(B, "karar", "veren", "hangi kalemlerde", "aylik br", "pay");
const sirali = [...K.entries()].sort((a, b) => b[1].br - a[1].br);
for (const [ad, k] of sirali)
  yaz(B, ad, k.sahip, [...k.tur].join("+"), k.br.toFixed(1), pay(k.br));
const cok = sirali.filter(([, k]) => k.tur.size > 1);
console.log(`  ${K.size} karar, ${FATURA.length} fatura satiri; ${cok.length} karar birden ` +
  `cok kaleme dagiliyor`);
const S = new Map();
for (const [, k] of K) S.set(k.sahip, (S.get(k.sahip) ?? 0) + k.br);
const sSirali = [...S.entries()].sort((a, b) => b[1] - a[1]);
const sMetin = sSirali.map(([s, v]) => `${s} ${v.toFixed(1)} br (${pay(v)})`);
console.log(`  karari verene gore: ${sMetin.slice(0, 2).join(", ")},`);
console.log(`  ${sMetin.slice(2).join(", ")}`);

console.log("\n3. istek ucreti nerede depolama ucretini geciyor (ham olcum akisi)");
const gercek = AKIS.sayac * AKIS.okumaGun * AKIS.gun;
console.log(`  hacim sabit: ${govdeGB().toFixed(2)} GB/ay govde, ` +
  `${(gercek / 1e6).toFixed(2)} milyon okuma/ay`);
const C = [15, 12, 12, 12, 10, 11];
yaz(C, "kalem/ay", "kalem bayt", "okuma/kalem", "depolama br", "istek br", "baskin");
for (const M of [1e4, 1e5, 3e5, 693372, 1e6, 5e6, 51.84e6, 2e8]) {
  const d = depolamaBr(M), i = istekBr(M);
  yaz(C, M.toLocaleString("en-US"), (govdeGB() * 1e9 / M).toFixed(0),
    (gercek / M).toFixed(2), d.toFixed(2), i.toFixed(2), i > d ? "istek" : "depolama");
}
const M0 = kesisim();
console.log(`  kesisim ${Math.round(M0).toLocaleString("en-US")} kalem/ay: ` +
  `kalem basina ${(govdeGB() * 1e9 / M0).toFixed(0)} bayt, ` +
  `${(gercek / M0).toFixed(1)} okuma/kalem`);
const Mv = gercek;
console.log(`  agin secimi her okuma ayri kalem: ${(Mv / M0).toFixed(1)} kat kesisimin otesi;`);
console.log(`  depolama ${depolamaBr(Mv).toFixed(2)} br, istek ${istekBr(Mv).toFixed(2)} br, ` +
  `oran ${(istekBr(Mv) / depolamaBr(Mv)).toFixed(1)}`);

console.log("\n4. faturanin cozunurlugu: kac ayrim veriyor, kac ayrim gerekiyor");
const D = [-28, 8, 16];
const EKIP = 5, ORTAM = 3, KAYNAK = 6;
yaz(D, "ayrim", "adet", "kaynak");
yaz(D, "fatura satiri (aylik)", FATURA.length, "fatura");
yaz(D, "kalem turu", TUR.length, "fatura");
yaz(D, "tasarim karari", K.size, "faturada yok");
yaz(D, "karari veren taraf", S.size, "faturada yok");
yaz(D, "ekip x ortam x kaynak turu", EKIP * ORTAM * KAYNAK, "faturada yok");
const kalan = EKIP * ORTAM * KAYNAK - FATURA.length;
console.log(`  fatura ${FATURA.length} ayrim veriyor, ag ${EKIP * ORTAM * KAYNAK} birim ` +
  `ayirmayi gerektiriyor: ${kalan} birim faturadan okunamiyor`);

const ms = Number(process.hrtime.bigint() - t0) / 1e6;   // ham olcum basilmaz, bant denetlenir
console.log(`\ndort tablo 2000 ms bandinda: ${ms < 2000 ? "evet" : "hayir"}`);
```

```
14 fatura satiri, aylik 1542 br (kurgu para birimi)

1. dort kalem: fatura neyi soyluyor
satir                     birim               miktar birim br   aylik br     pay
kiralanmis makine         makine-saat           8640    0.062      535.7   %34.7
islev cagri suresi        bin GB-saniye         41.6    0.850       35.4    %2.3
kenar katmani islem       bin cagri              930    0.011       10.2    %0.7
  hesaplama toplam        -                        -        -      581.3   %37.7
ham olcum govdesi         GB-ay                189.1    0.021        4.0    %0.3
kalem ustverisi           GB-ay                119.4    0.021        2.5    %0.2
islenmis seri             GB-ay                 1420    0.019       27.0    %1.7
anlik goruntu ve yedek    GB-ay                 2140    0.048      102.7    %6.7
kayit deposu              GB-ay                 1360    0.017       23.1    %1.5
  depolama toplam         -                        -        -      159.3   %10.3
bolge disina cikis        GB                    2960    0.082      242.7   %15.7
bolgeler arasi kopya      GB                    4400    0.019       83.6    %5.4
bolge ici bolgeler arasi  GB                   18200    0.009      163.8   %10.6
  aktarim toplam          -                        -        -      490.1   %31.8
nesne yazma               milyon istek         51.84    4.300      222.9   %14.5
nesne okuma               milyon istek       212.544    0.360       76.5    %5.0
islev cagrisi             milyon istek          62.1    0.190       11.8    %0.8
  istek toplam            -                        -        -      311.2   %20.2
  istek 311.2 br, depolama 159.3 br: oran 1.95

2. ayni fatura karara eslenince: kalem satiri bir karari adlandirmiyor
karar                           veren            hangi kalemlerde   aylik br    pay
uc ortamin ucu de surekli acik  platform                hesaplama      535.7  %34.7
rapor bolge disindan cekilir    raporlama           aktarim+istek      319.2  %20.7
her okuma ayri kalem yazilir    uygulama           depolama+istek      225.4  %14.6
her yazma uc bolgeye dagilir    platform                  aktarim      163.8  %10.6
gunluk anlik goruntu, 35 gun    yonetisim                depolama      102.7   %6.7
ikinci bolgeye surekli kopya    platform                  aktarim       83.6   %5.4
olay basina islev               uygulama          hesaplama+istek       47.2   %3.1
her toplam onceden hesaplanir   raporlama                depolama       27.0   %1.7
her istek kaydedilir            yonetisim                depolama       23.1   %1.5
on isleme kenarda               uygulama                hesaplama       10.2   %0.7
ham olcum 24 ay saklanir        yonetisim                depolama        4.0   %0.3
  11 karar, 14 fatura satiri; 3 karar birden cok kaleme dagiliyor
  karari verene gore: platform 783.1 br (%50.8), raporlama 346.2 br (%22.5),
  uygulama 282.8 br (%18.3), yonetisim 129.8 br (%8.4)

3. istek ucreti nerede depolama ucretini geciyor (ham olcum akisi)
  hacim sabit: 7.88 GB/ay govde, 51.84 milyon okuma/ay
       kalem/ay  kalem bayt okuma/kalem depolama br  istek br     baskin
         10,000      787968     5184.00        3.97      0.06   depolama
        100,000       78797      518.40        3.98      0.58   depolama
        300,000       26266      172.80        3.99      1.73   depolama
        693,372       11364       74.77        4.00      4.00      istek
      1,000,000        7880       51.84        4.02      5.78      istek
      5,000,000        1576       10.37        4.21     28.88      istek
     51,840,000         152        1.00        6.48    299.43      istek
    200,000,000          39        0.26       13.65   1155.20      istek
  kesisim 693,370 kalem/ay: kalem basina 11364 bayt, 74.8 okuma/kalem
  agin secimi her okuma ayri kalem: 74.8 kat kesisimin otesi;
  depolama 6.48 br, istek 299.43 br, oran 46.2

4. faturanin cozunurlugu: kac ayrim veriyor, kac ayrim gerekiyor
ayrim                           adet          kaynak
fatura satiri (aylik)             14          fatura
kalem turu                         4          fatura
tasarim karari                    11    faturada yok
karari veren taraf                 4    faturada yok
ekip x ortam x kaynak turu        90    faturada yok
  fatura 14 ayrim veriyor, ag 90 birim ayirmayi gerektiriyor: 76 birim faturadan okunamiyor

dort tablo 2000 ms bandinda: evet
```

Sayılar **ölçüm** sınıfındadır; girdileri yukarıdaki varsayımlardır.

#### Faturanın Şekli

Birinci tablo aylık 1.542 birimi dört kaleme ayırır. Hesaplama **%37,7** ile en büyüğüdür ve
neredeyse tamamı tek satırdan gelir: üç ortamın kiralanmış makineleri 535,7 birim, faturanın
**%34,7'si**. Aktarım **%31,8** ile ikincidir. İstek **%20,2**, depolama ise yalnız **%10,3**.

Sıralamanın ters çevirdiği beklenti şudur: veri saklayan bir ağda en küçük kalem depolamadır ve
**istek ücreti onun 1,95 katıdır**. Tek başına nesne yazma satırı 222,9 birim tutar; depolamanın
beş satırının toplamı 159,3 birimdir.

Birim fiyatın küçüklüğü de kalemin küçüklüğü anlamına gelmez. Bölge içi bölgeler arası aktarım
GB başına 0,009 birimle faturadaki en ucuz birim fiyattır; 18.200 GB ile faturanın **%10,6'sını**
tutar — depolamanın tamamından fazlasını. Ucuz olan çok kullanılır, çok kullanılan büyür.

#### Fatura Kalemi Bir Kararı Adlandırmıyor

İkinci tablo aynı tutarı, satırları doğuran karara göre yeniden toplar. On dört fatura satırı
**on bir karara** iner ve üçü tek bir kalem türüne sığmaz: "rapor bölge dışından çekilir" hem
aktarımda hem istekte görünür (319,2 birim), "her okuma ayrı kalem yazılır" hem depolamada hem
istekte (225,4 birim), "olay başına işlev" hem hesaplamada hem istekte (47,2 birim).

Bu, faturayı okumanın neden karar üretmediğini gösterir. İstek kalemi **%20,2** diye okunduğunda
tek bir şey değildir: içinde üç ayrı kararın artığı vardır ve o kararların her biri başka bir
kalemde de iz bırakır. İstek kalemini küçültmek için istek kaleminde yapılabilecek bir şey
yoktur; kararın kendisi değişmelidir.

Kararı verene göre toplam daha da keskindir. Faturanın **%50,8'i** platformun verdiği üç karardan
doğar: makinelerin sürekli açık kalması, her yazmanın üç bölgeye dağılması, ikinci bölgeye
sürekli kopya. Raporlama **%22,5**, uygulama **%18,3**, yönetişim **%8,4**. Faturayı ekiplere
gösterip kısıntı beklemek, tutarın yarısının hiçbir ekibin kararı olmadığı bir yerde başlar.

#### Küçük Ücretin Baskın Hâle Geldiği Nokta

Üçüncü tablo tek bir akışı izole eder. Ham ölçüm akışı ayda 51,84 milyon okuma ve **7,88 GB**
gövde üretir; bu hacim sabittir. Değişen tek şey akışın kaç kaleme bölündüğüdür.

Tarama iki eğriyi yan yana koyar. Depolama neredeyse yataydır: on bin kalemde 3,97 birim, iki
yüz milyon kalemde 13,65 birim — büyümenin tamamı kalem üstverisinden gelir. İstek ise
**doğrusaldır ve sıfırdan başlar**: on bin kalemde 0,06 birim, iki yüz milyonda 1.155,20 birim.

İki eğri **693.370 kalem/ay**'da kesişir. Kalem başına **11.364 bayt**, yani yaklaşık **74,8
okuma**. Bu noktanın altında depolama baskındır ve istek ücreti gürültüdür; üstünde tersi olur.

Ağın seçimi her okumayı ayrı kalem yazmaktır: kalem başına 152 bayt, kesişimin **74,8 katı**
ötesi. Orada depolama 6,48 birim, istek **299,43 birimdir** — kırk altı kat. İstek başına ücret
faturada 4,30 birim/milyon diye yazılıdır ve tek bir işlem için ölçülemeyecek kadar küçüktür;
baskın hâle gelmesi fiyattan değil, **sayıdan** gelir. Bu ücretin ardındaki tasarım kararı bir
depolama kararı gibi görünmez, bir **parçalama** kararıdır ve fatura o adı hiç kullanmaz.

#### Faturanın Çözünürlüğü

Dördüncü tablo sınırı sayar. Fatura ayda on dört satır ve dört kalem türü verir. Ağ ise beş ekip,
üç ortam ve altı kaynak türüyle **90 birim** ayırmayı gerektirir. On dört satırdan doksan birime
giden bir eşleme yoktur: **76 birim faturadan okunamaz**. Kararı veren taraf da, kararın kendisi
de faturada yoktur; ikisi de yalnız modelde bilinir.

Fatura bu hâliyle bir muhasebe belgesi değil, bir **toplam**dır. Sahip bilgisi faturada değilse
başka bir yerden gelmek zorundadır.

#### Özet

- Kurgu ağın aylık 1.542 birimlik faturası dört kaleme ayrılır: hesaplama %37,7, aktarım %31,8,
  istek %20,2, depolama %10,3. Veri saklayan bir ağda **istek ücreti depolamanın 1,95 katıdır**.
- Birim fiyatın küçüklüğü kalemin küçüklüğü demek değildir: GB başına 0,009 birimlik en ucuz
  aktarım satırı, 18.200 GB ile faturanın %10,6'sını tutar.
- On dört fatura satırı on bir tasarım kararından doğar ve üç karar birden çok kaleme dağılır;
  bir kalemi küçültmek o kalemde değil, kararda yapılan bir işle olur.
- Faturanın **%50,8'i** platformun verdiği üç karardan gelir; uygulama ekiplerinin kararı %18,3.
  Kısıntıyı ekipten beklemek tutarın yarısının dışında kalır.
- Sabit hacimli ham ölçüm akışında istek ücreti depolamayı **693.370 kalem/ay**'da geçer — kalem
  başına 11.364 bayt. Ağ 152 baytlık kalem yazar, kesişimin 74,8 katı ötesinde durur ve 6,48
  birimlik depolamaya karşılık **299,43 birim** istek ücreti öder.
- Fatura on dört ayrım verir, ağ 90 birim ayırmayı gerektirir: **76 birim faturadan okunamaz**.

#### Sonraki Adım

Fatura toplamı okundu ve kalemler ayrıldı, ama her kalemin karşısında hâlâ bir sahip yok. Sıradaki
ders sahiplik bilgisini faturanın dışından getirir: kaynaklara etiket takılır ve maliyet ekiplere
o etiketten dağıtılır. Ölçülecek olan dağıtımın kendisi değil, dağıtımın **tutmadığı** yerdir —
etiketsiz kaynağın tuttuğu pay, paylaşılan kaynağın hangi kuralla bölüşüleceği ve etiket
zorunluluğu getirildiğinde geçmiş faturaya ne olduğu.

### Etiketleme ve Maliyet Dağıtımı

Source: https://academia.sh/tr/kurslar/bulut-yonetisimi/etiketleme-ve-maliyet-dagitimi

Sahiplik bilgisi faturanın dışından gelir ve tam gelmez: 148 kaynaklı kurgu envanterde görünen etiket kapsamı %77,7 iken geçerli kapsam %75,0'tir, aylık 4.214,3 kurgu birimin %25,1'i hiçbir kurala girmeden atanamaz kalır. Paylaşılan 1.584,9 birim üç kuralla bölüştürüldüğünde aynı ekibin faturası %8,7 ile %18,6 arasında oynar. Etiket zorunluluğu atanamayan payı sıfırlar ama 37 kaynağı reddeder ve 511,9 birimlik 14 meşru işi durdurur; etiketler ay sonunda %95,9 kapsama çıksa bile o ayın 568,6 birimi (%13,5) geriye dönük düzelmez.

Önceki ders faturanın on dört ayrım verdiğini, ağın ise doksan birim ayırmayı gerektirdiğini
ölçtü. Aradaki boşluk faturadan kapanmaz; sahiplik bilgisi başka bir yerden gelmek zorundadır.
Bulut tarafında o yer **kaynağın kendisidir**: kaynağa bir etiket takılır ve maliyet o etiketten
dağıtılır.

Bu dersin sorusu dağıtımın nasıl yapılacağı değil, **nerede tutmadığıdır**. Ekip bazlı muhasebe
ve bölüştürülemeyen kalem M22/K08'de ölçüldü; burada ölçülen şey onun girdisi olan **etikettir**.

#### Etiketli Kaynak Envanteri

Örnek kurgu **bölgesel ölçüm ağı**dır: beş ekip, üç ortam, kiralanmış makine, ağ, depo, işlev ve
kenar katmanı. Kaynaklar, etiketler ve tutarlar kurgudur; **para birimi de kurgudur** ve `br`
diye anılır, gerçek bir fiyat listesine karşılık gelmez.

**BM7:** envanterde 148 kaynak vardır; sekiz tür, üçü birden çok ekip tarafından kullanılır ve
`paylasilan` etiketi taşır. **BM8:** bir kaynakta sahip etiketinin olup olmaması onun **nasıl
oluşturulduğuna** bağlıdır; dört oluşturma yolu vardır. **BM9:** yanlış yazılmış sahip etiketi
kapsam raporunda **etiketli görünür** ama ekip listesinde karşılığı yoktur; dağıtımda geçersizdir.
**BM10:** paylaşılan kaynağın gerçek sürücüsü **bilinmez** — bu derste karşılaştırılacak bir
gerçek pay yoktur, ölçülen şey sapma değil, kurala göre oynamadır. **BM11:** bir kaynağa en çok
on etiket anahtarı takılabilir; ağ yedi anahtar kullanır. **BM12:** etiket bir günde tamamlanır;
o günden önce kesilmiş fatura satırları etiketsizdir ve düzelmez.

Envanter süreç içi bir **modeldir** ve bir üreteçten türer; tohum görünürdür.

```js
// maliyet/envanter.mjs — etiketli kaynak envanteri modeli: gercek bir envanter yok. Kaynaklar
// bir uretecle turetilir, tohum gorunurdur ve koşum tekrarlanabilir. Para birimi kurgudur ve
// `br` diye anilir. Etiketin *olup olmamasi* kaynagin nasil olusturuldugu ile belirlenir;
// yanlis yazilmis etiket ayri bir durumdur: kapsam raporunda etiketli, dagitimda gecersiz.

export const TOHUM = 6108;
export const ADET = 148;
export const EKIP = ["sayac-okuma", "dogrulama", "faturalama", "saha", "raporlama"];
export const ORTAM = ["uretim", "hazirlik", "gelistirme"];
export const ETIKET_SINIRI = 10;                       // kaynak basina en cok etiket anahtari
export const KULLANILAN_ANAHTAR =
  ["sahip", "ortam", "hizmet", "surum", "gecici", "sorumlu", "maliyet-merkezi"];

// tur adi, aylik br alt-ust, paylasilan mi (birden cok ekip kullanir)
export const TUR = [
  ["kiralanmis makine", 18, 96, false], ["blok depo", 4, 34, false],
  ["nesne deposu", 6, 52, false], ["islev", 1, 12, false],
  ["kenar dugumu", 3, 21, false], ["ag gecidi", 12, 40, true],
  ["ortak veri yolu", 20, 64, true], ["izleme toplayici", 9, 30, true],
];

// olusturma yolu: ad, pay, sahip etiketi olma olasiligi, etiketin dogru yazilma olasiligi
export const YOL = [
  ["sablon", 0.40, 1.00, 1.00], ["otomatik olcekleme", 0.26, 0.71, 0.94],
  ["elle", 0.22, 0.55, 0.78], ["eski gecis", 0.12, 0.08, 0.60],
];

const sec = (tablo, u) => { let a = 0; for (const s of tablo) { a += s[1]; if (u < a) return s; }
  return tablo[tablo.length - 1]; };

// yanlis yazim bicimleri: kapsam raporunda etiket gorunur, ekip listesinde karsiligi yok
const VARYANT = [(e) => e.toUpperCase(), (e) => e.replace(/-/g, ""), (e) => e + "-ekibi"];

export const envanter = () => {
  let s = TOHUM >>> 0;
  const r = () => { s = (Math.imul(s, 1664525) + 1013904223) >>> 0; return s / 4294967296; };
  const liste = [];
  for (let i = 0; i < ADET; i++) {
    const [tad, alt, ust, pay] = TUR[Math.floor(r() * TUR.length)];
    const [yad, , pVar, pDogru] = sec(YOL, r());
    const ortam = ORTAM[Math.floor(r() * ORTAM.length)];
    const br = Math.round((alt + r() * (ust - alt)) * 10) / 10;
    const ekip = EKIP[Math.floor(r() * EKIP.length)];
    let sahip = null, gecerli = false;
    if (pay) { sahip = "paylasilan"; gecerli = true; }
    else if (r() < pVar) {
      if (r() < pDogru) { sahip = ekip; gecerli = true; }
      else sahip = VARYANT[Math.floor(r() * VARYANT.length)](ekip);
    }
    const gun = 1 + Math.floor(r() * 34);               // etiketin tamamlandigi gun; >30 hic
    const acil = yad === "elle" && r() < 0.18;          // acil onarim isi
    liste.push({ id: i, tur: tad, paylasilan: pay, yol: yad, ortam, br, sahip, gecerli,
      duzeltmeGunu: sahip && gecerli ? 0 : gun, acil });
  }
  return liste;
};

export const topla = (v) => v.reduce((a, b) => a + b, 0);
export const brToplam = (v) => topla(v.map((k) => k.br));
```

```js
// maliyet/dagit.mjs — etiket kapsami, maliyetin ekiplere dagitimi (uc kural), etiket
// zorunlulugunun reddettigi kaynaklar ve etiketin geriye islememesi. Sayilar envanter
// modelinden turer; olculen sey etiketin dogrulugu degil, *dagitimin tutmadigi yerdir*.
import { envanter, EKIP, TUR, YOL, ETIKET_SINIRI, KULLANILAN_ANAHTAR, TOHUM,
  topla, brToplam } from "./envanter.mjs";

const yaz = (g, ...s) => console.log(s.map((v, i) =>
  (g[i] < 0 ? String(v).padEnd(-g[i]) : String(v).padStart(g[i]))).join(""));
const t0 = process.hrtime.bigint();

const K = envanter(), T = brToplam(K), pay = (x) => `%${(100 * x / T).toFixed(1)}`;
console.log(`tohum ${TOHUM}: ${K.length} kaynak, aylik ${T.toFixed(1)} br (kurgu para birimi)`);

console.log("\n1. etiket kapsami: olusturma yoluna gore");
const A = [-20, 8, 10, 10, 10, 11, 9];
yaz(A, "olusturma yolu", "kaynak", "etiketli", "gecerli", "gecersiz", "etiketsiz", "br payi");
for (const [ad] of YOL) {
  const g = K.filter((k) => k.yol === ad), e = g.filter((k) => k.sahip);
  yaz(A, ad, g.length, e.length, g.filter((k) => k.gecerli).length,
    e.filter((k) => !k.gecerli).length, g.filter((k) => !k.sahip).length,
    pay(brToplam(g)));
}
const etiketli = K.filter((k) => k.sahip), gecerli = K.filter((k) => k.gecerli);
const gecersiz = K.filter((k) => k.sahip && !k.gecerli), bos = K.filter((k) => !k.sahip);
yaz(A, "toplam", K.length, etiketli.length, gecerli.length, gecersiz.length, bos.length, "%100");
console.log(`  gorunen kapsam %${(100 * etiketli.length / K.length).toFixed(1)}, ` +
  `gecerli kapsam %${(100 * gecerli.length / K.length).toFixed(1)}`);
console.log(`  gecersiz etiket ${gecersiz.length} kaynak ${brToplam(gecersiz).toFixed(1)} br ` +
  `(${pay(brToplam(gecersiz))}): kapsam raporunda etiketli gorunur`);
console.log(`  etiket anahtari siniri ${ETIKET_SINIRI}, kullanilan ` +
  `${KULLANILAN_ANAHTAR.length}, kalan ${ETIKET_SINIRI - KULLANILAN_ANAHTAR.length}`);

console.log("\n2. dagitim: dogrudan atanan, paylasilan, atanamayan");
const dogrudan = K.filter((k) => k.gecerli && k.sahip !== "paylasilan");
const paylasilan = K.filter((k) => k.sahip === "paylasilan");
const atanamayan = K.filter((k) => !k.gecerli);
const D = brToplam(dogrudan), P = brToplam(paylasilan), X = brToplam(atanamayan);
const B = [-14, 9, 11, 9];
yaz(B, "kume", "kaynak", "aylik br", "pay");
yaz(B, "dogrudan", dogrudan.length, D.toFixed(1), pay(D));
yaz(B, "paylasilan", paylasilan.length, P.toFixed(1), pay(P));
yaz(B, "atanamayan", atanamayan.length, X.toFixed(1), pay(X));
const ekipBr = EKIP.map((e) => brToplam(dogrudan.filter((k) => k.sahip === e)));
const ekipAdet = EKIP.map((e) => dogrudan.filter((k) => k.sahip === e).length);
const oran = (v) => { const t = topla(v); return v.map((x) => x / t); };
const KURAL = { esit: EKIP.map(() => 1 / EKIP.length), maliyet: oran(ekipBr),
  "kaynak sayisi": oran(ekipAdet) };
console.log(`  paylasilan ${P.toFixed(1)} br bir kurala gore bolusur;`);
console.log(`  atanamayan ${X.toFixed(1)} br (${pay(X)}) hicbir kurala girmez`);

console.log("\n3. uc bolusturme kurali: ayni ekibin faturasi kurala gore ne kadar oynuyor");
const C = [-14, ...EKIP.map(() => 13)];
yaz(C, "kural", ...EKIP);
const sonuc = {};
for (const [ad, p] of Object.entries(KURAL))
  sonuc[ad] = EKIP.map((_, i) => ekipBr[i] + P * p[i]);
yaz(C, "dogrudan", ...ekipBr.map((x) => x.toFixed(1)));
for (const [ad, v] of Object.entries(sonuc)) yaz(C, ad, ...v.map((x) => x.toFixed(1)));
const oynama = EKIP.map((_, i) => {
  const v = Object.values(sonuc).map((s) => s[i]);
  return [Math.min(...v), Math.max(...v)];
});
yaz(C, "en genis fark", ...oynama.map(([a, b]) => (b - a).toFixed(1)));
yaz(C, "faturaya gore", ...oynama.map(([a, b]) => `%${(100 * (b - a) / a).toFixed(1)}`));
const en = oynama.map(([a, b]) => (b - a) / a);
const i0 = en.indexOf(Math.max(...en));
console.log(`  karsilastirilacak bir gercek pay yok: olculen sapma degil, kurala gore oynama`);
console.log(`  en cok oynayan ${EKIP[i0]}: %${(100 * en[i0]).toFixed(1)}; ` +
  `atanamayan ${pay(X)} her uc kuralda da faturada yok`);

console.log("\n4. etiket zorunlulugu: kac kaynak reddedilir, kaci mesru is");
const red = K.filter((k) => !k.gecerli);
const E = [-20, 9, 11, 12, 11];
yaz(E, "olusturma yolu", "reddedilen", "aylik br", "mesru is", "duran br");
let mesruAdet = 0, mesruBr = 0;
for (const [ad] of YOL) {
  const g = red.filter((k) => k.yol === ad);
  const m = g.filter((k) => k.yol === "otomatik olcekleme" || k.acil);
  mesruAdet += m.length; mesruBr += brToplam(m);
  yaz(E, ad, g.length, brToplam(g).toFixed(1), m.length, brToplam(m).toFixed(1));
}
yaz(E, "toplam", red.length, brToplam(red).toFixed(1), mesruAdet, mesruBr.toFixed(1));
console.log(`  ${red.length} kaynak reddedilir (%${(100 * red.length / K.length).toFixed(1)}); ` +
  `bunun ${mesruAdet} tanesi kapasite ya da acil onarim isidir`);
console.log(`  zorunluluk atanamayan ${pay(X)} payi sifirlar, karsiliginda ` +
  `${mesruBr.toFixed(1)} br degerinde ${mesruAdet} is durur`);

console.log("\n5. etiket sonradan eklenince: gecmis fatura duzelmiyor");
const GUN = 30, KILOMETRE = [1, 5, 10, 15, 20, 25, 30];
const F = [6, 14, 9, 16, 16];
yaz(F, "gun", "etiketlenmis", "kapsam", "atanan br/gun", "birikmis kayip");
const gunlukKayip = (g) => brToplam(K.filter((k) => !k.gecerli && k.duzeltmeGunu > g)) / GUN;
let birikim = 0;
for (let g = 1; g <= GUN; g++) {
  birikim += gunlukKayip(g);
  if (!KILOMETRE.includes(g)) continue;
  const kapali = K.filter((k) => k.gecerli || k.duzeltmeGunu <= g);
  yaz(F, g, kapali.length, `%${(100 * kapali.length / K.length).toFixed(1)}`,
    (brToplam(kapali) / GUN).toFixed(2), birikim.toFixed(1));
}
const hic = K.filter((k) => !k.gecerli && k.duzeltmeGunu > GUN);
console.log(`  ay sonu kapsami %${(100 * (K.length - hic.length) / K.length).toFixed(1)}, ` +
  `ama ayin atanamayan payi ${birikim.toFixed(1)} br (%${(100 * birikim / T).toFixed(1)})`);
console.log(`  ${hic.length} kaynak hic etiketlenmez: ${brToplam(hic).toFixed(1)} br/ay ` +
  `her ay yeniden atanamaz`);

const ms = Number(process.hrtime.bigint() - t0) / 1e6;   // ham olcum basilmaz, bant denetlenir
console.log(`\nbes tablo 2000 ms bandinda: ${ms < 2000 ? "evet" : "hayir"}`);
```

```
tohum 6108: 148 kaynak, aylik 4214.3 br (kurgu para birimi)

1. etiket kapsami: olusturma yoluna gore
olusturma yolu        kaynak  etiketli   gecerli  gecersiz  etiketsiz  br payi
sablon                    58        58        58         0          0    %40.8
otomatik olcekleme        40        31        29         2          9    %30.6
elle                      27        16        14         2         11    %14.5
eski gecis                23        10        10         0         13    %14.1
toplam                   148       115       111         4         33     %100
  gorunen kapsam %77.7, gecerli kapsam %75.0
  gecersiz etiket 4 kaynak 123.6 br (%2.9): kapsam raporunda etiketli gorunur
  etiket anahtari siniri 10, kullanilan 7, kalan 3

2. dagitim: dogrudan atanan, paylasilan, atanamayan
kume             kaynak   aylik br      pay
dogrudan             58     1572.2    %37.3
paylasilan           53     1584.9    %37.6
atanamayan           37     1057.2    %25.1
  paylasilan 1584.9 br bir kurala gore bolusur;
  atanamayan 1057.2 br (%25.1) hicbir kurala girmez

3. uc bolusturme kurali: ayni ekibin faturasi kurala gore ne kadar oynuyor
kural           sayac-okuma    dogrulama   faturalama         saha    raporlama
dogrudan              286.6        250.3        267.8        309.8        457.7
esit                  603.6        567.3        584.8        626.8        774.7
maliyet               575.5        502.6        537.8        622.1        919.1
kaynak sayisi         641.8        550.9        568.4        555.7        840.3
en genis fark          66.3         64.7         47.0         71.0        144.4
faturaya gore         %11.5        %12.9         %8.7        %12.8        %18.6
  karsilastirilacak bir gercek pay yok: olculen sapma degil, kurala gore oynama
  en cok oynayan raporlama: %18.6; atanamayan %25.1 her uc kuralda da faturada yok

4. etiket zorunlulugu: kac kaynak reddedilir, kaci mesru is
olusturma yolu      reddedilen   aylik br    mesru is   duran br
sablon                      0        0.0           0        0.0
otomatik olcekleme         11      444.3          11      444.3
elle                       13      222.8           3       67.6
eski gecis                 13      390.1           0        0.0
toplam                     37     1057.2          14      511.9
  37 kaynak reddedilir (%25.0); bunun 14 tanesi kapasite ya da acil onarim isidir
  zorunluluk atanamayan %25.1 payi sifirlar, karsiliginda 511.9 br degerinde 14 is durur

5. etiket sonradan eklenince: gecmis fatura duzelmiyor
   gun  etiketlenmis   kapsam   atanan br/gun  birikmis kayip
     1           112    %75.7          106.85            33.6
     5           115    %77.7          108.90           161.3
    10           119    %80.4          112.15           306.2
    15           123    %83.1          115.44           434.3
    20           133    %89.9          129.34           513.4
    25           139    %93.9          136.04           552.4
    30           142    %95.9          137.50           568.6
  ay sonu kapsami %95.9, ama ayin atanamayan payi 568.6 br (%13.5)
  6 kaynak hic etiketlenmez: 89.3 br/ay her ay yeniden atanamaz

bes tablo 2000 ms bandinda: evet
```

Sayılar **ölçüm** sınıfındadır; girdileri yukarıdaki varsayımlardır.

#### Kapsam Tek Sayı Değil

Birinci tablo etiket kapsamını oluşturma yoluna göre ayırır ve iki farklı sayı üretir. **Görünen
kapsam %77,7**: 148 kaynağın 115'inde bir sahip etiketi vardır. **Geçerli kapsam %75,0**: bunların
dördünde etiket değeri hiçbir ekibe karşılık gelmez. Dört kaynak, 123,6 birim, faturanın
**%2,9'u** — kapsam raporunda sorunsuz görünür ve dağıtımda kaybolur.

Kapsamın nereden geldiği yolun kendisinde yazılıdır. Şablondan oluşan 58 kaynağın **tamamı**
doğru etiketlidir; etiketi yazan insan değil, şablondur. Eski geçişten gelen 23 kaynağın 13'ünde
hiç etiket yoktur, elle oluşturulan 27 kaynakta hem eksik etiket (11) hem yanlış yazım (2)
görülür. Otomatik ölçeklemeden gelen 40 kaynağın dokuzunda etiket yoktur: kaynağı devralmayan
ölçekleme etiketi de devralmaz.

Sınır da sayılır: kaynak başına on etiket anahtarı takılabilir, ağ yedi kullanır, **kalan
üçtür**; yeni bir ayrım eklemek bu üç yuvadan birini harcar.

#### Üç Kural, Üç Farklı Fatura

İkinci tablo dağıtımı üçe böler: doğrudan atanan 1.572,2 birim (%37,3), paylaşılan 1.584,9 birim
(%37,6) ve **atanamayan 1.057,2 birim (%25,1)**. Atanamayan pay bir bölüştürme sorunu değildir;
girdi eksiktir ve hiçbir kural onu kabul etmez.

Üçüncü tablo paylaşılanı üç kuralla böler: eşit pay, doğrudan atanan maliyet oranı ve kaynak
sayısı oranı. Üçü de yalnız etiketten okunur. M22/K08'den farklı olarak burada bir **gerçek pay**
yoktur; ölçülen şey sapma değil, **aynı ekibin faturasının kurala göre oynamasıdır**.

Raporlama en çok oynayandır: eşit payda 774,7, kaynak sayısında 840,3, maliyet oranında 919,1
birim — 144,4 birimlik fark, faturasının **%18,6'sı**. Faturalama en az oynar (%8,7). Ekip kendi
kaynaklarında hiçbir şey değiştirmeden, yalnız merkezde bir kural değiştiği için faturasını
altıda bir oynamış görebilir. Atanamayan %25,1 ise üç kuralda da görünmez; ekiplerin toplamı
toplam faturayı vermez.

#### Zorunluluğun Durdurduğu İş

Dördüncü tablo bariz çözümü uygular: geçerli sahip etiketi olmayan kaynağın oluşturulmasına izin
verilmez. Zorunluluk atanamayan **%25,1'i sıfırlar**, çünkü o kaynaklar hiç var olmaz.

Bedeli aynı tabloda durur. **37 kaynak reddedilir** ve bunların 14'ü meşru iştir: otomatik
ölçeklemenin açtığı 11 kaynak kapasite, elle açılanların üçü acil onarım işidir. Duran iş 511,9
birimdir. Otomatik ölçeklemede reddedilenlerin **tamamı** meşrudur — kural en çok, kimsenin
klavye başında olmadığı yerde ısırır. Eski geçişten gelen 13 red (390,1 birim) hiçbir meşru işi
durdurmaz: o kaynaklar zaten vardır ve zorunluluk yalnız **yenilerine** işler.

#### Etiket Geriye İşlemiyor

Beşinci tablo etiketleri ay içinde tamamlar. Kapsam 1. günde %75,7'den 30. günde **%95,9'a**
çıkar; envanter raporu ay sonunda neredeyse temizdir. Ayın faturası temiz değildir: birikmiş
atanamayan tutar **568,6 birim**, ayın **%13,5'i**.

Nedeni tek cümledir: fatura satırları gün gün kesilir ve kesilen satır, kaynağın o gün taşıdığı
etiketi taşır. 20. günde etiketlenen kaynağın ilk on dokuz günü atanamaz kalır. Kimi sağlayıcı,
kaynağın zaten taşıdığı bir etiketi maliyet dağıtımı için geriye dönük etkinleştirmeye izin verir;
hiç takılmamış bir etiketi geçmişe yazan yoktur. Kapsam **anlık**,
fatura **süreklidir**; ikisini aynı rapora koymak düzelmiş bir ay görüntüsü üretir. Altı kaynak
hiç etiketlenmez: 89,3 birim her ay yeniden atanamaz.

#### Özet

- 148 kaynaklı kurgu envanterde **görünen kapsam %77,7, geçerli kapsam %75,0'tir**; aradaki dört
  kaynak (123,6 birim, %2,9) raporda etiketli görünür ve dağıtımda kaybolur. Kapsam oluşturma
  yoluna bağlıdır: şablondan gelen 58 kaynağın tamamı doğru etiketli, eski geçişten gelen 23
  kaynağın 13'ü etiketsizdir.
- Aylık 4.214,3 birimin %37,3'ü doğrudan atanır, %37,6'sı paylaşılandır ve **%25,1'i hiçbir
  kurala girmez**; ekiplerin toplamı toplam faturayı vermez.
- Paylaşılan pay üç kuralla bölüştürüldüğünde aynı ekibin faturası %8,7 ile %18,6 arasında oynar;
  raporlamanın faturası 774,7 ile 919,1 birim arasında, 144,4 birimlik bir bantta durur.
- Etiket zorunluluğu atanamayan payı sıfırlar ama **37 kaynağı reddeder**; bunun 14'ü meşru iştir
  ve 511,9 birimlik iş durur. Otomatik ölçeklemenin 11 reddinin tamamı kapasite işidir.
- Etiketler ay sonunda %95,9 kapsama çıksa bile o ayın **568,6 birimi (%13,5)** atanamaz kalır:
  kapsam anlık, fatura süreklidir.

#### Sonraki Adım

Kalemler ayrıldı ve bir sahiplik denemesi yapıldı; ikisi de faturanın **geldikten sonra**
okunmasıdır. Sıradaki ders soruyu zaman eksenine taşır: bir harcama eğrisi üzerinde iki uyarı
türü koşturulur, fark etme günü sayılır ve faturanın gecikmeli gelmesi bir kısıt olarak tabloya
girer — uyarı geldiğinde harcamanın ne kadarı çoktan yapılmış olur.

### Bütçe ve Uyarılar

Source: https://academia.sh/tr/kurslar/bulut-yonetisimi/butce-ve-uyarilar

Beklenmedik harcamanın ne zaman fark edildiği ölçülür: kurgu bir harcama eğrisine yerleştirilen beş artış üzerinde eşik uyarısı ikisini tamamen kaçırır ve ilk tetiklendiğinde aylık bütçenin %86,4'ü çoktan harcanmıştır (kalan 204 birim), tahmin uyarısı beşini de yakalar ama doksan günün 63'ünde açık kalır. Eşik ailesinin en iyi ayarı 821 birim kaçırırken tahmin ailesi 12,5 birimde kalır; yanlış alarm farkı ise 21 olaysız günde 5'e karşı 6'dır. Faturanın gecikmesi doğrudan fark etme gününe eklenir: üç günlük gecikme ortalama gecikmeye 1,8 gün ve kaçırılan tutara 210 birim ekler, sekiz günlük gecikmede bir artış tamamen kaçar.

Önceki iki ders faturayı kalemlere ayırdı ve bir sahiplik denemesi yaptı; ikisi de fatura
geldikten sonra yapılır. Ay kapandığında hangi ekibin ne kadar harcadığı bilinir ve harcama
çoktan yapılmıştır.

Bu dersin sorusu ay içindedir: harcama beklenmedik biçimde yükseldiğinde bunun **kaçıncı gün**
fark edildiği ve yükselişin hiç fark edilmeden bitip bitmediği sayılır.

#### Harcama Eğrisi ve İki Uyarı

Örnek kurgu **bölgesel ölçüm ağı**dır: beş ekip, üç ortam, kiralanmış makine, ağ, depo, işlev ve
kenar katmanı. Eğri, bütçe ve olaylar kurgudur; **para birimi de kurgudur** ve `br` diye anılır,
gerçek bir fiyat listesine karşılık gelmez.

**BM13:** aylık bütçe 1.500 birimdir ve üç ay izlenir. **BM14:** eğri bir tabandan, haftalık bir
desenden, yavaş bir büyümeden ve gürültüden oluşur; büyüme yüzünden **olaysız taban da** bütçeye
yaklaşır. **BM15:** eğriye beş artış yerleştirilir; dördü başladığı ayda biter. **BM16:** eşik
uyarısı ay birikiminin bütçeye oranına bakar, tahmin uyarısı son *k* günün ortalamasıyla ay
sonunu öngörür. **BM17:** koşulun doğru olduğu her gün bir **uyarı günüdür**; artış sürerken
gelen uyarı fark etme, artışsız günde gelen uyarı **yanlış alarmdır**. **BM18:** fatura gecikmeli
gelir — *g*. günün kararı *g*−gecikme verisiyle alınır, yani koşul tam olarak gecikme kadar kayar.

Eğri, bütçe ve uyarılar süreç içi bir **modeldir**; gerçek bir harcama kaydı yoktur.

```js
// maliyet/harcama.mjs — gunluk harcama egrisi modeli: gercek bir harcama kaydi yok. Egri bir
// tabandan, haftalik desenden, yavas buyumeden ve elle yerlestirilmis *olaylardan* olusur;
// gurultu bir uretecten gelir, tohum gorunurdur, para birimi kurgudur ve `br` diye anilir.
// Olaysiz taban ayrica hesaplanir: bir olayin *fazla* harcamasi ikisinin farkidir.

export const TOHUM = 3391;
export const AY = 3, AY_GUN = 30, GUN = AY * AY_GUN;
export const BUTCE = 1500;                       // aylik butce (br, kurgu)
export const TABAN = 43, BUYUME = 0.12;          // gunluk taban ve gunluk yavas buyume
export const HAFTA = [1.08, 1.10, 1.06, 1.04, 0.98, 0.72, 0.68];

// olay: ad, baslangic gunu (1..90), sure (gun), gunluk fazla br
export const OLAY = [
  ["gelistirme ortami acik kaldi", 9, 22, 12.5],
  ["gecici veri kopyasi", 38, 6, 41.0],
  ["yanlis boyut secimi", 47, 40, 9.0],
  ["kenar dugumu cogaltma", 63, 25, 7.5],
  ["yeniden isleme dongusu", 71, 4, 63.0],
];

export const aktif = (g) => OLAY.filter(([, b, s]) => g >= b && g < b + s);

export const seri = (olayli = true) => {
  let s = TOHUM >>> 0;
  const r = () => { s = (Math.imul(s, 1664525) + 1013904223) >>> 0; return s / 4294967296; };
  const v = [0];
  for (let g = 1; g <= GUN; g++) {
    const gurultu = 0.94 + r() * 0.12;
    let x = (TABAN + BUYUME * (g - 1)) * HAFTA[(g - 1) % 7] * gurultu;
    if (olayli) for (const [, , , f] of aktif(g)) x += f;
    v.push(Math.round(x * 100) / 100);
  }
  return v;
};

export const ay = (g) => Math.floor((g - 1) / AY_GUN);
export const ayGunu = (g) => ((g - 1) % AY_GUN) + 1;
export const topla = (v) => v.reduce((a, b) => a + b, 0);
```

```js
// maliyet/uyari.mjs — iki uyari turu ayni egri uzerinde kosar: esik uyarisi (butcenin yuzdesi)
// ve tahmin uyarisi (ay sonu ongorusu). Sayilan sey uyarinin dogrulugu degil *fark etme
// gunudur*: olay basladiktan kac gun sonra uyari geliyor, o gunlerde ne kadar fazla harcaniyor.
// Fatura gecikmesi bir kisittir: g. gunun karari g-GECIKME verisiyle alinir, yani kosul tam
// olarak GECIKME gun kayar. Kosulun dogru oldugu her gun bir *uyari gunudur*.
import { OLAY, BUTCE, AY, AY_GUN, GUN, TOHUM, aktif, seri, ay, ayGunu,
  topla } from "./harcama.mjs";

const yaz = (g, ...s) => console.log(s.map((v, i) =>
  (g[i] < 0 ? String(v).padEnd(-g[i]) : String(v).padStart(g[i]))).join(""));
const t0 = process.hrtime.bigint();

const E = seri(), T = seri(false);
const fazla = (g) => E[g] - T[g];
const ayTop = (v, a) => topla(v.slice(a * AY_GUN + 1, (a + 1) * AY_GUN + 1));
const birikim = (a, g) => topla(E.slice(a * AY_GUN + 1, a * AY_GUN + g + 1));

console.log(`tohum ${TOHUM}: ${GUN} gun, aylik butce ${BUTCE} br (kurgu para birimi)`);

console.log("\n1. harcama egrisi: butce, gerceklesen, asim");
const A = [5, 10, 14, 11, 10, 13];
yaz(A, "ay", "butce", "gerceklesen", "asim", "olaysiz", "olay fazlasi");
for (let a = 0; a < AY; a++) {
  const ger = ayTop(E, a), tab = ayTop(T, a);
  yaz(A, a + 1, BUTCE, ger.toFixed(1), (ger - BUTCE).toFixed(1), tab.toFixed(1),
    (ger - tab).toFixed(1));
}
const kisa = OLAY.filter(([, b, s2]) => ay(b) === ay(b + s2 - 1)).length;
console.log(`  ${OLAY.length} olay yerlestirildi (yukaridaki modelde); ${kisa} tanesi ` +
  `basladigi ayda biter`);

// bir uyari turunu egri uzerinde kostur; donen sey tetiklenen gunlerin listesi
const kostur = (tur, p, gecikme) => {
  const gunler = [];
  for (let g = 1; g <= GUN; g++) {
    const v = g - gecikme;                       // faturadan okunabilen son gun
    if (v < 1) continue;
    const a = ay(v), d = ayGunu(v);
    if (ay(g) !== a) continue;                   // ay siniri: karar ayin kendi verisiyle
    const bir = birikim(a, d);
    let tetik = false;
    if (tur === "esik") tetik = bir / BUTCE >= p;
    else {
      if (d < p) continue;
      const ort = topla(E.slice(a * AY_GUN + d - p + 1, a * AY_GUN + d + 1)) / p;
      tetik = bir + ort * (AY_GUN - d) > BUTCE;
    }
    if (tetik) gunler.push(g);
  }
  return gunler;
};

// uyari gunlerini olaylara esle: fark etme gunu, gecikme, gecikmede harcanan fazla
const olc = (gunler) => {
  const bulunan = OLAY.map(([, b, s]) => {
    const g = gunler.find((x) => x >= b && x < b + s);
    return g === undefined ? null : g;
  });
  const yanlis = gunler.filter((g) => aktif(g).length === 0).length;
  const kacan = OLAY.filter((_, i) => bulunan[i] === null).length;
  const gecikmeler = bulunan.map((g, i) => (g === null ? null : g - OLAY[i][1]));
  const kacirilan = topla(OLAY.map(([, b, s], i) => {
    const son = bulunan[i] === null ? b + s : bulunan[i];
    let x = 0; for (let g = b; g < son; g++) x += fazla(g); return x;
  }));
  const gec = gecikmeler.filter((x) => x !== null);
  return { bulunan, gecikmeler, yanlis, kacan, kacirilan, toplam: gunler.length,
    ortGecikme: gec.length ? topla(gec) / gec.length : NaN };
};

console.log("\n2. iki uyari turu, ayni egri (esik %85, tahmin penceresi 7 gun, gecikme 0)");
const es = kostur("esik", 0.85, 0), ta = kostur("tahmin", 7, 0);
const oE = olc(es), oT = olc(ta);
const C = [-30, 8, 11, 10, 13, 10];
yaz(C, "olay", "baslar", "esik gunu", "gecikme", "tahmin gunu", "gecikme");
for (let i = 0; i < OLAY.length; i++) {
  const g = (x) => (x === null ? "kacti" : x);
  yaz(C, OLAY[i][0], OLAY[i][1], g(oE.bulunan[i]), g(oE.gecikmeler[i]),
    g(oT.bulunan[i]), g(oT.gecikmeler[i]));
}
// uyari geldigi gun butcenin ne kadari harcanmis: her ayin ilk uyari gunu
const kalan = (gunler) => {
  const ilk = [];
  for (let a = 0; a < AY; a++) {
    const g = gunler.find((x) => ay(x) === a);
    if (g !== undefined) ilk.push(birikim(a, ayGunu(g)) / BUTCE);
  }
  return topla(ilk) / ilk.length;
};
for (const [ad, o, g] of [["esik", oE, es], ["tahmin", oT, ta]]) {
  console.log(`  ${ad.padEnd(7)} ${o.toplam} uyari gunu, ${OLAY.length - o.kacan} olay ` +
    `yakalandi, ${o.kacan} kacti, ${o.yanlis} yanlis alarm gunu`);
  console.log(`  ${" ".repeat(7)} gecikmede ${o.kacirilan.toFixed(1)} br fazla; ilk uyari ` +
    `gunu butcenin %${(100 * kalan(g)).toFixed(1)}'i harcanmis, kalan ` +
    `${(BUTCE * (1 - kalan(g))).toFixed(0)} br`);
}

console.log("\n3. parametre taramasi: uyari ne kadar erken, kac yanlis alarm");
const D = [-9, 9, 12, 10, 8, 14, 8, 14];
yaz(D, "tur", "ayar", "uyari gunu", "yakalanan", "kacan", "ort. gecikme", "yanlis",
  "kacirilan br");
const ayarlar = [["esik", 0.60], ["esik", 0.85], ["esik", 1.00],
  ["tahmin", 3], ["tahmin", 7], ["tahmin", 14]];
const skor = [];
for (const [tur, p] of ayarlar) {
  const o = olc(kostur(tur, p, 0));
  skor.push([tur, p, o]);
  yaz(D, tur, tur === "esik" ? `%${(100 * p).toFixed(0)}` : `${p} gun`, o.toplam,
    OLAY.length - o.kacan, o.kacan, isNaN(o.ortGecikme) ? "-" : o.ortGecikme.toFixed(1),
    o.yanlis, o.kacirilan.toFixed(1));
}
const enIyi = skor.reduce((a, b) => (b[2].kacirilan < a[2].kacirilan ? b : a));
console.log(`  en az kaciran ayar: ${enIyi[0]} ${enIyi[1]}, ` +
  `${enIyi[2].kacirilan.toFixed(1)} br, ${enIyi[2].yanlis} yanlis alarm gunu`);
const olaysiz = [...Array(GUN)].map((_, i) => i + 1).filter((g) => aktif(g).length === 0).length;
console.log(`  olaysiz gun ${olaysiz}/${GUN}: yanlis alarm ancak bu gunlerde olabilir`);
console.log(`  ${enIyi[0]} ${enIyi[1]} uyariyi ${GUN} gunun ${enIyi[2].toplam} gununde ` +
  `(%${(100 * enIyi[2].toplam / GUN).toFixed(0)}) acik tutuyor`);

console.log("\n4. faturanin gecikmesi bir kisit: karar g-gecikme verisiyle alinir");
const F = [9, 12, 8, 14, 14, 13];
yaz(F, "gecikme", "uyari gunu", "kacan", "ort. gecikme", "kacirilan br", "butceye pay");
for (const gk of [0, 1, 3, 5, 8]) {
  const o = olc(kostur(enIyi[0], enIyi[1], gk));
  yaz(F, `${gk} gun`, o.toplam, o.kacan, isNaN(o.ortGecikme) ? "-" : o.ortGecikme.toFixed(1),
    o.kacirilan.toFixed(1), `%${(100 * o.kacirilan / (AY * BUTCE)).toFixed(1)}`);
}
const g0 = olc(kostur(enIyi[0], enIyi[1], 0)), g3 = olc(kostur(enIyi[0], enIyi[1], 3));
console.log(`  3 gunluk gecikme fark etme gunune ${(g3.ortGecikme - g0.ortGecikme).toFixed(1)} ` +
  `gun ekliyor ve kacirilan tutari ${(g3.kacirilan - g0.kacirilan).toFixed(1)} br buyutuyor`);

const ms = Number(process.hrtime.bigint() - t0) / 1e6;   // ham olcum basilmaz, bant denetlenir
console.log(`\ndort tablo 2000 ms bandinda: ${ms < 2000 ? "evet" : "hayir"}`);
```

```
tohum 3391: 90 gun, aylik butce 1500 br (kurgu para birimi)

1. harcama egrisi: butce, gerceklesen, asim
   ay     butce   gerceklesen       asim   olaysiz olay fazlasi
    1      1500        1553.7       53.7    1278.7        275.0
    2      1500        1752.8      252.8    1380.8        372.0
    3      1500        2137.0      637.0    1463.5        673.5
  5 olay yerlestirildi (yukaridaki modelde); 4 tanesi basladigi ayda biter

2. iki uyari turu, ayni egri (esik %85, tahmin penceresi 7 gun, gecikme 0)
olay                            baslar  esik gunu   gecikme  tahmin gunu   gecikme
gelistirme ortami acik kaldi         9         25        16           15         6
gecici veri kopyasi                 38      kacti     kacti           38         0
yanlis boyut secimi                 47         52         5           47         0
kenar dugumu cogaltma               63         77        14           67         4
yeniden isleme dongusu              71      kacti     kacti           71         0
  esik    29 uyari gunu, 3 olay yakalandi, 2 kacti, 3 yanlis alarm gunu
          gecikmede 1292.0 br fazla; ilk uyari gunu butcenin %86.4'i harcanmis, kalan 204 br
  tahmin  63 uyari gunu, 5 olay yakalandi, 0 kacti, 6 yanlis alarm gunu
          gecikmede 141.0 br fazla; ilk uyari gunu butcenin %34.6'i harcanmis, kalan 982 br

3. parametre taramasi: uyari ne kadar erken, kac yanlis alarm
tur           ayar  uyari gunu yakalanan   kacan  ort. gecikme  yanlis  kacirilan br
esik           %60          46         4       1           5.5       5         821.0
esik           %85          29         3       2          11.7       3        1292.0
esik          %100          17         3       2          15.7       3        1440.0
tahmin       3 gun          68         5       0           0.2       6          12.5
tahmin       7 gun          63         5       0           2.0       6         141.0
tahmin      14 gun          47         4       1           5.8       6         967.5
  en az kaciran ayar: tahmin 3, 12.5 br, 6 yanlis alarm gunu
  olaysiz gun 21/90: yanlis alarm ancak bu gunlerde olabilir
  tahmin 3 uyariyi 90 gunun 68 gununde (%76) acik tutuyor

4. faturanin gecikmesi bir kisit: karar g-gecikme verisiyle alinir
  gecikme  uyari gunu   kacan  ort. gecikme  kacirilan br  butceye pay
    0 gun          68       0           0.2          12.5         %0.3
    1 gun          65       0           0.8          82.5         %1.8
    3 gun          59       0           2.0         222.5         %4.9
    5 gun          53       0           3.2         362.5         %8.1
    8 gun          44       1           4.3         490.5        %10.9
  3 gunluk gecikme fark etme gunune 1.8 gun ekliyor ve kacirilan tutari 210.0 br buyutuyor

dort tablo 2000 ms bandinda: evet
```

Sayılar **ölçüm** sınıfındadır; girdileri yukarıdaki varsayımlardır.

#### Eşik Uyarısı Bütçeyi Bekliyor

Birinci tablo üç ayın da aşıldığını gösterir: 53,7 — 252,8 — 637,0 birim. Kaynağı yalnız artışlar
değildir; olaysız taban 1.278,7'den 1.463,5'e tırmanır ve üçüncü ayda bütçenin **%97,6'sını**
doldurur.

İkinci tablo eşik uyarısını %85'te koşturur. İki artış **tamamen kaçar**: geçici veri kopyası (6
gün, günlük 41 birim) ve yeniden işleme döngüsü (4 gün, günlük 63 birim). İkisi de kısa ve
büyüktür, ama birikimi eşiğin üstüne taşımadan biter. Uzun ve küçük olanlar 16 ve 14 gün sonra
fark edilir; toplam kaçırılan **1.292 birim**.

Nedeni ölçünün kendisindedir: eşik uyarısı artışa değil **birikime** bakar. İlk tetiklendiği gün
bütçenin ortalama **%86,4'ü** harcanmıştır, kalan **204 birimdir** — bu bir uyarı değil, bir kalan
bildirimidir. Eşik %60'a indirildiğinde bile kaçırılan 821 birimdir ve kısa artışlardan biri hâlâ
kaçar.

#### Tahmin Uyarısı Erken ama Sürekli

Tahmin uyarısı yedi günlük pencerede beş artışın **beşini de** yakalar. İki kısa artışı başladığı
gün (38 ve 71) fark eder, çünkü son yedi günün ortalaması bir günde sıçrar ve ay sonu öngörüsü
bütçeyi aşar. Kaçırılan tutar 1.292'den **141 birime** iner ve ilk uyarı geldiğinde bütçenin
yalnız **%34,6'sı** harcanmıştır — kalan 982 birim.

Üçüncü tablo bedelini gösterir. Pencere üç güne indirildiğinde kaçırılan tutar **12,5 birime**
düşer, ama uyarı 90 günün **68'inde (%76)** açık kalır. Yanlış alarm bunu açıklamaz: 21 artışsız
günün 6'sında yanlış alarm vardır, eşik %60'ta 5'inde. İki ailenin ayrıldığı yer yanlış alarm
değil **doğru alarmın süresidir**; tahmin uyarısı artış sürdükçe bağırır ve ayırt edici olmaktan
çıkar, eşik uyarısı sessizdir ama geç konuşur.

Pencere on dörde çıkarıldığında tahmin uyarısı eşiğe benzer: bir artış kaçar, kaçırılan 967,5
birime çıkar.

#### Faturanın Gecikmesi Bir Tavan Koyuyor

Dördüncü tablo tek bir kısıtı ekler: fatura verisi gecikmeli gelir. Uyarı koşulu tam olarak
gecikme kadar kaydığı için fark etme günü de aynı miktarda kayar. Ortalama gecikme 0,2 günden
1 günde 0,8'e, 3 günde 2,0'a, 8 günde 4,3'e çıkar.

Kaçırılan tutar buna doğrusal eşlik eder: 12,5 — 82,5 — 222,5 — 362,5 — 490,5 birim. Sekiz günlük
gecikmede dört günlük yeniden işleme döngüsü **veri görünmeden biter** ve tamamen kaçar; üç aylık
bütçenin **%10,9'u** fark edilmeden harcanır.

Bu bir tavandır: uyarı ayarı ne kadar iyileştirilirse iyileştirilsin, fark etme günü fatura
gecikmesinin altına inemez. Gecikme ayrı bir kalem de üretmez — bütçeden düşen tutar aynıdır,
yalnız uyarı gelmeden önce harcanmıştır.

#### Özet

- Üç ayın üçü de aşılır (53,7 — 252,8 — 637,0 birim); aşımın bir kısmı artıştan değil taban
  büyümesinden gelir — olaysız taban üçüncü ayda bütçenin %97,6'sını doldurur.
- **Eşik uyarısı birikime bakar, artışa değil**: %85 eşiğinde iki kısa artış tamamen kaçar ve ilk
  tetiklendiğinde bütçenin %86,4'ü harcanmıştır — kalan 204 birim. Kaçırılan toplam 1.292 birim.
- Tahmin uyarısı yedi günlük pencerede beş artışın beşini yakalar ve kaçırılanı 141 birime
  indirir; ilk uyarı geldiğinde bütçeden **982 birim** kalmıştır.
- Erken fark etmenin bedeli yanlış alarm değil süredir: üç günlük pencere kaçırılanı 12,5 birime
  indirirken uyarıyı 90 günün 68'inde (%76) açık tutar; yanlış alarm 21 artışsız günün 6'sındadır,
  eşik %60'ta 5'indedir.
- **Fatura gecikmesi fark etme gününe doğrudan eklenir**: 3 günlük gecikme ortalamaya 1,8 gün ve
  kaçırılana 210 birim ekler; 8 günlük gecikmede dört günlük bir artış hiç görülmez ve üç aylık
  bütçenin %10,9'u fark edilmeden harcanır.

#### Sonraki Adım

Uyarı, harcamanın beklenmedik biçimde yükseldiğini söyler; beklenen harcama hakkında hiçbir şey
söylemez. Taban her ay bütçeye biraz daha yaklaşırken hiçbir uyarı tetiklenmez, çünkü ortada bir
olay yoktur — yalnızca gereğinden büyük kurulmuş kaynaklar vardır. Sıradaki ders o tabana bakar:
kullanım geçmişinden küçültme adayları çıkarılır ve her adayın tasarrufu ile riski birlikte
sayılır.

### Kaynak Boyutlandırma

Source: https://academia.sh/tr/kurslar/bulut-yonetisimi/kaynak-boyutlandirma

Aşırı sağlamanın fatura tarafı ölçülür: kurgu ağın on kaynağında p95 doluluk ortalaması %31,4'tür ve p95 üzerine %20 pay bırakan küçültme aylık 875 kurgu birimin 401'ini (%45,8) vaat eder. Tasarrufun 353 birimi (%88,0) kesinti gerektirir, yedi adayda geçmiş tepe yeni kademeyi aşar ve en kötü anda %168,4 eksik kalır; hem kesintisiz hem risksiz olan pay yalnızca 10 birimdir. Güvenlik payı %0'dan %100'e çıkarıldığında tasarruf 458'den 64 birime, yetmeyen saat 47'den 3'e iner. Hiçbir kullanım raporunda görünmeyen 147,2 birimlik boşta kaynak ise kesintisiz silinir ve tek başına küçültme tasarrufunun %37'sini verir.

Önceki ders uyarıların beklenmedik artışları yakaladığını, beklenen harcamayı sorgulamadığını
ölçtü: taban bütçeye yaklaşırken hiçbir uyarı tetiklenmez, çünkü ortada olay değil gereğinden
büyük kurulmuş kaynaklar vardır.

Örnek boyutlandırma M23/K02'de ölçüldü ve tekrarlanmaz. Bu dersin ekseni **fatura tarafıdır**:
kullanım geçmişinden hangi kaynağın küçültülebileceği çıkarılır ve her adayın **tasarrufu ile
riski aynı satırda** sayılır.

#### Kullanım Geçmişi ve Boyut Merdiveni

Örnek kurgu **bölgesel ölçüm ağı**dır: beş ekip, üç ortam, kiralanmış makine, ağ, depo, işlev ve
kenar katmanı. Kaynaklar, kademeler ve tutarlar kurgudur; **para birimi de kurgudur** ve `br` diye
anılır, gerçek bir fiyat listesine karşılık gelmez.

**BM19:** on kaynak ve beş tür vardır; her türün bir **boyut merdiveni** vardır, her kademe bir
kapasite birimi ile bir aylık bedelden oluşur. **BM20:** kullanım geçmişi 30 gün × 24 saattir;
günlük desen, hafta sonu düşüşü, gürültü ve seyrek tepelerden oluşur. **BM21:** küçültme adayı,
p95 talebine bir **güvenlik payı** eklendikten sonra yeten en küçük kademedir. **BM22:** risk iki
sayıyla ölçülür — yeni kademe geçmişte kaç saat yetmezdi ve **en kötü anda ne kadar eksik**
kalırdı. **BM23:** kademe indirmenin kesinti gerektirip gerektirmediği türe bağlıdır. **BM24:**
boşta kaynağın kullanım oranı tanımsızdır; hiçbir doluluk raporunda görünmez.

Merdiven, geçmiş ve adaylar süreç içi bir **modeldir**; gerçek bir ölçüm kaydı yoktur.

```js
// maliyet/kapasite.mjs — boyut merdiveni ve kullanim gecmisi modeli: gercek bir kayit yok.
// Kademeler [kapasite birimi, aylik br] ciftidir; 30 gun x 24 saatlik gecmis bir uretecten
// turer, tohum gorunurdur, para birimi kurgudur ve `br` diye anilir. Ornek boyutlandirma
// M23/K02'de olculdu; burada olculen sey kademeyi indirmenin tasarrufu ve riskidir.

export const TOHUM = 8814;
export const GUN = 30, SAAT = GUN * 24;

export const MERDIVEN = {
  "kiralanmis makine": [[1, 14], [2, 27], [4, 52], [8, 101], [16, 198]],
  "blok depo":         [[100, 7], [250, 17], [500, 33], [1000, 64], [2000, 126]],
  "islev bellek":      [[1, 3], [2, 6], [4, 11], [8, 21]],
  "ag gecidi":         [[1, 22], [2, 41], [4, 79]],
  "kenar dugumu":      [[1, 9], [2, 17], [4, 32]],
};

// kademeyi indirmek kesinti gerektiriyor mu, gerekiyorsa neden
export const KESINTI = {
  "kiralanmis makine": ["evet", "yeniden baslat"],
  "blok depo":         ["evet", "veri tasima"],
  "islev bellek":      ["hayir", "sonraki cagri"],
  "ag gecidi":         ["hayir", "kademe gecisi"],
  "kenar dugumu":      ["evet", "dugum degisimi"],
};

// ad, tur, mevcut kademe indisi, ekip, taban talep, tepe carpani, tepe olasiligi
export const KAYNAK = [
  ["olcum-alici-1",  "kiralanmis makine", 3, "sayac-okuma", 2.10, 2.1, 0.012],
  ["olcum-alici-2",  "kiralanmis makine", 3, "sayac-okuma", 3.40, 1.6, 0.020],
  ["dogrulayici",    "kiralanmis makine", 2, "dogrulama",   1.15, 2.4, 0.008],
  ["fatura-hazirla", "kiralanmis makine", 4, "faturalama",  4.20, 2.8, 0.006],
  ["rapor-motoru",   "kiralanmis makine", 3, "raporlama",   1.05, 5.2, 0.004],
  ["ham-olcum-diski","blok depo",         3, "sayac-okuma", 340,  1.1, 0.010],
  ["arsiv-diski",    "blok depo",         4, "raporlama",   610,  1.0, 0.000],
  ["olay-islevi",    "islev bellek",      3, "dogrulama",   1.80, 2.0, 0.015],
  ["kuzey-gecidi",   "ag gecidi",         2, "sayac-okuma", 1.30, 2.2, 0.011],
  ["saha-dugumu",    "kenar dugumu",      2, "saha",        0.75, 2.6, 0.007],
];

// hicbir kullanim olcusunde gorunmeyen kalemler: kullanim orani tanimsizdir
// ad, adet, birim aylik br, neden bosta, silmek kesinti gerektiriyor mu
export const BOSTA = [
  ["bagli olmayan blok depo", 4, 17, "makine silindi, depo kaldi", "hayir"],
  ["kullanilmayan sabit adres", 6, 4, "gecis bitti, adres birakilmadi", "hayir"],
  ["eski anlik goruntu", 23, 2.4, "saklama kurali yok", "hayir"],
];

const DESEN = [0.42, 0.38, 0.36, 0.35, 0.38, 0.48, 0.66, 0.84, 0.98, 1.06, 1.10, 1.12,
  1.08, 1.09, 1.11, 1.07, 1.00, 0.92, 0.84, 0.76, 0.68, 0.60, 0.52, 0.46];

export const gecmis = (k) => {
  const [, , , , taban, tepe, p] = k;
  let s = (TOHUM + k[0].length * 7919) >>> 0;
  const r = () => { s = (Math.imul(s, 1664525) + 1013904223) >>> 0; return s / 4294967296; };
  const v = [];
  for (let t = 0; t < SAAT; t++) {
    const hafta = (Math.floor(t / 24) % 7) >= 5 ? 0.74 : 1.0;
    let x = taban * DESEN[t % 24] * hafta * (0.92 + r() * 0.16);
    if (r() < p) x *= tepe;
    v.push(x);
  }
  return v;
};

export const yuzdelik = (v, q) => {
  const s = [...v].sort((a, b) => a - b);
  return s[Math.min(s.length - 1, Math.floor(q * s.length))];
};
export const topla = (v) => v.reduce((a, b) => a + b, 0);
```

```js
// maliyet/olcek.mjs — kullanim gecmisinden kucultme adaylari cikarilir ve her adayin *tasarrufu
// ile riski birlikte* sayilir: onerilen kademe gecmiste kac saat yetmezdi, en kotu anda ne
// kadar eksik kalirdi. Kesinti gerektirenler ayrilir, bosta kaynak ayrica sayilir.
import { KAYNAK, MERDIVEN, KESINTI, BOSTA, SAAT, TOHUM, gecmis, yuzdelik,
  topla } from "./kapasite.mjs";

const yaz = (g, ...s) => console.log(s.map((v, i) =>
  (g[i] < 0 ? String(v).padEnd(-g[i]) : String(v).padStart(g[i]))).join(""));
const t0 = process.hrtime.bigint();

const G = KAYNAK.map(gecmis);
const kap = (t, i) => MERDIVEN[t][i][0], brOf = (t, i) => MERDIVEN[t][i][1];
const T = topla(KAYNAK.map((k) => brOf(k[1], k[2])));
const BOS = topla(BOSTA.map(([, n, b]) => n * b));
console.log(`tohum ${TOHUM}: ${KAYNAK.length} kaynak, ${SAAT} saat gecmis, ` +
  `aylik ${T} br + bosta ${BOS.toFixed(1)} br (kurgu para birimi)`);

console.log("\n1. kullanim gecmisi: mevcut kademe ne kadar dolu");
const A = [-17, -19, 10, 10, 9, 9, 10];
yaz(A, "kaynak", "tur", "kapasite", "aylik br", "p95", "tepe", "p95 dolu");
for (let i = 0; i < KAYNAK.length; i++) {
  const k = KAYNAK[i], c = kap(k[1], k[2]), v = G[i];
  yaz(A, k[0], k[1], c, brOf(k[1], k[2]), yuzdelik(v, 0.95).toFixed(2),
    Math.max(...v).toFixed(2), `%${(100 * yuzdelik(v, 0.95) / c).toFixed(0)}`);
}
const dolu = KAYNAK.map((k, i) => yuzdelik(G[i], 0.95) / kap(k[1], k[2]));
console.log(`  p95 doluluk ortalamasi %${(100 * topla(dolu) / dolu.length).toFixed(1)}; ` +
  `%50'nin altinda ${dolu.filter((x) => x < 0.5).length} kaynak`);

// pay: p95 uzerine eklenen guvenlik payi. Onerilen kademe = yeten en kucuk kademe.
const aday = (pay) => KAYNAK.map((k, i) => {
  const [ad, tur, mev] = k, v = G[i], hedef = yuzdelik(v, 0.95) * (1 + pay);
  let yeni = mev;
  for (let j = 0; j < MERDIVEN[tur].length; j++)
    if (MERDIVEN[tur][j][0] >= hedef) { yeni = Math.min(mev, j); break; }
  const c = kap(tur, yeni);
  const yetmez = v.filter((x) => x > c).length;
  const eksik = Math.max(0, (Math.max(...v) - c) / c);
  return { ad, tur, mev, yeni, tasarruf: brOf(tur, mev) - brOf(tur, yeni), yetmez, eksik,
    inis: mev - yeni, kalan: yeni };
});

console.log("\n2. kucultme adaylari (p95 + %20 guvenlik payi): tasarruf ve risk birlikte");
const B = [-16, 9, 8, 7, 9, 11, 10, 22];
yaz(B, "kaynak", "kademe", "yeni", "inis", "tasarruf", "yetmez sa.", "en kotu", "kesinti");
const AD = aday(0.20);
let tKes = 0, tKessiz = 0;
for (const a of AD) {
  if (a.inis === 0) continue;
  const [kes, neden] = KESINTI[a.tur];
  if (kes === "evet") tKes += a.tasarruf; else tKessiz += a.tasarruf;
  yaz(B, a.ad, kap(a.tur, a.mev), kap(a.tur, a.yeni), a.inis, a.tasarruf,
    a.yetmez, `%${(100 * a.eksik).toFixed(1)}`, `${kes} (${neden})`);
}
const inen = AD.filter((a) => a.inis > 0);
const tt = topla(AD.map((a) => a.tasarruf));
console.log(`  ${inen.length}/${KAYNAK.length} kaynak aday, tasarruf ${tt} br/ay ` +
  `(%${(100 * tt / T).toFixed(1)})`);
console.log(`  kesinti gerektiren ${tKes} br (%${(100 * tKes / tt).toFixed(1)}), ` +
  `kesintisiz ${tKessiz} br`);
const riskli = AD.filter((a) => a.inis > 0 && a.yetmez > 0);
console.log(`  ${riskli.length} adayda gecmis tepe yeni kademeyi asiyor: toplam ` +
  `${topla(riskli.map((a) => a.yetmez))} saat, en kotu eksik ` +
  `%${(100 * Math.max(...AD.map((a) => a.eksik))).toFixed(1)}`);
console.log(`  merdivende kalan inis: ${topla(inen.map((a) => a.kalan))} kademe, ` +
  `${inen.filter((a) => a.kalan === 0).length} kaynak en alt kademede`);

console.log("\n3. guvenlik payi taramasi: tasarruf ile yetmeyen saat birlikte hareket ediyor");
const C = [8, 8, 11, 9, 12, 12, 11];
yaz(C, "pay", "aday", "tasarruf", "pay %", "yetmez sa.", "saat payi", "en kotu");
for (const p of [0, 0.20, 0.35, 0.60, 1.00]) {
  const a = aday(p), i2 = a.filter((x) => x.inis > 0), s = topla(a.map((x) => x.tasarruf));
  const y = topla(a.map((x) => x.yetmez)), e = Math.max(...a.map((x) => x.eksik));
  yaz(C, `%${(100 * p).toFixed(0)}`, i2.length, s, `%${(100 * s / T).toFixed(1)}`, y,
    `%${(100 * y / (SAAT * KAYNAK.length)).toFixed(2)}`, `%${(100 * e).toFixed(1)}`);
}
console.log(`  yetmeyen saat butun taramada ${SAAT} x ${KAYNAK.length} saatin %1'inin`);
console.log(`  altinda kalir: belirleyici olan sayi degil, en kotu andaki eksiktir`);

console.log("\n4. bosta kaynak: hicbir kullanim orani raporunda gorunmez");
const D = [-26, 6, 10, 11, 32, 8];
yaz(D, "kalem", "adet", "birim br", "aylik br", "neden bosta", "kesinti");
for (const [ad, n, b, neden, kes] of BOSTA)
  yaz(D, ad, n, b, (n * b).toFixed(1), neden, kes);
yaz(D, "toplam", topla(BOSTA.map((x) => x[1])), "-", BOS.toFixed(1), "-", "hayir");
console.log(`  bosta ${BOS.toFixed(1)} br/ay, kullanilan faturanin ` +
  `%${(100 * BOS / T).toFixed(1)}'i; tamami kesintisiz silinir`);
console.log(`  ve ${tt} br'lik kucultme tasarrufunun ` +
  `%${(100 * BOS / tt).toFixed(0)}'ini tek basina verir`);

const ms = Number(process.hrtime.bigint() - t0) / 1e6;   // ham olcum basilmaz, bant denetlenir
console.log(`\ndort tablo 2000 ms bandinda: ${ms < 2000 ? "evet" : "hayir"}`);
```

```
tohum 8814: 10 kaynak, 720 saat gecmis, aylik 875 br + bosta 147.2 br (kurgu para birimi)

1. kullanim gecmisi: mevcut kademe ne kadar dolu
kaynak           tur                  kapasite  aylik br      p95     tepe  p95 dolu
olcum-alici-1    kiralanmis makine           8       101     2.42     5.13       %30
olcum-alici-2    kiralanmis makine           8       101     3.92     6.33       %49
dogrulayici      kiralanmis makine           4        52     1.31     3.15       %33
fatura-hazirla   kiralanmis makine          16       198     4.78    13.85       %30
rapor-motoru     kiralanmis makine           8       101     1.19     5.37       %15
ham-olcum-diski  blok depo                1000        64   387.62   438.71       %39
arsiv-diski      blok depo                2000       126   694.29   737.55       %35
olay-islevi      islev bellek                8        21     2.06     4.11       %26
kuzey-gecidi     ag gecidi                   4        79     1.48     2.81       %37
saha-dugumu      kenar dugumu                4        32     0.86     2.23       %21
  p95 doluluk ortalamasi %31.4; %50'nin altinda 10 kaynak

2. kucultme adaylari (p95 + %20 guvenlik payi): tasarruf ve risk birlikte
kaynak             kademe    yeni   inis tasarruf yetmez sa.   en kotu               kesinti
olcum-alici-1           8       4      1       49          6     %28.3 evet (yeniden baslat)
dogrulayici             4       2      1       25          3     %57.5 evet (yeniden baslat)
fatura-hazirla         16       8      1       97          5     %73.1 evet (yeniden baslat)
rapor-motoru            8       2      2       74          2    %168.4 evet (yeniden baslat)
ham-olcum-diski      1000     500      1       31          0      %0.0    evet (veri tasima)
arsiv-diski          2000    1000      1       62          0      %0.0    evet (veri tasima)
olay-islevi             8       4      1       10          1      %2.7 hayir (sonraki cagri)
kuzey-gecidi            4       2      1       38          1     %40.6 hayir (kademe gecisi)
saha-dugumu             4       2      1       15          2     %11.3 evet (dugum degisimi)
  9/10 kaynak aday, tasarruf 401 br/ay (%45.8)
  kesinti gerektiren 353 br (%88.0), kesintisiz 48 br
  7 adayda gecmis tepe yeni kademeyi asiyor: toplam 20 saat, en kotu eksik %168.4
  merdivende kalan inis: 16 kademe, 0 kaynak en alt kademede

3. guvenlik payi taramasi: tasarruf ile yetmeyen saat birlikte hareket ediyor
     pay    aday   tasarruf    pay %  yetmez sa.   saat payi    en kotu
      %0      10        458    %52.3          47       %0.65     %168.4
     %20       9        401    %45.8          20       %0.28     %168.4
     %35       8        370    %42.3          20       %0.28     %168.4
     %60       5        245    %28.0          16       %0.22     %168.4
    %100       2         64     %7.3           3       %0.04      %34.2
  yetmeyen saat butun taramada 720 x 10 saatin %1'inin
  altinda kalir: belirleyici olan sayi degil, en kotu andaki eksiktir

4. bosta kaynak: hicbir kullanim orani raporunda gorunmez
kalem                       adet  birim br   aylik br                     neden bosta kesinti
bagli olmayan blok depo        4        17       68.0      makine silindi, depo kaldi   hayir
kullanilmayan sabit adres      6         4       24.0  gecis bitti, adres birakilmadi   hayir
eski anlik goruntu            23       2.4       55.2              saklama kurali yok   hayir
toplam                        33         -      147.2                               -   hayir
  bosta 147.2 br/ay, kullanilan faturanin %16.8'i; tamami kesintisiz silinir
  ve 401 br'lik kucultme tasarrufunun %37'ini tek basina verir

dort tablo 2000 ms bandinda: evet
```

Sayılar **ölçüm** sınıfındadır; girdileri yukarıdaki varsayımlardır.

#### Doluluk Düşük, Tasarruf Büyük Görünüyor

Birinci tablo on kaynağın p95 talebini mevcut kapasiteye böler. Ortalama doluluk **%31,4** ve
**on kaynağın onu da** yarının altındadır. En uçtaki rapor motoru sekiz birimlik kademede oturur,
p95 talebi 1,19'dur — kapasitenin %15'i.

İkinci tablo bunu paraya çevirir. p95 üzerine %20 güvenlik payı bırakıldığında **dokuz kaynak
aday** olur ve aylık 875 birimlik faturadan **401 birim** düşer: **%45,8**. Tek istisna ölçüm
alıcı 2'dir: p95'i kapasitesinin yarısını doldurur ve bir alt kademe yetmez. Aynı satırın
sağındaki iki sütun bu sayıyı değiştirir.

#### Tasarrufun Yanında Duran İki Sayı

Birinci sütun **riski** sayar: yeni kademe geçmişte kaç saat yetmezdi. Yedi adayda bu sayı
sıfırdan büyüktür, toplamı 20 saattir — 7.200 saatlik geçmişin binde üçü. İkinci sayı bunu
önemsiz olmaktan çıkarır. **En kötü anda eksik kalan kapasite** rapor motorunda
**%168,4'tür**: iki birimlik yeni kademe, 5,37 birimlik tepenin karşısında yarıdan fazla açık
verir. Fatura hazırlama %73,1, doğrulayıcı %57,5 eksik kalır. Tepe anında hizmet kuyruğa girer ya da
reddedilir; ölçünün "iki saat" demesi bunu hafifletmez.

İkinci sütun **kesintiyi** kalem kalem yazar. Makine kademesi yeniden başlatma, blok depo veri
taşıma, kenar düğümü düğüm değişimi ister; kesintisiz inen yalnız işlev belleği ve ağ geçididir.
Tasarrufun **353 birimi (%88,0)** kesinti gerektirir, kesintisiz olan **48 birimdir**.

İki sütun birlikte okunduğunda tablo daralır. Kesintisiz 48 birimin 38'i ağ geçididir ve o
adayın en kötü eksiği **%40,6'dır**. Geriye hem kesintisiz hem kayda değer açık vermeyen tek
kalem kalır: olay işlevi, **10 birim** — 401 birimlik vaadin bedelsiz kısmı **%2,5**.

Diskler tersini gösterir: iki disk adayının riski tam olarak sıfırdır, ama 93 birimlik tasarrufu
veri taşıma kesintisi ister.

#### Güvenlik Payı Neyi Satın Alıyor

Üçüncü tablo payı tarar. Pay sıfırken tasarruf 458 birim (%52,3), yetmeyen saat 47'dir. Pay %20'de
yetmeyen saat 20'ye iner ve tasarruf yalnız 57 birim kaybeder: eğrinin en verimli yeri burasıdır.
Pay %60'ta tasarruf 245 birime düşer, yetmeyen saat ancak 16'ya iner — 156 birim ödenip 4 saat
kazanılır.

En kötü eksik ise **%100 paya kadar hiç değişmez** (%168,4), çünkü pay p95'e eklenir, tepeye
değil. Seyrek ve büyük tepesi olan kaynağın riski güvenlik payıyla satın alınamaz.

#### Hiç Dokunulmayan Kalem

Dördüncü tablo doluluk raporunun hiç göstermediği kalemi sayar. Bağlı olmayan dört blok depo,
kullanılmayan altı sabit adres ve saklama kuralı olmayan yirmi üç eski anlık görüntü aylık
**147,2 birim** tutar — kullanılan faturanın **%16,8'i**. Aday listesine hiç girmezler: kullanım
oranları tanımsızdır, bölünecek bir talep yoktur.

Karşılaştırma dersin sonucudur: 147,2 birimin tamamı **kesintisiz** silinir ve tepe riski
taşımaz, küçültmenin bedelsiz payı ise 10 birimdir. Boşta kaynak, küçültme tasarrufunun
**%37'sini** tek başına verir.

#### Özet

- On kaynağın **onu da** p95'te yarının altında doludur (ortalama %31,4, en düşüğü %15); p95 +
  %20 payla dokuz kaynak aday olur ve aylık 875 birimin **401'i (%45,8)** tasarruf görünür.
- Tasarrufun **353 birimi (%88,0) kesinti gerektirir**; kesintisiz 48 birimin 38'i en kötü anda
  %40,6 açık veren bir adaydır. Hem kesintisiz hem risksiz pay **10 birim, tasarrufun %2,5'idir**.
  Risk ve kesinti bağımsızdır: iki disk adayı hiç yetmezlik üretmez ama veri taşıma ister.
- Güvenlik payı yetmeyen saati satın alır, **en kötü eksiği satın alamaz**: pay %0'dan %100'e
  çıkarken tasarruf 458'den 64 birime iner ama en kötü eksik %168,4'te kalır — pay p95'e eklenir,
  tepeye değil.
- Boşta kaynak **147,2 birim (%16,8)** tutar ve hiçbir doluluk raporunda görünmez; kesintisiz
  silinir, küçültme tasarrufunun %37'sini tek başına verir.

#### Sonraki Adım

Bu dersin bütün sayıları aşağı yönlüdür: neyin küçültülebileceği, neyin silinebileceği. Büyüme
yönünde de bir sayı vardır ve faturada hiç görünmez. Sıradaki ders ölçek planını bir sınır
tablosuna uygular: hangi sınıra kaç birim kaldığı ve hangi sınırın önce dolduğu çıkarılır.

### Kota ve Servis Sınırları

Source: https://academia.sh/tr/kurslar/bulut-yonetisimi/kota-ve-servis-sinirlari

Ölçek planı kurgu bir sınır tablosuna uygulanır: sekiz sınırın ortalama doluluğu %66,5, altısı beş ekip tarafından paylaşılır ve ikisi hiç artırılamaz. Büyüme planı işletildiğinde ilk dolan sınır en dolu olan değil, en hızlı sürücüye bağlı olandır — 3,1. ayda ad çözümleme, 4,3. ayda işlev eş zamanlılığı; on iki ayın sonunda sekiz sınırın yedisi aşılır. İstek büyümesi %2'den %25'e tarandığında önce dolan sınırın kimliği değişir. Sınıra çarpmanın bedeli davranışa ve artırma süresine bağlıdır: toplam 2.195 kurgu birim ve 116 sınır-gün, bunun %51,7'si tek bir sessiz kısma sınırından gelir.

Önceki ders aşağı yönü ölçtü: neyin küçültülebileceği, neyin silinebileceği. Yukarı yönde de bir
sayı vardır ve faturada hiç görünmez. Kiralanan katmanın her kalemi bir tavanla gelir; o tavan
ödenen tutarla değil, sağlayıcının koyduğu **kotayla** belirlenir.

Kota mekaniğinin kendisi M22/K03'te ölçüldü ve burada tekrarlanmaz. Bu dersin sorusu ölçek
planına aittir: **hangi sınıra kaç birim kaldı**, büyüme sürdüğünde hangisi önce dolar ve
dolduğunda ne olur.

#### Sınır Tablosu ve Büyüme Planı

Örnek kurgu **bölgesel ölçüm ağı**dır: beş ekip, üç ortam, kiralanmış makine, ağ, depo, işlev ve
kenar katmanı. Sınırlar, büyüme oranları ve tutarlar kurgudur; **para birimi de kurgudur** ve
`br` diye anılır, gerçek bir fiyat listesine karşılık gelmez.

**BM25:** sekiz sınır vardır; her sınırın bir **kapsamı** (hesap, bölge, ağ, bölme) ve onu tüketen
bir **sürücüsü** vardır. **BM26:** kapsam, sınırın kaç ekip tarafından paylaşıldığını belirler.
**BM27:** büyüme planı sürücü bazındadır; her sürücünün aylık büyüme oranı ayrıdır. **BM28:** her
sınırın artırılabilir bir tavanı ve artırma isteğinin bir süresi vardır; tavan sınıra eşitse sınır
**artırılamaz**. **BM29:** sınıra çarpmanın davranışı dört türdür — oluşturma reddi, istek reddi,
kuyruk, sessiz kısma — ve **fark etme günü davranışa bağlıdır**. **BM30:** sınır doluyken günlük
bir kayıp oluşur; artırılamayan sınırda kayıp otuz gün, yani plan değişene kadar sürer.

Sınır tablosu ve büyüme planı süreç içi bir **modeldir**; gerçek bir sınır listesi yoktur.

```js
// maliyet/sinir.mjs — kota ve servis siniri tablosu modeli: gercek bir sinir listesi yok. Her
// satir bir sinir, onu tuketen bir *surucu* ve sinira carpildiginda ne oldugu ile birlikte
// tutulur. Kota mekanigi M22/K03'te olculdu; burada olculen sey buyume planinin bu tabloya
// uygulanmasidir. Para birimi kurgudur ve `br` diye anilir.

// ad, kapsam, surucu, mevcut kullanim, sinir, artirilabilir tavan, artirma gunu, davranis,
// sinir doluyken gunluk kayip (br)
export const SINIR = [
  ["bolge basina makine cekirdegi", "bolge", "sayac", 412, 640, 2000, 6, "olusturma reddi", 34],
  ["saniyede nesne yazma istegi", "bolme", "istek", 1850, 3500, 12000, 4, "istek reddi", 61],
  ["islev es zamanli calisma", "hesap", "istek", 640, 1000, 4000, 3, "kuyruk", 18],
  ["saniyede ad cozumleme", "ag", "istek", 7200, 10000, 10000, 0, "sessiz kisma", 27],
  ["hesap basina sabit adres", "hesap", "kenar", 34, 50, 200, 5, "olusturma reddi", 9],
  ["hesap basina sanal ag", "hesap", "ortam", 9, 12, 40, 7, "olusturma reddi", 4],
  ["bolme basina saklama kurali", "bolme", "veri", 62, 100, 100, 0, "olusturma reddi", 6],
  ["kural kumesi basina kural", "ag", "hizmet", 148, 200, 400, 9, "olusturma reddi", 12],
];

// buyume plani: her surucunun aylik buyume orani (kurgu)
export const BUYUME = { sayac: 0.06, istek: 0.11, veri: 0.09, kenar: 0.05, ortam: 0.02,
  hizmet: 0.04 };

// kapsam sinirin kac ekip tarafindan paylasildigini belirler: hesap, bolge ve ag kapsamli bir
// sinirda bir ekibin buyumesi otekilerin basligini tuketir
export const PAYLASAN = { hesap: 5, bolge: 5, ag: 5, bolme: 1 };

// sinira carpmanin davranisi: fark etme gunu ve neden o kadar surdugu
export const DAVRANIS = {
  "olusturma reddi": [1, "istek aninda hata doner"],
  "istek reddi":     [1, "cagiran hatayi gorur"],
  "kuyruk":          [4, "gecikme olarak sizar"],
  "sessiz kisma":    [12, "hicbir hata uretmez"],
};

export const dolmaAyi = (kullanim, sinir, g) =>
  g <= 0 ? Infinity : Math.log(sinir / kullanim) / Math.log(1 + g);
export const topla = (v) => v.reduce((a, b) => a + b, 0);
```

```js
// maliyet/plan.mjs — buyume plani sinir tablosuna uygulanir: her sinira kac birim kaldigi,
// hangi sinirin once doldugu, istek buyumesi tarandiginda sirdinin degisip degismedigi ve
// sinira carpmanin gunluk bedeli. Sayilar yalniz modelden turer.
import { SINIR, BUYUME, PAYLASAN, DAVRANIS, dolmaAyi, topla } from "./sinir.mjs";

const yaz = (g, ...s) => console.log(s.map((v, i) =>
  (g[i] < 0 ? String(v).padEnd(-g[i]) : String(v).padStart(g[i]))).join(""));
const t0 = process.hrtime.bigint();

console.log(`${SINIR.length} sinir, ${Object.keys(BUYUME).length} surucu ` +
  `(kurgu sinir tablosu ve kurgu buyume plani)`);

console.log("\n1. hangi sinira kac birim kaldi");
const A = [-30, -7, 7, 10, 9, 9, 10, 9];
yaz(A, "sinir", "kapsam", "ekip", "kullanim", "sinir", "kalan", "doluluk", "surucu");
for (const [ad, kap, sur, kul, sin] of SINIR)
  yaz(A, ad, kap, PAYLASAN[kap], kul, sin, sin - kul, `%${(100 * kul / sin).toFixed(1)}`, sur);
const dolulukOrt = topla(SINIR.map(([, , , k, s]) => k / s)) / SINIR.length;
const paylasilan = SINIR.filter(([, kap]) => PAYLASAN[kap] > 1);
console.log(`  ortalama doluluk %${(100 * dolulukOrt).toFixed(1)}; en dolu ` +
  `%${(100 * Math.max(...SINIR.map(([, , , k, s]) => k / s))).toFixed(1)}`);
console.log(`  ${paylasilan.length}/${SINIR.length} sinir bes ekip tarafindan paylasilir: ` +
  `bir ekibin buyumesi otekinin basligini tuketir`);
const sabit = SINIR.filter(([, , , , s, tavan]) => tavan <= s);
console.log(`  ${sabit.length} sinir artirilamaz (tavan = sinir): ` +
  sabit.map((x) => x[0]).join(", "));

console.log("\n2. buyume plani uygulaninca: hangi sinir once doluyor");
const B = [-30, 9, 10, 11, 11, 11];
yaz(B, "sinir", "buyume", "dolma ayi", "12. ay", "tavan kati", "artirma");
const sira = SINIR.map((x) => [x, dolmaAyi(x[3], x[4], BUYUME[x[2]])])
  .sort((a, b) => a[1] - b[1]);
for (const [[ad, kap, sur, kul, sin, tavan, gun], n] of sira) {
  const on = kul * Math.pow(1 + BUYUME[sur], 12);
  yaz(B, ad, `%${(100 * BUYUME[sur]).toFixed(0)}`, n === Infinity ? "-" : n.toFixed(1),
    `%${(100 * on / sin).toFixed(0)}`, (tavan / sin).toFixed(2) + "x",
    tavan <= sin ? "yok" : `${gun} gun`);
}
const on12 = SINIR.filter(([, , sur, kul, sin]) => kul * Math.pow(1 + BUYUME[sur], 12) > sin);
console.log(`  ilk dolan: ${sira[0][0][0]} (${sira[0][1].toFixed(1)}. ay); ` +
  `ikinci ${sira[1][0][0]} (${sira[1][1].toFixed(1)}. ay)`);
console.log(`  ilk dolan en dolu sinir degil: en dolu olan ` +
  `${SINIR.reduce((a, b) => (a[3] / a[4] >= b[3] / b[4] ? a : b))[0]}`);
console.log(`  12 ay sonunda ${on12.length}/${SINIR.length} sinir asilir`);

console.log("\n3. istek buyumesi taraniyor: ilk dolan sinir degisiyor mu");
const C = [7, 32, 7, 32, 7];
yaz(C, "istek", "ilk dolan", "ay", "ikinci dolan", "ay");
for (const g of [0.02, 0.05, 0.08, 0.11, 0.16, 0.25]) {
  const b = { ...BUYUME, istek: g };
  const s = SINIR.map((x) => [x, dolmaAyi(x[3], x[4], b[x[2]])]).sort((a, b2) => a[1] - b2[1]);
  yaz(C, `%${(100 * g).toFixed(0)}`, s[0][0][0], s[0][1].toFixed(1), s[1][0][0],
    s[1][1].toFixed(1));
}
console.log(`  istek surucusu uc sinira baglidir; hizi degistiginde sadece tarih degil,`);
console.log(`  once dolan sinirin *kimligi* de degisir`);

console.log("\n4. sinira carpinca ne oluyor ve artirilana kadar ne kaybediliyor");
const D = [-30, -17, 9, 10, 8, 11];
yaz(D, "sinir", "davranis", "fark etme", "artirma", "gun", "kayip br");
let tKayip = 0, tGun = 0;
for (const [ad, , , , sin, tavan, gun, dav, gk] of SINIR) {
  const [fark] = DAVRANIS[dav];
  const sure = tavan <= sin ? fark + 30 : fark + gun;    // artirilamiyorsa kayip surer
  tKayip += gk * sure; tGun += sure;
  yaz(D, ad, dav, fark, tavan <= sin ? "yok" : gun, sure, (gk * sure).toFixed(0));
}
console.log(`  toplam ${tKayip.toFixed(0)} br kayip, ${tGun} sinir-gun; ` +
  `ortalama ${(tGun / SINIR.length).toFixed(1)} gun/sinir`);
const sessiz = SINIR.filter((x) => x[7] === "sessiz kisma");
const hemen = SINIR.filter((x) => DAVRANIS[x[7]][0] === 1);
console.log(`  fark etme gunu davranisa bagli: ${hemen.length} sinir ayni gun gorulur, ` +
  `sessiz kisma ${DAVRANIS["sessiz kisma"][0]}. gunde`);
const sk = topla(sessiz.map((x) => x[8] * (12 + 30)));
console.log(`  sessiz kismanin kaybi ${sk.toFixed(0)} br, toplamin ` +
  `%${(100 * sk / tKayip).toFixed(1)}'i; sinir artirilamaz, plan degistirilir`);

const ms = Number(process.hrtime.bigint() - t0) / 1e6;   // ham olcum basilmaz, bant denetlenir
console.log(`\ndort tablo 2000 ms bandinda: ${ms < 2000 ? "evet" : "hayir"}`);
```

```
8 sinir, 6 surucu (kurgu sinir tablosu ve kurgu buyume plani)

1. hangi sinira kac birim kaldi
sinir                         kapsam    ekip  kullanim    sinir    kalan   doluluk   surucu
bolge basina makine cekirdegi bolge        5       412      640      228     %64.4    sayac
saniyede nesne yazma istegi   bolme        1      1850     3500     1650     %52.9    istek
islev es zamanli calisma      hesap        5       640     1000      360     %64.0    istek
saniyede ad cozumleme         ag           5      7200    10000     2800     %72.0    istek
hesap basina sabit adres      hesap        5        34       50       16     %68.0    kenar
hesap basina sanal ag         hesap        5         9       12        3     %75.0    ortam
bolme basina saklama kurali   bolme        1        62      100       38     %62.0     veri
kural kumesi basina kural     ag           5       148      200       52     %74.0   hizmet
  ortalama doluluk %66.5; en dolu %75.0
  6/8 sinir bes ekip tarafindan paylasilir: bir ekibin buyumesi otekinin basligini tuketir
  2 sinir artirilamaz (tavan = sinir): saniyede ad cozumleme, bolme basina saklama kurali

2. buyume plani uygulaninca: hangi sinir once doluyor
sinir                            buyume dolma ayi     12. ay tavan kati    artirma
saniyede ad cozumleme               %11       3.1       %252      1.00x        yok
islev es zamanli calisma            %11       4.3       %224      4.00x      3 gun
bolme basina saklama kurali          %9       5.5       %174      1.00x        yok
saniyede nesne yazma istegi         %11       6.1       %185      3.43x      4 gun
bolge basina makine cekirdegi        %6       7.6       %130      3.13x      6 gun
kural kumesi basina kural            %4       7.7       %118      2.00x      9 gun
hesap basina sabit adres             %5       7.9       %122      4.00x      5 gun
hesap basina sanal ag                %2      14.5        %95      3.33x      7 gun
  ilk dolan: saniyede ad cozumleme (3.1. ay); ikinci islev es zamanli calisma (4.3. ay)
  ilk dolan en dolu sinir degil: en dolu olan hesap basina sanal ag
  12 ay sonunda 7/8 sinir asilir

3. istek buyumesi taraniyor: ilk dolan sinir degisiyor mu
  istek                       ilk dolan     ay                    ikinci dolan     ay
     %2     bolme basina saklama kurali    5.5   bolge basina makine cekirdegi    7.6
     %5     bolme basina saklama kurali    5.5           saniyede ad cozumleme    6.7
     %8           saniyede ad cozumleme    4.3     bolme basina saklama kurali    5.5
    %11           saniyede ad cozumleme    3.1        islev es zamanli calisma    4.3
    %16           saniyede ad cozumleme    2.2        islev es zamanli calisma    3.0
    %25           saniyede ad cozumleme    1.5        islev es zamanli calisma    2.0
  istek surucusu uc sinira baglidir; hizi degistiginde sadece tarih degil,
  once dolan sinirin *kimligi* de degisir

4. sinira carpinca ne oluyor ve artirilana kadar ne kaybediliyor
sinir                         davranis         fark etme   artirma     gun   kayip br
bolge basina makine cekirdegi olusturma reddi          1         6       7        238
saniyede nesne yazma istegi   istek reddi              1         4       5        305
islev es zamanli calisma      kuyruk                   4         3       7        126
saniyede ad cozumleme         sessiz kisma            12       yok      42       1134
hesap basina sabit adres      olusturma reddi          1         5       6         54
hesap basina sanal ag         olusturma reddi          1         7       8         32
bolme basina saklama kurali   olusturma reddi          1       yok      31        186
kural kumesi basina kural     olusturma reddi          1         9      10        120
  toplam 2195 br kayip, 116 sinir-gun; ortalama 14.5 gun/sinir
  fark etme gunu davranisa bagli: 6 sinir ayni gun gorulur, sessiz kisma 12. gunde
  sessiz kismanin kaybi 1134 br, toplamin %51.7'i; sinir artirilamaz, plan degistirilir

dort tablo 2000 ms bandinda: evet
```

Sayılar **ölçüm** sınıfındadır; girdileri yukarıdaki varsayımlardır.

#### Kalan Başlık Kimin

Birinci tablo sekiz sınırın kalanını sayar. Ortalama doluluk **%66,5**, en dolusu hesap başına
sanal ağ (%75,0) ve orada kalan **üç birimdir** — üç ortam yerine dört ortam kurmak isteyen bir
ekip bu üç birimi harcar.

Kalanın kime ait olduğu kapsamda yazılıdır. **Sekiz sınırın altısı** hesap, bölge ya da ağ
kapsamlıdır ve beş ekip tarafından paylaşılır. Bir ekip yeni bir sabit adres aldığında ötekilerin
kalanı azalır; kimse kimsenin kotasını görmez. Yalnız iki sınır bölme kapsamlıdır ve tek ekibe
aittir. Bu, önceki derslerin dağıtım sorusunun tersidir: orada maliyet ekiplere bölünemiyordu,
burada **sınır zaten bölünmemiştir** ve ilk gelen tüketir.

İki sınırın tavanı kendi değerine eşittir: saniyede ad çözümleme ve bölme başına saklama kuralı
**artırılamaz**. Bunlar için "kaç birim kaldı" sorusunun tek anlamı vardır, çünkü sayının
büyümesinin bir yolu yoktur.

#### Önce Dolan Sınır En Dolu Sınır Değil

İkinci tablo büyüme planını işletir. Sıra doluluğa göre değil, **doluluk ile büyüme hızının
birleşimine** göre çıkar. İlk dolan saniyede ad çözümlemedir: %72,0 doluluk ama %11 aylık büyüme,
**3,1. ay**. İkincisi işlev eş zamanlı çalışmadır (%64,0 doluluk, %11 büyüme, 4,3. ay).

En dolu sınır olan hesap başına sanal ağ **14,5. aya** kadar dolmaz, çünkü onu tüketen ortam
sayısı ayda %2 büyür. Doluluk yüzdesine göre sıralanmış bir kota raporu bu ağda tam ters bir
öncelik listesi üretir.

On iki ayın sonunda **sekiz sınırın yedisi** aşılır. Aşımın büyüklüğü de farklıdır: ad çözümleme
sınırın **%252'sine**, işlev eş zamanlılığı %224'üne çıkar. Tavan katı sütunu bunun karşılığını
verir — işlev eş zamanlılığı dört katına çıkarılabilir ve on iki ayı taşır, ad çözümleme
çıkarılamaz.

#### Büyüme Hızı Sınırın Kimliğini Değiştiriyor

Üçüncü tablo tek bir sürücüyü tarar. İstek hızı üç sınıra birden bağlıdır, dolayısıyla planın en
belirsiz değişkenidir.

%2 ve %5'te ilk dolan sınır **bölme başına saklama kuralıdır** (5,5. ay) ve istekle hiç ilgisi
yoktur; veri hacmi tüketir. %8'den itibaren ilk sıraya ad çözümleme geçer ve %25'te 1,5. aya
iner. Değişen yalnız tarih değil, **sınırın kimliğidir**: yavaş büyümede hazırlanılacak sınır
saklama kuralı, hızlı büyümede ad çözümlemedir ve ikisinin hazırlığı ortak değildir — biri
saklama politikası, öteki mimari değişiklik ister.

Büyüme hızı tahmini bir sayıdır. Bu tablonun söylediği şey, tahminin yanlış olmasının maliyetinin
**yanlış tarihe hazırlanmak değil, yanlış sınıra hazırlanmak** olduğudur.

#### Çarpmanın Davranışı ve Artırmanın Süresi

Dördüncü tablo sınır dolduktan sonrasını sayar. Fark etme günü davranışa bağlıdır: oluşturma
reddi ve istek reddi çağıranın gördüğü bir hata üretir ve **aynı gün** fark edilir; kuyruk
gecikme olarak sızar (4 gün); sessiz kısma hiçbir hata üretmez ve **12 gün** sürer.

Artırma isteğinin süresi bunun üstüne eklenir: 3 ile 9 gün arasında. Toplam **116 sınır-gün** ve
**2.195 birim** kayıp çıkar; sınır başına ortalama 14,5 gün. Nesne yazma isteği en hızlı
kapanan olaydır (5 gün, 305 birim) çünkü hem hemen görülür hem dört günde artırılır.

Sayının **%51,7'si tek bir satırdan** gelir: saniyede ad çözümleme. Sessiz kısma 12 gün fark
edilmez ve sınır artırılamadığı için kayıp bir istekle kesilmez; 42 gün sürer ve **1.134 birim**
tutar. Artırılamayan bir sınırda "artırma süresi" diye bir sayı yoktur, yerine **plan değiştirme
süresi** vardır ve o süre bu tabloda ölçülmez.

#### Özet

- Sekiz sınırın ortalama doluluğu **%66,5**; en dolusunda kalan üç birimdir. **Altısı beş ekip
  tarafından paylaşılır**: sınır bölünmemiştir ve kalanı ilk büyüyen tüketir.
- İki sınır hiç artırılamaz (tavan = sınır); onlar için kalan sayısı tek anlamlıdır.
- **Önce dolan sınır en dolu sınır değildir**: ilk dolan %72,0 dolulukta ama %11 büyüyen ad
  çözümlemedir (3,1. ay); %75,0 ile en dolu olan sınır %2 büyüdüğü için 14,5. aya kadar dolmaz.
- On iki ayın sonunda sekiz sınırın **yedisi** aşılır; ad çözümleme sınırının %252'sine çıkar.
- İstek büyümesi %2'den %25'e tarandığında önce dolan sınırın **kimliği değişir** — saklama
  kuralından ad çözümlemeye. Tahminin yanlışlığı yanlış tarihe değil, **yanlış sınıra**
  hazırlanmak demektir.
- Çarpmanın bedeli davranış ile artırma süresinin toplamıdır: 116 sınır-gün, 2.195 birim. Bunun
  **%51,7'si** tek bir sessiz kısma sınırından gelir — 12 gün fark edilmez, artırılamaz, 42 gün
  sürer ve 1.134 birim tutar.

#### Sonraki Adım

Bu dersin her satırında aynı şey duruyor: sınırın değerini de, artırılıp artırılamayacağını da,
artırmanın kaç gün süreceğini de kiralanan taraf belirliyor. Artırılamayan iki sınırda tek çıkış
yolu planı değiştirmektir ve o değişiklik ağın kendi kararı olmaktan çıkmıştır. Sıradaki ders bu
bağımlılığın toplamını okur: kaç kalem taşınabilir, taşınamayanın yerine ne konur ve taşımanın
faturası ne tutar.

### Satıcı Bağımlılığı

Source: https://academia.sh/tr/kurslar/bulut-yonetisimi/satici-bagimliligi

Kiralanan on iki kalem taşınabilirlik derecesine ayrılır ve fatura ağırlığının taşınabilirliği hiç ölçmediği çıkar: aylık faturanın %48,3'ü kolay taşınır iki kalemden, %9,6'sı hiç taşınamayan üç kalemden gelir. Çıkış faturası 879 kurgu birimdir ve %52'si bayt değil istek ücretidir; yine de toplam taşıma bedelinin yalnız %9,1'i, gerisi 257 kişi-günlük iş yüküdür. Bağımlılığı azaltmanın üç yolu hazırlık, taşıma ve kaybettiği yetenekle ölçülür: en düşük başabaş noktası %48,9'dur ve bir yolun başabaşı %466'dır — taşıma kesin olsa bile ödemez.

Önceki ders sınırları ölçek planına kattı ve her satırda aynı şey durdu: sınırın değerini de
artırılıp artırılamayacağını da kiralanan taraf belirliyor. Bu dersin sorusu o cümlenin
sonundadır — **başka bir yere gitmek** ne kadar mümkün ve ne tutar.

#### Kalemler, Dereceler ve Çıkış Faturası

Örnek kurgu **bölgesel ölçüm ağı**dır: beş ekip, üç ortam, kiralanmış makine, ağ, depo, işlev ve
kenar katmanı. Kalemler ve tutarlar kurgudur; **para birimi de kurgudur** ve `br` diye anılır.

**BM31:** on iki kalem dört **taşınabilirlik derecesine** ayrılır — standart arayüzle taşınan,
uyarlamayla taşınan, yeniden yazım gerektiren, taşınamayan. **BM32:** her kalemin bir taşıma iş
yükü vardır; taşınamaz kalemlerde bu sayı **yerine kurulacak şeyin** iş yüküdür. **BM33:** her
kalem sağlayıcıya özgü bir yetenek kümesi kullanır ve hazırlık bunların bir kısmını kaybettirir.
**BM34:** çıkış ücreti bir kereliktir ve iki parçadan oluşur — bayt ve istek. **BM35:** ufuk 36
aydır; hazırlık bu süre boyunca, taşıma yalnız taşıma olursa ödenir.

Kalemler ve yollar süreç içi bir **modeldir**.

```js
// maliyet/tasinabilirlik.mjs — kiralanan kalemlerin tasinabilirlik modeli: gercek bir envanter
// yok. Her kalem bir *tasinabilirlik derecesine*, bir tasima is yukune ve saglayiciya ozgu
// yetenek sayisina baglidir. Para birimi kurgudur ve `br` diye anilir; birim fiyatlar bu
// konunun ilk dersindeki kurgu listeden alinmistir.

export const KISI_GUN = 34;                   // bir kisi-gunun kurgu bedeli (br)
export const CIKIS_GB = 0.082, OKUMA = 0.36;  // GB basina cikis, milyon istek basina okuma
export const UFUK = 36;                       // degerlendirme ufku (ay)

// ad, derece, is yuku (kisi-gun), aylik br, GB, nesne (milyon), ozel yetenek, yerine ne konur
export const KALEM = [
  ["ham olcum deposu", "standart arayuz", 4, 6.5, 308.6, 1244.16, 0, "-"],
  ["kiralanmis makine", "standart arayuz", 6, 535.7, 0, 0, 0, "-"],
  ["anlik goruntu", "uyarlama", 9, 102.7, 2140, 0.4, 2, "-"],
  ["kayit deposu", "uyarlama", 7, 23.1, 1360, 8, 1, "-"],
  ["ozel baglanti", "uyarlama", 9, 46.0, 0, 0, 3, "-"],
  ["yonetilen dizi depo", "uyarlama", 18, 196.0, 640, 3, 4, "-"],
  ["olay kuyrugu", "yeniden yazim", 22, 58.0, 90, 6, 5, "-"],
  ["islev calistirma", "yeniden yazim", 34, 47.2, 0, 0, 6, "-"],
  ["kimlik ve politika", "yeniden yazim", 41, 0, 0, 0, 7, "-"],
  ["anahtar yonetimi", "tasinamaz", 38, 34.0, 0, 0, 3, "kendi anahtar deposu"],
  ["denetim kaydi hatti", "tasinamaz", 24, 23.1, 620, 5, 2, "kendi kayit hatti"],
  ["tehdit tespiti", "tasinamaz", 45, 51.0, 0, 0, 4, "kural yazimi ve bakim"],
];
export const DERECE = ["standart arayuz", "uyarlama", "yeniden yazim", "tasinamaz"];

// bagimliligi azaltmanin yollari. Carpanlar dort dereceye sirayla uygulanir: hazirlik
// yapilmisken tasima is yukunun ne kadari kalir. Cikis carpani veri karsi tarafta duruyorsa
// duser. ad, bir kerelik kisi-gun, aylik kisi-gun, aylik ek br, carpanlar, cikis, yetenek kaybi
export const YOL = [
  ["hicbir sey", 0, 0.0, 0.0, [1.00, 1.00, 1.00, 1.00], 1.00, 0.00],
  ["soyutlama", 25, 0.6, 0.0, [1.00, 0.25, 0.35, 1.00], 1.00, 0.45],
  ["iki saglayici", 45, 0.0, 512.3, [0.00, 0.00, 0.50, 1.00], 0.05, 0.75],
  ["ortak ozellik", 0, 3.2, 0.0, [0.60, 0.30, 0.35, 0.00], 1.00, 0.85],
];

export const topla = (v) => v.reduce((a, b) => a + b, 0);
export const kova = (d) => KALEM.filter((k) => k[1] === d);
```

```js
// maliyet/cikis.mjs — kalemler tasinabilirlik derecesine ayrilir, cikis faturasi toplanir ve
// bagimliligi azaltmanin uc yolu hazirlik, tasima ve *kaybettigi yetenek* ile olculur; tasima
// olasiligi taranarak her yolun basabas noktasi cikarilir. Sayilar yalniz modelden turer.
import { KALEM, DERECE, YOL, KISI_GUN, CIKIS_GB, OKUMA, UFUK, topla,
  kova } from "./tasinabilirlik.mjs";

const yaz = (g, ...s) => console.log(s.map((v, i) =>
  (g[i] < 0 ? String(v).padEnd(-g[i]) : String(v).padStart(g[i]))).join(""));
const t0 = process.hrtime.bigint();
const AYLIK = topla(KALEM.map((k) => k[3])), IS = topla(KALEM.map((k) => k[2]));
const GB = topla(KALEM.map((k) => k[4])), NES = topla(KALEM.map((k) => k[5]));
const YET = topla(KALEM.map((k) => k[6])), CIKIS = GB * CIKIS_GB + NES * OKUMA;
console.log(`${KALEM.length} kiralanmis kalem, aylik ${AYLIK.toFixed(1)} br (kurgu birim)`);

console.log("\n1. tasinabilirlik derecesi, fatura agirligi ve cikis faturasi");
const A = [-17, 6, 6, 10, 8, 8, 8, 11, 10];
yaz(A, "derece", "kalem", "is", "aylik br", "fatura", "yetenek", "GB", "nesne (mn)",
  "cikis br");
for (const d of DERECE) {
  const g = kova(d), br = topla(g.map((k) => k[3]));
  const gb = topla(g.map((k) => k[4])), n = topla(g.map((k) => k[5]));
  yaz(A, d, g.length, topla(g.map((k) => k[2])), br.toFixed(1),
    `%${(100 * br / AYLIK).toFixed(1)}`, topla(g.map((k) => k[6])), gb.toFixed(0), n.toFixed(2),
    (gb * CIKIS_GB + n * OKUMA).toFixed(1));
}
yaz(A, "toplam", KALEM.length, IS, AYLIK.toFixed(1), "%100", YET, GB.toFixed(0), NES.toFixed(2),
  CIKIS.toFixed(1));
console.log("  tasinamaz kalemlerin yerine: " +
  kova("tasinamaz").map((k) => k[7]).join(", "));
const ham = KALEM[0];
console.log(`  cikisin %${(100 * NES * OKUMA / CIKIS).toFixed(0)}'si istek ucreti: ham olcum`);
console.log(`  deposunda ${(ham[4] * CIKIS_GB).toFixed(1)} br bayta karsilik ` +
  `${(ham[5] * OKUMA).toFixed(1)} br istek dusuyor`);
console.log(`  cikis ${CIKIS.toFixed(0)} br, aylik faturanin ` +
  `%${(100 * CIKIS / AYLIK).toFixed(0)}'i; is yuku ${(IS * KISI_GUN).toFixed(0)} br`);
console.log(`  cikis toplam tasima bedelinin ` +
  `%${(100 * CIKIS / (CIKIS + IS * KISI_GUN)).toFixed(1)}'i`);

const olc = (y) => {
  const [, birKerelik, aylikGun, aylikBr, carp, cikisCarp, kayip] = y;
  const is = topla(DERECE.map((d, i) => topla(kova(d).map((k) => k[2])) * carp[i]));
  return { hazirlik: birKerelik * KISI_GUN + UFUK * (aylikGun * KISI_GUN + aylikBr), is,
    tasima: is * KISI_GUN + CIKIS * cikisCarp, kayip: YET * kayip };
};

console.log("\n2. bagimliligi azaltmanin uc yolu (36 aylik ufuk)");
const C = [-15, 13, 10, 11, 9, 10];
yaz(C, "yol", "hazirlik br", "kalan is", "tasima br", "yetenek", "basabas");
const taban = olc(YOL[0]);
for (const y of YOL) {
  const o = olc(y), p = y === YOL[0] ? null : o.hazirlik / (taban.tasima - o.tasima);
  yaz(C, y[0], o.hazirlik.toFixed(0), o.is.toFixed(1), o.tasima.toFixed(0),
    o.kayip ? `-${o.kayip.toFixed(0)}` : "0", p === null ? "-" : `%${(100 * p).toFixed(1)}`);
}
console.log(`  ${YET} ozel yetenek var; her yol tasima bedelini yetenekle satin aliyor`);

console.log("\n3. tasima olasiligi taraniyor: beklenen bedel ve en ucuz yol");
const D = [9, 12, 11, 15, 15, 16];
yaz(D, "olasilik", ...YOL.map((y) => y[0]), "en ucuz");
for (const p of [0.05, 0.25, 0.50, 0.70, 1.00]) {
  const v = YOL.map((y) => { const o = olc(y); return o.hazirlik + p * o.tasima; });
  yaz(D, `%${(100 * p).toFixed(0)}`, ...v.map((x) => x.toFixed(0)),
    YOL[v.indexOf(Math.min(...v))][0]);
}
const ps = YOL.slice(1).map((y) => [y[0], olc(y).hazirlik / (taban.tasima - olc(y).tasima)]);
const en = ps.reduce((a, b) => (a[1] <= b[1] ? a : b));
console.log(`  en dusuk basabas ${en[0]}: %${(100 * en[1]).toFixed(1)}; altinda hicbir ` +
  `hazirlik odemiyor`);
console.log(`  ${ps.filter((x) => x[1] > 1).length} yolun basabasi %100'un ustunde: tasima ` +
  `kesin olsa bile odemiyor`);

const ms = Number(process.hrtime.bigint() - t0) / 1e6;   // ham olcum basilmaz, bant denetlenir
console.log(`\nuc tablo 2000 ms bandinda: ${ms < 2000 ? "evet" : "hayir"}`);
```

```
12 kiralanmis kalem, aylik 1123.3 br (kurgu birim)

1. tasinabilirlik derecesi, fatura agirligi ve cikis faturasi
derece            kalem    is  aylik br  fatura yetenek      GB nesne (mn)  cikis br
standart arayuz       2    10     542.2   %48.3       0     309    1244.16     473.2
uyarlama              4    43     367.8   %32.7      10    4140      11.40     343.6
yeniden yazim         3    97     105.2    %9.4      18      90       6.00       9.5
tasinamaz             3   107     108.1    %9.6       9     620       5.00      52.6
toplam               12   257    1123.3    %100      37    5159    1266.56     879.0
  tasinamaz kalemlerin yerine: kendi anahtar deposu, kendi kayit hatti, kural yazimi ve bakim
  cikisin %52'si istek ucreti: ham olcum
  deposunda 25.3 br bayta karsilik 447.9 br istek dusuyor
  cikis 879 br, aylik faturanin %78'i; is yuku 8738 br
  cikis toplam tasima bedelinin %9.1'i

2. bagimliligi azaltmanin uc yolu (36 aylik ufuk)
yol              hazirlik br  kalan is  tasima br  yetenek   basabas
hicbir sey                 0     257.0       9617        0         -
soyutlama               1584     161.7       6377      -17     %48.9
iki saglayici          19973     155.5       5331      -28    %466.0
ortak ozellik           3917      52.8       2676      -31     %56.4
  37 ozel yetenek var; her yol tasima bedelini yetenekle satin aliyor

3. tasima olasiligi taraniyor: beklenen bedel ve en ucuz yol
 olasilik  hicbir sey  soyutlama  iki saglayici  ortak ozellik         en ucuz
       %5         481       1903          20239           4051      hicbir sey
      %25        2404       3179          21306           4586      hicbir sey
      %50        4808       4773          22638           5255       soyutlama
      %70        6732       6048          23704           5790   ortak ozellik
     %100        9617       7961          25304           6593   ortak ozellik
  en dusuk basabas soyutlama: %48.9; altinda hicbir hazirlik odemiyor
  1 yolun basabasi %100'un ustunde: tasima kesin olsa bile odemiyor

uc tablo 2000 ms bandinda: evet
```

Sayılar **ölçüm** sınıfındadır; girdileri yukarıdaki varsayımlardır.

#### Fatura Ağırlığı Taşınabilirliği Ölçmüyor

Birinci tablo iki sıralamayı yan yana koyar ve ikisi terstir. Faturanın **%48,3'ü** standart
arayüzle taşınan iki kalemdendir ve o iki kalemin iş yükü **10 kişi-gündür**. Yeniden yazım
gerektiren üç kalem faturanın %9,4'ünü tutar ama 97 kişi-gün, taşınamayan üçü %9,6'yı tutar ve
107 kişi-gün ister.

Aynı ters ilişki yetenek sütununda da vardır: faturanın yarısını tutan iki kalem sağlayıcıya özgü
**sıfır** yetenek kullanır, %19'unu tutan yedi kalem 27 yeteneğin tamamını. Bağımlılık harcanan
parayla değil **kullanılan özellikle** birikir.

Taşınamayan üç kalemin yerine ne konacağı adıyla yazılıdır: kendi anahtar deposu, kendi kayıt
hattı, kural yazımı. Üçünde de yerine konan şey hizmet değil **sürekli bir iştir**.

#### Çıkış Faturası Nerede Birikiyor

Çıkış faturası **879 birimdir** — aylık faturanın %78'i, tek seferde. Bunun **%52'si bayt değil
istek ücretidir** ve farkı tek kalem üretir: ham ölçüm deposunda 25,3 birimlik bayta karşılık
**447,9 birim** istek düşer. Konunun ilk dersindeki parçalama kararı burada ikinci kez ödenir.

Ama çıkış taşımanın büyük kalemi değildir: 257 kişi-günlük iş **8.738 birim** tutar ve çıkış
toplamın yalnız **%9,1'idir**. Çıkış tek satırda görünür; asıl kalem hiçbir faturada görünmez.

#### Hazırlığın Bedeli Yetenektir

İkinci tablo üç azaltma yolunu ölçer. **Soyutlama katmanı** 36 ayda 1.584 birim tutar, taşımayı
9.617'den 6.377 birime indirir ve 37 yetenekten **17'sini** kaybettirir. **İki sağlayıcıda birden
koşmak** taşımayı 5.331 birime indirir ve çıkışı neredeyse sıfırlar, ama hazırlığı **19.973
birimdir** — taşımanın kendisinden iki kat pahalı. **Yalnız ortak özellikleri kullanmak** en ucuz
taşımayı verir (2.676 birim), hazırlığı 3.917'dir ve 37 yeteneğin **31'ini** alır.

Üç yolun ortak yanı sütunda durur: hiçbiri taşınabilirliği parayla satın almaz, **yetenekle takas
eder**. Taşınamayan üç kaleme hiçbiri dokunmaz.

#### Bağımlılığın Kabul Edilebilir Olduğu Yer

Üçüncü tablo taşıma olasılığını tarar. **%5 ve %25'te en ucuz yol hiçbir şey yapmamaktır**; %50'de
soyutlama, %70 ve üstünde ortak özellik öne geçer. En düşük başabaş **%48,9'dur**: üç yıl içinde
taşıma olasılığı bunun altındaysa hiçbir hazırlık kendini ödemez.

İki sağlayıcıda koşmanın başabaşı **%466'dır**; bir olasılık olarak anlamsız oluşu sonucun
kendisidir. Üç yıllık ikinci fatura tek seferlik taşımadan pahalı olduğu için o yol, taşıma
kesin olsa bile ödemez.

Bağımlılık bu tabloda bir hata değil bir **fiyattır**; ölçü "bağımlı mıyız" değil, **"taşıma
olasılığımız %48,9'un üstünde mi"** sorusudur.

#### Özet

- Fatura ağırlığı taşınabilirliği ölçmez: faturanın **%48,3'ü** en kolay taşınan iki kalemdendir
  ve o iki kalem sıfır özel yetenek kullanır; %19'unu tutan yedi kalem 27 yetenek kullanır.
- Üç kalem hiç taşınmaz; yerlerine konan şey hizmet değil **sürekli iştir** (107 kişi-gün).
- Çıkış faturası **879 birimdir** ve %52'si istek ücretidir — ham ölçüm deposunda baytın on yedi
  katı. Yine de taşımanın **%9,1'idir**; 257 kişi-günlük iş 8.738 birimle asıl kalemdir ve
  hiçbir faturada görünmez.
- Üç yol da taşınabilirliği **yetenekle takas eder** (17, 28, 31 yetenek) ve hiçbiri taşınamayan
  üç kaleme dokunmaz. En düşük başabaş **%48,9**, en yükseği **%466'dır**.

#### Kurs Kapanışı

| Ders | Kim yapabiliyor / görebiliyor | Sınır ve kalan | Daraltmanın ya da ölçmenin bedeli |
|---|---|---|---|
| kimlik/01 | grupta 231 etkin izin, 157 gerekli | 4 ayrılandan 3'ü kapanmıyor | kısma 142 meşru izni düşürür |
| kimlik/02 | tek yıldız 132 kat kapsam açıyor | 88 istekte açık ret kazanıyor | koşul 130 meşru okumayı durdurur |
| kimlik/03 | 840 isteğin 131'i izinli | 555 istek hesap sınırını aşıyor | belgeler kalkınca 15 iş durur |
| kimlik/04 | 30 çiftin 17'si güven listesinde | çağrı sınırına 480 kaldı | rol kapanınca günde 90 işlem durur |
| kimlik/05 | 79 anahtar kopyası, 49'u kayıtsız | 30 örneğin 3'ü kimlik alamıyor | konak kapsamı 54 fazla izin |
| kimlik/06 | 46 kalem açık, gereken 27 | güvenli eşik 275 gün, gözlenen 90 | 1 günlük pencere 8 yol durdurur |
| kimlik/07 | patlama yarıçapı 24 → 8 → 3 | kotada 1.142 aşım, 580 kalan | 24 belge 57 belgeye çıkıyor |
| güvenlik/01 | çözebilen çift 45'ten 20'ye | anahtar dönemine 43 gün kaldı | günde 132 meşru okuma durur |
| güvenlik/02 | 16 bacağın 4'ü bilinmiyor | geçiş penceresine 29 gün kaldı | 34 istemci yükseltilemiyor |
| güvenlik/03 | 90 günde 34 sırrı insan okudu | 17 sır hiç döndürülmedi | sıfır kaçıran pencere 601.584 dk |
| güvenlik/04 | 480 olayın 273'ü, varsayılanda 88 | kaydı 11 özne silebilir | ayrı hesap 6 meşru işi durdurur |
| güvenlik/05 | 46 ateşlemenin 32'si gerçek | tarama kotası 240, kalan 108 | düzelt kipi 8 yapılandırma bozar |
| güvenlik/06 | 25 erişimin 14'ü genel internetten | 18 uçtan 12 dolu, 6 boşta | kapatma 12 meşru erişimi kırar |
| güvenlik/07 | 11 zararlının 9'u, 8'i tek kaynakla | toplama 60 GB/gün, kalan 5 | eşik 3'te yakalanan 7'ye iner |
| güvenlik/08 | 26 kanıtın 7'si sağlayıcıdan | kanıt deposu 12 GB, kalan 4,28 | yılda 139 br, 160 kişi-saat |
| maliyet/01 | faturanın %50,8'i platform kararı | 14 ayrım var, 90 gerekli | istek kesişimi 693.370 kalem |
| maliyet/02 | geçerli kapsam %75,0 | etiket anahtarı 10, kalan 3 | zorunluluk 511,9 birimlik işi durdurur |
| maliyet/03 | ilk uyarıda bütçenin %86,4'ü gitmiş | kalan 204 br | uyarı 90 günün 68'inde açık |
| maliyet/04 | p95 doluluk %31,4 | merdivende 16 kademe kaldı | tasarrufun %88,0'ı kesinti ister |
| maliyet/05 | 6/8 sınır beş ekipte ortak | en dolusunda 3 birim kaldı | 116 sınır-gün, 2.195 br |
| maliyet/06 | faturanın %48,3'ü kolay taşınır | 3 kalem taşınamaz, 37 özel yetenek | başabaş %48,9'un altında ödemez |

| Kurs | Ölçü ekseni | Ölçü birimi |
|---|---|---|
| K01 Bulut Temelleri | kiralamanın bedeli | devredilen karar |
| K02 Bulutta Hesaplama ve Ağ | devredilen karar somut kalemde | geri alınamayan kalem |
| K03 Bulutta Depolama ve Veri | veri kiralandığında | çıkış ve aktarım |
| K04 Sunucusuz ve Kenar Bilişim | devredilen karar kısıt olarak geri gelir | kısıt kalemi |
| K05 Bulut Yönetişimi, Güvenlik ve Maliyet | kiralananın sahibi ve sınırı | yetki, görünürlük, kota |

M23 boyunca sorulan tek soru **neyi devrettiğin ve karşılığında neyi bıraktığındı**. Beş kurs aynı
kiralanmış ağı beş kez ölçtü ve her ölçüm aynı biçimi aldı: bir karar devredildi, bir kalem geri
alınamaz oldu. Bu kursta o kalem bir sahip ve bir sınır kazandı.

**Çıkış** sütunu beş kursta da taşındı ve toplamı burada okundu: taşınamayan üç kalem, 257
kişi-günlük iş, 879 birimlik çıkış faturası, %48,9'luk başabaş. Bağımlılık kiralamanın kusuru
değil **fiyatıdır**.

