# Yayınlama ve İnceleme

> İnceleme durumları, public/private dağıtım, kurulabilirlik kuralları, gönderim kontrol listesi, mağaza görselleri (ikon, kapak, ekran görüntüleri, store-assets/ ve listing.media), askıya alma ve izleme.
>
> Kaynak: https://tecof-app-dev.vercel.app/app-publishing · Bölüm: Uygulama geliştirme · Son güncelleme: 2018-10-20

Bir uygulama test mağazalarında geliştirildikten sonra incelemeye gönderilir ve onaylanınca dağıtım türüne göre katalogda listelenir ya da doğrudan bağlantıyla kurulur. Bu sayfa inceleme durumlarını, dağıtım seçeneklerini, kurulabilirlik kurallarını, gönderim öncesi kontrol listesini ve mağaza görsellerini anlatır.

---

## İnceleme Durumları

| Durum | Anlamı |
| :--- | :--- |
| `draft` | Geliştiriliyor; yalnız `testStores` mağazalarına kurulabilir |
| `in-review` | Tecof incelemesinde |
| `approved` | Onaylandı; dağıtım türüne göre yayında |
| `rejected` | Reddedildi; inceleme notuna göre düzeltip yeniden gönderin |

```mermaid
stateDiagram-v2
    [*] --> draft
    draft --> in_review: POST /developer/apps/:id/submit
    in_review --> approved: Onay
    in_review --> rejected: Ret (not ile)
    rejected --> in_review: Düzeltip yeniden gönderim
    approved --> in_review: Kapsam artışı (mevcut sürüm yayında kalır)
```

İncelemeye gönderim: `POST /api/developer/apps/:id/submit` (kapı maddeleri aşağıda). Tecof yöneticisi onaylar ya da reddeder; ret her zaman bir not içerir. Onaylı uygulamadaki kapsam artışları da aynı inceleme kuyruğuna düşer.

### Onay sonrası değişiklikler

| Değişiklik | Etki |
| :--- | :--- |
| `listing` (açıklama, bağlantılar, kategori) | Canlıya **hemen** yansır |
| `plans` | Canlıya **hemen** yansır |
| Kapsam artışı | **Yeniden inceleme** ister (`in-review`); inceleme sürerken mevcut sürüm yayında kalır. Kurulumlara `pendingScopes` yazılır, mağaza onaylayana kadar eski kapsamla çalışırlar |
| Kapsam azalması | Anında uygulanır |

---

## Dağıtım Türleri

`POST /api/developer/apps/:id/distribution { distribution }` ile seçilir.

| Dağıtım | Katalogda | Kurulum | İnceleme |
| :--- | :--- | :--- | :--- |
| `public` | `approved` olunca görünür | Katalogdan ya da bağlantıyla | Gerekir |
| `private` | Görünmez | Yalnız doğrudan kurulum bağlantısıyla | Gerekmez; partner aktif olmalı. Ücretli planlı olsa da yayında KYC istenmez (hak ediş ödemesi yine KYC/IBAN ister) |

Kurulum bağlantısı:

```text
https://app.tecof.com/app/apps/install/tcfa_xxxxxxxxxxxxxxxx
```

`private` dağıtım, tek bir müşteriye ya da ajans müşterilerinize özel uygulamalar için uygundur.

---

## Kurulabilirlik Kuralları

Bir mağaza uygulamayı ancak şu koşullarda kurabilir:

1. Uygulama platform sözleşmesiyle yazılmış ve durumu aktif.
2. Ve şunlardan biri:
   - `approved` + `public`
   - `private` dağıtım
   - Mağaza, uygulamanın `testStores` listesinde
3. Partner ve uygulama askıda değil.

Aynı mağazaya ikinci kurulum `409 store-app-already-installed` döner. Panel kurulumdan önce `GET /api/merchant/apps/install-preview/:ref` (`ref` = uygulama kimliği, istemci kimliği ya da slug) ile ad, ikon, geliştirici, istenen kapsamlar, planlar ve kurulabilirliği (`installable`, `reason`) gösterir.

Kurulum isteğinde mağazanın onayladığı kapsamlar istenen kümeye **birebir eşit** olmalıdır (`409 app-scopes-mismatch`); onay ekranı atlanarak kurulum yapılamaz.

---

## Test Mağazaları

- `testStores` yalnız **ekip üyesi olduğunuz** mağazaları kabul eder (`GET /api/developer/test-stores`).
- Onaysız (`draft`, `in-review`, `rejected`) uygulama yalnız bu mağazalara kurulur.
- `tecof app dev` ile kaydedilen `devUrl` yalnız test mağazalarında `appUrl`'in yerine geçer (8 saat geçerli).

---

## Gönderim Öncesi Kontrol Listesi

**Ön koşullar:** Geliştirici API'sini kullanabilmek için partner hesabınız ve üyeliğiniz `active` olmalıdır; `tecof.app.json` sunucu doğrulamasından geçmeyen yapılandırma zaten kaydedilmez (`invalid-app-config`).

### Gönderim kapısı

`POST /api/developer/apps/:id/submit` aşağıdaki maddelerden biri eksikse gönderimi reddeder:

| Madde | Not |
| :--- | :--- |
| İkon yüklendi | `POST /api/developer/apps/:id/media/icon` (512×512, bkz. [Mağaza Görselleri](#magaza-gorselleri)) |
| `listing.shortDescription` Türkçe metni dolu | |
| `listing.description` Türkçe metni dolu | |
| `listing.supportEmail` dolu | |
| `listing.privacyUrl` dolu | |
| `appUrl` `https` | `hosting: "tecof"` için dağıtım `ready` olunca otomatik yazılır |
| En az bir yüzey | Gömülü arayüz (`embedded: true`), webhook aboneliği ya da aksiyon |
| Ücretli plan varsa partner doğrulaması (KYC + IBAN) onaylı | Değilse `app-verification-required` |

### İnceleme hazırlığı

Sistem tarafından zorunlu tutulmaz; incelemenin hızlı ve olumlu sonuçlanması için hazırlayın:

| Madde |
| :--- |
| Ekran görüntüleri yüklendi (`POST /api/developer/apps/:id/media/screenshot`; 1280×800, en fazla 8) |
| `listing.shortDescription` ve `listing.description` İngilizce metinleri de dolu |
| `listing.category` doğru seçildi; `listing.supportUrl` ve `listing.websiteUrl` çalışıyor |
| `listing.privacyUrl` uygulamanın işlediği kişisel veriyi (sipariş, müşteri) açıklıyor |
| Yalnız gereken kapsamlar isteniyor |
| Webhook ve API aksiyonu istekleri imza + zaman damgasıyla doğrulanıyor; işleyiciler idempotent |
| `app.uninstalled` işleniyor; kaldırmada kendi tarafınızdaki veri temizleniyor |
| Sırlar Vault'ta; istemci sırrı tarayıcı koduna girmiyor |
| Aksiyonlar tüm yerleşimlerde test edildi; hata mesajları anlaşılır |
| Ücretli planda özellik kısıtlaması `app.subscription.updated` ile doğru çalışıyor |
| Gömülü arayüz panelin açık/koyu temasına ve diline (`context.theme`, `context.locale`) uyuyor |

---

## Mağaza Görselleri

Uygulama mağazası her uygulama için bir ikon, bir kapak ve ekran görüntüleri gösterir. Bu dosyaları uygulamanın reposunda `store-assets/` klasöründe tutun:

```text
tecof-app-ornek/
├── tecof.app.json
└── store-assets/
    ├── icon.png                  # 512×512
    ├── cover.png                 # 1600×900, logosuz
    └── screenshots/
        ├── 01-genel-bakis.png    # 1280×800
        ├── 02-siparisler.png
        └── 03-ayarlar.png
```

| Görsel | Varsayılan yol | Ölçü | Görüldüğü yer |
| :--- | :--- | :--- | :--- |
| İkon | `store-assets/icon.png` | 512×512, kare | Mağaza kartı, öne çıkanlar, detay sayfası, kurulum ekranı |
| Kapak | `store-assets/cover.png` | 1600×900 (16:9) | Mağaza kartı, öne çıkanlar şeridi, detay sayfası |
| Ekran görüntüleri | `store-assets/screenshots/` içindeki görseller, ad sırasıyla | 1280×800 (16:10), en fazla 8 | Detay sayfasındaki galeri |

PNG önerilir; JPEG ve WebP de kabul edilir (varsayılan adlarda `icon.webp`, `cover.jpg` gibi). Dosyaları 2 MB'ın altında tutun; partner yükleme uçları dosya başına 2 MB kabul eder.

### Görsel kuralları

- **Kapak logosuz olmalı.** Panel uygulamanın ikonunu ve adını kapağın üstüne kendisi yerleştirir. Kapağa logo, ürün adı ya da başka metin koymayın.
- **Kapağın önemli kısmı ortadaki yatay bantta kalsın.** Kapak mağaza kartında 16:9 görünür. Geniş ekranda öne çıkanlar şeridi 16:7 oranındadır ve kapağın sol kenarı metin paneline doğru silikleşir. Detay sayfası geniş ekranda kapağı 21:9'a kırpar ve alt kenarını sayfa zeminine doğru soldurur.
- **İkon kare ve opak zeminli olmalı.** Köşe yuvarlatmasını ve çerçeveyi panel uygular; kendi yuvarlatmanızı ya da gölgenizi eklemeyin. Saydam ikon açık temada beyaz, koyu temada koyu gri zemin üzerinde görünür. Logoyu kenarlara dayamayın.
- **Ekran görüntüleri uygulamanın gerçek ekranlarından alınmalı.** Galeri 16:10 bir kutuda görseli kırpmadan gösterir. Ekranlarda kurgusal veri kullanın; gerçek müşteri, mağaza, hesap ya da anahtar görünmesin. Dosyalar ada göre sıralandığı için adları `01-`, `02-` diye numaralandırın.
- Logo ya da ekran görüntüsünde başka bir markaya ait öğe varsa kaynağını ve kullanım iznini `store-assets/SOURCES.md` dosyasına not edin.

Ölçüleri ve dosya boyutlarını yükleme öncesinde kontrol edebilirsiniz:

```bash
file store-assets/icon.png store-assets/cover.png store-assets/screenshots/*.png   # ölçüler
du -h store-assets/*.png store-assets/screenshots/*.png                           # dosya başına ≤ 2 MB
```

### listing.media ile farklı yollar

Görseller başka bir klasördeyse ya da ekran görüntülerinin sırasını açıkça belirlemek istiyorsanız `tecof.app.json` içinde `listing.media` alanını kullanın:

```json
{
  "listing": {
    "media": {
      "icon": "store-assets/icon.png",
      "cover": "store-assets/cover.png",
      "screenshots": [
        "store-assets/screenshots/01-genel-bakis.png",
        "store-assets/screenshots/02-siparisler.png"
      ]
    }
  }
}
```

| Kural | Değer |
| :--- | :--- |
| Yol | Repo köküne göre; ayırıcı `/`. `/` ile başlayamaz; `.` ya da `..` bölümü (`./`, `a/../b`), boş bölüm (`a//b`) ve `\` içeremez; en fazla 200 karakter |
| Uzantı | `png`, `jpg`, `jpeg`, `webp` |
| `screenshots` | En fazla 8 yol, her biri bir kez; görseller yazıldığı sırayla alınır |

`listing.media` yalnız birinci parti uygulamaların [eşitlemesinde](#birinci-parti-uygulamalarda-esitleme) kullanılır; partner uygulamasında yalnız doğrulanır.

**Hangi yol kullanılır?** Eşitleme her görselin yolunu şu sırayla belirler:

1. Repodaki `tecof.app.json` dosyasında `listing.media` varsa yalnız o okunur.
2. Yoksa (dosya ya da alan yoksa, dosya okunamıyorsa) Tecof'ta saklı yapılandırmadaki `listing.media` geçerlidir. Bu yapılandırma uygulama repodan oluşturulurken alınır. Eşitleme onu güncellemez; yalnız yönetici panelindeki `tecof.app.json` düzenleyicisiyle (`PUT /api/apps/admin/apps/:id/config`) değişir.
3. Seçilen `listing.media`'da yazılmayan görsel `store-assets/` varsayılanına düşer. Kurala uymayan `icon` ya da `cover` yazılmamış sayılır. `screenshots` listesinde kurala uymayan yol atlanır; listede geçerli yol kalmazsa varsayılan klasör kullanılır.

Yazdığınız ama repoda olmayan yol varsayılana düşmez; eşitleme raporunda `missing` olarak görünür. `listing.media`'yı repodan silmek de varsayılanlara döndürmez; saklı yapılandırmada `listing.media` varsa o kullanılmaya devam eder. Varsayılanlara dönmek için alanı yönetici panelindeki `tecof.app.json` düzenleyicisinden de silin.

**Kurala uymayan yolun sonucu** yapılandırmanın nereden geldiğine bağlıdır:

| Nerede | Sonuç |
| :--- | :--- |
| `tecof app config push`, `tecof app deploy`, geliştirici portalı, yönetici panelindeki `tecof.app.json` düzenleyicisi | Yapılandırma reddedilir (`invalid-app-config`) |
| Birinci parti uygulamanın repodan oluşturulması | Yol atılır ve yanıtın `warnings` listesinde `source: "tecof.app.json"` ile görünür; yapılandırmanın geri kalanı alınır |
| Eşitleme | Yol yok sayılır (yukarıdaki 3. madde). Eşitleme sonucunun `errors` listesinde `config` hatası görünür ve durum `partial` olur (hiçbir görsel alınamazsa `error`) |

### Birinci parti uygulamalarda eşitleme

Tecof'un GitHub org'undaki (`tecof/tecof-app-<ad>`) birinci parti uygulamaların görselleri elle yüklenmez. Tecof dosyaları reponun varsayılan dalından (`main`) okuyup mağaza kaydına yükler; repoda değişmeyen dosyayı yeniden yüklemez:

| Ne zaman | Ne olur |
| :--- | :--- |
| Uygulama yönetici panelinde repodan oluşturulurken ya da var olan uygulama bir repoya bağlanırken | İlk görseller kayıtla birlikte gelir |
| Yönetici uygulama sayfasında **Repodan çek** dediğinde | Görseller repodan yeniden okunur |
| Her başarılı üretim dağıtımından sonra | Repodaki görsel değişikliği, dağıtım canlıya çıkınca mağazaya yansır |

> [!IMPORTANT]
> Yönetici panelinden elle yüklenen ikon, kapak ya da ekran görüntüleri eşitlemede korunur. Repodaki görsel bunların yerine yalnız yöneticinin **Zorla güncelle** seçeneğiyle (`force`) geçer. Elle yüklenmiş bir görsel, zorla güncellenene kadar repodaki değişikliğin mağazaya yansımasını engeller; kalıcı değişikliği repoda yapın.

Partner uygulamalarında otomatik eşitleme yoktur. İkon ve ekran görüntülerini geliştirici portalından ya da `POST /api/developer/apps/:id/media/icon` ve `…/media/screenshot` uçlarıyla yükleyin. Bu uçlar kapak kabul etmez; kapak yönetici panelinden eklenir. Aynı ölçü ve kurallar partner uygulamaları için de geçerlidir.

---

## Kod Sürümleri

Tecof barındırmalı bir uygulamanın kodunu yayınlamak incelemeden bağımsızdır: `tecof app push` staged bir sürüm açar, `tecof app promote vN` onu yeniden derlemeden canlıya alır, `tecof app rollback` önceki canlı sürüme anında döner. `tecof app push` `tecof.app.json` dosyasını göndermez; kapsam, liste ve plan değişiklikleri `tecof app config push` (ya da önce yapılandırmayı gönderen `tecof app deploy`) ile gider ve yukarıdaki inceleme kurallarına tabidir. `tecof app deploy` tüm kaynağı yükleyip doğrudan yayınlamaya devam eder.

| Komut | İş |
| :--- | :--- |
| `tecof app push [-m <mesaj>] [--prod]` | Yalnız değişen dosyaları yükler, numaralı sürüm açar (varsayılan staged) |
| `tecof app versions [vN]` | Sürümler ve durumları |
| `tecof app promote vN` | Sürümü canlıya alır |
| `tecof app rollback [vN]` | Daha önce canlıda olmuş bir sürüme döner |

Geliştirici portalında uygulamanın **Sürümler** sekmesi aynı sürümleri gösterir. Ayrıntılar: [Sürümler, Canlıya Alma ve Geri Alma](/versions-and-rollback).

---

## Askıya Alma

Tecof yöneticisi bir uygulamayı gerekçesiyle askıya alabilir (`status: "suspended"`):

- Uygulama katalogdan kalkar.
- Yeni kurulum yapılamaz.
- Kurulum token'ı **basılmaz**: uygulama Tecof API'sine erişemez; `/api/v1` çağrıları `401 app-suspended` döner.

Askının kaldırılması yönetici kararıdır. Partner hesabının askıya alınması da uygulamalarının kurulmasını engeller.

---

## İzleme

| Uç | Ne gösterir |
| :--- | :--- |
| `GET /api/developer/apps/:id/installs` | Kurulumlar |
| `GET /api/developer/apps/:id/charges` | Plan tahsilatları |
| `GET /api/developer/apps/:id/deliveries` | Webhook teslimatları |
| `GET /api/developer/apps/:id/action-runs` | Aksiyon çalıştırmaları |
| `GET /api/developer/apps/:id/deployments` | Dağıtımlar ve durumları (`tecof app deploy`) |
| `GET /api/developer/spaces/app_:id/versions` | Sürümler ve canlı sürüm (`tecof app push` ve diğer yayınlar) |

Geliştirici uçları `Authorization: Bearer tcfd_…` (CLI token'ı) ya da panel oturumu kabul eder. Kapsamlı CI token'ları `/api/developer/apps…` uçlarını kullanamaz (`403 scoped-token-forbidden`); uygulama sürümlerini alan (`/api/developer/spaces…`) uçlarıyla yönetir ([Güvenlik ve CI](/dev-security)).
