d1/iki-origin-fizibilite — kaynak8274 bayt ← review
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>hart artifact</title><script>window.HART_DATA={};</script></head><body><!doctype html><html lang="tr"><head><meta charset="utf-8">
<title>İkinci-Origin Fizibilite Raporu (ARTF-021 / F5)</title><meta name="robots" content="noindex">
<meta name="viewport" content="width=device-width,initial-scale=1">
<style>
body{max-width:860px;margin:0 auto;padding:28px 20px 60px;
font-family:system-ui,-apple-system,'Segoe UI',sans-serif;color:#1f2328;
line-height:1.65;font-size:15px}
h1{font-size:1.7em;border-bottom:1px solid #d8dee4;padding-bottom:.3em}
h2{font-size:1.35em;border-bottom:1px solid #eaeef2;padding-bottom:.25em;margin-top:1.6em}
h3{font-size:1.1em} a{color:#0969da;text-decoration:none}
a:hover{text-decoration:underline}
code{background:#eff1f3;padding:.15em .4em;border-radius:6px;
font:85% ui-monospace,SFMono-Regular,monospace}
pre{background:#f6f8fa;border:1px solid #e7eaee;border-radius:8px;
padding:12px 14px;overflow-x:auto}
pre code{background:none;padding:0;font-size:85%}
table{border-collapse:collapse;margin:1em 0}
th,td{border:1px solid #d0d7de;padding:6px 12px;font-size:.92em}
th{background:#f6f8fa}
blockquote{border-left:3px solid #d0d7de;margin:0;padding:0 14px;color:#59636e}
img{max-width:100%} hr{border:none;border-top:1px solid #d8dee4}
ul,ol{padding-left:1.6em} li{margin:.2em 0}
footer{margin-top:3em;padding-top:12px;border-top:1px solid #eaeef2;
font-size:12px;color:#59636e}
@media(prefers-color-scheme:dark){
body{background:#0d1117;color:#e6edf3}
h1{border-color:#30363d}h2{border-color:#21262d}
code{background:#2d333b}pre{background:#161b22;border-color:#30363d}
pre code{background:none}
th,td{border-color:#30363d}th{background:#161b22}
blockquote{border-color:#30363d;color:#8b949e}
a{color:#58a6ff}hr{border-color:#30363d}footer{border-color:#21262d;color:#8b949e}}
</style></head><body>
<h1>İkinci-Origin Fizibilite Raporu (ARTF-021 / F5)</h1>
<p>Tarih: 2026-09-28 · Durum: <strong>rapor — operatör kararı bekliyor</strong>
Bağlı: PLAN-ARTF-002 F5 · raw/web-claude-artifacts-2026.md</p>
<h2>Neden konu açıldı</h2>
<p>Claude Artifacts'ın en güçlü izolasyonu iki-origin: artifact'lar ayrı
host'ta (kullanıcı-yüzü <code>claude.ai</code>'dan ayrı) sunulur; artifact JS'i kötü
niyetli olsa bile ana oturum/cookie/token'a erişemez. Bizde tek-origin
(artifacts.gonet.com.tr) + hart'ın <code>default-src 'none'</code>+<code>script-src 'unsafe-inline'</code> CSP iskeleti + review iframe'i var.</p>
<h2>Ölçülmüş bulgular (2026-09-28, canlı sistem)</h2>
<ol>
<li><strong>iframe sandbox'suz:</strong> <code>&lt;iframe id=&quot;fr&quot; src=&quot;/a/...&quot;&gt;</code> — sandbox
attribute yok. Artifact ile parent <strong>same-origin</strong> olduğundan artifact
JS'i <code>parent.document</code>'a tam erişir: review sayfasının DOM'unu okur/
değiştirir, parent bağlamından <code>/review/arti/api/*</code> uçlarını
<strong>declare gate'i baypas ederek</strong> doğrudan çağırır.</li>
<li><strong>Cross-artifact store erişimi:</strong> server <code>o/n</code>'yi path'ten alır —
<code>/review/arti/api/store/d1/BASKA</code> ucu herkesin herkese açık
(link-sahipliği modeli; yorumlar da öyle). &quot;Kişisel&quot; veri için
bu yetersiz; shared state için kabul edilebilir.</li>
<li><strong>Gerçek sınır şu an:</strong> server-side rate limit + kota + artifact_var
(doğru tasarım — client kapısı zaten baypas edilebilir kabul
edilmeliydi; öyleydi).</li>
<li><strong>DNS:</strong> <code>*.gonet.com.tr</code> wildcard <strong>yok</strong> (foo-xyz-123 sorgusu boş).
NS Cloudflare (titan/evelyn) → wildcard cert DNS-01 + CF API token
ister.</li>
<li><strong>Traefik:</strong> Coolify label'ları path-bazlı —
hart <code>Host(artifacts.gonet.com.tr) &amp;&amp; PathPrefix(/)</code>, review
<code>PathPrefix(/review|/asistan)</code>. Yeni Host kuralı = compose'a bir
label bloğu (Coolify domains alanına domain eklemek de yeter).</li>
<li><strong>Cert:</strong> tek subdomain (<code>a.gonet.com.tr</code>) için HTTP-01 yeterli —
wildcard cert şart DEĞİL.</li>
</ol>
<h2>Tehdit modeli</h2>
<table>
<thead>
<tr>
<th>Kim</th>
<th>Ne yapabilir bugün</th>
<th>Sonuç</th>
</tr>
</thead>
<tbody>
<tr>
<td>Kötü artifact JS</td>
<td>parent DOM oku/yaz, arti API'lerini o/n kısıtsız çağır</td>
<td>yorumları taklit/deforme, başka store'ları oku/yaz; LLM kota tüketimi (rate+token frenli)</td>
</tr>
<tr>
<td>Bizde oturum yok</td>
<td>cookie/token ÇALAMAZ — çünkü yok</td>
<td>hesapsız model bu yüzden riski düşürür</td>
</tr>
<tr>
<td>hart CSP 'none'</td>
<td>dış ağ yok (connect-src none)</td>
<td>veri sızıntısı postMessage dışında yok — postMessage'ı da yalnız parent dinler</td>
</tr>
</tbody>
</table>
<p>Risk seviyesi: <strong>orta</strong> — bizde çalınacak oturum yok ama artifact'lar
arası &quot;güven sınırı&quot; fiilen yok.</p>
<h2>Seçenekler</h2>
<table>
<thead>
<tr>
<th>Seçenek</th>
<th>Ne yapılır</th>
<th>Maliyet</th>
<th>Kazanç</th>
<th>Kayıp</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>A (öneri)</strong> <code>a.gonet.com.tr</code></td>
<td>artifact <code>/a/</code> trafiği ikinci host'a; review/asistan ana host'ta kalır</td>
<td>DNS A kaydı (Cloudflare'da 1dk) + compose'a ikinci domain + arti protokol revizyonu</td>
<td>artifact JS parent'a artık same-origin DEĞİL — DOM erişimi imkânsız; declare gate gerçek sınıra döner; CSP postMessage'la köprü korunur</td>
<td>arti protokolü v2 gerekir (alt.)</td>
</tr>
<tr>
<td>B wildcard <code>*.gonet.com.tr</code></td>
<td>her artifact kendi subdomain</td>
<td>DNS-01 + CF API token + hostname→artifact map katmanı (hart path-bazlı — ek middleware)</td>
<td>en güçlü izolasyon (Claude modeline en yakın)</td>
<td>en pahalı: DNS API entegrasyonu + map katmanı + her yeni alt-alanın servis tarafında çözülmesi</td>
</tr>
<tr>
<td>C sandbox iframe (ara adım)</td>
<td><code>&lt;iframe sandbox=&quot;allow-scripts&quot;&gt;</code></td>
<td>1 satır</td>
<td>parent DOM erişimi kesilir hemen</td>
<td><code>e.origin='null'</code> + contentDocument kapanır → declare-meta okunamaz (aynı protokol fix'i yine şart); <code>/a/</code> doğrudan açılırsa sandbox'suz kalır</td>
</tr>
</tbody>
</table>
<h2>Öneri</h2>
<p><strong>Kademeli: önce C, sonra A.</strong> C ucuz ve bugünkü en keskin açığı
(parent DOM erişimi) hemen kapatır; A kalıcı hedef — Claude'un
mimarisine denk düşer ve hediyesi: arti köprüsünün &quot;iframe içi same-origin
DOM okuma&quot; bağımlılığı zaten kırılganlık kaynağı, ikisi aynı
protokol fix'ini ister.</p>
<p><strong>Protokol v2 (A veya C'de ortak):</strong> declare-meta okuması yerine shim
ilk mesajı kendisi ilan eder — <code>arti.hello {caps:[...]}</code> (aktif ilan).
Parent <code>e.source===FR.contentWindow</code> kontrolü yeterli (origin cross-
origin'de sabit değer değil). Caps listesi doğrulanamaz kaynaktan gelir
ama zaten doğrulanamazdı (meta'yı da artifact yazar) — gate'in işlevi
&quot;kazara aşma&quot; değil &quot;kasıtlı aşma&quot;yı sınırlamak değilse anlamlıdır;
asıl sınır server-side'da kalır.</p>
<h2>Geçiş planı (A seçilirse)</h2>
<ol>
<li>Cloudflare'da <code>a.gonet.com.tr</code> A kaydı → cx53 IP (5 dk).</li>
<li>Coolify service'e domain ekle: <code>a.gonet.com.tr</code> → hart'a
<code>Host(a.gonet.com.tr) &amp;&amp; PathPrefix(/a|/_hart)</code> kuralı; ana host'taki
<code>/a/</code> kuralı 301'e döner ya da paralel kalır (geçiş süresince
paralel önerilir).</li>
<li>arti protokolü v2: shim <code>arti.hello</code> gönderir; parent caps'i mesajdan
alır (meta okuması kaldırılır — hem A hem C'ye hazır).</li>
<li>Review iframe src <code>https://a.gonet.com.tr/a/...</code> olur; postMessage
targetOrigin <code>https://a.gonet.com.tr</code>.</li>
<li>Smoke: artifact store/complete/download köprüsü cross-origin'de.</li>
</ol>
<h2>Karar bekleyen</h2>
<p>Operatöre: A / B / C / yok (status quo kabul) — öneri A.</p>

<footer>Markdown kaynaktan render — artifacts-d1 · md-publish</footer>
</body></html></body></html>
remix: kaynağı kopyala → düzenle → yeni artifact olarak publish et: TOKEN=$(grep '^HART_TOKEN=' ~/Code/artifacts-d1/.env | cut -d= -f2) curl -X POST "https://artifacts.gonet.com.tr/v1/publish?owner=d1&artifact=YENI-SLUG&visibility=unlisted" -H "Authorization: Bearer $TOKEN" -H 'content-type: text/html' --data-binary @duzenlenmis.html (remix publish tokenı ister — HART_TOKEN .env'de; hesapsız modelde çatal link ile değil bu komutla olur)