Kashifly

Şeffaflık

Hangi veriyi, neden topluyoruz?

Söz vermek yerine gösteriyoruz: her madde ölçülerek çıkarıldı ve nasıl doğrulanacağı yazılı.

2026-09-26 · kashifly.com

Neden böyle bir sayfa var?

Gizlilik metinleri genellikle "verilerinizi önemsiyoruz" diye başlar ve hiçbir şey kanıtlamaz. Bu sayfa onun tersini denemektedir: her satırda hangi veriyi, hangi özellik için, nerede tuttuğumuz ve bunu nasıl doğrulayabileceğin yazıyor.

Aşağıdaki envanter 2026-09-26 tarihinde ölçülerek çıkarıldı: veritabanı şeması doğrudan okundu, tarayıcı depolaması kaynak taramasıyla listelendi, izleme betiği araması yapıldı ve grup sohbetinin şifreleme akışı satır satır incelendi.

Topladığımız veriler

Her kartta aynı altı soru cevaplanıyor: ne, neden, hangi özellik, nerede, ne kadar süre, hangi dayanak.

Hesap

E-posta adresi ve parola (özet/hash olarak)

NedenHesabını açmak, girişini doğrulamak ve parolanı sıfırlayabilmek.
Hangi özellikHesap oluşturma · giriş
Nerede dururSupabase Auth (auth.users)
Ne kadarHesabın silinene kadar
DayanakSözleşmenin ifası
Zorunlu muYalnız hesap açmak isteyenler için. Uygulamanın rehber ve sohbet tarafı hesapsız da çalışır.
KanıtSupabase Auth — parola bizde DÜZ METİN olarak hiç bulunmaz; doğrulamayı Supabase yapar.

Görünen ad ve avatar görseli

NedenProfilinde ve topluluk gönderilerinde seni "Gezgin" yerine kendi adınla göstermek.
Hangi özellikProfil · topluluk
Nerede dururpublic.profiles (full_name, avatar_url)
Ne kadarHesabın silinene kadar
DayanakSözleşmenin ifası
Zorunlu muHayır, boş bırakılabilir.
Kanıtpublic.profiles tablosu — 12 satır (26 Eyl ölçümü).

Ödeme

Abonelik planı, durum, yenilenme tarihi ve Stripe müşteri/abonelik kimliği

NedenBasic/Premium özelliklerini açmak ve aboneliğini yönetebilmen.
Hangi özellikAbonelik
Nerede dururpublic.profiles (plan, plan_status, plan_renews_at, stripe_customer_id, stripe_subscription_id)
Ne kadarAbonelik süresince + muhasebe yükümlülüğü gereği yasal saklama süresi
DayanakSözleşmenin ifası
Zorunlu muYalnız abonelik alanlar için.
Kanıtbackend/src/routes/billing.js — Stripe müşterisi orada oluşturuluyor; bizde yalnız KİMLİK saklanıyor.
⚠️ KART NUMARAN BİZDE DEĞİL. Ödeme sayfası Stripe'ın kendi altyapısıdır; kart verisi bizim sunucumuza hiç uğramaz.

Gezi

Kaydettiğin geziler (şehir, ülke, gün sayısı, program, duraklar, notun)

NedenPlanladığın geziyi sonra açabilmen ve cihaz değiştirsen bile kaybolmaması.
Hangi özellikGezilerim / Gezi Geçmişi
Nerede dururpublic.saved_trips
Ne kadarSen silene ya da hesabını kapatana kadar
DayanakSözleşmenin ifası
Zorunlu muHayır — kaydetmeden de plan üretebilirsin.
Kanıtpublic.saved_trips (itinerary, stops, note) — RLS açık, yalnız kendi satırını okursun.

İşaretlediğin gezilen yerler (ad, şehir, ülke, koordinat, tarih, not, fotoğraf bağlantısı)

NedenGezi günlüğünü ve haritadaki "gezdiğim yerler" katmanını oluşturmak.
Hangi özellikProfil → Journey Log
Nerede dururpublic.visited_places
Ne kadarSen silene kadar
DayanakAçık rıza
Zorunlu muHayır — tamamen isteğe bağlı bir kayıt defteridir.
Kanıtpublic.visited_places (lat, lng, visited_on).
⚠️ Buradaki koordinat, CİHAZININ TAKİP EDİLMESİYLE değil, senin bir yeri işaretlemenle oluşur.

Medya

Yüklediğin fotoğraf ve videolar, açıklama metni ve bağlı olduğu şehir

NedenKendi gezi günlüğünde göstermek; herkese açık işaretlediysen topluluk akışında yayımlamak.
Hangi özellikGünlük · Kartpostallar · topluluk
Nerede dururSupabase Storage (user-media kovası) + public.user_media
Ne kadarSen silene kadar
DayanakAçık rıza
Zorunlu muHayır.
Kanıtpublic.user_media (path, caption, city_key, is_public) + storage.objects.
⭐ FOTOĞRAFIN EXIF/GPS VERİSİ YÜKLEMEDEN ÖNCE SİLİNİR. Görsel tarayıcıda canvas'tan geçirilir; EXIF, GPS, IPTC ve XMP blokları yapısal olarak düşer (frontend/js/lib/medya-hazirla.js). Videoda konteyner metadata'sını tarayıcı temizleyemediği için iş sunucuda yapılır.

Topluluk

Beğenilerin ve yorumların (yorum metni, görünen adın, avatarın)

NedenTopluluk akışını işletmek ve yorumun kime ait olduğunu göstermek.
Hangi özellikTopluluk / keşfet
Nerede dururpublic.media_likes, public.media_comments
Ne kadarSen silene kadar
DayanakSözleşmenin ifası
Zorunlu muHayır.
Kanıtpublic.media_comments (body, author_name, author_avatar, edited_at).

Kaydettiğin oteller

NedenBeğendiğin konaklamayı sonra bulabilmen.
Hangi özellikKonaklama kartı ♥
Nerede dururpublic.saved_hotels
Ne kadarSen silene kadar
DayanakSözleşmenin ifası
Zorunlu muHayır.
Kanıtpublic.saved_hotels — kimlik ad değil KOORDİNAT (hotel_key), çünkü ad dile göre değişir.

Sohbet

Sohbetin senin hakkında öğrendiği kalıcı tercihler (ör. "kırmızı et yemiyor")

NedenAynı şeyi her sohbette yeniden anlatmak zorunda kalmaman.
Hangi özellikBana Sor — sohbet hafızası
Nerede dururpublic.chat_memory
Ne kadarSen silene kadar
DayanakAçık rıza
Zorunlu muHayır.
Kanıtpublic.chat_memory (fact, kind, city, source) — 25 satır (26 Eyl ölçümü).
⭐ BU KAYITLARI PROFİL → AYARLAR'DAN TEK TEK GÖRÜR VE SİLERSİN. Tablonun veritabanındaki açıklaması da bunu söylüyor.

Sorduğun sorunun metni (en fazla 200 karakter), şehir, dil ve zaman damgası

NedenAynı soruya verilen cevabı yeniden üretmeden sunmak (hız + maliyet) ve hangi soruların cevapsız kaldığını görüp ürünü düzeltmek.
Hangi özellikBana Sor — önbellek ve kalite ölçümü
Nerede dururRedis (geçici)
Ne kadarCevap önbelleği 7 gün · ölçüm kütüğü yalnız son 5.000 kayıt
DayanakMeşru menfaat
Zorunlu muSohbeti kullanmanın doğal parçası.
Kanıtbackend/src/redis.js — chatCacheSet varsayılan TTL 604800 sn; chatLogPush kütüğü ltrim ile son 5.000 kayda kırpılır.
⚠️ BU KAYITLARDA KULLANICI KİMLİĞİ YOKTUR. Kütüğe yazılan alanlar yalnız: soru metni, şehir, dil, zaman. Kimlik alanı hiç yazılmıyor — yani bir soruyu bir kişiye geri bağlayamayız.

Güvenlik

İhbarların ve moderasyon kayıtları (ihbar sebebi; kural ihlalinde eşleşen ifade ve metin parçası)

NedenTopluluğu spam, taciz ve yasa dışı içerikten korumak.
Hangi özellikİhbar et · içerik denetimi
Nerede dururpublic.reports, public.moderation_violations
Ne kadarİnceleme kapanana kadar
DayanakMeşru menfaat
Zorunlu muYalnız ihbar edildiğinde ya da bir kural ihlali işaretlendiğinde oluşur.
Kanıtpublic.reports (reason, status) ve public.moderation_violations (kaynak, tur, eslesen, metin).

Cihaz

Anlık konumun

NedenAcil durum kartında sana en yakın numarayı ve mesafeyi göstermek; grup gezisinde konumunu — SEN AÇTIYSAN — grup üyelerine iletmek; "yakınımdakiler" sorularını cevaplamak.
Hangi özellikSOS · grup canlı konum · yakınımdakiler
Nerede dururCihazında. Grup özelliğinde sunucunun BELLEĞİNDE (RAM), diske yazılmadan.
Ne kadarGrup oturumu boyunca; sayfa kapanınca kaybolur
DayanakAçık rıza
Zorunlu muHayır — izni vermezsen SOS elle seçimle, grup ise konumsuz çalışır.
KanıtTarayıcı konum izni olmadan hiç çalışmaz. Grup tarafında konum yalnız `me.visible` açıkken işlenir ve kalıcı yazma işlevine (persist) HİÇ girmez.
⛔ KONUM GEÇMİŞİ TUTULMUYOR. Nereden geçtiğini gösteren bir iz kaydı yok; yalnız "şu an" değeri var ve o da diske yazılmıyor.

IP adresinden türetilen ÜLKE bilgisi

NedenSiteyi ilk açtığında arayüzü muhtemelen anladığın dilde göstermek.
Hangi özellikOtomatik arayüz dili
Nerede dururHiçbir yerde saklanmıyor — istek anında kullanılıp atılıyor
Ne kadarSaklanmıyor
DayanakMeşru menfaat
Zorunlu muDil seçimini elle yaparsan bu adım devre dışı kalır.
Kanıtget.geojs.io çağrısı yalnız ülke kodu döndürür; sonucu bir tabloya YAZMIYORUZ. Dil tercihini elle değiştirirsen seçimin cihazında (kashif_lang) kalır ve IP'yi ezer.

Tarayıcı depolaması (localStorage / IndexedDB)

NedenDil tercihin, açık sohbetin, çevrimdışı indirdiğin harita karoları ve uygulama ipuçlarının hatırlanması.
Hangi özellikDil · sohbet · çevrimdışı harita · PWA ipuçları
Nerede dururYalnız kendi cihazında
Ne kadarSen tarayıcı verisini silene kadar
DayanakMeşru menfaat
Zorunlu muReddedersen uygulama çalışır ama tercihlerini hatırlamaz.
KanıtKullanılan anahtarlar: kashif_lang, kashif_chat, kashif_sohbet_id, kashif_izle, kashif_open_place, kf_cc_gallery_hidden, pwa-*. Çevrimdışı harita IndexedDB'de tutulur.
⭐ BUNLAR REKLAM ÇEREZİ DEĞİLDİR. Hiçbiri bir reklam ağına, veri simsarına ya da ölçüm şirketine gönderilmiyor; cihazından hiç çıkmıyorlar.

Toplamadıklarımız

Bu bölüm bilerek ölçülebilir maddelerden oluşur. "Gizliliğe önem veriyoruz" bir madde değildir; "kaynak kodda izleme betiği araması 0 sonuç verdi" bir maddedir.

İzleme — YALNIZ onay verirsen ve yalnız Google Analytics

Meta pikseli, Hotjar, Mixpanel, Amplitude, PostHog, Segment, Clarity ve reklam ağı etiketleri: hiçbiri yok. Yalnız Google Analytics 4 var ve çerez bandında "Kabul et" demediysen betiği sayfaya HİÇ eklenmez.

Nasıl doğrularsın: Onay verilmeden gtag betiği DOM'a hiç girmiyor (frontend/js/cerez.js: kimlik ve onay iki ayrı kapı). Reddedersen karar saklanır ve bir daha sorulmaz. Diğer ölçüm adlarının kaynak taraması 0 sonuç veriyor.

Reklam ve profilleme — YOK

Reklam göstermiyoruz, kimseye reklam kimliği yollamıyoruz, ilgi alanı profili çıkarmıyoruz, veri satmıyoruz.

Nasıl doğrularsın: Reklam ağı çağrısı yapan tek bir kod yolu yok; gelir modeli abonelik.

Kart bilgisi — BİZDE YOK

Kart numarası, son kullanma tarihi veya CVC hiçbir zaman sunucumuza ulaşmaz.

Nasıl doğrularsın: Ödeme akışı Stripe Checkout üzerinden yürür; bizde yalnız Stripe'ın verdiği müşteri/abonelik KİMLİĞİ durur.

Grup sohbetinin içeriği — OKUYAMIYORUZ

Mesajlar cihazında şifrelenir; sunucu yalnız şifreli metni iletir ve diske hiç yazmaz.

Nasıl doğrularsın: Aşağıdaki "Grup sohbeti" bölümünde satır satır kanıt var.

Konum geçmişi — TUTULMUYOR

Nereden geçtiğini gösteren bir iz kaydı yok.

Nasıl doğrularsın: Grup konumu yalnız bellekte; kalıcı yazma işlevi konum alanlarını hiç içermiyor.

Fotoğrafının EXIF/GPS verisi — SİLİNİYOR

Yüklediğin görselin çekildiği yer ve cihaz bilgisi bize hiç ulaşmaz.

Nasıl doğrularsın: Görsel yüklemeden önce canvas'tan geçirilir; EXIF/GPS/IPTC/XMP blokları yapısal olarak düşer.

Sohbet soruların kimliğine bağlanmıyor

Kalite ölçümü için tutulan soru kütüğünde kullanıcı kimliği alanı yok.

Nasıl doğrularsın: Kütüğe yazılan alanlar: soru, şehir, dil, zaman. Başka alan yazılmıyor.

Rehber ve şehir içeriğini okumak için hesap gerekmiyor

Şehir sayfaları, gezi kartları ve sohbet hesapsız çalışır; hesap yalnız kaydetmek, yüklemek ve topluluk için gerekir.

Nasıl doğrularsın: Giriş duvarı yalnız kayıt/yükleme/topluluk uçlarında var.

Grup sohbeti: neden içeriğini okuyamıyoruz

Gezi gruplarındaki sohbet uçtan uca şifrelidir. Bu, bir söz değil bir mimari sonuçtur; aşağıda adım adım, koddan alıntılarla gösteriliyor. İddiayı doğrulamak isteyen bir geliştirici dosya adlarına bakıp ilgili satırları arayabilir.

1. Şifreleme anahtarı SENİN TARAYICINDA üretilir.

AES-GCM 256 bit anahtar, Web Crypto API ile istemcide üretilir. Sunucu bu adıma hiç karışmaz.

cryptoKey = await crypto.subtle.generateKey(
  { name: 'AES-GCM', length: 256 }, true, ['encrypt', 'decrypt']);
📁 frontend/js/group.js

2. Anahtar davet bağlantısının # (fragment) kısmında paylaşılır — SUNUCUYA GİTMEZ.

Bu bir tercih değil, HTTP'nin kuralı: tarayıcılar adresin # işaretinden sonraki kısmını isteğe KOYMAZ (RFC 3986 §3.5). Yani anahtar, davet linkini açan kişinin tarayıcısında kalır; sunucunun erişebileceği bir yerde hiç bulunmaz.

const joinUrl = window.location.origin + window.location.pathname
  + '?plan=' + msg.planId + (keyB64 ? '#k=' + keyB64 : '');
📁 frontend/js/group.js

3. Mesaj, cihazından çıkmadan ÖNCE şifrelenir.

Her mesaj için rastgele 12 baytlık IV üretilir ve metin AES-GCM ile şifrelenir. Sunucuya giden şey base64 kodlanmış şifreli metindir.

const iv = crypto.getRandomValues(new Uint8Array(12));
const ct = await crypto.subtle.encrypt(
  { name: 'AES-GCM', iv }, cryptoKey, new TextEncoder().encode(text));
📁 frontend/js/group.js

4. Sunucu şifreli metni yalnız BELLEĞİNDE tutar ve iletir; çözmeye çalışmaz.

Gelen metin bir JavaScript dizisine eklenir, en fazla 200 mesaj tutulur, gruptakilere yayımlanır. Çözme (decrypt) çağrısı sunucu kodunda hiç geçmez — anahtar zaten orada yok.

// E2E: msg.text = istemcide AES-GCM ile şifrelenmiş ciphertext (base64).
// Sunucu içeriği ASLA çözmez/okumaz; yalnız RAM'de tutup iletir. Yedek YOK.
plan.messages.push(m);
if (plan.messages.length > 200) plan.messages.shift();
📁 backend/src/routes/group.js

5. Kalıcı depoya yazılan alanların arasında MESAJ YOKTUR.

Grup, sunucu yeniden başlasa da üyelerin bağlantısını kaybetmemesi için kalıcı bir kayıt tutar. O kaydın içinde ne olduğu tek satırda görülüyor: tarihler, gezi programı, kurucunun takma adı ve onaylanmış takma ad listesi. Mesaj dizisi bu listede YOK.

savePlan(id, {
  startDate, endDate, createdAt,
  itinerary, creatorNick,
  onaylanan: [...],   // yalnız TAKMA AD listesi
});
📁 backend/src/routes/group.js

6. Konumun da diske yazılmaz ve yalnız SEN açtıysan iletilir.

Konum mesajı, üyenin görünürlük bayrağı kapalıysa daha ilk satırda geri döner. Kabul edilen konum yalnız bellekteki üye nesnesine yazılır; yukarıdaki kalıcı kayıtta konum alanı yoktur.

const me = plan.members.get(ws);
if (!me || !me.visible) return;   // görünürlük kapalıysa İŞLENMEZ
me.lat = lat; me.lng = lng;       // yalnız BELLEK
📁 backend/src/routes/group.js

7. Grup bitiminden 24 saat sonra her şey silinir.

Saatlik bir temizlik döngüsü, bitiş tarihinin üzerinden 24 saat geçmiş grupları bellekten ve kalıcı depodan siler; bağlı üyelere de grubun kapandığı bildirilir.

if (now > expiry) {
  plans.delete(id);
  deletePlan(id);
}
📁 backend/src/routes/group.js

8. Sayfayı kapattığında anahtar bellekten silinir.

Gruptan çıkışta anahtar değişkeni boşaltılır. Yeniden girmek için davet bağlantısındaki anahtar gerekir — bizde bir kopyası yoktur, yani "şifreyi unuttum" diye kurtarabileceğimiz bir yedek de yoktur.

cryptoKey = null; keyB64 = null;   // E2E anahtarını bellekten sil
📁 frontend/js/group.js
Sonuç: Bunun pratik anlamı şudur: mahkeme kararıyla bile bize grup sohbetinin içeriğini veremeyiz, çünkü elimizde yalnız şifreli metin var ve anahtar hiçbir zaman sunucuya uğramıyor. Bu bir söz değil, mimarinin sonucu.

Hizmet sağlayıcılar

Ürünü çalıştırmak için kullandığımız sağlayıcılar ve her birine fiilen ne gönderildiği:

SağlayıcıNe içinOna ne gidiyorNerede
SupabaseHesap, veritabanı ve dosya depolamaHesap bilgilerin ve senin kaydettiğin içeriklerAB (Frankfurt)
RailwayUygulama sunucusuİsteklerin işlenmesi sırasında geçen verilerABD/AB
VercelWeb sitesinin dağıtımıSayfa istekleri (standart sunucu kayıtları)Küresel dağıtım ağı
StripeÖdemeÖdeme bilgilerini DOĞRUDAN Stripe alır; bizde kart verisi olmazABD/AB
Google Analytics 4Ziyaret istatistiği (onaya bağlı)Hangi sayfaların görüntülendiği, yaklaşık konum (IP son baytı silinerek), cihaz ve tarayıcı türü — YALNIZ sen onay verirsenABD/AB
Azure OpenAI · Groq · OpenRouter · CloudflareSohbet ve metin üretimiSorduğun sorunun metni ve şehrin gezi kartı listesi — kimlik bilgisi GÖNDERİLMEZABD/AB
Google PlacesMekân adresi, türü ve fotoğrafıMekân adı ve koordinatı — kullanıcı bilgisi GÖNDERİLMEZABD
TavilyGüncel bilgi için web aramasıArama sorgusu (şehir + konu) — kimlik GÖNDERİLMEZABD
OpenStreetMap · Overpass · NominatimHarita verisi, mekân ve helal/koşer etiketleriKoordinat ve arama metniAB
OpenFreeMap / MapLibreHarita karolarıBaktığın harita bölgesiAB
Wikipedia · WikidataŞehir ve mekân görselleri, bilgi kartlarıMekân adıKüresel
AladhanNamaz vakitleriŞehir koordinatıKüresel
get.geojs.ioIP → ülke (arayüz dili için)İsteğin IP adresi — sonuç BİZDE saklanmazKüresel
⚠️ Yapay zekâ sağlayıcılarına kimlik bilgisi gönderilmez: giden şey sorunun metni ve o şehrin gezi kartı listesidir. Kim sorduğu bilgisi istekte yer almaz.

Haklarını nasıl kullanırsın?

Kendi ülkendeki düzene göre hazırlanmış hukuki metni seç — hak listesi, başvuru yolu ve şikâyet makamı orada yazıyor: