Skip to content

About

Full-stack Turkish tech news aggregator — scrapes 27 sources (cybersecurity, CVE, Kubernetes, SRE, DevTools), translates to Turkish, and serves via a modern dark-mode UI. Built with Django REST Framework, React (Vite), Celery, Redis, and Docker/Kubernetes.

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

500 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Teknoloji Radar

Siber guvenlik haberleri, CVE zafiyetleri, Kubernetes ekosistemi, SRE (Site Reliability Engineering) haberleri, DevTools altyapi araclari guncellemeleri ve yapay zeka (AI) gelismelerini 47 farkli kaynaktan toplayan, Turkceye ceviren ve modern bir arayuzde sunan full-stack haber agregasyon uygulamasi.

Bu proje Vibe Coding yaklasimiyla, Claude Code (claude-opus-4-6) ile birlikte gelistirilmistir.

Uygulama surumu appVersion 2026.10.3 (CalVer; imaj etiketi)
Helm chart 2.2.1 (SemVer; etiket chart-2.2.1) — CHANGELOG
Calisma zamani Python 3.11, Django 5.2, Node 22, PostgreSQL 16, Redis 7
Testler 941 Django testi (news/tests/, PostgreSQL uzerinde CI'da kosar) ve 298 Vitest testi, 25 dosya (frontend/src/)
Dagitim Docker Compose (canli, yerel) · Helm (generic) · Argo CD + Vault (yerel GitOps, ADR-0008)
Lisans MIT

Icindekiler: Mimari · Ozellikler · Veri Kaynaklari · Teknoloji Yigini · Kurulum · Gelistirme ve Test · Kullanim · API · Entegrasyon API v1 · Proje Yapisi · Ceviri Sistemi · Periyodik Cekim · Surumleme · Kubernetes / Helm · CI ve Guvenlik Hatti · Operasyon ve Sorun Giderme · Ortam Degiskenleri · Belgeler ve Yol Haritasi · ADR


Mimari

Yerel topoloji

CyberNews yerel topoloji: GitHub repolari (tech-radar, yerel-gitops), docker-desktop Kubernetes (Argo CD, Vault Secrets Operator, Vault, tech-radar namespace'i), yerel-platform PostgreSQL, Docker Compose canli ortami ve gelistiricinin yerel-platform klonu (tf.sh, Terraform, sir_yaz.sh)

Okunusu, yukaridan asagiya:

  • GitHub: tech-radar chart'i chart-<surum> etiketiyle sunar; yerel-gitops kumede ne calisacagini tutar. Gelistirici yalniz yerel-gitops'a push eder.
  • docker-desktop Kubernetes: Argo CD iki repoyu okur (chart HTTPS ile, GitOps reposu salt okunur SSH deploy key ile, 2 dakikada bir) ve tech-radar namespace'ini senkron tutar. Vault Secrets Operator Vault'tan kv/tech-radar/uygulama'yi okuyup teknoloji-secret'i yazar; uygulama Secret'i env olarak alir. Argo CD, VSO ve Vault'u Terraform kurar; Terraform ayrica Vault'u (KV, auth, politikalar) ve Argo CD'nin kok Application'ini ayarlar.
  • yerel-platform PostgreSQL: tek sunucu, iki veritabani. K8s uygulamasi host.docker.internal:5432 uzerinden cybernews_k8s'e, compose yerel-platform agi uzerinden cybernews'e baglanir.
  • Docker Compose: canli ortam. api/worker/scheduler Redis'i cache ve broker olarak, LibreTranslate'i cekim aninda ceviri icin kullanir; 35 harici kaynagi ve Gemini API'yi disaridan ceker.

Gorsel Archify ile uretildi; etkilesimli HTML surumu repo disinda tutulur.

Compose ici bilesenler

                 ┌──────────────────────┐
                 │   React Frontend     │  Vite dev server (compose) /
                 │   Vite + Bootstrap 5 │  Nginx (imaj, K8s)
                 │   :3000              │
                 └──────────┬───────────┘
                            │ /api proxy
                 ┌──────────▼───────────┐        ┌───────────────────────┐
                 │  Django REST API     │◄──────►│  PostgreSQL 16        │
                 │  Gunicorn, DRF       │        │  yerel-platform       │
                 │  /api/* (arayuz)     │        │  (ayri repo, paylasilan│
                 │  /api/v1/* (dis API) │        │   yerel-postgres:5432) │
                 └───┬─────────────┬────┘        └───────────────────────┘
                     │             │
          ┌──────────▼──┐   ┌──────▼─────────────────────┐
          │  Redis 7    │◄──┤  Celery Worker + Beat       │
          │  cache +    │   │  cekim · ceviri · retranslate│
          │  broker     │   │  6 saatte bir / saatlik tur │
          └─────────────┘   └──────┬───────────────┬──────┘
                                   │               │
                      ┌────────────▼────┐   ┌──────▼──────────────┐
                      │ 35 harici kaynak│   │ Ceviri saglayicilari│
                      │ RSS · HTML · API│   │ LibreTranslate (yerel)│
                      └─────────────────┘   │ Gemini (yukseltme)   │
                                            └─────────────────────┘

Ayni kod uc bicimde calisir:

Ortam Ne icin Nasil kurulur Veritabani
Docker Compose Canli yerel ortam (gunluk kullanim) docker compose up -d --build yerel-postgres / cybernews
Helm (generic) Herhangi bir Kubernetes kumesi helm upgrade --install (bolum) chart ici PostgreSQL ya da harici
Argo CD + Vault (yerel GitOps) Paralel deneme ortami, docker-desktop yerel-gitops reposuna commit; platform yerel-platform Terraform'u (ADR-0008) yerel-postgres / cybernews_k8s

Ozellikler

  • 47 farkli kaynak — 12 siber guvenlik, 5 CVE, 3 Kubernetes, 5 SRE, 13 DevTools, 9 Yapay Zeka; hepsi anahtarsiz ve ucretsiz (GitHub API icin istege bagli GITHUB_TOKEN)
  • Asenkron cekim — "Getir" istegi Celery worker'a devredilir; arayuz 5 saniyede bir yeni kayitlari otomatik yansitir
  • Periyodik cekim — Celery Beat tum bolumleri 6 saatte bir otomatik gunceller (sadece yeni kayitlar cevrilir)
  • Yonetici korumali sifirlama — Veritabanini silen clear endpoint'leri yalnizca Django admin oturumuyla calisir
  • Tam makale cevirisi — Kisaltma yok, tum icerik Turkceye cevrilir
  • Teknik terim korumasi — 130+ terim (Kubernetes, Docker, Elasticsearch, CVE, CVSS, vb.) ceviri sirasinda bozulmaz
  • Turkce imla post-processing — Cumle basi buyuk harf, noktalama duzeltme, URL/surum koruma
  • Parca tabanli ceviri — Uzun makaleler cumle sinirlarindan 4500 karakterlik parcalara bolunerek cevrilir
  • Genel Bakis — Ana sayfa (/) zafiyet odaklidir: "Zafiyet Durumu · Son 24 Saat" basligi altinda kritik (24 sa), yuksek (7 gun) ve CISA KEV (7 gun) kutulari, son ziyaretten beri yeni kayit cumlesi, CVSS dagilim grafigi, "Oncelikli Zafiyetler" listesi, "Gundem" ve bir sonraki cekim saati; ozet sayilari yalniz GET /api/ozet/'ten, Gundem GET /api/gundem/'den gelir (asagidaki madde)
  • Gundem — Genel Bakis'teki kart, bes bolumun (Siber Guvenlik, Kubernetes, SRE, DevTools, Yapay Zeka; CVE haric) son 72 saatini tarar ve cok kaynakta birden yer alan buyuk olaylari one cikarir (tasarim). Hesap sunucuda news/gundem.py icindedir; LLM ve dis istek yoktur:
    • Pencere: created_at son 72 saat; ek olarak yayin tarihi 4 gunden eskiyse kayit disarida kalir (kaynak eski yazilari yeniden yayinlarsa sahte taze olay cikmaz)
    • Olay gruplama: Ingilizce orijinal basliklar uzerinden. Uydurma adlar (PHP2Shell gibi) ve ayni CVE kimligi tek basina baglar; ortak nadir bir ozel ad + baslik benzerligi baglar; ayni kaynaktan iki makale ancak yuksek benzerlikte ayni olay sayilir. Secim aninda, ayni ozneyi tasiyan cok kaynakli olaylar birlestirilir (tek kaynakli satirlar bu birlestirmeye girmez)
    • Ozet basliklari: cok konulu bultenler (THN "ThreatsDay" / "Weekly Recap", Help Net Security "Week in review", SecurityWeek "In Other News", "+ N more", iki ayri haberi ; ile baglayan mansetler) iki olay arasinda kopru kurmaz; yalniz tek bir olaya uyuyorsa ona tekrar olarak katilir. Kaynak sayisina ve rozete girmez, temsilci olmaz; bir bulten tek kaynakli haberi "cok kaynakli" yapamaz
    • Puan: her kaynagin tazelik carpani (24 saat yari omur) toplanir (ayri kaynak sayisi) + 0,5 x tekrar makalesi + 1,5 x etki sozcugu (hack, breach, zero-day gibi); tum yaslar esitse eski "ayri kaynak sayisi" olcusuyle ayni sonucu verir
    • Liste: en cok 6 oge; once cok kaynakli olaylar (puan sirasiyla), kalan yerler en yeni kayitlarla dolar. Cok kaynakli satirda "N kaynak" rozeti vardir; kaynak adlari rozetin ipucunda ve ekran okuyucu adinda yer alir
  • Ortak okuma paneli — Tum bolumler ayni panelde acilir: metin varsayilan olarak Turkce okunur, "Orijinali goster" ile ingilizce asil metin acilir; cevrilmemis kayit orijinal metinle ve "Cevrilmedi: orijinal metin" uyarisiyla gosterilir, cevrilemeyen paragraflar isaretlenir; CVE kayitlarinda CVSS, KEV satiri ve kaynak baglantilari yer alir
  • Paylasilabilir baglanti — Panel acikken adres ?kayit=<id> alir (ornek /news?kayit=123); adres kopyalanip acilinca ayni kayit okunur, geri tusu paneli kapatir. Kayit acik sayfada yoksa (baska sayfa, filtre disi, eski) liste ucundan ?id= ile istenir; silinmis/bilinmeyen kimlikte "Kayit bulunamadi" bildirimi cikar ve parametre adresten silinir
  • Karanlik tema — Yalnizca koyu tema (<html data-bs-theme="dark">); tema dugmesi yoktur. Vurgu #7aa2ff → #b98bff, kritik #ff5d8f, yuksek #ffb35d; sistem yazi tipleri, harici font/CDN yok (CSP degismez), prefers-reduced-motion icin animasyonlar durur (tasarim)
  • DevTools takibi — Seq, Ceph, MongoDB, PostgreSQL, RabbitMQ, Elasticsearch+Kibana, Redis, Moodle, LiteLLM, LangGraph, Langfuse, GitLab, Keycloak release guncellemeleri
  • CISA KEV — Aktif somurulen zafiyetler (Known Exploited Vulnerabilities) CVE bolumunde ayri kaynak; NVD API'sinin hasKev filtresiyle, eklenme tarihi ve federal son tarih bilgisiyle. Eklenme tarihi CVEEntry.kev_added_date alaninda (migration 0016) tutulur; NVD yolu bir KEV kaydini yeniden yazsa da bu tarihi ezmez; Genel Bakis'in KEV kutusu bu alana gore sayar
  • Filtre, siralama ve sayfalama — Alti bolumun hepsi ayni filtre cubugunu kullanir: Donem (1/3/7/14/30 gun veya Tumu, varsayilan 7), Siralama (yeni/eski; CVE'de CVSS), Kaynaklar, bolume ozel dugmeler (CVE: onem; Kubernetes: kategori) ve Arama kutusu (?ara=; basliklarda ve aciklamalarda, CVE'de kimlikte de; 2 karakterden kisa arama suzmez). Liste 5 sn'de bir yalniz ilk sayfada sessizce yenilenir (sonraki sayfalar kaymasin); yeni sorgu hatayla biterse eski liste yerine "Yeniden dene" kutusu cikar. Bilinmeyen adreste "Sayfa bulunamadi" sayfasi gosterilir. Gercek kayit sayisi satiri, numarali sayfalar (sayfa basina 25) ve adrese yazilan durum (?gun=tumu&sirala=cvss&sayfa=2&onem=kritik&kaynak=...) vardir; adres kopyalanip acilinca ayni gorunum gelir. Filtre ve siralama sunucuda created_at uzerinden, veritabanindan yapilir (tasarim)
  • Cekim penceresi — Cek dugmesi min(gun, 15) gunluk kayit ceker (news/serializers.py sinirlari: 1-30 gun haberler, 1-90 CVE/Kubernetes/SRE/Yapay Zeka, 1-120 DevTools)
  • Yeniden denemeli cekim — Gecici 429/5xx ve baglanti hatalarinda 2 ek deneme, ussel bekleme, Retry-After'a uyum (news/base_scraper.oturum_kur); onceden tek bir 503 kaynagi o tur bos birakiyordu
  • CVSS siddet filtresi — Kritik / Yuksek / Orta / Dusuk (CVE sayfasi); sunucuda CVSS araliklariyla (onem) uygulanir, "Tumunu goruntule" /cve?sirala=cvss acar
  • HTML rapor disa aktarma — Her bolumden koyu temali, yazdirilabilir HTML rapor indirilebilir; rapor o anki filtre ve siralamayi kullanir, en fazla 500 kayit icerir ve fazlaysa raporda not duser (utils/rapor.js). Okuma paneli, kaydi sayfadan cikmis olsa da acik kalir
  • Entegrasyon API (/api/v1/) — Token'li, imlecli delta okuma; OpenAPI 3 semasi ve Swagger UI; manuel tetikleme ve is takibi (ADR-0003)
  • Cekim gorunurlugu — Her cekim FetchRun olarak kaydedilir; GET /api/v1/status/ bolum basina tazelik ve son durum verir (ADR-0006)
  • Ceviri rozetleri — Her kayit saglayicisini tasir (LibreTranslate / Gemini); bekleyen cevirilerde Ingilizce metin kaybolmaz
  • Docker Compose — Tek komutla 6 container ayaga kalkar (PostgreSQL ayri yerel-platform reposunda paylasilir)
  • Kubernetes — Surumlu Helm chart (SemVer + CHANGELOG, CI kapilari); Argo CD Sync hook modu ve harici Secret destegi
  • GitOps + Vault — Yerel docker-desktop'ta Terraform ile kurulan Argo CD + HashiCorp Vault + Vault Secrets Operator zinciri; sirlar git'e ve state'e girmez (ADR-0008)
  • Guvenlik hatti — 9 GitHub Actions is akisi: test/build/Helm kapisi, CodeQL, Trivy (kaynak + imaj + SBOM), gitleaks, ZAP DAST, Dependency Review, zizmor, OpenSSF Scorecard, chart etiketi kapisi (plan)

Veri Kaynaklari

Siber Guvenlik Haberleri (12 kaynak)

Kaynak Yontem Aciklama
The Hacker News HTML Scraping Tam makale icerigi cekilir
Bleeping Computer HTML Scraping Sponsorlu icerik filtrelenir; Cloudflare Chrome UA'sini 403'ledigi icin Firefox UA, tur basina 10 makale ve 1 sn bekleme (429)
SecurityWeek RSS + tam makale RSS linkleri tasir, govde makale sayfasindan cekilir (ana sayfa HTML'inde link bos geliyordu)
Dark Reading RSS Feed HTML 403 dondugu icin RSS kullanilir
Krebs on Security HTML Scraping Brian Krebs'in guvenlik blogu
The Record RSS + tam makale Recorded Future'in haber sitesi
CyberScoop RSS Feed Tam metin content:encoded icinde gelir
Help Net Security RSS + tam makale Sektor haberleri, arastirma ozetleri
Infosecurity Magazine RSS Feed Kisa ozet; govde makale sayfasindaki paragraflardan tamamlanir
SANS ISC RSS Feed Internet Storm Center gunlukleri; tam metin RSS'te
The Register RSS Feed Security bolumu; tam metin RSS'te
Security Affairs RSS Feed Tam metin content:encoded icinde gelir

Yeni RSS kaynaklari scraper_multi.RSSNewsSource ile okunur: tur basina en fazla 15 haber, days penceresi, 200 karakterden kisa ozetler makale sayfasindan tamamlanir. Feed'den gelen linkler yalniz kaynagin kendi kok alaninda ve https ise acilir (news/base_scraper.link_guvenli; SSRF korumasi, bkz. GUVENLIK-PLANI 3a). fetch_all_news tavani kaynak sayisiyla buyur (max(30, 3 x kaynak)), boylece seyrek yazan kaynaklar (Krebs, SANS) tarih siralamasinda dusmez.

CVE Zafiyetleri (5 kaynak)

Kaynak Yontem Aciklama
CISA KEV NVD REST API (hasKev) Son days gunde KEV katalogu'na eklenen, aktif somurulen CVE'ler; baslikta CISA'nin zafiyet adi, aciklamada eklenme ve son tarih. cisa.gov JSON akisi bot korumasi nedeniyle 403 dondugu icin NVD uzerinden
NVD (Yayinlanan) REST API Son days gunde yayinlanan CVE'ler; startIndex ile sayfalanir (sayfa 2000, tavan 4000)
NVD (Guncel) REST API Son 2 gunde degisen CVE'ler; yalniz guncelleme kaynagi: veritabanindaki CVE'lerin CVSS/KEV/aciklama alanlarini gunceller, yeni kayit olarak yalniz yayin tarihi pencerede ise alinir
GitHub Advisory REST API CVSS, CWE, etkilenen paketler dahil
Tenable HTML Scraping Severity bilgisi dahil; aciklamasi yer tutucu ("No description provided") olan kayitlar alinmaz

Ayni CVE birden fazla kaynaktan gelirse tutulacak kayit cve_scraper.KAYNAK_ONCELIGI ile secilir: CISA KEV, NVD, NVD Guncel, GitHub Advisory, Tenable. Veritabaninda cevrilmis olan bir CVE yeniden cevrilmez, ama NVD ailesinden gelen veriyle ceviri disi alanlari guncellenir (news/cve_guncelleme.py): CVSS ve onem, KEV eklenme tarihi (kaynak CISA KEV olur), CWE ve referanslar; yer tutucu aciklama gercegiyle degisirse kayit ceviri kuyruguna doner. Degismeyen kayit yazilmaz (updated_at ilerlemez). Yeni kayitlar turda en fazla CVE_TUR_TAVANI (250) kadar islenir, KEV ve CVSS sirasiyla; kalanlar bir sonraki turda yine yenidir. Eski yer tutucu aciklamalar icin tek seferlik: python manage.py cve_aciklama_tamamla --uygula.

Kubernetes (3 kaynak)

Kaynak Yontem Aciklama
Kubernetes Blog HTML Scraping Resmi Kubernetes blog yazilari
Kubernetes GitHub REST API Release notlari, CHANGELOG formatinda
CNCF Blog WordPress API Cloud Native Computing Foundation haberleri

SRE (5 kaynak)

Kaynak Yontem Aciklama
SRE Weekly RSS Feed Haftalik bulten, bireysel makalelere ayristirilir
InfoQ SRE RSS Feed feed.infoq.com/sre/ konu akisi (HTML kartlari istemci tarafinda cizildigi icin RSS'e gecildi)
PagerDuty Eng RSS Feed Incident management ve SRE makaleleri
Google Cloud SRE RSS Feed SRE anahtar kelime filtresiyle
DZone DevOps RSS Feed feeds.dzone.com/devops-and-cicd (eski /devops adresi olu bir porta yonlendiriyordu)

DevTools — Altyapi Araclari (13 kaynak)

Kaynak Yontem Aciklama
Seq Datalust Blog RSS Yapilandirilmis log arama motoru, release filtreli
Ceph GitHub Releases Atom Dagitik storage, version tag tabanli
MongoDB GitHub Tags Atom + mongodb.com release notes Stabil rX.Y.Z tag'leri; aciklama resmi surum notlari sayfasindaki surum basligindan (blog RSS'i Haziran 2026'da donmustu)
PostgreSQL Resmi News RSS Resmi haberler, release notlari, ekosistem
RabbitMQ GitHub Releases API Mesaj kuyrugu, tam changelog
Elasticsearch + Kibana GitHub Releases API + elastic.co release notes Resmi release notes sayfasindan detayli changelog
Redis Blog RSS + tam makale Blog sayfasindan tam icerik cekilir (blockContent)
Moodle GitHub Tags API + moodledev.io Resmi release notes sayfasindan gercek icerik
LiteLLM GitHub Releases API LLM gateway; yalniz vX.Y.Z stabil surumler (gunluk dev/rc/backport elenir)
LangGraph GitHub Releases API Ajan orkestrasyonu; cekirdek X.Y.Z, sdk== ve cli== paketleri (checkpoint/prebuilt elenir)
Langfuse GitHub Releases API LLM gozlemlenebilirlik; vX.Y.Z surumleri, changelog
GitLab docs.gitlab.com surum Atom'u Ay surumleri ve yama surumleri, tam surum notu (gitlab.com/api/v4 anonim istege 403 donuyor)
Keycloak GitHub Releases API Kimlik yonetimi; X.Y.Z surumleri (nightly elenir)

LiteLLM, LangGraph, Langfuse ve Keycloak devtools_scraper.GitHubReleasesScraper ortak sinifiyla okunur (tag deseni + prerelease elemesi). GitHub API anonim limiti 60 istek/saat/IP'dir; GITHUB_TOKEN verilirse yalniz api.github.com isteklerine eklenir (bkz. Ortam Degiskenleri). fetch_all tavani kaynak sayisiyla buyur (max(30, 3 x kaynak)).

Yapay Zeka (9 kaynak)

Kaynak Yontem Aciklama
Hugging Face RSS Feed Model, dataset ve kutuphane duyurulari
MIT Tech Review AI RSS Feed Tam makale icerigi RSS icinde gelir
MarkTechPost RSS Feed Arastirma ve model haberleri
AWS ML Blog RSS Feed AWS makine ogrenmesi blogu
TechCrunch AI RSS Feed AI sektor haberleri
Google DeepMind RSS Feed DeepMind arastirma blogu
OpenAI Blog RSS Feed OpenAI duyurulari
Ars Technica AI RSS Feed Ars Technica yapay zeka bolumu (https://arstechnica.com/ai/feed/; 2026-10-14: KDnuggets yerine)
Import AI RSS Feed Jack Clark'in haftalik yapay zeka bulteni (https://importai.substack.com/feed)

Tum AI kaynaklari news/base_scraper.py icindeki ortak BaseRSSScraper ile okunur; RSS aciklamasi 200 karakterden kisaysa makale sayfasindan paragraf cekilir. Benchmark/leaderboard skorlari kapsam disidir (bkz. ADR-0002).


Teknoloji Yigini

Katman Teknolojiler
Backend Python 3.11, Django 5.2, Django REST Framework 3.18, drf-spectacular (OpenAPI 3), django-csp, Celery 5.6 + django-celery-beat, Gunicorn 22, Whitenoise
Frontend React 18, Vite 6, React Bootstrap 2.9, React Router DOM 7, Axios, react-hot-toast; Node 22; yalniz koyu tema (sistem yazi tipleri, src/styles/tema.css)
Veri PostgreSQL 16 (compose ve K8s; SQLite yalniz DEBUG=True ile hostta), Redis 7 (cache + Celery broker, django-redis)
Scraping BeautifulSoup4, lxml, Requests
Ceviri Cekim aninda yerel LibreTranslate 1.9.6 (aninda Turkce, rozetli); retranslate saatlik turlarla (gunde 20) bekleyen ve onemli LibreTranslate kayitlarini (CVE'de yalniz CVSS >= 7 ya da KEV) Gemini API (gemini-3.5-flash-lite, ucretsiz katman, kayit basina tek istek) ile yeniden eskiye dogru yukseltir + merkezi post-processing
Konteyner / dagitim Docker Compose, cok asamali Dockerfile'lar (non-root, digest sabitli taban imajlar), Nginx 1.31 (frontend imaji), Helm chart tech-radar
Platform (ayri repolar) yerel-platform: paylasilan PostgreSQL + Terraform (Argo CD, Vault, VSO); yerel-gitops: Argo CD Application'lari ve ortam degerleri
CI / guvenlik GitHub Actions, CodeQL, Trivy, gitleaks, OWASP ZAP, Dependency Review, zizmor, OpenSSF Scorecard, Dependabot, kubeconform

Tam surumler requirements.txt ve frontend/package.json dosyalarindadir; Dependabot bunlari haftalik gunceller.


Kurulum (Docker Compose)

Gereksinimler

  • Docker ve Docker Compose
  • Internet baglantisi (kaynak sitelere ve Gemini API'ye erisim icin; LibreTranslate yerel container'da calisir)
  • Paylasilan yerel PostgreSQL (yerel-platform reposu) ayakta ve cybernews veritabani olusturulmus

Hizli Baslangic

.env.example'i .env olarak kopyalayin. SECRET_KEY (openssl rand -hex 32) ve DB_PASSWORD (yerel-platform'daki cybernews kullanicisinin parolasi) zorunludur; GEMINI_API_KEY istege baglidir (bos birakilirsa Gemini hic denenmez, sistem LibreTranslate ile calisir); OPENROUTER_API_KEY, OPENROUTER_MODEL, DEEPL_API_KEY ve GEMINI_FALLBACK_MODEL ucretsiz yedek ceviri zincirini acar (bos = kapali, bkz. Ceviri Sistemi). Veritabani ayri yerel-platform reposundaki paylasilan PostgreSQL'dir; compose'dan once orada docker compose up -d calismis olmalidir:

git clone https://github.com/AdanedhelWrites/tech-radar.git
cd tech-radar/cybersecurity_news

cp .env.example .env
docker compose up -d --build
Servis URL
Frontend http://localhost:3000
Backend API http://localhost:8000/api/

Container'lar

Container Image Port Gorev
teknoloji-api teknoloji-haberleri-api:latest 8000 Django REST API, scraping, ceviri
teknoloji-frontend node:22-alpine 3000 React arayuz (Vite dev server, hot-reload; kaynak bind mount)
teknoloji-translate libretranslate/libretranslate:v1.9.6 — (kume ici 5000) Yerel ceviri; yalniz en,tr modelleri, ilk acilista ~258 MB indirir (volume teknoloji-translate-models); 4 CPU / 2 GB siniri
teknoloji-redis redis:7-alpine 6379 Cache + Celery message broker (volume teknoloji-redis-data)
teknoloji-worker teknoloji-haberleri-api:latest — Arka plan scraping + ceviri (celery worker)
teknoloji-scheduler teknoloji-haberleri-api:latest — Periyodik gorev zamanlayici (celery beat)
yerel-postgres (ayri repo: yerel-platform) postgres:16.15-alpine 127.0.0.1:5432 Paylasilan yerel PostgreSQL; CyberNews cybernews veritabanini ve kullanicisini kullanir

Container'lar teknoloji-network bridge agi uzerinden haberlesir; api, worker ve scheduler ayrica yerel-platform adli dis aga baglanir (PostgreSQL oradadir). Compose kaynak kodu /app'e bind mount eder; api entrypoint.sh ile acilista migrate + collectstatic calistirir (RUN_STARTUP_TASKS=true). Ayni imaj Kubernetes'te salt okunur kok dosya sistemiyle ve bu adimlar kapali calisir.

Yonetim Komutlari

# Baslat
docker compose up -d --build

# Durdur
docker compose down

# Loglari izle
docker compose logs -f teknoloji-api
docker compose logs -f teknoloji-worker

# Redis cache temizle
docker compose exec teknoloji-redis redis-cli FLUSHDB

# PostgreSQL shell
docker exec -it yerel-postgres psql -U cybernews -d cybernews

# Django shell
docker compose exec teknoloji-api python manage.py shell

# Sifirdan baslat (volume'lar dahil)
docker compose down -v && docker compose up -d --build

Veri tasima (SQLite -> PostgreSQL)

2026-10'da canli veri SQLite'tan PostgreSQL'e tasindi (ADR-0007). Ayni araclar her iki yonde calisir:

# Tam hassasiyetli dump (mikrosaniye ve metin bosluklari korunur). Dosya HASSASTIR:
# parola hash'leri ve API token'lari icerir; commit etmeyin, is bitince silin.
python manage.py veri_tasi_dump .fazb/dump.json
# Hedefte: migrate, sonra standart loaddata
python manage.py loaddata .fazb/dump.json
# Iki veritabaninda calistirip ciktilari karsilastirin; fark yoksa tasima kayipsizdir
python manage.py veri_ozeti

Django'nun dumpdata komutu bu is icin kullanilmaz: JSON bicimi tarihleri milisaniyeye kirpar (v1 imleci mikrosaniye tasir), XML bicimi metin bosluklarini kaybeder.

Yonetici Hesabi

"Sifirla" butonlari (POST /api/{bolum}/clear/) veritabanini sildigi icin yalnizca Django admin yetkisiyle calisir; oturum yoksa 403 doner. Ilk kurulumda bir yonetici olusturun:

docker compose exec teknoloji-api python manage.py createsuperuser

Ardindan http://localhost:8000/admin/ adresinden giris yapin. Oturum cerezi ayni tarayicidaki frontend isteklerinde de kullanilir; axios CSRF token'i csrftoken cerezinden otomatik ekler.


Gelistirme ve Test

Testler

941 Django testi news/tests/ altindadir ve news/test_runner.py (GuvenliTestRunner) ile kosar. Calistirici uc garanti verir: hicbir test gercek LibreTranslate'e gitmez (LIBRETRANSLATE_URL bos), hicbir test gercek Gemini'ye gitmez (GEMINI_API_KEY bos), hicbir test canli Redis devre kesicisini okumaz veya acmaz (kapilar surec ici). Saglayici testleri adresi/anahtari override_settings ile kendileri verir ve HTTP'yi mock'lar.

# Canli compose yigininda (ayni PostgreSQL sunucusunda ayri test veritabani acilir)
docker compose exec teknoloji-api python manage.py test news --noinput

# Tek kullanimlik PostgreSQL + Redis ile, canli yigina dokunmadan (CI ile ayni yol)
scripts/pg_test.sh test news --noinput

# Hostta SQLite ile hizli deneme (DEBUG=True, DB_HOST bos)
scripts/pg_test.sh --sqlite test news.tests.test_cursor

Frontend'de ESLint (flat config, frontend/eslint.config.js; npm run lint) CI'da build'den once kosar: @eslint/js onerilenleri, react-hooks/rules-of-hooks (hata) ve exhaustive-deps (uyari). Bolum sayfalarindaki 5 sn'lik liste yenileme hooks/useAraliklaYenile ile sekme arka plandayken durur.

Frontend birim testleri Vitest + Testing Library ile frontend/src/**/*.test.{js,jsx} altindadir (npm test); CI'da lint ile build arasinda kosar. 298 test, 25 dosya; kapsam: liste sorgusu hook'lari (useListeSorgusu), sayfa cubugu (SayfaCubugu), rapor olusturma (utils/rapor.js), HTML kacisi (utils/html.js), goreli zaman (utils/zaman), aralikli yenileme hook'u, ceviri rozeti, saglik seridi (SaglikSeridi), Genel Bakis (genel/), ortak okuma paneli (okuma/, utils/okuma*.js), ?kayit= baglantisi (useSeciliKayit), bolum sayfalari (bolum/), CVE listesi ve son ziyaret (utils/sonZiyaret.js, useZiyaretTabani). Worker baslatma zaman asimi gorulurse (Windows bind mount'ta yavas kurulum) npm test -- --maxWorkers=2 ile kosun; o da asarsa frontend'i konteynerin kendi dosya sistemine (or. /tmp) kopyalayip orada kosun (tum takim ~10 sn).

CI (Backend (Django testleri)) testleri PostgreSQL 16 servisiyle, DEBUG=False ve gercek bir SECRET_KEY ile kosar; migration'larin eksiksiz oldugu (makemigrations --check) ayni iste dogrulanir. Yeni bir test yazarken kodu gecici olarak bozup testin kirmiziya dondugunu gorun; mock'lanmis saglayici testlerinde "yesil ama hicbir seyi sinamiyor" tuzagi kolaydir.

Test dosyasi grubu Kapsam
test_cursor, test_filters, test_refresh, test_jobs, test_status, test_schema, test_auth /api/v1/ sozlesmesi: imlec, parametreler, kilit/soguma, is takibi, status, OpenAPI, token
test_translation*, test_gemini, test_retranslate Terim koruma, parca bolme, post-processing, saglayici zinciri, devre kesici, butce, yukseltme
test_saklama, test_fetchrun, test_eski_fetch_kapisi RETENTION_DAYS sil/yeniden yaz dongusu, FetchRun kaydi, eski /api/*/fetch/ uclarinin v1 kapisindan gecmesi
test_ayar_dogrulama, test_admin, test_cache, test_altyapi, test_modeller SECRET_KEY/DB_HOST korumalari, admin yetkisi, cache, model kisitlari
test_migrations_*, test_veri_tasima Veri migration'lari ve SQLite -> PostgreSQL tasima araclari
test_kaynak_sagligi, test_saglik Kaynak sagligi (kadans farkindalikli sessizlik), anonim /api/saglik/

Hostta calistirma

DEBUG varsayilani False oldugu icin anahtarsiz python manage.py ... reddedilir. Yerelde iki secenek:

# Konteynerde (onerilen; ortam compose'tan gelir)
docker compose exec teknoloji-api python manage.py <komut>

# Hostta SQLite ile (yalniz deneme)
DEBUG=True python manage.py <komut>

Frontend icin frontend/ altinda npm install && npm run dev yeterlidir; vite.config.js /api'yi localhost:8000'e proxy'ler. Compose'daki dev sunucusu calisirken hosttan npm install yapmayin (bind mount node_modules ve EACCES); once docker compose stop teknoloji-frontend.

Yonetim komutlari ve betikler

Komut / betik Ne yapar
manage.py veri_tasi_dump <dosya> Tam hassasiyetli (mikrosaniye koruyan) JSON dump; hassas icerik, commit edilmez
manage.py veri_ozeti Model basina satir sayisi ve alan ozeti; iki veritabanini karsilastirmak icin
manage.py bozuk_cevirileri_isaretle Turkce metninde XTRM yer tutucu kalintisi olan ya da Ingilizce kalmis (Turkce harf yok, kelimelerin %90'i orijinalde) 'cevrildi' kayitlari bulup needs_translation isaretler, deneme sayacini sifirlar; varsayilan rapor, --uygula yazar
manage.py cve_baslik_cevir Basligi Ingilizce kalmis onemli (CVSS >= 7 / KEV) GHSA/KEV CVE basliklarini Gemini paketiyle bir kez cevirir; dusuk/orta ve reddedilen basliklar Ingilizce kalir; yalniz turkish_title yazilir; varsayilan rapor, --uygula yazar
scripts/pg_test.sh Tek kullanimlik PostgreSQL + Redis'e karsi manage.py; canli yigina dokunmaz
scripts/ornek_istemci.py /api/v1/ delta senkron ornegi (yalniz standart kutuphane)
scripts/helm_yerel_dogrulama.sh imaj|kur|sok Chart'i yalniz docker-desktop'ta gercek kurulumla dogrular (S1-S7)
scripts/chart_surum_kontrol.sh <taban-ref> Chart dizini degistiyse Chart.yaml version artmis ve CHANGELOG girdisi var mi (CI kapisi)
scripts/imaj_etiket_kontrol.sh <render.yaml> Render'daki imajlar etiketli mi, latest yok mu, ucuncu taraf imajlar digest ile sabit mi (CI kapisi)
scripts/chart_etiket_kontrol.sh chart-<surum> chart-* etiketi Chart.yaml ile ayni mi (etiket push'unda CI kapisi)
scripts/zap_sarif.py <report_json.json> <cikti.sarif> ZAP JSON raporunu SARIF 2.1.0'a cevirir (DAST is akisi zap-baseline ve zap-api kategorileriyle Security sekmesine yukler)

Kod kurallari

  • Kod, yorum ve commit mesajlari ASCII Turkce (diakritiksiz). main korumalidir: her degisiklik bir daldan PR ile gelir, bes zorunlu check (Backend, Frontend, Helm / Compose, dependency-review, gitleaks) yesil ve dal main ile guncel olmadan merge edilemez; dogrudan push kapalidir.
  • Her onemli karar bir ADR'dir (docs/ADR-*.md); tasarim ve uygulama planlari docs/superpowers/ altindadir.
  • Sir degerleri (anahtar, parola, token) hicbir dosyaya, log'a veya ekrana yazilmaz; .env ve .fazb/ gitignore'dadir, gitleaks her PR'da tarar.
  • helm/tech-radar/ altindaki her degisiklik chart surumunu artirir ve CHANGELOG girdisi ister (bkz. Surumleme).
  • Python: ruff check . (yalniz F ve E9; pyproject.toml) ve coverage esigi (MIN_COVERAGE, CI) kapidir; yerelde py -3 -m venv .venv && .venv/Scripts/pip install -r requirements-dev.txt.

Kullanim

Her sayfa ayni duzeni takip eder:

  1. Sol panelden gun araligini (1-15 / DevTools ve Yapay Zeka icin 1-60) ve kaynaklari secin
  2. "Getir" butonuna tiklayin
  3. Cekim arka planda (Celery worker) baslar; cevrilen haberler orta panele birkac saniye icinde otomatik duser
  4. Bir habere tiklayarak sag panelde detayini goruntuleyin

Ek butonlar:

  • Yenile — Mevcut verileri yeniden yukler
  • Sifirla — Tum verileri temizler (yonetici girisi gerekir, bkz. Yonetici Hesabi)
  • Indir — Koyu temali HTML rapor olarak disa aktarir

API Endpoints

Her bolum (news, cve, k8s, sre, devtools, ai) ayni endpoint yapisini kullanir:

Method Endpoint Deseni Aciklama
GET /api/{bolum}/ Kayitli verileri listele (filtre, siralama ve sayfalama parametreleri asagida)
POST /api/{bolum}/fetch/ Arka planda cekim baslat — Celery task (body: {"days": 7, "sources": [...]})
POST /api/{bolum}/clear/ Tum verileri sil (yonetici oturumu gerekir, aksi halde 403)
GET /api/{bolum}/stats/ Istatistikleri getir: {success, total, by_source, last_update}; CVE'de ayrica by_severity, Kubernetes'te by_category, DevTools'ta by_type
GET /api/saglik/ Bolum basina son basarili cekim, son durum, ceviri bekleyen/vazgecilen, yukseltmeden vazgecilen (upgrade_given_up), sessiz kaynaklar; ust duzeyde translation_budget.gemini (Gemini gunluk butcesi) (anonim, 60 sn cache)
GET /api/gundem/ Gundem karti: son 72 saatin en cok 6 olayi, CVE haric (anonim, 120 sn cache). Yanit {success, olaylar[], hesaplandi}; her olay {bolum, kayit, kaynak_sayisi, kaynaklar[], diger_kaynaklar[], makale_sayisi, bolumler[], puan, ilk, son} (diger_kaynaklar: temsilcinin kaynagi disindaki her kaynaktan bir makale {kaynak, baslik, link, bolum, id}; okuma paneli bunlari "Ayni olayi yazan diger kaynaklar" olarak listeler) (kayit bolumun kendi serilestiricisinin ciktisidir). Hesap hatasinda 500 yerine 200 {success: false, olaylar: []} doner ve cache'e yazilmaz
GET /api/ozet/ Genel Bakis ozeti: critical_count (CVSS >= 9.0, son 24 sa), high_count (7.0-8.9, son 7 gun), kev_count (kev_added_date son 7 gun), priority (en fazla 5 oncelikli CVE), chart (CVSS noktalari), unscored_count, sources{total,silent}, fetch{last_success_at,next_at}; ?since=<ISO tarih> ile ek olarak new_since_count (anonim, 60 sn cache; new_since_count cache'e girmez)

Bolum isimleri: news (Siber Guvenlik, fetch endpoint: /api/fetch/), cve, k8s, sre, devtools, ai

Liste parametreleri

Alti liste ucu (/api/news/, /api/cve/, /api/k8s/, /api/sre/, /api/devtools/, /api/ai/) sorguyu veritabanindan yapar; bolum basina liste cache'i yoktur (eski 100 kayitlik cache 2026-11-05'te kaldirildi). Filtre ve siralama created_at alanina gore calisir. Gecersiz deger hata vermez, varsayilana duser.

Parametre Degerler Aciklama
gun 1, 3, 7, 14, 30 Son N gun; yoksa tum kayitlar
sirala yeni (varsayilan), eski; CVE'de ayrica cvss Siralama
sayfa 1, 2, ... Sayfa numarasi; son sayfayi asan deger son sayfaya indirilir
boyut varsayilan 25, en fazla 100 Sayfa boyutu
kaynak virgulle ayrilmis liste Kaynak adi tam eslesme
ara metin (2-100 karakter) Basliklarda ve aciklamalarda buyuk/kucuk harf duyarsiz arama; CVE'de cve_id'de de
id kayit kimligi Tekil kayit: diger parametreler yok sayilir, yanit ayni zarfla 0 ya da 1 kayit tasir (?kayit= paylasilan baglanti)
onem CVE: kritik, yuksek, orta, dusuk CVSS araliklari
kategori Kubernetes: kubernetes Kategori filtresi

Yanit: {success, data, cached, count, toplam, sayfa, sayfa_sayisi, boyut}. cached geriye uyumluluk icin kalir ve her zaman false'tur; count sayfadaki kayit sayisi, toplam filtreye uyan tum kayit sayisidir. Ornek: /api/cve/?gun=30&sirala=cvss&onem=kritik&sayfa=2. /api/v1/ degismedi.

Not: Siber guvenlik bolumunun fetch, clear ve stats endpoint'leri /api/news/ altinda degil, dogrudan /api/ altindadir: /api/fetch/, /api/clear/, /api/stats/

Kaldirilan uclar (2026-11-05): /api/{bolum}/export/ (tum tabloyu tek yanitta donduruyordu). HTML rapor arayuzde liste ucundan kurulur (frontend/src/utils/rapor.js); toplu veri isteyen dis tuketiciler /api/v1/ imlecli listesini kullanir.


Entegrasyon API (/api/v1/)

Yukaridaki /api/* uc noktalari React arayuzune hizmet eder. Dis tuketici uygulamalar /api/v1/ kullanmalidir: token ister, cache'e hic bakmaz, imlecli delta ile hicbir kaydi atlamadan ve tekrar islemeden senkron yapilmasini saglar. Karar gerekcesi icin ADR-0003.

Calisan ornek: scripts/ornek_istemci.py — alti bolumu bastan sona ceker, imleci diske yazar, yalnizca standart kutuphane kullanir.

Token alma

Token'lar Django admin'den uretilir ve iptal edilir:

# Kullanici olustur (yoksa) ve token uret
docker compose exec teknoloji-api python manage.py shell -c "
from django.contrib.auth.models import User
from rest_framework.authtoken.models import Token
u, _ = User.objects.get_or_create(username='entegrasyon')
print(Token.objects.get_or_create(user=u)[0].key)
"

Her istekte Authorization: Token <key> basligi gonderilir. Admin arayuzunde Auth Token → Tokens ekranindan da uretilebilir ve iptal edilebilir.

Uc noktalar

Method Uc nokta Aciklama
GET /api/v1/schema/ OpenAPI 3 semasi (token gerekir)
GET /api/v1/docs/ Swagger UI — tarayicida admin oturumuyla acilir
GET /api/v1/health/ Servis ayakta mi — tokensiz (Kubernetes probe'lari icin)
GET /api/v1/status/ Bolum basina veri tazeligi: last_success_at, last_status, last_fetched_count, last_saved_count, pending_translation, translation_given_up, total; kaynak sagligi: sources{ad: last_record_at, last_fetched_count, zero_runs, expected_gap_days, days_since_record, silent} ve silent_sources[]; silent = zero_runs >= SOURCE_SILENT_RUNS VE (hic kayit yok VEYA days_since_record > expected_gap_days)
GET /api/v1/{bolum}/ Imlecli delta okuma
POST /api/v1/{bolum}/refresh/ Tek bolum icin manuel cekim tetikler
POST /api/v1/refresh/ Alti bolumu birden tetikler
GET /api/v1/jobs/{job_id}/ Manuel tetiklenen isin durumu

Bolum isimleri: news, cve, kubernetes, sre, devtools, ai — dikkat: v1'de k8s degil kubernetes.

Delta dongusu

curl -H "Authorization: Token $CYBERNEWS_TOKEN" \
  "http://localhost:8000/api/v1/cve/?limit=200&min_severity=high"

Yanit zarfi:

{
  "results": [ ... ],
  "next_cursor": "eyJ1IjoiMjAyNi0wOS0yMFQyMjowODo1Mi43MDE4MzErMDA6MDAiLCJpIjoxMDM2NX0",
  "has_more": true,
  "count": 200
}

Dongu: next_cursor'i sakla, bir sonraki istekte ?since_cursor=<deger> olarak gonder, has_more false olana kadar tekrarla. Imlec opaktir — (updated_at, id) ikilisinin kodlanmis halidir, ic bicimi haber verilmeden degisebilir; acma, yalnizca sakla ve geri gonder. next_cursor bos sonucta bile doner ki saklayacak bir degerin hep olsun. Siralama her zaman updated_at ASC, id ASC'dir; bu akis sirasidir, ekrana basma sirasi degildir.

Ilk senkronda tum kayitlar yeni gorunur. Daraltmak icin ?since=YYYY-MM-DD kullanilabilir (yalnizca imlec yokken gecerlidir).

Parametre Bolumler Aciklama
since_cursor hepsi Opak imlec; verildiginde since yok sayilir
since hepsi YYYY-MM-DD — ilk senkronu daraltmak icin
limit hepsi Varsayilan 100, tavan 500
source hepsi Virgulle ayrilmis kaynak adlari
needs_translation hepsi true / false — cevirisi bekleyenler
min_severity cve low | medium | high | critical — esik ve uzeri
severity cve Virgulle ayrilmis tam eslesme (critical,high)
category kubernetes Virgulle ayrilmis kategori
entry_type devtools Virgulle ayrilmis tur

Gecersiz parametre sessizce yok sayilmaz; 400 invalid_parameter doner.

Upsert anahtari — id kullanmayin

Tuketici tarafi upsert (idempotent) olmalidir; salt insert cift kayit uretir. updated_at icerik degismese de ilerleyebilir, yani ayni kayit akista birden fazla kez gorunur.

Birlestirme anahtari olarak id kullanilmamalidir. id kalici degildir: saklama penceresi (RETENTION_DAYS) disina dusen bir kayit silinir ve kaynak onu tekrar dondurdugunde yeni bir id ile geri gelir. Kararli anahtarlar:

Bolum Upsert anahtari
cve cve_id
news, kubernetes, sre, devtools, ai link

Bunlar yazma yolunun da anahtarlaridir: news/tasks.py ayni alanlarla update_or_create yapar. Gerekce ve olcumler icin ADR-0005.

Uyari: Bes bolumden dordunde (kubernetes, sre, devtools, ai) link veritabaninda unique=True, cve icin cve_id de oyle. news bolumunde link uzerinde benzersizlik kisiti yoktur — anahtar yazma yolunun sozlesmesidir, sema garantisi degildir. Tuketici kendi tarafinda benzersiz indeks tanimlamalidir.

Silmeler akista bildirilmez (tombstone yok); tuketici kendi saklama suresini uygular.

Dil alanlari

Baslik ve aciklama ic ice doner ve severity normalize edilir:

{
  "title":    { "original": "Critical RCE in ...", "tr": "... kritik RCE" },
  "severity": { "code": "critical", "label": "Kritik" },
  "needs_translation": false,
  "translation_provider": "gemini"
}

Tuketici title.tr || title.original yazarak cevirisi henuz hazir olmayan kayitta Ingilizceye duser — kayit kaybolmaz, Turkcesi hazir olunca updated_at ilerledigi icin ayni anahtar uzerine guncelleme gelir. Filtreler severity'nin code degeri uzerinden calisir.

Manuel tetikleme

curl -X POST -H "Authorization: Token $CYBERNEWS_TOKEN" \
  http://localhost:8000/api/v1/cve/refresh/

202 ile {"job_id", "section", "status", "status_url"} doner; durum /api/v1/jobs/{job_id}/ ile izlenir. Uc katman korur: bolum kilidi (REFRESH_LOCK_TTL) cift kazimayi onler, paylasilan bolum sogumasi (REFRESH_COOLDOWN) kaynak siteleri ve ceviri kotasini korur, token basina hiz siniri tek istemciyi sinirlar. Sogumadaki bolum 429 cooldown ve Retry-After basligi dondurur. Toplu /api/v1/refresh/ her zaman 202 doner; govdede started / already_running / skipped listeleri bulunur.

Hiz sinirlari

Kapsam Oran
Okuma (v1_read) token basina 120/dk
Tetikleme (v1_refresh) token basina 12/saat
Bolum sogumasi REFRESH_COOLDOWN (900 sn) — tum token'lar arasinda paylasilir

Hata sozlesmesi

Tum v1 hatalari ayni bicimde doner:

{ "error": { "code": "invalid_cursor", "message": "Imlec cozulemedi: ..." } }
Kod HTTP Ne zaman
unauthorized 401 Token yok, gecersiz veya iptal edilmis
invalid_cursor 400 since_cursor cozulemedi
invalid_parameter 400 Parametre bicimi veya degeri gecersiz
not_found 404 refresh/ icin bilinmeyen bolum; bilinmeyen veya suresi dolmus job_id
throttled 429 Hiz siniri asildi
cooldown 429 Bolum sogumada (Retry-After basligi ile)
internal 500 Beklenmeyen sunucu hatasi

Not: Bu sozlesme yalnizca tanimli uc noktalar icin gecerlidir. Hic rotasi olmayan bir yol — ornegin GET /api/v1/k8s/, cunku v1'de bolum adi kubernetes'tir — DRF'e hic ulasmadan Django'nun duz HTML 404'unu dondurur, JSON gelmez. Tuketici yanit govdesini ayristirmadan once Content-Type'i kontrol etmelidir. Buna karsilik POST /api/v1/k8s/refresh/ rotalidir ve duzgun {"error": {"code": "not_found", ...}} dondurur.

Makine tarafindan okunur sozlesme

/api/v1/schema/ OpenAPI 3 dokumani dondurur ve yalnizca /api/v1/ uclarini kapsar; eski /api/* uclari bilincli olarak disaridadir.

curl -H "Authorization: Token $CYBERNEWS_TOKEN" \
  http://localhost:8000/api/v1/schema/ -o cybernews-v1.yaml

Semadan istemci uretilebilir (openapi-generator vb.). /api/v1/docs/ ayni semayi Swagger UI ile gosterir; tarayici Authorization basligi gondermedigi icin bu sayfa admin'de oturum acmis bir kullaniciyla acilir.

Not: Sema yayimlandigi andan itibaren dis sozlesmedir. Bir alanin tipi degisirse bu artik "dokumantasyon hatasi" degil, tuketicinin istemcisini kiran bir degisikliktir.


Proje Yapisi

cybersecurity_news/
├── cybernews/                  # Django proje ayarlari
│   ├── settings.py             # Env-var tabanli config (DB, Redis, CORS, CSP)
│   ├── guvenlik_basliklari.py  # Permissions-Policy, CORP, COEP middleware'i
│   ├── urls.py                 # Root URL yapilandirmasi
│   ├── celery.py               # Celery yapilandirmasi
│   └── wsgi.py
│
├── news/                       # Ana Django uygulamasi
│   ├── models.py               # NewsArticle, CVEEntry, KubernetesEntry, SREEntry, DevToolsEntry, AINewsEntry
│   ├── views.py                # API endpoint'leri (6 bolum x 4 endpoint + saglik, ozet, gundem)
│   ├── tasks.py                # Celery task'lari (cekim + ceviri)
│   ├── serializers.py          # DRF serializer'lari
│   ├── urls.py                 # API URL pattern'leri
│   ├── translation_utils.py    # Merkezi ceviri modulu (terim koruma + post-processing)
│   ├── translation_providers.py# Saglayici zinciri: LibreTranslate (cekim) + devre kesici
│   ├── gemini.py               # Gemini API istemcisi, hiz siniri, gunluk butce, tur payi
│   ├── kayit_cevirmenleri.py   # Ucretsiz yedek cevirmenler: Gemini 2. model, OpenRouter, DeepL Free + zincir
│   ├── retranslate.py          # Bekleyenleri cevir + LibreTranslate kayitlarini Gemini'ye yukselt (yedek zincirle)
│   ├── liste_sorgusu.py        # Liste ucleri icin filtre, siralama ve sayfalama sorgusu
│   ├── gundem.py               # Gundem: olay gruplama ve puan (saf fonksiyonlar, /api/gundem/)
│   ├── veri_tasima.py          # Tam hassasiyetli dump/ozet (SQLite -> PostgreSQL gecisi)
│   ├── test_runner.py          # GuvenliTestRunner: testler gercek saglayiciya gitmez
│   ├── management/commands/    # veri_tasi_dump, veri_ozeti, bozuk_cevirileri_isaretle, cve_baslik_cevir, cve_aciklama_tamamla
│   ├── tests/                  # 941 test (v1 sozlesmesi, ceviri, saklama, migration, ayar, gundem)
│   │   └── fixtures/gundem_basliklari.json  # Gundem gruplama testlerinin gercek baslik ornekleri
│   ├── base_scraper.py         # Ortak RSS okuyucu (BaseRSSScraper)
│   ├── ai_scraper.py           # 9 Yapay Zeka kaynagi scraper'i
│   ├── cve_scraper.py          # 5 CVE kaynagi scraper'i
│   ├── k8s_scraper.py          # 3 Kubernetes kaynagi scraper'i
│   ├── sre_scraper.py          # 5 SRE kaynagi scraper'i
│   ├── devtools_scraper.py     # 13 DevTools kaynagi scraper'i
│   ├── fetch_runs.py           # FetchRun satirlarini yazan Celery sinyalleri
│   ├── api_v1/                 # Dis tuketici entegrasyon katmani (ADR-0003)
│   │   ├── views.py            # Delta, refresh, jobs, status, health uc noktalari
│   │   ├── serializers.py      # v1 serializer'lari (alanlar tek tek yazilir)
│   │   ├── cursor.py           # (updated_at, id) keyset imleci
│   │   ├── filters.py          # Query parametresi ayristirma
│   │   └── refresh.py          # Bolum kilidi, soguma, job kaydi
│   └── admin.py                # Django admin kayitlari
│
├── scripts/
│   ├── ornek_istemci.py        # /api/v1/ delta senkron ornegi (stdlib-only)
│   ├── pg_test.sh              # Tek kullanimlik PostgreSQL + Redis ile manage.py / testler
│   ├── helm_yerel_dogrulama.sh # Chart'i yalniz docker-desktop'ta dogrular (S1-S7)
│   ├── chart_surum_kontrol.sh  # CI kapisi: chart degistiyse surum + CHANGELOG
│   ├── imaj_etiket_kontrol.sh  # CI kapisi: render'da etiketsiz / latest imaj yok
│   ├── chart_etiket_kontrol.sh # CI kapisi: chart-<surum> etiketi Chart.yaml ile ayni
│   └── zap_sarif.py            # ZAP JSON raporu -> SARIF (DAST bulgulari Security sekmesine)
│
├── scraper_multi.py            # 12 siber guvenlik kaynagi scraper'i
│
├── frontend/                   # React SPA
│   ├── src/
│   │   ├── App.jsx             # Router, Navbar (yalniz koyu tema), Genel Bakis rotasi
│   │   ├── App.css             # Duzen stilleri
│   │   ├── styles/tema.css     # Koyu tema token'lari ve bilesen stilleri
│   │   ├── components/
│   │   │   ├── NewsComponent.jsx       # Siber guvenlik sayfasi
│   │   │   ├── CVEComponent.jsx        # CVE sayfasi
│   │   │   ├── KubernetesComponent.jsx # Kubernetes sayfasi
│   │   │   ├── SREComponent.jsx        # SRE sayfasi
│   │   │   ├── DevToolsComponent.jsx   # DevTools sayfasi
│   │   │   ├── AINewsComponent.jsx     # Yapay Zeka sayfasi
│   │   │   ├── CeviriEtiketi.jsx       # Ceviri saglayici rozeti
│   │   │   ├── genel/                  # Genel Bakis: durum kutulari, CVSS grafigi, oncelikli liste, gundem
│   │   │   ├── bolum/BolumSayfasi.jsx  # Bolum sayfalari icin ortak liste + panel iskeleti
│   │   │   ├── bolum/HaberBolumu.jsx   # Haber bolumleri icin ortak filtre cubugu + liste
│   │   │   ├── bolum/SayfaCubugu.jsx   # Numarali sayfa cubugu
│   │   │   ├── bolum/secenekler.js     # Donem, siralama ve onem secenekleri
│   │   │   ├── cve/CveSatiri.jsx       # CVE liste satiri
│   │   │   └── okuma/OkumaPaneli.jsx   # Ortak okuma paneli (Turkce varsayilan, orijinal istege bagli)
│   │   ├── hooks/useSeciliKayit.js     # ?kayit= derin baglantisi
│   │   ├── hooks/useListeSorgusu.js    # Filtre/siralama/sayfa durumu <-> adres
│   │   ├── hooks/useBolumVerisi.js     # Bolum listesini sunucudan ceker (sayfali)
│   │   ├── utils/rapor.js              # Mevcut filtrelerle HTML rapor (en fazla 500 kayit)
│   │   └── services/
│   │       └── api.js          # Axios API servisleri
│   ├── Dockerfile              # Production build: Node 22 + Nginx 1.31 (non-root)
│   ├── .dockerignore           # node_modules bind mount'u build'i bozmasin
│   ├── nginx.conf              # SPA routing + /api proxy
│   ├── vite.config.js          # Dev proxy ayarlari
│   ├── index.html
│   └── package.json
│
├── docs/
│   ├── ADR-0001 ... ADR-0008   # Mimari karar kayitlari
│   ├── GUVENLIK-PLANI.md       # Guvenlik hatti: hatlar, bulgu yerleri, bekleyen isler
│   └── superpowers/
│       ├── specs/              # Tasarim belgeleri (karar + gerekce + testler)
│       └── plans/              # Uygulama planlari (gorev gorev) ve devir notlari
│
├── .github/workflows/          # CI, codeql, trivy, gitleaks, dast-zap, dependency-review,
│                               # zizmor, scorecard, chart-etiket (bkz. CI ve Guvenlik Hatti)
│
├── helm/tech-radar/            # Helm chart (tek dagitim kaynagi; surum: Chart.yaml)
│   ├── Chart.yaml              # version (SemVer) + appVersion (imaj etiketi)
│   ├── CHANGELOG.md            # Chart surumleri ve yukseltme notlari
│   ├── values.yaml             # Varsayilan degerler (gizli deger icermez)
│   ├── ci/yerel-values.yaml    # Yerel docker-desktop dogrulamasi
│   ├── ci/argocd-values.yaml   # CI'da Argo CD + VSO modunda render
│   ├── .helmignore
│   └── templates/
│       ├── _helpers.tpl        # Imaj, guvenlik baglami, ortam, ALLOWED_HOSTS yardimcilari
│       ├── configmap.yaml
│       ├── secret.yaml         # secretKey ve dbPassword zorunlu
│       ├── postgresql.yaml     # postgresql.enabled
│       ├── redis.yaml          # redis.enabled
│       ├── libretranslate.yaml # libretranslate.enabled
│       ├── backend.yaml
│       ├── frontend.yaml
│       ├── celery.yaml         # Worker + Beat
│       ├── migration-job.yaml  # helm: teknoloji-migrate-r<N>; argocd: sabit adli Sync hook
│       ├── ingress.yaml        # ingress.enabled
│       └── NOTES.txt
│
├── docker-compose.yml          # 6 servis (PostgreSQL ayri: yerel-platform)
├── Dockerfile                  # Backend multi-stage build (non-root, digest sabitli taban)
├── entrypoint.sh               # Startup: wait-for-db + migrate + collectstatic (compose)
├── requirements.txt            # Python bagimliliklari (surumler sabit)
├── SECURITY.md                 # Zafiyet bildirimi: GitHub private vulnerability reporting
├── .env.example                # SECRET_KEY, DB_PASSWORD (zorunlu), GEMINI_API_KEY, yedek ceviri anahtarlari, GITHUB_TOKEN
├── .gitleaksignore             # Gecmis commit'lere sabitli placeholder baseline'i (silinmez)
├── .gitignore                  # .env, .fazb/, db.sqlite3*, staticfiles/, node_modules
├── .dockerignore               # .env ve .env.* imaja girmez
└── manage.py

Depo kokundeki scraper*.py, gui*.py ve requirements_*.txt dosyalari projenin ilk masaustu/CLI surumunden kalmadir; web uygulamasi bunlari kullanmaz.


Ceviri Sistemi

Tum scraper'lar news/translation_utils.py merkezi modulunu kullanir. 3 katmanli mimari:

1. Teknik Terim Korumasi

Ceviri oncesinde 130+ teknik terim XTRM####X formatiyla placeholder'lara donusturulur. Ceviri sonrasi geri yerlestirilir. Ek olarak:

  • URL'ler (https://...) otomatik korunur
  • Surum numaralari (v1.2.3, 9.3.1) otomatik korunur
  • CVE numaralari (CVE-2024-12345) otomatik korunur
  • Backtick kod parcalari (`kubectl get pods`) otomatik korunur
  • SIG etiketleri ([SIG Node]) otomatik korunur
  • GitHub URL'leri ve paket isimleri otomatik korunur

Terimler uzunluktan kisaya siralanarak islenir — kisa terimlerin kelime icinde eslesmesin onlenir.

2. Parca Tabanli Ceviri

Uzun metinler cumle sinirlarindan 4500 karakterlik parcalara bolunur (saglayici istek boyutu sinirlarini asmamak icin). Her parca icin ayri terim koruma uygulanir. LibreTranslate bu parcalari kendi icinde ayrica 160 karakterlik alt parcalara boler (LIBRETRANSLATE_CHUNK_CHARS); Gemini yukseltmesi ise birden cok kaydi tek istekte paketler (bkz. Retranslate ve Gemini Yukseltme).

3. Turkce Post-Processing

Ceviri sonrasi otomatik duzeltmeler:

  • Cumle basi ve satir basi buyuk harf
  • Noktalama duzeltmeleri (noktadan sonra bosluk, parantez temizligi)
  • URL/email/dosya uzantisi korumasi (post-processing'in .co -> . Co yapmasi engellenir)
  • Ingilizce ay isimlerinin Turkceyecevirisi
  • Bozuk Turkce karakter encoding duzeltmesi
  • K8s kisaltmasinin korunmasi

4. Hiz Siniri ve Devre Kesici

  • LibreTranslate (cekim aninda) — Baglanti hatasi, zaman asimi veya 5xx gelirse kendi Redis devre kesicisi LIBRETRANSLATE_COOLDOWN (60 sn, varsayilan) boyunca acilir; 4xx devre kesiciyi acmaz. Yeniden deneme ve ayri bir hiz siniri yoktur, eszamanlilik compose CPU siniriyla dogal olarak sinirlanir.
  • Gemini (retranslate yukseltmesi) — Istekler arasi en az GEMINI_MIN_INTERVAL saniye (Redis uzerinden tum worker'lar icin ortak), gunluk GEMINI_DAILY_BUDGET istek tavani (retranslate turlarina yayilir, bkz. Retranslate ve Gemini Yukseltme), gecici 500/502/503/504 ve baglanti kopmasi once GEMINI_GECICI_BEKLEMELER (varsayilan 5,15 sn) ile yeniden denenir; 429/5xx ve 401/403/404 sonrasi GEMINI_COOLDOWN saniye devre kesici.
  • Kayip yok — Hicbir saglayici cevirmezse haber tam Ingilizce metniyle kaydedilir ve needs_translation=True isaretlenir; sonraki cekimde veya retranslate_pending turunde otomatik olarak yeniden denenir.

5. Retranslate ve Gemini Yukseltme

retranslate_pending Celery Beat gorevi (retranslate-pending-hourly) saatlik calisir: dakika 05, saatler 1-5, 7-11, 13-17 ve 19-23; cekim saatleri (00/06/12/18) atlanir, yani gunde 20 tur. Her tur iki isi yapar: bekleyen (needs_translation=True) kayitlari LibreTranslate ile cevirir (bolum basina imlec sirasiyla), ardindan translation_provider='libretranslate' kayitlari Gemini API (gemini-3.5-flash-lite) ile yukseltir; birden cok kayit tek istekte (paket) cevrilir.

  • Onem sinifi: CVE'lerde yalniz CVSS >= 7.0 ya da CISA KEV'deki kayitlar Gemini adayidir; digerleri (dusuk/orta skorlu ya da skoru olmayan) kalici olarak LibreTranslate cevirisiyle kalir, ne bekleyen ne yukseltme asamasinda Gemini'ye gitmez. Diger bolumlerde butun kayitlar adaydir.
  • Yeni kayit once: Yukseltme asamasinin imleci yoktur; her tur bolum basina en fazla RETRANSLATE_UPGRADE_BATCH (CVE'de RETRANSLATE_UPGRADE_BATCH_CVE) kaydi created_at azalan sirayla (en yeniden eskiye) alir. Eski LibreTranslate birikimi butce kaldikca geriye dogru erir.
  • Bolum onceligi: Sira CVE, haber, AI, SRE, DevTools, Kubernetes'tir ve katidir: ustteki bolumun adaylari bitmeden alttaki Gemini payi almaz. Bolumler icin ayrilmis bir pay yoktur (GEMINI_CVE_RESERVE kaldirildi, bkz. ADR-0005).
  • Paketleme: Yukseltme asamasi adaylari siraya sadik kalarak paketler; paket GEMINI_BATCH_CHARS (varsayilan 10000) karakteri ya da GEMINI_BATCH_MAX (varsayilan 15) kaydi asmaz. Yapili Kubernetes degisiklik kayitlari paketlenmez, tek basina gider. Paket cevirisi kayit basina dogrulanir; ek olarak capa capraz denetimi (CVE/GHSA numarasi, URL, kod parcasi, 3+ parcali surum) cevirisi baska kaydin capasini tasiyan kaydi reddeder (ayni bicimli yer degisimi onlenir); capasiz kayitlar etkilenmez. Paketli K8s cevirileri de ayni yapi isareti denetiminden gecer.
  • Bolme: Kesilen (MAX_TOKENS), bozuk yanitli (SAFETY vb. tamamlanmamis ya da cozulemeyen JSON, yanit_bozuk) ya da kayda ozgu 4xx alan paket ikiye bolunup ayni turda yeniden denenir; yalniz hala basarisiz olan tek kayit deneme sayacini artirir. Bekleyen asama kayit basina calismaya devam eder.
  • Tur payi: Gunluk butce (GEMINI_DAILY_BUDGET, varsayilan 450) gune yayilir. Bir turun Gemini payi ceil(kalan gunluk butce / Pasifik gece yarisina kadar kalan tur sayisi)'dir ve istek (paket) basina sayilir, kayit basina degil; kullanilmayan pay sonraki turlara kalir. Pay biterse yukseltme asamasi stopped_reason='gemini_tur_payi' ile durur, bekleyen kayitlar LibreTranslate ile surer; gunluk butce bitmisse sebep gemini_budget olur.
  • Deneme sayaci: Icerik hatasi (Gemini cevirmedi ya da dogrulama gecmedi) translation_attempts'i artirir; RETRANSLATE_MAX_ATTEMPTS'a ulasan kayit yukseltme adayi olmaktan cikar (/api/saglik/ sections[ad].upgrade_given_up). Aktarim ve kota hatalari (zaman asimi, baglanti, 429, 5xx) sayaci artirmaz. Gemini 401/403/404 (anahtar, yetki ya da model adi hatasi) ve anahtar/hesap sorunu bildiren 400 (error.details[].reason=API_KEY_INVALID ya da error.status FAILED_PRECONDITION / PERMISSION_DENIED / UNAUTHENTICATED) devre kesiciyi acar ve butceyi geri verir; sayac artmaz. Diger 400'ler kayda ozgu icerik hatasidir. Beklenmeyen istisna (kod hatasi) da devre kesiciyi acar. Savunma katmani: bir bolumde ayni turda 5 ardisik icerik hatasi (ARDISIK_HATA_SINIRI) gelirse o bolumun yukseltmesi o tur durur, kalan adaylar sayilmaz (tur sonucunda sections[ad].stopped_reason='ardisik_icerik_hatasi').
  • Tekil tur kilidi: Tur, Redis kilidi retranslate:kilit ile korunur (sahip jetonu, TTL min(RETRANSLATE_TIME_BUDGET + 600, CELERY_TASK_TIME_LIMIT + 60) sn; olu worker'in kilidi sonraki saatlik turu atlatmaz). Onceki tur surerken baslayan tur {'skipped': 'locked'} doner ve FetchRun satiri birakmaz.
  • Gorunurluk: /api/saglik/ translation_budget.gemini (used, limit, period, available, cooldown) dondurur; ana sayfa saglik seridi "Gemini kullanilan/sinir" gosterir. Bekleyen var ve son 6 bitmis tur (~6 saat) hic kayit cevirmediyse bolum stalled sayilir.

Eski google etiketli kayitlar yukseltilmez, etiketli kalir. 2026-10-21'den once ASCII'ye kaymis Gemini cevirileri (en az 10 kelime, hic Turkce harf yok; Gemini dogrulamasinin turkce harf yok kuraliyla ayni olcut, retranslate._ascii_gemini_cevirisi) de yukseltme adayidir; onem sinifi kurali onlara da uygulanir.

Saglamlastirma (2026-11-07): Scraper turunun sonundaki yazim, tur suresince retranslate'in yazdigi daha iyi ceviriyi ezmez (tasks._kaydet: cevrilmis kaydin ceviri alanlari yalniz en az ayni kalitede basarili ceviriyle yazilir). Gemini kapi ve butce sayaci Redis'e ulasamayinca kurulan yerel yedek 60 sn'de bir Redis'i yeniden dener; donuste yedegin saydigi istekler paylasilan sayaca eklenir. Haber tarihleri metnin icinden ayiklanir (base_scraper.ay_tarihi_coz; The Hacker News tarihindeki ikon karakteri yuzunden butun THN kayitlarina cekim gunu yaziliyordu, goc 0019 duzeltir), okunamayan tarih loga yazilir. RSS akisi HTTP hata kodunu loga yazar (403 artik bos akis gibi gorunmez).

Ceviri dogrulugu (2026-11-07): Son islem (turkish_post_process) yer tutucular geri konmadan once calisir; noktali ve alt cizgili tanimlayicilar (os.environ.get, blazer_usb.c) ve kod parcalari hem terim korumasinda hem son islemde korunur. Gemini her alanin capalarini (CVE/GHSA numarasi, URL, kod parcasi, surum) cevirisinde aynen arar, eksikse reddeder (tek kayit ve paket yolu); talimat bir terim sozlugu tasir (vulnerability -> guvenlik acigi, exploit -> istismar...; commit/branch/pipeline gibi terimler Ingilizce kalir). GHSA ozeti ve KEV zafiyet adi tasiyan CVE basliklari yalniz kayit cevirmeni (Gemini) yolunda cevrilir, yani onem sinifindaki kayitlarda; LibreTranslate kisa teknik basligi orijinalinden kotu cevirdigi icin (11-07 olcumu) dusuk/orta kayitlarin basligi Ingilizce kalir. Scraper'in ceviri istisnasi dali kaydi needs_translation olarak yazar. Etkinlik reklami paragraflari (TechCrunch, KubeCon kayit cagrisi) ceviriden once atilir (metin_temizle._reklam_mi).

Anahtar alma: Google AI Studio (aistudio.google.com) → Get API key → Create API key; cybersecurity_news/.env icine GEMINI_API_KEY=... (gitignore'da). Kart gerekmez; kota asilirsa 429 doner, sistem LibreTranslate ile surer.

Rozetler: Her kayit translation_provider tasir; arayuzde Makine çevirisi: LibreTranslate (sari), Çeviri: Gemini, Çeviri: OpenRouter, Çeviri: DeepL, Çeviri: Google (eski kayitlar).

Kuyruktan dusen kayitlar (translation_attempts >= RETRANSLATE_MAX_ATTEMPTS) arayuzde "Cevrilmedi: orijinal metin" rozetiyle gosterilir (rozet kosulu: needs_translation ve saglayici bos ve translation_attempts >= 1; hic denenmemis taze kayit rozet almaz); admin'de "Ceviri denemelerini sifirla" eylemi secili kayitlari yeniden kuyruga alir. GEMINI_MAX_CHARS (12.000) ustu kayitlar bilerek Ingilizce kalir (2026-10-14 karari).

6. Ucretsiz Yedek Ceviri Zinciri

Gemini'nin ucretsiz kotasi (gunde ~450 istek) yetmedigi ya da Gemini kapali oldugu gunlerde retranslate, ek ucretsiz saglayicilara duser. Zincir sirasi: Gemini birincil (GEMINI_MODEL) → Gemini ikinci model (GEMINI_FALLBACK_MODEL) → OpenRouter (ucretsiz model) → DeepL API Free. Anahtarlari/modeli bos olan halka zincirde yoktur; hepsi bossa davranis yedeksiz kurulumla aynidir (LibreTranslate ile surer).

  • Ne zaman devreye girer: Yalniz birincil Gemini gercekten kullanilamazken: gunluk butcesi bitmis, devre kesicisi acik ya da anahtari yok. Bir turun payi (gemini_tur_payi) bitmesi yedegi tetiklemez; kayit sonraki turu bekler. Yedekler tur payina tabi degildir, kendi sayac ve devre kesicileriyle sinirlidir. Istek duzeyi bir hata secilen yedegi kapatirsa ayni paket/kayit siradaki halkayla yeniden denenir (deneme sayaci artmaz). Bir yedegin ciktisi dogrulamadan gecmezse kayit ayni turda onu denememis siradaki hazir yedege gider; yalniz boyle yedek kalmadiginda deneme sayaci bir kez artar (ardisik hata serisine de bir kez girer; bekleyen asamada LibreTranslate yine son caredir). Birincil Gemini'nin reddi hemen sayilir, cunku birincil hazirken yedekler kullanilmaz. Yeniden secim paket basina sinirlidir (1 + yedek sayisi), yani bir paket sonsuza dek donmaz.
  • Kimler gider: Onem sinifi aynen gecerlidir: CVE'de yalniz CVSS >= 7 ya da KEV adaydir; CVSS < 7, skorsuz ve KEV disi CVE hicbir cevirmene (yedekler dahil) gitmez, LibreTranslate cevirisiyle kalir. Dogrulama (alan, yapi isareti, capa capraz denetimi) tum saglayicilara ayni uygulanir.
  • Yazilan etiket: Basarili ceviride translation_provider secilen saglayicinin adidir: gemini (birincil ve ikinci model), openrouter ya da deepl. libretranslate etiketli kayitlar yukseltme adayidir; OpenRouter/DeepL ile cevrilmis kayitlar sonradan tekrar yukseltilmez.
  • Yalniz ucretsiz garantileri: OpenRouter model adi :free ile bitmiyorsa (ya da bossa) hazir degil sayilir ve istek atilmaz; anahtar girilmis ama model bos ya da ucretli ise surec basina bir kez uyari loglanir. DeepL yalniz api-free.deepl.com ucuna gider (Pro ucu kodda yoktur); :fx ile bitmeyen (Free olmayan) DEEPL_API_KEY kullanilmaz, surec basina bir kez uyari loglanir (anahtar loga yazilmaz). Gemini ikinci model ayni anahtarin ayri ucretsiz kotasini kullanir. Gemini birincil ve ikinci model yalniz Google projesinde faturalandirma hesabi (billing) yoksa ucretsiz kalir; faturalandirma acik projede ucretsiz katmani olmayan bir model ucretlendirilir. Hicbir halka ucretli moda gecmez; kota bitince durur.
  • Sayaclar ve donemler: Gemini ve ikinci model gunluk (Pasifik gunu; gemini, gemini2 onekleri); OpenRouter gunluk (UTC; OPENROUTER_DAILY_BUDGET, aralik OPENROUTER_MIN_INTERVAL); DeepL aylik karakter sayaci (UTC ayi, DEEPL_MONTHLY_CHARS). DeepL 456 (kota doldu) dondurur ya da kalan karakter bir istegi karsilamiyorsa sayac ay tavanina doldurulur ve DeepL ay sonuna kadar kapanir (ay degisince sayac kendiliginden sifirlanir).
  • Gorunurluk: /api/saglik/ translation_budget birincil gemini'ye ek olarak yalniz ayarli yedekleri listeler (gemini2, openrouter, deepl); anahtar degerleri hicbir ozette yer almaz. Ana sayfa saglik seridi, kullanimi 0'dan buyuk olan yedegi gosterir. Rozetler: Çeviri: OpenRouter, Çeviri: DeepL (Gemini ikinci modeli Çeviri: Gemini gosterir).
  • Anahtarlar: OPENROUTER_API_KEY ve DEEPL_API_KEY degerlerini kullanici kendisi alir ve kendi .env dosyasina yazar (gitignore'da); depoya, imaja ve ornek dosyaya gercek deger girmez. Docker Compose bu degiskenleri teknoloji-api ve teknoloji-worker'a gecirir; Helm'de secrets.openrouterApiKey / secrets.deeplApiKey (chart 3.2.0).
  • Dagitim sirasi: Migration 0017 (translation_provider secenekleri openrouter ve deepl) yalniz secenek listesini degistirir, PostgreSQL'de islem yapmaz; yine de once migrate, sonra yeni kod dagitilir.

Periyodik Cekim (Celery Beat)

teknoloji-scheduler container'i, cybernews/settings.py icindeki CELERY_BEAT_SCHEDULE ile tum bolumleri 6 saatte bir (Europe/Istanbul 00:00, 06:00, 12:00, 18:00) otomatik gunceller. Worker ve ceviri yukunu dagitmak icin bolumler 10 dakika arayla kaydirilir:

Bolum Task Dakika Gun araligi
Siber Guvenlik fetch_news_task :00 7
CVE fetch_cve_task :10 7
Kubernetes fetch_k8s_task :20 30
SRE fetch_sre_task :30 30
DevTools fetch_devtools_task :40 30
Yapay Zeka fetch_ai_news_task :50 30

Tum cekimler (manuel "Getir" dahil) skip_existing=True ile calisir: veritabaninda zaten cevrilmis kayitlar tekrar cevrilmez; yalnizca yeni haberler ve ceviri bekleyen (needs_translation) kayitlar LibreTranslate'e gonderilir. Gun araligi task varsayilanidir; her cekim (manuel "Getir" dahil) bu araligin disinda kalan eski kayitlari siler. Bekleyen ve LibreTranslate kayitlarinin Gemini ile yukseltilmesi ayri bir Beat gorevidir (bkz. Retranslate ve Gemini Yukseltme): retranslate_pending_task, saatlik, dakika 05 (cekim saatleri 00/06/12/18 atlanir; gunde 20 tur).

Her cekim bir FetchRun satiri birakir (bolum, baslangic/bitis, fetched_count, saved_count, durum, hata ozeti, kaynak basina by_source). Son durumlar GET /api/v1/status/ ile okunur; Beat'in gercekten calistigini kontrol etmenin en kisa yolu budur (ADR-0006).

Loglar (2026-10-08): Scraper ve ceviri katmani print yerine logging kullanir; kaynak hatalari WARNING seviyesinde, modul adiyla (news.devtools_scraper, scraper_multi) gelir. docker compose logs teknoloji-worker | grep WARNING bir turda hangi kaynaklarin hata verdigini gosterir; LOG_FORMAT=json ile satirlar Loki/ELK'ye dogrudan gider. Worker Django LOGGING ayarini kullanir (CELERY_WORKER_HIJACK_ROOT_LOGGER=False).

Takili turlar (2026-10-09): Worker yeniden basladiginda ya da sert sure siniri (CELERY_TASK_TIME_LIMIT) alt sureci oldurdugunde task_postrun hic gelmez ve satir suresiz running kalirdi (canlida 4 satir, biri 5 gunluk). Ayni bolumun yeni turu acilirken eski running satirlari failure + stopped_reason=interrupted ile kapatilir.

Kaynak sagligi (2026-10-08): 8 kaynak aylarca sessizce olmustu (Bleeping Computer 403, SecurityWeek bos link, MongoDB/InfoQ/DZone donmus akislar); bolum toplami "success" gorundugu icin fark edilmedi. Artik her tur secili her kaynak icin kaynaktan gelen sayiyi (_drop_existing'den onceki) FetchRun.by_source'a yazar. /api/v1/status/ her kaynak icin zero_runs (ardisik 0 donen tamamlanmis tur) ve silent verir; SOURCE_SILENT_RUNS (varsayilan 4 = Beat'te 24 saat) esigi asan kaynaklar silent_sources listesindedir. Admin'deki FetchRun listesinde "0 donen kaynaklar" sutunu ayni bilgiyi tur basina gosterir. Seyrek yazan kaynaklar (Krebs, PagerDuty) kendi days penceresinde yine kayit dondurdugu icin yanlis pozitif vermez; yeni kayit olmamasi degil, kaynaktan hic kayit gelmemesi sessizliktir. Haftalik kontrol: curl .../api/v1/status/ | jq '.sections[].silent_sources'. 2026-10-14: sessizlik kadans farkindalikli — seyrek yayinlayan kaynak (RabbitMQ, Moodle, Ceph...) icin kaynak basina beklenen aralik (news/kaynaklar.py BEKLENEN_ARALIK_GUN), digerleri icin bolum penceresi; status ucu expected_gap_days ve days_since_record verir.


Surumleme

Uc ayri sayi vardir ve birbirine karistirilmamalidir:

Ne Nerede Kural Kim degistirir
Uygulama surumu helm/tech-radar/Chart.yaml appVersion; imaj etiketi teknoloji-haberleri-{api,frontend}:<appVersion> CalVer YYYY.M.N Yeni uygulama surumunde gelistirici
Chart surumu Chart.yaml version + git etiketi chart-<version> SemVer: uyumsuz values/sablon MAJOR, yeni istege bagli deger MINOR, duzeltme PATCH; her surum CHANGELOG.md'de ## [surum] basligi Chart dizinine dokunan her PR
Kumede calisan surum yerel-gitops reposunda Application'in targetRevision'i Degismez chart-* etiketi; yukseltme = etiketi degistir, geri alma = git revert GitOps reposuna commit

CI bu kurallari zorlar:

  • scripts/chart_surum_kontrol.sh: chart dizini degistiyse version artmis ve CHANGELOG girdisi var mi (CI, Helm / Compose dogrulama).
  • scripts/imaj_etiket_kontrol.sh: render'da etiketsiz veya latest imaj yok, ucuncu taraf imajlar digest ile sabit.
  • scripts/chart_etiket_kontrol.sh: chart-* etiketi push edilince Chart.yaml ile ayni surumu gosteriyor mu (chart etiketi is akisi).
  • Dockerfile'lardaki taban imajlar digest ile sabittir; Dependabot digest guncellemelerini PR olarak acar.

Etiket yalniz chart icin vardir (git tag chart-2.1.0 && git push origin chart-2.1.0); uygulama icin GitHub Release veya registry yayini yoktur, imajlar yerelde appVersion etiketiyle derlenir.


Kubernetes'e Deploy Etme (Helm)

Tek dagitim kaynagi helm/tech-radar/ chart'idir; ham manifest isteyen helm template ciktisini kullanir. Chart surumu Chart.yaml'dadir ve SemVer'e uyar (uyumsuz degisiklik MAJOR, yeni istege bagli deger MINOR, duzeltme PATCH); her surumun degisiklikleri ve yukseltme notlari helm/tech-radar/CHANGELOG.md'dedir ve CI bunu zorlar. appVersion uygulama imajinin etiketidir. Kararlar: ADR-0007.

Guvenlik: Asagidaki komutlar sablondur; <...> alanlarini kendi ortaminizla doldurun ve her komutta hedef baglami acikca verin (--kube-context / --context). Aktif kubectl baglamina guvenmeyin. Gizli degerleri values dosyasina yazmayin.

On gereksinimler

  • Kubernetes kumesi, kubectl ve Helm 3
  • Kumenin cekebilecegi bir registry'de backend ve frontend imajlari
  • Ingress kullanilacaksa bir Ingress Controller (ingress.className, varsayilan nginx)

Imajlar

docker build -t <registry>/teknoloji-haberleri-api:<surum> .
docker build -t <registry>/teknoloji-haberleri-frontend:<surum> ./frontend
docker push <registry>/teknoloji-haberleri-api:<surum>
docker push <registry>/teknoloji-haberleri-frontend:<surum>

image.tag verilmezse chart appVersion'i kullanir.

Kurulum

helm upgrade --install tech-radar ./helm/tech-radar \
  --kube-context <hedef-baglam> -n <namespace> --create-namespace \
  --set secrets.secretKey="<openssl rand -hex 32>" \
  --set secrets.dbPassword="<guclu-sifre>" \
  --set ingress.host=<alan-adi> \
  --set backend.image.repository=<registry>/teknoloji-haberleri-api \
  --set backend.image.tag=<surum> \
  --set frontend.image.repository=<registry>/teknoloji-haberleri-frontend \
  --set frontend.image.tag=<surum> \
  --wait --wait-for-jobs --timeout 15m

secrets.secretKey ve secrets.dbPassword zorunludur (bos birakilirsa render reddedilir); PostgreSQL ve uygulama ayni dbPassword'u kullanir. secrets.geminiApiKey istege baglidir; ucretsiz yedek ceviri anahtarlari secrets.openrouterApiKey ve secrets.deeplApiKey ile modeller/butceler config.app.geminiFallbackModel, openrouterModel, openrouterDailyBudget, deeplMonthlyChars vb. (chart 3.2.0) de bos/kapali gelir. Uretimde harici secret yonetimi (external-secrets, sealed-secrets, vault) tercih edin: Secret'i chart disinda yonetiyorsaniz secrets.existingSecret=<ad> verin; chart Secret olusturmaz, secrets.* zorunlu olmaz. Secret SECRET_KEY, DB_USER, DB_PASSWORD, GEMINI_API_KEY anahtarlarini icermelidir; GITHUB_TOKEN ve NVD_API_KEY istege baglidir (pod'a optional: true ile baglanir, yoksa ozellik kapali kalir). Chart 2.2.0'dan itibaren config.app.logLevel/logFormat, sourceSilentRuns, celeryTaskSoftTimeLimit/celeryTaskTimeLimit, axesFailureLimit/axesCooloffMinutes degerleri ConfigMap'e yazilir (CHANGELOG).

Nasil calisir

  • migration.mode=helm (varsayilan): her revizyonda teknoloji-migrate-r<revizyon> Job'u migration'lari uygular. migration.mode=argocd: Argo CD helm template kullandigi icin Job sabit adli (teknoloji-migrate) bir Sync hook'udur ve her senkronda yeniden olusturulur. Iki modda da api, worker ve scheduler migrasyon-bekle initContainer'inda migrate --check gecene kadar bekler. Geri alma sema geri almaz.
  • Backend probe'lari /api/v1/health/'e Host: localhost ile gider. ALLOWED_HOSTS sablonda kurulur: localhost, teknoloji-api (kume ici tuketici), ingress host'u ve config.django.extraAllowedHosts.
  • Statik dosyalar imajdadir; pod'lar RUN_STARTUP_TASKS=false ile acilir ve kok dosya sistemi salt okunurdur.
  • LibreTranslate (libretranslate.enabled) ilk acilista ~258 MB model indirir (internet gerekir); modeller PVC'de kalir.
  • Redis emptyDir kullanir: pod yeniden baslarsa bolum kilitleri, soguma, cache ve kuyruk kaybolur; Beat bir sonraki slotta yeniden planlar.
  • backend.name frontend/nginx.conf'a baglidir (teknoloji-api); degistirirseniz frontend imajini yeniden derleyin.

Guncelleme, geri alma, kaldirma

helm upgrade tech-radar ./helm/tech-radar --kube-context <hedef-baglam> -n <namespace> --reuse-values \
  --set backend.image.tag=<yeni-surum> --set frontend.image.tag=<yeni-surum> --wait --wait-for-jobs
helm history tech-radar --kube-context <hedef-baglam> -n <namespace>
helm rollback tech-radar <revizyon> --kube-context <hedef-baglam> -n <namespace>
helm uninstall tech-radar --kube-context <hedef-baglam> -n <namespace>
kubectl --context <hedef-baglam> delete namespace <namespace>   # PVC'ler (veri) de silinir

Yeni bir chart surumune gecmeden once CHANGELOG.md'deki yukseltme notunu okuyun (ornek: 2.0.0'da postgresPassword ve global.namespace kalkti).

Ham manifest

helm template tech-radar ./helm/tech-radar -n <namespace> \
  --set secrets.secretKey=<...> --set secrets.dbPassword=<...> > tech-radar.yaml

Ciktida secret degerleri acik metindir; commit etmeyin.

Yerel dogrulama (Docker Desktop Kubernetes)

Chart yalniz yerel docker-desktop baglaminda gercek kurulumla dogrulanir (S1-S7: kurulum, HTTP, uctan uca cekim, upgrade, PostgreSQL kaliciligi, zorunlu degerler, sokum):

scripts/helm_yerel_dogrulama.sh imaj   # :fazb-yerel imajlari
scripts/helm_yerel_dogrulama.sh kur    # S1-S6
scripts/helm_yerel_dogrulama.sh sok    # S7

Betik baglami degistirmez, yerel olmayan bir kumeyi reddeder, gizli degerleri calisma aninda uretir ve helm/tech-radar/ci/yerel-values.yaml'i kullanir.

GitOps ile kurulum (Argo CD + Vault, yerel)

Kisisel deneme ortami Argo CD ile git'ten kurulur (ADR-0008, tasarim: spec). Uc repo is bolusur:

Repo Rol Icerik
tech-radar (bu repo, public) Uygulama ve chart helm/tech-radar, her chart surumu icin degismez chart-<surum> etiketi
yerel-platform (private) Platform Paylasilan PostgreSQL; terraform/kume (Argo CD, Vault, VSO) ve terraform/yapilandirma (Vault KV/auth/politikalar, AppProject'ler, kok Application); scripts/tf.sh baglami docker-desktop'a kilitler
yerel-gitops (private) "Kumede ne calissin" apps/tech-radar.yaml (uc kaynakli Application), tech-radar/values-yerel.yaml (sir yok), tech-radar/manifests/ (ServiceAccount, VaultAuth, VaultStaticSecret)

Nasil calisir:

  • Argo CD chart'i bu reponun chart-<surum> etiketinden (su an chart-2.2.1), degerleri ve VSO nesnelerini yerel-gitops'tan okur; hedef namespace tech-radar, automated: {prune, selfHeal}.
  • migration.mode=argocd (Job sabit adli Sync hook) ve secrets.existingSecret=teknoloji-secret kullanilir; Secret'i Vault Secrets Operator kv/tech-radar/uygulama'dan yazar ve deger degisince api/worker/scheduler Deployment'larini yeniden baslatir.
  • K8s ortami paralel denemedir: ayri veritabani cybernews_k8s, Gemini ve Beat kapali, imajlar yerel (pullPolicy: Never); compose canli ortam olarak kalir.
  • Kumede calisan surum yerel-gitops'taki targetRevision'dir; yukseltme orada etiketi degistirmek, geri alma git revert. Argo CD arayuzundeki Rollback auto-sync altinda kapalidir.
  • Vault kilitliyse (Docker Desktop yeniden baslayinca) uygulama calismaya devam eder; yalniz sir yenilemesi bekler. Acmak: yerel-platform/scripts/vault_kilit_ac.sh.

Dogrulama senaryolari T1-T12 (kurulum, en az yetki, repo erisimi, yukseltme, rollback, sapma, sir rotasyonu, Vault yeniden baslatma, sifirdan kurulum) yerel-platform/scripts/k8s_dogrulama.sh ile kosar; sonuclar ADR-0008'dedir.

Onemli values parametreleri

Parametre Varsayilan Aciklama
secrets.secretKey "" Zorunlu. openssl rand -hex 32
secrets.dbPassword "" Zorunlu. PostgreSQL ve uygulamanin ortak parolasi
secrets.geminiApiKey "" Istege bagli; bos -> Gemini kapali
secrets.existingSecret "" Doluysa chart Secret olusturmaz, bu Secret'i kullanir (or. Vault Secrets Operator)
migration.mode helm argocd: Job sabit adli Argo CD Sync hook'u (helm template ile kurulum)
backend.image.tag / frontend.image.tag "" Bos -> appVersion
backend.replicas / frontend.replicas 2 Replika sayisi
postgresql.enabled true false = harici PostgreSQL (config.database.host)
postgresql.storage.size 5Gi PVC boyutu
redis.enabled true false = harici Redis (config.redis.*)
libretranslate.enabled true Yerel ceviri servisi
ingress.enabled / ingress.host true / teknoloji.example.com Ingress ve alan adi (ALLOWED_HOSTS'a girer)
ingress.tls.enabled false TLS/HTTPS
config.django.extraAllowedHosts "" Ek host'lar (virgulle)
config.app.* koddaki varsayilanlar RETENTION_DAYS, REFRESH_COOLDOWN, GEMINI_*, LIBRETRANSLATE_* ...

CI ve Guvenlik Hatti

Dokuz GitHub Actions is akisi vardir. CI, Dependency Review, PR'da gitleaks ve etiket push'unda chart etiketi kapidir (kirmiziysa merge/etiket gecmez), digerleri rapor uretir: bulgu varsa hat yesil kalir ve bulgu Security sekmesine duser; hat yalniz taramanin kendisi yapilamadiysa kirmizi olur. Ayrintili okuma rehberi ve bekleyen isler: docs/GUVENLIK-PLANI.md.

Is akisi Tetik Mod Ne yapar
CI PR, push, elle Kapi Backend (Django testleri): ruff (F, E9), PostgreSQL 16 ile 941 test + coverage kapisi (MIN_COVERAGE) + makemigrations --check; Frontend (Vite build): ESLint, Vitest (298 test), build; Helm / Compose dogrulama: helm lint, helm template (varsayilan + Argo CD modu), kubeconform, chart surum/imaj etiket kapilari, docker compose config
Dependency Review PR Kapi HIGH/CRITICAL zafiyetli bagimlilik getiren PR'i durdurur
gitleaks PR, push, Pazartesi PR'da kapi Commit'lerde sir tarar; baseline .gitleaksignore
trivy PR, push, Carsamba Rapor Kaynak agaci (vuln + secret + misconfig), backend ve frontend imajlari; CycloneDX SBOM artefakti
CodeQL Advanced PR, push, Pazar Rapor Python ve JavaScript statik analiz
DAST (ZAP baseline) PR, push, Pazartesi Rapor Uygulamayi PostgreSQL ile ayaga kaldirip OWASP ZAP baseline taramasi; JSON rapor scripts/zap_sarif.py ile SARIF'e cevrilip Code scanning'e yuklenir (kategori zap-baseline); gurultu kurallari .zap/rules.tsv ile IGNORE; HTML rapor artefakti; ayni iste /api/v1/ OpenAPI semasiyla token'li API taramasi (kategori zap-api)
zizmor .github/ degisince, Persembe Rapor Workflow dosyalarinin guvenlik denetimi
OpenSSF Scorecard push, Sali Rapor Depo guvenlik puani
chart etiketi chart-* etiketi push'u Kapi Etiket Chart.yaml version ile ayni mi, CHANGELOG girdisi var mi

Dependabot pip, npm, Docker (digest) ve GitHub Actions bagimliliklarini haftalik gunceller; major surumler filtrelidir. Dependabot PR'i gelince: eski bir main'den acildiysa Update branch (ruleset strict oldugu icin zaten zorunlu), bes zorunlu check yesilse merge; CI kirmiziysa merge etme, planlanmis yukseltme listesine ekle. main-koruma ruleset'i PR'siz push'u, silmeyi ve force-push'u engeller.

Bulgular nerede: kod ve imaj zafiyetleri, ZAP (DAST) bulgulari, sirlar ve workflow sorunlari Security → Code scanning (Tool filtresi); bagimlilik CVE'leri Security → Dependabot; ZAP'in HTML raporu ayrica ilgili Actions kosusunun artefaktinda. Zafiyet bildirimi icin SECURITY.md (GitHub private vulnerability reporting; ilk yanit 7 gun).

Uygulama tarafindaki korumalar: DEBUG=False iken bos, ornek, django-insecure onekli veya 32 karakterden kisa SECRET_KEY ile uygulama acilmaz (cybernews/ayar_dogrulama.py); DB_HOST bossa yalniz DEBUG=True ile SQLite; veritabanini silen uclar admin oturumu ister; /api/v1/ token + hiz siniri + paylasilan soguma; imajlar non-root, Kubernetes'te kok dosya sistemi salt okunur. Yanit basliklari: Content-Security-Policy (django-csp; script-src 'self' + nonce, inline script yok), Permissions-Policy, Cross-Origin-Resource-Policy, Cross-Origin-Embedder-Policy (cybernews/guvenlik_basliklari.py) ve Django varsayilanlari (nosniff, Referrer-Policy, COOP, X-Frame-Options DENY); WhiteNoise statik dosyalara Access-Control-Allow-Origin: * eklemez. Yeni inline <script> eklenmez; gerekirse nonce="{{ request.csp_nonce }}".


Operasyon ve Sorun Giderme

Saglik ve gorunurluk

# Servis ayakta mi (tokensiz)
curl -s http://localhost:8000/api/v1/health/

# Bolum basina tazelik: son basarili cekim, son durum, bekleyen ceviri sayisi
curl -s -H "Authorization: Token $CYBERNEWS_TOKEN" http://localhost:8000/api/v1/status/

# Ana sayfa saglik seridinin kaynagi: bolum basina sessiz kaynaklar (tokensiz, 60 sn cache)
curl -s localhost:8000/api/saglik/ | jq '.sections[] | .silent_sources'

# Genel Bakis kutularinin kaynagi (tokensiz, 60 sn cache)
curl -s localhost:8000/api/ozet/ | jq '{critical_count, high_count, kev_count, fetch}'

# Loglar
docker compose logs -f --tail=100 teknoloji-worker      # cekim ve ceviri
docker compose logs -f --tail=100 teknoloji-scheduler   # Beat planlamasi
docker compose logs -f --tail=100 teknoloji-translate   # LibreTranslate

# Celery kuyrugu ve worker durumu
docker compose exec teknoloji-worker celery -A cybernews inspect active
docker compose exec teknoloji-redis redis-cli -n 1 LLEN celery

Sik karsilasilan durumlar

Belirti Sebep Cozum
teknoloji-api acilmiyor, logda SECRET_KEY hatasi .env'de anahtar yok, ornek deger ya da 32 karakterden kisa openssl rand -hex 32 ile uret, .env'e yaz, docker compose up -d
DB_PASSWORD .env icinde tanimli olmali Compose degiskeni bos yerel-platform/scripts/uygulama_ekle.sh cybernews ile olusturulan parolayi .env'e yaz
api PostgreSQL'e baglanamiyor yerel-platform compose'u ayakta degil ya da yerel-platform dis agi yok Once yerel-platform'da docker compose up -d, sonra burada
Ilk cekimde ceviri yok, teknoloji-translate unhealthy LibreTranslate modelleri iniyor (~258 MB, start_period 120 sn) Bekle; docker compose logs teknoloji-translate. Internet yoksa ve volume bossa servis acilmaz
Kayitlar Ingilizce kaldi, rozet "bekliyor" Saglayici devre kesicisi acik ya da Gemini butcesi doldu Kayip yok; retranslate_pending bir sonraki turda dener. Durum: /api/v1/status/ pending_translation
/api/v1/*/refresh/ 429 cooldown Bolum sogumada (REFRESH_COOLDOWN, tum token'lar ortak) Retry-After kadar bekle; soguma bilincli bir koruma
Hostta manage.py reddediliyor DEBUG varsayilani False, anahtar ve DB_HOST yok Konteynerde calistir ya da DEBUG=True ile SQLite
npm install EACCES Compose dev sunucusu bind mount'ta node_modules tutuyor docker compose stop teknoloji-frontend, sonra docker compose run --rm --no-deps teknoloji-frontend npm install
Git Bash'te docker ... /app/... yolu C:/Program Files/Git/app oluyor MSYS yol cevirisi Komutun basina MSYS_NO_PATHCONV=1
compose run ... teknoloji-api manage.py migrate calistiriyor Entrypoint once migrate yapar --entrypoint python ver
K8s'te Secret yenilenmiyor, VSO Synced False, "Vault is sealed" Docker Desktop yeniden basladi, Vault kilitli Uygulama calismaya devam eder; yerel-platform/scripts/vault_kilit_ac.sh
K8s'te elle yaptigin degisiklik geri aliniyor Argo CD selfHeal Degisikligi yerel-gitops'a commit et; acil durumda once auto-sync'i kapat

Yedekleme

Canli veri yerel-platform'un PostgreSQL'indedir; yedek orada alinir (yerel-platform/scripts/yedekle.sh). Uygulama tarafinda tam hassasiyetli dump icin manage.py veri_tasi_dump, dogrulama icin manage.py veri_ozeti kullanilir; dump dosyasi parola hash'leri ve token'lar icerdigi icin .fazb/ altinda tutulur ve is bitince silinir. Redis yedeklenmez: kaybolursa cache, soguma ve kuyruk sifirlanir, Beat bir sonraki slotta devam eder.


Ortam Degiskenleri

Uygulama tamamen ortam degiskenleri ile yapilandirabilir. Docker Compose'da docker-compose.yml icinde, Kubernetes'te ConfigMap + Secret ile ayarlanir.

Degisken Varsayilan Aciklama
SECRET_KEY (yok) Zorunlu (DEBUG=False iken). Bos, depodaki ornek degerler, django-insecure onekli veya 32 karakterden kisa anahtar uygulamayi acmaz. Compose .env'den okur. Uretmek icin openssl rand -hex 32
DEBUG False Django debug modu
ALLOWED_HOSTS localhost,127.0.0.1 Virgulle ayrilmis izinli host listesi. Compose localhost,127.0.0.1,teknoloji-api verir. Helm chart'i bunu sablonda acik liste olarak kurar (probe'lar Host: localhost gonderir)
CORS_ALLOWED_ORIGINS http://localhost:3000,... Frontend origin'leri
CSRF_TRUSTED_ORIGINS http://localhost:3000,http://127.0.0.1:3000 Admin oturumuyla POST yapabilecek frontend origin'leri (Vite proxy changeOrigin kullandigi icin gerekli)
GEMINI_API_KEY (bos) Google AI Studio anahtari; bos ise Gemini hic denenmez
GEMINI_FALLBACK_MODEL (bos) Gemini ikinci model adi (ayni GEMINI_API_KEY, ayri Google kotasi); yalniz Gemini birincil kullanilamazken denenir. Bos: zincirde yok
GEMINI_FALLBACK_DAILY_BUDGET 450 Ikinci modelin gunluk istek butcesi (Pasifik gunu; sayac oneki gemini2)
OPENROUTER_API_KEY (bos) OpenRouter anahtari (openrouter.ai/keys); bos ise OpenRouter hic denenmez. Yalniz openrouter.ai'ye gider; log, ozet ve hata metnine yazilmaz
OPENROUTER_MODEL (bos) OpenRouter modeli. Adi :free ile bitmelidir; aksi halde (ve bossa) kullanilmaz, ucretli model yanlislikla secilemez
OPENROUTER_DAILY_BUDGET 50 Gunluk istek butcesi (UTC gunu); kredisiz hesapta ucretsiz modeller ~50 istek/gun
OPENROUTER_MIN_INTERVAL 4 Istekler arasi en az saniye (~20 istek/dk altinda)
OPENROUTER_TIMEOUT 60 Istek zaman asimi (sn)
OPENROUTER_COOLDOWN 600 Hata sonrasi devre kesici bekleme (sn)
DEEPL_API_KEY (bos) DeepL API Free anahtari (:fx ile biter); bos ise DeepL hic denenmez. Yalniz api-free.deepl.com'a gider
DEEPL_MONTHLY_CHARS 450000 Aylik karakter butcesi (UTC ayi); DeepL Free siniri 500.000, 50.000 guvenlik payi
DEEPL_MIN_INTERVAL 1 Istekler arasi en az saniye
DEEPL_TIMEOUT 30 Istek zaman asimi (sn)
DEEPL_COOLDOWN 600 Hata sonrasi devre kesici bekleme (sn)
GITHUB_TOKEN (bos) Istege bagli. GitHub Releases/Tags/Advisory isteklerinde Bearer baslik (anonim limit 60/saat/IP, token ile 5000). Yalniz api.github.com isteklerine eklenir; "Public repositories (read-only)" fine-grained token yeterlidir
NVD_API_KEY (bos) Istege bagli. NVD isteklerinde apiKey basligi (anonim 5 istek/30 sn, anahtarla 50). CVE turu 3 NVD istegi yapar (KEV, yayinlanan, guncel); 429'da kaynak bos doner. Ucretsiz, nvd.nist.gov/developers'tan e-posta ile; yalniz services.nvd.nist.gov'a gider
CELERY_TASK_SOFT_TIME_LIMIT 1500 Cekim gorevi bu sureyi asinca task icinde SoftTimeLimitExceeded yukselir; gorev failure ile kapanir, kilit serbest kalir
CELERY_TASK_TIME_LIMIT 1800 Sert sinir: worker alt sureci oldurulur, FetchRun running kalir, bolum kilidi REFRESH_LOCK_TTL sonunda duser. Soft'tan en az 60 sn buyuk tutulur
CELERY_WORKER_MAX_TASKS_PER_CHILD 50 Bu kadar gorevden sonra worker alt sureci yenilenir (bellek/baglanti birikimi)
LOG_LEVEL INFO Uygulama loglarinin seviyesi (DEBUG cekim ayraclarini da gosterir); Django/Celery kendi gurultusu WARNING'de kalir
LOG_FORMAT text text: 2026-10-08 17:05:32 WARNING news.devtools_scraper: [GitLab] Atom hatasi: ...; json: satir basina bir JSON nesnesi (ts, level, logger, msg, exc) — Loki/ELK icin (cybernews/loglama.py)
GEMINI_MODEL gemini-3.5-flash-lite Model
GEMINI_DAILY_BUDGET 450 Gunluk istek butcesi (Pasifik gunu; ucretsiz katman 500 RPD). Retranslate turlarina yayilir: tur payi = kalan butce / Pasifik gece yarisina kadar kalan tur. Bolumler butceyi paylasir; Gemini adayi kayit siniri: CVE'de CVSS >= 7 ya da KEV, digerlerinde hepsi; bolum sirasi CVE, haber, AI, SRE, DevTools, Kubernetes (kati)
GEMINI_MIN_INTERVAL 5 Istekler arasi saniye (15 RPM'in altinda)
GEMINI_COOLDOWN 600 429/5xx sonrasi bekleme (sn)
GEMINI_GECICI_BEKLEMELER 5,15 Gecici 5xx / baglanti kopmasinda devre kesiciden once yeniden deneme beklemeleri (sn, virgulle); bos = yeniden deneme yok
GEMINI_TIMEOUT 60 Istek zaman asimi (sn)
GEMINI_MAX_CHARS 12000 Bu uzunlugun ustundeki kayit Gemini'ye gitmez
GEMINI_BATCH_CHARS 10000 Yukseltme paketinin toplam karakter siniri (bir istekte birden cok kayit)
GEMINI_BATCH_MAX 15 Yukseltme paketindeki en fazla kayit sayisi
RETRANSLATE_BATCH 100 Retranslate turunda bolum basina taranan bekleyen kayit sayisi
RETRANSLATE_UPGRADE_BATCH 40 Tur ve bolum basina yukseltme siniri (en yeni kayittan baslar)
RETRANSLATE_UPGRADE_BATCH_CVE 150 CVE bolumunun tur basina yukseltme siniri (gunde ~600 yeni onemli CVE; 40'lik tavan eski adaylara sira birakmiyordu)
RETRANSLATE_MAX_ATTEMPTS 5 Bir kaydin icerik hatasiyla (saglayici reddetti / dogrulama gecmedi) kac kez denenecegi; esige ulasan kayit kuyruktan duser (needs_translation kalir) ve /api/v1/status/ translation_given_up ile sayilir. Basarili cevirinin sayaci sifirlar. Sayaci elle sifirlamak (admin ya da shell) kaydi yeniden kuyruga alir
TRANSLATE_MIN_RATIO 0.4 Ceviri kirpilma esigi: 80+ karakterlik metinde cikti/girdi orani bunun altindaysa ceviri reddedilir, kayit needs_translation kalir
RETENTION_DAYS 90 Saklama penceresi; updated_at bundan eski kayitlar cekim basinda silinir (cekim penceresinden ayridir)
REFRESH_COOLDOWN 900 /api/v1/*/refresh/ sonrasi bolum sogumasi (sn) — tum token'lar arasinda paylasilir
AXES_FAILURE_LIMIT 5 Admin girisinde ayni (kullanici adi, IP) ciftinden bu kadar basarisiz denemeden sonra kilit (django-axes); kilit AXES_COOLOFF_MINUTES (30) sonra acilir, basarili giris sayaci sifirlar. Acmak icin admin > Axes > Access attempts ya da manage.py axes_reset
SOURCE_SILENT_RUNS 4 Bir kaynak bu kadar ardisik tamamlanmis turda 0 kayit dondurur VE son kaydi beklenen araliktan eskiyse (ya da hic kaydi yoksa) /api/v1/status/ onu silent isaretler (4 tur = Beat'te 24 saat). Beklenen aralik: news/kaynaklar.py BEKLENEN_ARALIK_GUN (seyrek kaynaklar) ya da bolum cekim penceresi
REFRESH_LOCK_TTL 3600 Bolum cekim kilidinin omru (sn); worker olurse kilit bu surede kendiliginden duser
DB_HOST (bos) Doluysa PostgreSQL kullanilir. Bossa yalniz DEBUG=True iken SQLite (db.sqlite3); DEBUG=False iken uygulama acilmaz. Compose yerel-postgres verir
DB_PORT 5432 PostgreSQL port
DB_NAME cybernews Veritabani adi
DB_USER cybernews Veritabani kullanicisi
DB_PASSWORD (bos) Veritabani sifresi. Compose: .env'deki DB_PASSWORD (yerel-platform cybernews kullanicisi)
REDIS_URL redis://127.0.0.1:6379/0 Redis baglantisi (cache)
CELERY_BROKER_URL redis://127.0.0.1:6379/1 Redis baglantisi (Celery broker)

Hostta manage.py calistirmak: DEBUG varsayilani False oldugu icin anahtarsiz python manage.py ... artik reddedilir. Yerelde DEBUG=True python manage.py ... kullanin ya da komutu konteynerde calistirin (docker compose exec teknoloji-api ...). DB_HOST vermezseniz hostta DEBUG=True ile yerel db.sqlite3 kullanilir.


Bilinen Kisitlamalar

  • LibreTranslate cevirileri Gemini'ye gore daha dusuk kalitede olabilir (ozel ad/guvenlik terimi hatalari otomatik dogrulamayla yakalanmaz); rozetten ayirt edilir, retranslate_pending Gemini ile yukseltene kadar boyle kalir. Gemini gunluk butcesi (GEMINI_DAILY_BUDGET, varsayilan 450) asilirsa yukseltme bir sonraki gune kalir; CVE'lerden CVSS < 7 ve KEV disi olanlar ise butce ne olursa olsun kalici olarak LibreTranslate'te kalir (bkz. Hiz Siniri ve Devre Kesici)
  • Dark Reading HTML scraping'e 403 doner, bu yuzden RSS feed kullanilir
  • Gunicorn timeout 300 saniye — cok fazla kaynak secilirse zaman asimi olabilir
  • Her fetch'te toplam makale sayisi 30 ile sinirlidir (Gunicorn timeout'undan kacinmak icin)
  • Redis blog sayfasi JS-rendered — blockContent div'inden icerik cekilir, eger site yapisi degisirse guncelleme gerekebilir
  • Elastic 8.x serisi release notes farkli URL'de (/guide/en/...), sadece 9.x serisi icin detayli changelog cekilir
  • Yapay Zeka bolumu yalnizca haber RSS'lerini kapsar; benchmark/leaderboard skorlari ertelenmistir (ADR-0002)
  • artificialintelligence-news.com RSS'i 403 dondugu icin yerine MIT Technology Review AI kullanilir
  • news bolumunde link uzerinde veritabani benzersizlik kisiti yoktur; v1 tuketicisi kendi tarafinda benzersiz indeks tanimlamalidir (bkz. Upsert anahtari)
  • Yerel GitOps ortami bilinerek sinirlidir: Vault tek anahtar ve elle unseal, kok token yerel dosyada, Kubernetes Secret'lari etcd'de sifresiz, tek dugum, SSO yok, Argo CD polling (webhook yok). Uretim esdegerleri spec bolum 10'dadir
  • Compose ve K8s ayni PostgreSQL sunucusunda farkli veritabanlari (cybernews, cybernews_k8s) kullanir; ayni veritabanina ayni anda baglanmazlar

Belgeler ve Yol Haritasi

Belgeler

Belge Icerik
docs/ADR-*.md Mimari kararlar: baglam, karar, elenen alternatifler, sonuc ve canli dogrulama olcumleri
docs/GUVENLIK-PLANI.md Guvenlik hatti nasil okunur, bulgular nereye duser, haftalik rutin, bekleyen isler (P3-P5), gecmis
docs/superpowers/specs/ Tasarim belgeleri: her buyuk isin "neden, ne, nasil dogrulanir" metni (A1-A5b, guvenlik temizligi, Faz B, B3)
docs/superpowers/plans/ Uygulama planlari ve devir notlari; gorev gorev komutlar, beklenen ciktilar
helm/tech-radar/CHANGELOG.md Chart surumleri ve yukseltme notlari
SECURITY.md Zafiyet bildirimi

Tamamlanan asamalar

Tarih Asama Kayit
2026-09-11 Yapay Zeka bolumu (8 kaynak) ADR-0001, ADR-0002 (benchmark ertelendi)
2026-09-12 → 09-21 Entegrasyon API /api/v1/ A1-A5b: token, imlecli delta, refresh/jobs, FetchRun + status, OpenAPI ADR-0003, ADR-0006
2026-09-14 → 09-18 Ceviri saglayici zinciri; Google kaldirildi, Gemini yukseltme; saklama olcusu updated_at, CVE'ye butce onceligi ADR-0004, ADR-0005
2026-09-13 → 09-30 Guvenlik hatti (8 is akisi), Django 4.2 → 5.2, Dependabot 14 → 0, SECRET_KEY/ALLOWED_HOSTS korumalari GUVENLIK-PLANI P0-P2, P4 (kismi)
2026-10-02 Faz B1: SQLite → paylasilan yerel PostgreSQL, kayipsiz gecis (ozet birebir) ADR-0007
2026-10-03 Faz B2: Helm chart 2.0.0 docker-desktop'ta S1-S7 ile dogrulandi; CI chart kapilari ADR-0007
2026-10-04 B3: Terraform + Argo CD + Vault/VSO ile yerel GitOps; chart 2.1.0; T1-T12 gecti ADR-0008
2026-10-08 Kaynak turu: 35 → 48 kaynak (7 haber, CISA KEV, LiteLLM/LangGraph/Langfuse/GitLab/Keycloak); olu kaynak onarimi (Bleeping Computer 403, SecurityWeek bos link, MongoDB/InfoQ/DZone akislari); GITHUB_TOKEN news/tests/test_kaynaklar.py
2026-10-14 Kaynak turu 2: 48 → 47 (KDnuggets/MinIO/CIRCL cikti, Ars Technica AI/Import AI girdi); kadans farkindalikli sessizlik news/tests/test_kaynak_sagligi.py
2026-10-13 → 10-14 Guvenlik plani P5-b (haftalik ozet Issue) ve P5-c (/api/v1/ ZAP API taramasi); bakim dalgasi (yedek dongusu, saglik seridi, Vitest, ruff/coverage) GUVENLIK-PLANI, docs/superpowers/specs/2026-10-14-bakim-dalgasi-design.md

Acik isler ve adaylar

Guvenlik plani (GUVENLIK-PLANI) P0-P5 tamamlandi (2026-10-14); siraya konmus guvenlik isi yok.

Aday (henuz tasarlanmadi; kapsam notlari ADR-0002 ve B3 spec bolum 13):

  • Vault dinamik PostgreSQL kimlikleri (database secrets engine + VaultDynamicSecret) ile statik DB_PASSWORD'un kalkmasi.
  • Argo CD ApplicationSet (kok uygulamanin yerine) ve ikinci bir ortam klasoruyle terfi akisi; Argo CD Image Updater.
  • AI benchmark/leaderboard bileseni (ADR-0002, ertelendi).
  • Diger kisisel uygulamalarin ayni zincire eklenmesi (yeni uygulama = uygulamalar listesine bir eleman + yerel-gitops/apps/<ad>.yaml).

Kapsam disi (bilincli): gercek bir kumeye kurulum, imaj registry'si ve release yayini, SSO, cok dugum, K8s ortaminin canli olmasi.


Mimari Kararlar (ADR)

ADR Konu Durum
ADR-0001 AI News bileseni Accepted
ADR-0002 AI Benchmark / Leaderboard bileseni Proposed (ertelendi)
ADR-0003 Dis tuketiciler icin /api/v1/ entegrasyon katmani (imlecli delta, token, refresh, ceviri dogrulugu) Accepted (A1–A5b uygulandi, canlida dogrulandi)
ADR-0004 Ceviri saglayici zinciri (LibreTranslate yedek; 2026-09-15: Google kaldirildi, Gemini yukseltme) Accepted (degisiklik 2026-09-15)
ADR-0005 Saklama olcusu updated_at (sil/yeniden yaz dongusu) ve CVE'ye Gemini butce onceligi Accepted (uygulandi 2026-09-18, canlida dogrulandi; 2026-11-02: CVE rezervi kaldirildi, yerine onem sinifi)
ADR-0006 FetchRun gorunurlugu, durum semantigi ve dar GET /api/v1/status/ ucu (ADR-0003 bolum 11'in yerine gecer) Accepted (uygulandi 2026-09-21, canlida dogrulandi)
ADR-0007 SQLite'tan paylasilan yerel PostgreSQL'e kayipsiz gecis ve Helm chart dogrulamasi (Faz B) Accepted (B1 2026-10-02 ve B2 2026-10-03 uygulandi; docker-desktop'ta dogrulandi)
ADR-0008 Yerel GitOps: iki asamali Terraform, Argo CD "app of apps", Vault + Vault Secrets Operator, chart 2.1.0 (B3) Accepted (B3a + B3b 2026-10-04 uygulandi; T1-T12 docker-desktop'ta gecti)

Lisans

Bu proje MIT lisansi ile yayimlanmistir. Tam metin icin LICENSE dosyasina bakin.

About

Full-stack Turkish tech news aggregator — scrapes 27 sources (cybersecurity, CVE, Kubernetes, SRE, DevTools), translates to Turkish, and serves via a modern dark-mode UI. Built with Django REST Framework, React (Vite), Celery, Redis, and Docker/Kubernetes.

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages