# Güvenlik ve CI

> CLI kimlik bilgisi deposu, token ömürleri, kapsamlı CI token’ları, GitHub Actions örneği, ajan modu, gizli anahtar taraması ve korunan yollar.
>
> Kaynak: https://tecof-app-dev.vercel.app/dev-security · Bölüm: CLI · Son güncelleme: 2018-10-20

Bu sayfa CLI'ın kimlik bilgilerini nasıl sakladığını, token türlerini ve ömürlerini, CI için kapsamlı token'ları, bir GitHub Actions örneğini, ajan modunu, yüklemedeki gizli anahtar taramasını, korunan yolları ve kodlama ajanlarıyla çalışmayı anlatır.

---

## Kimlik Bilgisi Deposu

`tecof login` token'ı işletim sisteminin anahtarlığına yazar:

| Platform | Depo |
| :--- | :--- |
| macOS | Anahtar Zinciri; servis adı **Tecof CLI**, hesap `<profil>@<API host>` (ör. `default@api.tecof.com`) |
| Linux / BSD | Secret Service (`secret-tool`; ör. GNOME Keyring) |
| Diğerleri ya da anahtarlık yoksa | `~/.config/tecof/credentials.json` (dosya `0600`, klasör `0700`) |

- Anahtarlık kilitli ya da kullanılamıyorsa token dosyaya yazılır ve CLI uyarır; anahtarlık sonradan erişilebilir olunca kopya oraya taşınır.
- `TECOF_CREDENTIAL_STORE=keyring` anahtarlığı zorunlu kılar (yoksa hata verir), `plaintext` dosyayı seçer. `CI` ya da `TECOF_CONFIG_DIR` tanımlıysa varsayılan dosyadır.
- `TECOF_TOKEN` tanımlıysa kayıtlı girişin yerine her zaman o kullanılır.
- Token'lar API adresine bağlıdır: `--api` ile başka bir sunucuya bağlandığınızda kayıtlı token oraya gönderilmez. `TECOF_PROFILE` aynı makinede birden çok hesabı ayırır.
- Sır komut satırı argümanı olarak geçirilmez (süreç listesinde görünmez); anahtarlığa yazılan değer geri okunarak doğrulanır.
- `~/.config/tecof/config.json` yalnız üst bilgi tutar: API ve panel adresi, token bitişi, kullanıcı ve partner. Eski CLI sürümlerinin bu dosyaya yazdığı token ilk kullanımda anahtarlığa taşınır ve dosyadan silinir.
- Token'lar, istemci sırları ve önizleme sırları hiçbir çıktıda ve günlükte basılmaz. Tek istisna, yeni oluşturulan CI token'ının insan çıktısında bir kez gösterilmesidir.

---

## Token Türleri ve Ömürleri

| Tür | Nasıl alınır | Yetki | Ömür |
| :--- | :--- | :--- | :--- |
| Cihaz oturumu (`tcfd_…`) | `tecof login` ve panelde onay | Hesabınızın erişimi: üyesi olduğunuz mağazaların tema alanları, partner hesabınızın uygulamaları, bulut geliştirme, token yönetimi | 30 gün; 14 gün kullanılmazsa düşer |
| Kapsamlı CI token'ı (`tcfd_…`) | Panelde `/cli?tab=tokens` ya da `tecof tokens create` | Seçilen yetki seti ve alanlarla sınırlı | 1–365 gün (varsayılan 90); kullanılmama süresi yoktur |

| Yetki seti | Panelde | İzin verir |
| :--- | :--- | :--- |
| `read` | Salt okuma | Alan ve sürüm listesi, sürüm ayrıntısı, günlükler, önizleme bağlantısı, kaynak indirme, yerel geliştirme değişkenleri |
| `deploy` | Dağıtım | `read` ve push, canlıya alma, geri alma |

Kapsamlı token'ın yapamadıkları:

| İşlem | Yanıt |
| :--- | :--- |
| Bulut geliştirme (`tecof theme dev --cloud`) | `403 token-scope-insufficient` (`data.required: "full"`) |
| `read` yetkisiyle push, canlıya alma, geri alma | `403 token-scope-insufficient` (`data.required: "deploy"`) |
| Token'ın alan listesinde olmayan bir alan | `403 token-space-forbidden` |
| Uygulama yönetimi: `tecof app init`, `link`, `info`, `config push`, `dev`, `deploy`, `deployments`, `secret rotate` | `403 scoped-token-forbidden` |
| Token listeleme, yeni token basma, başka bir token'ı iptal etme, cihaz girişi onaylama | `403 scoped-token-forbidden` |

`tecof app push`, `app versions`, `app promote`, `app rollback` ve `app logs vN` alan uçlarını kullandığı için kapsamlı token'la çalışır.

Ortak kurallar:

- Erişim her istekte yeniden doğrulanır. Mağaza ekibinden çıkarılan ya da partner üyeliği biten kullanıcının token'ları ilgili alanlarda hemen çalışmaz; hesabı pasifleşen kullanıcının token'ları `401 token-revoked` döner.
- Kendi erişiminizden geniş bir token basılamaz: listedeki her alana basım anında erişiminiz olmalıdır (`403 space-not-allowed`).
- Alan listesi boş bırakılırsa token, erişebildiğiniz **tüm** alanlarda — sonradan erişim kazandıklarınız dahil — geçerli olur. CI için yalnız gereken alanı seçin.
- Token değeri yalnız oluşturulurken bir kez gösterilir; Tecof yalnız özetini saklar. Kaybederseniz iptal edip yenisini oluşturun.
- Süresi dolan token `401 token-expired` döner (`data.reason`: `expired` ya da cihaz oturumunda `idle`); CLI `tecof login` önerir.
- Kullanıcı başına en çok 50 etkin kapsamlı token bulunabilir (`409 token-limit-reached`) ve saatte en çok 20 token basılabilir.

> **Mağaza sahipleri için:** Tema alanlarına erişim mağaza ekibi üyeliğine bağlıdır; ekip rolü ayrıca bir kısıtlama getirmez. Kod üzerinde çalışmaması gereken kişileri ekipte tutmayın. Yazma işlemleri ayrıca paketin özel tema ve kod erişimi içermesini ister ([Paket gereksinimi](/spaces#paket-gereksinimi)).

---

## CI Token'ı Oluşturma

### Panelden

1. `https://app.tecof.com/cli?tab=tokens` (**Geliştirici erişimi → CLI anahtarları**) sayfasını açın ve **CI anahtarı oluştur**'a tıklayın.
2. **Ad:** token'ın nerede kullanıldığını anlatan bir ad (en çok 60 karakter), ör. "GitHub Actions · deploy".
3. **Yetki seti:** **Dağıtım** (`deploy`) ya da **Salt okuma** (`read`). Form **Dağıtım** seçili açılır.
4. **Alanlar:** yalnız gereken alanları seçin; boş bırakırsanız tüm alanlar geçerli olur. Dağıtım setinde salt okunur alanlar (ör. katalog temaları) seçilemez.
5. **Geçerlilik:** 1–365 gün (varsayılan 90).
6. Değer bir kez gösterilir: kopyalayıp CI ortamınızın gizli değişkenine (`TECOF_TOKEN`) kaydedin. Koda ya da depoya yazmayın.

Aynı sayfada onayladığınız cihazları ve CI token'larını görür, kullanılmayanları **İptal et** ile kapatırsınız.

### CLI ile

```bash
tecof tokens create --name github-actions --preset deploy --space thm_66f1a2b3c4d5e6f7a8b9c0d1 --expires 90
```

```text
✔ Token oluşturuldu: github-actions (deploy; thm_66f1a2b3c4d5e6f7a8b9c0d1)

  tcfd_…

! Bu değer yalnız bir kez gösterilir; şimdi güvenli bir yere (CI gizli değişkeni) kopyalayın.
CI'da: TECOF_TOKEN=<değer> tecof theme push --json
```

> **Dikkat:** `tecof tokens create` `--preset` verilmezse en dar yetkiyi (`read`) basar; push ve canlıya alma için `--preset deploy` verin. Panel formu ise **Dağıtım** seçili açılır.

- `--space` tekrarlanabilir ya da virgülle ayrılmış liste alır.
- `--json` ile token makbuzda maskelenir (`tcfd_***`) ve bir daha gösterilmez; değeri makbuzdan okumanız gerekiyorsa `--show-secret` ekleyin.
- `tecof tokens ls` token'ları listeler, `tecof tokens revoke <id>` iptal eder (yıkıcı işlem, onay ister).

---

## GitHub Actions Örneği

Senaryo: tema kodu kendi GitHub deponuzda duruyor (`tecof theme init` ile açılmış ve `.tecof/space.json` commit'lenmiş bir klasör). `main` dalına her push'ta staged bir sürüm açılır; sürüm, onaylayıcı tanımlanabilen bir ortamda canlıya alınır. `TECOF_TOKEN` deponun gizli değişkenidir: yalnız bu alana sınırlı, `deploy` yetkili, süreli bir kapsamlı token.

```yaml
name: Tecof tema yayını

on:
  push:
    branches: [main]

concurrency:
  group: tecof-theme
  cancel-in-progress: false

jobs:
  stage:
    runs-on: ubuntu-latest
    outputs:
      ref: ${{ steps.push.outputs.ref }}
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npm install -g @tecof/cli
      - id: push
        name: Staged sürüm
        env:
          TECOF_TOKEN: ${{ secrets.TECOF_TOKEN }}
        run: |
          tecof theme push --json --force > receipt.json
          echo "ref=$(jq -r '.version.ref // empty' receipt.json)" >> "$GITHUB_OUTPUT"

  promote:
    needs: stage
    if: needs.stage.outputs.ref != ''
    runs-on: ubuntu-latest
    environment: production
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npm install -g @tecof/cli
      - name: Canlıya al
        env:
          TECOF_TOKEN: ${{ secrets.TECOF_TOKEN }}
        run: tecof theme promote "${{ needs.stage.outputs.ref }}" --yes --json
```

- **Ajan modu:** CI'da stdin bir terminal değildir; CLI soru sormaz ve canlıya alma yalnız `--yes` ile çalışır.
- **`--force`:** CI'da yerel taban (`.tecof/state.json`) yoktur ve push, Tecof'taki `main` dalının o anki hâlinin üstüne kurulur. Deponuzdan sildiğiniz dosyaların Tecof'ta da silinmesi için `--force` gerekir; yoksa push durur (çıkış 4, `unknown-base`). Bu akışta deponuz istenen son durumdur: Tecof tarafında (Cloud IDE, AI) yapılmış ve deponuzda olmayan değişiklikler bu push'la geri alınır. Tecof'ta değişiklik yapan başka kişiler varsa o değişiklikleri önce deponuza alın.
- **Makbuz:** `--json` stdout'a yalnız başarı makbuzunu yazar; hata makbuzu stderr'e gider ve adım başarısız olur. Değişiklik yoksa (`noop`) `ref` boş kalır ve canlıya alma işi atlanır. Sürüm mesajı deponuzun son commit başlığından alınır.
- **Onay:** GitHub'da `production` ortamına onaylayıcı tanımlarsanız canlıya alma onay bekler; bu sırada staged sürümü panelde **Önizle** ile inceleyebilirsiniz. Canlıya alma işi alanı `.tecof/space.json` dosyasından bulduğu için depoyu checkout eder.
- **Çakışma:** Bu arada `main` değiştiyse canlıya alma `409 base-moved` ile durur (çıkış 4); yeni bir push başlatın. `concurrency` aynı alana eşzamanlı push'ları sıraya koyar (`409 space-busy` önlenir).
- **Uzun derlemeler:** `--json` modu derleme boyunca çıktı basmaz (varsayılan bekleme 900 saniye). Çıktısızlık süresi sınırlı CI sistemlerinde `TECOF_DEBUG=1` ilerlemeyi stderr'e yazar.

**Uygulama için** `tecof theme push` yerine `tecof app push --json`, `tecof theme promote` yerine `tecof app promote` kullanın. Alan kimliği `tecof.app.json` dosyasından gelir. Uygulama push'u her zaman `main` üstüne kurulup klasörü istenen durum saydığı için `--force` gerekmez (komut bu seçeneği kabul etmez). `tecof.app.json` değişiklikleri `tecof app config push` ile ayrıca gönderilir; bu komut kapsamlı token'la çalışmaz.

---

## Ajan Modu

`TECOF_AGENT=1` tanımlıysa ya da stdin bir terminal değilse (boru, CI, kodlama ajanı) CLI ajan modunda çalışır: soru sormaz, tarayıcı açmaz. `--json` modunda da soru sorulmaz.

Yıkıcı işlemler — `promote`, `rollback`, `push --prod`, `tokens revoke` — bu modda `--yes` ya da `TECOF_AGENT_ALLOW_DESTRUCTIVE=1` ister. Onay yoksa API'ye hiçbir istek gitmeden çıkış kodu **3** ile durur:

```text
$ tecof theme promote v12
✖ Bu işlem yıkıcı ve onay gerektiriyor (ajan/etkileşimsiz mod).
  Kullanıcı onayladıysa yeniden çalıştırın: tecof theme promote v12 --yes (ya da TECOF_AGENT_ALLOW_DESTRUCTIVE=1).
```

```json
{
  "ok": false,
  "command": "theme promote",
  "space": "thm_66f1a2b3c4d5e6f7a8b9c0d1",
  "error": {
    "code": "confirmation-required",
    "message": "Bu işlem yıkıcı ve onay gerektiriyor (ajan/etkileşimsiz mod)."
  },
  "next": { "action": "confirm", "command": "tecof theme promote v12 --yes" },
  "diagnostics": []
}
```

Ajanın doğru davranışı: kullanıcıya ne yapılacağını anlatıp onay istemek, onay gelirse `next.command` komutunu çalıştırmak. Kodlama ajanlarının ortamında `TECOF_AGENT_ALLOW_DESTRUCTIVE=1` tanımlamayın; bu, canlıya alma ve geri almayı kullanıcıya sormadan açar. Etkileşimli terminalde aynı işlemler `(e/H)` sorusuyla onay ister.

---

## Gizli Anahtar Taraması

Push'ta yüklenen her metin dosyası (2 MB'a kadar) sunucuda taranır. Engelleyen bir bulgu varsa o yükleme isteğindeki **hiçbir dosya** depoya yazılmaz, sürüm açılmaz ve push çıkış kodu 1 ile durur. İstisna mekanizması yoktur.

| Tür (`kind`) | Ne yakalanır |
| :--- | :--- |
| `tecof-secret` | Tecof'un gizli anahtar biçimleri: istemci sırrı, kurulum token'ı, CLI token'ı, kişisel erişim anahtarı, OAuth token ve kodları. Herkese açık istemci kimliği bulgu sayılmaz |
| `github-token` | GitHub erişim token'ları |
| `aws-access-key` | AWS erişim anahtarı kimlikleri |
| `stripe-live-key` | Stripe canlı gizli anahtarları |
| `slack-token` | Slack token'ları |
| `private-key` | PEM biçimli özel anahtar blokları |

Bulgular yol, satır ve türle bildirilir; **değer hiçbir zaman gösterilmez**:

```text
✖ Yüklenen dosyalarda 1 gizli anahtar bulundu; push durduruldu (değerler gösterilmez):
  lib/keys.ts:3 aws-access-key
  Sırları koddan çıkarın (ortam değişkeni kullanın) ve sızmışsa döndürün. İstisna mekanizması yok.
```

`--json` makbuzunda her bulgu `diagnostics` içinde `{ "level": "error", "code": "secret-detected", "path", "line", "kind" }` olarak yer alır; `next.action` `fix` olur.

- İkili dosyalar ve 2 MB'tan büyük dosyalar taranmaz.
- Mağazanın vitrin anahtarının (`NEXT_PUBLIC_MERCHANT_SECRET_KEY` değeri) bir tema dosyasına gömülmesi push'u engellemez — bu değer zaten tarayıcıya giden genel bir anahtardır — ama sunucu uyarı olarak kaydeder. Değeri koda yazmak yerine ortam değişkeninden okuyun.
- Sızan bir anahtarı silmek yetmez: anahtarı ilgili serviste döndürün (yenileyin).

---

## Gönderilmeyen ve Reddedilen Yollar

CLI şu yolları hiçbir zaman göndermez: `.git/`, `.github/`, `node_modules/`, `.next/`, `.vercel/`, `.turbo/`, `out/`, `coverage/`, `.tecof/`, `.DS_Store`, `*.log`, `.env*` (`.env.example` hariç), `.npmrc`, `*.pem`, `*.key`, `*.p12`, `*.pfx`, `id_rsa*`, `id_ed25519*`. Projenin `.gitignore` ve `.tecofignore` dosyaları da uygulanır ([Yok sayma kuralları](/cli-reference#yok-sayma-kurallari)).

Sunucu, CLI dışından gelen istekler dahil, şu yolları `400 path-forbidden` ile reddeder (`data.reason`):

| Neden | Yol |
| :--- | :--- |
| `git-dir` | Herhangi bir derinlikte `.git` klasörü |
| `github-dir` | Kökte `.github/`; iş akışları Tecof'un GitHub organizasyonunda çalışacağı için |
| `vercel-dir` | Herhangi bir derinlikte `.vercel` klasörü |
| `env-file` | `.env` ile başlayan dosyalar (`.env.example` hariç) |
| `npmrc` | `.npmrc` |
| `key-file` | `*.pem`, `*.key`, `*.p12`, `*.pfx`, `id_rsa*`, `id_ed25519*` |
| `absolute`, `dot-segment`, `backslash`, `control-char`, `too-long` | Mutlak yol, `.` ya da `..` bileşeni, ters bölü, denetim karakteri, 300 karakteri aşan yol |
| `case-collision`, `file-dir-conflict` | Yalnız büyük/küçük harfle ayrışan iki yol; aynı adda hem dosya hem klasör |

---

## Silinmeye Karşı Korunan Yollar

Sunucu, push'ta yer almayan dosyaları depodan siler. Şunlar **asla silinmez**:

- Herhangi bir derinlikte `.github/` altındaki dosyalar,
- Yukarıdaki sabit yok sayma listesine giren yollar,
- Depodaki kök `.gitignore` ve `.tecofignore` desenlerine uyan yollar (push yeni desenler getiriyorsa onlar da),
- Depodaki sembolik bağlantılar ve alt modüller.

Alt klasördeki ignore dosyalarını sunucu okumaz; ayrıntı için [Yok sayma kuralları](/cli-reference#yok-sayma-kurallari). Yerel tabanı olmayan (hiç `pull` yapılmamış) bir tema klasöründen yapılan push uzakta dosya silecekse CLI durur (çıkış 4, `unknown-base`); bilinçli silme için `--force` verin.

---

## Yerel Dosyalar

- `tecof theme dev`, `.env.local` dosyasını `0600` izinle yazar; `.env*` dosyaları hiçbir zaman gönderilmez.
- `.tecof/state.json` yalnız taban commit'ini ve dosya özetlerini tutar; sır içermez.
- `tecof theme pull` arşivi diske yazmadan önce bellekte doğrular: mutlak yol, `..`, ters bölü, sembolik ya da sabit bağlantı veya aygıt girişi içeren bir arşiv reddedilir ve hiçbir dosya yazılmaz. Proje kökünün dışına ya da bir bağlantının üzerinden yazılmaz; arşiv `.tecof/` klasörünü değiştiremez.
- Push sembolik bağlantıları izlemez; uyarıyla atlar.

---

## Kodlama Ajanları

### tecof setup agent

```bash
tecof setup agent                                      # Claude Code: .mcp.json
tecof setup agent --client cursor                      # Cursor: .cursor/mcp.json
tecof setup agent --merchant 66f0c0ffee0000000000abcd  # mağaza kapsamlı adres
```

```json
{
  "mcpServers": {
    "tecof": { "type": "http", "url": "https://api.tecof.com/mcp" }
  }
}
```

- Komut, projenin `.mcp.json` (Claude Code) ya da `.cursor/mcp.json` (Cursor; girdi yalnız `url` içerir) dosyasına Tecof uzak MCP sunucusunu ekler. Dosyadaki diğer sunucular korunur; aynı girdi zaten varsa dosyaya dokunulmaz.
- Dosyaya **sır yazılmaz**: istemci ilk bağlantıda Tecof giriş ve onay ekranını (OAuth) açar. Bu yüzden dosya güvenle commit'lenebilir.
- `--merchant` mağaza kapsamlı adresi (`/mcp/<mağaza kimliği>`) yazar.
- Dosyada farklı bir `tecof` girdisi varsa (ör. tema deposundaki `@tecof/mcp` stdio tanımı) `--force` olmadan değiştirilmez; makbuzda `next.action: "confirm"` döner.
- Ardından Claude Code'u bu klasörde yeniden başlatıp `/mcp` ile bağlantıyı onaylayın; Cursor'da Settings → MCP altında "tecof" sunucusunu etkinleştirin.

MCP araçları, kapsamlar ve onay kuralları: [MCP Entegrasyonu](/mcp). Ajan CLI'ı kendisi çalıştırıyorsa ajan modu kendiliğinden açılır; yıkıcı işlemlerde yukarıdaki onay akışını izleyin.

---

## Kontrol Listesi

- [ ] CI'da yalnız gereken alana sınırlı, `deploy` yetkili ve süreli bir kapsamlı token; değer CI gizli değişkeninde.
- [ ] Kodlama ajanlarının ortamında `TECOF_AGENT_ALLOW_DESTRUCTIVE` tanımlı değil.
- [ ] `.env*`, anahtar dosyaları ve `.npmrc` depoda değil; sırlar ortam değişkenlerinde.
- [ ] Önizleme bağlantıları yalnız yetkili kişilerle paylaşılıyor.
- [ ] Kullanılmayan cihaz oturumları ve CI token'ları `/cli?tab=tokens` ya da `tecof tokens revoke` ile iptal edildi.
- [ ] Mağaza ekibinde yalnız kod üzerinde çalışması gereken kişiler var.
