# Hızlı Başlangıç: Tecof CLI

> Uygulamayı sıfırdan test mağazasında çalıştırıp yayınlama: tecof app init/dev/push/promote, proje yapısı ve tecof.app.json referansı.
>
> Kaynak: https://tecof-app-dev.vercel.app/app-quickstart · Bölüm: Uygulama geliştirme · Son güncelleme: 2018-10-20

Bu sayfa bir partner uygulamasını sıfırdan test mağazasında çalıştırıp Tecof barındırmasına dağıtmayı adım adım anlatır. Örnekler Next.js App Router ve TypeScript kullanır.

**Gerekenler**

| Gereksinim | Not |
| :--- | :--- |
| Node.js 20+ | `@tecof/cli` Node ≥20 ister; uygulamanızın kullandığı `@tecof/app-sdk` Node ≥18 ile çalışır (bağımlılıksız; `node:crypto` + `fetch`) |
| Aktif partner üyeliği | Uygulama geliştirici programına kayıtlı, durumu `active` partner. Bkz. [Uygulama Geliştirme](/app-development) |
| Test mağazası | Ekip üyesi olduğunuz bir Tecof mağazası. Onaysız uygulama yalnız test mağazalarına kurulur |

---

## 1. CLI Kurulumu

```bash
npm i -g @tecof/cli
tecof --help
```

> **Not:** `tecof app push`, `app versions`, `app promote` ve `app rollback` komutları ([Sürümler ve geri alma](#surumler-ve-geri-alma-tecof-app-push)) `@tecof/cli` 0.2.0 ile gelir. `tecof --version` 0.2.0'dan küçükse `npm i -g @tecof/cli@latest` ile güncelleyin.

---

## 2. Giriş: tecof login

CLI, tarayıcıda onaylanan bir cihaz akışıyla giriş yapar; parola terminale yazılmaz.

```bash
tecof login
tecof whoami
```

CLI bir doğrulama kodu (`ABCD-EFGH` biçiminde) ve onay adresi (`https://app.tecof.com/cli?code=ABCD-EFGH` biçiminde) gösterir.

Akış:

1. CLI `POST /api/developer/cli/device { clientName }` ile cihaz kodu alır: `{ deviceCode, userCode: "ABCD-EFGH", verificationUri, expiresIn: 600, interval: 5 }`.
2. `verificationUri` adresini açıp panelde oturum açmış olarak isteği onaylarsınız ya da reddedersiniz. Onay ekranı CLI adını, IP'yi, istek zamanını, yetkilendirilecek hesabı ve (varsa) partner hesabını gösterir. Girişin kendisi partner üyeliği istemez; uygulama komutları istek anında aktif partner üyeliği arar.
3. CLI 5 saniyede bir `POST /api/developer/cli/token { deviceCode }` ile yoklar:

| Yanıt | Anlamı |
| :--- | :--- |
| `428 authorization-pending` | Henüz onaylanmadı, yoklama sürer |
| `403 authorization-denied` | İstek panelde reddedildi |
| `410 device-code-expired` | 10 dakika içinde onaylanmadı; `tecof login` ile yeniden başlayın |
| `200 { token: "tcfd_…", expiresAt, partner: { id, name } \| null, user: { id, email } }` | Giriş tamam; partner üyeliği olmayan kullanıcıda `partner` `null` |

Cihaz token'ı (`tcfd_…`) kişisel hesabınıza bağlıdır; 30 gün geçerlidir ve 14 gün kullanılmazsa düşer. Token işletim sisteminin anahtarlığında (macOS Anahtar Zinciri, Linux Secret Service; yoksa `~/.config/tecof/credentials.json`, izin `0600`) saklanır; `~/.config/tecof/config.json` yalnız üst bilgiyi (`apiUrl`, `tokenExpiresAt`, `partner`, `user`) tutar. Farklı bir API adresine (ör. yerel backend) bağlanmak için `tecof login --api <url>` kullanın. Ayrıntılar: [Güvenlik ve CI](/dev-security).

Açık CLI oturumlarınızı panelde `https://app.tecof.com/cli?tab=tokens` sayfasında, `tecof tokens ls` / `tecof tokens revoke <id>` ile ya da API'de `GET /api/developer/cli/tokens` ve `DELETE /api/developer/cli/tokens/:id` ile yönetebilirsiniz. `tecof logout` geçerli token'ı sunucuda da iptal eder.

---

## 3. Proje Oluşturma: tecof app init

```bash
tecof app init isbasi-demo --template starter --name "İşbaşı Demo"
cd isbasi-demo
npm install
```

| Seçenek | Açıklama |
| :--- | :--- |
| `[dir]` | Proje klasörü |
| `--template starter` | Başlangıç şablonu |
| `--template actions` | Aksiyon örnekleri içeren şablon |
| `--name` | Uygulama adı |

`tecof app init` uygulamayı geliştirici hesabınızda **sunucuda oluşturur**, `tecof.app.json` içine `id` / `clientId` bağını yazar ve istemci sırrını `.env.local` dosyasına kaydeder. İstemci sırrı **yalnız** `.env.local` dosyasında tutulur ve commit edilmez.

Mevcut bir uygulamaya bağlanmak için `tecof app link --app <id>` kullanın. İstemci sırrı yalnız oluşturma ve döndürme anında bir kez gösterildiğinden `app link` sırrı sunucudan alamaz: CLI ya `tecof app secret rotate` ile yeni sır almanızı önerir ya da elinizdeki sırrı elle girmenizi kabul eder.

### Proje yapısı

`starter` şablonunun ürettiği düzen (`@tecof/cli` 0.2.0). `actions` şablonu buna ek olarak `app/actions/[key]/` (iframe aksiyonu) ve `app/api/actions/[key]/route.ts` (API aksiyonu) içerir.

```text
isbasi-demo/
├── tecof.app.json              # uygulama yapılandırması (commit edilir)
├── .env.local                  # TECOF_CLIENT_ID / TECOF_CLIENT_SECRET / TECOF_API_URL (commit EDİLMEZ)
├── next.config.ts · postcss.config.mjs · tsconfig.json
├── lib/
│   ├── tecof.ts                # TecofApp örneği + withSession yardımcısı (yalnız sunucu)
│   └── settings-model.ts       # ayar formunun tek şeması (istemci + sunucu)
└── app/
    ├── layout.tsx · providers.tsx   # Geist + TecofAppProvider (@tecof/app-ui)
    ├── globals.css             # Tailwind 4 + React Suite + @tecof/app-ui katmanları
    ├── app-shell.tsx           # AppShell: başlık, durum, sekmeler
    ├── page.tsx                # genel bakış
    ├── settings/               # ayarlar sayfası + AppForm
    └── api/
        ├── session/route.ts    # oturum token'ı ile korunan örnek uç
        ├── settings/route.ts   # validateOnServer + Vault
        └── webhooks/route.ts   # createWebhookHandler (webhooks.path)
```

Arayüz kuralları için [Tasarım kimliği](/app-ui), form ve doğrulama için [Formlar ve şema](/app-forms).

### Ortam değişkenleri

```bash
# .env.local
TECOF_CLIENT_ID=tcfa_xxxxxxxxxxxxxxxx
TECOF_CLIENT_SECRET=tcfs_xxxxxxxxxxxxxxxx
TECOF_API_URL=https://api.tecof.com
# TECOF_PREVIOUS_CLIENT_SECRET=tcfs_...   # yalnız harici barındırmada, sır döndürmeden sonraki 24 saat
```

### SDK örneği

```ts
// lib/tecof.ts — yalnız sunucu kodunda içe aktarın
import { TecofApp } from "@tecof/app-sdk";

export const tecof = new TecofApp({
  clientId: process.env.TECOF_CLIENT_ID!,
  clientSecret: process.env.TECOF_CLIENT_SECRET!,
  previousClientSecret: process.env.TECOF_PREVIOUS_CLIENT_SECRET, // isteğe bağlı: sır döndürme geçişi
  apiUrl: process.env.TECOF_API_URL, // verilmezse TECOF_API_URL okunur
});
```

İstemci sırrını taşıyan değişkenleri asla `NEXT_PUBLIC_` önekiyle tanımlamayın; tarayıcı paketine girer.

---

## 4. Test Mağazasında Geliştirme: tecof app dev

### Test mağazasını tanımlayın

`tecof.app.json` içindeki `testStores` dizisine mağaza kimliğini (`merchantId`) ekleyin. Yalnız ekip üyesi olduğunuz mağazalar kabul edilir; listesini `GET /api/developer/test-stores` döner.

```json
{
  "testStores": ["66f0c0ffee0000000000abcd"]
}
```

Yapılandırmayı sunucuya gönderin:

```bash
tecof app config push
```

### Yerel sunucu ve tünel

```bash
tecof app dev --tunnel cloudflared
```

`tecof app dev` yerel geliştirme sunucunuzu başlatır (varsayılan port **3000**, `--port` ile değişir), tünelle dışarı açar ve tünel adresini uygulamanın `devUrl` değeri olarak kaydeder (`PUT /api/developer/apps/:id/dev-url`). Kurallar:

- `devUrl` **8 saat** geçerlidir; süre dolunca komutu yeniden çalıştırın.
- `devUrl` yalnız **test mağazası kurulumlarında** geçerlidir ve orada `appUrl`'in yerine geçer: panel iframe'i, **webhook teslimatları** ve **API aksiyonları** tünel adresinize gider (adres teslimat anında çözülür). Diğer mağazalar her zaman `appUrl`'i kullanır.

| `--tunnel` | Davranış |
| :--- | :--- |
| `cloudflared` | Cloudflare tüneli açar |
| `none` | Tünel açmaz |
| `<url>` | Kendi açtığınız tünel adresini (ör. başka bir tünel aracı) `devUrl` olarak kaydeder |

Böylece test mağazasında sipariş oluşturduğunuzda `order.paid` gibi webhook'lar ve panelden çalıştırdığınız aksiyonlar doğrudan yerel sunucunuza düşer. Tünel açmadan yalnız imza mantığını denemek için [Aksiyonlar → Yerelde test](/app-actions) bölümündeki imzalı `curl` örneğini kullanabilirsiniz.

### Test mağazasına kurun

Panelde kurulum bağlantısını açın:

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

Onay ekranı istenen kapsamları ve (varsa) planları gösterir. Onaydan sonra uygulamanız `app.installed` webhook'unu alır ve panelde "Uygulamalarım" altında açılır.

---

## 5. Dağıtım

Tecof barındırmalı (`hosting: "tecof"`) bir uygulamayı iki yolla yayınlarsınız:

| Yol | Ne yapar | Durum |
| :--- | :--- | :--- |
| `tecof app push` | Yalnız değişen dosyaları yükler ve numaralı bir sürüm açar; staged derlemeyi önizleyip yeniden derlemeden canlıya alırsınız, gerekirse anında geri alırsınız | Önerilen |
| `tecof app deploy` | Tüm kaynağı arşivleyip yükler ve doğrudan yayınlar | Çalışmaya devam eder |

### Sürümler ve Geri Alma: tecof app push

```bash
tecof app push -m "Fatura listesi"   # staged sürüm açar, ör. v5
tecof app versions                    # sürüm listesi
tecof app promote v5                  # yeniden derlemeden canlıya alır
tecof app rollback                    # bir önceki canlı sürüme döner
tecof app logs v5                     # sürümün derleme günlüğü
```

- Uygulamanın alan kimliği `app_<tecof.app.json içindeki id>` olur; `tecof spaces ls --kind app` uygulama alanlarını listeler.
- Her push `main` dalının o anki hâlinin üstüne kurulur ve klasör istenen son durum sayılır: klasörde olmayan dosyalar depodan silinir. Uygulamalarda `.tecof/` klasörü ve yerel taban kullanılmaz.
- `tecof.app.json` push ile **gönderilmez**; staged kod canlıdaki yapılandırmayı değiştirmesin diye. Yapılandırma değiştiyse `tecof app config push` çalıştırın.
- Depo, Vercel projesi, alan adı ve ortam değişkenleri yoksa ilk push onları ilk `tecof app deploy` gibi kurar. Ortam değişkenleri (aşağıdaki tablo) her push'ta derlemeden önce yeniden yazılır.
- Staged sürüm tam bir üretim derlemesidir ama alan adı almaz. `tecof app promote vN` alan adlarını yeniden derlemeden bu sürüme çevirir ve `main` dalını sürümün commit'ine hızlı ileri alır. `--prod` commit'i doğrudan `main` dalına yazar ve derleme bitince canlıya çıkar.
- `promote`, `rollback` ve `push --prod` onay ister; ajan ve CI ortamlarında `--yes` gerekir.
- `tecof app deploy` yayınları da sürüm listesinde (`source: "cli"`) görünür; geri alma onlarda da çalışır.
- Kendi sunucunuzda barındırılan uygulamalarda (`hosting: "external"`) sürüm komutları çalışmaz.
- Geliştirici portalında uygulamanın **Sürümler** sekmesi aynı sürümleri gösterir; canlıya alma ve geri alma oradan da yapılır.

Kurallar ve ayrıntılar: [Sürümler, Canlıya Alma ve Geri Alma](/versions-and-rollback). CI'dan yayın: [GitHub Actions örneği](/dev-security#github-actions-ornegi).

### Tek Adımda Dağıtım: tecof app deploy

```bash
tecof app deploy -m "İlk sürüm"
tecof app deployments          # dağıtım listesi ve durumları
tecof app logs <deploymentId>  # derleme günlüğü
```

`tecof app deploy` önce `tecof.app.json` dosyasını gönderir, sonra Tecof barındırmasına şu adımlarla dağıtır:

1. CLI projeyi kök klasörlü bir `.tar.gz` arşivine paketler ve yükler (`POST /api/developer/apps/:id/deployments`, multipart `bundle` + `message`).
2. İlk dağıtımda Tecof sizin için şunları açar:
   - GitHub org reposu `tecof-app-<slug>`
   - Vercel projesi `tecof-app-<slug>`
   - Ortam değişkenleri (aşağıdaki tablo)
   - Alan adı `<slug>.apps.<Tecof alan adı>` (varsayılan alt alan `apps`) — örneğin `isbasi.apps.tecof.site`. Alan adı kurulamazsa uygulama `https://tecof-app-<slug>.vercel.app` adresinde yayınlanır
3. Dosyalar tek commit ile varsayılan dala yazılır; Vercel üretim derlemesini başlatır. Önceki dağıtımda olup yeni pakette **bulunmayan dosyalar repodan silinir** (repo her dağıtımda paketin birebir kopyasıdır).
4. Dağıtım durumu: `queued` → `building` → `ready` | `error` | `canceled`. Durum `ready` olunca uygulamanın `appUrl` değeri otomatik güncellenir.

**Paket sınırları**

| Kural | Değer |
| :--- | :--- |
| Hariç tutulanlar | `node_modules`, `.next`, `.git`, `.vercel`, `.env*` |
| Toplam boyut | ≤ 25 MB |
| Dosya sayısı | ≤ 3000 |
| Dosya başına | ≤ 5 MB |

`.env*` dosyaları **yüklenmez**. Sırlar dağıtım ortamına Tecof tarafından verilir:

| Değişken | İçerik |
| :--- | :--- |
| `TECOF_CLIENT_ID` | İstemci kimliği |
| `TECOF_CLIENT_SECRET` | İstemci sırrı |
| `TECOF_API_URL` | Tecof API adresi |
| `TECOF_APP_URL` | Uygulamanın yayın adresi |
| `NEXT_PUBLIC_TECOF_CLIENT_ID` | İstemci kimliği (tarayıcı) |
| `NEXT_PUBLIC_TECOF_API_URL` | Tecof API adresi (tarayıcı) |

Sırrı döndürdüğünüzde (`tecof app secret rotate`) Vercel ortam değişkeni güncellenir ve yeniden dağıtım tetiklenir.

### Kendi sunucunuz (hosting: "external")

`hosting: "external"` seçildiğinde `appUrl` zorunludur ve `https://` olmalıdır (geliştirmede yalnız `http://localhost` / `http://127.0.0.1` kabul edilir). Dağıtım sizin sorumluluğunuzdadır; yukarıdaki ortam değişkenlerini kendiniz tanımlarsınız.

---

## CLI Komutları

| Komut | Açıklama |
| :--- | :--- |
| `tecof login [--api <url>] [--no-browser]` | Cihaz akışıyla giriş |
| `tecof logout` | Token'ı sunucuda iptal eder ve yerelden siler |
| `tecof whoami` | Giriş yapılan kullanıcı ve partner |
| `tecof status` · `tecof doctor` | Bağlı alan ve oturum özeti · ortam denetimi |
| `tecof app init [dir] [--template starter\|actions] [--name <ad>] [--slug <slug>]` | Uygulamayı sunucuda oluşturur, şablondan proje açar, sırrı `.env.local`'e yazar |
| `tecof app link [--app <id\|clientId\|slug>]` | Klasörü mevcut bir uygulamaya bağlar (sırrı alamaz; döndürme ya da elle giriş) |
| `tecof app info` | Bağlı uygulamanın bilgileri |
| `tecof app config push` | `tecof.app.json`'u sunucuya gönderir; art arda hatalar yüzünden pasife alınmış webhook aboneliklerini yeniden etkinleştirir |
| `tecof app dev [--port <n>] [--tunnel cloudflared\|none\|<url>]` | Yerel sunucu (varsayılan 3000) + tünel + `devUrl` kaydı |
| `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üm listesi ya da tek sürümün durumu |
| `tecof app promote vN` · `tecof app rollback [vN]` | Sürümü yeniden derlemeden canlıya alır · önceki canlı sürüme döner |
| `tecof app deploy [-m <mesaj>]` | Tüm kaynağı paketleyip doğrudan yayınlar |
| `tecof app deployments` | `app deploy` dağıtımlarının listesi |
| `tecof app logs <vN\|deploymentId>` | Sürümün ya da dağıtımın derleme günlüğü |
| `tecof app secret rotate` | İstemci sırrını döndürür (eski sır 24 saat geçerli kalır) |
| `tecof app open [--install]` | Uygulamayı geliştirici portalında ya da kurulum sayfasında açar |
| `tecof spaces ls` · `tecof tokens …` · `tecof setup agent` | Alanlar, CI token'ları, kodlama ajanı kurulumu |
| `tecof theme …` | Tema komutları: [Tema Geliştirme: Hızlı Başlangıç](/theme-quickstart) |

Tüm komutlar, seçenekler, çıkış kodları ve JSON makbuzları: [CLI Başvurusu](/cli-reference).

---

## tecof.app.json Referansı

Yapılandırma `tecof app config push`, `tecof app deploy` ya da geliştirici API'sinin `PUT /api/developer/apps/:id/config` ucuyla yazılır. Sunucu dosyayı doğrular, **bilinmeyen alanları atar** ve hataları şu biçimde döner:

```json
{
  "success": false,
  "messageCode": "invalid-app-config",
  "data": {
    "issues": [
      { "path": "actions[0].key", "code": "…", "message": "…" }
    ]
  }
}
```

### Tam örnek

```jsonc
{
  "id": "6720aa00bb11cc22dd33ee44",          // portal/CLI bağı (isteğe bağlı, sunucu yok sayar)
  "clientId": "tcfa_xxxxxxxxxxxxxxxx",        // bilgi amaçlı
  "name": "Logo İşbaşı",
  "slug": "isbasi",
  "hosting": "tecof",                          // "tecof" | "external"
  "appUrl": "https://isbasi.apps.tecof.site",  // external'da zorunlu; tecof'ta dağıtım sonrası otomatik
  "embedded": true,
  "scopes": ["orders:read", "customers:read", "products:read"],
  "webhooks": {
    "path": "/api/webhooks",
    "events": ["order.paid", "order.cancelled", "order.refunded"]
  },
  "actions": [
    {
      "key": "create-invoice", "type": "iframe", "placement": "order.detail",
      "title": { "tr": "İşbaşı'nda fatura kes", "en": "Create İşbaşı invoice" },
      "path": "/actions/create-invoice", "presentation": "modal"
    }
  ],
  "navigation": [
    { "label": { "tr": "Faturalar", "en": "Invoices" }, "path": "/invoices" }
  ],
  "settings": [
    { "key": "apiKey", "label": { "tr": "API anahtarı", "en": "API key" }, "type": "secret", "required": true },
    { "key": "invoiceMode", "label": { "tr": "Fatura tipi", "en": "Invoice mode" }, "type": "select",
      "options": [
        { "value": "draft", "label": { "tr": "Taslak", "en": "Draft" } },
        { "value": "issued", "label": { "tr": "Kesilmiş", "en": "Issued" } }
      ] }
  ],
  "appEvents": {
    "publishes": [
      { "name": "invoice.created", "description": { "tr": "Fatura oluşturuldu", "en": "Invoice created" } }
    ],
    "subscribes": ["app.kargo.shipment.created"]
  },
  "plans": [
    {
      "key": "standart", "name": { "tr": "Standart", "en": "Standard" },
      "description": { "tr": "Aylık plan", "en": "Monthly plan" },
      "price": 199, "currency": "TRY", "interval": "month", "trialDays": 14,
      "features": [{ "tr": "Sınırsız fatura", "en": "Unlimited invoices" }]
    }
  ],
  "listing": {
    "shortDescription": { "tr": "Siparişleri İşbaşı'nda faturalayın", "en": "Invoice orders in İşbaşı" },
    "description": { "tr": "…", "en": "…" },
    "category": "accounting",
    "supportEmail": "destek@ornek.com",
    "supportUrl": "https://ornek.com/destek",
    "privacyUrl": "https://ornek.com/gizlilik",
    "websiteUrl": "https://ornek.com",
    "media": {                                 // isteğe bağlı, yalnız birinci parti; yazılmayan görsel store-assets/ varsayılanı
      "icon": "store-assets/icon.png",
      "cover": "store-assets/cover.png",
      "screenshots": ["store-assets/screenshots/01-genel-bakis.png", "store-assets/screenshots/02-faturalar.png"]
    }
  },
  "testStores": ["66f0c0ffee0000000000abcd"]
}
```

### Alanlar

| Alan | Tip | Kural |
| :--- | :--- | :--- |
| `id` | string | İsteğe bağlı; CLI/portal bağı. Sunucu yok sayar |
| `clientId` | string | Bilgi amaçlı (`tcfa_…`) |
| `name` | string | Uygulama adı |
| `slug` | string | `^[a-z][a-z0-9-]{2,39}$`; global tekil; oluşturulduktan sonra **değişmez**. Metafield namespace'i, uygulama olayı öneki ve barındırma alan adı bundan türer |
| `hosting` | `"tecof"` / `"external"` | Tecof barındırması ya da kendi sunucunuz |
| `appUrl` | string | `external`'da zorunlu; `tecof`'ta dağıtım `ready` olunca otomatik yazılır |
| `embedded` | boolean | Panelde iframe arayüzü var mı |
| `scopes` | string[] | Yalnız uygulamaya açık kapsamlar. Bkz. [Kapsamlar](/app-auth) |
| `webhooks.path` | string | Webhook teslimat yolu (`appUrl`'e göre). Tanımlı değilse yaşam döngüsü olayları (`app.installed` vb.) ve uygulama olayları da teslim **edilemez** |
| `webhooks.events` | string[] | Olay kataloğundan; her olayın gerektirdiği okuma kapsamı `scopes` içinde olmalı. `*` kapalı. Bkz. [Webhook'lar](/app-webhooks) |
| `actions` | object[] | En fazla **12**. Bkz. [Aksiyonlar](/app-actions) |
| `navigation` | object[] | En fazla **8**; `{ label: { tr, en }, path }` |
| `settings` | object[] | Yerel ayar formu, en fazla **30** alan; `select` için `options: [{ value, label }]`. Bkz. [Ayarlar](/app-data) |
| `appEvents.publishes` | object[] | `{ name, description: { tr, en } }`. Bkz. [Uygulamalar Arası İletişim](/app-interop) |
| `appEvents.subscribes` | string[] | `app.<slug>.<ad>` ya da `app.<slug>.*` |
| `plans` | object[] | En fazla **4**; boşsa uygulama ücretsizdir. Bkz. [Ücretlendirme](/app-billing) |
| `listing.shortDescription`, `listing.description` | `{ tr, en }` | Katalog metinleri |
| `listing.category` | string | Mağazada bu sırayla gösterilir: `accounting` (Muhasebe), `shipping` (Kargo ve Lojistik), `management` (Yönetim), `marketing` (Pazarlama), `marketplace` (Pazaryeri), `other` (Diğer). Yazılmazsa `other`. Eski anahtarlar hâlâ kabul edilir ama kullanmayın: `invoicing` → `accounting`, `analytics` / `crm` / `automation` → `management` olarak kaydedilir ve yanıtta `category-deprecated` uyarısı döner. Listede olmayan değer yapılandırmayı reddeder (`invalid-value`) |
| `listing.supportEmail`, `supportUrl`, `privacyUrl`, `websiteUrl` | string | Destek ve yasal bağlantılar |
| `listing.media.icon`, `listing.media.cover` | string | Yalnız birinci parti uygulamada kullanılır. Repodaki ikon (512×512) ve kapak (1600×900, logosuz) görselinin repo köküne göre yolu: `/` ile başlamaz; `.` ya da `..` bölümü, boş bölüm ve `\` içermez; en fazla 200 karakter, uzantı `png` / `jpg` / `jpeg` / `webp`. Yazılmazsa `store-assets/icon.png` ve `store-assets/cover.png`; yazılan ama repoda olmayan yol `missing` olur, varsayılana düşmez. Repodaki `tecof.app.json`'da `listing.media` hiç yoksa Tecof'ta saklı yapılandırmadaki geçerlidir. Bkz. [Mağaza Görselleri](/app-publishing#magaza-gorselleri) |
| `listing.media.screenshots` | string[] | En fazla **8**, yinelenmeyen ekran görüntüsü yolu (1280×800), yazıldığı sırayla; yol kuralları ve çözüm sırası aynı. Yazılmazsa `store-assets/screenshots/` içindeki görseller ad sırasıyla |
| `testStores` | string[] | Mağaza kimlikleri; yalnız ekip üyesi olduğunuz mağazalar kabul edilir |

### Kurallar

- Tüm `path` alanları `appUrl`'e göredir ve `/` ile başlar. Mutlak URL verilecekse `https://` zorunludur; yalnız geliştirme adresi olarak `http://localhost` ve `http://127.0.0.1` kabul edilir.
- `scopes` yalnız uygulama kapsam listesinden seçilir; kapalı kapsamlar (`code:*`, `sandbox:run`, `deploy:write`, `memory:*`, `domains:write`, `ai:generate`) reddedilir.
- **Kapsam artışı mevcut kurulumlara otomatik geçmez.** Kurulum `pendingScopes` alır; mağaza onaylayana kadar eski kapsamla çalışır. Kapsam azalması anında uygulanır.
- Onaylanmış bir uygulamada `listing` ve `plans` değişiklikleri canlıya hemen yansır; **kapsam artışı yeniden inceleme ister** (inceleme sürerken mevcut sürüm yayında kalır). Bkz. [Yayınlama ve İnceleme](/app-publishing).
- Birinci parti uygulamalarda Tecof mağaza görsellerini (`listing.media` yolları ya da `store-assets/` varsayılanları) repodan kendisi çeker: oluşturmada ya da repoya bağlamada, yöneticinin **Repodan çek** işleminde ve her başarılı üretim dağıtımından sonra. Partner uygulamalarında ikon ve ekran görüntüleri portaldan ya da medya uçlarından yüklenir. Bkz. [Mağaza Görselleri](/app-publishing#magaza-gorselleri).

---

## Sonraki Adımlar

- [Kimlik Doğrulama ve Kapsamlar](/app-auth) — oturum token'ı ve imza doğrulama
- [API ile Veri Erişimi](/app-api) — sipariş ve müşteri okuma
- [Webhook'lar](/app-webhooks) — `order.paid` dinleme
- [Örnek Uygulama: Logo İşbaşı](/app-example-isbasi) — uçtan uca örnek
