Skip to content

fix: lansman öncesi kapsamlı audit düzeltmeleri (70 bulgu) + welcome filiz#49

Merged
Ohualtex merged 18 commits into
mainfrom
fix/audit-lansman
Jun 9, 2026
Merged

fix: lansman öncesi kapsamlı audit düzeltmeleri (70 bulgu) + welcome filiz#49
Ohualtex merged 18 commits into
mainfrom
fix/audit-lansman

Conversation

@Ohualtex

@Ohualtex Ohualtex commented Jun 9, 2026

Copy link
Copy Markdown
Owner

Özet

Lansman öncesi kapsamlı audit (16-dilimli çok-ajanlı denetim → 94 bulgu; dedup sonrası 70 onaylı). Hepsi düzeltildi + welcome filiz kozmetik uyumu. 18 commit, mantıklı parçalara bölünmüş.

Kapsam (70/70)

  • 🔴 Kritik (1): prod şema migration-only — init_db create_all prod-dışına gate'lendi + docker-entrypoint.sh (alembic upgrade head); belgelenen deploy DuplicateTable ile kırıktı + RBAC CHECK/index atlanıyordu.
  • 🟠 Yüksek (9): API_DEBUG echo sızıntısı · rate-limit nginx-IP (proxy-headers) · str(exc) info disclosure · stored+reflected XSS · select-click istenmeyen rol PATCH · max_length (SQLite↔PG 500) · delete cascade (sensör silme kırıktı) · area_hectares gt=0.
  • 🟡 Orta (28): metrics/model-perf endpoint auth · /docs prod-kapalı · analytics işaret/zero-baseline/SQL-agg · irrigation status+duration · email normalize · mqtt %0 okuma · plant error-as-success · severity Literal · role NOT NULL migration · frontend UX/i18n · .dockerignore/compose/requirements · ...
  • 🟢 Düşük (32): JWT exp zorunlu · bcrypt 72-byte guard · CORS exact-host · HSTS dedup · 500-yanıtlarda güvenlik header'ları · confidence varyans-bazlı · frontend cilalar · ...
  • 🎨 Kozmetik: welcome filiz ↔ site-içi maskot detay eşitliği.

Doğrulama

  • Backend pytest 654/654 · Frontend Vitest 75/75 · ruff + format + bandit temiz
  • alembic upgrade head fresh DB'de sorunsuz (deploy fix doğrulandı) · schemathesis register fuzz (bcrypt 500) çözüldü

Yöntem

Kritik+Yüksek elle (dikkatli); Orta+Düşük çok-ajanlı paralel workflow (ayrık dosyalar) → her batch tam-suite doğrulama → parça-commit. Migration/test-pinned/perf olanlar tek tek gerekçelendirildi (hepsi çözüldü).

Ohualtex and others added 18 commits June 9, 2026 13:44
…KSEK #1/#2/#3)

KRİTİK: init_db() create_all her prod boot'ta çalışıp belgelenen `alembic upgrade
head` adımını DuplicateTable ile bozuyor, RBAC CHECK + FK index'leri atlıyordu →
şema artık migration-only:
- main.py: create_all yalnız ENVIRONMENT != production
- docker-entrypoint.sh (yeni): prod'da `alembic upgrade head` → sonra uvicorn
- models.py: User'a ck_users_role_valid CHECK (create_all yolu prod ile eşleşsin)
Doğrulama: `alembic upgrade head` fresh DB'de sorunsuz koşuyor; 651/651 test geçti.

YÜKSEK:
- #1 API_DEBUG default False + prod'da SQLAlchemy echo zorla kapalı (SQL+param =
  şifre hash/PII log sızıntısı); .env.example + _validate_production warning
- #2 entrypoint: uvicorn --proxy-headers --forwarded-allow-ips → rate-limit nginx
  peer IP yerine gerçek client IP'sini görür (auth brute-force koruması)
- #3 exceptions.py: str(exc)/str(exc.orig) prod'da gizli + sunucuda log
  (path/SQL/secret info disclosure)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
#6)

- #4 monitoring.js: sensor_type/status escape (serbest str → stored XSS, admin
  oturumunda çalışırdı)
- #5 utils.js: showToast message innerHTML yerine textContent (backend hata
  detayı/dosya adı → reflected XSS)
- #6 main.js: click delegation <select>'i atlıyor (dropdown açmak istenmeyen
  rol-değişikliği PATCH'i gönderiyordu)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
#8/#9)

SQLite testte geçip PostgreSQL prod'da patlayan sınıf hatalar:
- #7 max_length: create/update şemalarına DB kolon uzunlukları (name 100/150,
  email 150, phone 20, soil_type 50, sensor_type 50, serial 100, alert 50/20) →
  PG'de 500 (StringDataRightTruncation) yerine 422. farms/sensors/alerts/auth/users
- #8 delete cascade: sensör→okuma/özet, field→analiz/sulama/görsel/ekim/gübre/uyarı,
  farm→hava/uyarı (FK IntegrityError 500 + SQLite orphan). Sensör silme artık çalışır.
- #9 fertilizer area_hectares gt=0 (negatif/sıfır → negatif gübre kg / yanlış "yeterli")

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
WeatherDataResponse wind_speed_kmh'i serialize etmiyordu → frontend Rüzgâr grafiği
prod'da hep 0. Alan eklendi + regresyon testi.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… kapat (ORTA #6/#7/#8)

- #6 metrics.py: deep_health_check + prometheus_metrics artık admin/developer ister
  (scheduler/pool/DB-hata sızıntısı); test_metrics deep-health auth-required'a güncellendi
- #7 model_performance.py: read endpoint'leri Bearer, drift (SystemAlert INSERT'lü)
  admin/developer ister (auth'suz veri enumeration + yazma)
- #8 main.py: docs_url/redoc_url/openapi_url prod'da None (attack-surface haritası kapalı)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…#15/#16/#17)

- #4 analytics _diff: negatif baseline'da işaret tersleniyordu → düzeltildi
- #5 analytics: boş dönem 0 yerine None → uydurma +100% değişim engellendi
- #9 fields.py: reading timestamp'leri UTC-offset'li ISO-8601 (Safari Invalid Date)
- #10 irrigation: water_amount gt=0, duration_min ge=0 (negatif/sıfır reddedilir)
- #12 irrigation: IrrigationResponse'a duration_min eklendi (Süre kolonu doluyor)
- #15 mqtt: eksik moisture_percent artık 0 yerine atlanıyor (sahte %0 okuma)
- #16 plants: çözülemeyen görsel sahte 200-success olarak kaydedilmiyor (422)
- #17 alerts şema: severity Literal[low,medium,critical] (bucket bozulması)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…gration (ORTA #13/#14/#18)

- #13 auth.py/users.py: email .strip().lower() (register/login/admin-create) →
  case/whitespace mükerrer hesap + login engeli bitti
- #14 alerts router: create_alert field_id sahipliğini de doğruluyor
- #18 migration c5eee337bec4: users.role NOT NULL (model/migration drift) —
  fresh DB'de doğrulandı, CHECK + index korundu, reversible

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- #23 monitoring: boş hava verisinde skeleton sonsuz dönmüyor (boş-durum)
- #24 monitoring: sensör count her yüklemede tazeleniyor (stale pagination)
- #25 alerts: özet kartları (Toplam/Açık/Kritik) filtreden bağımsız sayımdan
- #26 api.js + ui_helpers.js: Pydantic 422 detail-array alan mesajlarına çevriliyor
  (ham HTTP 422 yerine) — 2 kopya da düzeltildi + test güncellendi
- #27 labels.js/render.js/monitoring: sensör tip/status Türkçe etiket
- #28 dashboard: severity chip'leri low/medium/critical dışını da sayıyor (total senkron)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
#1/#2/#3)

- #1 .dockerignore (yeni): dev DB/secret/.git/tests prod imajına sızmıyor
- #2 docker-compose: api servisinden host-kaynak bind-mount kaldırıldı (prod
  container kendi imajını çalıştırır; dev için yorumlu örnek bırakıldı)
- #3 requirements.txt: bağımlılıklar == ile pinlendi; venv'de kurulu olmayan
  paho-mqtt/onnxruntime >= bırakıldı (follow-up)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- L1 email format sanity (EmailStr yok) + name min_length=1 (boş isim)
- L2 JWT decode exp+sub zorunlu (exp'siz token süresiz geçerliydi)
- L3 bcrypt 72-byte parola guard (sessiz truncation → açık 400)
- L4 parola/email validasyonu dup-check'ten ÖNCE (409 yerine 400 + enumeration azaldı)
- L5 PATCH /users/{id}/role testi (happy + self-lockout 409 + 404)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- L6 analytics /compare datetime'ları UTC-offset'li
- L8 farm/field update/delete None-guard (race → 500)
- L9 nem rounded değerle sınıflanıyor (sınır badge tutarlılığı)
- L11 weather precipitation rain['1h']=null → 0.0
- L12 sulama terminal durumdan (completed/cancelled) çıkış bloklandı (409)
- L19 plant upload commit hatasında orphan dosya temizleniyor
- L20 archiver SELECT/DELETE aynı id seti (geç gelen satır kaybı)
- L21 archiver boş grup min/max None (0.0 seed korupsiyonu)
- L22 report PDF None → N/A
- L7 naive DateTime riski yorumlandı (migration gerekir, follow-up)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…3/L14/L15)

- L13 IrrigationCreate source=manual default (manuel kayıt model etiketleniyordu)
- L14 nullable DB kolonları response'ta Optional (created_at/analysis_date/reading_timestamp null'da 500 önlendi)
- L15 DashboardLastDisease.severity yorumu düzeltildi (none|low|medium|high)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ik header'ları (DÜŞÜK L23/L24 + ORTA #21)

- L23 prod CORS kontrolü substring yerine hostname-exact (app.localhost.example.com bloklanmıyor, [::1] kaçmıyor)
- L24 çift/çelişen HSTS kaldırıldı (nginx TLS terminator sahiplenir)
- #21 exception handler'lar apply_security_headers ile güvenlik header'larını 500/error yanıtlarına da ekliyor

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- L10 sensör list/count apiAuth (Bearer)
- L16 hastalık severity CSS class'ları gerçek değerlere (low/medium/high)
- L17 unknown tanı Türkçe etiket · L18 confidence 0.0 artık %0 (— değil)
- L25 navigate() rol guard (farmer #users/#analytics shell açamıyor)
- L26 hardcoded dev-api-key fallback kaldırıldı
- L27 tarla-kart çift loadFieldDetail dedup · L28 hero count-up · L29 medium renk hizası
- L30 ölü _myFarms state kaldırıldı · L31 renderPlantResult _escAttr (latent XSS)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sensör-okuma ve karşılaştırma istatistikleri tüm satırları belleğe çekip (365 güne
kadar, potansiyel on binlerce satır) Python'da topluyordu. AVG/MIN/MAX/SUM artık
SQL aggregate ile hesaplanıyor — değerler aynı (AVG/MIN/MAX NULL'ları yok sayar =
non-null filtresi; SUM boş → 0.0). Dialect-özel günlük strftime gruplaması Python'da
bırakıldı (SQLite↔PG ayrışmasını önlemek için).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Eski formül |optimal-moisture|/200 idi: optimal nemde en DÜŞÜK, uçlarda en YÜKSEK
confidence veriyordu (ters) ve modelin gerçek belirsizliğinden kopuktu. Şimdi
RandomForest ağaçları arası tahmin std'sinden türetilir: ağaçlar hemfikirse (düşük
std) emin → CAP'e yakın, dağınıksa BASE'e iner. [0.7,0.95] aralığı clamp ile korunur
(range testi geçer). Doğrulama: optimal'de 0.93, kuru uçta 0.80.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- L7: PG oturum saat dilimi UTC'ye sabitlendi (connect_args options -c timezone=utc).
  Naive DateTime kolonları + UTC-aware filtreler (datetime.now(UTC)) artık tutarlı
  karşılaştırılır; sunucu-TZ kayma riski giderildi. (timestamptz kolon migration'ı
  ayrı follow-up.)
- #3: paho-mqtt ve onnxruntime == ile pinlendi (reproducible build; venv'de kurulu
  olmadıkları için lows turunda >= kalmışlardı).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Welcome ekranı filizi, site-içi #filizMascot'a göre detay katmanları eksikti
(viewBox 120×140 ve gövde geometrisi zaten aynıydı ama daha düz görünüyordu):
- Kol/el highlight'ları (iç-parıltı #4ade80 + el-parıltısı #86efac) — "eldeki gölgeler"
- Yaprak yan-damarları + üst parıltı maskotla hizalandı
- Göz: alt-gölge + eye-bg pupil grubunun DIŞINA + 3. parıltı (maskot yapısı)
- Sap: açık yeşil highlight eklendi
Artık welcome ve site-içi filiz tıpatıp aynı.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Ohualtex Ohualtex merged commit 8cb8ce2 into main Jun 9, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant