# Hesaplar ve İzinler

> Panoda oturum açmanın, rollerin, proje üyeliğinin, parolaların ve oturumların nasıl işlediği — ve kimse oturum açamadığında ne yapılacağı.

- Güncelleme: 2026-09-25
- Kaynak: https://contextator.com/tr/docs/accounts-and-permissions/
- Dil: tr-TR
- Yazar: Muhammet Şafak

---
Pano ve admin API'si kişisel bir hesabın arkasındadır. Bu örneği kullanan herkes kendisi olarak
oturum açar ve ne yapabileceği rolünden gelir.

- [İlk çalıştırma: kurulum kodu](#i̇lk-çalıştırma-kurulum-kodu)
- [Oturum açmak](#oturum-açmak)
- [Roller](#roller)
- [Users sayfası](#users-sayfası)
- [Bir projenin üyeleri](#bir-projenin-üyeleri)
- [Parolalar](#parolalar)
- [Oturumlar](#oturumlar)
- [`ADMIN_TOKEN`: betikler için erişim](#admin_token-betikler-için-erişim)
- [Kimse oturum açamadığında](#kimse-oturum-açamadığında)
- [Hesapların kapsamadığı şeyler](#hesapların-kapsamadığı-şeyler)

---

## İlk çalıştırma: kurulum kodu

Yepyeni bir örneğin hiç hesabı yoktur, bu yüzden ilk istediği şey bir **kurulum kodu**dur. Tek işi,
sunucuya ilk ulaşan kişinin değil, operatörün ilk hesabı almasını sağlamaktır.

Sunucuyu başlatın ve logu izleyin:

```bash
docker compose logs -f
```

Hiç hesap yokken, her başlatma bir kutu yazdırır:

```
┌─ Contextator first-run setup ───────────────────────────────────────────┐
│ No user accounts exist yet; the dashboard is waiting for its first one. │
│                                                                         │
│   Open   http://localhost:3444/setup                                    │
│   Code   KRTW-9MHD-2PQF                                                 │
│                                                                         │
│ A new code is printed on every start until that first account exists.   │
└─────────────────────────────────────────────────────────────────────────┘
```

**http://localhost:3444/setup**'ı açın — pano zaten sizi oraya yönlendirir — ve formu doldurun:

| Alan | Ne girilir |
|-------|---------------|
| **Setup code** | Kutudaki kod. Büyük/küçük harf, tire ve boşluk göz ardı edilir, bu yüzden nasıl okunuyorsa öyle yazın |
| **Username** | Küçük harf, rakam, `.`, `-` ya da `_`, 2–63 karakter, bir harf ya da rakamla başlar |
| **Display name** | Opsiyonel; üst çubukta kullanıcı adı yerine bunu gösterir |
| **Password** | En az 12 karakter. Başka hiçbir şey gerekmez |

**Create the root account** hesabı oluşturur, sizi oturum açtırır ve kurulumu kapatır. O andan
itibaren `/setup`, `/login`'e yönlendirir ve kod bir anlam ifade etmez — burada sonradan rotate edilecek
bir şey yoktur.

### Kodu kendiniz seçmek

İlk başlatmadan önce `.env` içinde ayarlayın, böylece onu bir daha aramak zorunda kalmazsınız:

```bash
SETUP_CODE=ekip-kurulum-2026
```

Seçtiğiniz bir kod asla loga yansıtılmaz; kutu, `.env`'dekini kullanmanızı söyler. Değişkeni temizleyip
yeniden başlatarak yeni bir tane üretilmesini ve yazdırılmasını sağlayabilirsiniz.

:::tip
Kodu mu kaybettiniz? Sunucuyu yeniden başlatın. İlk hesap var olana kadar her başlatmada yeni bir tane
yazdırılır — kurtarma hikâyesinin tamamı budur.
:::

## Oturum açmak

`/login`, bir kullanıcı adı ve bir parola ister, başka hiçbir şey istemez. Bilinçli olarak yaptığı
birkaç şey:

- **Yanlış bir parola ile bilinmeyen bir kullanıcı adı aynı cevabı verir** — *Wrong username or
  password* — aynı miktarda işten sonra, böylece form burada kimin hesabı olduğunu bulmak için
  kullanılamaz.
- **Devre dışı bırakılmış bir hesap, parola doğru olduğunda bunu söyler** (*This account is
  disabled*).
- **Çok fazla deneme iki kez yavaşlatılır.** IP adresi başına, `AUTH_LOGIN_WINDOW_MIN` dakika içinde
  `AUTH_LOGIN_MAX_ATTEMPTS` başarısız deneme `Retry-After` ile bir `429` alır. Hesap başına, aynı eşik
  her ek denemede ikiye katlanan, bir saatte tavanlanan bir kilitlenme başlatır.
- **Geçici bir parola sizi doğrudan `/change-password`'e gönderir** ve onu değiştirmeden başka hiçbir
  şey çalışmaz.

Oturum açmak tek bir çerez ayarlar: `contextator_session`. `HttpOnly`, `SameSite=Lax`, `/`'e kapsanmış
ve örnek HTTPS üzerinden sunulduğunda `Secure`'dır.

:::warning
Düz-HTTP bir LAN adresinde `AUTH_COOKIE_SECURE=0` ayarlayın. Aksi halde tarayıcıya çerezi yalnızca
HTTPS için tutması söylenir, onu düşürür ve pano sonsuza dek `/login`'e geri sıçrar.
:::

## Roller

Üç **örnek rolü** vardır, ve bunların üstünde member'lar için proje başına bir rol:

| | root | admin | editor | viewer |
|---|:--:|:--:|:--:|:--:|
| Proje listesini görmek | tümü | tümü | kendisininkiler | kendisininkiler |
| Bir proje oluşturmak / silmek | ✓ | ✓ | – | – |
| Yeniden indekslemek (artımlı ya da tam) | ✓ | ✓ | ✓ | – |
| Bir projenin kaynaklarını görmek | ✓ | ✓ | ✓ | ✓ |
| Bir kaynak eklemek, düzenlemek, silmek, senkronize etmek ya da test etmek | ✓ | ✓ | ✓ | – |
| Dosya yüklemek ve silmek | ✓ | ✓ | ✓ | – |
| Bir webhook secret'ını görmek ve yeniden üretmek | ✓ | ✓ | ✓ | – |
| Bir projenin MCP tokenlarını görmek | ✓ | ✓ | ✓ | ✓ |
| Bir MCP token üretmek ve iptal etmek | ✓ | ✓ | ✓ | – |
| MCP erişimini değiştirmek — token ya da hesap zorunlu kılmak, ya da endpoint'i yeniden open yapmak | ✓ | ✓ | – | – |
| Bir projenin üyelerini görmek | ✓ | ✓ | ✓ | ✓ |
| Bir üye eklemek, değiştirmek ya da kaldırmak | ✓ | ✓ | – | – |
| Hesapları yönetmek | ✓ | ✓ (root olanlar hariç) | – | – |

`editor` ve `viewer` **üyeliklerdir, rol değil**: üçüncü örnek rolü `member`'dır ve bir `member`
hesabı eklendiği her projede `viewer` ya da `editor` alır. `root` ve `admin`, hiçbir projede
listelenmeden her projeye ulaşır.

Kim sorarsa sorsun geçerli olan üç kural:

- **Son aktif root hesabı silinemez, düşürülemez ya da devre dışı bırakılamaz.** Bir örnek kendi
  kullanıcı yönetiminin dışında asla kilitli kalamaz.
- **Bir admin, bir root hesabına dokunamaz** ve `root` rolünü dağıtamaz. Yalnızca başka bir root
  yapabilir.
- **Kimse kendini devre dışı bırakamaz, düşüremez ya da silemez.**

### Göremediğiniz bir proje yok sayılır

Bir `member`, yalnızca listelendiği projeleri görür — proje listesinde ve her URL'de. Erişimi olmayan
birini istemek, hiç oluşturulmamış bir projeyle aynı şekilde `404` yanıtlar, bu yüzden proje id'leri
denenerek yoklanamaz.

### Düğmeler kural değildir

Pano, yapamayacağınız şeyi gizler, ama her kural sunucuda da, rotaları tek tek değil yöntemlerine ve
biçimlerine göre kapsayan tek bir tablodan yeniden uygulanır. Tarayıcının geliştirici araçlarıyla geri
getirilen bir düğme yine `403` yanıtlar.

## Users sayfası

Sağ üstteki hesap menüsünü açın ve **Users**'ı seçin (`#/~users`). Yalnızca `root` ve `admin`
hesapları içindir.

Hesap başına bir satır: kullanıcı adı ve görünen adı, rolü, **active**, **disabled** olup olmadığı ya
da **password change pending** durumu, kaç projeye ulaştığı ve en son ne zaman oturum açtığı.

| Düğme | Ne yapar |
|--------|--------------|
| **New user** | Bir hesap oluşturur — aşağıya bakın |
| **Edit** | Görünen ad, e-posta, rol ve active anahtarı |
| **Reset password** | Yeni bir geçici parola verir ve o hesabı her yerde oturumdan çıkarır |
| **Disable** / **Enable** | Devre dışı bir hesap oturum açamaz ve açık oturumları hemen sona erer |
| **Delete** | Hesabı, oturumlarını ve üyeliklerini kaldırır. Onaylamak için iki kez tıklayın |

Basmanıza izin verilmeyen bir düğme grileşir ve üzerine geldiğinizde nedenini söyler: *the last active
root account cannot be removed, demoted or disabled*, *you cannot change your own role or disable
yourself*, *only a root account can change another root account*.

### Bir hesap oluşturmak

**New user** şunları ister:

| Alan | Notlar |
|-------|-------|
| **Username** | Küçük harf, 2–63 karakter. Sonradan değiştirilemez |
| **Display name**, **E-mail** | Opsiyonel |
| **Role** | `member` ya da `admin`. `root` yalnızca siz root iseniz görünür |
| **Password** | Boş bırakın, sunucu bir tane üretsin; **Generate** sizin için bir tane doldurur |
| **Must change password at first sign-in** | Varsayılan olarak açık |

Parola, kopyalama düğmesi olan bir diyalogda **bir kez** gösterilir ve sonrasında asla
kurtarılamaz. Bunu kişiye nasıl böyle şeyler gönderiyorsanız öyle gönderin; ilk oturum açtıklarında
değiştirirler.

Bir `member` için hesabı oluşturmak işin yalnızca yarısıdır — onu bir projeye eklemeden hiçbir şeye
ulaşamaz.

## Bir projenin üyeleri

Bir proje seçin ve **Members**'a kaydırın. Bu panel `member` hesaplarıyla ilgilidir: `root` ve
`admin` orada listelenmez, çünkü zaten her projeye ulaşırlar.

- **Add member**, bu projede henüz olmayan aktif `member` hesaplarını sunar. Liste boşsa, önce
  [Users sayfasında](#users-sayfası) bir tane oluşturun.
- Her satırdaki rol açılır menüsü **viewer** ile **editor** arasında geçiş yapar:
  - **viewer** — projeyi okur: kaynaklarını, dokümanlarını, indeksleme geçmişini, MCP tokenlarını.
  - **editor** — bir viewer'ın yaptığı her şey, artı kaynak ekleme, düzenleme, senkronize etme ve
    silme, dosya yükleme ve silme, yeniden indeksleme, ve MCP token üretme ya da iptal etme.
- **Remove**, hesabı projeden çıkarır. Projeyi artık hiç görmez.

Yalnızca `root` ve `admin` bir üyeyi ekleyebilir, değiştirebilir ya da kaldırabilir; başka herkes
listeyi salt okunur görür.

:::warning
Üyelik, çağıranın herhangi bir kimliği olduğunda `/mcp/*`'a ulaşır. Bir hesabı adlandıran bir kimlik
bilgisi, **open** dâhil **her** modda o hesabın üyeliğine karşı denetlenir — yani bir connector'ı
kendisi olarak oturum açtıran biri, projeyi ancak onun üyesiyse okur, aksi halde `403` alır, bu açık
bir projede de kapalı bir proje kadar geçerlidir.

Modun karar verdiği şey, kimseyi adlandırmayan çağırandır. Bir proje **open** iken, URL'sini bilen bir
yabancı onu tıpkı bir `viewer` gibi, anonim olarak okur; **token required** bunu, yine kimliksiz
olarak, bir token'ı elinde tutan herkese daraltır; **account required** ikisini de reddeder, böylece
tek yol bir kimliktir. Bkz. [Projeler](/tr/docs/projects/).
:::

## Parolalar

`PASSWORD_MIN_LENGTH` (varsayılan olarak 12) tek kuraldır, iki bariz reddetmeyle birlikte: bir parola
kullanıcı adı olamaz ve yeni bir parola eskisi olamaz. Kompozisyon kuralı yok, engel listesi yok, en
fazla 128 karakter.

Parolalar salted `scrypt` hash'leri olarak saklanır. Asla loga yazılmazlar, API tarafından asla
döndürülmezler ve geri parolaya çevrilemezler — ne sizin tarafınızdan, ne de veritabanının bir kopyasına
sahip başka birinin tarafından. Unutulmuş bir parolanın aranmak yerine değiştirilmesinin nedeni budur.

### Kendi parolanızı değiştirmek

Hesap menüsü → **Change password**. Mevcut olanı, sonra yeni olanı iki kez ister. Kaydetmek
**hesabınızın her başka oturumunu** kapatır ve kullandığınızı açık bırakır.

### Geçici parolalar

Geçici bir parolayla oluşturulan ya da bir tanesiyle sıfırlanan bir hesap, değiştirilene kadar
`must change password` taşır. Bu sürerken, kişi oturum açıp parolayı değiştirebilir, başka hiçbir şey
işe yaramaz — her başka sayfa ve endpoint `403 password_change_required` yanıtlar (*Choose a new
password before using the dashboard*).

## Oturumlar

Bir oturum açma, yalnızca bir çerez değil, veritabanında bir satırdır, ve birini oturumdan çıkarmanın
gerçekten etkili olmasını sağlayan da budur. Yalnızca oturum token'ının bir hash'i saklanır.

| | Varsayılan | Ayar |
|---|---|---|
| Yeniden oturum açmadan önce boşta kalabileceği süre | 12 saat | `AUTH_SESSION_IDLE_MS` |
| Ne kadar aktif kullanılırsa kullanılsın bir oturumun yaşayabileceği en uzun süre | 30 gün | `AUTH_SESSION_TTL_DAYS` |

Oturumlar şunlar olduğunda erken biter:

| Ne oldu | Hangi oturumlar biter |
|---------------|--------------------|
| Kendi parolanızı değiştirdiniz | Hesabınızın her başka oturumu |
| Bir admin bir hesabın parolasını sıfırladı | O hesabın tümü |
| Bir hesap devre dışı bırakıldı ya da silindi | O hesabın tümü |
| Bir hesap daha düşük bir role indirildi | O hesabın tümü (bir yükseltme böyle yapmaz) |
| Hesap menüsünde **Sign out** | Kullandığınız o oturum |

Bir rol değişikliği her durumda hemen uygulanır — rol her istekte veritabanından okunur, oturuma
donmuş değildir.

Panoda kendi açık oturumlarınızı listeleyen bir sayfa yoktur; API'de vardır, `GET
/api/auth/sessions`'ta, onları sonlandırmak için `DELETE /api/auth/sessions?scope=others|all` ile
birlikte. Bkz. [Admin API](/tr/docs/admin-api/).

## `ADMIN_TOKEN`: betikler için erişim

`ADMIN_TOKEN` hâlâ orada ve hâlâ çalışıyor, ama artık panonun kilidi değil. Kişisi olmayan betikler,
CI ve cron job'ları için, `root` izinleriyle davranan **`/api/*`'e makine erişimi**dir —
`Authorization: Bearer <token>`.

```bash
curl -s http://localhost:3444/api/projects -H "Authorization: Bearer $ADMIN_TOKEN" | jq
```

- **Bir tarayıcıya yapıştırmayın.** Pano bunu kabul etmez ve koyacak bir yeri de yoktur; insanlar bir
  hesapla oturum açar. Onu bir root parolası gibi görün.
- Arkasında bir hesap yoktur, bu yüzden *sizin* hesabınızla ilgili endpoint'ler — bir parolayı
  değiştirmek, kendi oturumlarınızı listelemek — onu `403 token_has_no_account` ile reddeder.
- Çerez isteklerini koruyan same-site kontrolünden muaftır, çünkü bir bearer token, başka bir sitenin
  tarayıcınıza gönderttiği bir şey değildir.

Betiklenmiş hiçbir şeyin API'ye ihtiyacı yoksa boş bırakın.

## Kimse oturum açamadığında

Zahmet sırasına göre:

1. **Başka bir root ya da admin hesabı.** Users sayfası → kilitlenen hesapta **Reset password**.
2. **`ADMIN_TOKEN`.** `.env`'de ayarlayın, `docker compose up -d`, ve API üzerinden yeni bir parola
   dağıtın — bu, hiç hesap gerektirmeyen kaçış kapısıdır:

   ```bash
   export API=http://localhost:3444/api
   ID=$(curl -s $API/users -H "Authorization: Bearer $ADMIN_TOKEN" | jq -r '.[] | select(.username=="alice") | .id')
   curl -s -X POST $API/users/$ID/password -H "Authorization: Bearer $ADMIN_TOKEN" \
     -H 'content-type: application/json' -d '{}' | jq -r .temporaryPassword
   ```

   Her hesap kaybolduysa, aynı token `POST /api/users` ile yepyeni bir `root` hesabı oluşturabilir.
   Bkz. [Admin API](/tr/docs/admin-api/).
3. **Sıfırlama betiği**, kaynaktan çalışan bir kurulumda:

   ```bash
   npm run reset-password -- alice
   ```

   Tek argümanı olarak kullanıcı adını alır ve başka hiçbir şey sormaz. Doğrudan veritabanıyla
   konuşur, bu yüzden ne bir oturuma ne de `ADMIN_TOKEN`'a ihtiyaç duyar — yalnızca veritabanını
   gösteren `.env`'e. Hesabı ve yeni bir parolayı bir kez yazdırır, onu değiştirilmesi gerektiği
   şeklinde işaretler, hesap devre dışıysa yeniden etkinleştirir, herhangi bir kilitlenmeyi temizler
   ve sahip olduğu her oturumu iptal eder. Var olmayan bir isim verildiğinde, var olan hesapları
   listeler.

   ```
     Account:   alice (admin)
     Password:  hT4mQpbWnK9rXdzLvCuA

     Shown once. Sign in with it; the dashboard will ask for a new one straight away.
   ```

   Betik Docker imajının parçası değildir — depoyu ve geliştirme bağımlılıklarını gerektirir — bu
   yüzden bir konteyner kurulumunda yukarıdaki `ADMIN_TOKEN`'ı kullanın.

Bir örneğin hiç hesabı yoksa, yeniden bir kurulum kodu istemeye döner: yeniden başlatın ve
`/setup`'ı açın.

## Hesapların kapsamadığı şeyler

Hesaplar panoyu ve admin API'sini yönetir, ve `/mcp/*`'a da ulaşırlar — ama yalnızca birini
adlandıran bir çağıran için. **open** bir projeye anonim bir istek, ve kapalı birine bir `ctxm_…`
token, kimseyi adlandırmaz: ikisi de burada kim olduğunuz hakkında hiçbir şey bilmez, bu yüzden bir
`viewer` üyeliği orada hiçbir şey vermez ve bir token, onu elinde tutan herkese kendi projesindeki her
şeyi verir. Bir hesabı gerçekten adlandıran bir kimlik bilgisi farklı bir şeydir ve her modda, her
istekte o hesabın üyeliğine karşı denetlenir — onu kabul ettiren şey üyeliktir, mod değil. **account
required**, başka hiçbir yol bırakmayan moddur. `ADMIN_TOKEN` bir hesap değildir ve bunun hiçbirine
ulaşmaz.

İki kapı, yan yana: [Güvenlik](/tr/docs/security/).
