Ders 02 / 21
Politika Yapısı
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.
İçindekiler
Ö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
nodeile 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
31071923koda yazılıdır ve yüz yirmi sıra denendi.
Değerlendirici
// 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ı
// 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
// 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
// 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ı:
p428 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.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.