İçeriğe geç
academia.sh

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 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

// 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ı: 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.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat