diff --git a/docs/quality/qa-api-key-lifecycle.json b/docs/quality/qa-api-key-lifecycle.json new file mode 100644 index 0000000..935c4c7 --- /dev/null +++ b/docs/quality/qa-api-key-lifecycle.json @@ -0,0 +1,18 @@ +{ + "source": "localhost:5176 isolated browser QA", + "checks": { + "errorVisible": true, + "createDisabledOnError": true, + "retryRecovered": true, + "created": true, + "revokedEmpty": true, + "revokedSecretRemoved": true, + "normalBlocked": true, + "normalNoPreviousKey": true + }, + "error": "- banner:\n - text: İhale\n - generic: ist\n - textbox \"İhale, kurum veya İKN no ile arayın...\"\n - button \"ARA\":\n - generic: ARA\n - button \"ÜRÜN ARA\":\n - generic: ÜRÜN ARA\n - button \"Detaylı İhale Arama\":\n - button \"AI Şartname Analizi\":\n - generic: AI Şartname Analizi\n - button \"Web Siteni Tara (AI)\":\n - generic: Web Siteni Tara (AI)\n - generic: 7 gün\n - button \"Bildirimler\":\n - button \"Hesap menüsü\":\n - generic: A\n - generic: API\n- generic: \"5\"\n- generic: Canlı İhale Havuzu\n- generic: \"5\"\n- generic: Yüklü İhale\n- generic: \"0\"\n- generic: Bugün Eklenen\n- generic: \"5\"\n- generic: Kalem\n- generic: \"0\"\n- generic: Sonuç Arşivi\n- generic: \"0\"\n- generic: Takibimdeki\n- button \"Önceki sekmeler\":\n- button \"Sonraki sekmeler\":\n- button \"Ana İhale Listesi\":\n - generic: Ana İhale Listesi\n- button \"Günlük Bülten\":\n - generic: Günlük Bülten\n- button \"Sonuç Sorgula\":\n - generic: Sonuç Sorgula\n- button \"İhale Takvimi\":\n - generic: İhale Takvimi\n- button \"Sözleşme Sorgula\":\n - generic: Sözleşme Sorgula\n- button \"KDV Hesapla\":\n - generic: KDV Hesapla\n- button \"Sınır Değer\":\n - generic: Sınır Değer\n- button \"Fiyat Analizi\":\n - generic: Fiyat Analizi\n- button \"Kanban Pano Sürükle Takip\":\n - generic: Kanban Pano\n - generic: Sürükle Takip\n- button \"Rakip Radar Canlı Uyar\":\n - generic: Rakip Radar\n - generic: Canlı Uyar\n- button \"Doküman Deposu\":\n - generic: Doküman Deposu\n- button \"Analitik Dashboard\":\n - generic: Analitik Dashboard\n- button \"Kırmızı Bayrak Şeffaflık\":\n - generic: Kırmızı Bayrak\n - generic: Şeffaflık\n- button \"KİK Kurul Kararları\":\n - generic: KİK Kurul Kararları\n- button \"AB İhaleleri (TED)\":\n - generic: AB İhaleleri (TED)\n- button \"Planlar\":\n - generic: Planlar\n- button \"API & Webhooks\" [active]:\n - generic: API & Webhooks\n- button \"AI Model Ayarları Admin\":\n - generic: AI Model Ayarları\n - generic: Admin\n- button \"Mobil PWA\":\n - generic: Mobil PWA\n- main:\n - button \"Yeniden dene\"\n - heading \"API Erişimi\" [level=2]\n - paragraph: İhale verisini kendi sistemlerinize (ERP, CRM) taşımak için sunucu doğrulamalı API anahtarları.\n - heading \"API Anahtarları\" [level=3]:\n - text: API Anahtarları\n - paragraph: Anahtar listesi alınamadı. Yeniden deneyebilirsiniz.\n - textbox \"Anahtar adı\" [disabled]:\n - /placeholder: Anahtar adı (ör. ERP Entegrasyonu)\n - button \"Oluştur\" [disabled]:\n - text: Oluştur\n - alert:\n - paragraph: \"QA: Anahtar deposuna erişilemiyor.\"\n - heading \"MCP Sunucusu — yapay zekâ araçlarınıza İhaleist'i bağlayın\" [level=3]:\n - text: MCP Sunucusu — yapay zekâ araçlarınıza İhaleist'i bağlayın\n - paragraph:\n - text: \"Claude Code, Cursor, Claude Desktop gibi MCP destekli araçlar İhaleist'i doğrudan sorgular:\"\n - code: search_tenders\n - text: \",\"\n - code: get_tender\n - text: \",\"\n - code: search_results\n - text: \",\"\n - code: search_items\n - text: \",\"\n - code: upcoming_deadlines\n - text: . Yukarıdaki API anahtarınızı kullanır.\n - paragraph:\n - text: Claude Code\n - generic: — terminalde tek komut\n - button \"Kopyala\":\n - text: Kopyala\n - generic: \"claude mcp add --transport http ihaleist http://127.0.0.1:5176/mcp --header \\\"Authorization: Bearer ih_live_ANAHTARINIZ\\\"\"\n - paragraph:\n - text: Cursor / Windsurf\n - generic: — .cursor/mcp.json\n - button \"Kopyala\":\n - text: Kopyala\n - generic: \"{ \\\"mcpServers\\\": { \\\"ihaleist\\\": { \\\"url\\\": \\\"http://127.0.0.1:5176/mcp\\\", \\\"headers\\\": { \\\"Authorization\\\": \\\"Bearer ih_live_ANAHTARINIZ\\\" } } } }\"\n - paragraph:\n - text: Claude Desktop\n - generic: — claude_desktop_config.json (mcp-remote)\n - button \"Kopyala\":\n - text: Kopyala\n - generic: \"{ \\\"mcpServers\\\": { \\\"ihaleist\\\": { \\\"command\\\": \\\"npx\\\", \\\"args\\\": [ \\\"-y\\\", \\\"mcp-remote\\\", \\\"http://127.0.0.1:5176/mcp\\\", \\\"--header\\\", \\\"Authorization: Bearer ih_live_ANAHTARINIZ\\\" ] } } }\"\n - paragraph:\n - text: RSS beslemesi\n - generic: — Feedly, Outlook, Slack RSS, n8n… (il, sektor, q filtreleri)\n - button \"Kopyala\":\n - text: Kopyala\n - generic: http://127.0.0.1:5176/api/feeds/tenders.rss?key=ih_live_ANAHTARINIZ&il=İstanbul&q=eldiven\n - paragraph:\n - text: \"Sonuç ilanları beslemesi anahtarsız:\"\n - code: http://127.0.0.1:5176/api/feeds/sonuc.rss\n - text: (firma, idare, il filtreleri). Anahtarı\n - code: ih_live_ANAHTARINIZ\n - text: yerine yazın.\n - paragraph:\n - strong: \"Kullanım:\"\n - text: İsteklerinize\n - code: \"Authorization: Bearer ih_live_…\"\n - text: başlığını ekleyin. Anahtar sunucuda doğrulanır, her kullanımda son kullanım zamanı güncellenir, iptal ettiğinizde anında geçersiz olur.\n- button \"Kullanım kılavuzu (? tuşu)\":", + "recovered": "- banner:\n - text: İhale\n - generic: ist\n - textbox \"İhale, kurum veya İKN no ile arayın...\"\n - button \"ARA\":\n - generic: ARA\n - button \"ÜRÜN ARA\":\n - generic: ÜRÜN ARA\n - button \"Detaylı İhale Arama\":\n - button \"AI Şartname Analizi\":\n - generic: AI Şartname Analizi\n - button \"Web Siteni Tara (AI)\":\n - generic: Web Siteni Tara (AI)\n - generic: 7 gün\n - button \"Bildirimler\":\n - button \"Hesap menüsü\":\n - generic: A\n - generic: API\n- generic: \"5\"\n- generic: Canlı İhale Havuzu\n- generic: \"5\"\n- generic: Yüklü İhale\n- generic: \"0\"\n- generic: Bugün Eklenen\n- generic: \"5\"\n- generic: Kalem\n- generic: \"0\"\n- generic: Sonuç Arşivi\n- generic: \"0\"\n- generic: Takibimdeki\n- button \"Önceki sekmeler\":\n- button \"Ana İhale Listesi\":\n - generic: Ana İhale Listesi\n- button \"Günlük Bülten\":\n - generic: Günlük Bülten\n- button \"Sonuç Sorgula\":\n - generic: Sonuç Sorgula\n- button \"İhale Takvimi\":\n - generic: İhale Takvimi\n- button \"Sözleşme Sorgula\":\n - generic: Sözleşme Sorgula\n- button \"KDV Hesapla\":\n - generic: KDV Hesapla\n- button \"Sınır Değer\":\n - generic: Sınır Değer\n- button \"Fiyat Analizi\":\n - generic: Fiyat Analizi\n- button \"Kanban Pano Sürükle Takip\":\n - generic: Kanban Pano\n - generic: Sürükle Takip\n- button \"Rakip Radar Canlı Uyar\":\n - generic: Rakip Radar\n - generic: Canlı Uyar\n- button \"Doküman Deposu\":\n - generic: Doküman Deposu\n- button \"Analitik Dashboard\":\n - generic: Analitik Dashboard\n- button \"Kırmızı Bayrak Şeffaflık\":\n - generic: Kırmızı Bayrak\n - generic: Şeffaflık\n- button \"KİK Kurul Kararları\":\n - generic: KİK Kurul Kararları\n- button \"AB İhaleleri (TED)\":\n - generic: AB İhaleleri (TED)\n- button \"Planlar\":\n - generic: Planlar\n- button \"API & Webhooks\":\n - generic: API & Webhooks\n- button \"AI Model Ayarları Admin\":\n - generic: AI Model Ayarları\n - generic: Admin\n- button \"Mobil PWA\":\n - generic: Mobil PWA\n- main:\n - heading \"API Erişimi\" [level=2]\n - paragraph: İhale verisini kendi sistemlerinize (ERP, CRM) taşımak için sunucu doğrulamalı API anahtarları.\n - heading \"API Anahtarları\" [level=3]:\n - text: API Anahtarları\n - generic: 0 / 10 anahtar\n - paragraph: Henüz anahtar yok.\n - textbox \"Anahtar adı\":\n - /placeholder: Anahtar adı (ör. ERP Entegrasyonu)\n - button \"Oluştur\":\n - text: Oluştur\n - heading \"MCP Sunucusu — yapay zekâ araçlarınıza İhaleist'i bağlayın\" [level=3]:\n - text: MCP Sunucusu — yapay zekâ araçlarınıza İhaleist'i bağlayın\n - paragraph:\n - text: \"Claude Code, Cursor, Claude Desktop gibi MCP destekli araçlar İhaleist'i doğrudan sorgular:\"\n - code: search_tenders\n - text: \",\"\n - code: get_tender\n - text: \",\"\n - code: search_results\n - text: \",\"\n - code: search_items\n - text: \",\"\n - code: upcoming_deadlines\n - text: . Yukarıdaki API anahtarınızı kullanır.\n - paragraph:\n - text: Claude Code\n - generic: — terminalde tek komut\n - button \"Kopyala\":\n - text: Kopyala\n - generic: \"claude mcp add --transport http ihaleist http://127.0.0.1:5176/mcp --header \\\"Authorization: Bearer ih_live_ANAHTARINIZ\\\"\"\n - paragraph:\n - text: Cursor / Windsurf\n - generic: — .cursor/mcp.json\n - button \"Kopyala\":\n - text: Kopyala\n - generic: \"{ \\\"mcpServers\\\": { \\\"ihaleist\\\": { \\\"url\\\": \\\"http://127.0.0.1:5176/mcp\\\", \\\"headers\\\": { \\\"Authorization\\\": \\\"Bearer ih_live_ANAHTARINIZ\\\" } } } }\"\n - paragraph:\n - text: Claude Desktop\n - generic: — claude_desktop_config.json (mcp-remote)\n - button \"Kopyala\":\n - text: Kopyala\n - generic: \"{ \\\"mcpServers\\\": { \\\"ihaleist\\\": { \\\"command\\\": \\\"npx\\\", \\\"args\\\": [ \\\"-y\\\", \\\"mcp-remote\\\", \\\"http://127.0.0.1:5176/mcp\\\", \\\"--header\\\", \\\"Authorization: Bearer ih_live_ANAHTARINIZ\\\" ] } } }\"\n - paragraph:\n - text: RSS beslemesi\n - generic: — Feedly, Outlook, Slack RSS, n8n… (il, sektor, q filtreleri)\n - button \"Kopyala\":\n - text: Kopyala\n - generic: http://127.0.0.1:5176/api/feeds/tenders.rss?key=ih_live_ANAHTARINIZ&il=İstanbul&q=eldiven\n - paragraph:\n - text: \"Sonuç ilanları beslemesi anahtarsız:\"\n - code: http://127.0.0.1:5176/api/feeds/sonuc.rss\n - text: (firma, idare, il filtreleri). Anahtarı\n - code: ih_live_ANAHTARINIZ\n - text: yerine yazın.\n - paragraph:\n - strong: \"Kullanım:\"\n - text: İsteklerinize\n - code: \"Authorization: Bearer ih_live_…\"\n - text: başlığını ekleyin. Anahtar sunucuda doğrulanır, her kullanımda son kullanım zamanı güncellenir, iptal ettiğinizde anında geçersiz olur.\n- button \"Kullanım kılavuzu (? tuşu)\":", + "createdRedacted": "- banner:\n - text: İhale\n - generic: ist\n - textbox \"İhale, kurum veya İKN no ile arayın...\"\n - button \"ARA\":\n - generic: ARA\n - button \"ÜRÜN ARA\":\n - generic: ÜRÜN ARA\n - button \"Detaylı İhale Arama\":\n - button \"AI Şartname Analizi\":\n - generic: AI Şartname Analizi\n - button \"Web Siteni Tara (AI)\":\n - generic: Web Siteni Tara (AI)\n - generic: 7 gün\n - button \"Bildirimler\":\n - button \"Hesap menüsü\":\n - generic: A\n - generic: API\n- generic: \"5\"\n- generic: Canlı İhale Havuzu\n- generic: \"5\"\n- generic: Yüklü İhale\n- generic: \"0\"\n- generic: Bugün Eklenen\n- generic: \"5\"\n- generic: Kalem\n- generic: \"0\"\n- generic: Sonuç Arşivi\n- generic: \"0\"\n- generic: Takibimdeki\n- button \"Önceki sekmeler\":\n- button \"Ana İhale Listesi\":\n - generic: Ana İhale Listesi\n- button \"Günlük Bülten\":\n - generic: Günlük Bülten\n- button \"Sonuç Sorgula\":\n - generic: Sonuç Sorgula\n- button \"İhale Takvimi\":\n - generic: İhale Takvimi\n- button \"Sözleşme Sorgula\":\n - generic: Sözleşme Sorgula\n- button \"KDV Hesapla\":\n - generic: KDV Hesapla\n- button \"Sınır Değer\":\n - generic: Sınır Değer\n- button \"Fiyat Analizi\":\n - generic: Fiyat Analizi\n- button \"Kanban Pano Sürükle Takip\":\n - generic: Kanban Pano\n - generic: Sürükle Takip\n- button \"Rakip Radar Canlı Uyar\":\n - generic: Rakip Radar\n - generic: Canlı Uyar\n- button \"Doküman Deposu\":\n - generic: Doküman Deposu\n- button \"Analitik Dashboard\":\n - generic: Analitik Dashboard\n- button \"Kırmızı Bayrak Şeffaflık\":\n - generic: Kırmızı Bayrak\n - generic: Şeffaflık\n- button \"KİK Kurul Kararları\":\n - generic: KİK Kurul Kararları\n- button \"AB İhaleleri (TED)\":\n - generic: AB İhaleleri (TED)\n- button \"Planlar\":\n - generic: Planlar\n- button \"API & Webhooks\":\n - generic: API & Webhooks\n- button \"AI Model Ayarları Admin\":\n - generic: AI Model Ayarları\n - generic: Admin\n- button \"Mobil PWA\":\n - generic: Mobil PWA\n- main:\n - heading \"API Erişimi\" [level=2]\n - paragraph: İhale verisini kendi sistemlerinize (ERP, CRM) taşımak için sunucu doğrulamalı API anahtarları.\n - paragraph:\n - text: Anahtarınız oluşturuldu — bu değer bir daha gösterilmeyecek\n - code: [ANAHTAR GİZLENDİ]\n - button \"Kopyala\":\n - text: Kopyala\n - paragraph:\n - text: Sunucuda yalnızca anahtarın\n - strong: hash\n - text: \"'i saklanır; ham değeri biz de göremeyiz. Güvenli bir yere kaydedin.\"\n - heading \"API Anahtarları\" [level=3]:\n - text: API Anahtarları\n - generic: 1 / 10 anahtar\n - paragraph: QA geçici ERP\n - paragraph: [ANAHTAR GİZLENDİ]••••••••••••••••\n - paragraph: \"Oluşturma: 06.09.2026 · hiç kullanılmadı\"\n - button \"Anahtarı iptal et\":\n - textbox \"Anahtar adı\":\n - /placeholder: Anahtar adı (ör. ERP Entegrasyonu)\n - button \"Oluştur\":\n - text: Oluştur\n - heading \"MCP Sunucusu — yapay zekâ araçlarınıza İhaleist'i bağlayın\" [level=3]:\n - text: MCP Sunucusu — yapay zekâ araçlarınıza İhaleist'i bağlayın\n - paragraph:\n - text: \"Claude Code, Cursor, Claude Desktop gibi MCP destekli araçlar İhaleist'i doğrudan sorgular:\"\n - code: search_tenders\n - text: \",\"\n - code: get_tender\n - text: \",\"\n - code: search_results\n - text: \",\"\n - code: search_items\n - text: \",\"\n - code: upcoming_deadlines\n - text: . Yukarıdaki API anahtarınızı kullanır.\n - paragraph:\n - text: Claude Code\n - generic: — terminalde tek komut\n - button \"Kopyala\":\n - text: Kopyala\n - generic: \"claude mcp add --transport http ihaleist http://127.0.0.1:5176/mcp --header \\\"Authorization: Bearer [ANAHTAR GİZLENDİ]\\\"\"\n - paragraph:\n - text: Cursor / Windsurf\n - generic: — .cursor/mcp.json\n - button \"Kopyala\":\n - text: Kopyala\n - generic: \"{ \\\"mcpServers\\\": { \\\"ihaleist\\\": { \\\"url\\\": \\\"http://127.0.0.1:5176/mcp\\\", \\\"headers\\\": { \\\"Authorization\\\": \\\"Bearer [ANAHTAR GİZLENDİ]\\\" } } } }\"\n - paragraph:\n - text: Claude Desktop\n - generic: — claude_desktop_config.json (mcp-remote)\n - button \"Kopyala\":\n - text: Kopyala\n - generic: \"{ \\\"mcpServers\\\": { \\\"ihaleist\\\": { \\\"command\\\": \\\"npx\\\", \\\"args\\\": [ \\\"-y\\\", \\\"mcp-remote\\\", \\\"http://127.0.0.1:5176/mcp\\\", \\\"--header\\\", \\\"Authorization: Bearer [ANAHTAR GİZLENDİ]\\\" ] } } }\"\n - paragraph:\n - text: RSS beslemesi\n - generic: — Feedly, Outlook, Slack RSS, n8n… (il, sektor, q filtreleri)\n - button \"Kopyala\":\n - text: Kopyala\n - generic: http://127.0.0.1:5176/api/feeds/tenders.rss?key=[ANAHTAR GİZLENDİ]&il=İstanbul&q=eldiven\n - paragraph:\n - text: \"Sonuç ilanları beslemesi anahtarsız:\"\n - code: http://127.0.0.1:5176/api/feeds/sonuc.rss\n - text: (firma, idare, il filtreleri). Anahtarı\n - code: [ANAHTAR GİZLENDİ]\n - text: yerine yazın.\n - paragraph:\n - strong: \"Kullanım:\"\n - text: İsteklerinize\n - code: \"Authorization: Bearer ih_live_…\"\n - text: başlığını ekleyin. Anahtar sunucuda doğrulanır, her kullanımda son kullanım zamanı güncellenir, iptal ettiğinizde anında geçersiz olur.\n- button \"Kullanım kılavuzu (? tuşu)\":", + "revoked": "- banner:\n - text: İhale\n - generic: ist\n - textbox \"İhale, kurum veya İKN no ile arayın...\"\n - button \"ARA\":\n - generic: ARA\n - button \"ÜRÜN ARA\":\n - generic: ÜRÜN ARA\n - button \"Detaylı İhale Arama\":\n - button \"AI Şartname Analizi\":\n - generic: AI Şartname Analizi\n - button \"Web Siteni Tara (AI)\":\n - generic: Web Siteni Tara (AI)\n - generic: 7 gün\n - button \"Bildirimler\":\n - button \"Hesap menüsü\":\n - generic: A\n - generic: API\n- generic: \"5\"\n- generic: Canlı İhale Havuzu\n- generic: \"5\"\n- generic: Yüklü İhale\n- generic: \"0\"\n- generic: Bugün Eklenen\n- generic: \"5\"\n- generic: Kalem\n- generic: \"0\"\n- generic: Sonuç Arşivi\n- generic: \"0\"\n- generic: Takibimdeki\n- button \"Önceki sekmeler\":\n- button \"Ana İhale Listesi\":\n - generic: Ana İhale Listesi\n- button \"Günlük Bülten\":\n - generic: Günlük Bülten\n- button \"Sonuç Sorgula\":\n - generic: Sonuç Sorgula\n- button \"İhale Takvimi\":\n - generic: İhale Takvimi\n- button \"Sözleşme Sorgula\":\n - generic: Sözleşme Sorgula\n- button \"KDV Hesapla\":\n - generic: KDV Hesapla\n- button \"Sınır Değer\":\n - generic: Sınır Değer\n- button \"Fiyat Analizi\":\n - generic: Fiyat Analizi\n- button \"Kanban Pano Sürükle Takip\":\n - generic: Kanban Pano\n - generic: Sürükle Takip\n- button \"Rakip Radar Canlı Uyar\":\n - generic: Rakip Radar\n - generic: Canlı Uyar\n- button \"Doküman Deposu\":\n - generic: Doküman Deposu\n- button \"Analitik Dashboard\":\n - generic: Analitik Dashboard\n- button \"Kırmızı Bayrak Şeffaflık\":\n - generic: Kırmızı Bayrak\n - generic: Şeffaflık\n- button \"KİK Kurul Kararları\":\n - generic: KİK Kurul Kararları\n- button \"AB İhaleleri (TED)\":\n - generic: AB İhaleleri (TED)\n- button \"Planlar\":\n - generic: Planlar\n- button \"API & Webhooks\":\n - generic: API & Webhooks\n- button \"AI Model Ayarları Admin\":\n - generic: AI Model Ayarları\n - generic: Admin\n- button \"Mobil PWA\":\n - generic: Mobil PWA\n- main:\n - heading \"API Erişimi\" [level=2]\n - paragraph: İhale verisini kendi sistemlerinize (ERP, CRM) taşımak için sunucu doğrulamalı API anahtarları.\n - heading \"API Anahtarları\" [level=3]:\n - text: API Anahtarları\n - generic: 0 / 10 anahtar\n - paragraph: Henüz anahtar yok.\n - textbox \"Anahtar adı\":\n - /placeholder: Anahtar adı (ör. ERP Entegrasyonu)\n - button \"Oluştur\":\n - text: Oluştur\n - heading \"MCP Sunucusu — yapay zekâ araçlarınıza İhaleist'i bağlayın\" [level=3]:\n - text: MCP Sunucusu — yapay zekâ araçlarınıza İhaleist'i bağlayın\n - paragraph:\n - text: \"Claude Code, Cursor, Claude Desktop gibi MCP destekli araçlar İhaleist'i doğrudan sorgular:\"\n - code: search_tenders\n - text: \",\"\n - code: get_tender\n - text: \",\"\n - code: search_results\n - text: \",\"\n - code: search_items\n - text: \",\"\n - code: upcoming_deadlines\n - text: . Yukarıdaki API anahtarınızı kullanır.\n - paragraph:\n - text: Claude Code\n - generic: — terminalde tek komut\n - button \"Kopyala\":\n - text: Kopyala\n - generic: \"claude mcp add --transport http ihaleist http://127.0.0.1:5176/mcp --header \\\"Authorization: Bearer ih_live_ANAHTARINIZ\\\"\"\n - paragraph:\n - text: Cursor / Windsurf\n - generic: — .cursor/mcp.json\n - button \"Kopyala\":\n - text: Kopyala\n - generic: \"{ \\\"mcpServers\\\": { \\\"ihaleist\\\": { \\\"url\\\": \\\"http://127.0.0.1:5176/mcp\\\", \\\"headers\\\": { \\\"Authorization\\\": \\\"Bearer ih_live_ANAHTARINIZ\\\" } } } }\"\n - paragraph:\n - text: Claude Desktop\n - generic: — claude_desktop_config.json (mcp-remote)\n - button \"Kopyala\":\n - text: Kopyala\n - generic: \"{ \\\"mcpServers\\\": { \\\"ihaleist\\\": { \\\"command\\\": \\\"npx\\\", \\\"args\\\": [ \\\"-y\\\", \\\"mcp-remote\\\", \\\"http://127.0.0.1:5176/mcp\\\", \\\"--header\\\", \\\"Authorization: Bearer ih_live_ANAHTARINIZ\\\" ] } } }\"\n - paragraph:\n - text: RSS beslemesi\n - generic: — Feedly, Outlook, Slack RSS, n8n… (il, sektor, q filtreleri)\n - button \"Kopyala\":\n - text: Kopyala\n - generic: http://127.0.0.1:5176/api/feeds/tenders.rss?key=ih_live_ANAHTARINIZ&il=İstanbul&q=eldiven\n - paragraph:\n - text: \"Sonuç ilanları beslemesi anahtarsız:\"\n - code: http://127.0.0.1:5176/api/feeds/sonuc.rss\n - text: (firma, idare, il filtreleri). Anahtarı\n - code: ih_live_ANAHTARINIZ\n - text: yerine yazın.\n - paragraph:\n - strong: \"Kullanım:\"\n - text: İsteklerinize\n - code: \"Authorization: Bearer ih_live_…\"\n - text: başlığını ekleyin. Anahtar sunucuda doğrulanır, her kullanımda son kullanım zamanı güncellenir, iptal ettiğinizde anında geçersiz olur.\n- button \"Kullanım kılavuzu (? tuşu)\":", + "normal": "- banner:\n - text: İhale\n - generic: ist\n - textbox \"İhale, kurum veya İKN no ile arayın...\"\n - button \"ARA\":\n - generic: ARA\n - button \"ÜRÜN ARA\":\n - generic: ÜRÜN ARA\n - button \"Detaylı İhale Arama\":\n - button \"AI Şartname Analizi\":\n - generic: AI Şartname Analizi\n - button \"Web Siteni Tara (AI)\":\n - generic: Web Siteni Tara (AI)\n - generic: 7 gün\n - button \"Bildirimler\":\n - button \"Hesap menüsü\":\n - generic: L\n - generic: Laboratuvar\n- generic: \"5\"\n- generic: Canlı İhale Havuzu\n- generic: \"5\"\n- generic: Yüklü İhale\n- generic: \"0\"\n- generic: Bugün Eklenen\n- generic: \"5\"\n- generic: Kalem\n- generic: \"0\"\n- generic: Sonuç Arşivi\n- generic: \"0\"\n- generic: Takibimdeki\n- button \"Önceki sekmeler\":\n- button \"Ana İhale Listesi\":\n - generic: Ana İhale Listesi\n- button \"Günlük Bülten\":\n - generic: Günlük Bülten\n- button \"Sonuç Sorgula\":\n - generic: Sonuç Sorgula\n- button \"İhale Takvimi\":\n - generic: İhale Takvimi\n- button \"Sözleşme Sorgula\":\n - generic: Sözleşme Sorgula\n- button \"KDV Hesapla\":\n - generic: KDV Hesapla\n- button \"Sınır Değer\":\n - generic: Sınır Değer\n- button \"Fiyat Analizi\":\n - generic: Fiyat Analizi\n- button \"Kanban Pano Sürükle Takip\":\n - generic: Kanban Pano\n - generic: Sürükle Takip\n- button \"Rakip Radar Canlı Uyar\":\n - generic: Rakip Radar\n - generic: Canlı Uyar\n- button \"Doküman Deposu\":\n - generic: Doküman Deposu\n- button \"Analitik Dashboard\":\n - generic: Analitik Dashboard\n- button \"Kırmızı Bayrak Şeffaflık\":\n - generic: Kırmızı Bayrak\n - generic: Şeffaflık\n- button \"KİK Kurul Kararları\":\n - generic: KİK Kurul Kararları\n- button \"AB İhaleleri (TED)\":\n - generic: AB İhaleleri (TED)\n- button \"Planlar\":\n - generic: Planlar\n- button \"API & Webhooks\" [active]:\n - generic: API & Webhooks\n- button \"Mobil PWA\":\n - generic: Mobil PWA\n- main:\n - heading \"API Erişimi\" [level=2]\n - paragraph: İhale verisini kendi sistemlerinize (ERP, CRM) taşımak için sunucu doğrulamalı API anahtarları.\n - paragraph:\n - text: API erişimi\n - strong: Kurumsal\n - text: planda sunulur. Mevcut planınızda API anahtarı oluşturulamaz — Planlar sekmesinden yükseltebilirsiniz.\n - heading \"API Anahtarları\" [level=3]:\n - text: API Anahtarları\n - generic: 0 / 0 anahtar\n - paragraph: Henüz anahtar yok.\n - textbox \"Anahtar adı\" [disabled]:\n - /placeholder: Anahtar adı (ör. ERP Entegrasyonu)\n - button \"Oluştur\" [disabled]:\n - text: Oluştur\n - heading \"MCP Sunucusu — yapay zekâ araçlarınıza İhaleist'i bağlayın\" [level=3]:\n - text: MCP Sunucusu — yapay zekâ araçlarınıza İhaleist'i bağlayın\n - paragraph:\n - text: \"Claude Code, Cursor, Claude Desktop gibi MCP destekli araçlar İhaleist'i doğrudan sorgular:\"\n - code: search_tenders\n - text: \",\"\n - code: get_tender\n - text: \",\"\n - code: search_results\n - text: \",\"\n - code: search_items\n - text: \",\"\n - code: upcoming_deadlines\n - text: . Yukarıdaki API anahtarınızı kullanır.\n - paragraph:\n - text: Claude Code\n - generic: — terminalde tek komut\n - button \"Kopyala\":\n - text: Kopyala\n - generic: \"claude mcp add --transport http ihaleist http://127.0.0.1:5176/mcp --header \\\"Authorization: Bearer ih_live_ANAHTARINIZ\\\"\"\n - paragraph:\n - text: Cursor / Windsurf\n - generic: — .cursor/mcp.json\n - button \"Kopyala\":\n - text: Kopyala\n - generic: \"{ \\\"mcpServers\\\": { \\\"ihaleist\\\": { \\\"url\\\": \\\"http://127.0.0.1:5176/mcp\\\", \\\"headers\\\": { \\\"Authorization\\\": \\\"Bearer ih_live_ANAHTARINIZ\\\" } } } }\"\n - paragraph:\n - text: Claude Desktop\n - generic: — claude_desktop_config.json (mcp-remote)\n - button \"Kopyala\":\n - text: Kopyala\n - generic: \"{ \\\"mcpServers\\\": { \\\"ihaleist\\\": { \\\"command\\\": \\\"npx\\\", \\\"args\\\": [ \\\"-y\\\", \\\"mcp-remote\\\", \\\"http://127.0.0.1:5176/mcp\\\", \\\"--header\\\", \\\"Authorization: Bearer ih_live_ANAHTARINIZ\\\" ] } } }\"\n - paragraph:\n - text: RSS beslemesi\n - generic: — Feedly, Outlook, Slack RSS, n8n… (il, sektor, q filtreleri)\n - button \"Kopyala\":\n - text: Kopyala\n - generic: http://127.0.0.1:5176/api/feeds/tenders.rss?key=ih_live_ANAHTARINIZ&il=İstanbul&q=eldiven\n - paragraph:\n - text: \"Sonuç ilanları beslemesi anahtarsız:\"\n - code: http://127.0.0.1:5176/api/feeds/sonuc.rss\n - text: (firma, idare, il filtreleri). Anahtarı\n - code: ih_live_ANAHTARINIZ\n - text: yerine yazın.\n - paragraph:\n - strong: \"Kullanım:\"\n - text: İsteklerinize\n - code: \"Authorization: Bearer ih_live_…\"\n - text: başlığını ekleyin. Anahtar sunucuda doğrulanır, her kullanımda son kullanım zamanı güncellenir, iptal ettiğinizde anında geçersiz olur.\n- button \"Kullanım kılavuzu (? tuşu)\":" +} \ No newline at end of file diff --git a/docs/quality/uygulama-durumu.md b/docs/quality/uygulama-durumu.md index 7d404e2..a0be3f6 100644 --- a/docs/quality/uygulama-durumu.md +++ b/docs/quality/uygulama-durumu.md @@ -605,3 +605,11 @@ API anahtarı istemcisinde 30 saniye zaman aşımı, yanıt biçimi kontrolü ve Doğrulama: boş başarılı liste, 503, geçersiz JSON/veri, geç gelen farklı oturum yanıtı ve zaman aşımında tek oluşturma isteği. Gerçek izole yerel HTTP sunucusunda oluşturma → gizli alanları içermeyen liste → MCP initialize erişimi → son kullanım zamanı → iptal → 401 zinciri geçti. Başka hesap iptal edemedi; iptal yanıtında limit korundu. Test anahtarları geçici veritabanında tutuldu ve çıktıya yazılmadı. Sonuç: 132 test başarılı; üretim derlemesi geçti. Tarayıcıda hata/hesap değişimi/kopyalama kabulü henüz yapılmadı. Büyük paket uyarıları ve D01–D11 kalan işleri açık. Canlı yayın yapılmadı. + +### D09 — API anahtarı tarayıcı kabulü + +Yeni, izole localhost:5176 test sunucusunda görünür test kontrol ekranıyla yalnız anahtar listeleme isteğine 503 hatası uygulandı. API ekranı çökmedi; hata ve yeniden deneme göründü, oluşturma kapandı. Kontrol ekranından hata kaldırılınca aynı uygulama ekranındaki yeniden deneme 0/10 listesini getirdi. Gerçek test anahtarı oluşturuldu: tek seferlik kutu, ad ve 1/10 sayacı görüldü. İptal sonrası kutu kayboldu, liste boşaldı ve limit 0/10 olarak korundu. + +Normal test hesabına görünür giriş ekranından geçildiğinde 0/0 limit, Kurumsal plan açıklaması ve kapalı oluşturma görüldü. Önceki anahtar adı görünmedi. Bu geçiş tam sayfa yüklemesiyle yapılmıştır; devam eden istek sırasında hesap değişimi bu tarayıcı kontrolünde kanıtlanmış değildir. Pano izin hatası da açık kabul maddesidir. + +Kanıt: qa-api-key-lifecycle.json, sekiz kontrol doğru. Anahtar değeri ve öneki kanıtta maskelendi; oluşturulan anahtar test sonunda iptal edildi. Test yardımcısındaki hata kontrolleri yalnız yerel QA sunucusundadır, üretime dahil değildir. Üretim kodu değişmediğinden önceki 132 test/build tekrarlanmadı; QA değişikliği çalışan tarayıcı akışıyla doğrulandı. Tam plan ve canlı yayın açık. diff --git a/tests/browser-qa.mjs b/tests/browser-qa.mjs index 759c542..9b37b6a 100644 --- a/tests/browser-qa.mjs +++ b/tests/browser-qa.mjs @@ -11,11 +11,17 @@ process.env.AUTH_SECRET=randomBytes(32).toString('hex'); const {signToken}=await import('../server/auth.mjs'); const user={email:'browser-qa@example.test',name:'Laboratuvar QA',isAdmin:false}; const token=signToken(user); +const keyUser={email:'keys-browser-qa@example.test',name:'API QA',isAdmin:true}; +const keyToken=signToken(keyUser); +let apiKeyListFailure=false; const probe=netServer();await new Promise(r=>probe.listen(0,'127.0.0.1',r));const port=probe.address().port;await new Promise(r=>probe.close(r)); const api=spawn(process.execPath,['server/index.js'],{cwd:new URL('..',import.meta.url),env:{PATH:process.env.PATH,NODE_ENV:'test',AUTH_SECRET:process.env.AUTH_SECRET,IHALEIST_USER_DATA_DIR:dir,IHALEIST_SHARED_DATA_DIR:join(dir,'shared'),PORT:String(port),UYUM_GOMME:'0'},stdio:'ignore'}); const entries=[['1582991','Giresun','10.09.2026','10:00'],['1534665','Kayseri','22.09.2026','11:00'],['1499061','Akdeniz','22.09.2026','10:30'],['1573235','Aksaray','09.09.2026','10:00'],['1523851','Tepecik','11.09.2026','10:00']]; const tenders=entries.map(([id,city,date,time])=>({id:'qa-'+id,ikn:'2026/'+id,baslik:'QA — '+city+' laboratuvar',kurum:city+' TEST KURUMU',sehir:city,tarih:date,saat:time,alimTuru:'Mal Alımı',sektor:'Laboratuvar & Ölçüm',sektorler:['Laboratuvar & Ölçüm'],durum:'Açık',takipte:false,kanbanStatus:'incelenecek',items:[{id:'1',ad:'Sentetik test kalemi',miktar:2,birim:'adet'}],aciklama:'Bu yalnızca yerel arayüz test verisidir. Teklif geçerlilik süresi 120 takvim günü. Birim fiyat teklif. '.repeat(3)})); const ui=await createServer({server:{host:'127.0.0.1',port:0,proxy:{'/api':{target:'http://127.0.0.1:'+port}}},plugins:[{name:'qa-fixtures',configureServer(server){server.middlewares.use((req,res,next)=>{ + if(req.url==='/qa-api-controls') {res.setHeader('Content-Type','text/html; charset=utf-8');res.end(`
Yalnız geçici test deposunu etkiler.
`);return;} + if(req.method==='POST' && req.url?.startsWith('/qa-api-failure?')) {apiKeyListFailure=new URL(req.url,'http://localhost').searchParams.get('mode')==='on';res.end('ok');return;} + if(apiKeyListFailure && req.method==='GET' && req.url==='/api/me/apikeys') {res.writeHead(503,{'Content-Type':'application/json'});res.end(JSON.stringify({success:false,error:'QA: Anahtar deposuna erişilemiyor.'}));return;} if(req.url==='/qa-signin') {res.setHeader('Content-Type','text/html; charset=utf-8');res.end(`Sentetik ihale verileri ve geçici kullanıcı deposu kullanılır.
`);return;} if(req.url?.startsWith('/api/tenders')){res.setHeader('Content-Type','application/json');res.end(JSON.stringify({success:true,tenders,totalCount:5,todayCount:0,historyCount:0,source:'Yerel sentetik QA',fetchedAt:new Date().toISOString()}));return;} next();