# Eklenti kilidini açma planı: aşama 1–3 — 2026-10-12 Sahibin soruları (2026-10-10): "Eklentilerle en fazla ne yapılabilir? Bambaşka bir uygulama yapıp içine entegre edilebilir mi? Sınırlarımız ne? Discord ile farkımız ne?" Önerilen sıra 1 → 2 → 3 → 4 → (5 + 6) → 7 idi. Sahip 2026-10-12'de "önerdiğin sırada devam edelim" dedi. Bu belge ilk üç aşamanın tasarımıdır. ## Karar / Öneri - **Aşama 1 (yapıldı, PR #100):** Pazar yeri eklentisinin korumalı çerçevesi ses ve video çalabiliyor, WebAssembly derleyebiliyor ve **yalnızca kendi dosyalarını** okuyabiliyor. Uygulamaya, API'ye, başka eklentiye ve dışarıya hâlâ erişemiyor. - **Aşama 2 (yapıldı, `feat/plugin-phase2`):** Eklenti dış adresler isteyebilir, ya da arayüzü tamamen kendi sitesinde olabilir (Discord Activities gibi). Bunun için **kurulumda sahibin açık onayı** şart. Onaylanan adresler o sürümün güvenlik politikasına yazılır. Plandan ayrılan noktalar aşağıda, "Aşama 2 — uygulamada" başlığında. - **Aşama 3:** Eklenti sunucuda **etkiler** üretebilir: - zamanlayıcı ("30 sn sonra fazı bitir"); - topluluk başına kalıcı küçük depo (lider tablosu); - sohbete uygulama mesajı; - (3b) ses odasında oyuncuyu susturma, örneğin VV'de ölüler. Her biri manifestte izin olarak istenir ve kurulumda onaylanır. **3a (zamanlayıcı, depo, sohbet) yapıldı (`feat/plugin-phase3`)**; plandan ayrılan noktalar "Aşama 3 — uygulamada" başlığında. 3b (`voice.mute`) sonra. - **Ortak temel:** Aşama 2 ve 3 aynı onay akışını kullanır. Önce temeli kurmak, sonra iki aşamayı paralel yürütmek en hızlısı. ## Aşama 1 — çerçevede medya, WebAssembly ve kendi dosyaları - **CSP:** - `script-src 'self' 'wasm-unsafe-eval'`; - `media-src data: blob:`; - `connect-src `. `` = `https:///api/plugin-ui///`. - **Adres yapılandırmadan gelir, istekten değil.** Kaynak `LOBBYFORGE_APP_ORIGIN`, yoksa `NEXT_PUBLIC_BASE_URL`. Dosyalar herkese açık önbelleklenir; Host başlığının politikaya yazılması önbellek zehirlemesine yol açardı. - **Dosya türleri:** - ses ve video: `mp3 ogg oga opus wav m4a flac webm mp4`; - veri: `wasm bin data pck`. - **Range isteklerine 206.** Safari aksi halde medya çalmıyor. - **Hâlâ yok:** worker, `eval`, SharedArrayBuffer. Çok iş parçacıklı Unity ve Godot derlemeleri çalışmaz; tek iş parçacıklı Godot web dışa aktarımı ve Emscripten derlemeleri çalışır. ## Ortak temel — manifestte istek, kurulumda onay **Manifest (sandbox-v1), yeni ve isteğe bağlı alanlar:** ```json { "network": { "connect": ["https://api.example.com"], "img": ["https://cdn.example.com"], "media": ["https://cdn.example.com"], "frame": ["https://embed.example.com"] }, "ui": { "url": "https://game.example.com/play" }, "permissions": ["timers", "storage", "chat"] } ``` **Doğrulama:** Her iki ikiz doğrulayıcı (`apps/web/lib/sandbox-manifest.ts`, `apps/plugin-worker/src/manifest.ts`) ortak vaka tablosuyla doğrular. - **Adres listeleri:** - Yalnız `https:`. - Yalnız köken (origin): yol, sorgu, parça, joker ve kullanıcı bilgisi yok. - IP adresi, `localhost`, `.local`, `.internal`, `.lan`, `.home.arpa` yok. Aksi halde izleyicilerin tarayıcısı yerel ağı taramak için kullanılabilir. - Liste başına en çok 8 adres. - **`ui.url`:** - `https:` olmalı; - kökeni kurulumun kendi kökeni olamaz (çerçeve kendi sandbox'ını kaldırabilirdi); - aynı kurallardan geçer. - **`permissions`:** Bilinen adlar `timers`, `storage`, `chat`, `voice.mute`. Bilinmeyen ad paketi reddettirir. **Onay:** - Kurulum API'si paketi indirip doğruladıktan sonra paket `network`, `ui.url` ya da `permissions` istiyorsa ve istekte birebir eşleşen bir `approve` yoksa kurmaz. `409 approval_required` ile istenenleri döner. - Pazar yeri ekranı onay penceresini gösterir: - Bu eklenti şu adreslere bağlanabilir: … - Arayüzü şu sitede çalışır: game.example.com. O site her izleyicinin oyunda gördüğünü ve görünen adını görür. - İzinler: zamanlayıcı, kalıcı depo, sohbete mesaj. - Sahip onaylayınca istek `approve` ile yinelenir. - Programla yapılan bir kurulum hiçbir şeyi sessizce onaylayamaz. - **Sürüm yükseltme:** Yeni sürüm yeni bir şey istiyorsa onay yeniden sorulur. Pencere farkı gösterir. - **Kayıt:** - Onay `active.json`'a `approved: { network, ui, permissions, at }` olarak yazılır. - Denetim kaydına `plugin.install` satırı düşer. - **Kaynak:** Politika etkin sürümün manifestinden üretilir. Sürüm değişmezdir; kurulum onaydır. - **Kaldırma:** Kaldırmak ya da devre dışı bırakmak her şeyi geri alır. ## Aşama 2 — dış adresler ve dış arayüz **Dosya modu (`ui: true`):** Onaylı adresler çerçevenin CSP'sine eklenir: `connect-src`, `img-src`, `media-src` ve `frame-src`. - Çerçevenin içindeki iframe, sandbox bayraklarını miras alır; opak köken kalır. - Çerez ve depolama isteyen dış siteler bu modda çalışmaz. **Dış arayüz modu (`ui: { url }`):** Lobi, eklentinin sitesini doğrudan çerçeveler. Discord Activities modeline denk gelir. - **Çerçeve:** `