← Tüm rehberler

9 dk okuma

Yapay zekâyla yaptığın uygulama bilgisayarında çalışıyor. Yayına çıkmak kalan %30'da

Claude Code, Cursor veya Lovable ile uygulama yaptın mı? Yayına çıkmanın önündekiler: anahtarlar, giriş, App Review, abonelik, analitik, derin bağlantılar.

Claude Code, Cursor ya da Lovable ile bir uygulama yaptıysan ve bilgisayarında sorunsuz çalışıyorsa, yolun büyük kısmını gelmişsin demektir. Geriye kalan iş nadiren eksik bir özelliktir. Uygulamaya yabancılar, mağazalar, para ve arada bir de kötü niyetli biri dokunduğunda ortaya çıkan iştir: uygulama dosyasından herkesin çıkarabildiği API anahtarları, hiç denemediğin giriş yolları, App Review kuralları, aslında ücret almayan abonelikler, tek kişiyi üç kişi sayan analitik ve uygulamayı açıp hiçbir şey yapmayan derin bağlantılar.

Buna %30 diyoruz, çünkü içeriden öyle hissettiriyor. Ölçtüğümüz bir oran değil. Biz Lumio Studio'yuz, İstanbul'da küçük bir yazılım stüdyosuyuz. Kendi uygulamalarımızı yayınlıyoruz (Kalo, Runlock, ScrollShelf, LittleChats ve Muslim SuperApp App Store'da) ve kodumuzun çoğunu bir yapay zekâ asistanıyla birlikte yazıyoruz. Aşağıdaki her örnek bizim başımıza geldi. Hepsini bulduğumuz gün not ettik. Yani bu yazı için uydurulmuş bir liste değil, kendi notlarımız.

Demo neden seni yanıltıyor

Yapay zekâ asistanı kodu ona gösterdiğin yol için yazar. Sen de temiz kurulumda, uygulamayı sıfırdan açarak, kendi hesabınla ve hiç iade istememiş bir telefonda test edersin. O yol çalışır. Canlı ortam ise o yolun etrafındaki her şeydir ve sen sormadıkça model bunları düşünmek için bir sebep görmez.

Yani asıl soru "çalışıyor mu?" değil. "Ben olmayan biri ikinci kez denediğinde ne oluyor?"

1. Uygulamanın içindeki API anahtarı herkese açık

APK ya da IPA içinde yayınladığın her şey çıkarılabilir. Firebase her platform için bir API anahtarı oluşturur ve bu anahtarlarda varsayılan olarak hiçbir uygulama kısıtlaması yoktur.

Eylül 2026'da biri Kalo'nun herkese açık APK'sından kısıtlamasız Android anahtarını çıkardı ve onunla Vertex AI görsel modellerini çağırmaya başladı. Kalo bir kalori sayacı, hiç görsel üretmiyor. Günde 150 ile 270 arası başarılı istek geldi ve fark edene kadar yaklaşık ₺1.900'e mal oldu. Fark etmemizi sağlayan şey de faturaydı. App Check zorunlu değildi, o yüzden hiçbir istek engellenmedi. Denetim kayıtları kapalıydı, kimin yaptığını bile göremedik.

Bir ayrıntı bize ayrıca zaman kaybettirdi: Firebase AI Logic için App Check firebaseml.googleapis.com servis kimliğinde zorunlu kılınıyor. firebasevertexai ile denersen hata alırsın ve bu hata kolayca "zaten korunuyor" diye okunur.

İlk yayından önce:

  1. Her anahtarı kısıtla: Android anahtarını paket adına ve SHA-1'e, iOS anahtarını bundle ID'ye, tarayıcı anahtarını alan adlarına ve yalnızca ihtiyaç duyduğu API'lere.
  2. App Check'i aç ve uygulamanın çağırdığı her serviste zorunlu kıl.
  3. Bulut projesine bütçe uyarısı koy. Faturan izleme aracın olmasın.

Uygulaman modele kendi sunucun üzerinden gidiyorsa benzer bir tuzak daha var. Fiş okuyan uygulamamızın aracı sunucusu günlerce kurulu ve sağlıklı görünüyordu: sağlık kontrolü yeşil, adres cevap veriyor. Tek bir model çağrısını bile tamamlamamıştı, çünkü sunucunun servis hesabının Vertex'i çağırma yetkisi yoktu. Bunu TestFlight'ta bulduk, Android sürümü Google Play'de çoktan yayındayken. O günden beri kuralımız şu: kurulum tamamlandı demek yetmez. Model çıktısıyla 200 dönen tek bir gerçek istek görmeden bitti demiyoruz.

2. Giriş, ikinci yolda bozulur

Yayınladığımız giriş hatalarının çoğu ilk girişte değildi. Hemen yanındaki yollardaydı.

Kalo kullanıcıyı açılışta anonim olarak giriş yaptırıyor, sonra Apple ya da Google hesabını bu anonim hesaba bağlıyor. Uygulama içinden çıkış yapınca anonim kullanıcı bir sonraki açılışa kadar ortadan kalkıyor. Apple ve Google girişi onun orada olduğunu varsaydı, noCurrentUser hatası verdi ve kullanıcı uygulamayı kapatıp açmak dışında çıkışı olmayan bir "Giriş yapılamadı" mesajı gördü. E-posta girişinde bunun için bir yedek yol vardı, diğer ikisinde yoktu. Bunu ancak uygulamayı yeniden başlatmadan çıkış yapıp tekrar girerek yakalarsın. Kimsenin yapmadığı test de tam olarak bu.

İkincisi Apple ile Giriş. Apple kimliğini bağlamak, o Apple ID'nin zaten bir hesabı olduğu için başarısız olursa, akla gelen ilk çözüm aynı kimlikle giriş yapmaktır. Derlenir ve her seferinde başarısız olur: Apple kimliği Firebase karşısında tek kullanımlık. Gelen hata (17094, "duplicate credential" diyen bir nonce mesajı) seni yanlış katmana yönlendirir. Çözüm, yeni bir nonce ile Apple girişini baştan yapmak.

Girişi başarılı sayan sahte (mock) testlerde bu hataların ikisi de görünmez. Yalnızca gerçek sunucuya karşı ortaya çıkar.

3. App Review, simülatörün bakmadığı yerlere bakar

Sadece yazısına basınca çalışan butonlar

SwiftUI'da etiketi padding ya da .frame(maxWidth: .infinity) kullanan bir buton, .contentShape(...) eklemezsen yalnızca yazının harflerine basınca tepki verir. Ekranda tam genişlikte bir buton gibi görünür. İncelemeci kenarına basar, hiçbir şey olmaz ve ret gerekçesinde butonun "herhangi bir işlem başlatmadığı" yazar. iPad'de bu çok kolay bir ret sebebi ve her ret bir inceleme turuna mal olur.

Konsept reddine yeni build değil, cevap gerekir

Uygulamalarımızdan biri Apple'ın spam kuralı olan 4.3(a) maddesinden reddedildi. Kayıt modelini, adını ve ekran görüntülerini değiştirip API üzerinden yeniden gönderdik. İki gün sonra aynı ret kelimesi kelimesine geri geldi. Resolution Center için hazırladığımız cevap ise hâlâ depoda, gönderilmemiş duruyordu. Çökme hatasına yeni bir build cevap verir. Uygulamanın ne olduğuna dair bir yargıya ise önce yazılı cevap verilir, sonra yeniden gönderilir.

Hesap yoksa da veri silme gerekir

Apple'ın hesap silme kuralı hesabı olmayan bir uygulamaya uygulanmaz. Ama KVKK, GDPR ve Google Play'in Veri güvenliği formu kişisel veriyle ilgilenir ve bir analitik kimliği ya da abonelik müşteri kimliği de kişisel veridir. Ayarlar'a bir "Tüm verilerimi sil" satırı koy.

4. Abonelik: hiç para almayan ödeme ekranı

App Store Connect hazır bir aboneliği READY_TO_SUBMIT olarak gösterir. Bu, gönderime eklenebilir demek, gönderimin içinde olduğu anlamına gelmez. Ürünleri gönderime eklenmemiş bir ödeme ekranıyla bir uygulamayı incelemeye gönderdik. İncelemeci fark ederse ret alırsın. Fark etmezse ödeme ekranı hiçbir şey satmadan yayına çıkar. İlk abonelik grubu, grubun kendisi ve içindeki her ürünle birlikte, konsoldan elle eklenerek gönderilmeli. API bunları ekleyemiyor.

Sonra satıştan sonrası geliyor. Kalo, Google Play'de aylarca gerçek zamanlı geliştirici bildirimleri kapalıyken satış yaptı. Bir kullanıcı iade aldı, iade Adapty'ye (kullandığımız abonelik SDK'sı) hiç ulaşmadı ve kâğıt üzerinde premium erişimi 2027'ye kadar açık kaldı. Yenilemeler ve iptaller de aynı şekilde görünmezdi.

En kötüsü şuydu: Android'de yıllık abonelik alan bir kullanıcı ödeme yaptı, sonra beş gün boyunca her isteği reddedildi. Satın alma webhook'u, uygulama Adapty'ye kullanıcının kim olduğunu söylemeden önce gelmişti. Sunucumuz olayı reddetti ve hiçbir şey saklamadı. Baktığımızda 60 günde gelen 48 webhook'un 12'sinin aynı hatayı döndürdüğünü gördük. Hatayı bize iade isteyerek o kullanıcı buldurdu. Artık kime ait olduğu belli olmayan bir satın alma atılmıyor, saklanıyor. Uygulama ödemeden hemen sonra onu sahiplenebiliyor ve zamanlanmış bir iş geri kalanları tekrar deniyor.

5. Tek kişiyi üç kişi sayan analitik

PostHog, çoğu analitik SDK'sı gibi, sen identify çağırana kadar rastgele bir anonim kimlik kullanır. İlk olay bundan önce gönderilirse uygulamanın her soğuk açılışı yeni bir kişi sayılabilir. Hunilerin bozulur, gerçekte olmayan elde tutma düşüşleri görürsün ve bunu ancak bir test kullanıcısının bir saatte dört kimliği olduğunu gördüğünde anlarsın. İlk olaydan önce sabit bir kimlikle (Firebase uid'si ya da kalıcı olarak sakladığın bir UUID) identify et. Otomatik yakalama sen fırsat bulmadan olay gönderiyorsa kapat.

Sessiz bir panel her zaman sakin bir panel değildir. Kalo'nun üç Android sürümü, git'e eklenmeyen google-services.json dosyası olmayan bir kopyadan derlendi. Derleme bir uyarıyla geçti ve yaklaşık on gün boyunca her kurulum açılışta çöktü. Çöken uygulama hiçbir şey göndermediği için PostHog sadece sustu. Bu sırada ücretli bir reklam kampanyası insanları uygulamaya göndermeye devam ediyordu. Bir kullanıcının mesajından ve Play vitals'tan öğrendik. Artık o dosya yoksa sürüm derlemesi başarısız oluyor ve her yayından sonra Play vitals'a bakıyoruz.

6. Uygulamayı açıp duran derin bağlantılar

Kalo için altı sistem üzerinde bir geri kazanım teklifi kurduk: iki mağaza, Adapty, PostHog, sunucumuz ve iki uygulama. Her katman kontrol edilmiş, yeşildi, düzinelerce test geçiyordu. Özellik çalışmıyordu. Bildirim geldi, kullanıcı dokundu, uygulama açıldı ve derin bağlantı yönlendiricisi varsayılan duruma düştü, çünkü kimse paywall rotasını eklememişti.

Testler kodla aynı oturumda yazılmıştı, o yüzden kodun kör noktasını aynen paylaşıyordu. Artık bir entegrasyona ancak baştan sona takip ettiğimiz tek bir gerçek girdiyi söyleyebildiğimizde bitti diyoruz: şu bildirim, şu dosyalardan geçip şu ekranı açıyor.

Bitti demeden önce çalıştırman gereken prompt

Bir özelliğin sonunda bunu Claude Code ya da Cursor'a yapıştır, en üste özelliği yaz:

Özellik: <ne yaptığını bir kullanıcının söyleyeceği tek cümleyle yaz>

Bitti demeden önce bunu, kodu yazmamış şüpheci biri gibi incele:
1. Gerçek bir girdi seç (bir dokunma, bir push yükü, bir webhook, bir derin bağlantı)
   ve onu dosya dosya kullanıcının gördüğü yere kadar takip et. Dosya yollarını göster.
   Kodu olmayan bir adım varsa söyle.
2. Mutlu yol dışındaki her yolu listele: ikinci deneme, çıkış yapmış kullanıcı,
   internetsiz, iadeden sonra, yeniden kurulumdan sonra, yepyeni bir hesapla.
3. Bunun bağlı olduğu her anahtarı, token'ı ve yapılandırma dosyasını listele;
   biri eksikken sürüm derlemesinin açıkça hata verip vermediğini söyle.
4. Bunun canlıda çalıştığını hangi analitik olayı kanıtlıyor ve hangi kullanıcı
   kimliğiyle gönderiliyor?
5. Testlerde sahte (mock) yapılan, ancak gerçek sunucuya karşı bozulabilecek ne var?
Henüz hiçbir şeyi düzeltme. Bana listeyi ver.

Yayın haftası kontrol listesi

  1. Her API anahtarı paket ve SHA-1, bundle ID ya da alan adıyla kısıtlı, App Check zorunlu.
  2. Her yapay zekâ ya da ücretli uç noktadan 200 dönen tek bir gerçek canlı istek.
  3. Her giriş sağlayıcısıyla, uygulamayı yeniden başlatmadan çıkış yapıp tekrar giriş.
  4. Her abonelik ürünü inceleme gönderimine eklenmiş.
  5. İki mağazanın iade ve yenileme bildirimleri abonelik altyapına ulaşıyor.
  6. Analitik kimliği ilk olaydan önce atanmış, tek test kullanıcısı tek kişi olarak görünüyor.
  7. Bir yapılandırma dosyası eksikken başarısız olan sürüm derlemesi ve her yayından sonra okunan çökme raporları.
  8. Bir derin bağlantı ve bir bildirim, dokunmadan ekrana kadar takip edilmiş.
  9. Hesap olmasa bile bir "Tüm verilerimi sil" yolu.

Hâlâ yanlış yaptıklarımız

Buradaki her maddeyi yanlış yaparak öğrendik, genelde de geçen bir testin her şeyin yolunda olduğunu söylemesinden hemen sonra. Liste uzamaya devam ediyor ve bir sonraki yayının tertemiz olacağını iddia etmeyeceğiz. Değişen şu: bu kontrolleri artık bir kullanıcı bize yazdıktan sonra değil, yayından önce yapıyoruz.

Daha fazla örnek ve kullandığımız kontrollerin tamamıyla uzun hali ücretsiz bir e-kitapta: Yapay zekâyla uygulama çıkarmak: kimsenin anlatmadığı %30. Henüz fikir aşamasındaysan uygulama proje planlayıcı ilk promptu yazmadan önce fikrini kabaca bir kapsam ve tahmine dönüştürür.

Sizin için yapmamızı ister misiniz? Projenizi anlatın ↗

Yapay zekâyla yaptığın uygulama bilgisayarında çalışıyor. Yayına çıkmak kalan %30'da | Lumio Studio