Siber Risk İstisnasi ve Risk Kabul Formu

Siber güvenlik gereksinimlerinden geçici olarak sapılması gerektiğinde, talebin gerekçesini ve doğurabileceği riskleri kayıt altına almak gerekir. Siber Risk İstisnası ve Risk Kabul Formu, istisna talebinin kapsamını, sorumlularını, risk değerlendirmesini, telafi edici kontrollerini, onayını ve kapanış adımlarını tek bir kayıtta izlemek için hazırlanmıştır.

Form; bir gereksinimin neden karşılanamadığını, istisnanın hangi sistem ve hesapları kapsadığını, ne kadar süreyle geçerli olacağını ve riski azaltmak için hangi önlemlerin alınacağını belgeler. Ayrıca istisnayı sona erdirecek kalıcı çözümün ve sorumluların takip edilmesine yardımcı olur.

Bir Not defteri açarak, aşağıdaki (Mavi satırlar) html kodu içine kaydedin. Not defteri uzantısını .txt yerine ".html" olarak değiştirip kaydedin. Ör: "Siber Risk İstisnası ve Risk Kabul Formu.html" sayfayı kapatıp tekrar açtığınızda, web browser üzerinden sayfanız açılacaktır. 

Sol tarafta görünen logo için, html dosyanız nerede ise, masaüstü veya oluşturulan bir klasör. Logonuzda aynı yerde olursa forma yansır. Logo ismi "logo.jpg" olmalı. Çift tıklayarak açtığınızda, browser üzerinde form açılışı gerçekleşir. Veya alanına 5 kez peş peşe tıklayarak çalışma esnasında logo değişimi de yapılabilir.

Başlık, başlığın altındaki, başlığın sağındaki ve alttaki yazıları, not defteri içinde "Ctrl + F" tuşları ile kelime yazarak bulabilir, ilgili metinleri kendinize göre uyarlayarak kaydederek kullanabilirsiniz. Başlık alanındaki "OLGUN BAŞKANLIĞI" alanına 5 kez peş peşe tıklayarak; Departman, Müdürlük veya Başkanlığınıza ait bilgiyi manuel girebilirsiniz.

Formda hangi bilgiler yer alır? (Form dokuz bölümden oluşur)

  1. Talep kaydı: Talep numarası, tarih, tür, durum ve talep dönemi.
  2. Talep sahibi ve sorumlular: Talep eden, sistem sahibi, risk sahibi ve teknik sorumlular.
  3. Etkilenen sistem ve kapsam: Sistem adı, envanter numarası, kritiklik, ortam, kullanıcılar ve veri türü.
  4. İstisna açıklaması: Karşılanamayan gereksinim, istenen sapma, iş gerekçesi ve alternatifler.
  5. Risk değerlendirmesi: Risk senaryosu, tehdit ve zafiyet bilgileri, etki alanları ve puanlama gerekçesi.
  6. Telafi edici kontroller: İstisna süresince riski azaltacak veya izleyecek kontroller, sorumluları ve doğrulama kanıtları.
  7. Kalıcı çözüm ve aksiyon planı: İstisnayı sona erdirecek işler, sorumlular ve hedef tarihler.
  8. İnceleme ve karar: Güvenlik incelemesi, karar, onaylayan yetkili, karar gerekçesi ve onay dönemi.
  9. İzleme, yenileme ve kapatma: Gözden geçirme ve yenileme tarihleri, yeniden değerlendirme tetikleyicileri, kanıtlar ve kapatma adımları.
Olasılık ve etki puanları 1–5 aralığında seçilir. Form, ilk risk puanını ve kontroller sonrasındaki artık risk puanını olasılık × etki hesabıyla gösterir. Bu puanlar değerlendirmeyi destekler; kurumun onaylı risk metodolojisinin ve yetkili karar sürecinin yerini almaz.

Nasıl kullanılır?

  1. Formu açın ve talep numarasını, talep türünü, tarihleri ve durum bilgisini girin. Talep numarası SRI- ön ekiyle başlar; elle düzenlenebilir.
  2. Talep sahibini, sistem sahibini ve riski kabul etme sorumluluğunu taşıyan risk sahibini belirtin.
  3. İstisnanın hangi sistemleri, ortamları, kullanıcıları ve verileri kapsadığını açıkça tanımlayın.
  4. Karşılanamayan gereksinimi ve sapma ihtiyacının gerekçesini yazın. Değerlendirilen alternatifleri ve istisna verilmezse oluşabilecek etkiyi de kaydedin.
  5. Risk senaryosunu, tehdit kaynağını ve zafiyeti açıklayın. Olasılık ve etki değerlerini seçin; form risk puanlarını otomatik hesaplar.
  6. + Kontrol Ekle ile telafi edici kontroller oluşturun. Her satırda kontrolü, sorumluyu, hedef tarihi ve doğrulama kanıtını belirtin.
  7. + Aksiyon Ekle ile kalıcı çözüm adımlarını ekleyin. Sorumlu, hedef tarih ve aksiyon durumunu takip edin.
  8. Güvenlik inceleme sonucunu ve karar bilgilerini girin. Onaylanan kapsamı, koşulları ve geçerlilik tarihlerini kaydedin.
  9. Ara gözden geçirme, yenileme ve kapatma bilgilerini tamamlayın. İlgili kanıt ve belge referanslarını ekleyin.

Excel Dışarı Aktar, form alanlarını ve telafi edici kontrol/aksiyon satırlarını Excel dosyasına aktarır. Excel İçeri Aktar ile daha önce dışa aktarılmış veya aynı yapıya göre hazırlanmış .xlsx dosyası forma yüklenebilir. İçe aktarma dosyasında Form ve Kontroller ve Aksiyonlar adlı çalışma sayfaları bulunmalıdır.

PDF / Yazdır düğmesi yazdırma penceresini açar. Buradan yazıcıyı seçebilir veya PDF olarak kaydedebilirsiniz. Yazdırma düzeni A4 yatay sayfa boyutunu, sayfa numaralarını ve bölüm başlıklarıyla form satırlarının mümkün olduğunca birlikte kalmasını hedefler.

Taslak, logo ve tarayıcı kullanımı: Formdaki değişiklikler tarayıcının yerel depolamasına otomatik kaydedilir ve aynı tarayıcıda yeniden açıldığında yüklenir. Formu Temizle, form alanlarını ve kayıtlı form taslağını siler.

Başlıkta aynı klasörde logo.jpg bulunursa logo gösterilir. Logo alanına beş kez art arda tıklayarak başka bir resim seçebilirsiniz; seçilen logo bu tarayıcıda saklanır.

Form, çevrimiçi bir sunucuya kayıt yapmaz. Taslak ve değiştirilmiş logo yalnızca kullanıldıkları tarayıcıda tutulduğundan, kurumsal kayıt ve onay süreçleri için kurumun belirlediği kayıt sistemleri kullanılmalıdır.

Formun boş hali;

Formun dolu hali:

PDF / Yazdır

Dışarı Aktarılan Excel Verisi:


HTML Kod:
<!DOCTYPE html>
<html lang="tr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Siber Risk İstisnası ve Risk Kabul Formu</title>
<style>
:root{--bg:#f8fafc;--card:#fff;--blue:#0284c7;--blue-dark:#075985;--blue-soft:#e0f2fe;--line:#d7dee8;--text:#0f172a;--muted:#64748b;--green-soft:#dcfce7;--orange-soft:#ffedd5;--red:#b91c1c;--red-soft:#fee2e2;--gray-soft:#f1f5f9;--shadow:0 2px 8px rgba(15,23,42,.06)}
*{box-sizing:border-box;font-family:"Segoe UI",Arial,sans-serif}html,body{margin:0;min-height:100%;background:var(--bg);color:var(--text)}body{padding:12px}.container{width:100%;max-width:1500px;margin:0 auto}
.header{width:100%;display:grid;grid-template-columns:clamp(42px,6vw,60px) minmax(0,1fr) max-content;align-items:center;gap:clamp(6px,1vw,12px);background:#fff;border:1px solid var(--line);border-left:5px solid var(--blue);border-radius:6px;padding:10px 14px;box-shadow:var(--shadow);margin-bottom:10px}.logoBox{width:60px;height:60px;display:flex;align-items:center;justify-content:center;overflow:hidden;cursor:pointer}.logoBox:hover{outline:1px dashed #94a3b8;border-radius:4px}.logoBox:focus-visible{outline:2px solid var(--blue);outline-offset:2px}#logoFile{display:none}.logoBox img{width:100%;height:100%;object-fit:contain}.headerTitleBlock{align-self:center;min-width:0}.headerTitle{font-size:21px;font-weight:750;line-height:1.15}.headerSub{margin-top:4px;color:var(--muted);font-size:11.5px;line-height:1.35}.headerRight{justify-self:end;align-self:center;width:max-content;max-width:40vw;min-width:0;text-align:right;color:#000;font-size:clamp(9px,1.1vw,15px);font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;cursor:default}.headerRight[contenteditable=true]{max-width:min(55vw,760px);min-width:180px;width:max-content;margin-left:auto;overflow:visible;text-overflow:clip;outline:1px dashed var(--blue);background:#f0f9ff;border-radius:3px;padding:2px 4px;cursor:text}
.toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:8px;background:#fff;border:1px solid var(--line);border-radius:6px;box-shadow:var(--shadow);padding:9px 11px;margin-bottom:10px}button,.fileButton{border:1px solid #cbd5e1;border-radius:6px;padding:8px 12px;background:var(--gray-soft);color:#334155;font-size:12px;font-weight:700;cursor:pointer}button:hover,.fileButton:hover{filter:brightness(.97)}.primaryButton{background:var(--blue-soft);border-color:#bae6fd;color:var(--blue-dark)}.importButton{background:var(--green-soft);border-color:#bbf7d0;color:#166534}.dangerButton{background:var(--red-soft);border-color:#fecaca;color:var(--red)}.toolbarStatus{margin-left:auto;color:var(--muted);font-size:11px}.toolbar input[type=file]{display:none}
.card{background:#fff;border:1px solid var(--line);border-radius:6px;padding:14px;box-shadow:var(--shadow)}.formGrid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px}.group{display:flex;flex-direction:column;min-width:0}.half{grid-column:span 2}.full{grid-column:1/-1}label{margin-bottom:4px;color:#334155;font-size:13px;font-weight:700;line-height:1.3}.hint{margin-top:4px;color:var(--muted);font-size:10.5px;line-height:1.4}input,select,textarea{width:100%;min-width:0;border:1px solid #cbd5e1;border-radius:6px;padding:8px 9px;background:#fff;color:var(--text);font-size:13px;outline:none}input:focus,select:focus,textarea:focus{border-color:var(--blue);box-shadow:0 0 0 2px rgba(2,132,199,.12)}textarea{min-height:70px;resize:none;overflow:hidden;line-height:1.45;white-space:pre-wrap;overflow-wrap:anywhere}.sectionTitle{grid-column:1/-1;margin:12px 0 0;padding:7px 9px;background:#f8fafc;border-left:3px solid var(--blue);color:#334155;font-size:13.5px;font-weight:800;line-height:1.25}.sectionIntro{grid-column:1/-1;margin:-6px 0 0;color:var(--muted);font-size:11px;line-height:1.45}.checkGroup{display:flex;flex-wrap:wrap;gap:8px 16px;border:1px solid #cbd5e1;border-radius:6px;padding:9px;background:#fff}.checkItem{display:inline-flex;align-items:center;gap:6px;color:#334155;font-size:12px;font-weight:500;line-height:1.35}input[type=checkbox]{width:auto;accent-color:var(--blue)}
.scorePanel{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px;align-items:stretch}.scoreCard{border:1px solid var(--line);border-radius:6px;padding:10px;background:#fff}.scoreLabel{display:block;color:var(--muted);font-size:11px;font-weight:700;margin-bottom:5px}.scoreValue{display:flex;align-items:center;gap:8px;font-size:17px;font-weight:800}.riskBadge{display:inline-block;padding:3px 8px;border-radius:999px;font-size:10px;font-weight:800;text-transform:uppercase}.riskLow{color:#166534;background:var(--green-soft)}.riskModerate{color:#9a3412;background:var(--orange-soft)}.riskHigh{color:#c2410c;background:#fed7aa}.riskCritical{color:#991b1b;background:var(--red-soft)}
.dynamicList{display:flex;flex-direction:column;gap:8px}.dynamic-row{display:grid;grid-template-columns:minmax(180px,2fr) minmax(140px,1fr) minmax(130px,1fr) minmax(150px,1fr) 36px;gap:7px;align-items:center;padding:8px;border:1px solid var(--line);border-radius:6px;background:#fff}.dynamic-row.action-row{grid-template-columns:minmax(180px,2fr) minmax(140px,1fr) minmax(130px,1fr) minmax(130px,1fr) 36px}.dynamic-row input,.dynamic-row select{font-size:12px;padding:7px 8px}.removeRow{width:34px;height:34px;padding:0;color:var(--red);background:var(--red-soft);border-color:#fecaca;font-size:18px}.addRow{align-self:flex-start;margin-top:7px;color:var(--blue-dark);background:var(--blue-soft);border-color:#bae6fd}.printMirror{display:none}
@media(max-width:900px){body{padding:7px}.header{grid-template-columns:46px minmax(0,1fr) max-content;gap:6px}.logoBox{width:42px;height:42px}.headerTitle{font-size:17px}.headerRight{grid-column:auto;justify-self:end;align-self:center;max-width:32vw;font-size:clamp(9px,1.3vw,13px);white-space:nowrap}.formGrid{grid-template-columns:repeat(2,minmax(0,1fr))}.dynamic-row,.dynamic-row.action-row{grid-template-columns:repeat(2,minmax(0,1fr))}.dynamic-row .removeRow{grid-column:2;justify-self:end}.toolbarStatus{width:100%;margin-left:0}}
@media(max-width:560px){.formGrid{grid-template-columns:1fr}.half,.full,.sectionTitle,.sectionIntro{grid-column:1/-1}.scorePanel{grid-template-columns:1fr}.toolbar button,.fileButton{flex:1 1 145px}.header{grid-template-columns:38px minmax(0,1fr) max-content;gap:5px;padding:8px}.logoBox{width:36px;height:36px}.headerTitle{font-size:clamp(12px,3.4vw,16px)}.headerSub{font-size:clamp(8px,2vw,10px)}.headerRight{max-width:29vw;font-size:clamp(8px,2.1vw,11px);white-space:nowrap;overflow:hidden;text-overflow:clip}.headerRight[contenteditable=true]{max-width:29vw;min-width:0}}
@page{size:A4 landscape;margin:8mm 8mm 14mm;@bottom-right{content:"Sayfa " counter(page) " / " counter(pages);font-family:"Segoe UI",Arial,sans-serif;font-size:9px;color:#64748b}}@media print{html,body{width:100%;margin:0!important;padding:0!important;background:#fff!important;color:#0f172a!important;font-size:10px}.container{max-width:none;width:100%}.toolbar{display:none!important}.header{grid-template-columns:48px minmax(0,1fr) max-content!important;gap:8px;margin:0 0 6px;padding:6px 9px;box-shadow:none;border-radius:4px;break-inside:avoid}.logoBox{width:42px;height:42px}.headerTitleBlock{align-self:center}.headerTitle{font-size:15px}.headerSub{font-size:9px}.headerRight{display:block!important;justify-self:end!important;align-self:center!important;width:max-content;max-width:40vw;color:#000!important;font-size:13px;text-align:right;white-space:nowrap}.card{padding:8px;box-shadow:none;border-radius:4px}.formGrid{grid-template-columns:repeat(4,minmax(0,1fr))!important;gap:8px}.sectionTitle{margin-top:8px;padding:4px 6px;font-size:11px;break-inside:avoid;page-break-inside:avoid;break-after:avoid;page-break-after:avoid}.sectionIntro{break-inside:avoid;page-break-inside:avoid;break-after:avoid;page-break-after:avoid}.group{break-inside:avoid;page-break-inside:avoid}.group>label{break-after:avoid;page-break-after:avoid}label{font-size:10px}input,select,textarea,.dynamic-row input,.dynamic-row select{padding:4px 5px;font-size:9px;border-radius:3px;box-shadow:none!important}textarea{display:none!important}.printMirror{display:block!important;min-height:24px;width:100%;padding:4px 5px;border:1px solid #cbd5e1;border-radius:3px;background:#fff;color:#0f172a;font-size:9px;line-height:1.35;white-space:pre-wrap;overflow-wrap:anywhere}.dynamic-row,.dynamic-row.action-row{grid-template-columns:minmax(180px,2fr) minmax(120px,1fr) minmax(110px,1fr) minmax(120px,1fr) 0!important;gap:5px;padding:5px;break-inside:avoid}.dynamic-row .removeRow,.addRow{display:none!important}.scoreCard,.checkGroup,.dynamic-row{break-inside:avoid;page-break-inside:avoid}*{-webkit-print-color-adjust:exact!important;print-color-adjust:exact!important}}
</style>
</head>
<body>
<div class="container">
  <header class="header">
    <div class="logoBox" id="logoBox" role="button" tabindex="0" aria-label="Logoyu değiştirmek için beş kez tıklayın" title="Logoyu değiştirmek için 5 kez art arda tıklayın"><img id="orgLogo" src="logo.jpg" alt="Kurum logosu" onerror="this.style.display='none'"></div>
    <input id="logoFile" type="file" accept="image/jpeg,image/png,image/webp,image/gif">
    <div class="headerTitleBlock"><div class="headerTitle">Siber Risk İstisnası ve Risk Kabul Formu</div><div class="headerSub">(Güvenlik gereksiniminden sapma taleplerinin değerlendirilmesi ve izlenmesi)</div></div>
    <div class="headerRight" id="headerRight" title="Düzenlemek için 5 kez tıklayın">OLGUN BAŞKANLIĞI</div>
  </header>
  <nav class="toolbar" aria-label="Form işlemleri">
    <button type="button" class="primaryButton" id="exportButton">Excel Dışarı Aktar</button>
    <label class="fileButton importButton" for="importFile">Excel İçeri Aktar</label>
    <input id="importFile" type="file" accept=".xlsx,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet">
    <button type="button" id="printButton">PDF / Yazdır</button>
    <button type="button" class="dangerButton" id="resetButton">Formu Temizle</button>
    <span class="toolbarStatus" id="toolbarStatus" aria-live="polite">Talep numarası elle düzenlenebilir.</span>
  </nav>
  <main class="card">
    <form id="riskForm">
      <div class="formGrid">
        <h2 class="sectionTitle">1. Talep Kaydı</h2>
        <div class="group"><label for="requestNo">Talep Numarası</label><input id="requestNo" name="requestNo" type="text" value="SRI-" required></div>
        <div class="group"><label for="requestDate">Talep Tarihi</label><input id="requestDate" name="requestDate" type="date" required></div>
        <div class="group"><label for="requestType">Talep Türü</label><select id="requestType" name="requestType" required><option value="">Seçiniz</option><option>Güvenlik kontrolü istisnası</option><option>Süre uzatımı</option><option>Geçici kullanım</option><option>Teknik uyumsuzluk</option><option>Diğer</option></select></div>
        <div class="group"><label for="status">Talep Durumu</label><select id="status" name="status"><option>Taslak</option><option>İncelemede</option><option>Ek bilgi bekliyor</option><option>Onaylandı</option><option>Koşullu onaylandı</option><option>Reddedildi</option><option>Süresi doldu</option><option>Kapatıldı</option></select></div>
        <div class="group"><label for="requestedStart">İstenen Başlangıç Tarihi</label><input id="requestedStart" name="requestedStart" type="date"></div>
        <div class="group"><label for="requestedEnd">İstenen Bitiş Tarihi</label><input id="requestedEnd" name="requestedEnd" type="date" required></div>
        <div class="group half"><label for="previousRequest">Önceki Talep Numarası</label><input id="previousRequest" name="previousRequest" type="text" placeholder="Yenileme veya tekrar başvuruysa"></div>

        <h2 class="sectionTitle">2. Talep Sahibi ve Sorumlular</h2>
        <div class="group half"><label for="requester">Talep Eden Kişi</label><input id="requester" name="requester" type="text" required></div>
        <div class="group half"><label for="requesterRoleUnit">Görevi ve Birimi</label><input id="requesterRoleUnit" name="requesterRoleUnit" type="text"></div>
        <div class="group half"><label for="serviceOwner">Hizmet / Sistem Sahibi</label><input id="serviceOwner" name="serviceOwner" type="text" required></div>
        <div class="group half"><label for="riskOwner">Risk Sahibi</label><input id="riskOwner" name="riskOwner" type="text" required><span class="hint">Riski kabul etme yetkisi ve sorumluluğu bulunan yönetici.</span></div>
        <div class="group half"><label for="technicalOwner">Teknik Sorumlu</label><input id="technicalOwner" name="technicalOwner" type="text"></div>
        <div class="group half"><label for="securityReviewer">Güvenlik İnceleyicisi / Birimi</label><input id="securityReviewer" name="securityReviewer" type="text"></div>

        <h2 class="sectionTitle">3. Etkilenen Sistem ve Kapsam</h2>
        <div class="group half"><label for="systemName">Sistem, Uygulama veya Hizmet Adı</label><input id="systemName" name="systemName" type="text" required></div>
        <div class="group"><label for="inventoryId">Envanter Numarası</label><input id="inventoryId" name="inventoryId" type="text"></div>
        <div class="group"><label for="criticality">Kritiklik Seviyesi</label><select id="criticality" name="criticality"><option value="">Seçiniz</option><option>Düşük</option><option>Orta</option><option>Yüksek</option><option>Kritik</option></select></div>
        <div class="group half"><label for="environment">Ortam ve Bileşenler</label><input id="environment" name="environment" type="text" placeholder="Üretim, test, bulut, ağ bölgesi vb."></div>
        <div class="group half"><label for="usersUnits">Etkilenen Kullanıcılar / Birimler</label><input id="usersUnits" name="usersUnits" type="text"></div>
        <div class="group half"><label for="dataType">İşlenen Veri Türü / Sınıflandırması</label><select id="dataType" name="dataType"><option value="">Seçiniz</option><option>Genel</option><option>Kurum içi</option><option>Kişisel veri</option><option>Hassas / özel nitelikli veri</option><option>Gizli / kritik</option><option>Diğer</option></select></div>
        <div class="group half"><label for="dependencies">Dış Hizmet ve Tedarikçi Bağımlılıkları</label><input id="dependencies" name="dependencies" type="text"></div>

        <h2 class="sectionTitle">4. İstisna Talebinin Açıklaması</h2>
        <div class="group half"><label for="requirementSource">Gereksinimin Kaynağı</label><select id="requirementSource" name="requirementSource" required><option value="">Seçiniz</option><option>Kurum politikası</option><option>Güvenlik standardı / baz çizgi</option><option>Sözleşme</option><option>Mevzuat / düzenleyici yükümlülük</option><option>Teknik gereksinim</option><option>Diğer</option></select></div>
        <div class="group half"><label for="requirementReference">Kontrol Numarası, Madde ve Sürüm</label><input id="requirementReference" name="requirementReference" type="text"></div>
        <div class="group full"><label for="exceptionDetails">Karşılanamayan Gereksinim ve İstenen Sapma</label><textarea id="exceptionDetails" name="exceptionDetails" required placeholder="Hangi gereksinimin hangi bölümüne, nasıl ve ne ölçüde uyulamayacağını açıklayın."></textarea></div>
        <div class="group full"><label for="scopeDetails">İstisnanın Sınırları</label><textarea id="scopeDetails" name="scopeDetails" placeholder="Etkilenen sistemleri, kullanıcıları, işlemleri, ortamları ve kapsam dışı kalan alanları belirtin."></textarea></div>
        <div class="group full"><label for="businessReason">İş Gerekçesi ve İstisnaya İhtiyaç Nedeni</label><textarea id="businessReason" name="businessReason" required></textarea></div>
        <div class="group full"><label for="alternatives">Değerlendirilen Alternatifler ve Uygulanamama Gerekçeleri</label><textarea id="alternatives" name="alternatives"></textarea></div>
        <div class="group full"><label for="noExceptionImpact">İstisna Verilmezse Oluşacak Etki</label><textarea id="noExceptionImpact" name="noExceptionImpact"></textarea></div>

        <h2 class="sectionTitle">5. Risk Değerlendirmesi</h2>
        <div class="group full"><label for="riskScenario">Risk Senaryosu</label><textarea id="riskScenario" name="riskScenario" required placeholder="Tehdit, zafiyet ve olası olayın nasıl sonuç doğurabileceğini açıklayın."></textarea></div>
        <div class="group half"><label for="threatSource">Tehdit Kaynağı / Tehdit Bilgisi</label><input id="threatSource" name="threatSource" type="text"></div>
        <div class="group half"><label for="weakness">Zafiyet veya Kontrol Eksikliği</label><input id="weakness" name="weakness" type="text"></div>
        <div class="group"><label for="inherentLikelihood">İlk Olasılık (1–5)</label><select id="inherentLikelihood" name="inherentLikelihood" class="riskInput"><option value="">Seçiniz</option><option value="1">1 — Çok düşük</option><option value="2">2 — Düşük</option><option value="3">3 — Orta</option><option value="4">4 — Yüksek</option><option value="5">5 — Çok yüksek</option></select></div>
        <div class="group"><label for="inherentImpact">İlk Etki (1–5)</label><select id="inherentImpact" name="inherentImpact" class="riskInput"><option value="">Seçiniz</option><option value="1">1 — Çok düşük</option><option value="2">2 — Düşük</option><option value="3">3 — Orta</option><option value="4">4 — Yüksek</option><option value="5">5 — Çok yüksek</option></select></div>
        <div class="group"><label for="residualLikelihood">Kontroller Sonrası Olasılık (1–5)</label><select id="residualLikelihood" name="residualLikelihood" class="riskInput"><option value="">Seçiniz</option><option value="1">1 — Çok düşük</option><option value="2">2 — Düşük</option><option value="3">3 — Orta</option><option value="4">4 — Yüksek</option><option value="5">5 — Çok yüksek</option></select></div>
        <div class="group"><label for="residualImpact">Kontroller Sonrası Etki (1–5)</label><select id="residualImpact" name="residualImpact" class="riskInput"><option value="">Seçiniz</option><option value="1">1 — Çok düşük</option><option value="2">2 — Düşük</option><option value="3">3 — Orta</option><option value="4">4 — Yüksek</option><option value="5">5 — Çok yüksek</option></select></div>
        <div class="group full"><label>Gizlilik, Bütünlük ve Erişilebilirlik Etkisi</label><div class="checkGroup"><label class="checkItem"><input type="checkbox" name="ciaImpact" value="Gizlilik"> Gizlilik</label><label class="checkItem"><input type="checkbox" name="ciaImpact" value="Bütünlük"> Bütünlük</label><label class="checkItem"><input type="checkbox" name="ciaImpact" value="Erişilebilirlik"> Erişilebilirlik</label></div></div>
        <div class="group full"><label>Diğer Etki Alanları</label><div class="checkGroup"><label class="checkItem"><input type="checkbox" name="otherImpact" value="Görev / hizmet"> Görev / hizmet</label><label class="checkItem"><input type="checkbox" name="otherImpact" value="Vatandaş / müşteri"> Vatandaş / müşteri</label><label class="checkItem"><input type="checkbox" name="otherImpact" value="Operasyon"> Operasyon</label><label class="checkItem"><input type="checkbox" name="otherImpact" value="Mali"> Mali</label><label class="checkItem"><input type="checkbox" name="otherImpact" value="Mevzuat / uyum"> Mevzuat / uyum</label><label class="checkItem"><input type="checkbox" name="otherImpact" value="Kişisel veri"> Kişisel veri</label><label class="checkItem"><input type="checkbox" name="otherImpact" value="İtibar"> İtibar</label><label class="checkItem"><input type="checkbox" name="otherImpact" value="Ulusal güvenlik"> Ulusal güvenlik</label></div></div>
        <div class="group full"><label for="riskRationale">Puanlama Gerekçesi ve Varsayımlar</label><textarea id="riskRationale" name="riskRationale"></textarea></div>
        <div class="group full"><div class="scorePanel"><div class="scoreCard"><span class="scoreLabel">İlk Risk Puanı</span><div class="scoreValue"><span id="inherentScore">—</span><span id="inherentBadge" class="riskBadge">Değerlendirilmedi</span></div></div><div class="scoreCard"><span class="scoreLabel">Kontroller Sonrası Artık Risk</span><div class="scoreValue"><span id="residualScore">—</span><span id="residualBadge" class="riskBadge">Değerlendirilmedi</span></div></div><div class="scoreCard"><span class="scoreLabel">Puanlama Bilgisi</span><div class="hint">Örnek hesaplama: olasılık × etki. Kurumun onaylı risk metodolojisi esas alınmalıdır.</div></div></div></div>

        <h2 class="sectionTitle">6. Telafi Edici Kontroller</h2><p class="sectionIntro">İstisna süresince riski azaltan veya izleyen her önlemi sorumlusu ve doğrulama kanıtıyla kaydedin.</p>
        <div class="group full"><div class="dynamicList" id="controlsList"></div><button type="button" class="addRow" id="addControlButton">+ Kontrol Ekle</button></div>
        <div class="group full"><label for="existingControls">Mevcut Kontroller</label><textarea id="existingControls" name="existingControls" placeholder="İstisna öncesinde zaten uygulanan kontrolleri açıklayın."></textarea></div>

        <h2 class="sectionTitle">7. Kalıcı Çözüm ve Aksiyon Planı</h2><p class="sectionIntro">İstisnayı sona erdirecek kalıcı çözümü, sorumluyu, hedef tarihi ve doğrulama yöntemini belirtin.</p>
        <div class="group full"><div class="dynamicList" id="actionsList"></div><button type="button" class="addRow" id="addActionButton">+ Aksiyon Ekle</button></div>
        <div class="group full"><label for="acceptedResidualRisk">İstisna Süresince Kabul Edilen Artık Risk</label><textarea id="acceptedResidualRisk" name="acceptedResidualRisk"></textarea></div>

        <h2 class="sectionTitle">8. İnceleme ve Karar</h2>
        <div class="group half"><label for="securityReviewResult">Güvenlik İnceleme Sonucu</label><select id="securityReviewResult" name="securityReviewResult"><option value="">Seçiniz</option><option>Uygun görüş</option><option>Koşullu uygun görüş</option><option>Uygun görüş verilmedi</option><option>Ek bilgi gerekli</option></select></div>
        <div class="group half"><label for="securityReviewDate">Güvenlik İnceleme Tarihi</label><input id="securityReviewDate" name="securityReviewDate" type="date"></div>
        <div class="group half"><label for="decision">Karar</label><select id="decision" name="decision"><option value="">Seçiniz</option><option>Onay</option><option>Koşullu onay</option><option>Ret</option><option>Ek bilgi talebi</option><option>Üst makama eskalasyon</option></select></div>
        <div class="group half"><label for="decisionDate">Karar Tarihi</label><input id="decisionDate" name="decisionDate" type="date"></div>
        <div class="group half"><label for="approvingAuthority">Onaylayan Yetkili</label><input id="approvingAuthority" name="approvingAuthority" type="text"></div>
        <div class="group half"><label for="approvalRole">Onaylayan Yetkilinin Görevi</label><input id="approvalRole" name="approvalRole" type="text"></div>
        <div class="group full"><label for="decisionScope">Onaylanan Kapsam ve Koşullar</label><textarea id="decisionScope" name="decisionScope"></textarea></div>
        <div class="group full"><label for="decisionRationale">Karar Gerekçesi</label><textarea id="decisionRationale" name="decisionRationale"></textarea></div>
        <div class="group half"><label for="approvedStart">Onaylanan Başlangıç Tarihi</label><input id="approvedStart" name="approvedStart" type="date"></div>
        <div class="group half"><label for="approvedEnd">Onaylanan Bitiş Tarihi</label><input id="approvedEnd" name="approvedEnd" type="date"></div>

        <h2 class="sectionTitle">9. İzleme, Yenileme ve Kapatma</h2>
        <div class="group half"><label for="reviewDate">Ara Gözden Geçirme Tarihi</label><input id="reviewDate" name="reviewDate" type="date"></div>
        <div class="group half"><label for="renewalDate">Yenileme Başvuru Tarihi</label><input id="renewalDate" name="renewalDate" type="date"></div>
        <div class="group full"><label>Yeniden Değerlendirme Tetikleyicileri</label><div class="checkGroup"><label class="checkItem"><input type="checkbox" name="triggers" value="Yeni zafiyet veya tehdit"> Yeni zafiyet veya tehdit</label><label class="checkItem"><input type="checkbox" name="triggers" value="Güvenlik olayı"> Güvenlik olayı</label><label class="checkItem"><input type="checkbox" name="triggers" value="Sistem değişikliği"> Sistem değişikliği</label><label class="checkItem"><input type="checkbox" name="triggers" value="Kapsam genişlemesi"> Kapsam genişlemesi</label><label class="checkItem"><input type="checkbox" name="triggers" value="Kontrol başarısızlığı"> Kontrol başarısızlığı</label><label class="checkItem"><input type="checkbox" name="triggers" value="Gereksinim değişikliği"> Gereksinim değişikliği</label></div></div>
        <div class="group full"><label for="evidenceReferences">Kanıt ve Belge Referansları</label><textarea id="evidenceReferences" name="evidenceReferences" placeholder="Belge adı, kayıt numarası veya kurumsal depo referansı yazın."></textarea></div>
        <div class="group full"><label for="closureAction">İstisna Bittiğinde Uygulanacak İşlem</label><textarea id="closureAction" name="closureAction" placeholder="Kalıcı kontrolün devreye alınması, erişimin kapatılması veya başka bir sonlandırma adımını belirtin."></textarea></div>
        <div class="group half"><label for="closureDate">Kapatma Tarihi</label><input id="closureDate" name="closureDate" type="date"></div>
        <div class="group half"><label for="closedBy">Kapatan Kişi</label><input id="closedBy" name="closedBy" type="text"></div>
      </div>
    </form>
  </main>
</div>
<script>
(function(){
"use strict";
const STORAGE_KEY="olgun_siber_risk_istisnasi_v1",HEADER_KEY="olgun_risk_form_header_right",LOGO_KEY="olgun_risk_form_logo",EXCEL_NAME="Siber Risk İstisnası ve Risk Kabul Formu.xlsx";
const form=document.getElementById("riskForm"),statusText=document.getElementById("toolbarStatus"),controlsList=document.getElementById("controlsList"),actionsList=document.getElementById("actionsList"),headerRight=document.getElementById("headerRight"),logoBox=document.getElementById("logoBox"),orgLogo=document.getElementById("orgLogo"),logoFile=document.getElementById("logoFile");
const enc=new TextEncoder(),dec=new TextDecoder("utf-8");
function todayISO(){const d=new Date(Date.now()-new Date().getTimezoneOffset()*60000);return d.toISOString().slice(0,10)}
function updateStatus(s){statusText.textContent=s}
const savedLogo=localStorage.getItem(LOGO_KEY);if(savedLogo){orgLogo.src=savedLogo;orgLogo.style.display=""}let logoClicks=[];function requestLogoChange(){const now=Date.now();logoClicks=logoClicks.filter(t=>now-t<2500);logoClicks.push(now);if(logoClicks.length>=5){logoClicks=[];logoFile.click();updateStatus("Yeni logo seçin.")}}logoBox.addEventListener("click",requestLogoChange);logoBox.addEventListener("keydown",e=>{if(e.key==="Enter"||e.key===" "){e.preventDefault();requestLogoChange()}});logoFile.addEventListener("change",()=>{const file=logoFile.files&&logoFile.files[0];logoFile.value="";if(!file)return;if(!file.type.startsWith("image/")){alert("Lütfen bir resim dosyası seçin.");return}if(file.size>2*1024*1024){alert("Logo dosyası 2 MB veya daha küçük olmalıdır.");return}const reader=new FileReader();reader.onload=()=>{try{const value=String(reader.result);localStorage.setItem(LOGO_KEY,value);orgLogo.src=value;orgLogo.style.display="";updateStatus("Logo bu tarayıcıya kaydedildi.")}catch(err){alert("Logo tarayıcıya kaydedilemedi. Daha küçük bir resim seçin.")}};reader.onerror=()=>alert("Logo dosyası okunamadı.");reader.readAsDataURL(file)});
function u16(v){return new Uint8Array([v&255,(v>>>8)&255])}function u32(v){return new Uint8Array([v&255,(v>>>8)&255,(v>>>16)&255,(v>>>24)&255])}
function concatBytes(parts){let n=0;for(const p of parts)n+=p.length;const out=new Uint8Array(n);let o=0;for(const p of parts){out.set(p,o);o+=p.length}return out}
let crcTable=null;function crc32(bytes){if(!crcTable){crcTable=new Uint32Array(256);for(let n=0;n<256;n++){let c=n;for(let k=0;k<8;k++)c=(c&1)?(0xedb88320^(c>>>1)):(c>>>1);crcTable[n]=c>>>0}}let c=0xffffffff;for(const b of bytes)c=crcTable[(c^b)&255]^(c>>>8);return (c^0xffffffff)>>>0}
function makeStoredZip(files){const local=[],central=[];let offset=0;for(const file of files){const name=enc.encode(file.name),data=typeof file.data==="string"?enc.encode(file.data):file.data,crc=crc32(data);const lh=concatBytes([u32(0x04034b50),u16(20),u16(0),u16(0),u16(0),u16(0),u32(crc),u32(data.length),u32(data.length),u16(name.length),u16(0),name,data]);local.push(lh);const ch=concatBytes([u32(0x02014b50),u16(20),u16(20),u16(0),u16(0),u16(0),u16(0),u32(crc),u32(data.length),u32(data.length),u16(name.length),u16(0),u16(0),u16(0),u16(0),u32(0),u32(offset),name]);central.push(ch);offset+=lh.length}const cd=concatBytes(central),body=concatBytes(local),end=concatBytes([u32(0x06054b50),u16(0),u16(0),u16(files.length),u16(files.length),u32(cd.length),u32(body.length),u16(0)]);return concatBytes([body,cd,end])}
function xmlEscape(s){return String(s??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/\"/g,"&quot;").replace(/'/g,"&apos;")}
function colName(n){let s="";while(n){const r=(n-1)%26;s=String.fromCharCode(65+r)+s;n=Math.floor((n-1)/26)}return s}
function sheetXml(rows){let xml='<?xml version="1.0" encoding="UTF-8" standalone="yes"?><worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><sheetData>';rows.forEach((row,ri)=>{xml+='<row r="'+(ri+1)+'">';row.forEach((v,ci)=>{const ref=colName(ci+1)+(ri+1);xml+='<c r="'+ref+'" t="inlineStr"><is><t xml:space="preserve">'+xmlEscape(v)+"</t></is></c>"});xml+="</row>"});return xml+"</sheetData></worksheet>"}
function workbookBytes(formRows,detailRows){const types='<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"><Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/><Default Extension="xml" ContentType="application/xml"/><Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/><Override PartName="/xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/><Override PartName="/xl/worksheets/sheet2.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/></Types>';const rootRels='<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/></Relationships>';const book='<?xml version="1.0" encoding="UTF-8" standalone="yes"?><workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"><sheets><sheet name="Form" sheetId="1" r:id="rId1"/><sheet name="Kontroller ve Aksiyonlar" sheetId="2" r:id="rId2"/></sheets></workbook>';const bookRels='<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet1.xml"/><Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet2.xml"/></Relationships>';return makeStoredZip([{name:"[Content_Types].xml",data:types},{name:"_rels/.rels",data:rootRels},{name:"xl/workbook.xml",data:book},{name:"xl/_rels/workbook.xml.rels",data:bookRels},{name:"xl/worksheets/sheet1.xml",data:sheetXml(formRows)},{name:"xl/worksheets/sheet2.xml",data:sheetXml(detailRows)}])}
function requireOfflineZipSupport(){if(typeof DecompressionStream==="undefined")throw new Error("Bu tarayıcı .xlsx içe aktarmayı desteklemiyor. Güncel Chrome veya Edge kullanın.")}
function findEOCD(bytes){const v=new DataView(bytes.buffer,bytes.byteOffset,bytes.byteLength);for(let p=bytes.length-22;p>=Math.max(0,bytes.length-65557);p--){if(v.getUint32(p,true)===0x06054b50)return p}throw new Error("XLSX ZIP dizini bulunamadı.")}
async function unzipEntries(buffer){const bytes=new Uint8Array(buffer),v=new DataView(bytes.buffer,bytes.byteOffset,bytes.byteLength),eocd=findEOCD(bytes),count=v.getUint16(eocd+10,true),cdStart=v.getUint32(eocd+16,true),files=new Map();let p=cdStart;for(let i=0;i<count;i++){if(v.getUint32(p,true)!==0x02014b50)throw new Error("XLSX merkez dizini bozuk.");const method=v.getUint16(p+10,true),compressedSize=v.getUint32(p+20,true),nameLen=v.getUint16(p+28,true),extraLen=v.getUint16(p+30,true),commentLen=v.getUint16(p+32,true),localOffset=v.getUint32(p+42,true),name=dec.decode(bytes.slice(p+46,p+46+nameLen));p+=46+nameLen+extraLen+commentLen;const lp=localOffset;if(v.getUint32(lp,true)!==0x04034b50)throw new Error("XLSX yerel dosya başlığı bozuk.");const ln=v.getUint16(lp+26,true),le=v.getUint16(lp+28,true),start=lp+30+ln+le,packed=bytes.slice(start,start+compressedSize);let data;if(method===0)data=packed;else if(method===8){requireOfflineZipSupport();const stream=new Blob([packed]).stream().pipeThrough(new DecompressionStream("deflate-raw"));data=new Uint8Array(await new Response(stream).arrayBuffer())}else throw new Error("XLSX içindeki desteklenmeyen ZIP sıkıştırma yöntemi: "+method);files.set(name,data)}return files}
function parseXml(bytes){const doc=new DOMParser().parseFromString(dec.decode(bytes),"application/xml");if(doc.getElementsByTagName("parsererror").length)throw new Error("XLSX XML içeriği okunamadı.");return doc}
function localChildren(node,name){return Array.from(node.children||[]).filter(x=>x.localName===name)}
function colIndex(ref){const letters=(ref.match(/^[A-Z]+/i)||["A"])[0].toUpperCase();let n=0;for(const c of letters)n=n*26+c.charCodeAt(0)-64;return n-1}
function resolveTarget(base,target){if(target.startsWith("/"))return target.slice(1);const bits=base.split("/");bits.pop();for(const part of target.split("/")){if(part==="..")bits.pop();else if(part!==".")bits.push(part)}return bits.join("/")}
function sharedStrings(files){const data=files.get("xl/sharedStrings.xml");if(!data)return [];const doc=parseXml(data);return Array.from(doc.getElementsByTagNameNS("*","si")).map(si=>Array.from(si.getElementsByTagNameNS("*","t")).map(t=>t.textContent).join(""))}
function sheetRows(bytes,strings){const doc=parseXml(bytes),rows=[];for(const row of Array.from(doc.getElementsByTagNameNS("*","row"))){const out=[];for(const cell of localChildren(row,"c")){const idx=colIndex(cell.getAttribute("r")||"A1"),type=cell.getAttribute("t"),v=localChildren(cell,"v")[0],inline=localChildren(cell,"is")[0];let value="";if(type==="inlineStr"&&inline)value=Array.from(inline.getElementsByTagNameNS("*","t")).map(t=>t.textContent).join("");else if(v){value=v.textContent||"";if(type==="s")value=strings[Number(value)]||"";else if(type==="b")value=value==="1"?"TRUE":"FALSE"}out[idx]=value}rows.push(out)}return rows}
async function workbookSheets(buffer){const files=await unzipEntries(buffer),wb=parseXml(files.get("xl/workbook.xml")),rels=parseXml(files.get("xl/_rels/workbook.xml.rels")),relMap=new Map();for(const r of Array.from(rels.getElementsByTagNameNS("*","Relationship")))relMap.set(r.getAttribute("Id"),r.getAttribute("Target"));const strings=sharedStrings(files),out={};for(const s of Array.from(wb.getElementsByTagNameNS("*","sheet"))){const id=s.getAttributeNS("http://schemas.openxmlformats.org/officeDocument/2006/relationships","id")||s.getAttribute("r:id"),target=relMap.get(id);if(!target)continue;const path=resolveTarget("xl/workbook.xml",target),bytes=files.get(path);if(bytes)out[s.getAttribute("name")]=sheetRows(bytes,strings)}return out}
function makeInput(placeholder,key,value,type){const input=document.createElement("input");input.type=type||"text";input.placeholder=placeholder;input.dataset.key=key;input.value=value||"";return input}
function makeSelect(options,key,value){const select=document.createElement("select");select.dataset.key=key;options.forEach(text=>{const option=document.createElement("option");option.textContent=text;option.value=text;select.appendChild(option)});select.value=value||"";return select}
function createDynamicRow(container,kind,data){const item=data||{},row=document.createElement("div");row.className="dynamic-row"+(kind==="action"?" action-row":"");if(kind==="control"){row.appendChild(makeInput("Kontrol / önlem açıklaması","description",item.description));row.appendChild(makeInput("Sorumlu kişi / birim","owner",item.owner));row.appendChild(makeInput("Hedef tarih","due",item.due,"date"));row.appendChild(makeInput("Doğrulama / kanıt","proof",item.proof))}else{row.appendChild(makeInput("Kalıcı çözüm / aksiyon","description",item.description));row.appendChild(makeInput("Sorumlu kişi / birim","owner",item.owner));row.appendChild(makeInput("Hedef tarih","due",item.due,"date"));row.appendChild(makeSelect(["Planlandı","Devam ediyor","Tamamlandı","Gecikti"],"status",item.status||"Planlandı"))}const btn=document.createElement("button");btn.type="button";btn.className="removeRow";btn.textContent="−";btn.title="Bu satırı kaldır";btn.setAttribute("aria-label","Bu satırı kaldır");btn.addEventListener("click",()=>{row.remove();if(kind==="control"&&!controlsList.children.length)createDynamicRow(controlsList,"control");if(kind==="action"&&!actionsList.children.length)createDynamicRow(actionsList,"action");scheduleAutosave()});row.appendChild(btn);container.appendChild(row)}
function collectRows(container){return Array.from(container.querySelectorAll(".dynamic-row")).map(row=>{const result={};row.querySelectorAll("[data-key]").forEach(el=>result[el.dataset.key]=el.value);return result})}
function collectFields(){const fields={};form.querySelectorAll("input[name],select[name],textarea[name]").forEach(el=>{if(el.type==="checkbox"){if(!fields[el.name])fields[el.name]=[];if(el.checked)fields[el.name].push(el.value)}else fields[el.name]=el.value});return fields}
function collectData(){return{version:1,savedAt:new Date().toISOString(),fields:collectFields(),controls:collectRows(controlsList),actions:collectRows(actionsList)}}
function applyData(data){if(!data||typeof data!=="object")throw new Error("Geçersiz kayıt biçimi.");const fields=data.fields||{};form.querySelectorAll("input[name],select[name],textarea[name]").forEach(el=>{const value=fields[el.name];if(el.type==="checkbox"){el.checked=(Array.isArray(value)?value:[]).includes(el.value)}else if(value!==undefined&&value!==null)el.value=String(value)});controlsList.innerHTML="";(Array.isArray(data.controls)?data.controls:[]).forEach(item=>createDynamicRow(controlsList,"control",item));if(!controlsList.children.length)createDynamicRow(controlsList,"control");actionsList.innerHTML="";(Array.isArray(data.actions)?data.actions:[]).forEach(item=>createDynamicRow(actionsList,"action",item));if(!actionsList.children.length)createDynamicRow(actionsList,"action");growAllTextareas();updateRiskScores()}
function saveDraft(show){if(show&&!form.reportValidity())return;try{localStorage.setItem(STORAGE_KEY,JSON.stringify(collectData()));updateStatus("Taslak bu tarayıcıya kaydedildi: "+new Date().toLocaleTimeString("tr-TR"));if(show)alert("Taslak bu tarayıcıya kaydedildi.")}catch(e){updateStatus("Taslak kaydedilemedi.");if(show)alert("Taslak kaydedilemedi.")}}
function loadDraft(){try{const saved=localStorage.getItem(STORAGE_KEY);if(saved){applyData(JSON.parse(saved));updateStatus("Bu tarayıcıdaki son taslak yüklendi.")}}catch(e){updateStatus("Önceki taslak okunamadı.")}}
function labelFor(el){if(el.id){const label=document.querySelector('label[for="'+el.id+'"]');if(label)return label.textContent.trim()}const wrap=el.closest("label");if(wrap)return wrap.textContent.trim();const group=el.closest(".group");const label=group&&group.querySelector("label");return label?label.textContent.trim():el.name}
function exportExcel(){const rows=[["Alan","Form Alanı","Değer"]],grouped=new Set();form.querySelectorAll("input[name],select[name],textarea[name]").forEach(el=>{if(el.type==="checkbox"){if(grouped.has(el.name))return;grouped.add(el.name);const selected=Array.from(form.querySelectorAll('input[type="checkbox"][name="'+el.name+'"]')).filter(x=>x.checked).map(x=>x.value);rows.push([labelFor(el),el.name,selected.join("; ")])}else rows.push([labelFor(el),el.name,el.value])});const details=[["Tür","Açıklama","Sorumlu","Hedef Tarih","Doğrulama / Durum"]];collectRows(controlsList).forEach(x=>details.push(["Telafi Edici Kontrol",x.description||"",x.owner||"",x.due||"",x.proof||""]));collectRows(actionsList).forEach(x=>details.push(["Kalıcı Çözüm / Aksiyon",x.description||"",x.owner||"",x.due||"",x.status||""]));const bytes=workbookBytes(rows,details),blob=new Blob([bytes],{type:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}),url=URL.createObjectURL(blob),a=document.createElement("a");a.href=url;a.download=EXCEL_NAME;document.body.appendChild(a);a.click();a.remove();setTimeout(()=>URL.revokeObjectURL(url),1000);updateStatus("Excel dosyası dışarı aktarıldı.")}
function parseImportedExcel(sheets){const rows=sheets.Form;if(!rows||!rows.length)throw new Error("Form sayfası bulunamadı.");const fields={};rows.slice(1).forEach(row=>{const key=String(row[1]||"").trim();if(!key)return;const value=row[2]===undefined||row[2]===null?"":String(row[2]),checkbox=form.querySelector('input[type="checkbox"][name="'+key+'"]');fields[key]=checkbox?(value?value.split(";").map(x=>x.trim()).filter(Boolean):[]):value});const controls=[],actions=[];(sheets["Kontroller ve Aksiyonlar"]||[]).slice(1).forEach(row=>{const type=String(row[0]||"").trim(),item={description:String(row[1]||""),owner:String(row[2]||""),due:String(row[3]||"")};if(type==="Telafi Edici Kontrol"){item.proof=String(row[4]||"");controls.push(item)}else if(type==="Kalıcı Çözüm / Aksiyon"){item.status=String(row[4]||"Planlandı");actions.push(item)}});return{fields,controls,actions}}
async function importExcel(file){if(!file)return;try{const sheets=await workbookSheets(await file.arrayBuffer());applyData(parseImportedExcel(sheets));saveDraft(false);updateStatus("Excel dosyasındaki kayıt forma yüklendi.")}catch(e){console.error(e);alert("Excel dosyası okunamadı. Geçerli bir .xlsx dosyası seçin. "+(e&&e.message?e.message:""))}}
function band(score){if(!score)return{label:"Değerlendirilmedi",className:""};if(score<=4)return{label:"Düşük",className:"riskLow"};if(score<=9)return{label:"Orta",className:"riskModerate"};if(score<=16)return{label:"Yüksek",className:"riskHigh"};return{label:"Kritik",className:"riskCritical"}}
function setRisk(scoreId,badgeId,lid,iid){const l=Number(document.getElementById(lid).value),i=Number(document.getElementById(iid).value),score=l&&i?l*i:null,b=band(score);document.getElementById(scoreId).textContent=score?score+" / 25":"—";const badge=document.getElementById(badgeId);badge.textContent=b.label;badge.className="riskBadge "+b.className}
function updateRiskScores(){setRisk("inherentScore","inherentBadge","inherentLikelihood","inherentImpact");setRisk("residualScore","residualBadge","residualLikelihood","residualImpact")}
function growTextarea(el){el.style.height="auto";el.style.height=Math.max(el.scrollHeight,70)+"px"}function growAllTextareas(){form.querySelectorAll("textarea").forEach(growTextarea)}
function preparePrint(){form.querySelectorAll("textarea").forEach(el=>{let mirror=el.nextElementSibling;if(!mirror||!mirror.classList.contains("printMirror")){mirror=document.createElement("div");mirror.className="printMirror";el.insertAdjacentElement("afterend",mirror)}mirror.textContent=el.value||" "})}

document.getElementById("exportButton").addEventListener("click",exportExcel);document.getElementById("importFile").addEventListener("change",e=>{importExcel(e.target.files&&e.target.files[0]);e.target.value=""});document.getElementById("printButton").addEventListener("click",()=>{preparePrint();window.print()});window.addEventListener("beforeprint",preparePrint);
document.getElementById("resetButton").addEventListener("click",()=>{if(!confirm("Form alanlarını ve bu tarayıcıdaki kayıtlı taslağı silmek istiyor musunuz?"))return;localStorage.removeItem(STORAGE_KEY);form.reset();form.elements.requestNo.value="SRI-";form.elements.requestDate.value=todayISO();controlsList.innerHTML="";actionsList.innerHTML="";createDynamicRow(controlsList,"control");createDynamicRow(actionsList,"action");growAllTextareas();updateRiskScores();updateStatus("Form temizlendi.")});document.getElementById("addControlButton").addEventListener("click",()=>{createDynamicRow(controlsList,"control");scheduleAutosave()});document.getElementById("addActionButton").addEventListener("click",()=>{createDynamicRow(actionsList,"action");scheduleAutosave()});form.addEventListener("submit",e=>e.preventDefault());let autosaveTimer;function scheduleAutosave(){clearTimeout(autosaveTimer);autosaveTimer=setTimeout(()=>saveDraft(false),500)}form.addEventListener("input",e=>{if(e.target.matches("textarea"))growTextarea(e.target);scheduleAutosave()});form.addEventListener("change",e=>{if(e.target.classList.contains("riskInput"))updateRiskScores();scheduleAutosave()});
let clicks=[];headerRight.addEventListener("click",()=>{const now=Date.now();clicks=clicks.filter(t=>now-t<2500);clicks.push(now);if(clicks.length>=5&&headerRight.getAttribute("contenteditable")!=="true"){headerRight.setAttribute("contenteditable","true");headerRight.focus();updateStatus("Başlık sağ metni düzenlenebilir. Kaydetmek için alan dışına tıklayın.")}});headerRight.addEventListener("keydown",e=>{if(e.key==="Enter"){e.preventDefault();headerRight.blur()}});headerRight.addEventListener("blur",()=>{if(headerRight.getAttribute("contenteditable")==="true"){localStorage.setItem(HEADER_KEY,headerRight.textContent.trim());headerRight.removeAttribute("contenteditable");clicks=[];updateStatus("Başlık metni bu tarayıcıya kaydedildi.")}});const savedHeader=localStorage.getItem(HEADER_KEY);if(savedHeader)headerRight.textContent=savedHeader;
createDynamicRow(controlsList,"control");createDynamicRow(actionsList,"action");if(!form.elements.requestDate.value)form.elements.requestDate.value=todayISO();loadDraft();growAllTextareas();updateRiskScores();
})();
</script>
</body>
</html>