Problem
İş değiştirmek, yüksek lisans yapmak, şehir değiştirmek gibi büyük kararlar genelde sezgiyle veriliyor; karar verildikten sonra da hangi varsayımla verildiği hatırlanmıyor. Ele almak istediğim sorun buydu: kararın gerekçesini, sayısal tahminlerini ve alternatiflerini kayıt altına alan, sonradan geri dönüp bakılabilen yapılandırılmış bir kayıt katmanı. Yani asıl mesele "yapay zekâ karar versin" değil, kararın girdilerini şemaya oturtmak.
Yaklaşım
Next.js 16 App Router üzerinde, Prisma + PostgreSQL ile dokuz tablolu bir veri modeli kurdum: users, user_preferences, decisions, decision_options, decision_inputs, analyses, analysis_scores, analysis_checkpoints, decision_history. Modelin özü decision_inputs tablosu: yedi serbest metin alanı (finansal/kariyer/duygusal/sosyal etki, alternatifler, bilinmeyenler, kısıtlar) ve yedi sayısal alan (tahmini kazanç/kayıp, başarı olasılığı, belirsizlik, stres, büyüme potansiyeli, geri döndürme zorluğu). Analiz çıktısı üç senaryoyu (iyimser/gerçekçi/kötümser) Json kolonlarında tutuyor, puanlar ise sorgulanabilir olsun diye ayrı analysis_scores tablosunda tam sayı kolonlar. Tüm REST uçları tek bir zarfla dönüyor: {success, message, data}. Kimlik doğrulama httpOnly cookie içinde JWT; her uç önce getSession ile oturumu, sonra kaydın o kullanıcıya ait olup olmadığını kontrol ediyor (findFirst ile userId koşulu), yani yetkilendirme veri sorgusuna gömülü. Girdi doğrulama Zod ile.
Kararlar ve takaslar
- Tüm uçları tek bir {success, message, data} zarfına bağladım, çünkü istemcinin her cevabı aynı sözleşmeyle okumasını istedim ve ok()/fail() yardımcılarıyla bunu tek yerden ürettim; alternatif her route'un kendi cevap şeklini döndürmesiydi, o da on beş uçta on beş ayrı ayrıştırma dalı demekti.
- Oturumu httpOnly, sameSite=strict ve üretimde secure bir cookie içindeki JWT olarak kurdum, çünkü MVP aşamasında ayrı bir auth servisi ya da oturum tablosu işletmek istemedim; alternatif NextAuth ya da veritabanında oturum kaydıydı — bilinçli takas şu: token'ı sunucudan tek tek iptal edemiyorum, karşılığında altyapı yok.
- Yetkilendirmeyi ayrı bir katman yerine sorgunun içine koydum: kayıtlar findFirst({ where: { id, userId: session.userId } }) ile çekiliyor, yani başkasının kaydı "yetkisiz" değil "bulunamadı" olarak dönüyor. Çünkü önce-getir-sonra-kontrol et deseninde kontrolü atlamak kolay; alternatif kaydı çekip sahipliği elle karşılaştırmaktı ve o unutulmaya açıktı.
- API sözlüğünü veritabanı enum'undan ayrı tuttum: dışarıda zaman ufku '6_ay' / '1_yil' / '3_yil', Prisma tarafında 'ay_6' / 'yil_1' / 'yil_3' ve sınırda elle eşleniyor. Çünkü Prisma enum tanımlayıcıları rakamla başlayamıyor, yani okunur API değerleri ile geçerli enum adları aynı olamıyordu. Bunun kabul ettiğim maliyeti şu: aynı eşleme zinciri POST ve PUT route'larında iki kez tekrarlanıyor, paylaşılan bir yardımcıya çıkarılmamış — sonraki adımda toplanması gereken bir borç.
- Analiz sonucunu ikiye ayırdım: senaryolar Json kolonda, puanlar ayrı tabloda tam sayı kolonlar. Çünkü senaryo metinlerinin şekli değişebilir ama puanlar üzerinde sıralama/filtreleme yapılacak; alternatif her şeyi tek bir Json alanına koymaktı, o zaman "toplam puanı en yüksek kararlar" gibi basit bir sorgu bile uygulama katmanında dönüyordu.
Sonuç
Bu bir Phase 1 iskeleti ve öyle sunulmalı. NET DURUM: analiz uçları şu an MOCK — /analyze, /compare ve /devils-advocate kodda "(Phase 1 mock)" mesajıyla sabit veri döndürüyor, gerçek bir puanlama ya da model çağrısı YOK. Yani ürünün adı "karar motoru" ama motor henüz yazılmamış; var olan şey motoru taşıyacak iskelet. Gerçekten çalışan kısımlar: dokuz tablolu Prisma şeması, on beş REST route dosyası, Zod doğrulama şemaları, cookie-JWT kimlik doğrulama (register/login), sorguya gömülü sahiplik kontrolü, sekiz parçalı UI bileşen seti (Button, Input, Card, ProgressBar, StatBox, EmptyState, ResultCard, ComparisonCard), route iskeleti (splash, onboarding, auth, dashboard, decisions, history, profile) ve demo kullanıcı + dört karar ekleyen seed betiği. ÖLÇÜM YOK: test, kullanıcı ya da performans verisi yok. Depoda iki commit var (ikisi de 2026-04-12) ve sonrasında ilerleme yok — projenin dürüst durumu "başlatıldı, Phase 1 tamamlandı, Phase 2 başlamadı".
Teknolojiler
Kaynaklar
Bu sayfadaki teknik iddialar aşağıdaki kaynaklardan çıkarıldı.
- https://github.com/msgxr/decision-engine
- https://github.com/msgxr/decision-engine/blob/main/README.md
- https://github.com/msgxr/decision-engine/blob/main/docs/phase1-architecture.md
- https://github.com/msgxr/decision-engine/blob/main/prisma/schema.prisma
- https://github.com/msgxr/decision-engine/blob/main/prisma/seed.ts
- https://github.com/msgxr/decision-engine/blob/main/package.json
- https://github.com/msgxr/decision-engine/blob/main/src/lib/validation.ts
- https://github.com/msgxr/decision-engine/blob/main/src/lib/auth.ts
- https://github.com/msgxr/decision-engine/blob/main/src/lib/api-response.ts
- https://github.com/msgxr/decision-engine/blob/main/src/lib/constants.ts
- https://github.com/msgxr/decision-engine/blob/main/src/app/api/decisions/route.ts
- https://github.com/msgxr/decision-engine/blob/main/src/app/api/decisions/%5Bid%5D/analyze/route.ts
- https://github.com/msgxr/decision-engine/blob/main/src/app/api/decisions/%5Bid%5D/devils-advocate/route.ts
Doğrulayamadıklarım
Metni yazarken teyit edemediğim noktalar. Görünür tutuyorum — teyitsizi sessizce iddia etmektense.
- lib/projects.ts stack'i ['TypeScript','Node.js','Rule Engine'] diyor — 'Rule Engine' etiketi YANLIŞ: depoda kural motoru yok, analiz uçları sabit mock döndürüyor. Gerçek yığın Next.js 16 + React 19 + Prisma + PostgreSQL + Zod + Tailwind 4. Etiket düzeltilmeli.
- ÖNEMLİ ÇERÇEVE: constants.ts'teki SUB_SLOGAN "AI destekli senaryo analizi, risk puanlama ve stratejik karar desteği" diyor ve README "dark-theme-first bir SaaS MVP" diyor. Depoda LLM/AI entegrasyonu HİÇ YOK (bağımlılıklarda yapay zekâ SDK'sı bulunmuyor). Bu ifadeler ürün vizyonu; vaka sayfası bunları mevcut yetenek gibi sunmamalı.
- DOGRULANAMADI: Veritabanının gerçekten migrate edilip çalıştırıldığı. prisma/ altında schema.prisma ve seed.ts var ama migrations dizini depoda YOK; şemanın canlı bir Postgres'e uygulandığına dair kanıt bulunmuyor.
- Canlı dağıtım YOK (GitHub Pages API 404, package.json'da dağıtım betiği yok, homepage tanımsız). Yerel çalıştırma bir PostgreSQL bağlantısı gerektiriyor.
- Kodda doğrulanmış güvenlik notu (övgüye çevrilmemeli): JWT imzası process.env.JWT_SECRET yokken "dev-secret" varsayılanına düşüyor. MVP iskeletinde anlaşılır, üretim duruşu olarak sunulamaz.
- DOGRULANAMADI: docs/phase1-architecture.md "Phase 1 kapsamı" listesini veriyor ama Phase 2 planı, yol haritası ya da analiz algoritmasının nasıl kurulacağına dair belge depoda yok. "Sonraki adım" anlatısı depoya dayandırılamaz.