---
title: 'Biçim ve Doğrulama Denetimleri'
source: 'https://academia.sh/tr/kurslar/kod-olarak-altyapi/bicim-ve-dogrulama-denetimleri'
course: 'Kod Olarak Altyapı'
language: tr
updated: '2026-08-17T18:09:07+00:00'
license: 'CC BY-SA 4.0'
---

# Biçim ve Doğrulama Denetimleri

Altyapı kaydının uygulanmadan önce sınanması: kurgu tanım dosyaları üzerinde biçim, söz dizimi ve tip/başvuru denetimlerinin gerçekten koşturulması, on altı bilinen kusurda her denetimin tuttuğu, yalnız kendisinin tuttuğu ve kaçırdığı sayıların ölçülmesi, koşum maliyetinin okunan dosya ve karşılaştırma cinsinden sayılması, statik denetimin göremediği kusur sınıfının adıyla yazılması.

Kayıt yazıldı: altyapı bir yapılandırma dilinde tanımlandı, dosyalara bölündü, tekrar eden parçalar
modülleşti. Buraya kadar ölçülen kaydın **düzeniydi**; hiç ölçülmeyen ise **doğruluğu**. Bu dosyalar
uygulandığında istenen altyapı mı çıkıyor, yoksa uygulama yarıda mı kalıyor? Soru uygulamadan önce
sorulmazsa yanıtı uygulamanın kendisi verir ve yanıtın bedeli yaratılmış kaynaktır.

**Statik denetim** kaydı uygulamadan önce okur: hiçbir kaynağa dokunmaz, sağlayıcıya bağlanmaz,
yalnız diskteki metni okur. Bu ders üç statik denetimi yazar ve kurgu tanım
dosyaları üzerinde koşturur — biçim, söz dizimi, tip ve başvuru tutarlılığı. Her denetimin bilinen
kusur kümesinde **tuttuğu ve yalnız kendisinin tuttuğu**, **kaçırdığı** ve **koşum maliyeti**
sayılır; sonda statik denetimin göremediği kusur sınıfı uygulamada ölçülür. Through-line
**bölgesel ölçüm ağıdır** ve kurgudur.

## Kayıt ve Bilinen Kusur Kümesi

**AD1 — ölçüm ağının üretim ortamı dört tanım dosyasında on bir kaynakta tutulur: üç ağ, beş
makine, bir kuyruk, bir veri deposu, bir nesne deposu (kurgu).** **AD2 — yapılandırma dilinin
biçimi kendi küçük biçimimizdir**: sütun 0'da blok başlığı, altında iki boşluk girintili alanlar,
`=` düz değer, `->` başvuru. **AD3 — bilinen kusur kümesi on altı kusurdur ve elle
işaretlenmiştir**; her kusur temiz kaydın belirli bir satırına enjekte edilir ve bulgunun hangi
kusura karşılık geldiği satır numarasından okunur.

```js
// kur.mjs — olcum aginin kaydini yazar, kopyasina bilinen kusurlari enjekte eder (kurgu)
import { mkdirSync, writeFileSync } from "node:fs";

// bicim: sutun 0'da "kaynak <tur>/<ad>:", altinda iki bosluk girintili alan satirlari;
// "=" duz deger, "->" baska bir kaynaga basvuru, "#" yorum, bloklar arasinda bir bos satir
const blok = (tur, ad, alan) => `kaynak ${tur}/${ad}:\n` +
  alan.map(([a, y, d]) => `  ${a.padEnd(8)}${y} ${d}`).join("\n") + "\n";
const MAKINE = [["bati-1", "bati", "orta", 40], ["bati-2", "bati", "orta", 40],
  ["bati-3", "bati", "buyuk", 80], ["dogu-1", "dogu", "orta", 40], ["dogu-2", "dogu", "buyuk", 80]];
const DOSYA = {
  "ag.tanim": ["bati", "dogu", "kuzey"].map((b, i) => blok("ag", `omurga-${b}`,
    [["bolge", "=", b], ["blok", "=", `10.2${i}.0.0/16`], ["ozel", "=", "evet"]])).join("\n"),
  "makine.tanim": MAKINE.map(([n, b, by, d]) => blok("makine", `toplayici-${n}`,
    [["bolge", "=", b], ["boyut", "=", by], ["disk_gb", "=", d],
      ["ag", "->", `ag/omurga-${b}`]])).join("\n"),
  "akis.tanim": blok("kuyruk", "olcum-kuyrugu", [["bolge", "=", "bati"], ["saklama", "=", 72],
    ["ag", "->", "ag/omurga-bati"]]) + "\n" + blok("veri_deposu", "olcum-deposu",
    [["bolge", "=", "bati"], ["boyut", "=", "buyuk"], ["disk_gb", "=", 500], ["yedek", "=", 14],
      ["ag", "->", "ag/omurga-bati"]]),
  "arsiv.tanim": blok("nesne_deposu", "olcum-arsiv", [["bolge", "=", "bati"],
    ["surumlu", "=", "evet"], ["sinif", "=", "soguk"]]),
};

// bilinen kusur kumesi: [kod, dosya, temiz kayittaki satir, yerine gelen, kusurun konumu]
const KUSUR = [
  ["K01", "ag.tanim", 2, "  bolge   = bati  "],
  ["K02", "ag.tanim", 9, "  ozel    = acik"],
  ["K03", "makine.tanim", 3, "   boyut   = orta"],
  ["K04", "makine.tanim", 5, "  ag      -> nesne_deposu/olcum-arsiv"],
  ["K05", "makine.tanim", 10, "  disk_gb=40"],
  ["K06", "makine.tanim", 16, "  disk_gb = seksen"],
  ["K07", "makine.tanim", 18, "@sil", 19],
  ["K08", "makine.tanim", 22, "  disk_gb = 40\n  disk_gb = 60"],
  ["K09", "makine.tanim", 23, "  ag      -> ag/omurga-guney"],
  ["K10", "makine.tanim", 25, "kaynak makine/toplayici-dogu-1:"],
  ["K11", "ag.tanim", 11, "kaynak ag/omurga-kuzey"],
  ["K12", "akis.tanim", 2, "  bolge   = bati\n  bolgeler = bati,dogu"],
  ["K13", "akis.tanim", 3, "\tsaklama = 72"],
  ["K14", "akis.tanim", 8, "  boyut   ="],
  ["K15", "akis.tanim", 11, "  # ag baglantisi sonra eklenecek", 6],
  ["K16", "arsiv.tanim", 4, "  sinif   = soguk\n  etiket olcum arsivi"],
];

mkdirSync("kayit", { recursive: true });
mkdirSync("taslak", { recursive: true });
const konum = [];
for (const [dosya, icerik] of Object.entries(DOSYA)) {
  writeFileSync(`kayit/${dosya}`, icerik);
  const yama = new Map(KUSUR.filter((k) => k[1] === dosya).map((k) => [k[2], k[3]]));
  const yeni = [], harita = {};
  icerik.split("\n").forEach((s, i) => { // bir kusur satiri silebilir ya da satir ekleyebilir
    const d = yama.get(i + 1);
    if (d === "@sil") return;
    yeni.push(...(d ?? s).split("\n"));
    harita[i + 1] = yeni.length; // temiz kayittaki satir -> taslaktaki son karsiligi
  });
  writeFileSync(`taslak/${dosya}`, yeni.join("\n"));
  for (const [kod, , satir, , k] of KUSUR.filter((x) => x[1] === dosya))
    konum.push({ kod, dosya, satir: harita[k ?? satir] });
}
writeFileSync("kusur.json", JSON.stringify(konum));

const metin = Object.values(DOSYA).join("");
console.log(`kayit: ${Object.keys(DOSYA).length} dosya, ${metin.match(/^kaynak /gm).length} kaynak, ` +
  `${metin.split("\n").length} satir; taslak: ayni kayit + ${KUSUR.length} bilinen kusur\n`);
console.log(DOSYA["akis.tanim"].split("\n").slice(0, 4).join("\n"));
```

```
kayit: 4 dosya, 11 kaynak, 59 satir; taslak: ayni kayit + 16 bilinen kusur

kaynak kuyruk/olcum-kuyrugu:
  bolge   = bati
  saklama = 72
  ag      -> ag/omurga-bati
```

## Üç Statik Denetim

**AD4 — biçim kuralları altı tanedir ve ekipçe kabul edilmiştir.** **AD5 — her kaynak türünün
alanları, tipleri ve zorunlulukları kayıtla birlikte tutulan bir şemadadır.** Üçü de aynı biçimde
bulgu üretir — dosya, satır, kural — ama bağlamları farklıdır: biçim tek satıra bakar, söz dizimi
satıra ve bloğuna bakar, tip/başvuru kaydın tamamını ister; çünkü bir makinenin `ag` alanı başka
dosyadaki kaynağa işaret eder.

```js
// denetim.mjs — ayni kayit uzerinde uc statik denetim: bicim, soz dizimi, tip/basvuru
import { readFileSync, readdirSync } from "node:fs";

const SEMA = { // tur -> "alan:tip" listesi; "!" zorunlu, "@t" t turunden bir kaynaga basvuru
  ag: "bolge:metin! blok:metin! ozel:mantik!",
  makine: "bolge:metin! boyut:metin! disk_gb:sayi! ag:@ag!",
  kuyruk: "bolge:metin! saklama:sayi! ag:@ag!",
  veri_deposu: "bolge:metin! boyut:metin! disk_gb:sayi! yedek:sayi! ag:@ag!",
  nesne_deposu: "bolge:metin! surumlu:mantik! sinif:metin!",
};
const alanlar = (tur) => Object.fromEntries(SEMA[tur].split(" ").map((x) => x.split(":")));
const BASLIK = /^kaynak ([a-z_]+)\/([a-z0-9-]+):$/, ALAN = /^\s+([a-z_]+)\s*(=|->)\s*(.*)$/;
const oku = (dz) => readdirSync(dz).filter((d) => d.endsWith(".tanim"))
  .map((d) => [d, readFileSync(`${dz}/${d}`, "utf8").split("\n")]);
const say = { bicim: 0, sozdizim: 0, tip: 0 };

// 1) bicim: alti satir-yerel kural; bir satirdan baska hicbir sey okumaz
const R = [
  ["R1", (s) => s.length && s !== s.trimEnd()],                          // satir sonunda bosluk
  ["R2", (s) => /^ *\t/.test(s)],                                        // girintide sekme
  ["R3", (s) => /^ +\S/.test(s) && !/^ {2}\S/.test(s)],                  // girinti iki bosluk degil
  ["R4", (s) => /=|->/.test(s) && !/^\s*#/.test(s) && !/ (=|->)( |$)/.test(s)],  // ayrac boslugu yok
  ["R5a", (s) => /^[^\s#]/.test(s) && !s.endsWith(":")],                 // baslik iki nokta ile bitmiyor
  ["R5b", (s, i, L) => /^[^\s#]/.test(s) && i > 0 && L[i - 1] !== ""],   // blok oncesi bos satir yok
];
function bicim(dosyalar) {
  const b = [];
  for (const [d, L] of dosyalar) L.forEach((s, i) => R.forEach(([k, f]) => {
    say.bicim += 1;
    if (f(s, i, L)) b.push({ dosya: d, satir: i + 1, kural: k });
  }));
  return b;
}

// 2) soz dizimi: satir ve blok yerel; ayni dosyanin disina hic bakmaz
function sozdizim(dosyalar) {
  const b = [], ad = new Map();
  for (const [d, L] of dosyalar) {
    let anahtar = null;
    L.forEach((s, i) => {
      const E = (k) => b.push({ dosya: d, satir: i + 1, kural: k });
      say.sozdizim += 3;
      if (s === "" || /^\s*#/.test(s)) return;
      if (/^\S/.test(s)) {
        const m = BASLIK.exec(s);
        anahtar = null;
        if (!m) return E("P1 baslik kalibi tutmuyor");
        anahtar = new Set();
        const yol = `${m[1]}/${m[2]}`;
        if (ad.has(yol)) E(`P4 yinelenen kaynak adi (${ad.get(yol)})`);
        else ad.set(yol, `${d}:${i + 1}`);
        return;
      }
      const m = ALAN.exec(s);
      if (!m) return E("P2 taninmayan satir");
      if (m[3].trim() === "") return E("P2 deger yok");
      if (anahtar?.has(m[1])) E(`P3 yinelenen anahtar (${m[1]})`);
      anahtar?.add(m[1]);
    });
  }
  return b;
}

// 3) tip/basvuru: kaydin tamamini ister, cunku basvurular dosya sinirini asar
function tipBasvuru(dosyalar) {
  const kaynak = [], b = [];
  for (const [d, L] of dosyalar) { // bozuk baslikli blok modele hic girmez
    let c = null;
    L.forEach((s, i) => {
      const m = /^\S/.test(s) ? BASLIK.exec(s) : ALAN.exec(s);
      if (/^\S/.test(s)) c = m ? { tur: m[1], ad: m[2], dosya: d, satir: i + 1, alan: {} } : null;
      else if (c && m) c.alan[m[1]] = { deger: m[3].trim(), satir: i + 1 };
      else return;
      if (/^\S/.test(s) && c) kaynak.push(c);
    });
  }
  const tipi = (v) => (["evet", "hayir"].includes(v) ? "mantik" : /^-?\d+$/.test(v) ? "sayi" : "metin");
  for (const k of kaynak) {
    const sema = alanlar(k.tur);
    for (const [a, v] of Object.entries(k.alan)) {
      const E = (kural) => b.push({ dosya: k.dosya, satir: v.satir, kural });
      say.tip += 2;
      if (!sema[a]) { E(`C1 semada yok (${a})`); continue; }
      const t = sema[a].replace("!", "");
      if (!t.startsWith("@")) {
        if (v.deger === "" || tipi(v.deger) !== t) E(`C2 ${t} degil ("${v.deger}")`);
        continue;
      }
      let h = null;
      for (const x of kaynak) { say.tip += 1; if (`${x.tur}/${x.ad}` === v.deger) { h = x; break; } }
      if (!h) E(`C4 hedef yok (${v.deger})`);
      else if (h.tur !== t.slice(1)) E(`C5 yanlis tur (${h.tur})`);
    }
    for (const [a, t] of Object.entries(sema)) {
      say.tip += 1;
      if (t.endsWith("!") && !k.alan[a])
        b.push({ dosya: k.dosya, satir: k.satir, kural: `C3 zorunlu alan yok (${a})` });
    }
  }
  return b;
}

const taslak = oku("taslak"), temiz = oku("kayit");
const D = [["bicim", bicim, 1], ["sozdizim", sozdizim, 1], ["tip/basvuru", tipBasvuru, 4]];
const bulgu = D.map(([ad, f]) => [ad, f(taslak)]);
const m = [say.bicim, say.sozdizim, say.tip]; // sayaclar yalniz taslak kosumundan okunur
const K = JSON.parse(readFileSync("kusur.json", "utf8"));
const kod = (f) => K.find((x) => x.dosya === f.dosya && x.satir === f.satir)?.kod ?? "??";

console.log(`${"denetim".padEnd(13)}${"kod".padEnd(5)}${"konum".padEnd(20)}kural`);
for (const [ad, l] of bulgu) for (const f of l)
  console.log(`${ad.padEnd(13)}${kod(f).padEnd(5)}${`${f.dosya}:${f.satir}`.padEnd(20)}${f.kural}`);

const tut = bulgu.map(([, l]) => new Set(l.map(kod)));
console.log(`\n${"denetim".padEnd(13)}${"bulgu".padStart(6)}${"tuttugu".padStart(9)}` +
  `${"yalniz kendisi".padStart(16)}${"kacirdigi".padStart(11)}${"karsilastirma".padStart(15)}` +
  `${"tek dosya icin".padStart(16)}`);
bulgu.forEach(([ad, l], j) => {
  const y = [...tut[j]].filter((k) => tut.every((s, o) => o === j || !s.has(k))).length;
  console.log(`${ad.padEnd(13)}${String(l.length).padStart(6)}${String(tut[j].size).padStart(9)}` +
    `${String(y).padStart(16)}${String(K.length - tut[j].size).padStart(11)}` +
    `${String(m[j]).padStart(15)}${String(D[j][2]).padStart(16)}`);
});
console.log(`\nuc denetim birlikte ${K.length} kusurun ` +
  `${new Set(tut.flatMap((s) => [...s])).size} tanesini tutar; hicbir kusura karsilik gelmeyen ` +
  `bulgu ${bulgu.flatMap(([, l]) => l).filter((f) => kod(f) === "??").length}; ` +
  `temiz kayitta toplam bulgu ${D.reduce((s, [, f]) => s + f(temiz).length, 0)}`);
```

```
denetim      kod  konum               kural
bicim        K01  ag.tanim:2          R1
bicim        K11  ag.tanim:11         R5a
bicim        K13  akis.tanim:4        R2
bicim        K03  makine.tanim:3      R3
bicim        K05  makine.tanim:10     R4
bicim        K07  makine.tanim:18     R5b
sozdizim     K11  ag.tanim:11         P1 baslik kalibi tutmuyor
sozdizim     K14  akis.tanim:9        P2 deger yok
sozdizim     K16  arsiv.tanim:5       P2 taninmayan satir
sozdizim     K08  makine.tanim:22     P3 yinelenen anahtar (disk_gb)
sozdizim     K10  makine.tanim:25     P4 yinelenen kaynak adi (makine.tanim:18)
tip/basvuru  K02  ag.tanim:9          C2 mantik degil ("acik")
tip/basvuru  K12  akis.tanim:3        C1 semada yok (bolgeler)
tip/basvuru  K14  akis.tanim:9        C2 metin degil ("")
tip/basvuru  K15  akis.tanim:7        C3 zorunlu alan yok (ag)
tip/basvuru  K04  makine.tanim:5      C5 yanlis tur (nesne_deposu)
tip/basvuru  K06  makine.tanim:16     C2 sayi degil ("seksen")
tip/basvuru  K09  makine.tanim:23     C4 hedef yok (ag/omurga-guney)

denetim       bulgu  tuttugu  yalniz kendisi  kacirdigi  karsilastirma  tek dosya icin
bicim             6        6               5         10            384               1
sozdizim          5        5               3         11            192               1
tip/basvuru       7        7               6          9            131               4

uc denetim birlikte 16 kusurun 16 tanesini tutar; hicbir kusura karsilik gelmeyen bulgu 0; temiz kayitta toplam bulgu 0
```

## Kapsam, Örtüşme ve Bedel

Üç denetim on altı kusurun on altısını da tutar, ama hiçbiri tek başına yetmez: en geniş kapsamlı
olan tip/başvuru bile dokuz kusuru kaçırır. Örtüşme iki yerdedir — başlıktaki iki nokta eksikliği
(K11) hem biçime hem söz dizimine, boş bırakılmış değer (K14) hem söz dizimine hem tipe takılır.
Kalan on dört kusur tek bir denetimin işidir; "yalnız kendisi" sütunu 5, 3 ve 6 verir.

Karşılaştırma sayıları sezginin tersini söyler: **en çok karşılaştırma yapan denetim en az bağlam
isteyendir.** Biçim 384 karşılaştırma yapar (64 satır çarpı altı kural), tip/başvuru yalnız 131.
Bedel karşılaştırmada değil **kapsamdadır**: tek dosya değiştiğinde ilk iki denetim o dosyayı
okuyup karar verebilir, tip/başvuru dördünü birden okumak zorundadır. Üstelik başvuru çözümü kaynak listesini baştan taradığından tip denetiminin
karşılaştırması kaynak sayısıyla karesel büyür. Tabloda sessiz iki sayı daha var: kusura karşılık
gelmeyen bulgu ile temiz kayıttaki toplam bulgu sıfırdır.

## Statik Denetimin Göremediği Sınıf

Üç denetimin de göremediği kusurların ortak adı **sağlayıcı gerçeğine bağlı kusurlardır**: kararı
veren durum kayıtta değildir — bölgedeki kota, bölgede bulunan makine boyutları, ad havuzunda
tutulmuş bir ad, o kaynak türünde yaratma izni. Hiçbiri metinde yazmaz.

**AD6 — sağlayıcının kotası, bölge-boyut kataloğu, ad havuzu, izinleri ve kaynak yaratma süreleri
kurgudur.** Aşağıdaki blok statik denetimin sıfır bulgu verdiği temiz kaydı bu modele uygular;
kalemler kaydın okunma sırasına göre işlenir ve reddedilen atlanır.

```js
// uygulama.mjs — temiz kayit bir saglayici modeline uygulanir; saglayici da sureler de kurgudur
import { readFileSync, readdirSync } from "node:fs";

const SAGLAYICI = {
  kota: { bati: 2, dogu: 4 },                            // bolge basina makine ust siniri
  katalog: { bati: ["orta", "buyuk"], dogu: ["orta"] },  // bolgede bulunan boyutlar
  tutulanAd: ["olcum-arsiv"],                            // ad kuresel benzersiz
  izin: { ag: 1, makine: 1, kuyruk: 1, veri_deposu: 0, nesne_deposu: 1 },
};
const SURE = { ag: 20, makine: 45, kuyruk: 30, veri_deposu: 180, nesne_deposu: 15, red: 5 };

const kaynak = [];
for (const d of readdirSync("kayit")) for (const s of readFileSync(`kayit/${d}`, "utf8").split("\n")) {
  const h = /^kaynak ([a-z_]+)\/([a-z0-9-]+):$/.exec(s), a = /^\s+([a-z_]+)\s*=\s*(.+)$/.exec(s);
  if (h) kaynak.push({ tur: h[1], ad: h[2], alan: {} });
  else if (a) kaynak.at(-1).alan[a[1]] = a[2].trim();
}

let saat = 0, yaratilan = 0;
const red = [], sayilan = {};
for (const k of kaynak) {
  let hata = null;
  if (!SAGLAYICI.izin[k.tur]) hata = "yetki reddi";
  else if (SAGLAYICI.tutulanAd.includes(k.ad)) hata = "ad tutulmus";
  else if (k.tur === "makine") {
    sayilan[k.alan.bolge] = (sayilan[k.alan.bolge] ?? 0) + 1;
    if (sayilan[k.alan.bolge] > SAGLAYICI.kota[k.alan.bolge]) hata = "kota asildi";
    else if (!SAGLAYICI.katalog[k.alan.bolge].includes(k.alan.boyut)) hata = "katalogda yok";
  }
  if (hata) red.push({ ad: `${k.tur}/${k.ad}`, hata, saniye: saat, yaratilan });
  else yaratilan += 1;
  saat += hata ? SURE.red : SURE[k.tur];
}

console.log(`${kaynak.length} kalem uygulandi: ${yaratilan} yaratildi, ${red.length} reddedildi, ` +
  `toplam ${saat} saniye\n`);
console.log(`${"reddedilen kalem".padEnd(28)}${"neden".padEnd(15)}${"kacinci saniyede".padStart(17)}` +
  `${"o ana dek yaratilan".padStart(21)}`);
for (const r of red) console.log(`${r.ad.padEnd(28)}${r.hata.padEnd(15)}` +
  `${String(r.saniye).padStart(17)}${String(r.yaratilan).padStart(21)}`);
```

```
11 kalem uygulandi: 7 yaratildi, 4 reddedildi, toplam 245 saniye

reddedilen kalem            neden           kacinci saniyede  o ana dek yaratilan
veri_deposu/olcum-deposu    yetki reddi                   90                    4
nesne_deposu/olcum-arsiv    ad tutulmus                   95                    4
makine/toplayici-bati-3     kota asildi                  190                    6
makine/toplayici-dogu-2     katalogda yok                240                    7
```

Dört kusur da statik denetimin temiz saydığı kayıttadır; fark zamanda ve bedeldedir. Üç denetim 64
satırı 707 karşılaştırmayla tarar ve sonucu hiç kaynak yaratmadan verir; sağlayıcıya bağlı ilk kusur
90., sonuncusu 240. saniyede görünür ve o anlara kadar dört ve yedi kaynak yaratılmıştır. Koşum
bittiğinde altyapı yarımdır: kuyruk vardır, beslediği veri deposu yoktur. Bu sınıfı statik denetime
taşımanın tek yolu sağlayıcı durumunu kayda getirmektir — yeni bir kayıt, yeni bir sapma kaynağı.

## Özet

- Kurgu ölçüm ağının kaydı dört dosyada on bir kaynak tutar; kopyasına on altı bilinen kusur
  enjekte edilip üç statik denetim gerçek dosyalarda koşturuldu.
- Biçim 6 bulgu verdi (5'i yalnız kendisinin), söz dizimi 5 (3'ü), tip/başvuru 7 (6'sı); üçü
  birlikte 16 kusurun 16'sını tuttu, en geniş denetim tek başına 9 kusur kaçırdı.
- Örtüşme iki kusurdadır: iki nokta eksikliği biçim ile söz dizimine, boş değer söz dizimi ile
  tipe takılır.
- Bedel karşılaştırmada değil kapsamdadır: biçim 384, söz dizimi 192, tip/başvuru 131 karşılaştırma
  yapar, ama tek dosya değişince ilk ikisi 1, tip/başvuru 4 dosya okur.
- Göremediği sınıf **sağlayıcı gerçeğine bağlı kusurlardır** (kota, bölge kataloğu, tutulmuş ad,
  yetki); sıfır bulguyla geçen kayıtta dördü uygulamada çıktı (ilki 90., sonuncusu 240. saniyede) ve
  geride 7 yaratılmış kaynakla yarım bir altyapı bıraktı.

## Sonraki Adım

Bu dersin denetimleri kaydın **kendi kurallarını** sınadı. Hiçbiri "bu kaynak açık ağa bakmamalı"
türünden bir kuralı sınamadı; böyle kurallar dışarıdan gelir ve kaydın doğruluğuyla değil
**kabul edilebilirliğiyle** ilgilidir. Sonraki ders bir
politika kümesini aynı kayıt üzerinde koşturur: politika **tanım** üzerinde mi **plan** üzerinde mi
koşmalı? İki tarama aynı ihlal kümesinde karşılaştırılır — hangisi hesaplanan değerleri görüyor ve
muafiyet kaç ihlale yol açıyor.
