@nsupp/desktop
v0.1.0
Published
nsupp desktop shell — Electron module (corner icon or embedded) plus the bridge contract and host examples for WebView2, WebKitGTK and Tauri.
Maintainers
Readme
@nsupp/desktop
Masaüstü uygulamalarına nsupp destek sohbetini ekleyen kabuk katmanı: Electron modülü (iki kip)
- köprü sözleşmesi + WebView2 / WebKitGTK / Tauri host örnekleri.
Durum: deneysel. Paket ve Windows örnekleri artık gerçek bir Windows 11 makinesinde DERLENİYOR (aşağıda ölçümler), ama hiçbiri gerçek bir pencerede gözle doğrulanmadı — derlenmek çalışmak değildir. Gözle doğrulanana kadar "destekleniyor" demiyoruz. Bkz. Doğrulama.
Ne GÖNDERİYORUZ, ne GÖNDERMİYORUZ
| | |
|---|---|
| ✅ Electron modülü (köşe ikonu / gömülü kip) | Windows · Linux · macOS |
| ✅ Köprü sözleşmesi + kaynak kapısı + önyükleme üreteci (JS) | her kabuk aynı kopyayı kullanır |
| ✅ Host örnekleri: WebView2 (C#), WebKitGTK (C), Tauri (Rust) | ornekler/ |
| ❌ Windows için derlenmiş yerel SDK | yazılmadı — gerekmiyor (aşağıda gerekçe) |
| ❌ Linux için derlenmiş yerel SDK | yazılmadı — WebKitGTK ABI çatallı, köprü zaten JS |
Neden yerel SDK yok? Sohbetin görünümü ve işlevinin tamamı web widget'ıdır (~4900 satır);
yerel arayüzü ikinci kez yazma yolu bu üründe zaten ölçülerek terk edildi. Kabuğun işi ~50
satırdır: gezinme kilidi, dış-bağlantı kapısı, jeton saklama, önyükleme enjeksiyonu. Linux'ta
WebKitGTK'nın register_script_message_handler'ı sayfaya birebir
window.webkit.messageHandlers.nsupp.postMessage verdiği için widget'ın mevcut köprü dalı
hiçbir değişiklik olmadan çalışır; Windows'ta ise kabuk, widget'ın bildiği adı
(window.NsuppNative) WebView2'nin chrome.webview kanalının üstüne tanımlar. widget.js'e bu
program kapsamında tek satır eklenmemiştir.
Kurulum (Electron)
npm i @nsupp/desktopElectron 30+ gerekir: gömülü kip WebContentsView kullanır (Electron 30.0.0'da eklendi,
BrowserViewın yerini aldı). electron bu paketin isteğe bağlı peer bağımlılığıdır ve paket
onu kendisi import ETMEZ — modülü siz verirsiniz (test edilebilirliğin ve sürüm bağımsızlığının
şartı).
① Köşede ikon (balon)
import * as elektron from 'electron';
import { NsuppElectronChatController, NsuppElectronChatPresenter } from '@nsupp/desktop';
const kontrolcu = new NsuppElectronChatController({
elektron,
config: { apiBase: 'https://api.nsupp.com', publicKey: 'pk_…', appKey: 'ak_…' },
});
const sunum = new NsuppElectronChatPresenter(kontrolcu, { kip: 'balon' });
sunum.start(); // köşede 60×60 ikon
// sunum.present() / dismiss() / toggle()
await sunum.reset(); // çıkışta: jeton + WebView deposu silinir, pencereler kapanırkip: 'panel' seçerseniz ikon çizilmez; sohbeti kendi menünüzden present() ile açarsınız.
② Kendi arayüzünüze gömülü
import { NsuppElectronChatView } from '@nsupp/desktop';
const gorunum = new NsuppElectronChatView(kontrolcu);
gorunum.mount(pencere, { x: 0, y: 0, width: 360, height: 520 });
// pencere yeniden boyutlanınca: gorunum.setBounds({ … })
await gorunum.reset(); // çıkışta: görünüm sökülür, jeton + WebView deposu silinirGömülü kipte kontrolcu.reset()'i doğrudan çağırmayın: pencere sizindir, kapatacak bir pencere
yoktur ve görünüm sökülmediği için WebContentsView sıfırlanmış oturumun sohbetini ekranda
göstermeye devam eder. gorunum.reset() önce söker, sonra siler.
Gömülü kip iframe değildir: /widget/:publicKey/app sayfası frame-ancestors 'none' +
X-Frame-Options: DENY taşır (bilinçli — o sayfa aktif ziyaretçi oturumu taşır ve çerçevelenmesi
clickjacking yüzeyi açar). Bunun yerine ayrı bir üst-düzey WebContentsView kullanılır. O
sayfayı çerçevelenebilir listeye eklemeyin.
Preload
Modül preload dosyasını paket kökünden çözer (preload.cjs). Paketleyici (asar/webpack) yolu
değiştiriyorsa preloadYolu ile kendi kopyanızın yolunu verin — dosyayı değiştirmeyin, üç
guard'ı orada yaşıyor.
Görünüm ve ayarlar
Widget'ın görünümü, metinleri ve bölümleri (Makaleler, ön-sohbet, hamburger menüsü, marka satırı)
yalnız çalışma alanı ayarından gelir; kabuk hiçbirini geçersiz kılmaz. Pencere ölçüleri web
widget'ıyla eşlenmiştir ve tek kaynaktan okunur: src/olculer.json (panel 360×520, ikon 60, kenar
20, panel alt boşluğu 76, dikey pay 120). olculer-kayma.test.ts bu sayıları widget.js
kaynağıyla karşılaştırır — CSS değişirse test kırmızı yanar. Panel, çalışma alanına web'deki
max-width/max-height kurallarıyla AYNI biçimde sığdırılır (panelBoyutu(); iOS/macOS
NsuppOlculer.panelBoyutu ile aynı formül).
Köşe ikonunun rengi çalışma alanından ÇEKİLMEZ (ikon, widget yapılandırması indirilmeden önce
görünür; rengi ağdan beklemek ikonun geç ve renk atlayarak belirmesi olurdu). Sistem vurgu rengi
kullanılır; Linux'ta sistem vurgu rengi API'si YOKTUR, orada nötr bir ton kullanılır ve
balonRengi: '#rrggbb' ile kendi renginizi verebilirsiniz.
Diğer kabuklar (WebView2 · WebKitGTK · Tauri)
ornekler/ altındaki üç dosya, aynı kapıları (gezinme kilidi · dış bağlantı · köprü kaynak
doğrulaması · oturum nesli · medya izni) kendi platformlarında kurar. JS tarafı için bu
paketi kullanın — kaynak kapısını ve önyükleme scriptini yeniden yazmayın:
import { kaynakCoz, hostAdresi, onyuklemeJS } from '@nsupp/desktop';
const kaynak = kaynakCoz('https://api.nsupp.com');
const adres = hostAdresi('https://api.nsupp.com', 'pk_…');
const js = onyuklemeJS({ kaynak, appKey, visitorToken, kopru: 'webview2' }); // Linux/macOS: 'hazir'Güvenlik — platform platform
| Kontrol | Electron | WebView2 | WebKitGTK |
|---|---|---|---|
| Gezinme kilidi (ana çerçeve) | will-navigate | NavigationStarting | decide-policy |
| Gezinme kilidi (alt çerçeve) | will-frame-navigate | FrameNavigationStarting | aynı sinyal (çerçeve ayrımı yok) |
| Yeni pencere → dışarı | setWindowOpenHandler + shell.openExternal | NewWindowRequested | NEW_WINDOW_ACTION |
| Köprüde kaynak doğrulaması | ✅ senderFrame.url + ana çerçeve kimliği | ✅ args.Source | ❌ yok (aşağıya bakın) |
| Oturum verisi | bellek-içi partition + clearStorageData() | ClearBrowsingDataAsync() | website_data_manager_clear() |
| Çıkış nesli (epok) | ✅ webContents başına (bu paket) | ✅ NavigationId başına (yalnız örnekte) | ✅ load-changed damgası (yalnız örnekte) |
| Medya izni (mikrofon) | setPermissionRequestHandler + setPermissionCheckHandler | PermissionRequested (+ FrameCreated) | permission-request (+ enable-media-stream) |
Ortak kurallar:
- Kaynak karşılaştırması ayrıştırılmıştır (şema+host+port, varsayılan port normalize).
https://[email protected]/xvehttps://api.nsupp.com.evil.example/xmetin öneki testini geçer, kaynak kapısını GEÇMEZ (altın vektör olarak testte kilitlidir). - Dış bağlantı yalnız pencere-açma yolundan sistem tarayıcısına gider (izinli şemalar:
http,https,mailto,tel). Gezinme yolunda tarayıcı AÇILMAZ: gezinme kullanıcı niyetini bildirmez ve niyetsiz bir yönlendirmenin varsayılan tarayıcıyı açması kimlik-avı yüzeyidir. - Sohbet gövdeleri diske yazılmaz (bellek-içi WebView oturumu). Ziyaretçi jetonu ise kabuk
tarafından kalıcı saklanır — saklanmasaydı her açılış yeni ziyaretçi üretir ve geçmiş kaybolurdu.
Jeton anonim oturum tanıtıcısıdır, kimlik sırrı değildir;
reset()onu siler.
Medya izni (Electron) — kapı bir yüzeyi AÇMAZ, DARALTIR
Widget'ın sesli mesajı web'de eksiksiz çalışır, çünkü izni tarayıcı sorar. WebView'da soran yoktur: kararı barındıran uygulama verir. Electron'un bu karardaki varsayılanı — resmî güvenlik dokümanı, "Handle session permission requests from remote content" — tüm izin isteklerini otomatik onaylamaktır. Yani kanca kurulmadan önceki durum "mikrofon kapalı" değil, "mikrofon da kamera da konum da bildirim de uzak içeriğe açık"tı.
NsuppElectronChatController kurulurken iki kancayı da bağlar ve ikisi de aynı kararı verir:
setPermissionRequestHandler— gerçek yakalama isteği. DetaymediaTypestaşır (çoğul, dizi).setPermissionCheckHandler— izin sorgusu. DetaymediaTypetaşır (tekil dize,unknownolabilir). İki kanca ayrı çağrılır; resmî sıralama önce kontrol, reddedilirse istektir — yalnız birini kurmak diğerinin varsayılanını yürürlükte bırakır.
Kapı üç koşulu birlikte arar, ve media içinde yalnız audio geçer:
| Koşul | Sonuç |
|---|---|
| İzin media değil (kamera, konum, bildirim, MIDI, display-capture, fileSystem…) | RET |
| Kaynak bizim origin'imiz değil (ayrıştırılmış şema+host+port) | RET |
| İstek ana çerçeveden gelmiyor (isMainFrame !== true) | RET |
| mediaTypes içinde audio dışında bir tür var (video, ['audio','video']) | RET |
| Tür hiç bildirilmemiş ya da unknown | RET (sesin istendiği kanıtlanamaz) |
| Bizim ana çerçevemiz + yalnız audio | İZİN |
Kanca session.defaultSessiona değil, yalnız kendi bellek-içi partition'ımıza (nsupp-chat)
kurulur — satıcının kendi pencerelerinin kamerası/konumu bizim "yalnız ses" kuralımıza takılmaz.
Her ret sebebiyle birlikte onHata'ya yazılır: "mikrofon düğmesine bastım, hiçbir şey olmuyor" tek
başına teşhis edilemez.
macOS'ta kod tek başına YETMEZ (satıcının işi). Oturum kancası Chromium katmanını açar; işletim sistemi katmanını açmaz. macOS 10.14+ mikrofon için TCC onayı ister ve uygulamanın
Info.plist'indeNSMicrophoneUsageDescriptionyoksa istem hiç gösterilmez — sesli mesaj sessizce ölür. Paketleyicinizde bu anahtarı tanımlayın; durumusystemPreferences.getMediaAccessStatus('microphone')ile okuyabilir, istemisystemPreferences.askForMediaAccess('microphone')ile gösterebilirsiniz (yalnız macOS; daha önce reddedilmişse istem gösterilmez, kullanıcı Sistem Ayarları'ndan değiştirmelidir). Bu paket bu çağrıyı sizin adınıza yapmaz: TCC istemi uygulamanın tamamına aittir ve ne zaman gösterileceği satıcının ürün kararıdır.
Kapının kablolaması electron-kablolama.test.ts içinde sahte bir oturumla sürülerek pinlidir
(kanca gerçekten kuruldu mu, ['audio','video'] reddedildi mi, ret onHata'ya yazıldı mı). Yine de
gerçek bir Electron penceresinde mikrofonla ölçülmedi — yeşil test "çalışıyor" demek değildir.
reset() GERİ ALINAMAZ — oturum nesli
reset() asenkrondur (clearStorageData bir Promise döner) ve sayfa, pencereler kapanana kadar
yaşamaya devam eder. O aralıkta sayfadan çıkan bir jeton mesajı bütün güvenlik kapılarını geçer
— kaynağı bizim, gönderen ana çerçeve — ve jetonu geri yazarak çıkışı sessizce geri alırdı:
kullanıcı çıkış yaptığını sanarken bir sonraki açılışta aynı ziyaretçi oturumu geri gelirdi. Kaynak
ve çerçeve kapıları bunu yakalayamaz; yakalayan tek şey nesildir.
Bu yüzden Electron denetleyicisi bir oturum nesli (epok) tutar: reset() nesli senkron olarak,
ilk satırda artırır ve kablolanmış her webContents kablolandığı nesli taşır. Nesli tutmayan
gönderenin mesajı yok sayılır (ve sebebi onHata'ya yazılır — sessiz reddetme teşhis edilemez).
Sıfırlamadan sonra açılan pencere yeni nesille kablolanır, normal çalışır.
ornekler/webview2-host.cs aynı korumayı Windows tarafında kurar (kopyalayanın referansı odur):
nesil Sifirlanın ilk satırında, senkron artar; her gezinme NavigationStartingte başladığı
nesille işaretlenir ve ContentLoading ekrandaki belgeye o damgayı koyar — sıfırlamadan ÖNCE
başlamış bir gezinme sonradan yüklense bile bayat sayılır. Önyükleme script'i de Sifirlada sökülüp
jetonsuz hâliyle yeniden eklenir (script bir kopyadır: tazelenmezse eski jetonu taşır).
ornekler/webkitgtk-host.c aynı korumayı Linux'ta kurar: nesil nsupp_sifirlanın ilk satırında,
senkron artar; load-changed → WEBKIT_LOAD_STARTED yüklemenin başladığı nesli saklar ve
WEBKIT_LOAD_COMMITTED ekrandaki belgeye o damgayı koyar (damgasız/tanınmayan belge bayat
sayılır). WebKitGTK'da gezinme kimliği yoktur; tek WebView'da aynı anda tek provisional yükleme
olduğu için tek bekleme yuvası yeterlidir. Mesaj anında gönderen belge ayırt edilemediğinden
(aşağıdaki "bilinen sınır") kapı "ekrandaki belge güncel nesle ait mi" sorusuna indirgenir.
ornekler/tauri-host.rs damgayı pencere başına koyar: initialization_script (jetonu taşıyan
kopya) pencere kurulurken sabitlendiği için o pencerede doğan her belge, pencerenin kurulduğu nesle
aittir; damgayı on_page_load (PageLoadEvent::Started) yazar. Çıkış nesli artırır, pencereyi
destroy() eder ve jetonsuz script'le yeniden kurar — yalnız reload etmek eski jetonu sayfaya
geri enjekte ederdi.
Linux örneği (
webkitgtk-host.c) artık DERLENİYOR ve ÇALIŞIYOR — gerçek WebKitGTK 2.50.6 / GTK 3.24.38 üzerinde ölçüldü (Xvfb'li konteyner): köprü kuruluyor, panel açılıyor, ziyaretçi jetonu depoya yazılıyor. O ölçüm bir kusur da buldu: enjeksiyon izin-listesi kalıbıorigin/*biçiminde kuruluyordu ve WebKit kalıpları host'ta PORT kabul etmediği için özel portlu her kurulumda script SESSİZCE hiç enjekte edilmiyordu (bkz. dosya içindeki gerekçe).Windows örnekleri (
webview2-host.cs,tauri-host.rs) gerçek bir Windows 11 makinesinde DERLENDİ — her ikisinin gerektirdiği paketler artık dosya başlıklarında yazılı (bu ölçüm sırasında Tauri örneğinin iki bağımlılığının hiç yazılmadığı ortaya çıktı:urlencodingvetauri-plugin-opener; kopyalayancannot find module or crateile duvara toslardı).webkitgtk-host.cHÂLÂ derlenmedi (Linux makinesi yok). Kopyaladıktan sonra en az iki yönü kendiniz ölçün: çıkıştan sonra eski sayfanın jetonu yazılmamalı, çıkıştan sonra açılan sayfanın jetonu yazılabilmeli.
Medya izni (örnek host'lar) — WebView2 · WebKitGTK · Tauri
Electron tarafı için yukarıdaki bölüme bakın; varsayılanı terstir (Electron işlenmemiş izni otomatik ONAYLAR, aşağıdaki üç platform ise REDDEDER). Kapının kendisi her yerde aynı: aynı üç koşul, aynı deny-by-default.
Widget'ın sesli mesajı web'de eksiksiz çalışır: mikrofon düğmesi (çalışma alanındaki
allowVoiceMessage ayarına bağlı) → getUserMedia({audio:true}) → MediaRecorder → 2 dk tavanı →
/upload → sohbette <audio controls>.
Tarayıcıda izni tarayıcı sorar; WebView'da soracak kimse yoktur. Bu üç platformda kabuk izni işlemezse varsayılan reddetmektir — yani özellik hata bile vermeden, sessizce ölür. Örnek host'lar bu kapıyı kurar ve izni kör vermez; üç koşul birlikte aranır:
- isteği yapan belge bizim origin'imizde mi,
- istenen izin mikrofon mu — kamera, konum, bildirim, MIDI vb. reddedilir (widget yalnız sesli mesaj için mikrofon ister; fazlasını açmak gereksiz yüzeydir),
- ana çerçeve mi.
Reddedilen izin sessiz kalmaz: sebebi teşhis kanalına yazılır (Teshis / h->teshis /
ayar.teshis). Bu depoda "sessiz kilit = teşhis edilemez hata" dersi kayıtlıdır — mikrofon
açılmadığında kullanıcı "bozuk" der, geliştirici hiçbir iz bulamaz.
| | WebView2 (C#) | WebKitGTK (C) | Tauri (Rust) |
|---|---|---|---|
| ① kaynak | ✅ args.Uri | ⚠️ ekrandaki belgenin URI'si | ⚠️ Linux: ekrandaki belge · ✅ Windows: args.Uri |
| ② yalnız mikrofon | ✅ PermissionKind | ✅ is_for_audio_device + video reddi | ✅ aynı |
| ③ ana çerçeve | ✅ FrameCreated + Handled | ❌ uygulanamaz | ❌ uygulanmıyor |
Üç uyarı, örnek dosyaların içinde de gerekçesiyle yazılıdır:
- WebKitGTK'da
enable-media-streamvarsayılanıFALSE. Açılmazsa sayfadanavigator.mediaDeviceshiç oluşmaz: izin kancası tek başına yetmez, düğme izin sorulmadan düşer. İkisi birlikte gerekir. - ③ koşulu WebKit'te uygulanamaz.
permission-requestsinyali gönderen çerçeveyi bildirmez (imzasında ne origin ne frame vardır) — köprü mesajındaki bilinen sınırın aynısı. Taşıyıcı kontrol gezinme izin-listesidir; artakalan risk kendi origin'imizden türeyen bir alt çerçevedir ve o çerçeve zaten sayfayla aynı origin'de olduğu için sayfanın deposuna da erişir. "Alt çerçeve reddediliyor" diye yazmayın; Linux'ta reddedilmiyor. - Yalnız ses.
getUserMedia({audio:true, video:true})isteği "ses için mi" sorusuna datrueder; bu yüzden video ayrıca yasaklanır — yoksa aynı izinle kamera da açılırdı.
Windows gizlilik ayarı: bu kapı yalnız web tarafını açar. İşletim sistemi düzeyinde uygulamanın
mikrofon erişimi kapalıysa (Ayarlar → Gizlilik ve güvenlik → Mikrofon) getUserMedia yine düşer.
Bunu kabuk kodu veremez; kurulum dokümanınıza yazın.
Tauri: taşınabilir izin API'si YOK
WebviewWindowBuilderın tüm kancaları sayıldı (on_navigation, on_new_window, on_page_load,
on_download, on_web_resource_request, …) — izin/medya karşılığı olan hiçbiri yok. Kapı bu
yüzden Tauri'nin belgelenmiş kaçış kapısı with_webview ile, platformun yerel tutamacı üzerinden
kurulur (Windows: webview2-com, Linux: webkit2gtk). Bu iki crate'in sürümü Tauri'ninkiyle
eşleşmelidir (cargo tree -i webkit2gtk), yoksa tipler aynı sayılmaz ve derleme düşer.
🔴 macOS kapsanmıyor. WKWebView'da karar WKUIDelegatein
requestMediaCapturePermissionFor… yöntemine düşer; o delegate'i wry kurar ve Tauri onu
değiştirmek için yüzey vermez. Tutamacı ele geçirip delegate'i değiştirmek wry'nin kendi işleyişini
(yeni pencere, dosya seçici, JS diyalogları) kırardı. wry tarafında konu hâlâ açıktır
(tauri-apps/wry#1195). Yani macOS'ta mikrofon davranışı wry sürümüne bağlıdır ve bu örnek onu
garanti etmez — örnek, boşluğu teşhis kanalına yazarak ilan eder.
DERLENMEDİ. Bu bölümdeki üç dosya değişikliği (C#, C, Rust) yazıldığı makinede derlenemedi — araç zinciri yok. API adlarının tamamı resmî dokümandan doğrulandı (WebView2
CoreWebView2PermissionKind/PermissionRequested, WebKitGTKwebkit_user_media_permission_is_for_audio_device,webkit2gtk/webview2-comcrate imzaları), ama doğrulanmış API adı derlenmiş kod değildir. Windows/Linux'ta derleyip çalıştırın. Kaynak testleri (ornekler-kaynak.test.ts) kapının metnini pinler, davranışını değil.
Linux'ta bilinen sınır (dokümana yazılıdır, çünkü kod bunu yapamıyor)
WebKitGTK'nın script-message-received sinyali gönderen çerçeve ve origin bilgisi taşımaz.
Bu yüzden Linux'ta köprü mesajı geldiği anda kaynak doğrulaması yapılamaz (Electron'da
senderFrame, WebView2'de args.Source ile yapılır). Taşıyıcı kontrol gezinme izin-listesidir:
yabancı bir belge o WebView'a hiç yüklenemez. Artakalan risk kendi origin'imizden türeyen bir alt
çerçevedir — ki o çerçeve zaten sayfayla aynı origin'de olduğu için sayfanın deposuna erişebilir.
"Köprü origin'e bağlıdır" diye yazmayın; Linux'ta değildir.
Kapsam dürüstlüğü
- Bu paket Electron için bir modül, diğer kabuklar için örnek + sözleşme gönderir. "Windows/Linux yerel SDK" DEMİYORUZ.
- MAUI ve WPF Linux'u kapsamaz;
webview2-host.csörneği Windows içindir. - Flutter masaüstü listelenmiyor: birinci-taraf
webview_flutteryalnız Android/iOS/macOS destekler. Hedeflenen üçüncü-taraf paket adıyla seçilip doğrulanmadan "destekleniyor" yazılmaz.
Doğrulama
Bu paket macOS bir makinede yazıldı. Windows tarafı 2026-08-04'te gerçek bir makinede (Windows 11 Home / AMD64 · node 24.16 · .NET 8.0.408 · rustc 1.96.0 · WebView2 Runtime 151.0.4129.59) SSH üzerinden ölçüldü:
| Ne | Komut | Sonuç |
|---|---|---|
| Üretim kaynağı | tsc -p tsconfig.json --noEmit | çıkış 0 |
| Test kaynağı | tsc -p tsconfig.test.json | çıkış 0 |
| Testler | vitest run . | 43/43, çıkış 0 |
| WebView2 örneği | dotnet build (net8.0-windows) | çıkış 0, 0 hata |
| Tauri örneği | cargo check | çıkış 0 (bağımlılık eksiği bulundu ve yazıldı) |
Yani sayılar macOS'takiyle birebir aynı. Hiçbiri gerçek bir pencerede çalıştırılmadı — derlenmek çalışmak değildir. Linux (WebKitGTK) hâlâ hiç derlenmedi.
Depoda koşan doğrulama şunlardır:
npx tsc -p packages/desktop --noEmit # üretim kaynağı
npx tsc -p packages/desktop/tsconfig.test.json # testler de tip-denetiminde
npx vitest run packages/desktop # 43 testTestler Electron API'sini sahte nesnelerle sürer ve kablolamayı kanıtlar (gezinme gerçekten
durdu mu, yabancı gönderen depoya ulaşabildi mi, reset() depoyu sildi mi, uçuştaki bir mesaj
çıkışı geri alabildi mi) — çünkü bu üründe en
sık yapılan hata saf fonksiyonu test edip üretim kablolamasını test etmemektir. Yine de yeşil
test "çalışıyor" demek değildir.
Doğrulama durumu (2026-08-04)
Aşağıdaki altı maddenin 1, 2, 3, 5 ve 6'sı ölçüldü; 4 hâlâ ölçülmedi.
| Ne | Nerede | Nasıl |
|---|---|---|
| Electron kabuğu | Windows 11 | öz-denetim koşumu 16/16 (panel 360×520 · odak çalınmıyor · ekranın %24'ü · reset() pencereyi beklemeden kaldırıyor · gömülü kip mount/unmount) |
| WebView2 (yerel .NET) | Windows 11 | kullanıcının oturumunda 5/5 — köprü object, panel acik, localStorage'da ph_support_token_… |
| WebKitGTK | Linux konteyneri | derlendi + çalıştı — köprü kuruldu, panel açıldı, jeton yazıldı |
| Tauri v2 | Windows 11 | derlendi + kullanıcı tarafından çalıştırıldı ve çalıştığı teyit edildi |
Madde 4 de ölçüldü (2026-08-04), iki kabukta:
| Ne | Electron (Windows 11) | WebKitGTK (Linux) |
|---|---|---|
| Yabancı origin'e gezinme engellendi | ✅ URL değişmedi ve gerçek yabancı sunucuya 0 istek | ✅ deneme sonrası adres hâlâ host sayfası |
| İzinli https sistem tarayıcısına devredildi | ✅ tam 1 kez, WebView gezinmedi | ⚠️ içeride açılmadığı ölçüldü; "tarayıcıya gitti" yarısı konteynerde gözlenemez |
| İzinsiz şema (myapp://, bankauygulamasi://) devredilmedi | ✅ hiçbiri | ✅ içeride açılmadı |
"Yabancı sunucuya 0 istek" ölçümü bilinçli: .invalid gibi çözülmeyen bir adres kullanmak
"engellendi" ile "adres zaten çözülemedi"yi karıştırırdı. Gerçek bir yerel sunucu dinlendi ve
istek sayacı sıfır kaldı.
KALAN: madde 4 WebView2 ve Tauri kabuklarında ÇALIŞTIRILARAK ölçülmedi (ikisi de etkileşimli masaüstü oturumu istiyor). Kod yolu üçünde de aynı sözleşmeyi kuruyor ve kaynak testleriyle pinli, ama bu bir ölçüm değil.
Paketin "deneysel" etiketi şunların tamamı gerçek bir kabukta gözle doğrulandığında kalkar:
- Gömülü kip ve balon kipi, panel ayarlarının tamamını (renk, ön-sohbet, Makaleler, marka satırı) web ile aynı gösteriyor.
- Balon kipinde satıcının kendi arayüzü tıklanabilir kalıyor (şeffaf tam-ekran katman yok).
- Sohbet penceresi açıldığında odak çalınmıyor.
- İzin dışı bir URL içeride açılmıyor; dış bağlantı sistem tarayıcısına gidiyor.
- Uygulama kapanıp açıldığında ziyaretçi geçmişi KORUNUYOR;
reset()sonrası SİLİNİYOR — vereset()çağrıldığı anda sohbet penceresi/görünümü ekrandan KALKIYOR (depo temizlemeyi beklemeden), sonraki açılışta eski sohbet GERİ GELMİYOR. - Windows'ta (WebView2) ve Linux'ta (WebKitGTK) köprü kuruluyor — jeton kabuğa ulaşıyor.
Lisans
Apache-2.0
