openapi: 3.1.0
info:
  title: Paftara Platform API
  version: 1.0.0
  summary: Sosyal platform çekirdeğinin web ve mobil istemcileri için REST sözleşmesi
  description: |
    Paftara web uygulaması ve React Native mobil uygulaması aynı `ApiClient` sözleşmesini kullanır.
    Demo sürümünde `MockAdapter` bu uçları tarayıcı içinde taklit eder; kurulumda `HttpAdapter` gerçek sunucuya bağlanır.
    Tını (yankı) sayıları YALNIZ içerik sahibine döner; herkese açık beğeni ya da takipçi sayacı yoktur.
    Bu belge Briefikir tarafından hazırlanmış bir demo sözleşmesidir.
  contact:
    name: Briefikir
    url: https://www.briefikir.com.tr/yazilim/mobil-uygulama-gelistirme/
servers:
  - url: https://api.ornek-platform.com
    description: Üretim (kurulumda müşterinin alan adı)
  - url: https://api-test.ornek-platform.com
    description: Test ortamı
security:
  - bearer: []
tags:
  - name: Oturum
    description: Giriş, iki adımlı doğrulama, jeton yenileme
  - name: Ben
    description: Oturum sahibinin durumu, ayarları ve oturumları
  - name: Gönderiler
    description: Paylaşım, görünürlük halkası, planlı paylaşım, iş birliği etiketi
  - name: Yankı
    description: Beğeni yerine tınılar ve yanıtlar (yazı, ses izi, fotoğraf)
  - name: Örgüler
    description: Ortak üretim zinciri — halkalar ve dallanma
  - name: Anlar
    description: Konuma ve zamana bağlı 24 saatlik içerik
  - name: Kapsüller
    description: İleri tarihe kilitli zaman kapsülleri
  - name: Mesajlar
    description: Birebir ve grup sohbetleri, istekler, kaybolan mesaj
  - name: Atölye
    description: Gerçek zamanlı ortak pano (WebSocket kanalıyla)
  - name: Etkinlikler
    description: Ada etkinlikleri, katılım, takvim dosyası
  - name: Keşif
    description: Arama ve öneriler (öneri nedeni ile)
  - name: Bildirimler
    description: Gruplanmış bildirimler ve özet kipi
  - name: Medya
    description: Ön imzalı adresle doğrudan yükleme
  - name: KVKK
    description: Veri dışa aktarım ve başvurular
  - name: Yönetim
    description: Güven merkezi — moderasyon, kurallar, bayraklar
paths:
  /v1/oturum/giris:
    post:
      tags: [Oturum]
      summary: E-posta ve parolayla giriş
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/GirisIstek'
            example:
              eposta: defne@example.com
              parola: ornek-parola-2026
      responses:
        '200':
          description: İki adımlı doğrulama gerekiyorsa `ikiAdim` bileti, gerekmiyorsa jeton döner
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GirisYanit'
              example:
                ikiAdim: true
                bilet: 2fa_8KQ2M9
        '401':
          $ref: '#/components/responses/Yetkisiz'
        '429':
          $ref: '#/components/responses/CokIstek'
  /v1/oturum/iki-adim:
    post:
      tags: [Oturum]
      summary: İki adımlı doğrulama kodunu onayla
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [bilet, kod]
              properties:
                bilet:
                  type: string
                kod:
                  type: string
                  pattern: '^[0-9]{6}$'
            example:
              bilet: 2fa_8KQ2M9
              kod: '482613'
      responses:
        '200':
          description: Jeton çifti
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Jeton'
        '401':
          $ref: '#/components/responses/Yetkisiz'
  /v1/oturum/yenile:
    post:
      tags: [Oturum]
      summary: Erişim jetonunu yenileme jetonuyla yenile
      description: HttpAdapter 401 aldığında bu ucu bir kez çağırır ve isteği yineler.
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [yenile]
              properties:
                yenile:
                  type: string
      responses:
        '200':
          description: Yeni jeton çifti
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Jeton'
        '401':
          $ref: '#/components/responses/Yetkisiz'
  /v1/ben/durum:
    get:
      tags: [Ben]
      summary: Oturum sahibinin görebildiği durum
      description: Halka kuralı (`gorebilir`) sunucuda uygulanır; istemciye yalnız görebileceği içerik gider.
      responses:
        '200':
          description: Durum özeti
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Durum'
  /v1/ben/ayarlar:
    patch:
      tags: [Ben]
      summary: Ayarları güncelle (tema, dil, süre bütçesi, sessiz saatler, bildirim kipi)
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/KullaniciAyar'
      responses:
        '200':
          description: Güncel ayarlar
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/KullaniciAyar'
  /v1/ben/oturumlar:
    get:
      tags: [Ben]
      summary: Açık oturumlar (web, iOS, Android)
      responses:
        '200':
          description: Oturum listesi
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Oturum'
  /v1/ben/oturumlar/{id}:
    delete:
      tags: [Ben]
      summary: Bir oturumu kapat
      parameters:
        - $ref: '#/components/parameters/Id'
      responses:
        '204':
          description: Kapatıldı
  /v1/gonderiler:
    post:
      tags: [Gönderiler]
      summary: Gönderi paylaş
      description: Gönderi aktif moderasyon kurallarından geçer; tetiklenen kurala göre işaretlenir, incelemeye alınır ya da gizlenir.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/GonderiGirdi'
            example:
              ada: seramik
              baslik: Kül sırı, ikinci deneme
              metin: 1240 derecede 20 dakika bekletip yavaş soğuttum.
              halka: cevre
              etiketler: [sır, fırın]
              medya: [yerel/2026-10-25/kase.webp]
      responses:
        '201':
          description: Oluşturuldu
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Gonderi'
        '422':
          $ref: '#/components/responses/Dogrulama'
  /v1/gonderiler/{id}:
    get:
      tags: [Gönderiler]
      summary: Gönderi ayrıntısı
      parameters:
        - $ref: '#/components/parameters/Id'
      responses:
        '200':
          description: Gönderi
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Gonderi'
        '404':
          $ref: '#/components/responses/Yok'
    delete:
      tags: [Gönderiler]
      summary: Kendi gönderini sil
      parameters:
        - $ref: '#/components/parameters/Id'
      responses:
        '204':
          description: Silindi
  /v1/gonderiler/{id}/tinilar:
    post:
      tags: [Yankı]
      summary: Tını bırak (beğeni yerine)
      parameters:
        - $ref: '#/components/parameters/Id'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [tini]
              properties:
                tini:
                  $ref: '#/components/schemas/Tini'
      responses:
        '204':
          description: Kaydedildi (sayı döndürülmez)
    get:
      tags: [Yankı]
      summary: Tını dağılımı — YALNIZ içerik sahibine
      parameters:
        - $ref: '#/components/parameters/Id'
      responses:
        '200':
          description: Sahibine özel sayaç
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TiniSayac'
        '403':
          description: İçerik sahibi değilsiniz; sayılar herkese açık değildir
  /v1/gonderiler/{id}/yanitlar:
    post:
      tags: [Yankı]
      summary: Yanıt ekle (yazı, ses izi ≤60 sn, fotoğraf)
      parameters:
        - $ref: '#/components/parameters/Id'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/YanitGirdi'
      responses:
        '201':
          description: Yanıt
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Yanit'
  /v1/orguler/{id}:
    get:
      tags: [Örgüler]
      summary: Örgü ve halka ağacı
      parameters:
        - $ref: '#/components/parameters/Id'
      responses:
        '200':
          description: Örgü
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Orgu'
  /v1/orguler/{orgu}/halkalar:
    post:
      tags: [Örgüler]
      summary: Örgüye halka ekle (devam ettir)
      parameters:
        - name: orgu
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [ust, metin]
              properties:
                ust:
                  type: string
                  description: Devam ettirilen halkanın gönderi kimliği
                metin:
                  type: string
                medya:
                  type: array
                  items:
                    type: string
      responses:
        '201':
          description: Yeni halka (gönderi)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Gonderi'
  /v1/anlar:
    get:
      tags: [Anlar]
      summary: Çevrendeki anlar (semt düzeyinde bulanık)
      parameters:
        - name: lat
          in: query
          schema:
            type: number
        - name: lng
          in: query
          schema:
            type: number
      responses:
        '200':
          description: Son 24 saatin anları
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/An'
    post:
      tags: [Anlar]
      summary: An paylaş
      description: Kesin konum yalnız `kesin=true` ve kullanıcının açık izni varsa saklanır.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/An'
      responses:
        '201':
          description: Paylaşıldı
  /v1/kapsuller:
    post:
      tags: [Kapsüller]
      summary: Zaman kapsülü oluştur
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Kapsul'
      responses:
        '201':
          description: Kilitli kapsül; açılış tarihinde bildirim gönderilir
  /v1/sohbetler:
    get:
      tags: [Mesajlar]
      summary: Sohbetler ve mesaj istekleri
      parameters:
        - name: kutu
          in: query
          schema:
            type: string
            enum: [sohbet, istek]
      responses:
        '200':
          description: Sohbet listesi
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Sohbet'
  /v1/sohbetler/{sohbet}/mesajlar:
    post:
      tags: [Mesajlar]
      summary: Mesaj gönder
      description: Kaybolan mesaj açıksa sunucu `bitis` alanını doldurur ve süre dolunca iki tarafta da siler.
      parameters:
        - name: sohbet
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MesajGirdi'
      responses:
        '201':
          description: Mesaj
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Mesaj'
  /v1/atolye/{oda}/kartlar:
    post:
      tags: [Atölye]
      summary: Panoya kart ekle
      description: |
        Gerçek zamanlı eşitleme `wss://api.ornek-platform.com/v1/atolye/{oda}/canli` WebSocket kanalıyla yapılır.
        Kalıcı işlemler (kart ekle/taşı/sil, oda sohbeti) olay olarak yayılır; imleç konumu yalnız kanalda taşınır, saklanmaz.
      parameters:
        - name: oda
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AtolyeKart'
      responses:
        '201':
          description: Kart
  /v1/etkinlikler/{id}/katil:
    post:
      tags: [Etkinlikler]
      summary: Etkinliğe katıl (sınır doluysa bekleme listesi)
      parameters:
        - $ref: '#/components/parameters/Id'
      responses:
        '200':
          description: Katılım durumu
          content:
            application/json:
              schema:
                type: object
                properties:
                  durum:
                    type: string
                    enum: [katildi, bekleme]
  /v1/etkinlikler/{id}/takvim.ics:
    get:
      tags: [Etkinlikler]
      summary: Takvime ekle dosyası
      parameters:
        - $ref: '#/components/parameters/Id'
      responses:
        '200':
          description: iCalendar dosyası
          content:
            text/calendar:
              schema:
                type: string
  /v1/arama:
    get:
      tags: [Keşif]
      summary: Ada, kişi, örgü ve etiket araması
      description: Türkçe karakter duyarsız ve yazım hatasına toleranslıdır (ör. "seramk" → Seramik).
      parameters:
        - name: q
          in: query
          required: true
          schema:
            type: string
        - name: tur
          in: query
          schema:
            type: string
            enum: [ada, kisi, orgu, etiket]
      responses:
        '200':
          description: Sonuçlar; öneriler `neden` alanıyla gelir
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/AramaSonuc'
  /v1/bildirimler:
    get:
      tags: [Bildirimler]
      summary: Gruplanmış bildirimler
      parameters:
        - name: kip
          in: query
          schema:
            type: string
            enum: [hepsi, ozet, onemli]
      responses:
        '200':
          description: Bildirimler
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Bildirim'
  /v1/medya/yukleme:
    post:
      tags: [Medya]
      summary: Ön imzalı yükleme adresi iste
      description: İstemci dosyayı dönen adrese doğrudan PUT eder, ardından `/v1/medya/yukleme/tamam` çağırır. Sunucu görseli boyutlandırır (avif/webp) ve EXIF konumunu siler.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [ad, tur, boyut]
              properties:
                ad:
                  type: string
                tur:
                  type: string
                  example: image/jpeg
                boyut:
                  type: integer
                  maximum: 15728640
      responses:
        '200':
          description: Yükleme bileti
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/YuklemeBilet'
  /v1/medya/yukleme/tamam:
    post:
      tags: [Medya]
      summary: Yüklemeyi tamamla
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [anahtar]
              properties:
                anahtar:
                  type: string
      responses:
        '200':
          description: Medya adresi
          content:
            application/json:
              schema:
                type: object
                properties:
                  url:
                    type: string
                    format: uri
  /v1/kullanicilar/{id}/veri-disa-aktarim:
    get:
      tags: [KVKK]
      summary: Kişisel verilerin JSON dökümü
      parameters:
        - $ref: '#/components/parameters/Id'
      responses:
        '200':
          description: Kullanıcının bütün verisi
          content:
            application/json:
              schema:
                type: object
  /v1/kvkk/talepler:
    post:
      tags: [KVKK]
      summary: KVKK başvurusu oluştur (erişim, düzeltme, silme, itiraz)
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/KvkkTalep'
      responses:
        '201':
          description: Başvuru; son yanıt tarihi 30 gün sonrası
  /v1/yonetim/moderasyon:
    get:
      tags: [Yönetim]
      summary: Moderasyon kuyruğu
      parameters:
        - name: durum
          in: query
          schema:
            type: string
            enum: [bekliyor, karar, itiraz, itiraz-sonuc]
      responses:
        '200':
          description: Kayıtlar
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/ModKayit'
  /v1/yonetim/moderasyon/{id}/karar:
    post:
      tags: [Yönetim]
      summary: Moderasyon kararı ver
      parameters:
        - $ref: '#/components/parameters/Id'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [tur, gerekce]
              properties:
                tur:
                  type: string
                  enum: [kaldir, uyari, kisitla, askiya-al, geri-yukle, gecersiz]
                gerekce:
                  type: string
                sablon:
                  type: string
      responses:
        '200':
          description: Karar işlem günlüğüne yazıldı
  /v1/yonetim/kurallar:
    get:
      tags: [Yönetim]
      summary: Otomatik moderasyon kuralları
      responses:
        '200':
          description: Kurallar
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/ModKural'
    post:
      tags: [Yönetim]
      summary: Kural ekle ya da güncelle
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ModKural'
      responses:
        '201':
          description: Kaydedildi; yeni gönderilere hemen uygulanır
  /v1/yonetim/bayraklar:
    patch:
      tags: [Yönetim]
      summary: Özellik bayrakları
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Bayraklar'
      responses:
        '200':
          description: Güncel bayraklar
  /v1/komut/{ad}:
    post:
      tags: [Ben]
      summary: Genel işlem ucu
      description: HTTP_ESLEME tablosunda ayrı ucu olmayan çekirdek işlemleri (ör. sohbetAyar, atolyeKartTasi) aynı adla çalıştırır.
      parameters:
        - name: ad
          in: path
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              type: object
      responses:
        '200':
          description: İşlem sonucu
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
webhooks:
  gonderi.olusturuldu:
    post:
      summary: Yeni gönderi yayınlandı
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/OlayGonderi'
      responses:
        '200':
          description: Alındı
  moderasyon.karar:
    post:
      summary: Moderasyon kararı verildi
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/OlayModerasyon'
      responses:
        '200':
          description: Alındı
  kvkk.talep:
    post:
      summary: Yeni KVKK başvurusu
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/KvkkTalep'
      responses:
        '200':
          description: Alındı
components:
  securitySchemes:
    bearer:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: Erişim jetonu 15 dakika, yenileme jetonu 30 gün geçerlidir.
  parameters:
    Id:
      name: id
      in: path
      required: true
      schema:
        type: string
  responses:
    Yetkisiz:
      description: Oturum yok ya da jeton geçersiz
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Hata'
    Yok:
      description: Kayıt bulunamadı ya da görünürlük halkası dışında
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Hata'
    Dogrulama:
      description: Girdi doğrulaması başarısız (zod şemasıyla aynı kurallar)
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Hata'
    CokIstek:
      description: Hız sınırı
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Hata'
  schemas:
    Hata:
      type: object
      required: [ileti]
      properties:
        ileti:
          type: string
          example: En az birkaç kelime yazın
        alanlar:
          type: object
          additionalProperties:
            type: string
    GirisIstek:
      type: object
      required: [eposta, parola]
      properties:
        eposta:
          type: string
          format: email
        parola:
          type: string
          minLength: 10
    GirisYanit:
      type: object
      properties:
        ikiAdim:
          type: boolean
        bilet:
          type: string
        jeton:
          $ref: '#/components/schemas/Jeton'
    Jeton:
      type: object
      required: [erisim, yenile, bitis]
      properties:
        erisim:
          type: string
        yenile:
          type: string
        bitis:
          type: integer
          description: Unix zaman damgası (ms)
    Halka:
      type: string
      enum: [yakin, cevre, ada, herkes]
      description: Görünürlük halkası
    Tini:
      type: string
      enum: [ilham, ogrendim, bendede, emek, merak]
    TiniSayac:
      type: object
      description: Yalnız içerik sahibine döner
      properties:
        ilham:
          type: integer
        ogrendim:
          type: integer
        bendede:
          type: integer
        emek:
          type: integer
        merak:
          type: integer
      example:
        ilham: 6
        ogrendim: 4
        bendede: 2
        emek: 9
        merak: 3
    Kullanici:
      type: object
      properties:
        id:
          type: string
        ad:
          type: string
        kullaniciAdi:
          type: string
        semt:
          type: string
        il:
          type: string
        adalar:
          type: array
          items:
            type: string
        avatar:
          type: string
          nullable: true
    Ada:
      type: object
      properties:
        id:
          type: string
          example: seramik
        ad:
          type: string
          example: Seramik
        renk:
          type: string
        x:
          type: number
        y:
          type: number
        r:
          type: number
    Medya:
      type: object
      properties:
        tur:
          type: string
          enum: [foto, video, metin, ses]
        url:
          type: string
        sure:
          type: number
    GonderiGirdi:
      type: object
      required: [ada, metin, halka]
      properties:
        ada:
          type: string
        baslik:
          type: string
          maxLength: 80
        metin:
          type: string
          minLength: 3
          maxLength: 2200
        halka:
          $ref: '#/components/schemas/Halka'
        etiketler:
          type: array
          maxItems: 8
          items:
            type: string
        medya:
          type: array
          items:
            type: string
          description: Yükleme anahtarları
        isbirligi:
          type: string
          description: İş birliği etiketi (zorunlu bildirim)
        uyari:
          type: string
          description: İçerik uyarısı katmanı
        planli:
          type: string
          format: date-time
    Gonderi:
      type: object
      properties:
        id:
          type: string
        yazar:
          type: string
        ada:
          type: string
        baslik:
          type: string
        metin:
          type: string
        medya:
          type: array
          items:
            $ref: '#/components/schemas/Medya'
        halka:
          $ref: '#/components/schemas/Halka'
        tarih:
          type: string
          format: date-time
        orgu:
          type: object
          properties:
            id:
              type: string
            ust:
              type: string
              nullable: true
        durum:
          type: string
          enum: [yayinda, kaldirildi, incelemede, taslak]
    YanitGirdi:
      type: object
      required: [tur]
      properties:
        tur:
          type: string
          enum: [yazi, ses, foto]
        metin:
          type: string
        ses:
          type: object
          properties:
            sure:
              type: number
              maximum: 60
            dalga:
              type: array
              items:
                type: number
        foto:
          type: string
    Yanit:
      type: object
      properties:
        id:
          type: string
        gonderi:
          type: string
        kim:
          type: string
        tur:
          type: string
        metin:
          type: string
        tarih:
          type: string
          format: date-time
    Orgu:
      type: object
      properties:
        id:
          type: string
        ad:
          type: string
        ada:
          type: string
        baslatan:
          type: string
        kok:
          type: string
        oneCikanDal:
          type: string
        halkalar:
          type: array
          items:
            $ref: '#/components/schemas/Gonderi'
    An:
      type: object
      properties:
        metin:
          type: string
        semt:
          type: string
        il:
          type: string
        lat:
          type: number
        lng:
          type: number
        kesin:
          type: boolean
          default: false
        bitis:
          type: string
          format: date-time
    Kapsul:
      type: object
      required: [baslik, metin, kime, acilis]
      properties:
        baslik:
          type: string
        metin:
          type: string
        kime:
          type: string
          enum: [kendime, cevreme, adaya]
        acilis:
          type: string
          format: date-time
    Sohbet:
      type: object
      properties:
        id:
          type: string
        tur:
          type: string
          enum: [birebir, grup]
        ad:
          type: string
        uyeler:
          type: array
          items:
            type: string
        istek:
          type: boolean
        kaybolan:
          type: integer
          description: Saniye (86400 ya da 604800); yoksa kapalı
        okunduBilgisi:
          type: boolean
    MesajGirdi:
      type: object
      properties:
        metin:
          type: string
          maxLength: 2000
        ses:
          type: object
        foto:
          type: string
        gonderi:
          type: string
    Mesaj:
      type: object
      properties:
        id:
          type: string
        sohbet:
          type: string
        kim:
          type: string
        tarih:
          type: string
          format: date-time
        metin:
          type: string
        okuyan:
          type: array
          items:
            type: string
        bitis:
          type: string
          format: date-time
    AtolyeKart:
      type: object
      properties:
        tur:
          type: string
          enum: [foto, not]
        x:
          type: number
        y:
          type: number
        slot:
          type: string
        metin:
          type: string
          maxLength: 280
    Bildirim:
      type: object
      properties:
        id:
          type: string
        tur:
          type: string
        metin:
          type: string
        onemli:
          type: boolean
        okundu:
          type: boolean
    AramaSonuc:
      type: object
      properties:
        tur:
          type: string
          enum: [ada, kisi, orgu, etiket]
        id:
          type: string
        baslik:
          type: string
        neden:
          type: string
          example: Seramik adasında 3 ortak örgün var
    YuklemeBilet:
      type: object
      properties:
        anahtar:
          type: string
        url:
          type: string
          format: uri
        yontem:
          type: string
          enum: [PUT]
        basliklar:
          type: object
          additionalProperties:
            type: string
        sonGecerlilik:
          type: string
          format: date-time
    KullaniciAyar:
      type: object
      properties:
        tema:
          type: string
          enum: [sistem, acik, koyu]
        dil:
          type: string
          enum: [tr, en]
        sureButcesi:
          type: integer
        bildirimKipi:
          type: string
          enum: [hepsi, ozet, onemli]
        okunduBilgisi:
          type: boolean
        varsayilanHalka:
          $ref: '#/components/schemas/Halka'
    Oturum:
      type: object
      properties:
        id:
          type: string
        cihaz:
          type: string
        platform:
          type: string
          enum: [web, ios, android]
        yer:
          type: string
        son:
          type: string
          format: date-time
    KvkkTalep:
      type: object
      properties:
        id:
          type: string
        tur:
          type: string
          enum: [erisim, silme, duzeltme, itiraz]
        kullanici:
          type: string
        tarih:
          type: string
          format: date-time
        sonTarih:
          type: string
          format: date-time
        durum:
          type: string
          enum: [yeni, inceleniyor, tamamlandi, reddedildi]
    ModKayit:
      type: object
      properties:
        id:
          type: string
        hedefTur:
          type: string
          enum: [gonderi, yanit, mesaj, kullanici, an]
        kaynak:
          type: string
          enum: [sikayet, otomatik]
        sinif:
          type: string
        kurallar:
          type: array
          items:
            type: string
        durum:
          type: string
    ModKural:
      type: object
      properties:
        id:
          type: string
        ad:
          type: string
        tur:
          type: string
          enum: [yasakli-kelime, spam-hizi, tekrar-baglanti, yeni-hesap]
        kelimeler:
          type: array
          items:
            type: string
        esik:
          type: integer
        eylem:
          type: string
          enum: [isaretle, incelemeye-al, gizle]
        aktif:
          type: boolean
    Bayraklar:
      type: object
      properties:
        atolye:
          type: boolean
        anHaritasi:
          type: boolean
        sesIzi:
          type: boolean
        kapsul:
          type: boolean
        kayitAcik:
          type: boolean
        mesajIstekleri:
          type: boolean
        enArayuz:
          type: boolean
    Durum:
      type: object
      description: İstemcinin ihtiyaç duyduğu, halka kuralından geçmiş durum
      properties:
        ben:
          type: string
        ayar:
          $ref: '#/components/schemas/KullaniciAyar'
        adalar:
          type: array
          items:
            $ref: '#/components/schemas/Ada'
        gonderiler:
          type: array
          items:
            $ref: '#/components/schemas/Gonderi'
        sohbetler:
          type: array
          items:
            $ref: '#/components/schemas/Sohbet'
        bayraklar:
          $ref: '#/components/schemas/Bayraklar'
    OlayGonderi:
      type: object
      properties:
        olay:
          type: string
          const: gonderi.olusturuldu
        zaman:
          type: string
          format: date-time
        veri:
          $ref: '#/components/schemas/Gonderi'
      example:
        olay: gonderi.olusturuldu
        zaman: '2026-10-25T11:42:00+03:00'
        veri:
          id: g-seramik-s07
          ada: seramik
          halka: herkes
    OlayModerasyon:
      type: object
      properties:
        olay:
          type: string
          const: moderasyon.karar
        zaman:
          type: string
          format: date-time
        kayit:
          type: string
        karar:
          type: string
          enum: [kaldir, uyari, kisitla, askiya-al, geri-yukle, gecersiz]
        gerekce:
          type: string
