# Slack entegrasyonu

> Sorgu taleplerini Slack uygulaması ya da gelen webhook ile onaylayın — düğmeler, canlı güncelleme, /queryproxy, imzalı geri çağrılar, tek kullanımlık token.

- Dokümantasyon: Kılavuzlar
- Güncelleme: 2026-11-04
- Kaynak: https://queryproxy.com/tr/docs/slack-entegrasyonu/
- Dil: tr-TR
- Yazar: Muhammet Şafak

---
Slack entegrasyonuyla yeni sorgu talepleri bir kanala **Approve / Reject**
düğmeleriyle duyurulur; kararlar QueryProxy'ye geri akar — webdekiyle aynı
kurallarla (rol denetimi, kendine onay yok) ve kriptografik doğrulamayla.

Bir takımı bağlamanın iki yolu vardır ve ikisi yan yana bulunabilir:

| | Slack uygulaması | Gelen webhook |
| :-- | :-- | :-- |
| Kuran | Kurulum için bir kez yönetici, sonra takım başına DBA **Add to Slack** ile | Takım başına DBA |
| Mesajlar | Bot tarafından gönderilir ve talebin bütün ömrü boyunca **yerinde güncellenir** | Bir kez gönderilir; karardan sonra güncellenir |
| Ekstralar | Thread özeti, isteğe bağlı doğrudan mesajlar, `/queryproxy` komutu, kimlik önerileri | Yok |
| Secret | Uygulamanın signing secret'ı, ortam değişkeninde | Takım başına signing secret, veritabanında |

Bir takımda ikisi de varsa uygulama kullanılır. Webhook kipi önceki sürümlerden
değişmemiştir ve [aşağıda](#gelen-webhook-kurulum) anlatılır.

## Slack uygulaması

Bir kurulumun bütün takımlarına tek Slack uygulaması hizmet eder. İşletmeci onu bir
kez oluşturur ve kimlik bilgilerini ortama yazar; her takım sonra tek tıkla kendi
çalışma alanına kurar.

### Uygulamayı oluşturun

1. [api.slack.com/apps](https://api.slack.com/apps) adresinde bir Slack uygulaması
   oluşturun.
2. **OAuth & Permissions** altında
   `https://queryproxy-sunucunuz/integrations/slack/callback` yönlendirme URL'sini
   ve şu bot kapsamlarını ekleyin: `chat:write`, `chat:write.public`, `commands`,
   `im:write`, `incoming-webhook`, `users:read` ve `users:read.email`.
3. **Interactivity & Shortcuts** altında etkileşimi,
   `https://queryproxy-sunucunuz/webhooks/slack/interactions` istek URL'siyle açın.
4. **Slash Commands** altında `/queryproxy` komutunu
   `https://queryproxy-sunucunuz/webhooks/slack/commands` istek URL'siyle oluşturun.
5. **Event Subscriptions** altında istek URL'sini
   `https://queryproxy-sunucunuz/webhooks/slack/events` yapın ve
   `app_uninstalled` ile `tokens_revoked` bot olaylarına abone olun.
6. **Basic Information**'dan client id'yi, client secret'ı ve signing secret'ı
   ortama yazın ve konteynerleri yeniden başlatın:

   ```dotenv
   QUERYPROXY_SLACK_CLIENT_ID=...
   QUERYPROXY_SLACK_CLIENT_SECRET=...
   QUERYPROXY_SLACK_SIGNING_SECRET=...
   ```

Bunlar ayarlanana kadar ChatOps sayfası hangi değişkenlerin eksik olduğunu söyler
ve **Add to Slack** düğmesi göstermez.

### Takım için kurun

Takımın bir DBA'i (ya da bir sistem yöneticisi) **ChatOps**'u açıp **Add to Slack**
düğmesine basar. Slack onay ve mesajların gideceği kanalı sorar; tarayıcı sonra
QueryProxy'ye döner. Sayfa çalışma alanını, kanalı ve kuranı gösterir. Düğmeye
yeniden basmak başka bir kanala ya da çalışma alanına kurar.

Kurulum, tarayıcı oturumuna bağlı, 10 dakika geçerli ve tek kullanımlık bir
`state` ile OAuth v2 kullanır; eksik, bayat ya da yabancı `state` taşıyan bir
geri çağrı `403` ile reddedilir ve Slack'e hiç gidilmez. Bot token'ı takım başına
şifreli saklanır. Slack'in kanal için verdiği webhook URL'si saklanmaz. Denetim
günlüğü `slack.installed` kaydeder, token'ı asla.

### Uygulama ne yapar

- **Güncel kalan kartlar.** Talep kartını bot gönderir ve talep ilerledikçe
  yerinde düzenler: onaylandı, reddedildi, iptal edildi, çalışıyor, tamamlandı ya
  da başarısız. Adım başına yeni mesaj yoktur. Hatırlatmayla değiştirilen kart
  düğmeleri kaldırılarak *Moved: use the newer message* olarak düzenlenir.
- **Thread özeti.** Bir çalışma bitince bot, kartın thread'ine durum, satır sayısı,
  süre ve bir bağlantıyla yanıt verir. Yanıtta SQL, sonuç verisi ya da hata metni
  yoktur.
- **Onaylayanlara doğrudan mesaj.** ChatOps sayfasındaki isteğe bağlı bir anahtar,
  Slack üye kimliği olan her takım DBA'sına (talep sahibi hariç) bağlantılı kısa bir
  mesaj yollar. SQL ve düğme taşımaz.

### /queryproxy komutu

`/queryproxy`, Slack'te kişinin kullanabildiği bağlantılarla bir form açar. Gönderim,
Slack'ten geldiği işaretli olağan bir talep açar; aynı korumalardan geçer ve aynı
onayı bekler. Form açılmadan önce ve gönderilirken QueryProxy, Slack
kullanıcısının aktif bir QueryProxy kullanıcısıyla eşleştiğini, bağlantının
takımının uygulamayı o çalışma alanına kurduğunu ve kullanıcının bağlantıyı
kullanabildiğini denetler; aksi hâlde yalnızca o kişi bir hata görür. Aynı formu iki
kez göndermek iki talep açmaz. Birkaç QueryProxy takımı tek Slack çalışma alanını
paylaşıyorsa form hepsinin kullanılabilir bağlantılarını, en çok 100, listeler.

### Slack kullanıcılarını QueryProxy kullanıcılarına eşleme

Slack tıklamaları, kullanıcıdaki **Slack üye kimliği** üzerinden QueryProxy
kullanıcısı olarak işlem yapar ([webhook kurulumunun](#gelen-webhook-kurulum) son
adımına bakın). Kurulumdan sonra ve haftada bir QueryProxy, kimliği olmayan her
kullanıcıyı e-posta adresiyle arar ve bir eşleşme önerir. Öneriler Users
sayfasında **Slack matching suggestions** altında görünür. Bir sistem yöneticisi
öneriyi **onaylar**: üye kimliği bağlanır ve `chat_identity.linked` olarak, kaynağı
`slack_suggestion` ile denetlenir; ya da **reddeder**: öneri silinir (haftalık
tarama aynısını yeniden önerebilir). Hiçbir şey otomatik bağlanmaz.

### Uygulamayı kaldırma

ChatOps sayfasındaki **Remove app** (DBA ya da yönetici) saklanan bot token'ını ve
çalışma alanının önerilerini siler; `slack.uninstalled` olayını `removed_by_user`
nedeniyle ve işlemi yapan kişiyle yazar. Slack'e token'ı iptal etmesini **söylemez**;
bu yüzden uygulamayı Slack'te çalışma alanından da kaldırın. Takımın yapılandırılmış
bir webhook'u varsa çalışmaya devam eder.

Slack `app_uninstalled` ya da `tokens_revoked` gönderdiğinde veya bot token'ını
reddettiğinde de QueryProxy kurulumu kendiliğinden düşürür (`slack.uninstalled`,
neden `token_rejected`).

### Ayarlar

| Değişken | Varsayılan | Anlamı |
| :-- | :-- | :-- |
| `QUERYPROXY_SLACK_CLIENT_ID` | yok | Slack uygulamasının client id'si |
| `QUERYPROXY_SLACK_CLIENT_SECRET` | yok | Slack uygulamasının client secret'ı |
| `QUERYPROXY_SLACK_SIGNING_SECRET` | yok | Slack uygulamasının signing secret'ı; Slack'in gönderdiği her isteği doğrular |
| `QUERYPROXY_SLACK_RATE_LIMIT` | `300` | Slack çalışma alanı başına dakikadaki istek (etkileşimler, komutlar, olaylar); imza doğrulandıktan sonra sayılır |

İmza denetlenmeden önce her adres Slack uç noktalarına dakikada 120 istek
gönderebilir; aşılınca yanıt `429` olur. İki sınır ayrıdır; böylece sahte trafik bir
çalışma alanının bütçesini tüketemez. Teams ucunun kendi sınırı vardır.

Yükseltme, bir takımın webhook URL'sini ve signing secret'ını isteğe bağlı yapan
iki migration çalıştırır; böylece takım yalnızca uygulamayı kullanabilir. Uygulaması
olup kendi signing secret'ı olmayan bir takım, bir sistem yöneticisi secret girene
kadar webhook URL'si kaydedemez; bu ilk girişte yürürlükteki secret sorulmaz.

## Gelen webhook: kurulum

1. [api.slack.com/apps](https://api.slack.com/apps) adresinden çalışma alanınız
   için bir **Slack uygulaması** oluşturun.
2. **Incoming Webhooks**'u etkinleştirin ve onay kanalınız (ör. `#db-approvals`)
   için bir webhook ekleyin.
3. **Interactivity**'yi etkinleştirin ve istek URL'sini şuna ayarlayın:

   ```
   https://queryproxy-sunucunuz/webhooks/slack/interactions
   ```

4. QueryProxy'de **ChatOps**'u açın; **webhook URL'sini** ve uygulamanın
   **signing secret**'ını yapıştırın. İkisi de şifreli saklanır. İlk kurulum
   secret'sız kaydedilemediği için bu adımı **bir sistem yöneticisi** yapar;
   sonrasında webhook URL'sini ve açık/kapalı bayrağını takımın DBA'leri
   güncellemeye devam eder. Webhook URL'si `https://` olmalı ve host'u izin
   listesinde bulunmalıdır (varsayılan olarak `hooks.slack.com`,
   `*.webhook.office.com`, `*.logic.azure.com` ve `*.powerplatform.com`; liste sohbet sağlayıcıları
   arasında ortaktır; `QUERYPROXY_CHAT_WEBHOOK_ALLOWED_HOSTS` ile genişletin).
5. Sistem yöneticisi olarak **Teams & Users → Manage users** ekranını açın ve her onaylayıcının **Slack üye kimliğini** girin
   (ör. `U0123ABC` — Slack profilinde *Copy member ID* ile görünür). Bu eşleme,
   Slack tıklamalarını QueryProxy kullanıcılarına bağlar.

> **Kırıcı değişiklik — signing secret'ı yalnızca sistem yöneticisi
> belirleyebilir.** Bir DBA artık secret'ı giremez ya da döndüremez; webhook
> URL'si ve enabled bayrağı DBA'lerde kalır. Mevcut secret'ı değiştirmek için
> yönetici, **yürürlükteki secret'ı da girmek zorundadır** — secret bilgisi,
> rotasyonu uçtan devralmadan ayıran tek şeydir. Gerekçe: HMAC yalnızca
> "çağıranın secret'ı bildiğini" kanıtlar, "şu kişi onayladı" demez; secret'ı
> kendi seçebilen bir DBA, kendi talebini bir meslektaşı adına onaylayıp denetim
> izine o kişinin adını yazdırabiliyordu. ChatOps'u zaten kurmuş kurulumlarda
> secret'ın yükseltmeden sonra **bir kez döndürülmesi** önerilir.
>
> Aynı gerekçeyle entegrasyonu **silmek de yalnızca sistem yöneticisinin
> işidir**: yeniden kurmak için gereken secret'ı ancak bir yönetici girebildiği
> için, silme düğmesi bir DBA'in elinde takımın ChatOps'tan tek yönlü çıkışı
> olurdu. DBA'in gündelik, geri alınabilir kontrolü **Enabled** bayrağını
> kapatıp kaydetmektir.

## Nasıl görünür

Bir talep gönderildiğinde QueryProxy; talep sahibi, bağlantı, SQL önizlemesi (400
karakterde kesilir; metin ve sayı literalleri varsayılan olarak `?` görünür,
`QUERYPROXY_CHAT_INCLUDE_SQL` önizlemeyi `full` ya da `none` yapar) ve
üç aksiyonla bir mesaj yayınlar: **Approve**, **Reject** ve **Open in
QueryProxy**. Karardan sonra mesaj yerinde güncellenir — düğmeler kaybolur ve
sonuç görünür; bayat bir mesajdan ikinci kez karar verilemez.

Slack'ten yapılan redler "Rejected via Slack by &lt;isim&gt;" genel gerekçesini
kaydeder. Yazılı gerekçe için web arayüzünden reddedin.

Yönetici **override**'ı olacak bir **Approve** basışı (onaylayan takımın DBA'si
değil ya da kendi talebine karar veriyor) uygulanmaz. Her override yazılı bir
gerekçe ister; bu yüzden Slack, gerekçeyi gireceğiniz web formuna bir bağlantıyla
yanıt verir ve aksiyon token'ı harcanmaz. `QUERYPROXY_PENDING_REMIND_AFTER` saat
(varsayılan `4`) boyunca `pending` kalan bir talep, yeni bir mesajla bir
hatırlatma alır; süresi dolmuş eski bir mesajın düğmesi ise daha yeni mesaja
işaret eden bir yanıt verir.

> **Kırıcı değişiklik — bu sürümden önce gönderilmiş mesajlardaki düğmeler
> çalışmaz.** Her **Approve** / **Reject** düğmesi artık, yalnızca o talebe bağlı,
> **24 saat** ömürlü ve **tek kullanımlık** bir aksiyon token'ı taşır. Eski
> mesajlarda böyle bir token yoktur; tıklama doğrulanamadı mesajıyla geri
> çevrilir. O talepleri web arayüzünden karara bağlayın — yeni gönderilen
> talepler token'lı düğmelerle gelir.

## Güvenlik

Slack'ten gelen her geri çağrı, herhangi bir şey olmadan önce doğrulanır:

- **İmza** — `X-Slack-Signature` başlığı
  `v0=HMAC_SHA256("v0:{timestamp}:{raw_body}", signing_secret)` ile sabit
  zamanlı karşılaştırmayla eşleşmelidir.
- **Tekrar koruması** — `X-Slack-Request-Timestamp`'e göre **±5 dakikadan**
  eski istekler reddedilir.
- **Aksiyon token'ı** — düğmenin taşıdığı token canlı, kullanılmamış ve tam
  olarak o talebe bağlı olmalıdır. Böylece geri çağrı, QueryProxy'nin gerçekten
  yayınladığı bir mesajı yanıtlar ve her mesaj **yalnızca bir kez** karar verir;
  secret'ı elinde tutmak tek başına yoktan bir karar uydurmaya ya da yakalanmış
  bir tıklamayı yeniden oynatmaya yetmez. Token karar gerçekten kaydedildikten
  sonra yakılır — yetkilendirmeye takılan bir tıklama kanalın hakkını harcamaz.
- **Kimlik** — tıklayan Slack kullanıcısı, bir yöneticinin oluşturduğu eşleme
  üzerinden bir QueryProxy kullanıcısına çözülmeli; bu kullanıcı ya
  **entegrasyonun takımına üye** olup o takımda DBA rolünü taşımalı ya da
  admin olmalıdır. Eşlenmemiş veya yetkisiz kullanıcılar özel bir hata mesajı
  görür; hiçbir şey değişmez.
- **Kurallar** — kendine onay Slack'te de aynen engellidir. Webde olduğu gibi
  admin'ler DBA rolü kuralını ve kendine onay engelini aşabilir; kuralı aşan
  bir admin onayı denetim günlüğünde işaretlenir.

Sahte veya bayat bir geri çağrı `401` döner ve hiçbir durumu değiştirmez.
Geri çağrılar Slack uygulamasının signing secret'ıyla
(`QUERYPROXY_SLACK_SIGNING_SECRET`) ya da gelen webhook kipinde takımın kendi
signing secret'ıyla doğrulanır. `/queryproxy` komutu, açtığı form ve Events ucu
**yalnızca** uygulamanın secret'ını kabul eder: takıma özgü secret orada
reddedilir. Slack uçları, [Ayarlar](#ayarlar) altında anlatıldığı gibi hız
sınırlıdır.
